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);
+ std::size_t pos2=funcName.find_first_of("+-*/^><",0,7);
+ std::size_t pos3=funcName.find_first_not_of("+-*/^><",0,7);
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);
std::size_t pos6=0;
for(int i=0;i<nbOfParamsInFunc;i++)
{
- std::size_t pos5=newExp2.find_first_of(',');
+ std::size_t pos5=newExp2.find_first_of(',',pos6);
std::size_t len=std::string::npos;
if(pos5!=std::string::npos)
len=pos5-pos6;
return true;
}
+void ExprParser::parseForCmp() throw(INTERP_KERNEL::Exception)
+{
+ std::string::const_iterator iter;
+ int curLevel=0;
+ std::string curPart;
+ bool isParsingSucceed=false;
+ for(iter=_expr.begin();iter!=_expr.end();iter++)
+ {
+ switch(*iter)
+ {
+ case '>':
+ case '<':
+ {
+ isParsingSucceed=true;
+ if(!curPart.empty())
+ {
+ _sub_expr.push_back(ExprParser(curPart.c_str(),this));
+ curPart.clear();
+ _func_btw_sub_expr.push_back(FunctionsFactory::buildBinaryFuncFromString(*iter));
+ }
+ else
+ {
+ std::ostringstream errMsg;
+ char MSGTYP1[]="Error non unary function for '";
+ errMsg << EXPR_PARSE_ERR_MSG << MSGTYP1 << *iter << "'";
+ std::string tmp=_expr.substr(iter-_expr.begin());
+ locateError(errMsg,tmp,0);
+ throw INTERP_KERNEL::Exception(errMsg.str().c_str());
+ }
+ break;
+ }
+ case '(':
+ curLevel++;
+ curPart+=*iter;
+ break;
+ case ')':
+ curLevel--;
+ curPart+=*iter;
+ break;
+ default:
+ curPart+=*iter;
+ }
+ }
+ if(isParsingSucceed)
+ {
+ if(!curPart.empty())
+ {
+ _sub_expr.push_back(ExprParser(curPart.c_str(),this));
+ _is_parsing_ok=true;
+ }
+ else
+ {
+ std::ostringstream errMsg;
+ char MSGTYP4[]="Error following expression finished by > / < without right part.";
+ errMsg << EXPR_PARSE_ERR_MSG << MSGTYP4 << _expr;
+ throw INTERP_KERNEL::Exception(errMsg.str().c_str());
+ }
+ }
+}
+
void ExprParser::parseForAddMin() throw(INTERP_KERNEL::Exception)
{
std::string::const_iterator iter;
parseUnaryFunc();
if(!_is_parsing_ok)
{
- parseForAddMin();
+ parseForCmp();
if(!_is_parsing_ok)
{
- parseForMulDiv();
+ parseForAddMin();
if(!_is_parsing_ok)
- parseForPow();
+ {
+ parseForMulDiv();
+ if(!_is_parsing_ok)
+ parseForPow();
+ }
}
}
if(!_is_parsing_ok)
void prepareExprEvaluationVecLowLev() const throw(INTERP_KERNEL::Exception);
bool tryToInterpALeaf() throw(INTERP_KERNEL::Exception);
void parseUnaryFunc() throw(INTERP_KERNEL::Exception);
+ void parseForCmp() throw(INTERP_KERNEL::Exception);
void parseForAddMin() throw(INTERP_KERNEL::Exception);
void parseForMulDiv() throw(INTERP_KERNEL::Exception);
void parseForPow() throw(INTERP_KERNEL::Exception);
const char MinFunction::REPR[]="min";
+const char GreaterThanFunction::REPR[]=">";
+
+const char LowerThanFunction::REPR[]="<";
+
+const char IfFunction::REPR[]="if";
+
Function *FunctionsFactory::buildFuncFromString(const char *type, int nbOfParams) throw(INTERP_KERNEL::Exception)
{
switch(nbOfParams)
return buildUnaryFuncFromString(type);
case 2:
return buildBinaryFuncFromString(type);
+ case 3:
+ return buildTernaryFuncFromString(type);
default:
throw INTERP_KERNEL::Exception("Invalid number of params detected : limited to 2 !");
}
return new MaxFunction;
if(tmp==MinFunction::REPR)
return new MinFunction;
+ if(tmp==GreaterThanFunction::REPR)
+ return new GreaterThanFunction;
+ if(tmp==LowerThanFunction::REPR)
+ return new LowerThanFunction;
std::string msg("Invalid binary function detected : \"");
msg+=type; msg+="\"";
throw INTERP_KERNEL::Exception(msg.c_str());
}
+Function *FunctionsFactory::buildTernaryFuncFromString(const char *type) throw(INTERP_KERNEL::Exception)
+{
+ std::string tmp(type);
+ if(tmp==IfFunction::REPR)
+ return new IfFunction();
+ std::string msg("Invalid ternary 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 false;
}
+
+GreaterThanFunction::~GreaterThanFunction()
+{
+}
+
+void GreaterThanFunction::operate(std::vector<Value *>& stack) const throw(INTERP_KERNEL::Exception)
+{
+ Value *val1=stack.back();
+ stack.pop_back();
+ Value *& val2=stack.back();
+ Value *val3;
+ try
+ {
+ val3=val1->greaterThan(val2);
+ }
+ catch(INTERP_KERNEL::Exception& e)
+ {
+ delete val1;
+ throw e;
+ }
+ delete val1;
+ delete val2;
+ val2=val3;
+}
+
+void GreaterThanFunction::operateX86(std::vector<std::string>& asmb) const throw(INTERP_KERNEL::Exception)
+{
+ throw INTERP_KERNEL::Exception("Assembly Not implemented yet !");
+}
+
+const char *GreaterThanFunction::getRepr() const
+{
+ return REPR;
+}
+
+bool GreaterThanFunction::isACall() const
+{
+ return false;
+}
+
+LowerThanFunction::~LowerThanFunction()
+{
+}
+
+void LowerThanFunction::operate(std::vector<Value *>& stack) const throw(INTERP_KERNEL::Exception)
+{
+ Value *val1=stack.back();
+ stack.pop_back();
+ Value *& val2=stack.back();
+ Value *val3;
+ try
+ {
+ val3=val1->lowerThan(val2);
+ }
+ catch(INTERP_KERNEL::Exception& e)
+ {
+ delete val1;
+ throw e;
+ }
+ delete val1;
+ delete val2;
+ val2=val3;
+}
+
+void LowerThanFunction::operateX86(std::vector<std::string>& asmb) const throw(INTERP_KERNEL::Exception)
+{
+ throw INTERP_KERNEL::Exception("Assembly Not implemented yet !");
+}
+
+const char *LowerThanFunction::getRepr() const
+{
+ return REPR;
+}
+
+bool LowerThanFunction::isACall() const
+{
+ return false;
+}
+
+int TernaryFunction::getNbInputParams() const
+{
+ return 3;
+}
+
+IfFunction::~IfFunction()
+{
+}
+
+void IfFunction::operate(std::vector<Value *>& stack) const throw(INTERP_KERNEL::Exception)
+{
+ Value *val1=stack.back();
+ stack.pop_back();
+ Value *val2=stack.back();
+ stack.pop_back();
+ Value *&val3=stack.back();
+ Value *val4;
+ try
+ {
+ val4=val1->ifFunc(val2,val3);
+ }
+ catch(INTERP_KERNEL::Exception& e)
+ {
+ delete val1;
+ delete val2;
+ throw e;
+ }
+ delete val1;
+ delete val2;
+ delete val3;
+ val3=val4;
+}
+
+void IfFunction::operateX86(std::vector<std::string>& asmb) const throw(INTERP_KERNEL::Exception)
+{
+ throw INTERP_KERNEL::Exception("Assembly Not implemented yet !");
+}
+
+const char *IfFunction::getRepr() const
+{
+ return REPR;
+}
+
+bool IfFunction::isACall() const
+{
+ return false;
+}
+
//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);
+ static Function *buildTernaryFuncFromString(const char *type) throw(INTERP_KERNEL::Exception);
};
class INTERPKERNELEXPREVAL_EXPORT Function
public:
static const char REPR[];
};
+
+ class INTERPKERNELEXPREVAL_EXPORT GreaterThanFunction : public BinaryFunction
+ {
+ public:
+ ~GreaterThanFunction();
+ void operate(std::vector<Value *>& stack) const throw(INTERP_KERNEL::Exception);
+ void operateX86(std::vector<std::string>& asmb) const throw(INTERP_KERNEL::Exception);
+ const char *getRepr() const;
+ bool isACall() const;
+ public:
+ static const char REPR[];
+ };
+
+ class INTERPKERNELEXPREVAL_EXPORT LowerThanFunction : public BinaryFunction
+ {
+ public:
+ ~LowerThanFunction();
+ void operate(std::vector<Value *>& stack) const throw(INTERP_KERNEL::Exception);
+ void operateX86(std::vector<std::string>& asmb) const throw(INTERP_KERNEL::Exception);
+ const char *getRepr() const;
+ bool isACall() const;
+ public:
+ static const char REPR[];
+ };
+
+ class INTERPKERNELEXPREVAL_EXPORT TernaryFunction : public Function
+ {
+ public:
+ int getNbInputParams() const;
+ };
+
+ class INTERPKERNELEXPREVAL_EXPORT IfFunction : public TernaryFunction
+ {
+ public:
+ ~IfFunction();
+ void operate(std::vector<Value *>& stack) const throw(INTERP_KERNEL::Exception);
+ void operateX86(std::vector<std::string>& asmb) const throw(INTERP_KERNEL::Exception);
+ const char *getRepr() const;
+ bool isACall() const;
+ public:
+ static const char REPR[];
+ };
}
#endif
return new ValueDouble(std::min(_data,valC->_data));
}
+Value *ValueDouble::greaterThan(const Value *other) const throw(INTERP_KERNEL::Exception)
+{
+ const ValueDouble *valC=checkSameType(other);
+ return new ValueDouble(_data>valC->_data?std::numeric_limits<double>::max():-std::numeric_limits<double>::max());
+}
+
+Value *ValueDouble::lowerThan(const Value *other) const throw(INTERP_KERNEL::Exception)
+{
+ const ValueDouble *valC=checkSameType(other);
+ return new ValueDouble(_data<valC->_data?std::numeric_limits<double>::max():-std::numeric_limits<double>::max());
+}
+
+Value *ValueDouble::ifFunc(const Value *the, const Value *els) const throw(INTERP_KERNEL::Exception)
+{
+ const ValueDouble *theC=checkSameType(the);
+ const ValueDouble *elsC=checkSameType(els);
+ if(_data==std::numeric_limits<double>::max())
+ return new ValueDouble(theC->_data);
+ if(_data==-std::numeric_limits<double>::max())
+ return new ValueDouble(elsC->_data);
+ throw INTERP_KERNEL::Exception("ValueDouble::ifFunc : The fist element of ternary function if is not a binary op !");
+}
+
const ValueDouble *ValueDouble::checkSameType(const Value *val) throw(INTERP_KERNEL::Exception)
{
const ValueDouble *valC=dynamic_cast<const ValueDouble *>(val);
return 0;
}
+Value *ValueUnit::greaterThan(const Value *other) const throw(INTERP_KERNEL::Exception)
+{
+ unsupportedOp(GreaterThanFunction::REPR);
+ return 0;
+}
+
+Value *ValueUnit::lowerThan(const Value *other) const throw(INTERP_KERNEL::Exception)
+{
+ unsupportedOp(LowerThanFunction::REPR);
+ return 0;
+}
+
+Value *ValueUnit::ifFunc(const Value *the, const Value *els) const throw(INTERP_KERNEL::Exception)
+{
+ unsupportedOp(IfFunction::REPR);
+ return 0;
+}
+
Value *ValueUnit::mult(const Value *other) const throw(INTERP_KERNEL::Exception)
{
const ValueUnit *valC=checkSameType(other);
std::transform(_dest_data,_dest_data+_sz_dest_data,otherC->getData(),ret->getData(),std::ptr_fun<const double&, const double&, const double& >(std::min));
return ret;
}
+
+Value *ValueDoubleExpr::greaterThan(const Value *other) const throw(INTERP_KERNEL::Exception)
+{
+ const ValueDoubleExpr *otherC=static_cast<const ValueDoubleExpr *>(other);
+ ValueDoubleExpr *ret=new ValueDoubleExpr(_sz_dest_data,_src_data);
+ for(int i=0;i<_sz_dest_data;i++)
+ if(_dest_data[i]<=otherC->getData()[i])
+ {
+ std::fill(ret->getData(),ret->getData()+_sz_dest_data,-std::numeric_limits<double>::max());
+ return ret;
+ }
+ std::fill(ret->getData(),ret->getData()+_sz_dest_data,std::numeric_limits<double>::max());
+ return ret;
+}
+
+Value *ValueDoubleExpr::lowerThan(const Value *other) const throw(INTERP_KERNEL::Exception)
+{
+ const ValueDoubleExpr *otherC=static_cast<const ValueDoubleExpr *>(other);
+ ValueDoubleExpr *ret=new ValueDoubleExpr(_sz_dest_data,_src_data);
+ for(int i=0;i<_sz_dest_data;i++)
+ if(_dest_data[i]>=otherC->getData()[i])
+ {
+ std::fill(ret->getData(),ret->getData()+_sz_dest_data,-std::numeric_limits<double>::max());
+ return ret;
+ }
+ std::fill(ret->getData(),ret->getData()+_sz_dest_data,std::numeric_limits<double>::max());
+ return ret;
+}
+
+Value *ValueDoubleExpr::ifFunc(const Value *the, const Value *els) const throw(INTERP_KERNEL::Exception)
+{
+ const ValueDoubleExpr *theC=static_cast<const ValueDoubleExpr *>(the);
+ const ValueDoubleExpr *elsC=static_cast<const ValueDoubleExpr *>(els);
+ ValueDoubleExpr *ret=new ValueDoubleExpr(_sz_dest_data,_src_data);
+ bool okmax=true;
+ bool okmin=true;
+ for(int i=0;i<_sz_dest_data && (okmax || okmin);i++)
+ {
+ okmax=_dest_data[i]==std::numeric_limits<double>::max();
+ okmin=_dest_data[i]==-std::numeric_limits<double>::max();
+ }
+ if(okmax || okmin)
+ {
+ if(okmax)
+ std::copy(theC->getData(),theC->getData()+_sz_dest_data,ret->getData());
+ else
+ std::copy(elsC->getData(),elsC->getData()+_sz_dest_data,ret->getData());
+ return ret;
+ }
+ else
+ {
+ throw INTERP_KERNEL::Exception("ValueDoubleExpr::ifFunc : first parameter of ternary func is NOT a consequence of a boolean op !");
+ }
+}
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;
+ virtual Value *greaterThan(const Value *other) const throw(INTERP_KERNEL::Exception) = 0;
+ virtual Value *lowerThan(const Value *other) const throw(INTERP_KERNEL::Exception) = 0;
+ //ternary
+ virtual Value *ifFunc(const Value *the, const Value *els) const throw(INTERP_KERNEL::Exception) = 0;
};
class INTERPKERNELEXPREVAL_EXPORT ValueDouble : public Value
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);
+ Value *greaterThan(const Value *other) const throw(INTERP_KERNEL::Exception);
+ Value *lowerThan(const Value *other) const throw(INTERP_KERNEL::Exception);
+ //
+ Value *ifFunc(const Value *the, const Value *els) const throw(INTERP_KERNEL::Exception);
private:
ValueDouble(double val);
static const ValueDouble *checkSameType(const Value *val) 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);
+ Value *greaterThan(const Value *other) const throw(INTERP_KERNEL::Exception);
+ Value *lowerThan(const Value *other) const throw(INTERP_KERNEL::Exception);
+ //
+ Value *ifFunc(const Value *the, const Value *els) const throw(INTERP_KERNEL::Exception);
private:
ValueUnit(const DecompositionInUnitBase& unit);
static void unsupportedOp(const char *type) 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);
+ Value *greaterThan(const Value *other) const throw(INTERP_KERNEL::Exception);
+ Value *lowerThan(const Value *other) const throw(INTERP_KERNEL::Exception);
+ //
+ Value *ifFunc(const Value *the, const Value *els) const throw(INTERP_KERNEL::Exception);
private:
int _sz_dest_data;
double *_dest_data;
#include "ExprEvalInterpTest.hxx"
#include "InterpKernelExprParser.hxx"
+#include <limits>
+#include <iterator>
+
using namespace INTERP_TEST;
void ExprEvalInterpTest::testBuildStringFromFortran()
INTERP_KERNEL::Unit unit12("m-m");
CPPUNIT_ASSERT(!unit12.isInterpretationOK());
}
+
+void ExprEvalInterpTest::testInterpreter3()
+{
+ INTERP_KERNEL::ExprParser expr1("2.3+x>5.");
+ expr1.parse();
+ std::set<std::string> res;
+ expr1.getSetOfVars(res);
+ CPPUNIT_ASSERT_EQUAL(1,(int)res.size());
+ CPPUNIT_ASSERT(*(res.begin())=="x");
+ expr1.prepareExprEvaluationVec();
+ double input[3];
+ input[0]=0.;
+ double res2[3];
+ expr1.evaluateExpr(1,input,res2);
+ CPPUNIT_ASSERT(-std::numeric_limits<double>::max()==res2[0]);
+ input[0]=2.8;
+ expr1.evaluateExpr(1,input,res2);
+ CPPUNIT_ASSERT(std::numeric_limits<double>::max()==res2[0]);
+ input[0]=2.6;
+ expr1.evaluateExpr(1,input,res2);
+ CPPUNIT_ASSERT(-std::numeric_limits<double>::max()==res2[0]);
+ //
+ INTERP_KERNEL::ExprParser expr2("2.3+x<5.");
+ expr2.parse();
+ res.clear();
+ expr2.getSetOfVars(res);
+ CPPUNIT_ASSERT_EQUAL(1,(int)res.size());
+ CPPUNIT_ASSERT(*(res.begin())=="x");
+ expr2.prepareExprEvaluationVec();
+ input[0]=0.;
+ expr2.evaluateExpr(1,input,res2);
+ CPPUNIT_ASSERT(std::numeric_limits<double>::max()==res2[0]);
+ input[0]=2.8;
+ expr2.evaluateExpr(1,input,res2);
+ CPPUNIT_ASSERT(-std::numeric_limits<double>::max()==res2[0]);
+ input[0]=2.6;
+ expr2.evaluateExpr(1,input,res2);
+ CPPUNIT_ASSERT(std::numeric_limits<double>::max()==res2[0]);
+ //
+ INTERP_KERNEL::ExprParser expr3("if(2.3+x<5.,2+3*x,3+x/2)");
+ expr3.parse();
+ res.clear();
+ expr3.getSetOfVars(res);
+ CPPUNIT_ASSERT_EQUAL(1,(int)res.size());
+ CPPUNIT_ASSERT(*(res.begin())=="x");
+ expr3.prepareExprEvaluationVec();
+ input[0]=0.;
+ expr3.evaluateExpr(1,input,res2);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(2.,res2[0],1e-12);
+ input[0]=2.8;
+ expr3.evaluateExpr(1,input,res2);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(4.4,res2[0],1e-12);
+ input[0]=2.6;
+ expr3.evaluateExpr(1,input,res2);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(9.8,res2[0],1e-12);
+}
CPPUNIT_TEST( testInterpreter2 );
CPPUNIT_TEST( testInterpreterUnit0 );
CPPUNIT_TEST( testInterpreterUnit1 );
+ CPPUNIT_TEST( testInterpreter3 );
CPPUNIT_TEST_SUITE_END();
public:
void setUp() { }
void testInterpreter0();
void testInterpreter1();
void testInterpreter2();
+ void testInterpreter3();
void testInterpreterUnit0();
void testInterpreterUnit1();
};