dune-istl  2.1.1
multitypeblockvector.hh
Go to the documentation of this file.
00001 #ifndef DUNE_MULTITYPEVECTOR_HH
00002 #define DUNE_MULTITYPEVECTOR_HH
00003 
00004 #ifdef HAVE_BOOST_FUSION
00005 
00006 #include<cmath>
00007 #include<iostream>
00008 
00009 #include "istlexception.hh"
00010 
00011 #include <boost/fusion/sequence.hpp>
00012 #include <boost/fusion/container.hpp>
00013 #include <boost/fusion/iterator.hpp>
00014 #include <boost/typeof/typeof.hpp>
00015 #include <boost/fusion/algorithm.hpp>
00016 
00017 namespace mpl=boost::mpl;
00018 namespace fusion=boost::fusion;
00019 
00020 // forward decl
00021 namespace Dune {
00022   template<typename T1, typename T2=fusion::void_, typename T3=fusion::void_, typename T4=fusion::void_,
00023            typename T5=fusion::void_, typename T6=fusion::void_, typename T7=fusion::void_,
00024            typename T8=fusion::void_, typename T9=fusion::void_>
00025   class MultiTypeBlockVector;
00026 }
00027 
00028 #include "gsetc.hh"
00029 
00030 namespace Dune {
00031    
00055   template<int current_element, int remaining_elements, typename TVec>
00056   class MultiTypeBlockVector_Print {
00057   public:
00061     static void print(const TVec& v) {
00062       std::cout << "\t(" << current_element << "):\n" << fusion::at_c<current_element>(v) << "\n";
00063       MultiTypeBlockVector_Print<current_element+1,remaining_elements-1,TVec>::print(v);   //next element
00064     }
00065   };
00066   template<int current_element, typename TVec>            //recursion end (remaining_elements=0)
00067   class MultiTypeBlockVector_Print<current_element,0,TVec> {
00068   public:
00069     static void print(const TVec& v) {std::cout << "\n";}
00070   };
00071 
00072 
00073 
00085   template<int count, typename T1, typename T2>
00086   class MultiTypeBlockVector_Ident {
00087   public:
00088 
00093     static void equalize(T1& a, const T2& b) {
00094       fusion::at_c<count-1>(a) = b;           //equalize current elements
00095       MultiTypeBlockVector_Ident<count-1,T1,T2>::equalize(a,b);    //next elements
00096     }
00097   };
00098   template<typename T1, typename T2>                      //recursion end (count=0)
00099   class MultiTypeBlockVector_Ident<0,T1,T2> {public: static void equalize (T1& a, const T2& b) {} };
00100 
00101 
00102 
00103 
00104 
00105 
00111   template<int count, typename T>
00112   class MultiTypeBlockVector_Add {
00113   public:
00114         
00118     static void add (T& a, const T& b) {    //add vector elements
00119       fusion::at_c<(count-1)>(a) += fusion::at_c<(count-1)>(b);
00120       MultiTypeBlockVector_Add<count-1,T>::add(a,b);
00121     }
00122 
00126     static void sub (T& a, const T& b) {    //sub vector elements
00127       fusion::at_c<(count-1)>(a) -= fusion::at_c<(count-1)>(b);
00128       MultiTypeBlockVector_Add<count-1,T>::sub(a,b);
00129     }
00130   };
00131   template<typename T>                                    //recursion end; specialization for count=0
00132   class MultiTypeBlockVector_Add<0,T> {public: static void add (T& a, const T& b) {} static void sub (T& a, const T& b) {} };
00133 
00134 
00135 
00141   template<int count, typename TVec, typename Ta>
00142   class MultiTypeBlockVector_AXPY {
00143   public:
00144 
00148     static void axpy(TVec& x, const Ta& a, const TVec& y) {
00149       fusion::at_c<(count-1)>(x).axpy(a,fusion::at_c<(count-1)>(y));
00150       MultiTypeBlockVector_AXPY<count-1,TVec,Ta>::axpy(x,a,y);
00151     }
00152   };
00153   template<typename TVec, typename Ta>                    //specialization for count=0
00154   class MultiTypeBlockVector_AXPY<0,TVec,Ta> {public: static void axpy (TVec& x, const Ta& a, const TVec& y) {} };
00155 
00156 
00162   template<int count, typename TVec, typename Ta>
00163   class MultiTypeBlockVector_Mulscal {
00164   public:
00165 
00169     static void mul(TVec& x, const Ta& a) {
00170       fusion::at_c<(count-1)>(x) *= a;
00171       MultiTypeBlockVector_Mulscal<count-1,TVec,Ta>::mul(x,a);
00172     }
00173   };
00174   template<typename TVec, typename Ta>                    //specialization for count=0
00175   class MultiTypeBlockVector_Mulscal<0,TVec,Ta> {public: static void mul (TVec& x, const Ta& a) {} };
00176 
00177 
00178 
00185   template<int count, typename TVec>
00186   class MultiTypeBlockVector_Mul {
00187   public:
00188     static typename TVec::field_type mul(const TVec& x, const TVec& y) {
00189       return (fusion::at_c<count-1>(x) * fusion::at_c<count-1>(y)) + MultiTypeBlockVector_Mul<count-1,TVec>::mul(x,y);
00190     }
00191   };
00192   template<typename TVec>
00193   class MultiTypeBlockVector_Mul<0,TVec> {
00194   public: static typename TVec::field_type mul(const TVec& x, const TVec& y) {return 0;}
00195   };
00196 
00197 
00198 
00199 
00200 
00207   template<int count, typename T>
00208   class MultiTypeBlockVector_Norm {
00209   public:
00210 
00214     static double result (const T& a) {             //result = sum of all elements' 2-norms
00215       return fusion::at_c<count-1>(a).two_norm2() + MultiTypeBlockVector_Norm<count-1,T>::result(a);
00216     }
00217   };
00218 
00219   template<typename T>                                    //recursion end: no more vector elements to add...
00220   class MultiTypeBlockVector_Norm<0,T> {
00221   public: 
00222     static double result (const T& a) {return 0.0;} 
00223   };
00224 
00230   template<typename T1, typename T2, typename T3, typename T4,
00231            typename T5, typename T6, typename T7, typename T8, typename T9>
00232   class MultiTypeBlockVector : public fusion::vector<T1, T2, T3, T4, T5, T6, T7, T8, T9> {
00233 
00234   public:
00235 
00239     typedef MultiTypeBlockVector<T1, T2, T3, T4, T5, T6, T7, T8, T9> type;
00240 
00241     typedef typename T1::field_type field_type;
00242 
00246     const int count() {return mpl::size<type>::value;}
00247 
00251     template<typename T>
00252     void operator= (const T& newval) {MultiTypeBlockVector_Ident<mpl::size<type>::value,type,T>::equalize(*this, newval); }
00253 
00257     void operator+= (const type& newv) {MultiTypeBlockVector_Add<mpl::size<type>::value,type>::add(*this,newv);}
00258 
00262     void operator-= (const type& newv) {MultiTypeBlockVector_Add<mpl::size<type>::value,type>::sub(*this,newv);}
00263 
00264     void operator*= (const int& w) {MultiTypeBlockVector_Mulscal<mpl::size<type>::value,type,const int>::mul(*this,w);}
00265     void operator*= (const float& w) {MultiTypeBlockVector_Mulscal<mpl::size<type>::value,type,const float>::mul(*this,w);}
00266     void operator*= (const double& w) {MultiTypeBlockVector_Mulscal<mpl::size<type>::value,type,const double>::mul(*this,w);}
00267 
00268     field_type operator* (const type& newv) const {return MultiTypeBlockVector_Mul<mpl::size<type>::value,type>::mul(*this,newv);}
00269 
00273     double two_norm2() const {return MultiTypeBlockVector_Norm<mpl::size<type>::value,type>::result(*this);}
00274 
00278     double two_norm() const {return sqrt(this->two_norm2());}
00279 
00283     template<typename Ta>
00284     void axpy (const Ta& a, const type& y) {
00285       MultiTypeBlockVector_AXPY<mpl::size<type>::value,type,Ta>::axpy(*this,a,y);
00286     }
00287 
00288   };
00289 
00290 
00291 
00297   template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9>
00298   std::ostream& operator<< (std::ostream& s, const MultiTypeBlockVector<T1,T2,T3,T4,T5,T6,T7,T8,T9>& v) {
00299     MultiTypeBlockVector_Print<0,mpl::size<MultiTypeBlockVector<T1,T2,T3,T4,T5,T6,T7,T8,T9> >::value,MultiTypeBlockVector<T1,T2,T3,T4,T5,T6,T7,T8,T9> >::print(v);
00300     return s;
00301   }
00302 
00303 
00304 
00305 } // end namespace
00306 
00307 #endif
00308 
00309 #endif