NGSolve
5.3
|
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