dune-istl
2.1.1
|
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