NGSolve  5.3
ngstd/evalfunc.hpp
00001 #ifndef FILE_EVALFUNC
00002 #define FILE_EVALFUNC
00003 
00004 /**************************************************************************/
00005 /* File:   evalfunc.hpp                                                   */
00006 /* Author: Joachim Schoeberl                                              */
00007 /* Date:   01. Oct. 95                                                    */
00008 /**************************************************************************/
00009 
00010 
00011 namespace ngstd
00012 {
00013 
00014 
00015 
00016 
00017   class GenericVariable 
00018   {
00019     int dim;
00020     bool iscomplex;
00021     double * data;
00022   public:
00023     GenericVariable (const GenericVariable & v2)
00024     {
00025       dim = v2.dim;
00026       iscomplex = v2.iscomplex;
00027       int hdim = iscomplex ? 2*dim : dim;
00028       data = new double[hdim];
00029       for (int j = 0; j < hdim; j++)
00030         data[j] = v2.data[j];
00031     }
00032     GenericVariable (GenericVariable && v2)
00033     {
00034       cout << "move constr" << endl;
00035       dim = v2.dim;
00036       iscomplex = v2.iscomplex;
00037       int hdim = iscomplex ? 2*dim : dim;
00038       data = new double[hdim];
00039       for (int j = 0; j < hdim; j++)
00040         data[j] = v2.data[j];
00041     }
00042     GenericVariable (bool acomplex = false, int adim = 1)
00043       : dim(adim), iscomplex(acomplex)
00044     {
00045       int hdim = iscomplex ? 2*dim : dim;
00046       data = new double[hdim];
00047     }
00048     ~GenericVariable ()  
00049     { 
00050       delete [] data; 
00051     }
00052     GenericVariable & operator= (const GenericVariable & v2)
00053     {
00054       dim = v2.dim;
00055       iscomplex = v2.iscomplex;
00056       int hdim = iscomplex ? 2*dim : dim;
00057       delete [] data;
00058       data = new double[hdim];
00059       for (int j = 0; j < hdim; j++)
00060         data[j] = v2.data[j];
00061       return *this;
00062     }
00063 
00064     int Dimension() const { return dim; }
00065     bool IsComplex () const { return iscomplex; }
00066 
00067     double & ValueDouble(int i = 0) { return data[i]; }
00068     complex<double> & ValueComplex (int i = 0) 
00069     { return reinterpret_cast<std::complex<double>*>(data)[i]; }
00070     
00071     const double & ValueDouble(int i = 0) const { return data[i]; }
00072     const std::complex<double> & ValueComplex (int i = 0) const 
00073     { return reinterpret_cast<complex<double>*>(data)[i]; }
00074 
00075     
00076     template <typename SCAL> SCAL Value (int i) const;
00077   };
00078 
00079   template<> 
00080   inline double GenericVariable::Value<double> (int i) const 
00081   { 
00082     if (iscomplex) throw Exception ("Value<double> called for complex variable");
00083     return data[i]; 
00084   }
00085   template<> 
00086   inline std::complex<double> GenericVariable::Value<std::complex<double>> (int i) const 
00087   { 
00088     if (iscomplex)
00089       return complex<double> (data[2*i], data[2*i+1]);
00090     else
00091       return complex<double> (data[i]);
00092   }
00093 
00094 
00095   inline ostream & operator<< (ostream & ost, const GenericVariable & var)
00096   {
00097     if (var.IsComplex())
00098       for (int i = 0; i < var.Dimension(); i++)
00099         ost << var.ValueComplex(i) << ", ";
00100     else
00101       for (int i = 0; i < var.Dimension(); i++)
00102         ost << var.ValueDouble(i) << ", ";
00103     return ost;
00104   }
00105 
00106 
00107 
00108 
00109 
00110 
00111 
00112 
00113 
00120 class NGS_DLL_HEADER EvalFunction
00121 {
00122 
00124   enum EVAL_TOKEN
00125   {
00126     ADD = '+', SUB = '-', MULT = '*', DIV = '/', LP ='(', RP = ')',
00127     COMMA = ',',
00128     NEG = 100, 
00129     VEC_ADD, VEC_SUB, VEC_SCAL_MULT, SCAL_VEC_MULT, VEC_VEC_MULT, VEC_SCAL_DIV, VEC_ELEM, VEC_DIM,
00130     AND, OR, NOT, GREATER, LESS, GREATEREQUAL, LESSEQUAL, EQUAL,
00131     CONSTANT, IMAG, VARIABLE, FUNCTION, GLOBVAR, GLOBGENVAR, /* COEFF_FUNC,*/ END, STRING,
00132     SIN, COS, TAN, ATAN, ATAN2, EXP, LOG, ABS, SIGN, SQRT, STEP,
00133     BESSELJ0, BESSELY0, BESSELJ1, BESSELY1
00134   };
00135 
00136 public:
00138   EvalFunction ();
00140   EvalFunction (istream & aist);
00142   EvalFunction (const string & str);
00144   EvalFunction (const EvalFunction & eval2);
00146   virtual ~EvalFunction ();
00147 
00149   bool Parse (istream & aist);
00151   void DefineConstant (const string & name, double val);
00153   void DefineGlobalVariable (const string & name, double * var);
00155   void DefineGlobalVariable (const string & name, GenericVariable * var);
00157   void DefineArgument (const string & name, int num, int vecdim = 1, bool iscomplex = false);
00158 
00160   double Eval (const double * x = NULL) const;
00162   void Eval (const double * x, double * y, int ydim) const;
00163 
00165   complex<double> Eval (const complex<double> * x = NULL) const;
00167   void Eval (const complex<double> * x, complex<double> * y, int ydim) const;
00169   void Eval (const complex<double> * x, double * y, int ydim) const;
00170 
00171   /*
00173   template <typename TIN>
00174   void Eval (const TIN * x, complex<double> * y, int ydim) const;
00175   */
00176   template <typename TIN, typename TCALC>
00177   void Eval (const TIN * x, TCALC * stack) const;
00178 
00179 
00181   bool IsComplex () const;
00182 
00184   bool IsResultComplex () const { return res_type.iscomplex; }
00185 
00187   bool IsConstant () const;
00189   double EvalConstant () const;
00190 
00192   int Dimension() const { return res_type.vecdim; }
00193 
00195   void AddConstant (double val)
00196   { program.Append (step (val)); }
00197 
00199   void AddVariable (int varnum)
00200   { program.Append (step(varnum)); }
00201 
00203   void AddGlobVariable (const double * dp)
00204   { program.Append (step(dp)); }
00205 
00207   void AddGlobVariable (const GenericVariable * dp)
00208   { program.Append (step(dp)); }
00209 
00211   void AddOperation (EVAL_TOKEN op)
00212   { program.Append (step(op)); }
00213 
00215   void AddFunction (double (*fun) (double))
00216   { program.Append (step(fun)); }
00217 
00219   void Print (ostream & ost) const;
00220 protected:
00221    
00223   class step
00224   {
00225   public:
00227     EVAL_TOKEN op;
00229     union UNION_OP
00230     {
00232       double val;
00234       const double *globvar;
00236       const GenericVariable *globgenvar;
00238       int varnum;
00240       double (*fun) (double);
00241     }; 
00243     UNION_OP operand;
00244 
00246     short int vecdim;
00247 
00248     step () { ; }
00249 
00250     step (EVAL_TOKEN hop)
00251     { 
00252       op = hop;
00253       operand.val = 0;
00254     }
00255 
00256     step (double hval)
00257     { 
00258       op = CONSTANT;
00259       operand.val = hval;
00260     }
00261 
00262     step (int varnum)
00263     { 
00264       op = VARIABLE;
00265       operand.varnum = varnum;
00266     }
00267 
00268     step (const double * aglobvar)
00269     { 
00270       op = GLOBVAR;
00271       operand.globvar = aglobvar;
00272     }
00273 
00274     step (const GenericVariable * aglobvar)
00275     { 
00276       op = GLOBGENVAR;
00277       operand.globgenvar = aglobvar;
00278     }
00279 
00280     step (double (*fun) (double))
00281     {
00282       op = FUNCTION;
00283       operand.fun = fun;
00284     }
00285   };
00286 
00288   Array<step> program;
00289 
00290   class ResultType
00291   {
00292   public:
00293     int vecdim;
00294     bool isbool;
00295     bool iscomplex;
00296     ResultType ()
00297       : vecdim(1), isbool(false), iscomplex(false)
00298     { ; }
00299   };
00300 
00301   ResultType res_type;
00302   const double eps;
00303 
00305   ResultType ParseExpression ();
00307   ResultType ParseCommaExpression ();
00309   ResultType ParseSubExpression ();
00311   ResultType ParseTerm ();
00313   ResultType ParsePrimary ();
00314 
00316   istream * ist;
00317 
00319   EVAL_TOKEN token;
00321   double num_value;
00323   char string_value[1000];
00325   int var_num, var_dim;
00327   bool var_iscomplex;
00329   double * globvar;
00330   GenericVariable * globgenvar;
00331   streampos lastpos;
00332 
00333   typedef double(*TFUNP) (double);
00335   static SymbolTable<TFUNP> functions;
00336 
00338   SymbolTable<double> constants;
00339 
00341   SymbolTable<double*> globvariables;
00343   SymbolTable<GenericVariable*> genericvariables;
00344   
00345 public:
00347   struct argtype
00348   {
00349     int argnum;
00350     int dim;
00351     bool iscomplex;
00352   public:
00353     argtype ()
00354       : argnum(-1), dim(1), iscomplex(false) { ; }
00355     argtype (int aanum, int adim = 1, bool acomplex = false)
00356       : argnum(aanum), dim(adim), iscomplex(acomplex) { ; }
00357   };
00358   SymbolTable<argtype> arguments;
00359   int num_arguments;
00360 
00362   EVAL_TOKEN GetToken() const
00363     { return token; }
00364 
00366   double GetNumValue() const
00367     { return num_value; }
00368 
00370   int GetVariableNumber() const
00371     { return var_num; }
00373   int GetVariableDimension() const
00374     { return var_dim; }
00375   bool GetVariableIsComplex() const
00376     { return var_iscomplex; }
00377 
00379   const char * GetStringValue() const
00380     { return string_value; }
00381   
00383   void ReadNext(bool optional = true);
00384   void WriteBack();
00385 
00386   bool ToBool (double x)  const { return x > eps; }
00387   bool ToBool (complex<double> x) const { return x.real() > eps; }
00388   double CheckReal (double x)  const { return x; }
00389   double CheckReal (complex<double> x) const 
00390   {
00391     if (x.imag() != 0) cerr << "illegal complex value" << endl; 
00392     return x.real();
00393   }
00394 
00395   double Abs (double x) const { return std::fabs(x); }
00396   double Abs (complex<double> x) const { return abs(x); }
00397 };
00398 
00399 
00400 }
00401 
00402 
00403 #endif
00404 
00405