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
00015
00016
00017
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
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.;
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
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
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
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