Zaawansowane CPP/Ćwiczenia 8: Metaprogramowanie: Różnice pomiędzy wersjami

Z Studia Informatyczne
Przejdź do nawigacjiPrzejdź do wyszukiwania
Mirek (dyskusja | edycje)
Nie podano opisu zmian
Mirek (dyskusja | edycje)
Nie podano opisu zmian
Linia 190: Linia 190:
Najpierw definiujemy szablon, który wykonuje mnożenie <tt>I</tt>-tego wiersza macierzy <tt>A</tt> przez wektor <tt>v</tt>:
Najpierw definiujemy szablon, który wykonuje mnożenie <tt>I</tt>-tego wiersza macierzy <tt>A</tt> przez wektor <tt>v</tt>:


  template<size_t N,typename T = double > struct Inner {
  template<int M,size_t I> double row_vec(double *A, double *v) {
    static T dot(T *a,T *b) {
    return inner<M>(A+I*M,v);
        return (*a)*(*b)+Inner<N-1,T>::dot(++a,++b);
}
    }
 
}<br>
Następnie implementujemy rekurencyjnie mnożenie kolejnych wierszy macierzy:
  template<typename T > struct Inner<1,T> {
 
     static T dot(T *a,T *b) {
  template<int N,int M> struct matrix_vec_c {
         return (*a)*(*b);
     static void matrix_vec(double *A,double *v,double *u) {
         u[N-1]=row_vec<M,N-1>(A,v);
        matrix_vec_c<N-1,M>::matrix_vec(A,v,u);
     }
     }
};<br>
template<int M> struct matrix_vec_c<0,M> {
    static void matrix_vec(double *A,double *v,double *u) {}
  };
  };


a następnie dodajemy funkcję wywołującą tę metodę:
Używamy szablonu klasy aby móc wykorzystać specjalizację częściową. Tak jak w poprzednim zadaniou opakowujemy wywołanie metody w szablon funkcji:


  template<size_t N,typename T> T dot( T *a,T *b) {
  template<size_t N,size_t M>
    return Inner<N,T>::dot(a,b);
inline void matrix_vec(double *u,double *A,double *v) {
  };
    matrix_vec_c<N,M>::matrix_vec(A,v,u);
  }


Patrz plik [http://osilek.mimuw.edu.pl/images/8/8b/Inner.h inner.h].
Całość kodu znajduje się w pliku [http://osilek.mimuw.edu.pl/images/8/8b/Inner.h matrix.h].
</div></div>
</div></div>

Wersja z 12:05, 21 wrz 2006

Ćwiczenie 1

Napisz szablon funkcji lub klasy wyliczający funkcję silnia:

n!=n(n1)(n2)1
Rozwiązanie

Ćwiczenie 2

Zaimplementuj szablon Pow<N,M> obliczający NM. Np.:

Pow<3,4>::val;

powinno mieć wartość 81.

Rozwiązanie

Ćwiczenie 3

Wymyśl i zaimplementuj jako metaprogram szybszy algorytm funkcji pow(x).

Podpowiedź
Rozwiązanie

Ćwiczenie 4

Napisz szablon generujący pierwsze N wyrazów rozwinięcia funkcji sin(x):

sin<N>(x)=xx33!++(1)N+1(x)2N1(2N1)!

Możesz skorzystać z rozwiązań wcześniejszych zadań.

Rozwiązanie

Ćwiczenie 5

Napisz szablon generujący funkcję implementującą iloczyn skalarny dwu wektorów.

template<size_t N> double inner(double *x, double *y);

Parametrem szablonu ma być dlugość mnożonych wektorów.

inner <N> (x,y)=x1y1+yNxN

Ćwiczenie 6

Rozszerz powyższy szablon tak, aby również typ elementów wektora był parametrem szablonu:

template<size_t N, typename T> T dot(T *x, T *y);
Podpowiedź
Rozwiązanie

Ćwiczenie 7

Napisz szablon generujący funkcję implementującą iloczyn macierzy NxM i wektora o M elementach:

 void matrix_v<N>(double *A,double *v,double *u)
Parser nie mógł rozpoznać (nieznana funkcja „\aligned”): {\displaystyle \displaystyle \aligned u_0&= A_{0,0} v_0+A_{0,1} v_1+\cdots+A_{0,M-1} v_{M-1}\\ u_1&= A_{1,0} v_0+A_{1,1} v_1+\cdots+A_{1,M-1} v_{M-1}\\ &\vdots&\\ u_{N-1}&= A_{N-1,0} v_0+A_{N-1,1} v_1+\cdots+A_{N-1,M-1} v_{M-1}\\ \endaligned}

Tablica A jest reprezentowana w pamięci zgodnie z konwencją C, tzn. wiersz po wierszu: elementowi Ai,j odpowiada A[M*i+j].

Rozwiązanie