dune-localfunctions  2.1.1
multiindex.hh
Go to the documentation of this file.
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