dune-localfunctions  2.1.1
field.hh
Go to the documentation of this file.
00001 #ifndef DUNE_FIELD_HH
00002 #define DUNE_FIELD_HH
00003 
00004 #if HAVE_ALGLIB
00005 #include <alglib/amp.h>
00006 #endif
00007 
00008 #include <dune/common/gmpfield.hh>
00009 #include <dune/common/fvector.hh>
00010 #include <dune/common/fmatrix.hh>
00011 
00012 namespace Dune
00013 {
00014 
00015   // Unity
00016   // -----
00017 
00028   template< class Field >
00029   struct Unity
00030   {
00031     operator Field () const
00032     {
00033       return Field( 1 );
00034     }
00035   };
00036 
00037   template< class Field >
00038   Field operator+ ( const Unity< Field > &u, const Field &f )
00039   {
00040     return (Field)u + f;
00041   }
00042 
00043   template< class Field >
00044   Field operator- ( const Unity< Field > &u, const Field &f )
00045   {
00046     return (Field)u - f;
00047   }
00048 
00049   template< class Field >
00050   Field operator* ( const Unity< Field > &u, const Field &f )
00051   {
00052     return f;
00053   }
00054 
00055   template< class Field >
00056   Field operator/ ( const Unity< Field > &u, const Field &f )
00057   {
00058     return (Field)u / f;
00059   }
00060 
00061 
00062 
00063   // Zero
00064   // ----
00065 
00077   template< class Field >
00078   struct Zero
00079   {
00080     operator Field () const
00081     {
00082       return Field( 0 );
00083     }
00084     static const Field epsilon()
00085     {
00086       return Field(1e-12);
00087     }
00088   };
00089 #if HAVE_ALGLIB
00090   template< unsigned int precision >
00091   struct Zero< amp::ampf< precision > >
00092   {
00093     typedef amp::ampf< precision > Field;
00094     operator Field () const
00095     {
00096       return Field( 0 );
00097     }
00098     static const Field epsilon()
00099     {
00100       return Field(1e-20);
00101     }
00102   };
00103 #endif
00104 #if HAVE_GMP
00105   template< unsigned int precision >
00106   struct Zero< GMPField< precision > >
00107   {
00108     typedef GMPField< precision > Field;
00109     operator Field () const
00110     {
00111       return Field( 0 );
00112     }
00113     static const Field epsilon()
00114     {
00115       return Field(1e-20);
00116     }
00117   };
00118 #endif
00119 
00120   template< class Field >
00121   inline bool operator == ( const Zero< Field > &, const Field &f )
00122   {
00123     return ( f < Zero<Field>::epsilon() && f > -Zero<Field>::epsilon() );
00124   }
00125 
00126   template< class Field >
00127   inline bool operator == ( const Field &f, const Zero< Field > &z)
00128   {
00129     return ( z == f );
00130   }
00131 
00132   template< class Field >
00133   inline bool operator< ( const Zero< Field > &, const Field &f )
00134   {
00135     return f > Zero<Field>::epsilon();
00136   }
00137 
00138   template< class Field >
00139   inline bool operator< ( const Field &f, const Zero< Field > & )
00140   {
00141     return f < -Zero<Field>::epsilon();
00142   }
00143 
00144   template< class Field >
00145   inline bool operator> ( const Zero< Field > &z, const Field &f )
00146   {
00147     return f < z;
00148   }
00149 
00150   template< class Field >
00151   inline bool operator> ( const Field &f, const Zero< Field > &z )
00152   {
00153     return z < f;
00154   }
00155 
00156 
00157   // field_cast
00158   // ----------
00159 
00172   template< class F2, class F1 >
00173   inline void field_cast ( const F1 &f1, F2 &f2 )
00174   {
00175     f2 = f1;
00176   }
00177 
00178 #if HAVE_ALGLIB
00179   template< unsigned int precision >
00180   inline void field_cast ( const amp::ampf< precision > &f1, double &f2 )
00181   {
00182     f2 = f1.toDouble();
00183   }
00184 
00185   template< unsigned int precision >
00186   inline void field_cast ( const amp::ampf< precision > &f1, long double &f2 )
00187   {
00188     f2 = f1.toDouble();
00189   }
00190 #endif
00191 
00192 #if HAVE_GMP
00193   template< unsigned int precision >
00194   inline void field_cast ( const Dune::GMPField< precision > &f1, double &f2 )
00195   {
00196     f2 = f1.get_d();
00197   }
00198 
00199   template< unsigned int precision >
00200   inline void field_cast ( const Dune::GMPField< precision > &f1, long double &f2 )
00201   {
00202     f2 = f1.get_d();
00203   }
00204 #endif
00205 
00206   template< class F2, class F1, int dim >
00207   inline void field_cast ( const Dune::FieldVector< F1, dim > &f1, Dune::FieldVector< F2, dim > &f2 )
00208   {
00209     for( int d = 0; d < dim; ++d )
00210       field_cast( f1[ d ], f2[ d ] );
00211   }
00212   template< class F2, class F1 >
00213   inline void field_cast ( const Dune::FieldVector< F1, 1 > &f1, F2 &f2 )
00214   {
00215     field_cast( f1[ 0 ], f2 );
00216   }
00217   template< class F2, class F1 >
00218   inline void field_cast ( const F1 &f1, Dune::FieldVector< F2, 1 > &f2 )
00219   {
00220     field_cast( f1, f2[ 0 ] );
00221   }
00222 
00223   template< class F2, class F1, int rdim, int cdim >
00224   inline void field_cast ( const Dune::FieldMatrix< F1, rdim, cdim > &f1, Dune::FieldMatrix< F2, rdim, cdim > &f2 )
00225   {
00226     for( int r = 0; r < rdim; ++r )
00227       field_cast( f1[ r ], f2[ r ] );
00228   }
00229   template< class F2, class F1 >
00230   inline void field_cast ( const Dune::FieldMatrix<F1,1,1> &f1, Dune::FieldMatrix< F2, 1,1 > &f2 )
00231   {
00232     field_cast( f1[ 0 ][ 0 ], f2[ 0 ][ 0 ] );
00233   }
00234   template< class F2, class F1 >
00235   inline void field_cast ( const Dune::FieldMatrix< F1, 1,1 > &f1, F2 &f2 )
00236   {
00237     field_cast( f1[ 0 ][ 0 ], f2 );
00238   }
00239   template< class F2, class F1 >
00240   inline void field_cast ( const F1 &f1, Dune::FieldMatrix< F2, 1,1 > &f2 )
00241   {
00242     field_cast( f1, f2[ 0 ][ 0 ] );
00243   }
00244   template< class F2, class F1 >
00245   inline void field_cast ( const Dune::FieldVector<F1,1> &f1, Dune::FieldMatrix< F2, 1,1 > &f2 )
00246   {
00247     field_cast( f1[ 0 ], f2[ 0 ][ 0 ] );
00248   }
00249   template< class F2, class F1 >
00250   inline void field_cast ( const Dune::FieldMatrix<F1,1,1> &f1, Dune::FieldVector< F2, 1 > &f2 )
00251   {
00252     field_cast( f1[ 0 ][ 0 ], f2[ 0 ] );
00253   }
00254 
00255   template< class F2, class F1 >
00256   inline void field_cast ( const Dune::FieldVector< F1, 1 > &f1, Dune::FieldVector<F2, 1> &f2 )
00257   {
00258     field_cast( f1[ 0 ], f2[ 0 ] );
00259   }
00260 
00261   template< class F2,class V > 
00262   struct FieldCast
00263   {
00264     typedef F2 type;
00265   };
00266   template< class F2,class F1,int dim > 
00267   struct FieldCast< F2, Dune::FieldVector<F1,dim> >
00268   {
00269     typedef Dune::FieldVector<F2,dim> type;
00270   };
00271   template< class F2,class F1,int dim1, int dim2> 
00272   struct FieldCast< F2, Dune::FieldMatrix<F1,dim1,dim2> >
00273   {
00274     typedef Dune::FieldMatrix<F2,dim1,dim2> type;
00275   };
00276   template< class F2,class V > 
00277   inline typename FieldCast<F2,V>::type field_cast ( const V &f1 )
00278   {
00279     typename FieldCast<F2,V>::type f2;
00280     field_cast( f1, f2 );
00281     return f2;
00282   }
00283 
00284 
00285   // Precision
00286   // this is not a perfect solution to obtain the
00287   // precision of a field - definition is not clear
00288   // to be removed
00289   // ---------
00290 
00291   template <class Field>
00292   struct Precision;
00293 
00294   template<>
00295   struct Precision< double >
00296   {
00297     static const unsigned int value = 64;
00298   };
00299 
00300   template<>
00301   struct Precision< long double >
00302   {
00303     static const unsigned int value = 80;
00304   };
00305 
00306   template<>
00307   struct Precision< float >
00308   {
00309     static const unsigned int value = 32;
00310   };
00311 
00312 #if HAVE_ALGLIB
00313   template< unsigned int precision >
00314   struct Precision< amp::ampf< precision > >
00315   {
00316     static const unsigned int value = precision;
00317   };
00318 #endif
00319 #if HAVE_GMP
00320   template< unsigned int precision >
00321   struct Precision< GMPField< precision > >
00322   {
00323     static const unsigned int value = precision;
00324   };
00325 #endif
00326 
00327   // ComputeField
00328   // ------------
00329 
00330   template <class Field,unsigned int sum>
00331   struct ComputeField 
00332   {
00333     typedef Field Type;
00334   };
00335 
00336 #if HAVE_ALGLIB
00337   template< unsigned int precision, unsigned int sum >
00338   struct ComputeField< amp::ampf< precision >, sum >
00339   {
00340     typedef amp::ampf<precision+sum> Type;
00341   };
00342 #endif
00343 #if HAVE_GMP
00344   template< unsigned int precision, unsigned int sum >
00345   struct ComputeField< GMPField< precision >, sum >
00346   {
00347     typedef GMPField<precision+sum> Type;
00348   };
00349 #endif
00350 }
00351 
00352 // to be moved to different location...
00353 namespace std
00354 {
00355 
00356 #if HAVE_ALGLIB
00357   template< unsigned int precision >
00358   inline ostream &
00359   operator<< ( ostream &out, 
00360                const amp::ampf< precision > &value )
00361   {
00362     return out << value.toDec();
00363   }
00364 
00365   template< unsigned int precision >
00366   inline amp::ampf< precision > sqrt ( const amp::ampf< precision > &a )
00367   {
00368     return amp::sqrt( a );
00369   }
00370 
00371   template< unsigned int precision >
00372   inline amp::ampf< precision > abs ( const amp::ampf< precision > &a )
00373   {
00374     return amp::abs( a );
00375   }
00376 #endif // #if HAVE_ALGLIB
00377 
00378 }
00379 
00380 #endif // #ifndef DUNE_FIELD_HH