From 37b6d10d70fea294f51b7631514c57182a81217d Mon Sep 17 00:00:00 2001 From: ageay Date: Mon, 22 Feb 2010 07:29:52 +0000 Subject: [PATCH] *** empty log message *** --- .../ExprEval/INTERPKERNELEXPREVALDefines.hxx | 33 + .../ExprEval/InterpKernelExprParser.cxx | 674 ++++++++++++++++++ .../ExprEval/InterpKernelExprParser.hxx | 98 +++ .../ExprEval/InterpKernelFunction.cxx | 549 ++++++++++++++ .../ExprEval/InterpKernelFunction.hxx | 234 ++++++ .../ExprEval/InterpKernelUnit.cxx | 353 +++++++++ .../ExprEval/InterpKernelUnit.hxx | 98 +++ .../ExprEval/InterpKernelValue.cxx | 409 +++++++++++ .../ExprEval/InterpKernelValue.hxx | 138 ++++ src/INTERP_KERNEL/ExprEval/Makefile.am | 56 ++ src/INTERP_KERNEL/Makefile.am | 6 +- src/INTERP_KERNELTest/ExprEvalInterpTest.cxx | 380 ++++++++++ src/INTERP_KERNELTest/ExprEvalInterpTest.hxx | 53 ++ src/INTERP_KERNELTest/Makefile.am | 3 + src/INTERP_KERNELTest/TestInterpKernel.cxx | 2 + 15 files changed, 3083 insertions(+), 3 deletions(-) create mode 100644 src/INTERP_KERNEL/ExprEval/INTERPKERNELEXPREVALDefines.hxx create mode 100644 src/INTERP_KERNEL/ExprEval/InterpKernelExprParser.cxx create mode 100644 src/INTERP_KERNEL/ExprEval/InterpKernelExprParser.hxx create mode 100644 src/INTERP_KERNEL/ExprEval/InterpKernelFunction.cxx create mode 100644 src/INTERP_KERNEL/ExprEval/InterpKernelFunction.hxx create mode 100644 src/INTERP_KERNEL/ExprEval/InterpKernelUnit.cxx create mode 100644 src/INTERP_KERNEL/ExprEval/InterpKernelUnit.hxx create mode 100644 src/INTERP_KERNEL/ExprEval/InterpKernelValue.cxx create mode 100644 src/INTERP_KERNEL/ExprEval/InterpKernelValue.hxx create mode 100644 src/INTERP_KERNEL/ExprEval/Makefile.am create mode 100644 src/INTERP_KERNELTest/ExprEvalInterpTest.cxx create mode 100644 src/INTERP_KERNELTest/ExprEvalInterpTest.hxx diff --git a/src/INTERP_KERNEL/ExprEval/INTERPKERNELEXPREVALDefines.hxx b/src/INTERP_KERNEL/ExprEval/INTERPKERNELEXPREVALDefines.hxx new file mode 100644 index 000000000..665de2e94 --- /dev/null +++ b/src/INTERP_KERNEL/ExprEval/INTERPKERNELEXPREVALDefines.hxx @@ -0,0 +1,33 @@ +// Copyright (C) 2007-2008 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// +#ifndef __INTERPKERNELEXPREVALDEFINES_HXX__ +#define __INTERPKERNELEXPREVALDEFINES_HXX__ + +//export symbols +#ifdef WIN32 +# if defined INTERPKERNELEXPREVAL_EXPORTS || defined interpkernelexpreval_EXPORTS +# define INTERPKERNELEXPREVAL_EXPORT __declspec(dllexport) +# else +# define INTERPKERNELEXPREVAL_EXPORT __declspec(dllimport) +# endif +#else +# define INTERPKERNELEXPREVAL_EXPORT +#endif + +#endif diff --git a/src/INTERP_KERNEL/ExprEval/InterpKernelExprParser.cxx b/src/INTERP_KERNEL/ExprEval/InterpKernelExprParser.cxx new file mode 100644 index 000000000..e5e358930 --- /dev/null +++ b/src/INTERP_KERNEL/ExprEval/InterpKernelExprParser.cxx @@ -0,0 +1,674 @@ +#include "InterpKernelExprParser.hxx" +#include "InterpKernelValue.hxx" + +#include +#include +#include +#include +#include + +using namespace INTERP_KERNEL; + +const char LeafExprVar::END_OF_RECOGNIZED_VAR[]="Vec"; + +const char ExprParser::WHITE_SPACES[]=" \n"; + +const char ExprParser::EXPR_PARSE_ERR_MSG[]="Invalid expression detected : "; + +LeafExpr *LeafExpr::buildInstanceFrom(const std::string& expr) throw(INTERP_KERNEL::Exception) +{ + std::istringstream stream; + stream.str(expr); + double val; + stream >> val; + if(!stream.fail()) + if(stream.eof()) + return new LeafExprVal(val); + else + { + std::ostringstream errMsg; + char MSGTYP6[]="Error following expression is not consedered as a double value : "; + errMsg << MSGTYP6 << expr; + throw INTERP_KERNEL::Exception(errMsg.str().c_str()); + } + else + return new LeafExprVar(expr); +} + +LeafExpr::~LeafExpr() +{ +} + +LeafExprVal::LeafExprVal(double value):_value(value) +{ +} + +LeafExprVal::~LeafExprVal() +{ +} + +void LeafExprVal::fillValue(Value *val) const throw(INTERP_KERNEL::Exception) +{ + val->setDouble(_value); +} + +LeafExprVar::LeafExprVar(const std::string& var):_fast_pos(-1),_var_name(var) +{ +} + +void LeafExprVar::fillValue(Value *val) const throw(INTERP_KERNEL::Exception) +{ + val->setVarname(_fast_pos,_var_name); +} + +void LeafExprVar::prepareExprEvaluation(const std::vector& vars) const throw(INTERP_KERNEL::Exception) +{ + std::vector::const_iterator iter=std::find(vars.begin(),vars.end(),_var_name); + if(iter==vars.end()) + { + if(!isRecognizedKeyVar(_var_name,_fast_pos)) + { + std::ostringstream oss; oss << "Var : " << _var_name << " not in : "; + std::copy(vars.begin(),vars.end(),std::ostream_iterator(oss,", ")); + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + return; + } + _fast_pos=iter-vars.begin(); +} + +void LeafExprVar::prepareExprEvaluationVec() const throw(INTERP_KERNEL::Exception) +{ + if(!isRecognizedKeyVar(_var_name,_fast_pos)) + _fast_pos=-2; +} + +bool LeafExprVar::isRecognizedKeyVar(const std::string& var, int& pos) +{ + if(var.length()!=sizeof(END_OF_RECOGNIZED_VAR)) + return false; + std::string end=var.substr(1); + if(end!=END_OF_RECOGNIZED_VAR) + return false; + char first=var[0]; + if(first<'I' || first>'Z') + return false; + pos=-7-(first-'I'); + return true; +} + +LeafExprVar::~LeafExprVar() +{ +} + +ExprParser::ExprParser(const char *expr):_is_parsed(false),_leaf(0),_is_parsing_ok(false),_expr(expr) +{ +} + +//! For \b NOT null terminated strings coming from FORTRAN. +ExprParser::ExprParser(const char *expr, int lgth):_is_parsed(false),_leaf(0),_is_parsing_ok(false) +{ + _expr=buildStringFromFortran(expr,lgth); +} + +ExprParser::~ExprParser() +{ + delete _leaf; + releaseFunctions(); +} + +std::size_t ExprParser::findCorrespondingOpenBracket(const std::string& expr, std::size_t posOfCloseBracket) +{ + int level=0; + for(std::size_t iter=posOfCloseBracket-1;iter>=0;iter--) + if(expr[iter]==')') + level++; + else if(expr[iter]=='(') + { + if(level==0) + return iter; + else + level--; + } + return std::string::npos; +} + +std::string ExprParser::buildStringFromFortran(const char *expr, int lgth) +{ + std::string ret(expr,lgth); + std::string whiteSpaces(WHITE_SPACES); + std::size_t found=ret.find_last_not_of(whiteSpaces); + if (found!=std::string::npos) + ret.erase(found+1); + else + ret.clear();//ret is all whitespace + return ret; +} + +std::string ExprParser::deleteWhiteSpaces(const std::string& expr) +{ + std::string ret(expr); + std::string whiteSpaces(WHITE_SPACES); + std::size_t where1=0,where2=0; + while(where2!=std::string::npos && where1!=std::string::npos) + { + where1=ret.find_first_of(whiteSpaces.c_str(),where1,whiteSpaces.length()); + if(where1!=std::string::npos) + { + where2=ret.find_first_not_of(whiteSpaces,where1); + if(where2!=std::string::npos) + ret.erase(ret.begin()+where1,ret.begin()+where2); + else + ret.erase(ret.begin()+where1,ret.end()); + } + } + return ret; +} + +void ExprParser::parse() throw(INTERP_KERNEL::Exception) +{ + _is_parsed=true; + _is_parsing_ok=false; + _sub_expr.clear(); + releaseFunctions(); + if(!_expr.empty()) + { + checkBracketsParity(); + if(!simplify()) + parseDeeper(); + } + _is_parsing_ok=true; +} + +double ExprParser::evaluate() const throw(INTERP_KERNEL::Exception) +{ + Value *gen=new ValueDouble; + ValueDouble *res=(ValueDouble *)evaluateLowLev(gen); + delete gen; + double ret=res->getData(); + delete res; + return ret; +} + +DecompositionInUnitBase ExprParser::evaluateUnit() const throw(INTERP_KERNEL::Exception) +{ + Value *gen=new ValueUnit; + ValueUnit *res=0; + try + { + res=(ValueUnit *)evaluateLowLev(gen); + } + catch(INTERP_KERNEL::Exception& e) + { + delete gen; + throw e; + } + delete gen; + DecompositionInUnitBase ret=res->getData(); + delete res; + return ret; +} + +void ExprParser::evaluateExpr(int szOfOutParam, double *outParam, const double *inParam) const throw(INTERP_KERNEL::Exception) +{ + Value *gen=new ValueDoubleExpr(szOfOutParam,inParam); + ValueDoubleExpr *res=0; + try + { + res=(ValueDoubleExpr *)evaluateLowLev(gen); + } + catch(INTERP_KERNEL::Exception& e) + { + delete gen; + throw e; + } + delete gen; + std::copy(res->getData(),res->getData()+szOfOutParam,outParam); + delete res; +} + +void ExprParser::prepareExprEvaluation(const std::vector& vars) const throw(INTERP_KERNEL::Exception) +{ + if(_leaf) + { + LeafExprVar *leafC=dynamic_cast(_leaf); + if(leafC) + leafC->prepareExprEvaluation(vars); + } + else + for(std::list::const_iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++) + (*iter).prepareExprEvaluation(vars); +} + +void ExprParser::prepareExprEvaluationVec() const throw(INTERP_KERNEL::Exception) +{ + std::set trueVars; + getTrueSetOfVars(trueVars); + if(trueVars.size()>1) + { + std::ostringstream oss; oss << "For this type of evaluation only one not keyword variable authorized : "; + oss << "having " << trueVars.size() << " : "; + std::copy(trueVars.begin(),trueVars.end(),std::ostream_iterator(oss," ")); oss << " !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + prepareExprEvaluationVecLowLev(); +} + +void ExprParser::prepareExprEvaluationVecLowLev() const throw(INTERP_KERNEL::Exception) +{ + if(_leaf) + { + LeafExprVar *leafC=dynamic_cast(_leaf); + if(leafC) + leafC->prepareExprEvaluationVec(); + } + else + for(std::list::const_iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++) + (*iter).prepareExprEvaluationVecLowLev(); +} + +Value *ExprParser::evaluateLowLev(Value *valGen) const throw(INTERP_KERNEL::Exception) +{ + if(!_is_parsing_ok) + throw INTERP_KERNEL::Exception("Parsing fails ! Invalid expression !"); + if(_sub_expr.empty() && !_leaf) + throw INTERP_KERNEL::Exception("Empty expression !"); + std::vector stackOfVal; + try + { + if(_leaf) + { + Value *ret=valGen->newInstance(); + try + { + _leaf->fillValue(ret); + } + catch(INTERP_KERNEL::Exception& e) + { + delete ret; + throw e; + } + stackOfVal.resize(1); + stackOfVal[0]=ret; + } + else + { + stackOfVal.resize(_sub_expr.size()); + std::vector::reverse_iterator iter2=stackOfVal.rbegin(); + for(std::list::const_iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++,iter2++) + *iter2=(*iter).evaluateLowLev(valGen); + } + std::list::const_iterator iter3; + for(iter3=_func_btw_sub_expr.begin();iter3!=_func_btw_sub_expr.end();iter3++) + (*iter3)->operate(stackOfVal); + } + catch(INTERP_KERNEL::Exception& e) + { + for(std::vector::iterator iter4=stackOfVal.begin();iter4!=stackOfVal.end();iter4++) + delete *iter4; + throw e; + } + return stackOfVal.back(); +} + +void ExprParser::getSetOfVars(std::set& vars) const +{ + if(_leaf) + { + LeafExprVar *leafC=dynamic_cast(_leaf); + if(leafC) + vars.insert(leafC->getVar()); + } + else + for(std::list::const_iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++) + (*iter).getSetOfVars(vars); +} + +void ExprParser::getTrueSetOfVars(std::set& trueVars) const +{ + std::set vars; + getSetOfVars(vars); + trueVars.clear(); + for(std::set::const_iterator iter=vars.begin();iter!=vars.end();iter++) + { + int tmp; + if(!LeafExprVar::isRecognizedKeyVar(*iter,tmp)) + trueVars.insert(*iter); + } +} + +void ExprParser::parseDeeper() throw(INTERP_KERNEL::Exception) +{ + for(std::list::iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++) + if(!(*iter).simplify()) + (*iter).parseDeeper(); +} + +/*! + * This method has the responsability to see if this->_expr can be seen as a unary function of something. + * Something defined as the contain of highest level barckets. + * Typically '(3*x+2)' and 'cos(4*l+p*n)' will be intercepted by this method whereas '3*x+2' not...etc.. + */ +void ExprParser::parseUnaryFunc() throw(INTERP_KERNEL::Exception) +{ + if(_expr[_expr.length()-1]!=')') + return ; + //at this level of code _expr + std::size_t pos1=_expr.find_first_of('('); + std::size_t pos4=findCorrespondingOpenBracket(_expr,_expr.length()-1); + if(pos4!=pos1) + return ; + std::string funcName=_expr.substr(0,pos1); + std::size_t pos2=funcName.find_first_of("+-*/^",0,5); + std::size_t pos3=funcName.find_first_not_of("+-*/^",0,5); + if(pos2!=std::string::npos && pos3!=std::string::npos) + return ;//Bracket group is not alone, can't conclude not recursively. + std::string newExp2=_expr.substr(pos1+1,_expr.length()-pos1-2); + int nbOfParamsInFunc=std::count(newExp2.begin(),newExp2.end(),',')+1; + if(pos3!=std::string::npos) + _func_btw_sub_expr.push_back(FunctionsFactory::buildFuncFromString(funcName.c_str(),nbOfParamsInFunc)); + else + { + int lgth=funcName.length(); + char tmp[2]; tmp[1]='\0'; + for(int i=0;i_expr is interpretable without any recursion. + * \return true if no recursion needed, false if this->_expr is too complex to be interpreted at this level. + * \throw exception if this->_expr is simple enough to try to interprate this and this expression contains an error. + */ +bool ExprParser::tryToInterpALeaf() throw(INTERP_KERNEL::Exception) +{ + std::size_t pos=_expr.find_first_not_of("+-",0,2); + std::string minimizedExpr=_expr.substr(pos); + std::size_t pos2=minimizedExpr.find_first_of("+-*/^()",0,7); + if(pos2!=std::string::npos) + return false; + delete _leaf; + _leaf=LeafExpr::buildInstanceFrom(minimizedExpr); + int nbOfNegs=0; + for(std::size_t i=0;i::iterator iter=_func_btw_sub_expr.begin();iter!=_func_btw_sub_expr.end();iter++) + delete *iter; + _func_btw_sub_expr.clear(); +} + +/*! + * This method parse this->_expr at the current level. + * This method first try to see if this->_expr is a leaf, if not it try a unary function of something (see INTERP_KERNEL::ExprParser::parseUnaryFunc method) + * If true is returned, no deeper parsing needed, if false is returned for a full parsing of this->_expr INTERP_KERNEL::ExprParser::parseDeeper call needed. + */ +bool ExprParser::simplify() throw(INTERP_KERNEL::Exception) +{ + if(tryToInterpALeaf()) + return true; + parseUnaryFunc(); + if(!_is_parsing_ok) + { + parseForAddMin(); + if(!_is_parsing_ok) + { + parseForMulDiv(); + if(!_is_parsing_ok) + parseForPow(); + } + } + if(!_is_parsing_ok) + { + std::ostringstream errMsg; + char MSGTYP3[]="Error in interpreting : "; + errMsg << EXPR_PARSE_ERR_MSG << MSGTYP3 << _expr; + locateError(errMsg,_expr,0); + throw INTERP_KERNEL::Exception(errMsg.str().c_str()); + } + return false; +} + +void ExprParser::checkBracketsParity() const throw(INTERP_KERNEL::Exception) +{ + std::string::const_iterator iter; + int curLevel=0; + for(iter=_expr.begin();iter!=_expr.end();iter++) + { + if(*iter=='(') + curLevel++; + else if(*iter==')') + { + if(curLevel==0) + { + std::ostringstream errMsg; + char MSGTYP1[]="Error in brackets : closing brackets ')' before openning '('"; + errMsg << EXPR_PARSE_ERR_MSG << MSGTYP1; + locateError(errMsg,_expr,iter-_expr.begin()); + throw INTERP_KERNEL::Exception(errMsg.str().c_str()); + } + curLevel--; + } + } + if(curLevel!=0) + { + std::ostringstream errMsg; + char MSGTYP2[]="Error in brackets : not finally closed expr."; + errMsg << EXPR_PARSE_ERR_MSG << MSGTYP2; + throw INTERP_KERNEL::Exception(errMsg.str().c_str()); + } +} + +void ExprParser::locateError(std::ostream& stringToDisp, const std::string& srcOfErr, int posOfErr) +{ + stringToDisp << "Position is " << posOfErr << " of string : \"" << srcOfErr << "\"" << std::endl; +} diff --git a/src/INTERP_KERNEL/ExprEval/InterpKernelExprParser.hxx b/src/INTERP_KERNEL/ExprEval/InterpKernelExprParser.hxx new file mode 100644 index 000000000..3b5c046e6 --- /dev/null +++ b/src/INTERP_KERNEL/ExprEval/InterpKernelExprParser.hxx @@ -0,0 +1,98 @@ +#ifndef __INTERPKERNELEXPRPARSER_HXX__ +#define __INTERPKERNELEXPRPARSER_HXX__ + +#include "INTERPKERNELEXPREVALDefines.hxx" +#include "InterpKernelUnit.hxx" +#include "InterpKernelException.hxx" +#include "InterpKernelFunction.hxx" + +#include +#include +#include +#include + +namespace INTERP_KERNEL +{ + class ValueDouble; + + class INTERPKERNELEXPREVAL_EXPORT LeafExpr + { + public: + virtual ~LeafExpr(); + virtual void fillValue(Value *val) const throw(INTERP_KERNEL::Exception) = 0; + static LeafExpr *buildInstanceFrom(const std::string& expr) throw(INTERP_KERNEL::Exception); + }; + + class INTERPKERNELEXPREVAL_EXPORT LeafExprVal : public LeafExpr + { + public: + LeafExprVal(double value); + ~LeafExprVal(); + void fillValue(Value *val) const throw(INTERP_KERNEL::Exception); + private: + double _value; + }; + + class INTERPKERNELEXPREVAL_EXPORT LeafExprVar : public LeafExpr + { + public: + LeafExprVar(const std::string& var); + ~LeafExprVar(); + void fillValue(Value *val) const throw(INTERP_KERNEL::Exception); + std::string getVar() const { return _var_name; } + void prepareExprEvaluation(const std::vector& vars) const throw(INTERP_KERNEL::Exception); + void prepareExprEvaluationVec() const throw(INTERP_KERNEL::Exception); + static bool isRecognizedKeyVar(const std::string& var, int& pos); + public: + static const char END_OF_RECOGNIZED_VAR[]; + private: + mutable int _fast_pos; + std::string _var_name; + }; + + class INTERPKERNELEXPREVAL_EXPORT ExprParser + { + public: + ExprParser(const char *expr); + ExprParser(const char *expr, int lgth); + ~ExprParser(); + void parse() throw(INTERP_KERNEL::Exception); + bool isParsingSuccessfull() const { return _is_parsing_ok; } + double evaluate() const throw(INTERP_KERNEL::Exception); + DecompositionInUnitBase evaluateUnit() const throw(INTERP_KERNEL::Exception); + void prepareExprEvaluation(const std::vector& vars) const throw(INTERP_KERNEL::Exception); + void evaluateExpr(int szOfOutParam, double *outParam, const double *inParam) const throw(INTERP_KERNEL::Exception); + void prepareExprEvaluationVec() const throw(INTERP_KERNEL::Exception); + void getSetOfVars(std::set& vars) const; + void getTrueSetOfVars(std::set& vars) const; + static std::string buildStringFromFortran(const char *expr, int lgth); + static std::string deleteWhiteSpaces(const std::string& expr); + private: + Value *evaluateLowLev(Value *valGen) const throw(INTERP_KERNEL::Exception); + private: + void prepareExprEvaluationVecLowLev() const throw(INTERP_KERNEL::Exception); + bool tryToInterpALeaf() throw(INTERP_KERNEL::Exception); + void parseUnaryFunc() throw(INTERP_KERNEL::Exception); + void parseForAddMin() throw(INTERP_KERNEL::Exception); + void parseForMulDiv() throw(INTERP_KERNEL::Exception); + void parseForPow() throw(INTERP_KERNEL::Exception); + void parseDeeper() throw(INTERP_KERNEL::Exception); + bool simplify() throw(INTERP_KERNEL::Exception); + void releaseFunctions(); + void checkBracketsParity() const throw(INTERP_KERNEL::Exception); + static std::size_t findCorrespondingOpenBracket(const std::string& expr, std::size_t posOfCloseBracket); + static void locateError(std::ostream& stringToDisp, const std::string& srcOfErr, int posOfErr); + private: + bool _is_parsed; + LeafExpr *_leaf; + bool _is_parsing_ok; + std::string _expr; + std::list _sub_expr; + std::list _func_btw_sub_expr; + private: + static const char WHITE_SPACES[]; + static const char EXPR_PARSE_ERR_MSG[]; + }; +} + +#endif diff --git a/src/INTERP_KERNEL/ExprEval/InterpKernelFunction.cxx b/src/INTERP_KERNEL/ExprEval/InterpKernelFunction.cxx new file mode 100644 index 000000000..3f22d6bcc --- /dev/null +++ b/src/INTERP_KERNEL/ExprEval/InterpKernelFunction.cxx @@ -0,0 +1,549 @@ +#include "InterpKernelFunction.hxx" +#include "InterpKernelValue.hxx" + +#include + +using namespace INTERP_KERNEL; + +const char IdentityFunction::REPR[]="Id"; + +const char PositiveFunction::REPR[]="+"; + +const char NegateFunction::REPR[]="-"; + +const char CosFunction::REPR[]="cos"; + +const char SinFunction::REPR[]="sin"; + +const char TanFunction::REPR[]="tan"; + +const char SqrtFunction::REPR[]="sqrt"; + +const char AbsFunction::REPR[]="abs"; + +const char PlusFunction::REPR[]="+"; + +const char MinusFunction::REPR[]="-"; + +const char MultFunction::REPR[]="*"; + +const char DivFunction::REPR[]="/"; + +const char PowFunction::REPR[]="^"; + +const char ExpFunction::REPR[]="exp"; + +const char LnFunction::REPR[]="ln"; + +const char MaxFunction::REPR[]="max"; + +const char MinFunction::REPR[]="min"; + +Function *FunctionsFactory::buildFuncFromString(const char *type, int nbOfParams) throw(INTERP_KERNEL::Exception) +{ + switch(nbOfParams) + { + case 1: + return buildUnaryFuncFromString(type); + case 2: + return buildBinaryFuncFromString(type); + default: + throw INTERP_KERNEL::Exception("Invalid number of params detected : limited to 2 !"); + } +} + +Function *FunctionsFactory::buildUnaryFuncFromString(const char *type) throw(INTERP_KERNEL::Exception) +{ + std::string tmp(type); + if(tmp.empty()) + return new IdentityFunction; + if(tmp==CosFunction::REPR) + return new CosFunction; + if(tmp==SinFunction::REPR) + return new SinFunction; + if(tmp==TanFunction::REPR) + return new TanFunction; + if(tmp==SqrtFunction::REPR) + return new SqrtFunction; + if(tmp==AbsFunction::REPR) + return new AbsFunction; + if(tmp==PositiveFunction::REPR) + return new PositiveFunction; + if(tmp==NegateFunction::REPR) + return new NegateFunction; + if(tmp==ExpFunction::REPR) + return new ExpFunction; + if(tmp==LnFunction::REPR) + return new LnFunction; + // + std::string msg("Invalid unary function detected : \""); + msg+=type; msg+="\""; + throw INTERP_KERNEL::Exception(msg.c_str()); +} + +Function *FunctionsFactory::buildBinaryFuncFromString(const char *type) throw(INTERP_KERNEL::Exception) +{ + std::string tmp(type); + if(tmp==PositiveFunction::REPR) + return new PlusFunction; + if(tmp==NegateFunction::REPR) + return new MinusFunction; + if(tmp==MultFunction::REPR) + return new MultFunction; + if(tmp==DivFunction::REPR) + return new DivFunction; + if(tmp==PowFunction::REPR) + return new PowFunction; + if(tmp==MaxFunction::REPR) + return new MaxFunction; + if(tmp==MinFunction::REPR) + return new MinFunction; + std::string msg("Invalid binary function detected : \""); + msg+=type; msg+="\""; + throw INTERP_KERNEL::Exception(msg.c_str()); +} + +Function *FunctionsFactory::buildBinaryFuncFromString(char type) throw(INTERP_KERNEL::Exception) +{ + char tmp[2]; tmp[0]=type; tmp[1]='\0'; + return buildBinaryFuncFromString(tmp); +} + +Function::~Function() +{ +} + +IdentityFunction::~IdentityFunction() +{ +} + +void IdentityFunction::operate(std::vector& stack) const throw(INTERP_KERNEL::Exception) +{ +} + +const char *IdentityFunction::getRepr() const +{ + return REPR; +} + +bool IdentityFunction::isACall() const +{ + return false; +} + +PositiveFunction::~PositiveFunction() +{ +} + +int UnaryFunction::getNbInputParams() const +{ + return 1; +} + +void PositiveFunction::operate(std::vector& stack) const throw(INTERP_KERNEL::Exception) +{ +} + +const char *PositiveFunction::getRepr() const +{ + return REPR; +} + +bool PositiveFunction::isACall() const +{ + return false; +} + +NegateFunction::~NegateFunction() +{ +} + +void NegateFunction::operate(std::vector& stack) const throw(INTERP_KERNEL::Exception) +{ + Value *val=stack.back(); + val->negate(); +} + +const char *NegateFunction::getRepr() const +{ + return REPR; +} + +bool NegateFunction::isACall() const +{ + return false; +} + +CosFunction::~CosFunction() +{ +} + +void CosFunction::operate(std::vector& stack) const throw(INTERP_KERNEL::Exception) +{ + Value *val=stack.back(); + val->cos(); +} + +const char *CosFunction::getRepr() const +{ + return REPR; +} + +bool CosFunction::isACall() const +{ + return true; +} + +SinFunction::~SinFunction() +{ +} + +void SinFunction::operate(std::vector& stack) const throw(INTERP_KERNEL::Exception) +{ + Value *val=stack.back(); + val->sin(); +} + +const char *SinFunction::getRepr() const +{ + return REPR; +} + +bool SinFunction::isACall() const +{ + return true; +} + +TanFunction::~TanFunction() +{ +} + +void TanFunction::operate(std::vector& stack) const throw(INTERP_KERNEL::Exception) +{ + Value *val=stack.back(); + val->tan(); +} + +const char *TanFunction::getRepr() const +{ + return REPR; +} + +bool TanFunction::isACall() const +{ + return true; +} + +SqrtFunction::~SqrtFunction() +{ +} + +void SqrtFunction::operate(std::vector& stack) const throw(INTERP_KERNEL::Exception) +{ + Value *val=stack.back(); + val->sqrt(); +} + +const char *SqrtFunction::getRepr() const +{ + return REPR; +} + +bool SqrtFunction::isACall() const +{ + return true; +} + +AbsFunction::~AbsFunction() +{ +} + +void AbsFunction::operate(std::vector& stack) const throw(INTERP_KERNEL::Exception) +{ + Value *val=stack.back(); + val->abs(); +} + +const char *AbsFunction::getRepr() const +{ + return REPR; +} + +bool AbsFunction::isACall() const +{ + return false; +} + +void ExpFunction::operate(std::vector& stack) const throw(INTERP_KERNEL::Exception) +{ + Value *val=stack.back(); + val->exp(); +} + +const char *ExpFunction::getRepr() const +{ + return REPR; +} + +bool ExpFunction::isACall() const +{ + return true; +} + +LnFunction::~LnFunction() +{ +} + +void LnFunction::operate(std::vector& stack) const throw(INTERP_KERNEL::Exception) +{ + Value *val=stack.back(); + val->ln(); +} + +const char *LnFunction::getRepr() const +{ + return REPR; +} + +bool LnFunction::isACall() const +{ + return true; +} + +int BinaryFunction::getNbInputParams() const +{ + return 2; +} + +PlusFunction::~PlusFunction() +{ +} + +void PlusFunction::operate(std::vector& stack) const throw(INTERP_KERNEL::Exception) +{ + Value *val1=stack.back(); + stack.pop_back(); + Value *& val2=stack.back(); + Value *val3; + try + { + val3=val1->plus(val2); + } + catch(INTERP_KERNEL::Exception& e) + { + delete val1; + throw e; + } + delete val1; + delete val2; + val2=val3; +} + +const char *PlusFunction::getRepr() const +{ + return REPR; +} + +bool PlusFunction::isACall() const +{ + return false; +} + +MinusFunction::~MinusFunction() +{ +} + +void MinusFunction::operate(std::vector& stack) const throw(INTERP_KERNEL::Exception) +{ + Value *val1=stack.back(); + stack.pop_back(); + Value *& val2=stack.back(); + Value *val3; + try + { + val3=val1->minus(val2); + } + catch(INTERP_KERNEL::Exception& e) + { + delete val1; + throw e; + } + delete val1; + delete val2; + val2=val3; +} + +const char *MinusFunction::getRepr() const +{ + return REPR; +} + +bool MinusFunction::isACall() const +{ + return false; +} + +MultFunction::~MultFunction() +{ +} + +void MultFunction::operate(std::vector& stack) const throw(INTERP_KERNEL::Exception) +{ + Value *val1=stack.back(); + stack.pop_back(); + Value *& val2=stack.back(); + Value *val3=val1->mult(val2); + delete val1; + delete val2; + val2=val3; +} + +const char *MultFunction::getRepr() const +{ + return REPR; +} + +bool MultFunction::isACall() const +{ + return false; +} + +DivFunction::~DivFunction() +{ +} + +void DivFunction::operate(std::vector& stack) const throw(INTERP_KERNEL::Exception) +{ + Value *val1=stack.back(); + stack.pop_back(); + Value *& val2=stack.back(); + Value *val3; + try + { + val3=val1->div(val2); + } + catch(INTERP_KERNEL::Exception& e) + { + delete val1; + throw e; + } + delete val1; + delete val2; + val2=val3; +} + +const char *DivFunction::getRepr() const +{ + return REPR; +} + +bool DivFunction::isACall() const +{ + return false; +} + +PowFunction::~PowFunction() +{ +} + +void PowFunction::operate(std::vector& stack) const throw(INTERP_KERNEL::Exception) +{ + Value *val1=stack.back(); + stack.pop_back(); + Value *& val2=stack.back(); + Value *val3; + try + { + val3=val1->pow(val2); + } + catch(INTERP_KERNEL::Exception& e) + { + delete val1; + throw e; + } + delete val1; + delete val2; + val2=val3; +} + +const char *PowFunction::getRepr() const +{ + return REPR; +} + +bool PowFunction::isACall() const +{ + return true; +} + +ExpFunction::~ExpFunction() +{ +} + +MaxFunction::~MaxFunction() +{ +} + +void MaxFunction::operate(std::vector& stack) const throw(INTERP_KERNEL::Exception) +{ + Value *val1=stack.back(); + stack.pop_back(); + Value *& val2=stack.back(); + Value *val3; + try + { + val3=val1->max(val2); + } + catch(INTERP_KERNEL::Exception& e) + { + delete val1; + throw e; + } + delete val1; + delete val2; + val2=val3; +} + +const char *MaxFunction::getRepr() const +{ + return REPR; +} + +bool MaxFunction::isACall() const +{ + return false; +} + +MinFunction::~MinFunction() +{ +} + +void MinFunction::operate(std::vector& stack) const throw(INTERP_KERNEL::Exception) +{ + Value *val1=stack.back(); + stack.pop_back(); + Value *& val2=stack.back(); + Value *val3; + try + { + val3=val1->min(val2); + } + catch(INTERP_KERNEL::Exception& e) + { + delete val1; + throw e; + } + delete val1; + delete val2; + val2=val3; +} + +const char *MinFunction::getRepr() const +{ + return REPR; +} + +bool MinFunction::isACall() const +{ + return false; +} diff --git a/src/INTERP_KERNEL/ExprEval/InterpKernelFunction.hxx b/src/INTERP_KERNEL/ExprEval/InterpKernelFunction.hxx new file mode 100644 index 000000000..cd158e5f1 --- /dev/null +++ b/src/INTERP_KERNEL/ExprEval/InterpKernelFunction.hxx @@ -0,0 +1,234 @@ +#ifndef __INTERPKERNELFUNCTION_HXX__ +#define __INTERPKERNELFUNCTION_HXX__ + +#include "INTERPKERNELEXPREVALDefines.hxx" +#include "InterpKernelException.hxx" + +#include + +namespace INTERP_KERNEL +{ + class Value; + class Function; + + class INTERPKERNELEXPREVAL_EXPORT FunctionsFactory + { + public: + static Function *buildFuncFromString(const char *type, int nbOfParams) throw(INTERP_KERNEL::Exception); + static Function *buildUnaryFuncFromString(const char *type) throw(INTERP_KERNEL::Exception); + //static Function *buildUnaryFuncFromString(char type) throw(INTERP_KERNEL::Exception); + static Function *buildBinaryFuncFromString(const char *type) throw(INTERP_KERNEL::Exception); + static Function *buildBinaryFuncFromString(char type) throw(INTERP_KERNEL::Exception); + }; + + class INTERPKERNELEXPREVAL_EXPORT Function + { + public: + virtual ~Function(); + virtual int getNbInputParams() const = 0; + virtual void operate(std::vector& stack) const throw(INTERP_KERNEL::Exception) = 0; + virtual const char *getRepr() const = 0; + virtual bool isACall() const = 0; + }; + + class INTERPKERNELEXPREVAL_EXPORT UnaryFunction : public Function + { + public: + int getNbInputParams() const; + }; + + class INTERPKERNELEXPREVAL_EXPORT IdentityFunction : public UnaryFunction + { + public: + ~IdentityFunction(); + void operate(std::vector& stack) const throw(INTERP_KERNEL::Exception); + const char *getRepr() const; + bool isACall() const; + public: + static const char REPR[]; + }; + + class INTERPKERNELEXPREVAL_EXPORT PositiveFunction : public UnaryFunction + { + public: + ~PositiveFunction(); + void operate(std::vector& stack) const throw(INTERP_KERNEL::Exception); + const char *getRepr() const; + bool isACall() const; + public: + static const char REPR[]; + }; + + class INTERPKERNELEXPREVAL_EXPORT NegateFunction : public UnaryFunction + { + public: + ~NegateFunction(); + void operate(std::vector& stack) const throw(INTERP_KERNEL::Exception); + const char *getRepr() const; + bool isACall() const; + public: + static const char REPR[]; + }; + + class INTERPKERNELEXPREVAL_EXPORT CosFunction : public UnaryFunction + { + public: + ~CosFunction(); + void operate(std::vector& stack) const throw(INTERP_KERNEL::Exception); + const char *getRepr() const; + bool isACall() const; + public: + static const char REPR[]; + }; + + class INTERPKERNELEXPREVAL_EXPORT SinFunction : public UnaryFunction + { + public: + ~SinFunction(); + void operate(std::vector& stack) const throw(INTERP_KERNEL::Exception); + const char *getRepr() const; + bool isACall() const; + public: + static const char REPR[]; + }; + + class INTERPKERNELEXPREVAL_EXPORT TanFunction : public UnaryFunction + { + public: + ~TanFunction(); + void operate(std::vector& stack) const throw(INTERP_KERNEL::Exception); + const char *getRepr() const; + bool isACall() const; + public: + static const char REPR[]; + }; + + class INTERPKERNELEXPREVAL_EXPORT SqrtFunction : public UnaryFunction + { + public: + ~SqrtFunction(); + void operate(std::vector& stack) const throw(INTERP_KERNEL::Exception); + const char *getRepr() const; + bool isACall() const; + public: + static const char REPR[]; + }; + + class INTERPKERNELEXPREVAL_EXPORT AbsFunction : public UnaryFunction + { + public: + ~AbsFunction(); + void operate(std::vector& stack) const throw(INTERP_KERNEL::Exception); + const char *getRepr() const; + bool isACall() const; + public: + static const char REPR[]; + }; + + class INTERPKERNELEXPREVAL_EXPORT ExpFunction : public UnaryFunction + { + public: + ~ExpFunction(); + void operate(std::vector& stack) const throw(INTERP_KERNEL::Exception); + const char *getRepr() const; + bool isACall() const; + public: + static const char REPR[]; + }; + + class INTERPKERNELEXPREVAL_EXPORT LnFunction : public UnaryFunction + { + public: + ~LnFunction(); + void operate(std::vector& stack) const throw(INTERP_KERNEL::Exception); + const char *getRepr() const; + bool isACall() const; + public: + static const char REPR[]; + }; + + class INTERPKERNELEXPREVAL_EXPORT BinaryFunction : public Function + { + public: + int getNbInputParams() const; + }; + + class PlusFunction : public BinaryFunction + { + public: + ~PlusFunction(); + void operate(std::vector& stack) const throw(INTERP_KERNEL::Exception); + const char *getRepr() const; + bool isACall() const; + public: + static const char REPR[]; + }; + + class INTERPKERNELEXPREVAL_EXPORT MinusFunction : public BinaryFunction + { + public: + ~MinusFunction(); + void operate(std::vector& stack) const throw(INTERP_KERNEL::Exception); + const char *getRepr() const; + bool isACall() const; + public: + static const char REPR[]; + }; + + class INTERPKERNELEXPREVAL_EXPORT MultFunction : public BinaryFunction + { + public: + ~MultFunction(); + void operate(std::vector& stack) const throw(INTERP_KERNEL::Exception); + const char *getRepr() const; + bool isACall() const; + public: + static const char REPR[]; + }; + + class INTERPKERNELEXPREVAL_EXPORT DivFunction : public BinaryFunction + { + public: + ~DivFunction(); + void operate(std::vector& stack) const throw(INTERP_KERNEL::Exception); + const char *getRepr() const; + bool isACall() const; + public: + static const char REPR[]; + }; + + class INTERPKERNELEXPREVAL_EXPORT PowFunction : public BinaryFunction + { + public: + ~PowFunction(); + void operate(std::vector& stack) const throw(INTERP_KERNEL::Exception); + const char *getRepr() const; + bool isACall() const; + public: + static const char REPR[]; + }; + + class INTERPKERNELEXPREVAL_EXPORT MaxFunction : public BinaryFunction + { + public: + ~MaxFunction(); + void operate(std::vector& stack) const throw(INTERP_KERNEL::Exception); + const char *getRepr() const; + bool isACall() const; + public: + static const char REPR[]; + }; + + class INTERPKERNELEXPREVAL_EXPORT MinFunction : public BinaryFunction + { + public: + ~MinFunction(); + void operate(std::vector& stack) const throw(INTERP_KERNEL::Exception); + const char *getRepr() const; + bool isACall() const; + public: + static const char REPR[]; + }; +} + +#endif diff --git a/src/INTERP_KERNEL/ExprEval/InterpKernelUnit.cxx b/src/INTERP_KERNEL/ExprEval/InterpKernelUnit.cxx new file mode 100644 index 000000000..86d5dec51 --- /dev/null +++ b/src/INTERP_KERNEL/ExprEval/InterpKernelUnit.cxx @@ -0,0 +1,353 @@ +#include "InterpKernelUnit.hxx" +#include "InterpKernelExprParser.hxx" + +#include +#include +#include +#include + +using namespace INTERP_KERNEL; + +UnitDataBase UnitDataBase::_uniqueMapForExpr; + +static const char InterpKernelMuAscii[2]={-0x4B,0x0}; + +static const char InterpKernelMuUnicode[3]={-0x3E,-0x4B,0x0}; + +const char *UnitDataBase::PREF_POW10[NB_OF_PREF_POW10]={"y","z","a","f","p","n",InterpKernelMuAscii,InterpKernelMuUnicode,"u","m","c","d", + "da","h","k","M","G","T","P","E","Z","Y"}; + +const double UnitDataBase::POW10[NB_OF_PREF_POW10]={1e-24,1e-21,1e-18,1e-15,1e-12,1e-9,1e-6,1e-6,1e-6,1e-3,1e-2,1e-1, + 1e1,1e2,1e3,1e6,1e9,1e12,1e15,1e18,1e21,1e24}; + +static const char InterpKernelDegreeCAscii[3]={-0x50,0x43,0x0}; + +static const char InterpKernelDegreeCUnicode[4]={-0x3E,-0x50,0x43,0x0}; + +static const char InterpKernelDegreeCUnicodeWin[3]={-0x08,0x43,0x0}; + +const char *UnitDataBase::UNITS_RECOGN[NB_OF_UNITS_RECOGN]={"g","m","s","A","K", + "W","J","Hz","V","h","min","t","N","dyn", + "eV","Pa","atm","bar",InterpKernelDegreeCAscii,"C","ohm","F","S", + "T","H","P","St",InterpKernelDegreeCUnicode,InterpKernelDegreeCUnicodeWin}; + +const short UnitDataBase::PROJ_IN_BASE[NB_OF_UNITS_RECOGN][SIZE_OF_UNIT_BASE]= + { + {1,0,0,0,0},//g + {0,1,0,0,0},//m + {0,0,1,0,0},//s + {0,0,0,1,0},//A + {0,0,0,0,1},//K + {1,2,-3,0,0},//W + {1,2,-2,0,0},//J + {0,0,-1,0,0},//Hz + {1,2,-3,-1,0},//V + {0,0,1,0,0},//h + {0,0,1,0,0},//min + {1,0,0,0,0},//t + {1,1,-2,0,0},//N + {1,1,-2,0,0},//dyn + {1,2,-2,0,0},//eV + {1,-1,-2,0,0},//Pa + {1,-1,-2,0,0},//atm + {1,-1,-2,0,0},//bar + {0,0,0,0,1},//degree C + {0,0,1,1,0},//C + {1,2,-3,-2,0},//ohm + {-1,-2,4,2,0},//F + {-1,-2,3,2,0},//S + {1,0,-2,-1,0},//T + {1,2,-2,-2,0},//H + {1,-1,-1,0,0},//P + {0,2,-1,0,0},//St + {0,0,0,0,1},//degree C + {0,0,0,0,1}//degree C + }; + +const double UnitDataBase::MUL_COEFF[NB_OF_UNITS_RECOGN]= + { 1.,1.,1.,1.,1., + 1000.,1000.,1.,1000.,3600.,3600.,1e6,1000.,1e-2, + 1.60217733e-16,1000.,1.01325e8,1e8,1.,1.,1000.,1e-3, + 1000.,1000.,100.,1.,1.,1.,1.}; + +const double UnitDataBase::ADD_COEFF[NB_OF_UNITS_RECOGN]= + { 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 273.15, 0., 0., 0., 0., 0., 0., 0., 0., 273.15 ,273.15}; + +UnitDataBase::UnitDataBase() +{ + for(int i=0;i::const_iterator iter=_units_semantic.find(work); + if(iter!=_units_semantic.end()) + { + ret=(*iter).second; + std::map::const_iterator iter2=_units_add.find(work); + addFact=(*iter2).second; + std::map::const_iterator iter3=_units_mul.find(work); + mFact=(*iter3).second; + work2=unit.substr(0,i); + } + } + if(!ret) + { + std::ostringstream os; + os << "Unit : " << unit << " not recognized !"; + throw INTERP_KERNEL::Exception(os.str().c_str()); + } + if(!work2.empty()) + { + std::map::const_iterator iter4=_prefix_pow_10.find(work2); + if(iter4==_prefix_pow_10.end()) + { + std::ostringstream os; + os << "Unit : " << unit << " not fully recognized : \"" << work << "\" detected as core unit and \""; + os << work2 << "\" not recognized prefix !"; + throw INTERP_KERNEL::Exception(os.str().c_str()); + } + addFact=0.; + mFact*=(*iter4).second; + } + return ret; +} + +DecompositionInUnitBase::DecompositionInUnitBase():_add_to_base(0.),_mult_fact_to_base(1.) +{ + _value[0]=0; + _value[1]=0; + _value[2]=0; + _value[3]=0; + _value[4]=0; +} + +void DecompositionInUnitBase::setInfo(const short *vals, double addFact, double mFact) +{ + _add_to_base=addFact; + _mult_fact_to_base=mFact; + _value[0]=vals[0]; + _value[1]=vals[1]; + _value[2]=vals[2]; + _value[3]=vals[3]; + _value[4]=vals[4]; +} + +bool DecompositionInUnitBase::operator==(const DecompositionInUnitBase& other) const +{ + return _value[0]==other._value[0] && _value[1]==other._value[1] && _value[2]==other._value[2] && _value[3]==other._value[3] && _value[4]==other._value[4]; +} + +void DecompositionInUnitBase::getTranslationParams(const DecompositionInUnitBase& other, double& mul, double& add) const +{ + if((*this)==other) + { + mul=_mult_fact_to_base/other._mult_fact_to_base; + add=_add_to_base/other._mult_fact_to_base-other._add_to_base; + } + else + { + mul=std::numeric_limits::max(); + add=std::numeric_limits::max(); + } +} + +bool DecompositionInUnitBase::isEqual(short mass, short lgth, short time, short intensity, short temp, double add, double mult) +{ + bool ret1=mass==_value[0]; + bool ret2=lgth==_value[1]; + bool ret3=time==_value[2]; + bool ret4=intensity==_value[3]; + bool ret5=temp==_value[4]; + bool ret6=areDoubleEquals(add,_add_to_base); + bool ret7=areDoubleEquals(mult,_mult_fact_to_base); + return ret1 && ret2 && ret3 && ret4 && ret5 && ret6 && ret7; +} + +void DecompositionInUnitBase::negate() +{ + _mult_fact_to_base=-_mult_fact_to_base; +} + +bool DecompositionInUnitBase::isAdimensional() const +{ + return _value[0]==0 && _value[1]==0 && _value[2]==0 && _value[3]==0 && _value[4]==0; +} + +bool DecompositionInUnitBase::isUnitary() const +{ + return areDoubleEquals(_add_to_base,0.) && areDoubleEquals(_mult_fact_to_base,1.); +} + +void DecompositionInUnitBase::tryToConvertInUnit(double val) throw(INTERP_KERNEL::Exception) +{ + int valI=(int)val; + if((val-(double)valI)!=0.) + { + std::ostringstream os; + os << "Double value " << val << " can't be considered as integer. Not admitable for units !"; + throw INTERP_KERNEL::Exception(os.str().c_str()); + } + _value[0]=0; + _value[1]=0; + _value[2]=0; + _value[3]=0; + _value[4]=0; + _add_to_base=0; + _mult_fact_to_base=valI; +} + +DecompositionInUnitBase &DecompositionInUnitBase::operator*(const DecompositionInUnitBase& other) +{ + _value[0]+=other._value[0]; _value[1]+=other._value[1]; _value[2]+=other._value[2]; _value[3]+=other._value[3]; _value[4]+=other._value[4]; + _mult_fact_to_base*=other._mult_fact_to_base; + _add_to_base=0.; + return *this; +} + +DecompositionInUnitBase &DecompositionInUnitBase::operator/(const DecompositionInUnitBase& other) +{ + _value[0]-=other._value[0]; _value[1]-=other._value[1]; _value[2]-=other._value[2]; _value[3]-=other._value[3]; _value[4]-=other._value[4]; + _mult_fact_to_base/=other._mult_fact_to_base; + _add_to_base=0.; + return *this; +} + +DecompositionInUnitBase &DecompositionInUnitBase::operator^(const DecompositionInUnitBase& other) throw(INTERP_KERNEL::Exception) +{ + if(!other.isAdimensional()) + throw INTERP_KERNEL::Exception("Trying to execute operator ^ with a second member not adimensionnal"); + int exp=couldItBeConsideredAsInt(other._mult_fact_to_base); + _value[0]*=exp; _value[1]*=exp; _value[2]*=exp; _value[3]*=exp; _value[4]*=exp; + _mult_fact_to_base=powInt(_mult_fact_to_base,exp); + _add_to_base=0.; + return *this; +} + +void DecompositionInUnitBase::dealWithAddFactor(const DecompositionInUnitBase& other) +{ + if(!areDoubleEquals(_add_to_base,0.)) + if(other.isAdimensional()) + if(areDoubleEquals(other._mult_fact_to_base,1.)) + return ; + if(!other.areDoubleEquals(_add_to_base,0.)) + if(isAdimensional()) + if(areDoubleEquals(_mult_fact_to_base,1.)) + return ; + _add_to_base=0.; +} + +double DecompositionInUnitBase::powInt(double val, int exp) +{ + double work=1.; + if(exp==0) + return 1.; + if(exp>0) + for(int i=0;i::max(); +} + +std::string Unit::getCoarseRepr() const +{ + return _coarse_repr; +} diff --git a/src/INTERP_KERNEL/ExprEval/InterpKernelUnit.hxx b/src/INTERP_KERNEL/ExprEval/InterpKernelUnit.hxx new file mode 100644 index 000000000..62c62d79c --- /dev/null +++ b/src/INTERP_KERNEL/ExprEval/InterpKernelUnit.hxx @@ -0,0 +1,98 @@ +#ifndef __INTERPKERNELUNIT_HXX__ +#define __INTERPKERNELUNIT_HXX__ + +#include "INTERPKERNELEXPREVALDefines.hxx" +#include "InterpKernelException.hxx" + +#include +#include + +namespace INTERP_KERNEL +{ + class INTERPKERNELEXPREVAL_EXPORT UnitDataBase + { + public: + UnitDataBase(); + const short *getInfoForUnit(const std::string& unit, + double& addFact, double& mFact) const throw(INTERP_KERNEL::Exception); + static UnitDataBase _uniqueMapForExpr; + static const int SIZE_OF_UNIT_BASE=5; + private: + std::map _prefix_pow_10; + std::map _units_semantic; + std::map _units_mul; + std::map _units_add; + private: + static const int NB_OF_PREF_POW10=22; + static const char *PREF_POW10[NB_OF_PREF_POW10]; + static const double POW10[NB_OF_PREF_POW10]; + static const int NB_OF_UNITS_RECOGN=29; + static const char *UNITS_RECOGN[NB_OF_UNITS_RECOGN]; + static const short PROJ_IN_BASE[NB_OF_UNITS_RECOGN][SIZE_OF_UNIT_BASE]; + static const double MUL_COEFF[NB_OF_UNITS_RECOGN]; + static const double ADD_COEFF[NB_OF_UNITS_RECOGN]; + }; + + class INTERPKERNELEXPREVAL_EXPORT DecompositionInUnitBase + { + public: + DecompositionInUnitBase(); + void setInfo(const short *vals, double addFact, double mFact); + short operator[](int i) const { return _value[i]; } + bool operator==(const DecompositionInUnitBase& other) const; + void getTranslationParams(const DecompositionInUnitBase& other, double& mul, double& add) const; + bool isEqual(short mass, short lgth, short time, short intensity, short temp, + double add, double mult); + bool isUnitary() const; + //! \b WARNING no test is done on the fact that unit is adimensionnal. + void negate(); + bool isAdimensional() const; + void tryToConvertInUnit(double val) throw(INTERP_KERNEL::Exception); + DecompositionInUnitBase &operator*(const DecompositionInUnitBase& other); + DecompositionInUnitBase &operator/(const DecompositionInUnitBase& other); + DecompositionInUnitBase &operator^(const DecompositionInUnitBase& other) throw(INTERP_KERNEL::Exception); + private: + void dealWithAddFactor(const DecompositionInUnitBase& other); + static int couldItBeConsideredAsInt(double val) throw(INTERP_KERNEL::Exception); + static bool areDoubleEquals(double a, double b); + static double powInt(double val, int exp); + private: + short _value[UnitDataBase::SIZE_OF_UNIT_BASE]; + double _add_to_base; + double _mult_fact_to_base; + }; + + /*! + * This class deals with units. + * This class has two main responsabilities : + * - interprete units by giving simply their representation in string type. + * - performing operations on these units. + * + * All the possible units are represented with a unique tuple with 5 elements + * representing the unique decomposition of a unit in the following base. + * + * dimension 0 stands for mass in g (\b NOT kg to simplify parsing). + * dimension 1 stands for length in m. + * dimension 2 stands for time in s. + * dimension 3 stands for elec intensity A. + * dimension 4 stands for temperature in K. + */ + class INTERPKERNELEXPREVAL_EXPORT Unit + { + public: + Unit(const char *reprC, bool tryToInterp=true); + Unit(const char *reprFortran, int sizeOfRepr, bool tryToInterp=true); + void tryToInterprate() const; + bool isInterpretationOK() const; + bool isCompatibleWith(const Unit& other) const; + double convert(const Unit& target, double sourceVal) const; + std::string getCoarseRepr() const; + private: + std::string _coarse_repr; + mutable bool _is_interpreted; + mutable bool _is_interpretation_ok; + mutable DecompositionInUnitBase _decomp_in_base; + }; +} + +#endif diff --git a/src/INTERP_KERNEL/ExprEval/InterpKernelValue.cxx b/src/INTERP_KERNEL/ExprEval/InterpKernelValue.cxx new file mode 100644 index 000000000..b6440572c --- /dev/null +++ b/src/INTERP_KERNEL/ExprEval/InterpKernelValue.cxx @@ -0,0 +1,409 @@ +#include "InterpKernelValue.hxx" +#include "InterpKernelFunction.hxx" + +#include +#include +#include + +using namespace INTERP_KERNEL; + +ValueDouble::ValueDouble():_data(std::numeric_limits::max()) +{ +} + +Value *ValueDouble::newInstance() const +{ + return new ValueDouble; +} + +ValueDouble::ValueDouble(double val):_data(val) +{ +} + +void ValueDouble::setDouble(double val) throw(INTERP_KERNEL::Exception) +{ + _data=val; +} + +void ValueDouble::setVarname(int fastPos, const std::string& var) throw(INTERP_KERNEL::Exception) +{ + std::string msg("Error var : "); msg+=var; msg+=" not numeric : use another expression evaluator !"; + throw INTERP_KERNEL::Exception(msg.c_str()); +} + +void ValueDouble::positive() throw(INTERP_KERNEL::Exception) +{ +} + +void ValueDouble::negate() throw(INTERP_KERNEL::Exception) +{ + _data=-_data; +} + +void ValueDouble::sqrt() throw(INTERP_KERNEL::Exception) +{ + _data=std::sqrt(_data); +} + +void ValueDouble::cos() throw(INTERP_KERNEL::Exception) +{ + _data=std::cos(_data); +} + +void ValueDouble::sin() throw(INTERP_KERNEL::Exception) +{ + _data=std::sin(_data); +} + +void ValueDouble::tan() throw(INTERP_KERNEL::Exception) +{ + _data=std::tan(_data); +} + +void ValueDouble::abs() throw(INTERP_KERNEL::Exception) +{ + if(_data<0.) + _data=-_data; +} + +void ValueDouble::exp() throw(INTERP_KERNEL::Exception) +{ + _data=std::exp(_data); +} + +void ValueDouble:: ln() throw(INTERP_KERNEL::Exception) +{ + _data=std::log(_data); +} + +Value *ValueDouble::plus(const Value *other) const throw(INTERP_KERNEL::Exception) +{ + const ValueDouble *valC=checkSameType(other); + return new ValueDouble(_data+valC->_data); +} + +Value *ValueDouble::minus(const Value *other) const throw(INTERP_KERNEL::Exception) +{ + const ValueDouble *valC=checkSameType(other); + return new ValueDouble(_data-valC->_data); +} + +Value *ValueDouble::mult(const Value *other) const throw(INTERP_KERNEL::Exception) +{ + const ValueDouble *valC=checkSameType(other); + return new ValueDouble(_data*valC->_data); +} + +Value *ValueDouble::div(const Value *other) const throw(INTERP_KERNEL::Exception) +{ + const ValueDouble *valC=checkSameType(other); + return new ValueDouble(_data/valC->_data); +} + +Value *ValueDouble::pow(const Value *other) const throw(INTERP_KERNEL::Exception) +{ + const ValueDouble *valC=checkSameType(other); + return new ValueDouble(std::pow(_data,valC->_data)); +} + +Value *ValueDouble::max(const Value *other) const throw(INTERP_KERNEL::Exception) +{ + const ValueDouble *valC=checkSameType(other); + return new ValueDouble(std::max(_data,valC->_data)); +} + +Value *ValueDouble::min(const Value *other) const throw(INTERP_KERNEL::Exception) +{ + const ValueDouble *valC=checkSameType(other); + return new ValueDouble(std::min(_data,valC->_data)); +} + +const ValueDouble *ValueDouble::checkSameType(const Value *val) throw(INTERP_KERNEL::Exception) +{ + const ValueDouble *valC=dynamic_cast(val); + if(!valC) + throw INTERP_KERNEL::Exception("Trying to operate on non homogeneous Values (double with other type) !"); + return valC; +} + +ValueUnit::ValueUnit() +{ +} + +Value *ValueUnit::newInstance() const +{ + return new ValueUnit; +} + +ValueUnit::ValueUnit(const DecompositionInUnitBase& unit):_data(unit) +{ +} + +void ValueUnit::setDouble(double val) throw(INTERP_KERNEL::Exception) +{ + _data.tryToConvertInUnit(val); +} + +void ValueUnit::setVarname(int fastPos, const std::string& var) throw(INTERP_KERNEL::Exception) +{ + double add,mult; + const short *projInBase=UnitDataBase::_uniqueMapForExpr.getInfoForUnit(var,add,mult); + _data.setInfo(projInBase,add,mult); +} + +void ValueUnit::positive() throw(INTERP_KERNEL::Exception) +{ + unsupportedOp(PositiveFunction::REPR); +} + +void ValueUnit::negate() throw(INTERP_KERNEL::Exception) +{ + _data.negate(); +} + +void ValueUnit::sqrt() throw(INTERP_KERNEL::Exception) +{ + unsupportedOp(SqrtFunction::REPR); +} + +void ValueUnit::cos() throw(INTERP_KERNEL::Exception) +{ + unsupportedOp(CosFunction::REPR); +} + +void ValueUnit::sin() throw(INTERP_KERNEL::Exception) +{ + unsupportedOp(SinFunction::REPR); +} + +void ValueUnit::tan() throw(INTERP_KERNEL::Exception) +{ + unsupportedOp(TanFunction::REPR); +} + +void ValueUnit::abs() throw(INTERP_KERNEL::Exception) +{ + unsupportedOp(AbsFunction::REPR); +} + +void ValueUnit::exp() throw(INTERP_KERNEL::Exception) +{ + unsupportedOp(ExpFunction::REPR); +} + +void ValueUnit::ln() throw(INTERP_KERNEL::Exception) +{ + unsupportedOp(LnFunction::REPR); +} + +Value *ValueUnit::plus(const Value *other) const throw(INTERP_KERNEL::Exception) +{ + unsupportedOp(PlusFunction::REPR); + return 0; +} + +Value *ValueUnit::minus(const Value *other) const throw(INTERP_KERNEL::Exception) +{ + unsupportedOp(MinusFunction::REPR); + return 0; +} + +Value *ValueUnit::mult(const Value *other) const throw(INTERP_KERNEL::Exception) +{ + const ValueUnit *valC=checkSameType(other); + DecompositionInUnitBase tmp=_data; + tmp*valC->getData(); + return new ValueUnit(tmp); +} + +Value *ValueUnit::div(const Value *other) const throw(INTERP_KERNEL::Exception) +{ + const ValueUnit *valC=checkSameType(other); + DecompositionInUnitBase tmp=_data; + tmp/valC->getData(); + return new ValueUnit(tmp); +} + +Value *ValueUnit::pow(const Value *other) const throw(INTERP_KERNEL::Exception) +{ + const ValueUnit *valC=checkSameType(other); + DecompositionInUnitBase tmp=_data; + tmp^valC->getData(); + return new ValueUnit(tmp); +} + +Value *ValueUnit::max(const Value *other) const throw(INTERP_KERNEL::Exception) +{ + unsupportedOp(MaxFunction::REPR); + return 0; +} + +Value *ValueUnit::min(const Value *other) const throw(INTERP_KERNEL::Exception) +{ + unsupportedOp(MinFunction::REPR); + return 0; +} + +const ValueUnit *ValueUnit::checkSameType(const Value *val) throw(INTERP_KERNEL::Exception) +{ + const ValueUnit *valC=dynamic_cast(val); + if(!valC) + throw INTERP_KERNEL::Exception("Trying to operate on non homogeneous Values (Units with other type) !"); + return valC; +} + +void ValueUnit::unsupportedOp(const char *type) throw(INTERP_KERNEL::Exception) +{ + const char msg[]="Unsupported operation for units :"; + std::string msgStr(msg); + msgStr+=type; + throw INTERP_KERNEL::Exception(msgStr.c_str()); +} + +ValueDoubleExpr::ValueDoubleExpr(int szDestData, const double *srcData):_sz_dest_data(szDestData),_dest_data(new double[_sz_dest_data]),_src_data(srcData) +{ +} + +ValueDoubleExpr::~ValueDoubleExpr() +{ + delete [] _dest_data; +} + +Value *ValueDoubleExpr::newInstance() const +{ + return new ValueDoubleExpr(_sz_dest_data,_src_data); +} + +void ValueDoubleExpr::setDouble(double val) throw(INTERP_KERNEL::Exception) +{ + std::fill(_dest_data,_dest_data+_sz_dest_data,val); +} + +void ValueDoubleExpr::setVarname(int fastPos, const std::string& var) throw(INTERP_KERNEL::Exception) +{ + if(fastPos==-2) + std::copy(_src_data,_src_data+_sz_dest_data,_dest_data); + else if(fastPos>-2) + std::fill(_dest_data,_dest_data+_sz_dest_data,_src_data[fastPos]); + else + { + std::fill(_dest_data,_dest_data+_sz_dest_data,0.); + _dest_data[-7-fastPos]=1.; + } +} + +void ValueDoubleExpr::positive() throw(INTERP_KERNEL::Exception) +{ +} + +void ValueDoubleExpr::negate() throw(INTERP_KERNEL::Exception) +{ + std::transform(_dest_data,_dest_data+_sz_dest_data,_dest_data,std::negate()); +} + +void ValueDoubleExpr::sqrt() throw(INTERP_KERNEL::Exception) +{ + double *it=std::find_if(_dest_data,_dest_data+_sz_dest_data,std::bind2nd(std::less(),0.)); + if(it!=_dest_data+_sz_dest_data) + throw INTERP_KERNEL::Exception("Trying to apply sqrt on < 0. value !"); + std::transform(_dest_data,_dest_data+_sz_dest_data,_dest_data,std::ptr_fun(std::sqrt)); +} + +void ValueDoubleExpr::cos() throw(INTERP_KERNEL::Exception) +{ + std::transform(_dest_data,_dest_data+_sz_dest_data,_dest_data,std::ptr_fun(std::cos)); +} + +void ValueDoubleExpr::sin() throw(INTERP_KERNEL::Exception) +{ + std::transform(_dest_data,_dest_data+_sz_dest_data,_dest_data,std::ptr_fun(std::sin)); +} + +void ValueDoubleExpr::tan() throw(INTERP_KERNEL::Exception) +{ + std::transform(_dest_data,_dest_data+_sz_dest_data,_dest_data,std::ptr_fun(std::tan)); +} + +void ValueDoubleExpr::abs() throw(INTERP_KERNEL::Exception) +{ + std::transform(_dest_data,_dest_data+_sz_dest_data,_dest_data,std::ptr_fun(fabs)); +} + +void ValueDoubleExpr::exp() throw(INTERP_KERNEL::Exception) +{ + std::transform(_dest_data,_dest_data+_sz_dest_data,_dest_data,std::ptr_fun(std::exp)); +} + +void ValueDoubleExpr::ln() throw(INTERP_KERNEL::Exception) +{ + double *it=std::find_if(_dest_data,_dest_data+_sz_dest_data,std::bind2nd(std::less_equal(),0.)); + if(it!=_dest_data+_sz_dest_data) + throw INTERP_KERNEL::Exception("Trying to apply sqrt on < 0. value !"); + std::transform(_dest_data,_dest_data+_sz_dest_data,_dest_data,std::ptr_fun(std::log)); +} + +Value *ValueDoubleExpr::plus(const Value *other) const throw(INTERP_KERNEL::Exception) +{ + const ValueDoubleExpr *otherC=static_cast(other); + ValueDoubleExpr *ret=new ValueDoubleExpr(_sz_dest_data,_src_data); + std::transform(_dest_data,_dest_data+_sz_dest_data,otherC->getData(),ret->getData(),std::plus()); + return ret; +} + +Value *ValueDoubleExpr::minus(const Value *other) const throw(INTERP_KERNEL::Exception) +{ + const ValueDoubleExpr *otherC=static_cast(other); + ValueDoubleExpr *ret=new ValueDoubleExpr(_sz_dest_data,_src_data); + std::transform(_dest_data,_dest_data+_sz_dest_data,otherC->getData(),ret->getData(),std::minus()); + return ret; +} + +Value *ValueDoubleExpr::mult(const Value *other) const throw(INTERP_KERNEL::Exception) +{ + const ValueDoubleExpr *otherC=static_cast(other); + ValueDoubleExpr *ret=new ValueDoubleExpr(_sz_dest_data,_src_data); + std::transform(_dest_data,_dest_data+_sz_dest_data,otherC->getData(),ret->getData(),std::multiplies()); + return ret; +} + +Value *ValueDoubleExpr::div(const Value *other) const throw(INTERP_KERNEL::Exception) +{ + const ValueDoubleExpr *otherC=static_cast(other); + double *it=std::find(otherC->getData(),otherC->getData()+_sz_dest_data,0.); + if(it!=otherC->getData()+_sz_dest_data) + throw INTERP_KERNEL::Exception("Trying to operate division by 0. !"); + ValueDoubleExpr *ret=new ValueDoubleExpr(_sz_dest_data,_src_data); + std::transform(_dest_data,_dest_data+_sz_dest_data,otherC->getData(),ret->getData(),std::divides()); + return ret; +} + +Value *ValueDoubleExpr::pow(const Value *other) const throw(INTERP_KERNEL::Exception) +{ + const ValueDoubleExpr *otherC=static_cast(other); + double p=otherC->getData()[0]; + if(p<0.) + { + double *it=std::find_if(_dest_data,_dest_data+_sz_dest_data,std::bind2nd(std::less(),0.)); + if(it!=_dest_data+_sz_dest_data) + throw INTERP_KERNEL::Exception("Trying to operate pow(a,b) with a<0. and b<0. !"); + } + ValueDoubleExpr *ret=new ValueDoubleExpr(_sz_dest_data,_src_data); + std::transform(_dest_data,_dest_data+_sz_dest_data,ret->getData(),std::bind2nd(std::ptr_fun(powl),p)); + return ret; +} + +Value *ValueDoubleExpr::max(const Value *other) const throw(INTERP_KERNEL::Exception) +{ + const ValueDoubleExpr *otherC=static_cast(other); + ValueDoubleExpr *ret=new ValueDoubleExpr(_sz_dest_data,_src_data); + std::transform(_dest_data,_dest_data+_sz_dest_data,otherC->getData(),ret->getData(),std::ptr_fun(fmax)); + return ret; +} + +Value *ValueDoubleExpr::min(const Value *other) const throw(INTERP_KERNEL::Exception) +{ + const ValueDoubleExpr *otherC=static_cast(other); + ValueDoubleExpr *ret=new ValueDoubleExpr(_sz_dest_data,_src_data); + std::transform(_dest_data,_dest_data+_sz_dest_data,otherC->getData(),ret->getData(),std::ptr_fun(fmin)); + return ret; +} diff --git a/src/INTERP_KERNEL/ExprEval/InterpKernelValue.hxx b/src/INTERP_KERNEL/ExprEval/InterpKernelValue.hxx new file mode 100644 index 000000000..ae0357c7a --- /dev/null +++ b/src/INTERP_KERNEL/ExprEval/InterpKernelValue.hxx @@ -0,0 +1,138 @@ +#ifndef __INTERPKERNELVALUE_HXX__ +#define __INTERPKERNELVALUE_HXX__ + +#include "INTERPKERNELEXPREVALDefines.hxx" +#include "InterpKernelException.hxx" +#include "InterpKernelUnit.hxx" + +namespace INTERP_KERNEL +{ + class INTERPKERNELEXPREVAL_EXPORT Value + { + public: + virtual Value *newInstance() const = 0; + virtual ~Value() { } + virtual void setDouble(double val) throw(INTERP_KERNEL::Exception) = 0; + virtual void setVarname(int fastPos, const std::string& var) throw(INTERP_KERNEL::Exception) = 0; + //unary + virtual void positive() throw(INTERP_KERNEL::Exception) = 0; + virtual void negate() throw(INTERP_KERNEL::Exception) = 0; + virtual void sqrt() throw(INTERP_KERNEL::Exception) = 0; + virtual void cos() throw(INTERP_KERNEL::Exception) = 0; + virtual void sin() throw(INTERP_KERNEL::Exception) = 0; + virtual void tan() throw(INTERP_KERNEL::Exception) = 0; + virtual void abs() throw(INTERP_KERNEL::Exception) = 0; + virtual void exp() throw(INTERP_KERNEL::Exception) = 0; + virtual void ln() throw(INTERP_KERNEL::Exception) = 0; + //binary + virtual Value *plus(const Value *other) const throw(INTERP_KERNEL::Exception) = 0; + virtual Value *minus(const Value *other) const throw(INTERP_KERNEL::Exception) = 0; + virtual Value *mult(const Value *other) const throw(INTERP_KERNEL::Exception) = 0; + virtual Value *div(const Value *other) const throw(INTERP_KERNEL::Exception) = 0; + virtual Value *pow(const Value *other) const throw(INTERP_KERNEL::Exception) = 0; + virtual Value *max(const Value *other) const throw(INTERP_KERNEL::Exception) = 0; + virtual Value *min(const Value *other) const throw(INTERP_KERNEL::Exception) = 0; + }; + + class INTERPKERNELEXPREVAL_EXPORT ValueDouble : public Value + { + public: + ValueDouble(); + Value *newInstance() const; + void setDouble(double val) throw(INTERP_KERNEL::Exception); + void setVarname(int fastPos, const std::string& var) throw(INTERP_KERNEL::Exception); + // + double getData() const { return _data; } + void positive() throw(INTERP_KERNEL::Exception); + void negate() throw(INTERP_KERNEL::Exception); + void sqrt() throw(INTERP_KERNEL::Exception); + void cos() throw(INTERP_KERNEL::Exception); + void sin() throw(INTERP_KERNEL::Exception); + void tan() throw(INTERP_KERNEL::Exception); + void abs() throw(INTERP_KERNEL::Exception); + void exp() throw(INTERP_KERNEL::Exception); + void ln() throw(INTERP_KERNEL::Exception); + // + Value *plus(const Value *other) const throw(INTERP_KERNEL::Exception); + Value *minus(const Value *other) const throw(INTERP_KERNEL::Exception); + Value *mult(const Value *other) const throw(INTERP_KERNEL::Exception); + Value *div(const Value *other) const throw(INTERP_KERNEL::Exception); + Value *pow(const Value *other) const throw(INTERP_KERNEL::Exception); + Value *max(const Value *other) const throw(INTERP_KERNEL::Exception); + Value *min(const Value *other) const throw(INTERP_KERNEL::Exception); + private: + ValueDouble(double val); + static const ValueDouble *checkSameType(const Value *val) throw(INTERP_KERNEL::Exception); + private: + double _data; + }; + + class INTERPKERNELEXPREVAL_EXPORT ValueUnit : public Value + { + public: + ValueUnit(); + Value *newInstance() const; + void setDouble(double val) throw(INTERP_KERNEL::Exception); + void setVarname(int fastPos, const std::string& var) throw(INTERP_KERNEL::Exception); + // + DecompositionInUnitBase getData() const { return _data; } + void positive() throw(INTERP_KERNEL::Exception); + void negate() throw(INTERP_KERNEL::Exception); + void sqrt() throw(INTERP_KERNEL::Exception); + void cos() throw(INTERP_KERNEL::Exception); + void sin() throw(INTERP_KERNEL::Exception); + void tan() throw(INTERP_KERNEL::Exception); + void abs() throw(INTERP_KERNEL::Exception); + void exp() throw(INTERP_KERNEL::Exception); + void ln() throw(INTERP_KERNEL::Exception); + // + Value *plus(const Value *other) const throw(INTERP_KERNEL::Exception); + Value *minus(const Value *other) const throw(INTERP_KERNEL::Exception); + Value *mult(const Value *other) const throw(INTERP_KERNEL::Exception); + Value *div(const Value *other) const throw(INTERP_KERNEL::Exception); + Value *pow(const Value *other) const throw(INTERP_KERNEL::Exception); + Value *max(const Value *other) const throw(INTERP_KERNEL::Exception); + Value *min(const Value *other) const throw(INTERP_KERNEL::Exception); + private: + ValueUnit(const DecompositionInUnitBase& unit); + static void unsupportedOp(const char *type) throw(INTERP_KERNEL::Exception); + static const ValueUnit *checkSameType(const Value *val) throw(INTERP_KERNEL::Exception); + private: + DecompositionInUnitBase _data; + }; + + class INTERPKERNELEXPREVAL_EXPORT ValueDoubleExpr : public Value + { + public: + ValueDoubleExpr(int szDestData, const double *srcData); + ~ValueDoubleExpr(); + double *getData() const { return _dest_data; } + Value *newInstance() const; + void setDouble(double val) throw(INTERP_KERNEL::Exception); + void setVarname(int fastPos, const std::string& var) throw(INTERP_KERNEL::Exception); + // + void positive() throw(INTERP_KERNEL::Exception); + void negate() throw(INTERP_KERNEL::Exception); + void sqrt() throw(INTERP_KERNEL::Exception); + void cos() throw(INTERP_KERNEL::Exception); + void sin() throw(INTERP_KERNEL::Exception); + void tan() throw(INTERP_KERNEL::Exception); + void abs() throw(INTERP_KERNEL::Exception); + void exp() throw(INTERP_KERNEL::Exception); + void ln() throw(INTERP_KERNEL::Exception); + // + Value *plus(const Value *other) const throw(INTERP_KERNEL::Exception); + Value *minus(const Value *other) const throw(INTERP_KERNEL::Exception); + Value *mult(const Value *other) const throw(INTERP_KERNEL::Exception); + Value *div(const Value *other) const throw(INTERP_KERNEL::Exception); + Value *pow(const Value *other) const throw(INTERP_KERNEL::Exception); + Value *max(const Value *other) const throw(INTERP_KERNEL::Exception); + Value *min(const Value *other) const throw(INTERP_KERNEL::Exception); + private: + int _sz_dest_data; + double *_dest_data; + const double *_src_data; + }; +} + +#endif diff --git a/src/INTERP_KERNEL/ExprEval/Makefile.am b/src/INTERP_KERNEL/ExprEval/Makefile.am new file mode 100644 index 000000000..0df59eaf9 --- /dev/null +++ b/src/INTERP_KERNEL/ExprEval/Makefile.am @@ -0,0 +1,56 @@ +# Copyright (C) 2007-2008 CEA/DEN, EDF R&D +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# +# File : Makefile.am +# Author : Anthony GEAY (CEA/DEN/DANS/DM2S/SFME/LGLS) +# Module : MED +# +include $(top_srcdir)/adm_local/unix/make_common_starter.am + +lib_LTLIBRARIES = libinterpkernelexpreval.la + +salomeinclude_HEADERS = \ +INTERPKERNELEXPREVALDefines.hxx \ +InterpKernelExprParser.hxx \ +InterpKernelFunction.hxx \ +InterpKernelUnit.hxx \ +InterpKernelValue.hxx + + +EXTRA_DIST += \ +INTERPKERNELEXPREVALDefines.hxx \ +InterpKernelExprParser.hxx \ +InterpKernelFunction.hxx \ +InterpKernelUnit.hxx \ +InterpKernelValue.hxx + +dist_libinterpkernelexpreval_la_SOURCES = \ + InterpKernelExprParser.cxx \ + InterpKernelFunction.cxx \ + InterpKernelUnit.cxx \ + InterpKernelValue.cxx + +libinterpkernelexpreval_la_CPPFLAGS=-I$(srcdir)/../Bases + +libinterpkernelexpreval_la_LDFLAGS= + +libinterpkernelexpreval_la_LIBADD= ../Bases/libinterpkernelbases.la + +AM_CPPFLAGS += $(libinterpkernelexpreval_la_CPPFLAGS) + +LDADD= $(libinterpkernelexpreval_la_LDFLAGS) diff --git a/src/INTERP_KERNEL/Makefile.am b/src/INTERP_KERNEL/Makefile.am index 3afcd5360..fd748819a 100644 --- a/src/INTERP_KERNEL/Makefile.am +++ b/src/INTERP_KERNEL/Makefile.am @@ -23,9 +23,9 @@ # include $(top_srcdir)/adm_local/unix/make_common_starter.am -SUBDIRS = Bases Geometric2D . +SUBDIRS = Bases Geometric2D ExprEval . -DIST_SUBDIRS = Bases Geometric2D +DIST_SUBDIRS = Bases Geometric2D ExprEval lib_LTLIBRARIES = libinterpkernel.la @@ -173,7 +173,7 @@ libinterpkernel_la_CPPFLAGS=-I$(srcdir)/Geometric2D -I$(srcdir)/Bases libinterpkernel_la_LDFLAGS= # the geom2D library is included in the interpkernel one -libinterpkernel_la_LIBADD= ./Geometric2D/libInterpGeometric2DAlg.la Bases/libinterpkernelbases.la +libinterpkernel_la_LIBADD= ./Geometric2D/libInterpGeometric2DAlg.la Bases/libinterpkernelbases.la ExprEval/libinterpkernelexpreval.la AM_CPPFLAGS += $(libinterpkernel_la_CPPFLAGS) LDADD= $(libinterpkernel_la_LDFLAGS) diff --git a/src/INTERP_KERNELTest/ExprEvalInterpTest.cxx b/src/INTERP_KERNELTest/ExprEvalInterpTest.cxx new file mode 100644 index 000000000..9bf31ed00 --- /dev/null +++ b/src/INTERP_KERNELTest/ExprEvalInterpTest.cxx @@ -0,0 +1,380 @@ +// Copyright (C) 2007-2008 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// +#include "ExprEvalInterpTest.hxx" +#include "InterpKernelExprParser.hxx" + +using namespace std; +using namespace INTERP_TEST; + +void ExprEvalInterpTest::testBuildStringFromFortran() +{ + char toto1[]="123456 "; + char result[]="123456"; + string titi; + titi=INTERP_KERNEL::ExprParser::buildStringFromFortran(toto1,8); + CPPUNIT_ASSERT_EQUAL(6,(int)titi.length()); + CPPUNIT_ASSERT(titi==result); + // + char toto2[]=" 23456 "; + char result2[]=" 23456"; + titi=INTERP_KERNEL::ExprParser::buildStringFromFortran(toto2,8); + CPPUNIT_ASSERT(titi==result2); + CPPUNIT_ASSERT_EQUAL(6,(int)titi.length()); + // + char toto3[]=" 3456 "; + char result3[]=" 3456"; + titi=INTERP_KERNEL::ExprParser::buildStringFromFortran(toto3,8); + CPPUNIT_ASSERT(titi==result3); + CPPUNIT_ASSERT_EQUAL(6,(int)titi.length()); + // + char toto4[]=" "; + titi=INTERP_KERNEL::ExprParser::buildStringFromFortran(toto4,8); + CPPUNIT_ASSERT_EQUAL(0,(int)titi.length()); + // + char toto5[]=" 345677"; + titi=INTERP_KERNEL::ExprParser::buildStringFromFortran(toto5,8); + CPPUNIT_ASSERT(titi==toto5); + CPPUNIT_ASSERT_EQUAL(8,(int)titi.length()); +} + +void ExprEvalInterpTest::testDeleteWhiteSpaces() +{ + char toto[]=" jkhjkh ooooppp l "; + char result[]="jkhjkhoooopppl"; + string totoS(toto); + string totoR=INTERP_KERNEL::ExprParser::deleteWhiteSpaces(totoS); + CPPUNIT_ASSERT(totoR==result); + CPPUNIT_ASSERT_EQUAL(14,(int)totoR.length()); + // + char toto2[]=" jkhjkh ooooppp l "; + totoS=toto2; + totoR=INTERP_KERNEL::ExprParser::deleteWhiteSpaces(totoS); + CPPUNIT_ASSERT(totoR==result); + CPPUNIT_ASSERT_EQUAL(14,(int)totoR.length()); + // + char toto3[]=" jkhjkh oooo pppl "; + totoS=toto3; + totoR=INTERP_KERNEL::ExprParser::deleteWhiteSpaces(totoS); + CPPUNIT_ASSERT(totoR==result); + CPPUNIT_ASSERT_EQUAL(14,(int)totoR.length()); + // + char toto4[]=" jkhjkh oooo pppl"; + totoS=toto4; + totoR=INTERP_KERNEL::ExprParser::deleteWhiteSpaces(totoS); + CPPUNIT_ASSERT(totoR==result); + CPPUNIT_ASSERT_EQUAL(14,(int)totoR.length()); + // + char toto5[]="jkhjkh oooo pppl"; + totoS=toto5; + totoR=INTERP_KERNEL::ExprParser::deleteWhiteSpaces(totoS); + CPPUNIT_ASSERT(totoR==result); + CPPUNIT_ASSERT_EQUAL(14,(int)totoR.length()); + // + totoS=result; + totoR=INTERP_KERNEL::ExprParser::deleteWhiteSpaces(totoS); + CPPUNIT_ASSERT(totoR==result); + CPPUNIT_ASSERT_EQUAL(14,(int)totoR.length()); + // + char toto6[]="j k h j k h o o o o p p p l"; + totoS=toto6; + totoR=INTERP_KERNEL::ExprParser::deleteWhiteSpaces(totoS); + CPPUNIT_ASSERT(totoR==result); + CPPUNIT_ASSERT_EQUAL(14,(int)totoR.length()); + // + char toto7[]="j k h j k h o o o o p pp l"; + totoS=toto7; + totoR=INTERP_KERNEL::ExprParser::deleteWhiteSpaces(totoS); + CPPUNIT_ASSERT(totoR==result); + CPPUNIT_ASSERT_EQUAL(14,(int)totoR.length()); + // + char toto8[]=" "; + totoS=toto8; + totoR=INTERP_KERNEL::ExprParser::deleteWhiteSpaces(totoS); + CPPUNIT_ASSERT(totoR.empty()); + // + char toto9[]=""; + totoS=toto9; + totoR=INTERP_KERNEL::ExprParser::deleteWhiteSpaces(totoS); + CPPUNIT_ASSERT(totoR.empty()); + // + char toto10[]="j\n k \nh\nj \n\n k\nh \n o \no\n o\n o \np\n\npp \n\n l"; + totoS=toto10; + totoR=INTERP_KERNEL::ExprParser::deleteWhiteSpaces(totoS); + CPPUNIT_ASSERT(totoR==result); + CPPUNIT_ASSERT_EQUAL(14,(int)totoR.length()); +} + +void ExprEvalInterpTest::testInterpreter0() +{ + INTERP_KERNEL::ExprParser expr1("3*-2"); + expr1.parse(); + CPPUNIT_ASSERT_DOUBLES_EQUAL(-6.,expr1.evaluate(),1e-15); + INTERP_KERNEL::ExprParser expr2("-2.3"); + expr2.parse(); + CPPUNIT_ASSERT_DOUBLES_EQUAL(-2.3,expr2.evaluate(),1e-15); + INTERP_KERNEL::ExprParser expr3("--2.3"); + expr3.parse(); + CPPUNIT_ASSERT_DOUBLES_EQUAL(2.3,expr3.evaluate(),1e-15); + INTERP_KERNEL::ExprParser expr4("-++2.3"); + expr4.parse(); + CPPUNIT_ASSERT_DOUBLES_EQUAL(-2.3,expr4.evaluate(),1e-15); + INTERP_KERNEL::ExprParser expr5("+2.3"); + expr5.parse(); + CPPUNIT_ASSERT_DOUBLES_EQUAL(2.3,expr5.evaluate(),1e-15); + INTERP_KERNEL::ExprParser expr6("3^-1"); + expr6.parse(); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.33333333333333333,expr6.evaluate(),1e-15); +} + +void ExprEvalInterpTest::testInterpreter1() +{ + INTERP_KERNEL::ExprParser expr1("3+2*5"); + expr1.parse(); + CPPUNIT_ASSERT_DOUBLES_EQUAL(13.,expr1.evaluate(),1e-14); + INTERP_KERNEL::ExprParser expr2("3+2^3*5"); + expr2.parse(); + CPPUNIT_ASSERT_DOUBLES_EQUAL(43.,expr2.evaluate(),1e-14); + INTERP_KERNEL::ExprParser expr3("3+2^(2*5)"); + expr3.parse(); + CPPUNIT_ASSERT_DOUBLES_EQUAL(1027.,expr3.evaluate(),1e-14); + INTERP_KERNEL::ExprParser expr4("(3.2+4.3)*(1.3+2.3*7.8)"); + expr4.parse(); + CPPUNIT_ASSERT_DOUBLES_EQUAL(144.3,expr4.evaluate(),1e-10); + INTERP_KERNEL::ExprParser expr5("(3.2+4.3)*cos(1.3+2.3*7.8)"); + expr5.parse(); + CPPUNIT_ASSERT_DOUBLES_EQUAL(6.9355510138337619,expr5.evaluate(),1e-14); + INTERP_KERNEL::ExprParser expr6("3+2-4-7+4.3"); + expr6.parse(); + CPPUNIT_ASSERT_DOUBLES_EQUAL(-1.7,expr6.evaluate(),1e-14); + INTERP_KERNEL::ExprParser expr7("3.2*4.5/3.3/2.2"); + expr7.parse(); + CPPUNIT_ASSERT_DOUBLES_EQUAL(1.9834710743801653,expr7.evaluate(),1e-14); + INTERP_KERNEL::ExprParser expr8("3.2*4.5/3.3/2.2"); + expr8.parse(); + CPPUNIT_ASSERT_DOUBLES_EQUAL(1.9834710743801653,expr8.evaluate(),1e-14); + INTERP_KERNEL::ExprParser expr9("(((1.23456789)))"); + expr9.parse(); + CPPUNIT_ASSERT_DOUBLES_EQUAL(1.23456789,expr9.evaluate(),1e-14); + INTERP_KERNEL::ExprParser expr10("3.2*((2*5.2+6.)+(1.2*1.2+3.))"); + expr10.parse(); + CPPUNIT_ASSERT_DOUBLES_EQUAL(66.688,expr10.evaluate(),1e-13); + INTERP_KERNEL::ExprParser expr11("((3.2*(((2*5.2+6.)+(1.2*1.2+3.)))))"); + expr11.parse(); + CPPUNIT_ASSERT_DOUBLES_EQUAL(66.688,expr11.evaluate(),1e-13); + INTERP_KERNEL::ExprParser expr12("((3.2*(cos((2*5.2+6.)+(1.2*1.2+3.)))))"); + expr12.parse(); + CPPUNIT_ASSERT_DOUBLES_EQUAL(-1.3038041398761016,expr12.evaluate(),1e-14); + INTERP_KERNEL::ExprParser expr13("((3.2*(sin((2*5.2+6.)+(1.2*1.2+3.)))))"); + expr13.parse(); + CPPUNIT_ASSERT_DOUBLES_EQUAL(2.9223440531261784,expr13.evaluate(),1e-14); + INTERP_KERNEL::ExprParser expr14("((3.2*(tan((2*5.2+6.)+(1.2*1.2+3.)))))"); + expr14.parse(); + CPPUNIT_ASSERT_DOUBLES_EQUAL(-7.1724737512280257,expr14.evaluate(),1e-14); + INTERP_KERNEL::ExprParser expr15("((3.2*(sqrt((2*5.2+6.)+(1.2*1.2+3.)))))"); + expr15.parse(); + CPPUNIT_ASSERT_DOUBLES_EQUAL(14.608271629457059,expr15.evaluate(),1e-13); + INTERP_KERNEL::ExprParser expr16("-((3.2*(sqrt((2*5.2+6.)+(1.2*1.2+3.)))))"); + expr16.parse(); + CPPUNIT_ASSERT_DOUBLES_EQUAL(-14.608271629457059,expr16.evaluate(),1e-13); + INTERP_KERNEL::ExprParser expr17("(-(3.2*(sqrt((2*5.2+6.)+(1.2*1.2+3.)))))"); + expr17.parse(); + CPPUNIT_ASSERT_DOUBLES_EQUAL(-14.608271629457059,expr17.evaluate(),1e-13); + INTERP_KERNEL::ExprParser expr18("((-3.2*(sqrt((2*5.2+6.)+(1.2*1.2+3.)))))"); + expr18.parse(); + CPPUNIT_ASSERT_DOUBLES_EQUAL(-14.608271629457059,expr18.evaluate(),1e-13); + INTERP_KERNEL::ExprParser expr19("((3.2*(exp((6.+2*5.2)+(1.2*1.2+3.)))))"); + expr19.parse(); + CPPUNIT_ASSERT_DOUBLES_EQUAL(3596226038.1784945,expr19.evaluate(),1e-6); + INTERP_KERNEL::ExprParser expr20("((3.2*(ln((2*5.2+6.)+(1.2*1.2+3.)))))"); + expr20.parse(); + CPPUNIT_ASSERT_DOUBLES_EQUAL(9.7179974940325309,expr20.evaluate(),1e-14); + INTERP_KERNEL::ExprParser expr21("max(3.2,4.5)"); + expr21.parse(); + CPPUNIT_ASSERT_DOUBLES_EQUAL(4.5,expr21.evaluate(),1e-14); + INTERP_KERNEL::ExprParser expr22("3.*max(((3.2*(ln((2*5.2+6.)+(1.2*1.2+3.))))),((3.2*(exp((6.+2*5.2)+(1.2*1.2+3.))))))"); + expr22.parse(); + CPPUNIT_ASSERT_DOUBLES_EQUAL(10788678114.535484,expr22.evaluate(),1e-5); + INTERP_KERNEL::ExprParser expr23("min(3.2,4.5)"); + expr23.parse(); + CPPUNIT_ASSERT_DOUBLES_EQUAL(3.2,expr23.evaluate(),1e-14); +} + +void ExprEvalInterpTest::testInterpreter2() +{ + INTERP_KERNEL::ExprParser expr1("3.5*x+x*x*x/(2+x)+2*5*y"); + expr1.parse(); + std::set res,expected; + expr1.getSetOfVars(res); + CPPUNIT_ASSERT_EQUAL(2,(int)res.size()); + expected.insert("x"); expected.insert("y"); + CPPUNIT_ASSERT(std::equal(res.begin(),res.end(),expected.begin())); + double xyValue[2]={1.,3.}; + double res1; + std::vector vars; vars.push_back("x"); vars.push_back("y"); + expr1.prepareExprEvaluation(vars); + expr1.evaluateExpr(1,&res1,xyValue); + CPPUNIT_ASSERT_DOUBLES_EQUAL(33.833333333333336,res1,1e-13); + xyValue[0]=-2.; + CPPUNIT_ASSERT_THROW(expr1.evaluateExpr(1,&res1,xyValue),INTERP_KERNEL::Exception); + double res2[2]; + xyValue[0]=1.; + expr1.evaluateExpr(2,res2,xyValue); + CPPUNIT_ASSERT_DOUBLES_EQUAL(33.833333333333336,res2[0],1e-13); + CPPUNIT_ASSERT_DOUBLES_EQUAL(33.833333333333336,res2[1],1e-13); + INTERP_KERNEL::ExprParser expr2("3.5*tan(2.3*x)*IVec+(cos(1.2+y/x)*JVec)"); + expr2.parse(); + res.clear(); expected.clear(); + expr2.getSetOfVars(res); + CPPUNIT_ASSERT_EQUAL(4,(int)res.size()); + expected.insert("x"); expected.insert("y"); expected.insert("IVec"); expected.insert("JVec"); + CPPUNIT_ASSERT(std::equal(res.begin(),res.end(),expected.begin())); + expr2.prepareExprEvaluation(vars); + expr2.evaluateExpr(2,res2,xyValue); + CPPUNIT_ASSERT_DOUBLES_EQUAL(-3.9172477460694637,res2[0],1e-14); + CPPUNIT_ASSERT_DOUBLES_EQUAL(-0.49026082134069943,res2[1],1e-14); + INTERP_KERNEL::ExprParser expr3("3.5*u+u^2.4+2."); + expr3.parse(); + expr3.prepareExprEvaluationVec(); + expr3.evaluateExpr(2,res2,xyValue); + CPPUNIT_ASSERT_DOUBLES_EQUAL(6.5,res2[0],1e-14); + CPPUNIT_ASSERT_DOUBLES_EQUAL(26.466610165238237,res2[1],1e-14); + INTERP_KERNEL::ExprParser expr4("3.5*v+u^2.4+2."); + expr4.parse(); + CPPUNIT_ASSERT_THROW(expr4.prepareExprEvaluationVec(),INTERP_KERNEL::Exception); +} + +void ExprEvalInterpTest::testInterpreterUnit0() +{ + INTERP_KERNEL::ExprParser expr1("kg"); + expr1.parse(); + INTERP_KERNEL::DecompositionInUnitBase unit=expr1.evaluateUnit(); + CPPUNIT_ASSERT(unit.isEqual(1,0,0,0,0,0.,1000.)); + INTERP_KERNEL::ExprParser expr2("kgT"); + expr2.parse(); + CPPUNIT_ASSERT_THROW(expr2.evaluateUnit(),INTERP_KERNEL::Exception); + INTERP_KERNEL::ExprParser expr3("g"); + expr3.parse(); + unit=expr3.evaluateUnit(); + CPPUNIT_ASSERT(unit.isEqual(1,0,0,0,0,0.,1.)); + INTERP_KERNEL::ExprParser expr4("g*m"); + expr4.parse(); + unit=expr4.evaluateUnit(); + CPPUNIT_ASSERT(unit.isEqual(1,1,0,0,0,0.,1.)); + INTERP_KERNEL::ExprParser expr5("g*m/K"); + expr5.parse(); + unit=expr5.evaluateUnit(); + CPPUNIT_ASSERT(unit.isEqual(1,1,0,0,-1,0.,1.)); + INTERP_KERNEL::ExprParser expr6("g*m/K^2"); + expr6.parse(); + unit=expr6.evaluateUnit(); + CPPUNIT_ASSERT(unit.isEqual(1,1,0,0,-2,0.,1.)); + INTERP_KERNEL::ExprParser expr7("g/K^2*m"); + expr7.parse(); + unit=expr7.evaluateUnit(); + CPPUNIT_ASSERT(unit.isEqual(1,1,0,0,-2,0.,1.)); + INTERP_KERNEL::ExprParser expr8("g/(K^2*m)"); + expr8.parse(); + unit=expr8.evaluateUnit(); + CPPUNIT_ASSERT(unit.isEqual(1,-1,0,0,-2,0.,1.)); + INTERP_KERNEL::ExprParser expr9("km/h"); + expr9.parse(); + unit=expr9.evaluateUnit(); + CPPUNIT_ASSERT(unit.isEqual(0,1,-1,0,0,0.,0.27777777777777779)); + INTERP_KERNEL::ExprParser expr10("m/s"); + expr10.parse(); + unit=expr10.evaluateUnit(); + CPPUNIT_ASSERT(unit.isEqual(0,1,-1,0,0,0.,1.)); + INTERP_KERNEL::ExprParser expr11("m+s"); + expr11.parse(); + CPPUNIT_ASSERT_THROW(expr11.evaluateUnit(),INTERP_KERNEL::Exception); + INTERP_KERNEL::ExprParser expr12("m-m"); + expr12.parse(); + CPPUNIT_ASSERT_THROW(expr12.evaluateUnit(),INTERP_KERNEL::Exception); + const char expr13C[3]={-0x50,0x43,0x0}; + INTERP_KERNEL::ExprParser expr13(expr13C); + expr13.parse(); + unit=expr13.evaluateUnit(); + CPPUNIT_ASSERT(unit.isEqual(0,0,0,0,1,273.15,1.)); + const char expr14C[4]={-0x3E,-0x50,0x43,0x0}; + INTERP_KERNEL::ExprParser expr14(expr14C); + expr14.parse(); + unit=expr14.evaluateUnit(); + CPPUNIT_ASSERT(unit.isEqual(0,0,0,0,1,273.15,1.)); + INTERP_KERNEL::ExprParser expr15("kN/kg"); + expr15.parse(); + unit=expr15.evaluateUnit(); + CPPUNIT_ASSERT(unit.isEqual(0,1,-2,0,0,0.,1000.)); + INTERP_KERNEL::ExprParser expr16("cm"); + expr16.parse(); + unit=expr16.evaluateUnit(); + CPPUNIT_ASSERT(unit.isEqual(0,1,0,0,0,0.,0.01)); + INTERP_KERNEL::ExprParser expr17("m"); + expr17.parse(); + unit=expr17.evaluateUnit(); + CPPUNIT_ASSERT(unit.isEqual(0,1,0,0,0,0.,1)); + const char expr18C[3]={-0x08,0x43,0x0}; + INTERP_KERNEL::ExprParser expr18(expr18C); + expr18.parse(); + unit=expr18.evaluateUnit(); + CPPUNIT_ASSERT(unit.isEqual(0,0,0,0,1,273.15,1.)); + const char expr19C[6]={-0x50,0x43,0x2F,-0x50,0x43,0x0}; + INTERP_KERNEL::ExprParser expr19(expr19C); + expr19.parse(); + unit=expr19.evaluateUnit(); + CPPUNIT_ASSERT(unit.isEqual(0,0,0,0,0,0.,1.)); + const char expr20C[9]={-0x50,0x43,0x2A,-0x50,0x43,0x2F,-0x50,0x43,0x0}; + INTERP_KERNEL::ExprParser expr20(expr20C); + expr20.parse(); + unit=expr20.evaluateUnit(); + CPPUNIT_ASSERT(unit.isEqual(0,0,0,0,1,0.,1.)); +} + +void ExprEvalInterpTest::testInterpreterUnit1() +{ + INTERP_KERNEL::Unit unit1("m/s"); + INTERP_KERNEL::Unit unit2("km/h"); + CPPUNIT_ASSERT(unit1.isCompatibleWith(unit2) && unit2.isCompatibleWith(unit1)); + CPPUNIT_ASSERT_DOUBLES_EQUAL(360,unit1.convert(unit2,100.),1e-10); + INTERP_KERNEL::Unit unit3("J/s"); + INTERP_KERNEL::Unit unit4("kW"); + CPPUNIT_ASSERT(unit3.isCompatibleWith(unit4) && unit4.isCompatibleWith(unit3)); + CPPUNIT_ASSERT_DOUBLES_EQUAL(1.,unit3.convert(unit4,1000.),1e-10); + CPPUNIT_ASSERT(unit4.getCoarseRepr()=="kW"); + INTERP_KERNEL::Unit unit5("kpT"); + CPPUNIT_ASSERT(!unit5.isInterpretationOK()); + CPPUNIT_ASSERT(unit5.getCoarseRepr()=="kpT"); + INTERP_KERNEL::Unit unit6("m*kpT"); + CPPUNIT_ASSERT(!unit6.isInterpretationOK()); + INTERP_KERNEL::Unit unit7("m*s^-1"); + CPPUNIT_ASSERT(unit7.isCompatibleWith(unit2) && unit2.isCompatibleWith(unit7)); + CPPUNIT_ASSERT_DOUBLES_EQUAL(360,unit7.convert(unit2,100.),1e-10); + const char unit8C[3]={-0x50,0x43,0x0}; + INTERP_KERNEL::Unit unit8(unit8C); + INTERP_KERNEL::Unit unit9("K"); + CPPUNIT_ASSERT(unit9.isCompatibleWith(unit8) && unit8.isCompatibleWith(unit9)); + CPPUNIT_ASSERT_DOUBLES_EQUAL(335.15,unit8.convert(unit9,62.),1e-10); + CPPUNIT_ASSERT_DOUBLES_EQUAL(-16.37,unit9.convert(unit8,256.78),1e-10); + INTERP_KERNEL::Unit unit10("m"); + INTERP_KERNEL::Unit unit11("cm"); + CPPUNIT_ASSERT(unit10.isCompatibleWith(unit11) && unit11.isCompatibleWith(unit10)); + CPPUNIT_ASSERT_DOUBLES_EQUAL(6200.,unit10.convert(unit11,62.),1e-8); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.62,unit11.convert(unit10,62.),1e-15); + INTERP_KERNEL::Unit unit12("m-m"); + CPPUNIT_ASSERT(!unit12.isInterpretationOK()); +} diff --git a/src/INTERP_KERNELTest/ExprEvalInterpTest.hxx b/src/INTERP_KERNELTest/ExprEvalInterpTest.hxx new file mode 100644 index 000000000..0a3851281 --- /dev/null +++ b/src/INTERP_KERNELTest/ExprEvalInterpTest.hxx @@ -0,0 +1,53 @@ +// Copyright (C) 2007-2008 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// +#ifndef _EXPREVALINTERPTEST_HXX_ +#define _EXPREVALINTERPTEST_HXX_ + +#include + +#include "InterpKernelTestExport.hxx" + +namespace INTERP_TEST +{ + class INTERPKERNELTEST_EXPORT ExprEvalInterpTest : public CppUnit::TestFixture + { + CPPUNIT_TEST_SUITE( ExprEvalInterpTest ); + CPPUNIT_TEST( testBuildStringFromFortran ); + CPPUNIT_TEST( testDeleteWhiteSpaces ); + CPPUNIT_TEST( testInterpreter0 ); + CPPUNIT_TEST( testInterpreter1 ); + CPPUNIT_TEST( testInterpreter2 ); + CPPUNIT_TEST( testInterpreterUnit0 ); + CPPUNIT_TEST( testInterpreterUnit1 ); + CPPUNIT_TEST_SUITE_END(); + public: + void setUp() { } + void tearDown() { } + void cleanUp() { } + void testBuildStringFromFortran(); + void testDeleteWhiteSpaces(); + void testInterpreter0(); + void testInterpreter1(); + void testInterpreter2(); + void testInterpreterUnit0(); + void testInterpreterUnit1(); + }; +} + +#endif diff --git a/src/INTERP_KERNELTest/Makefile.am b/src/INTERP_KERNELTest/Makefile.am index 7651c0533..a7c0b6e31 100644 --- a/src/INTERP_KERNELTest/Makefile.am +++ b/src/INTERP_KERNELTest/Makefile.am @@ -42,6 +42,8 @@ libInterpKernelTest_la_SOURCES= \ CppUnitTest.hxx \ CppUnitTest.cxx \ InterpolationPlanarTestSuite.hxx \ + ExprEvalInterpTest.hxx \ + ExprEvalInterpTest.cxx \ QuadraticPlanarInterpTest.hxx \ QuadraticPlanarInterpTest.cxx \ QuadraticPlanarInterpTest2.cxx \ @@ -64,6 +66,7 @@ libInterpKernelTest_la_CPPFLAGS = \ -I$(srcdir)/../INTERP_KERNEL \ -I$(srcdir)/../INTERP_KERNEL/Geometric2D \ -I$(srcdir)/../INTERP_KERNEL/Bases \ + -I$(srcdir)/../INTERP_KERNEL/ExprEval \ -DOPTIMIZE -DLOG_LEVEL=0 libInterpKernelTest_la_LDFLAGS = \ diff --git a/src/INTERP_KERNELTest/TestInterpKernel.cxx b/src/INTERP_KERNELTest/TestInterpKernel.cxx index c8f8ea073..05611fbe6 100644 --- a/src/INTERP_KERNELTest/TestInterpKernel.cxx +++ b/src/INTERP_KERNELTest/TestInterpKernel.cxx @@ -19,6 +19,7 @@ #include "CppUnitTest.hxx" #include "BBTreeTest.hxx" +#include "ExprEvalInterpTest.hxx" #include "QuadraticPlanarInterpTest.hxx" #include "SingleElementPlanarTests.hxx" #include "TransformedTriangleIntersectTest.hxx" @@ -39,6 +40,7 @@ using namespace INTERP_TEST; //--- Registers the fixture into the 'registry' CPPUNIT_TEST_SUITE_REGISTRATION( BBTreeTest); +CPPUNIT_TEST_SUITE_REGISTRATION( ExprEvalInterpTest ); CPPUNIT_TEST_SUITE_REGISTRATION( QuadraticPlanarInterpTest ); CPPUNIT_TEST_SUITE_REGISTRATION( SingleElementPlanarTests ); CPPUNIT_TEST_SUITE_REGISTRATION( TransformedTriangleIntersectTest ); -- 2.39.2