dune-localfunctions
2.1.1
|
00001 #ifndef DUNE_MULTIINDEX_HH 00002 #define DUNE_MULTIINDEX_HH 00003 00004 #include <vector> 00005 #include <ostream> 00006 00007 #include <dune/common/fvector.hh> 00008 00009 #include <dune/localfunctions/utility/field.hh> 00010 00011 namespace Dune 00012 { 00013 /**************************************************************** 00014 * Provide a Field class which can be used in evaluation methods 00015 * to produce MultiIndex presentation of polynomials. 00016 ****************************************************************/ 00017 // Internal Forward Declarations 00018 // ----------------------------- 00019 00020 template< int dim, class Field > 00021 class MultiIndex; 00022 00023 template< int dim, class Field > 00024 std::ostream &operator<< ( std::ostream &, const MultiIndex< dim,Field > & ); 00025 00026 00027 00028 // MultiIndex 00029 // ---------- 00030 00031 template< int dim,class Field > 00032 class MultiIndex 00033 { 00034 typedef MultiIndex< dim, Field > This; 00035 00036 friend std::ostream &operator<<<> ( std::ostream &, const This & ); 00037 00038 public: 00039 static const int dimension = dim; 00040 00041 MultiIndex () 00042 : vecZ_( 0 ), 00043 vecOMZ_( 0 ), 00044 factor_( 1. ), 00045 next_( 0 ) 00046 {} 00047 template <class F> 00048 explicit MultiIndex (const F &f) 00049 : vecZ_( 0 ), 00050 vecOMZ_( 0 ), 00051 factor_( field_cast<Field>(f) ), 00052 next_( 0 ) 00053 {} 00054 00055 MultiIndex ( int, const This &other ) 00056 : vecZ_( other.vecOMZ_ ), 00057 vecOMZ_( other.vecZ_ ), 00058 factor_( other.factor_ ) 00059 { 00060 assert(!other.next_); 00061 if (other.next_) 00062 { 00063 next_ = new This( *(other.next_) ); 00064 } 00065 else 00066 next_ = 0; 00067 } 00068 00069 MultiIndex ( const This &other ) 00070 : vecZ_( other.vecZ_ ), 00071 vecOMZ_( other.vecOMZ_ ), 00072 factor_( other.factor_ ) 00073 { 00074 if (other.next_) 00075 { 00076 next_ = new This( *(other.next_) ); 00077 } 00078 else 00079 next_ = 0; 00080 } 00081 00082 ~MultiIndex() 00083 { 00084 remove(); 00085 } 00086 00087 int z(int i) const 00088 { 00089 return vecZ_[i]; 00090 } 00091 int omz(int i) const 00092 { 00093 return vecOMZ_[i]; 00094 } 00095 const Field &factor() const 00096 { 00097 return factor_; 00098 } 00099 00100 This &operator= ( const This &other ) 00101 { 00102 remove(); 00103 vecZ_ = other.vecZ_; 00104 vecOMZ_ = other.vecOMZ_; 00105 factor_ = other.factor_; 00106 if (other.next_) 00107 next_ = new This(*(other.next_)); 00108 return *this; 00109 } 00110 This &operator= ( const Zero<This> &f ) 00111 { 00112 remove(); 00113 vecZ_ = 0; 00114 vecOMZ_ = 0; 00115 factor_ = 0.; 00116 return *this; 00117 } 00118 This &operator= ( const Unity<This> &f ) 00119 { 00120 remove(); 00121 vecZ_ = 0; 00122 vecOMZ_ = 0; 00123 factor_ = 1.; 00124 return *this; 00125 } 00126 template <class F> 00127 This &operator= ( const F &f ) 00128 { 00129 remove(); 00130 vecZ_ = 0; 00131 vecOMZ_ = 0; 00132 factor_ = field_cast<Field>(f); 00133 return *this; 00134 } 00135 00136 bool operator== (const This &other) const 00137 { 00138 assert(!next_ && !other.next_); 00139 return (vecZ_==other.vecZ_ && vecOMZ_==other.vecOMZ_ && factor_==other.factor_); 00140 } 00141 00142 template <class F> 00143 This &operator*= ( const F &f ) 00144 { 00145 factor_ *= field_cast<Field>(f); 00146 if (next_) 00147 (*next_) *= f; 00148 return *this; 00149 } 00150 template <class F> 00151 This &operator/= ( const F &f ) 00152 { 00153 factor_ /= field_cast<Field>(f); 00154 if (next_) 00155 (*next_) /= f; 00156 return *this; 00157 } 00158 00159 This &operator*= ( const This &other ) 00160 { 00161 assert(!other.next_); 00162 vecZ_ += other.vecZ_; 00163 vecOMZ_ += other.vecOMZ_; 00164 factor_ *= other.factor_; 00165 if (next_) 00166 (*next_) *= other; 00167 return *this; 00168 } 00169 This &operator/= ( const This &other ) 00170 { 00171 assert(!other.next_); 00172 vecZ_ -= other.vecZ_; 00173 vecOMZ_ -= other.vecOMZ_; 00174 factor_ /= other.factor_; 00175 if (next_) 00176 (*next_) /= other; 00177 return *this; 00178 } 00179 00180 This &operator+= ( const This &other ) 00181 { 00182 assert(!other.next_); 00183 if (std::abs(other.factor_)<1e-10) 00184 return *this; 00185 if (std::abs(factor_)<1e-10) 00186 { 00187 *this = other; 00188 return *this; 00189 } 00190 if (!sameMultiIndex(other)) 00191 { 00192 if (next_) 00193 (*next_)+=other; 00194 else 00195 { 00196 next_ = new This(other); 00197 } 00198 } 00199 else 00200 factor_ += other.factor_; 00201 return *this; 00202 } 00203 This &operator-= ( const This &other ) 00204 { 00205 assert(!other.next_); 00206 if (!sameMultiIndex(other)) 00207 { 00208 if (next_) 00209 next_-=other; 00210 else 00211 { 00212 next_ = new This(other); 00213 } 00214 } 00215 else 00216 factor_ -= other.factor_; 00217 return *this; 00218 } 00219 00220 template <class F> 00221 This operator* ( const F &f ) const 00222 { 00223 This z = *this; 00224 return (z *= f); 00225 } 00226 template <class F> 00227 This operator/ ( const F &f ) const 00228 { 00229 This z = *this; 00230 return (z /= f); 00231 } 00232 00233 This operator* ( const This &other ) const 00234 { 00235 This z = *this; 00236 return (z *= other); 00237 } 00238 This operator/ ( const This &other ) const 00239 { 00240 This z = *this; 00241 return (z /= other); 00242 } 00243 00244 This operator+ ( const This &other ) const 00245 { 00246 This z = *this; 00247 return (z += other); 00248 } 00249 This operator- ( const This &other ) const 00250 { 00251 This z = *this; 00252 return (z -= other); 00253 } 00254 00255 void set ( int d, int power = 1 ) 00256 { 00257 vecZ_[ d ] = power; 00258 } 00259 00260 int absZ () const 00261 { 00262 int ret = 0; 00263 for( int i = 0; i < dimension; ++i ) 00264 ret += std::abs( vecZ_[ i ] ); 00265 return ret; 00266 } 00267 00268 int absOMZ() const 00269 { 00270 int ret = 0; 00271 for( int i = 0; i < dimension; ++i ) 00272 ret += std::abs( vecOMZ_[ i ] ); 00273 return ret; 00274 } 00275 00276 bool sameMultiIndex(const This &ind) 00277 { 00278 for( int i = 0; i < dimension; ++i ) 00279 { 00280 if ( vecZ_[i] != ind.vecZ_[i] || 00281 vecOMZ_[i] != vecOMZ_[i] ) 00282 return false; 00283 } 00284 return true; 00285 } 00286 00287 private: 00288 void remove() 00289 { 00290 if (next_) 00291 { 00292 next_->remove(); 00293 delete next_; 00294 next_ = 0; 00295 } 00296 } 00297 00298 typedef Dune::FieldVector< int, dimension > Vector; 00299 00300 Vector vecZ_; 00301 Vector vecOMZ_; 00302 Field factor_; 00303 00304 This *next_; 00305 }; 00306 00307 template <int dim, class Field, class F> 00308 MultiIndex<dim,Field> operator* ( const F &f, 00309 const MultiIndex<dim,Field> &m) 00310 { 00311 MultiIndex<dim,Field> z = m; 00312 return (z *= f); 00313 } 00314 template <int dim, class Field, class F> 00315 MultiIndex<dim,Field> operator/ ( const F &f, 00316 const MultiIndex<dim,Field> &m) 00317 { 00318 MultiIndex<dim,Field> z = m; 00319 return (z /= f); 00320 } 00321 00322 template <int d, class F> 00323 std::ostream &operator<<(std::ostream& out,const std::vector<MultiIndex<d,F> >& y) { 00324 for (unsigned int r=0;r<y.size();++r) { 00325 out << "f_{" << r << "}(" << char('a'); 00326 for (int i=1;i<d;++i) 00327 out << "," << char('a'+i); 00328 out << ")="; 00329 out << y[r] << std::endl; 00330 } 00331 return out; 00332 } 00333 template <int d,class F,int dimR> 00334 std::ostream &operator<<(std::ostream& out, 00335 const std::vector<Dune::FieldVector<MultiIndex<d,F>,dimR> >& y) { 00336 out << "\\begin{eqnarray*}" << std::endl; 00337 for (unsigned int k=0;k<y.size();++k) { 00338 out << "f_{" << k << "}(" << char('a'); 00339 for (int i=1;i<d;++i) 00340 out << "," << char('a'+i); 00341 out << ") &=& ( "; 00342 out << y[k][0] ; 00343 for (unsigned int r=1;r<dimR;++r) { 00344 out << " , " << y[k][r] ; 00345 } 00346 out << " ) \\\\" << std::endl; 00347 } 00348 out << "\\end{eqnarray*}" << std::endl; 00349 return out; 00350 } 00351 template <int d,class F,int dimR1,int dimR2> 00352 std::ostream &operator<<(std::ostream& out, 00353 const std::vector<Dune::FieldMatrix<MultiIndex<d,F>,dimR1,dimR2> >& y) { 00354 out << "\\begin{eqnarray*}" << std::endl; 00355 for (unsigned int k=0;k<y.size();++k) { 00356 for (int q=0;q<dimR2;q++) { 00357 out << "d_{" << char('a'+q) << "}f_{" << k << "}(" << char('a'); 00358 for (int i=1;i<d;++i) 00359 out << "," << char('a'+i); 00360 out << ") &=& ( "; 00361 out << y[k][0][q] ; 00362 for (unsigned int r=1;r<dimR1;++r) { 00363 out << " , " << y[k][r][q] ; 00364 } 00365 out << " ) \\\\" << std::endl; 00366 } 00367 } 00368 out << "\\end{eqnarray*}" << std::endl; 00369 return out; 00370 } 00371 template <int d, class F> 00372 std::ostream &operator<<(std::ostream& out,const MultiIndex<d,F>& val) 00373 { 00374 bool first = true; 00375 const MultiIndex<d,F> *m = &val; 00376 do { 00377 if (m->absZ()==0 && std::abs(m->factor())<1e-10) 00378 { 00379 if (!m->next_ || !first) 00380 { 00381 out << "0"; 00382 break; 00383 } 00384 else { 00385 m = m->next_; 00386 continue; 00387 } 00388 } 00389 if (m->factor()>0 && !first) 00390 out << " + "; 00391 else if (m->factor()<0) 00392 if (!first) 00393 out << " - "; 00394 else 00395 out << "- "; 00396 else 00397 out << " "; 00398 first = false; 00399 F f = std::abs(m->factor()); 00400 if (m->absZ()==0) 00401 out << f; 00402 else { 00403 if ( std::abs(f)<1e-10) 00404 out << 0; 00405 else 00406 { 00407 F f_1(f); 00408 f_1 -= 1.; // better Unity<F>(); 00409 if ( std::abs(f_1)>1e-10) 00410 out << f; 00411 int absVal = 0; 00412 for (int i=0;i<d;++i) { 00413 if (m->vecZ_[i]==0) 00414 continue; 00415 else if (m->vecZ_[i]==1) 00416 out << char('a'+i); 00417 else if (m->vecZ_[i]>0) 00418 out << char('a'+i) << "^" << m->vecZ_[i] << ""; 00419 else if (m->vecZ_[i]<0) 00420 out << char('a'+i) << "^" << m->vecZ_[i] << ""; 00421 absVal += m->vecZ_[i]; 00422 if (absVal<m->absZ()) out << ""; 00423 } 00424 } 00425 } 00426 /* 00427 if (mi.absOMZ()>0) { 00428 for (int i=0;i<=mi.absZ();++i) { 00429 if (mi.vecOMZ_[i]==0) 00430 continue; 00431 else if (mi.vecOMZ_[i]==1) 00432 out << (1-char('a'+i)); 00433 else if (mi.vecOMZ_[i]>0) 00434 out << (1-char('a'+i)) << "^" << mi.vecOMZ_[i]; 00435 else if (mi.vecOMZ_[i]<0) 00436 out << (1-char('a'+i)) << "^" << mi.vecOMZ_[i]; 00437 if (i==mi.absZ()+1) out << "*"; 00438 } 00439 } 00440 */ 00441 m = m->next_; 00442 } while (m); 00443 return out; 00444 } 00445 00446 template< int dim, class F> 00447 struct Unity< MultiIndex< dim, F > > 00448 { 00449 typedef MultiIndex< dim, F > Field; 00450 00451 operator Field () const 00452 { 00453 return Field(); 00454 } 00455 00456 Field operator- ( const Field &other ) const 00457 { 00458 return Field( 1, other ); 00459 } 00460 00461 Field operator/ ( const Field &other ) const 00462 { 00463 return Field() / other; 00464 } 00465 }; 00466 00467 00468 00469 template< int dim, class F > 00470 struct Zero< MultiIndex< dim,F > > 00471 { 00472 typedef MultiIndex< dim,F > Field; 00473 00474 // zero does not acutally exist 00475 operator Field () 00476 { 00477 return Field(0); 00478 } 00479 }; 00480 00481 template< int dim, class Field > 00482 bool operator< ( const Zero< MultiIndex< dim,Field > > &, const MultiIndex< dim,Field > & ) 00483 { 00484 return true; 00485 } 00486 00487 template< int dim, class Field > 00488 bool operator< ( const MultiIndex< dim, Field > &f, const Zero< MultiIndex< dim,Field > > & ) 00489 { 00490 return true; 00491 } 00492 00493 } 00494 00495 #endif // #ifndef DUNE_MULTIINDEX_HH