From: ageay Date: Tue, 25 Jan 2011 10:08:00 +0000 (+0000) Subject: Dealing with if <,> in expr X-Git-Tag: V6_main_FINAL~1090 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=802c8a5100f7a80562abc026b31f0ee52193b244;p=tools%2Fmedcoupling.git Dealing with if <,> in expr --- diff --git a/src/INTERP_KERNEL/ExprEval/InterpKernelExprParser.cxx b/src/INTERP_KERNEL/ExprEval/InterpKernelExprParser.cxx index 1f6b497b5..2d8055ffe 100644 --- a/src/INTERP_KERNEL/ExprEval/InterpKernelExprParser.cxx +++ b/src/INTERP_KERNEL/ExprEval/InterpKernelExprParser.cxx @@ -380,8 +380,8 @@ void ExprParser::parseUnaryFunc() throw(INTERP_KERNEL::Exception) 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); @@ -401,7 +401,7 @@ void ExprParser::parseUnaryFunc() throw(INTERP_KERNEL::Exception) std::size_t pos6=0; for(int i=0;i': + 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; @@ -640,12 +700,16 @@ bool ExprParser::simplify() throw(INTERP_KERNEL::Exception) 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) diff --git a/src/INTERP_KERNEL/ExprEval/InterpKernelExprParser.hxx b/src/INTERP_KERNEL/ExprEval/InterpKernelExprParser.hxx index 7ff8babb5..07334076e 100644 --- a/src/INTERP_KERNEL/ExprEval/InterpKernelExprParser.hxx +++ b/src/INTERP_KERNEL/ExprEval/InterpKernelExprParser.hxx @@ -105,6 +105,7 @@ namespace INTERP_KERNEL 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); diff --git a/src/INTERP_KERNEL/ExprEval/InterpKernelFunction.cxx b/src/INTERP_KERNEL/ExprEval/InterpKernelFunction.cxx index dd16329f6..ad23a0891 100644 --- a/src/INTERP_KERNEL/ExprEval/InterpKernelFunction.cxx +++ b/src/INTERP_KERNEL/ExprEval/InterpKernelFunction.cxx @@ -58,6 +58,12 @@ const char MaxFunction::REPR[]="max"; 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) @@ -66,6 +72,8 @@ Function *FunctionsFactory::buildFuncFromString(const char *type, int 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 !"); } @@ -117,11 +125,25 @@ Function *FunctionsFactory::buildBinaryFuncFromString(const char *type) throw(IN 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'; @@ -649,3 +671,130 @@ bool MinFunction::isACall() const { return false; } + +GreaterThanFunction::~GreaterThanFunction() +{ +} + +void GreaterThanFunction::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->greaterThan(val2); + } + catch(INTERP_KERNEL::Exception& e) + { + delete val1; + throw e; + } + delete val1; + delete val2; + val2=val3; +} + +void GreaterThanFunction::operateX86(std::vector& 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& 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& 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& 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& 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; +} + diff --git a/src/INTERP_KERNEL/ExprEval/InterpKernelFunction.hxx b/src/INTERP_KERNEL/ExprEval/InterpKernelFunction.hxx index 160e15ba9..5ef74540f 100644 --- a/src/INTERP_KERNEL/ExprEval/InterpKernelFunction.hxx +++ b/src/INTERP_KERNEL/ExprEval/InterpKernelFunction.hxx @@ -38,6 +38,7 @@ namespace INTERP_KERNEL //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 @@ -266,6 +267,48 @@ namespace INTERP_KERNEL public: static const char REPR[]; }; + + class INTERPKERNELEXPREVAL_EXPORT GreaterThanFunction : public BinaryFunction + { + public: + ~GreaterThanFunction(); + void operate(std::vector& stack) const throw(INTERP_KERNEL::Exception); + void operateX86(std::vector& 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& stack) const throw(INTERP_KERNEL::Exception); + void operateX86(std::vector& 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& stack) const throw(INTERP_KERNEL::Exception); + void operateX86(std::vector& asmb) 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/InterpKernelValue.cxx b/src/INTERP_KERNEL/ExprEval/InterpKernelValue.cxx index 5e3bcfe19..338541960 100644 --- a/src/INTERP_KERNEL/ExprEval/InterpKernelValue.cxx +++ b/src/INTERP_KERNEL/ExprEval/InterpKernelValue.cxx @@ -137,6 +137,29 @@ Value *ValueDouble::min(const Value *other) const throw(INTERP_KERNEL::Exception 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::max():-std::numeric_limits::max()); +} + +Value *ValueDouble::lowerThan(const Value *other) const throw(INTERP_KERNEL::Exception) +{ + const ValueDouble *valC=checkSameType(other); + return new ValueDouble(_data_data?std::numeric_limits::max():-std::numeric_limits::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::max()) + return new ValueDouble(theC->_data); + if(_data==-std::numeric_limits::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(val); @@ -227,6 +250,24 @@ Value *ValueUnit::minus(const Value *other) const throw(INTERP_KERNEL::Exception 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); @@ -423,3 +464,57 @@ Value *ValueDoubleExpr::min(const Value *other) const throw(INTERP_KERNEL::Excep std::transform(_dest_data,_dest_data+_sz_dest_data,otherC->getData(),ret->getData(),std::ptr_fun(std::min)); return ret; } + +Value *ValueDoubleExpr::greaterThan(const Value *other) const throw(INTERP_KERNEL::Exception) +{ + const ValueDoubleExpr *otherC=static_cast(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::max()); + return ret; + } + std::fill(ret->getData(),ret->getData()+_sz_dest_data,std::numeric_limits::max()); + return ret; +} + +Value *ValueDoubleExpr::lowerThan(const Value *other) const throw(INTERP_KERNEL::Exception) +{ + const ValueDoubleExpr *otherC=static_cast(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::max()); + return ret; + } + std::fill(ret->getData(),ret->getData()+_sz_dest_data,std::numeric_limits::max()); + return ret; +} + +Value *ValueDoubleExpr::ifFunc(const Value *the, const Value *els) const throw(INTERP_KERNEL::Exception) +{ + const ValueDoubleExpr *theC=static_cast(the); + const ValueDoubleExpr *elsC=static_cast(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::max(); + okmin=_dest_data[i]==-std::numeric_limits::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 !"); + } +} diff --git a/src/INTERP_KERNEL/ExprEval/InterpKernelValue.hxx b/src/INTERP_KERNEL/ExprEval/InterpKernelValue.hxx index 95ac2e66b..71f1b79fe 100644 --- a/src/INTERP_KERNEL/ExprEval/InterpKernelValue.hxx +++ b/src/INTERP_KERNEL/ExprEval/InterpKernelValue.hxx @@ -51,6 +51,10 @@ namespace INTERP_KERNEL 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 @@ -79,6 +83,10 @@ namespace INTERP_KERNEL 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); @@ -112,6 +120,10 @@ namespace INTERP_KERNEL 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); @@ -147,6 +159,10 @@ namespace INTERP_KERNEL 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; diff --git a/src/INTERP_KERNELTest/ExprEvalInterpTest.cxx b/src/INTERP_KERNELTest/ExprEvalInterpTest.cxx index b62b39e35..96032f6a3 100644 --- a/src/INTERP_KERNELTest/ExprEvalInterpTest.cxx +++ b/src/INTERP_KERNELTest/ExprEvalInterpTest.cxx @@ -20,6 +20,9 @@ #include "ExprEvalInterpTest.hxx" #include "InterpKernelExprParser.hxx" +#include +#include + using namespace INTERP_TEST; void ExprEvalInterpTest::testBuildStringFromFortran() @@ -378,3 +381,59 @@ void ExprEvalInterpTest::testInterpreterUnit1() 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 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::max()==res2[0]); + input[0]=2.8; + expr1.evaluateExpr(1,input,res2); + CPPUNIT_ASSERT(std::numeric_limits::max()==res2[0]); + input[0]=2.6; + expr1.evaluateExpr(1,input,res2); + CPPUNIT_ASSERT(-std::numeric_limits::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::max()==res2[0]); + input[0]=2.8; + expr2.evaluateExpr(1,input,res2); + CPPUNIT_ASSERT(-std::numeric_limits::max()==res2[0]); + input[0]=2.6; + expr2.evaluateExpr(1,input,res2); + CPPUNIT_ASSERT(std::numeric_limits::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); +} diff --git a/src/INTERP_KERNELTest/ExprEvalInterpTest.hxx b/src/INTERP_KERNELTest/ExprEvalInterpTest.hxx index a135201da..2730af59a 100644 --- a/src/INTERP_KERNELTest/ExprEvalInterpTest.hxx +++ b/src/INTERP_KERNELTest/ExprEvalInterpTest.hxx @@ -36,6 +36,7 @@ namespace INTERP_TEST CPPUNIT_TEST( testInterpreter2 ); CPPUNIT_TEST( testInterpreterUnit0 ); CPPUNIT_TEST( testInterpreterUnit1 ); + CPPUNIT_TEST( testInterpreter3 ); CPPUNIT_TEST_SUITE_END(); public: void setUp() { } @@ -46,6 +47,7 @@ namespace INTERP_TEST void testInterpreter0(); void testInterpreter1(); void testInterpreter2(); + void testInterpreter3(); void testInterpreterUnit0(); void testInterpreterUnit1(); };