C++ Mathematical Expression Library (ExprTk) http://www.partow.net/programming/exprtk/index.html
This commit is contained in:
parent
a60b7646c1
commit
437632dbdb
230
exprtk.hpp
230
exprtk.hpp
|
@ -1619,6 +1619,7 @@ namespace exprtk
|
|||
e_in ,
|
||||
e_like ,
|
||||
e_ilike ,
|
||||
e_inranges ,
|
||||
e_vov
|
||||
};
|
||||
|
||||
|
@ -2672,6 +2673,18 @@ namespace exprtk
|
|||
static inline details::operator_type operation() { return details::e_ilike; }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct inrange_op
|
||||
{
|
||||
static inline T process(const T& t0, const T& t1, const T& t2) { return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0); }
|
||||
static inline T process(const std::string& t0, const std::string& t1, const std::string& t2)
|
||||
{
|
||||
return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0);
|
||||
}
|
||||
static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_inranges; }
|
||||
static inline details::operator_type operation() { return details::e_ilike; }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class vov_base_node : public expression_node<T>
|
||||
{
|
||||
|
@ -2705,6 +2718,17 @@ namespace exprtk
|
|||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class sosos_base_node : public expression_node<T>
|
||||
{
|
||||
public:
|
||||
|
||||
inline virtual operator_type operation() const
|
||||
{
|
||||
return details::e_default;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename Operation>
|
||||
class vov_node : public vov_base_node<T>
|
||||
{
|
||||
|
@ -3172,6 +3196,63 @@ namespace exprtk
|
|||
sos_node<T,SType0,SType1,Operation>& operator=(sos_node<T,SType0,SType1,Operation>&);
|
||||
};
|
||||
|
||||
template <typename T, typename SType0, typename SType1, typename SType2, typename Operation>
|
||||
class sosos_node : public sosos_base_node<T>
|
||||
{
|
||||
public:
|
||||
|
||||
typedef expression_node<T>* expression_ptr;
|
||||
typedef Operation operation_t;
|
||||
|
||||
//variable op variable node
|
||||
explicit sosos_node(SType0 s0, SType1 s1, SType2 s2)
|
||||
: s0_(s0),
|
||||
s1_(s1),
|
||||
s2_(s2)
|
||||
{}
|
||||
|
||||
inline T value() const
|
||||
{
|
||||
return Operation::process(s0_,s1_,s2_);
|
||||
}
|
||||
|
||||
inline typename expression_node<T>::node_type type() const
|
||||
{
|
||||
return Operation::type();
|
||||
}
|
||||
|
||||
inline operator_type operation() const
|
||||
{
|
||||
return Operation::operation();
|
||||
}
|
||||
|
||||
inline std::string& s0()
|
||||
{
|
||||
return s0_;
|
||||
}
|
||||
|
||||
inline std::string& s1()
|
||||
{
|
||||
return s1_;
|
||||
}
|
||||
|
||||
inline std::string& s2()
|
||||
{
|
||||
return s2_;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
SType0 s0_;
|
||||
SType1 s1_;
|
||||
SType2 s2_;
|
||||
|
||||
private:
|
||||
|
||||
sosos_node(sosos_node<T,SType0,SType1,SType2,Operation>&);
|
||||
sosos_node<T,SType0,SType1,SType2,Operation>& operator=(sosos_node<T,SType0,SType1,SType2,Operation>&);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
inline bool is_vov_node(const expression_node<T>* node)
|
||||
{
|
||||
|
@ -3290,6 +3371,13 @@ namespace exprtk
|
|||
return new node_type(t1,t2,t3);
|
||||
}
|
||||
|
||||
template <typename node_type,
|
||||
typename T1, typename T2, typename T3>
|
||||
inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, T3 t3) const
|
||||
{
|
||||
return new node_type(t1,t2,t3);
|
||||
}
|
||||
|
||||
template <typename node_type,
|
||||
typename T1, typename T2,
|
||||
typename T3>
|
||||
|
@ -4305,6 +4393,19 @@ namespace exprtk
|
|||
return ((0 == expression_holder_) || (0 == expression_holder_->expr));
|
||||
}
|
||||
|
||||
inline expression& release()
|
||||
{
|
||||
if (expression_holder_)
|
||||
{
|
||||
if (0 == --expression_holder_->ref_count)
|
||||
{
|
||||
delete expression_holder_;
|
||||
}
|
||||
expression_holder_ = 0;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
~expression()
|
||||
{
|
||||
if (expression_holder_)
|
||||
|
@ -5234,6 +5335,19 @@ namespace exprtk
|
|||
return false;
|
||||
}
|
||||
|
||||
inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[3])
|
||||
{
|
||||
bool b0_string = details::is_string_node(branch[0]) || details::is_const_string_node(branch[0]);
|
||||
bool b1_string = details::is_string_node(branch[1]) || details::is_const_string_node(branch[1]);
|
||||
bool b2_string = details::is_string_node(branch[2]) || details::is_const_string_node(branch[2]);
|
||||
if ((b0_string || b1_string || b2_string) && !(b0_string && b1_string && b2_string))
|
||||
return true;
|
||||
if ((details::e_inrange != operation) && b0_string && b1_string && b2_string)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2])
|
||||
{
|
||||
bool b0_string = details::is_string_node(branch[0]) || details::is_const_string_node(branch[0]);
|
||||
|
@ -5241,6 +5355,14 @@ namespace exprtk
|
|||
return (b0_string && b1_string && valid_string_operation(operation));
|
||||
}
|
||||
|
||||
inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[3])
|
||||
{
|
||||
bool b0_string = details::is_string_node(branch[0]) || details::is_const_string_node(branch[0]);
|
||||
bool b1_string = details::is_string_node(branch[1]) || details::is_const_string_node(branch[1]);
|
||||
bool b2_string = details::is_string_node(branch[2]) || details::is_const_string_node(branch[2]);
|
||||
return (b0_string && b1_string && b2_string && (details::e_inrange == operation));
|
||||
}
|
||||
|
||||
// Note: Extended Optimisations
|
||||
// When using older C++ compilers due to the large number of type instantiations
|
||||
// required by the extended optimisations the compiler may crash or not be able
|
||||
|
@ -5303,7 +5425,14 @@ namespace exprtk
|
|||
|
||||
inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr (&branch)[3])
|
||||
{
|
||||
return synthesize_expression<trinary_node_t,3>(operation,branch);
|
||||
if ((0 == branch[0]) || (0 == branch[1]) || (0 == branch[2]))
|
||||
return error_node();
|
||||
else if (is_invalid_string_op(operation,branch))
|
||||
return error_node();
|
||||
else if (is_string_operation(operation,branch))
|
||||
return synthesize_string_expression(operation,branch);
|
||||
else
|
||||
return synthesize_expression<trinary_node_t,3>(operation,branch);
|
||||
}
|
||||
|
||||
inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr (&branch)[4])
|
||||
|
@ -5988,8 +6117,8 @@ namespace exprtk
|
|||
|
||||
inline expression_node_ptr synthesize_csocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
|
||||
{
|
||||
std::string s0 = dynamic_cast<details::string_literal_node<Type>*>(branch[0])->str();
|
||||
std::string s1 = dynamic_cast<details::string_literal_node<Type>*>(branch[1])->str();
|
||||
const std::string s0 = dynamic_cast<details::string_literal_node<Type>*>(branch[0])->str();
|
||||
const std::string s1 = dynamic_cast<details::string_literal_node<Type>*>(branch[1])->str();
|
||||
expression_node_ptr result = error_node();
|
||||
if (details::e_add == opr)
|
||||
result = node_allocator_->allocate_c<details::string_literal_node<Type> >(s0 + s1);
|
||||
|
@ -6033,6 +6162,101 @@ namespace exprtk
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifndef exprtk_disable_string_capabilities
|
||||
inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[3])
|
||||
{
|
||||
if (details::e_inrange != opr)
|
||||
return error_node();
|
||||
else if (
|
||||
details::is_const_string_node(branch[0]) &&
|
||||
details::is_const_string_node(branch[1]) &&
|
||||
details::is_const_string_node(branch[2])
|
||||
)
|
||||
{
|
||||
const std::string s0 = dynamic_cast<details::string_literal_node<Type>*>(branch[0])->str();
|
||||
const std::string s1 = dynamic_cast<details::string_literal_node<Type>*>(branch[1])->str();
|
||||
const std::string s2 = dynamic_cast<details::string_literal_node<Type>*>(branch[2])->str();
|
||||
Type v = (((s0 <= s1) && (s1 <= s2)) ? Type(1) : Type(0));
|
||||
node_allocator_->free(branch[0]);
|
||||
node_allocator_->free(branch[1]);
|
||||
node_allocator_->free(branch[2]);
|
||||
return node_allocator_->allocate_c<details::literal_node<Type> >(v);
|
||||
}
|
||||
else if (
|
||||
details::is_string_node(branch[0]) &&
|
||||
details::is_string_node(branch[1]) &&
|
||||
details::is_string_node(branch[2])
|
||||
)
|
||||
{
|
||||
std::string& s0 = dynamic_cast<details::stringvar_node<Type>*>(branch[0])->ref();
|
||||
std::string& s1 = dynamic_cast<details::stringvar_node<Type>*>(branch[1])->ref();
|
||||
std::string& s2 = dynamic_cast<details::stringvar_node<Type>*>(branch[2])->ref();
|
||||
typedef typename details::sosos_node<Type,std::string&,std::string&,std::string&,details::inrange_op<Type> > inrange_t;
|
||||
return node_allocator_->allocate_type<inrange_t,std::string&,std::string&,std::string&>(s0,s1,s2);
|
||||
}
|
||||
else if (
|
||||
details::is_const_string_node(branch[0]) &&
|
||||
details::is_string_node(branch[1]) &&
|
||||
details::is_const_string_node(branch[2])
|
||||
)
|
||||
{
|
||||
std::string s0 = dynamic_cast<details::string_literal_node<Type>*>(branch[0])->str();
|
||||
std::string& s1 = dynamic_cast< details::stringvar_node<Type>*>(branch[1])->ref();
|
||||
std::string s2 = dynamic_cast<details::string_literal_node<Type>*>(branch[2])->str();
|
||||
typedef typename details::sosos_node<Type,std::string,std::string&,std::string,details::inrange_op<Type> > inrange_t;
|
||||
node_allocator_->free(branch[0]);
|
||||
node_allocator_->free(branch[2]);
|
||||
return node_allocator_->allocate_type<inrange_t,std::string,std::string&,std::string>(s0,s1,s2);
|
||||
}
|
||||
else if (
|
||||
details::is_string_node(branch[0]) &&
|
||||
details::is_const_string_node(branch[1]) &&
|
||||
details::is_string_node(branch[2])
|
||||
)
|
||||
{
|
||||
std::string& s0 = dynamic_cast< details::stringvar_node<Type>*>(branch[0])->ref();
|
||||
std::string s1 = dynamic_cast<details::string_literal_node<Type>*>(branch[1])->str();
|
||||
std::string& s2 = dynamic_cast< details::stringvar_node<Type>*>(branch[2])->ref();
|
||||
typedef typename details::sosos_node<Type,std::string&,std::string,std::string&,details::inrange_op<Type> > inrange_t;
|
||||
node_allocator_->free(branch[1]);
|
||||
return node_allocator_->allocate_type<inrange_t,std::string&,std::string,std::string&>(s0,s1,s2);
|
||||
}
|
||||
else if (
|
||||
details::is_string_node(branch[0]) &&
|
||||
details::is_string_node(branch[1]) &&
|
||||
details::is_const_string_node(branch[2])
|
||||
)
|
||||
{
|
||||
std::string& s0 = dynamic_cast< details::stringvar_node<Type>*>(branch[0])->ref();
|
||||
std::string& s1 = dynamic_cast< details::stringvar_node<Type>*>(branch[1])->ref();
|
||||
std::string s2 = dynamic_cast<details::string_literal_node<Type>*>(branch[2])->str();
|
||||
typedef typename details::sosos_node<Type,std::string&,std::string&,std::string,details::inrange_op<Type> > inrange_t;
|
||||
node_allocator_->free(branch[2]);
|
||||
return node_allocator_->allocate_type<inrange_t,std::string&,std::string&,std::string>(s0,s1,s2);
|
||||
}
|
||||
else if (
|
||||
details::is_const_string_node(branch[0]) &&
|
||||
details:: is_string_node(branch[1]) &&
|
||||
details:: is_string_node(branch[2])
|
||||
)
|
||||
{
|
||||
std::string s0 = dynamic_cast<details::string_literal_node<Type>*>(branch[0])->str();
|
||||
std::string& s1 = dynamic_cast< details::stringvar_node<Type>*>(branch[1])->ref();
|
||||
std::string& s2 = dynamic_cast< details::stringvar_node<Type>*>(branch[2])->ref();
|
||||
typedef typename details::sosos_node<Type,std::string,std::string&,std::string&,details::inrange_op<Type> > inrange_t;
|
||||
node_allocator_->free(branch[0]);
|
||||
return node_allocator_->allocate_type<inrange_t,std::string,std::string&,std::string&>(s0,s1,s2);
|
||||
}
|
||||
else
|
||||
return error_node();
|
||||
}
|
||||
#else
|
||||
inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&)[3])
|
||||
{
|
||||
return error_node();
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename NodeType, std::size_t N>
|
||||
inline expression_node_ptr synthesize_expression(const details::operator_type& operation, expression_node_ptr (&branch)[N])
|
||||
{
|
||||
|
|
|
@ -849,12 +849,14 @@ struct test_ab
|
|||
: expr(e),
|
||||
a(v0),
|
||||
b(v1),
|
||||
c("ccc"),
|
||||
result(r)
|
||||
{}
|
||||
|
||||
std::string expr;
|
||||
std::string a;
|
||||
std::string b;
|
||||
std::string c;
|
||||
T result;
|
||||
};
|
||||
|
||||
|
@ -880,6 +882,7 @@ inline bool run_test02()
|
|||
test_ab<T>("'a123b' like '*123?'" ,"","",T(1.0)),
|
||||
test_ab<T>("'1XYZ2' ilike '*xyz*'" ,"","",T(1.0)),
|
||||
test_ab<T>("'1XYZ2' ilike '*xyz?'" ,"","",T(1.0)),
|
||||
test_ab<T>("inrange('aaa','bbb','ccc')" ,"","",T(1.0)),
|
||||
test_ab<T>("a == b" ,"aaa","aaa",T(1.0)),
|
||||
test_ab<T>("a != b" ,"aaa","bbb",T(1.0)),
|
||||
test_ab<T>("a < b" ,"aaa","bbb",T(1.0)),
|
||||
|
@ -913,6 +916,11 @@ inline bool run_test02()
|
|||
test_ab<T>("a ilike '*xyz?'" ,"1XYZ2","",T(1.0)),
|
||||
test_ab<T>("'1XYZ2' ilike b" ,"","*xyz*",T(1.0)),
|
||||
test_ab<T>("'1XYZ2' ilike b" ,"","*xyz?",T(1.0)),
|
||||
test_ab<T>("inrange(a,'bbb',c)" ,"aaa","bbb",T(1.0)),
|
||||
test_ab<T>("inrange('aaa',b,'ccc')" ,"aaa","bbb",T(1.0)),
|
||||
test_ab<T>("inrange(a,b,c)" ,"aaa","bbb",T(1.0)),
|
||||
test_ab<T>("inrange(a,b,'ccc')" ,"aaa","bbb",T(1.0)),
|
||||
test_ab<T>("inrange('aaa',b,c)" ,"aaa","bbb",T(1.0)),
|
||||
};
|
||||
|
||||
|
||||
|
@ -928,6 +936,7 @@ inline bool run_test02()
|
|||
exprtk::symbol_table<T> symbol_table;
|
||||
symbol_table.add_stringvar("a",test.a);
|
||||
symbol_table.add_stringvar("b",test.b);
|
||||
symbol_table.add_stringvar("c",test.c);
|
||||
|
||||
exprtk::expression<T> expression;
|
||||
expression.register_symbol_table(symbol_table);
|
||||
|
@ -1268,6 +1277,7 @@ inline bool run_test08()
|
|||
"(3min(x,y))==(3*min(x,y))",
|
||||
"(sin(x)y)==(sin(x)*y)",
|
||||
"(sin(x)cos(y)+1)==(sin(x)*cos(y)+1)",
|
||||
"(sgn(sin(x))cos(sgn(y))+1)==(sgn(sin(x))*cos(sgn(y))+1)",
|
||||
"equal($f00(x,y,z),((x+y)/z))",
|
||||
"equal($f01(x,y,z),((x+y)*z))",
|
||||
"equal($f02(x,y,z),((x-y)/z))",
|
||||
|
@ -1828,6 +1838,63 @@ inline bool run_test10()
|
|||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool run_test11()
|
||||
{
|
||||
typedef exprtk::expression<T> expression_t;
|
||||
std::string expression_string = "(x + y) / 3";
|
||||
|
||||
T x = T(1.0);
|
||||
T y = T(2.0);
|
||||
|
||||
exprtk::symbol_table<T> symbol_table;
|
||||
symbol_table.add_variable("x",x);
|
||||
symbol_table.add_variable("y",y);
|
||||
|
||||
expression_t expression;
|
||||
expression.register_symbol_table(symbol_table);
|
||||
|
||||
static const std::size_t rounds = 100000;
|
||||
|
||||
for (std::size_t i = 0; i < rounds; ++i)
|
||||
{
|
||||
{
|
||||
exprtk::parser<T> parser;
|
||||
if (!parser.compile(expression_string,expression))
|
||||
{
|
||||
std::cout << "run_test11() - Error: " << parser.error() << "\tExpression: " << expression_string << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (not_equal<T>(expression.value(),(x + y)/T(3.0),0.000001))
|
||||
{
|
||||
printf("run_test11() - Error in evaluation!(1)\n");
|
||||
return false;
|
||||
}
|
||||
expression.release();
|
||||
T result2 = expression.value();
|
||||
if (result2 == result2)
|
||||
{
|
||||
printf("run_test11() - Error in evaluation!(2)\n");
|
||||
return false;
|
||||
}
|
||||
{
|
||||
exprtk::parser<T> parser;
|
||||
if (!parser.compile(expression_string,expression))
|
||||
{
|
||||
std::cout << "run_test11() - Error: " << parser.error() << "\tExpression: " << expression_string << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (not_equal<T>(expression.value(),(x + y)/T(3.0),0.000001))
|
||||
{
|
||||
printf("run_test11() - Error in evaluation!(3)\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
return (
|
||||
|
@ -1841,7 +1908,8 @@ int main()
|
|||
run_test07<double>() &&
|
||||
run_test08<double>() &&
|
||||
run_test09<double>() &&
|
||||
run_test10<double>()
|
||||
run_test10<double>() &&
|
||||
run_test11<double>()
|
||||
)
|
||||
? 0 : 1;
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ http://www.opensource.org/licenses/cpl1.0.php
|
|||
All updates and the most recent version of the C++ Mathematical
|
||||
Expression Library can be found at:
|
||||
(1) http://www.partow.net/programming/exprtk/index.html
|
||||
|
||||
(2) svn checkout http://exprtk.googlecode.com/svn/ exprtk
|
||||
|
||||
[INSTALLATION]
|
||||
(1) exprtk.hpp should be placed in a project or system include path
|
||||
|
|
Loading…
Reference in New Issue