C++ Mathematical Expression Library (ExprTk) http://www.partow.net/programming/exprtk/index.html

This commit is contained in:
Arash Partow 2014-01-22 08:13:37 +11:00
parent e3d51a3222
commit e98df89433
3 changed files with 655 additions and 344 deletions

View File

@ -14306,7 +14306,16 @@ namespace exprtk
binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
details::free_node(*(expr_gen.node_allocator_),branch[0]); details::free_node(*(expr_gen.node_allocator_),branch[0]);
expression_node_ptr result = error_node(); expression_node_ptr result = error_node();
if (synthesize_sf3ext_expression::template compile<vtype,vtype,vtype>(expr_gen,id(expr_gen,o0,o1),v0,v1,v2,result))
// (v0 / v1) / v2 --> (vovov) v0 / (v1 * v2)
if ((details::e_div == o0) && (details::e_div == o1))
{
const bool synthesis_result =
synthesize_sf3ext_expression::
template compile<vtype,vtype,vtype>(expr_gen,"t/(t*t)",v0,v1,v2,result);
return (synthesis_result) ? result : error_node();
}
else if (synthesize_sf3ext_expression::template compile<vtype,vtype,vtype>(expr_gen,id(expr_gen,o0,o1),v0,v1,v2,result))
return result; return result;
else if (!expr_gen.valid_operator(o0,f0)) else if (!expr_gen.valid_operator(o0,f0))
return error_node(); return error_node();
@ -14342,7 +14351,16 @@ namespace exprtk
binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
details::free_node(*(expr_gen.node_allocator_),branch[1]); details::free_node(*(expr_gen.node_allocator_),branch[1]);
expression_node_ptr result = error_node(); expression_node_ptr result = error_node();
if (synthesize_sf3ext_expression::template compile<vtype,vtype,vtype>(expr_gen,id(expr_gen,o0,o1),v0,v1,v2,result))
// v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1
if ((details::e_div == o0) && (details::e_div == o1))
{
const bool synthesis_result =
synthesize_sf3ext_expression::
template compile<vtype,vtype,vtype>(expr_gen,"(t*t)/t",v0,v2,v1,result);
return (synthesis_result) ? result : error_node();
}
else if (synthesize_sf3ext_expression::template compile<vtype,vtype,vtype>(expr_gen,id(expr_gen,o0,o1),v0,v1,v2,result))
return result; return result;
else if (!expr_gen.valid_operator(o0,f0)) else if (!expr_gen.valid_operator(o0,f0))
return error_node(); return error_node();
@ -14379,7 +14397,16 @@ namespace exprtk
details::free_node(*(expr_gen.node_allocator_),branch[0]); details::free_node(*(expr_gen.node_allocator_),branch[0]);
details::free_node(*(expr_gen.node_allocator_),branch[1]); details::free_node(*(expr_gen.node_allocator_),branch[1]);
expression_node_ptr result = error_node(); expression_node_ptr result = error_node();
if (synthesize_sf3ext_expression::template compile<vtype,vtype,ctype>(expr_gen,id(expr_gen,o0,o1),v0,v1,c,result))
// (v0 / v1) / c --> (vovoc) v0 / (v1 * c)
if ((details::e_div == o0) && (details::e_div == o1))
{
const bool synthesis_result =
synthesize_sf3ext_expression::
template compile<vtype,vtype,ctype>(expr_gen,"t/(t*t)",v0,v1,c,result);
return (synthesis_result) ? result : error_node();
}
else if (synthesize_sf3ext_expression::template compile<vtype,vtype,ctype>(expr_gen,id(expr_gen,o0,o1),v0,v1,c,result))
return result; return result;
else if (!expr_gen.valid_operator(o0,f0)) else if (!expr_gen.valid_operator(o0,f0))
return error_node(); return error_node();
@ -14415,7 +14442,16 @@ namespace exprtk
binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
details::free_node(*(expr_gen.node_allocator_),branch[1]); details::free_node(*(expr_gen.node_allocator_),branch[1]);
expression_node_ptr result = error_node(); expression_node_ptr result = error_node();
if (synthesize_sf3ext_expression::template compile<vtype,vtype,ctype>(expr_gen,id(expr_gen,o0,o1),v0,v1,c,result))
// v0 / (v1 / c) --> (vocov) (v0 * c) / v1
if ((details::e_div == o0) && (details::e_div == o1))
{
const bool synthesis_result =
synthesize_sf3ext_expression::
template compile<vtype,ctype,vtype>(expr_gen,"(t*t)/t",v0,c,v1,result);
return (synthesis_result) ? result : error_node();
}
else if (synthesize_sf3ext_expression::template compile<vtype,vtype,ctype>(expr_gen,id(expr_gen,o0,o1),v0,v1,c,result))
return result; return result;
else if (!expr_gen.valid_operator(o0,f0)) else if (!expr_gen.valid_operator(o0,f0))
return error_node(); return error_node();
@ -14451,7 +14487,16 @@ namespace exprtk
binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
details::free_node(*(expr_gen.node_allocator_),branch[0]); details::free_node(*(expr_gen.node_allocator_),branch[0]);
expression_node_ptr result = error_node(); expression_node_ptr result = error_node();
if (synthesize_sf3ext_expression::template compile<vtype,ctype,vtype>(expr_gen,id(expr_gen,o0,o1),v0,c,v1,result))
// (v0 / c) / v1 --> (vovoc) v0 / (v1 * c)
if ((details::e_div == o0) && (details::e_div == o1))
{
const bool synthesis_result =
synthesize_sf3ext_expression::
template compile<vtype,vtype,ctype>(expr_gen,"t/(t*t)",v0,v1,c,result);
return (synthesis_result) ? result : error_node();
}
else if (synthesize_sf3ext_expression::template compile<vtype,ctype,vtype>(expr_gen,id(expr_gen,o0,o1),v0,c,v1,result))
return result; return result;
else if (!expr_gen.valid_operator(o0,f0)) else if (!expr_gen.valid_operator(o0,f0))
return error_node(); return error_node();
@ -14487,7 +14532,16 @@ namespace exprtk
binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
details::free_node(*(expr_gen.node_allocator_),branch[1]); details::free_node(*(expr_gen.node_allocator_),branch[1]);
expression_node_ptr result = error_node(); expression_node_ptr result = error_node();
if (synthesize_sf3ext_expression::template compile<vtype,ctype,vtype>(expr_gen,id(expr_gen,o0,o1),v0,c,v1,result))
// v0 / (c / v1) --> (vovoc) (v0 * v1) / c
if ((details::e_div == o0) && (details::e_div == o1))
{
const bool synthesis_result =
synthesize_sf3ext_expression::
template compile<vtype,vtype,ctype>(expr_gen,"(t*t)/t",v0,v1,c,result);
return (synthesis_result) ? result : error_node();
}
else if (synthesize_sf3ext_expression::template compile<vtype,ctype,vtype>(expr_gen,id(expr_gen,o0,o1),v0,c,v1,result))
return result; return result;
else if (!expr_gen.valid_operator(o0,f0)) else if (!expr_gen.valid_operator(o0,f0))
return error_node(); return error_node();
@ -14523,7 +14577,16 @@ namespace exprtk
binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
details::free_node(*(expr_gen.node_allocator_),branch[0]); details::free_node(*(expr_gen.node_allocator_),branch[0]);
expression_node_ptr result = error_node(); expression_node_ptr result = error_node();
if (synthesize_sf3ext_expression::template compile<ctype,vtype,vtype>(expr_gen,id(expr_gen,o0,o1),c,v0,v1,result))
// (c / v0) / v1 --> (covov) c / (v0 * v1)
if ((details::e_div == o0) && (details::e_div == o1))
{
const bool synthesis_result =
synthesize_sf3ext_expression::
template compile<ctype,vtype,vtype>(expr_gen,"t/(t*t)",c,v0,v1,result);
return (synthesis_result) ? result : error_node();
}
else if (synthesize_sf3ext_expression::template compile<ctype,vtype,vtype>(expr_gen,id(expr_gen,o0,o1),c,v0,v1,result))
return result; return result;
else if (!expr_gen.valid_operator(o0,f0)) else if (!expr_gen.valid_operator(o0,f0))
return error_node(); return error_node();
@ -14560,7 +14623,16 @@ namespace exprtk
details::free_node(*(expr_gen.node_allocator_),branch[0]); details::free_node(*(expr_gen.node_allocator_),branch[0]);
details::free_node(*(expr_gen.node_allocator_),branch[1]); details::free_node(*(expr_gen.node_allocator_),branch[1]);
expression_node_ptr result = error_node(); expression_node_ptr result = error_node();
if (synthesize_sf3ext_expression::template compile<ctype,vtype,vtype>(expr_gen,id(expr_gen,o0,o1),c,v0,v1,result))
// c / (v0 / v1) --> (covov) (c * v1) / v0
if ((details::e_div == o0) && (details::e_div == o1))
{
const bool synthesis_result =
synthesize_sf3ext_expression::
template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",c,v1,v0,result);
return (synthesis_result) ? result : error_node();
}
else if (synthesize_sf3ext_expression::template compile<ctype,vtype,vtype>(expr_gen,id(expr_gen,o0,o1),c,v0,v1,result))
return result; return result;
else if (!expr_gen.valid_operator(o0,f0)) else if (!expr_gen.valid_operator(o0,f0))
return error_node(); return error_node();
@ -15235,6 +15307,38 @@ namespace exprtk
template compile<ctype,vtype,vtype>(expr_gen,"(t*t)*t",(c0 * c1),v0,v1,result); template compile<ctype,vtype,vtype>(expr_gen,"(t*t)*t",(c0 * c1),v0,v1,result);
return (synthesis_result) ? result : error_node(); return (synthesis_result) ? result : error_node();
} }
// (c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1)
else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
{
const bool synthesis_result =
synthesize_sf3ext_expression::
template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",(c0 / c1),v0,v1,result);
return (synthesis_result) ? result : error_node();
}
// (c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1)
else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
{
const bool synthesis_result =
synthesize_sf3ext_expression::
template compile<ctype,vtype,vtype>(expr_gen,"t/(t*t)",(c0 * c1),v0,v1,result);
return (synthesis_result) ? result : error_node();
}
// (c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)
else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
{
const bool synthesis_result =
synthesize_sf3ext_expression::
template compile<ctype,vtype,vtype>(expr_gen,"t*(t*t)",(c0 / c1),v0,v1,result);
return (synthesis_result) ? result : error_node();
}
// (c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1)
else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
{
const bool synthesis_result =
synthesize_sf3ext_expression::
template compile<ctype,vtype,vtype>(expr_gen,"t/(t*t)",(c0 / c1),v0,v1,result);
return (synthesis_result) ? result : error_node();
}
else if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,c1,v1,result)) else if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,c1,v1,result))
return result; return result;
else if (!expr_gen.valid_operator(o0,f0)) else if (!expr_gen.valid_operator(o0,f0))
@ -15307,7 +15411,7 @@ namespace exprtk
template compile<ctype,vtype,vtype>(expr_gen,"(t+t)-t",(c1 - c0),v0,v1,result); template compile<ctype,vtype,vtype>(expr_gen,"(t+t)-t",(c1 - c0),v0,v1,result);
return (synthesis_result) ? result : error_node(); return (synthesis_result) ? result : error_node();
} }
// (c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1 // (v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1
else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2)) else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
{ {
const bool synthesis_result = const bool synthesis_result =
@ -15315,6 +15419,38 @@ namespace exprtk
template compile<ctype,vtype,vtype>(expr_gen,"(t*t)*t",(c0 * c1),v0,v1,result); template compile<ctype,vtype,vtype>(expr_gen,"(t*t)*t",(c0 * c1),v0,v1,result);
return (synthesis_result) ? result : error_node(); return (synthesis_result) ? result : error_node();
} }
// (v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)
else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
{
const bool synthesis_result =
synthesize_sf3ext_expression::
template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",(c0 / c1),v0,v1,result);
return (synthesis_result) ? result : error_node();
}
// (v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1
else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
{
const bool synthesis_result =
synthesize_sf3ext_expression::
template compile<ctype,vtype,vtype>(expr_gen,"(t*t)*t",Type(1) / (c0 * c1),v0,v1,result);
return (synthesis_result) ? result : error_node();
}
// (v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)
else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
{
const bool synthesis_result =
synthesize_sf3ext_expression::
template compile<ctype,vtype,vtype>(expr_gen,"t*(t/t)",(c0 * c1),v0,v1,result);
return (synthesis_result) ? result : error_node();
}
// (v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1
else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
{
const bool synthesis_result =
synthesize_sf3ext_expression::
template compile<ctype,vtype,vtype>(expr_gen,"t*(t/t)",Type(1) / (c0 * c1),v0,v1,result);
return (synthesis_result) ? result : error_node();
}
else if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,v1,c1,result)) else if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,v1,c1,result))
return result; return result;
else if (!expr_gen.valid_operator(o0,f0)) else if (!expr_gen.valid_operator(o0,f0))
@ -15387,7 +15523,7 @@ namespace exprtk
template compile<ctype,vtype,vtype>(expr_gen,"t-(t+t)",(c0 + c1),v0,v1,result); template compile<ctype,vtype,vtype>(expr_gen,"t-(t+t)",(c0 + c1),v0,v1,result);
return (synthesis_result) ? result : error_node(); return (synthesis_result) ? result : error_node();
} }
// (c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1 // (c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1
else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2)) else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
{ {
const bool synthesis_result = const bool synthesis_result =
@ -15395,6 +15531,38 @@ namespace exprtk
template compile<ctype,vtype,vtype>(expr_gen,"(t*t)*t",(c0 * c1),v0,v1,result); template compile<ctype,vtype,vtype>(expr_gen,"(t*t)*t",(c0 * c1),v0,v1,result);
return (synthesis_result) ? result : error_node(); return (synthesis_result) ? result : error_node();
} }
// (c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)
else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
{
const bool synthesis_result =
synthesize_sf3ext_expression::
template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",(c0 / c1),v0,v1,result);
return (synthesis_result) ? result : error_node();
}
// (c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0)
else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
{
const bool synthesis_result =
synthesize_sf3ext_expression::
template compile<ctype,vtype,vtype>(expr_gen,"t*(t/t)",(c0 / c1),v1,v0,result);
return (synthesis_result) ? result : error_node();
}
// (c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)
else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
{
const bool synthesis_result =
synthesize_sf3ext_expression::
template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",(c0 * c1),v0,v1,result);
return (synthesis_result) ? result : error_node();
}
// (c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1)
else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
{
const bool synthesis_result =
synthesize_sf3ext_expression::
template compile<ctype,vtype,vtype>(expr_gen,"t/(t*t)",(c0 / c1),v0,v1,result);
return (synthesis_result) ? result : error_node();
}
else if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,v1,c1,result)) else if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,v1,c1,result))
return result; return result;
else if (!expr_gen.valid_operator(o0,f0)) else if (!expr_gen.valid_operator(o0,f0))
@ -15467,7 +15635,7 @@ namespace exprtk
template compile<vtype,vtype,ctype>(expr_gen,"(t+t)-t",v0,v1,(c1 + c0),result); template compile<vtype,vtype,ctype>(expr_gen,"(t+t)-t",v0,v1,(c1 + c0),result);
return (synthesis_result) ? result : error_node(); return (synthesis_result) ? result : error_node();
} }
// (c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1 // (v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1
else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2)) else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
{ {
const bool synthesis_result = const bool synthesis_result =
@ -15475,6 +15643,38 @@ namespace exprtk
template compile<ctype,vtype,vtype>(expr_gen,"(t*t)*t",(c0 * c1),v0,v1,result); template compile<ctype,vtype,vtype>(expr_gen,"(t*t)*t",(c0 * c1),v0,v1,result);
return (synthesis_result) ? result : error_node(); return (synthesis_result) ? result : error_node();
} }
// (v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1)
else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
{
const bool synthesis_result =
synthesize_sf3ext_expression::
template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",(c0 / c1),v0,v1,result);
return (synthesis_result) ? result : error_node();
}
// (v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1)
else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
{
const bool synthesis_result =
synthesize_sf3ext_expression::
template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",(c1 / c0),v0,v1,result);
return (synthesis_result) ? result : error_node();
}
// (v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)
else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
{
const bool synthesis_result =
synthesize_sf3ext_expression::
template compile<ctype,vtype,vtype>(expr_gen,"(t*t)*t",(c0 / c1),v0,v1,result);
return (synthesis_result) ? result : error_node();
}
// (v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1)
else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
{
const bool synthesis_result =
synthesize_sf3ext_expression::
template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",Type(1) / (c0 * c1),v0,v1,result);
return (synthesis_result) ? result : error_node();
}
else if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,c1,v1,result)) else if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,c1,v1,result))
return result; return result;
else if (!expr_gen.valid_operator(o0,f0)) else if (!expr_gen.valid_operator(o0,f0))

View File

@ -1137,8 +1137,27 @@ struct test_xy
T result; T result;
}; };
template <typename T>
struct test_xyz
{
test_xyz(std::string e, const T& v0, const T& v1, const T& v2, const T& r)
: expr(e),
x(v0),
y(v1),
z(v2),
result(r)
{}
std::string expr;
T x;
T y;
T z;
T result;
};
template <typename T> template <typename T>
inline bool run_test01() inline bool run_test01()
{
{ {
static const test_xy<T> test_list[] = static const test_xy<T> test_list[] =
{ {
@ -1349,6 +1368,22 @@ inline bool run_test01()
test_xy<T>("((x + 2) - (3 + y))",T(7.0),T(9.0),T(((7.0 + 2.0) - (3.0 + 9.0)))), test_xy<T>("((x + 2) - (3 + y))",T(7.0),T(9.0),T(((7.0 + 2.0) - (3.0 + 9.0)))),
test_xy<T>("((x - 2) - (3 - y))",T(7.0),T(9.0),T(((7.0 - 2.0) - (3.0 - 9.0)))), test_xy<T>("((x - 2) - (3 - y))",T(7.0),T(9.0),T(((7.0 - 2.0) - (3.0 - 9.0)))),
test_xy<T>("((2 * x) * (3 * y))",T(7.0),T(9.0),T(((2.0 * 7.0) * (3.0 * 9.0)))), test_xy<T>("((2 * x) * (3 * y))",T(7.0),T(9.0),T(((2.0 * 7.0) * (3.0 * 9.0)))),
test_xy<T>("((2 * x) / (3 * y))",T(7.0),T(9.0),T(((2.0 * 7.0) / (3.0 * 9.0)))),
test_xy<T>("((2 / x) * (3 / y))",T(7.0),T(9.0),T(((2.0 / 7.0) * (3.0 / 9.0)))),
test_xy<T>("((2 * x) / (3 / y))",T(7.0),T(9.0),T(((2.0 * 7.0) / (3.0 / 9.0)))),
test_xy<T>("((2 / x) / (3 * y))",T(7.0),T(9.0),T(((2.0 / 7.0) / (3.0 * 9.0)))),
test_xy<T>("((x * 2) / (y * 3))",T(7.0),T(9.0),T(((7.0 * 2.0) / (9.0 * 3.0)))),
test_xy<T>("((x / 2) * (y / 3))",T(7.0),T(9.0),T(((7.0 / 2.0) * (9.0 / 3.0)))),
test_xy<T>("((x * 2) / (y / 3))",T(7.0),T(9.0),T(((7.0 * 2.0) / (9.0 / 3.0)))),
test_xy<T>("((x / 2) / (y * 3))",T(7.0),T(9.0),T(((7.0 / 2.0) / (9.0 * 3.0)))),
test_xy<T>("((2 * x) / (y * 3))",T(7.0),T(9.0),T(((2.0 * 7.0) / (9.0 * 3.0)))),
test_xy<T>("((2 / x) * (y / 3))",T(7.0),T(9.0),T(((2.0 / 7.0) * (9.0 / 3.0)))),
test_xy<T>("((2 * x) / (y / 3))",T(7.0),T(9.0),T(((2.0 * 7.0) / (9.0 / 3.0)))),
test_xy<T>("((2 / x) / (y * 3))",T(7.0),T(9.0),T(((2.0 / 7.0) / (9.0 * 3.0)))),
test_xy<T>("((x * 2) / (3 * y))",T(7.0),T(9.0),T(((7.0 * 2.0) / (3.0 * 9.0)))),
test_xy<T>("((x / 2) * (3 / y))",T(7.0),T(9.0),T(((7.0 / 2.0) * (3.0 / 9.0)))),
test_xy<T>("((x * 2) / (3 / y))",T(7.0),T(9.0),T(((7.0 * 2.0) / (3.0 / 9.0)))),
test_xy<T>("((x / 2) / (3 * y))",T(7.0),T(9.0),T(((7.0 / 2.0) / (3.0 * 9.0)))),
test_xy<T>("0 * (abs (x) + acos (y) + asin (x) + atan (y))",T(1.0),T(1.0),T(0.0)), test_xy<T>("0 * (abs (x) + acos (y) + asin (x) + atan (y))",T(1.0),T(1.0),T(0.0)),
test_xy<T>("0 * (ceil (x) + cos (y) + cosh (x) + exp (y))",T(1.0),T(1.0),T(0.0)), test_xy<T>("0 * (ceil (x) + cos (y) + cosh (x) + exp (y))",T(1.0),T(1.0),T(0.0)),
test_xy<T>("0 * (floor(x) + log (y) + log10(x) + round(y))",T(1.0),T(1.0),T(0.0)), test_xy<T>("0 * (floor(x) + log (y) + log10(x) + round(y))",T(1.0),T(1.0),T(0.0)),
@ -1421,6 +1456,70 @@ inline bool run_test01()
return false; return false;
} }
} }
}
{
static const test_xyz<T> test_list[] =
{
test_xyz<T>("((x / y) / z )",T(7.0),T(9.0),T(3.0),T(((7.0 / 9.0) / 3.0 ))),
test_xyz<T>("((x / y) / 2 )",T(7.0),T(9.0),T(3.0),T(((7.0 / 9.0) / 2.0 ))),
test_xyz<T>("((x / 2) / y )",T(7.0),T(9.0),T(3.0),T(((7.0 / 2.0) / 9.0 ))),
test_xyz<T>("((2 / x) / y )",T(7.0),T(9.0),T(3.0),T(((2.0 / 7.0) / 9.0 ))),
test_xyz<T>("( x / (y / z))",T(7.0),T(9.0),T(3.0),T(( 7.0 / (9.0 / 3.0)))),
test_xyz<T>("( x / (y / 2))",T(7.0),T(9.0),T(3.0),T(( 7.0 / (9.0 / 2.0)))),
test_xyz<T>("( x / (2 / y))",T(7.0),T(9.0),T(3.0),T(( 7.0 / (2.0 / 9.0)))),
test_xyz<T>("( 2 / (x / y))",T(7.0),T(9.0),T(3.0),T(( 2.0 / (7.0 / 9.0))))
};
static const std::size_t test_list_size = sizeof(test_list) / sizeof(test_xyz<T>);
const std::size_t rounds = 60;
for (std::size_t r = 0; r < rounds; ++r)
{
bool loop_result = true;
for (std::size_t i = 0; i < test_list_size; ++i)
{
test_xyz<T>& test = const_cast<test_xyz<T>&>(test_list[i]);
exprtk::symbol_table<T> symbol_table;
symbol_table.add_variable("x",test.x);
symbol_table.add_variable("y",test.y);
symbol_table.add_variable("z",test.z);
exprtk::expression<T> expression;
expression.register_symbol_table(symbol_table);
{
exprtk::parser<T> parser;
if (!parser.compile(test.expr,expression))
{
printf("run_test01() - Error: %s Expression: %s\n",
parser.error().c_str(),
test.expr.c_str());
loop_result = false;
continue;
}
}
T result = expression.value();
if (not_equal(result,test.result))
{
printf("run_test01() - Computation Error: Expression: [%s]\tExpected: %19.15f\tResult: %19.15f\n",
test.expr.c_str(),
test.result,
result);
loop_result = false;
}
}
if (!loop_result)
{
return false;
}
}
}
return true; return true;
} }

View File

@ -415,9 +415,9 @@ There are three primary components, that are specialized upon a given
numeric type, which make up the core of ExprTk. The components are as numeric type, which make up the core of ExprTk. The components are as
follows: follows:
1. Symbol Table exprtk::symbol_table<T> 1. Symbol Table exprtk::symbol_table<NumericType>
2. Expression exprtk::expression<T> 2. Expression exprtk::expression<NumericType>
3. Parser exprtk::parser<T> 3. Parser exprtk::parser<NumericType>
(1) Symbol Table (1) Symbol Table
@ -447,13 +447,13 @@ Expression: z := (x + y^-2.345) * sin(pi / min(w - 7.3,v))
/ \ ___/ \___ / \ ___/ \___
Variable(x) [Power] / \ Variable(x) [Power] / \
______/ \______ Constant(pi) [Binary-Func(min)] ______/ \______ Constant(pi) [Binary-Func(min)]
/ \ ___/ \___ / \ ____/ \____
Variable(y) [Negate] / \ Variable(y) [Negate] / \
| / Variable(v) | / Variable(v)
Constant(2.345) / Constant(2.345) /
/ /
[Subtract] [Subtract]
____/ \___ ____/ \____
/ \ / \
Variable(w) Constant(7.3) Variable(w) Constant(7.3)
@ -484,58 +484,58 @@ correctly optimize such expressions for a given architecture.
+-------------+-------------+ +--------------+------------------+ +-------------+-------------+ +--------------+------------------+
| Prototype | Operation | | Prototype | Operation | | Prototype | Operation | | Prototype | Operation |
+-------------+-------------+ +--------------+------------------+ +-------------+-------------+ +--------------+------------------+
$f00(x,y,z) | (x + y) / z $f47(x,y,z,w) | x + ((y + z) / w) $f00(x,y,z) | (x + y) / z $f48(x,y,z,w) | x + ((y + z) / w)
$f01(x,y,z) | (x + y) * z $f48(x,y,z,w) | x + ((y + z) * w) $f01(x,y,z) | (x + y) * z $f49(x,y,z,w) | x + ((y + z) * w)
$f02(x,y,z) | (x + y) - z $f49(x,y,z,w) | x + ((y - z) / w) $f02(x,y,z) | (x + y) - z $f50(x,y,z,w) | x + ((y - z) / w)
$f03(x,y,z) | (x + y) + z $f50(x,y,z,w) | x + ((y - z) * w) $f03(x,y,z) | (x + y) + z $f51(x,y,z,w) | x + ((y - z) * w)
$f04(x,y,z) | (x - y) / z $f51(x,y,z,w) | x + ((y * z) / w) $f04(x,y,z) | (x - y) + z $f52(x,y,z,w) | x + ((y * z) / w)
$f05(x,y,z) | (x - y) * z $f52(x,y,z,w) | x + ((y * z) * w) $f05(x,y,z) | (x - y) / z $f53(x,y,z,w) | x + ((y * z) * w)
$f06(x,y,z) | (x * y) + z $f53(x,y,z,w) | x + ((y / z) + w) $f06(x,y,z) | (x - y) * z $f54(x,y,z,w) | x + ((y / z) + w)
$f07(x,y,z) | (x * y) - z $f54(x,y,z,w) | x + ((y / z) / w) $f07(x,y,z) | (x * y) + z $f55(x,y,z,w) | x + ((y / z) / w)
$f08(x,y,z) | (x * y) / z $f55(x,y,z,w) | x + ((y / z) * w) $f08(x,y,z) | (x * y) - z $f56(x,y,z,w) | x + ((y / z) * w)
$f09(x,y,z) | (x * y) * z $f56(x,y,z,w) | x - ((y + z) / w) $f09(x,y,z) | (x * y) / z $f57(x,y,z,w) | x - ((y + z) / w)
$f10(x,y,z) | (x / y) + z $f57(x,y,z,w) | x - ((y + z) * w) $f10(x,y,z) | (x * y) * z $f58(x,y,z,w) | x - ((y + z) * w)
$f11(x,y,z) | (x / y) - z $f58(x,y,z,w) | x - ((y - z) / w) $f11(x,y,z) | (x / y) + z $f59(x,y,z,w) | x - ((y - z) / w)
$f12(x,y,z) | (x / y) / z $f59(x,y,z,w) | x - ((y - z) * w) $f12(x,y,z) | (x / y) - z $f60(x,y,z,w) | x - ((y - z) * w)
$f13(x,y,z) | (x / y) * z $f60(x,y,z,w) | x - ((y * z) / w) $f13(x,y,z) | (x / y) / z $f61(x,y,z,w) | x - ((y * z) / w)
$f14(x,y,z) | x / (y + z) $f61(x,y,z,w) | x - ((y * z) * w) $f14(x,y,z) | (x / y) * z $f62(x,y,z,w) | x - ((y * z) * w)
$f15(x,y,z) | x / (y - z) $f62(x,y,z,w) | x - ((y / z) / w) $f15(x,y,z) | x / (y + z) $f63(x,y,z,w) | x - ((y / z) / w)
$f16(x,y,z) | x / (y * z) $f63(x,y,z,w) | x - ((y / z) * w) $f16(x,y,z) | x / (y - z) $f64(x,y,z,w) | x - ((y / z) * w)
$f17(x,y,z) | x / (y / z) $f64(x,y,z,w) | ((x + y) * z) - w $f17(x,y,z) | x / (y * z) $f65(x,y,z,w) | ((x + y) * z) - w
$f18(x,y,z) | x * (y + z) $f65(x,y,z,w) | ((x - y) * z) - w $f18(x,y,z) | x / (y / z) $f66(x,y,z,w) | ((x - y) * z) - w
$f19(x,y,z) | x * (y - z) $f66(x,y,z,w) | ((x * y) * z) - w $f19(x,y,z) | x * (y + z) $f67(x,y,z,w) | ((x * y) * z) - w
$f20(x,y,z) | x * (y * z) $f67(x,y,z,w) | ((x / y) * z) - w $f20(x,y,z) | x * (y - z) $f68(x,y,z,w) | ((x / y) * z) - w
$f21(x,y,z) | x * (y / z) $f68(x,y,z,w) | ((x + y) / z) - w $f21(x,y,z) | x * (y * z) $f69(x,y,z,w) | ((x + y) / z) - w
$f22(x,y,z) | x - (y + z) $f69(x,y,z,w) | ((x - y) / z) - w $f22(x,y,z) | x * (y / z) $f70(x,y,z,w) | ((x - y) / z) - w
$f23(x,y,z) | x - (y - z) $f70(x,y,z,w) | ((x * y) / z) - w $f23(x,y,z) | x - (y + z) $f71(x,y,z,w) | ((x * y) / z) - w
$f24(x,y,z) | x - (y / z) $f71(x,y,z,w) | ((x / y) / z) - w $f24(x,y,z) | x - (y - z) $f72(x,y,z,w) | ((x / y) / z) - w
$f25(x,y,z) | x - (y * z) $f72(x,y,z,w) | (x * y) + (z * w) $f25(x,y,z) | x - (y / z) $f73(x,y,z,w) | (x * y) + (z * w)
$f26(x,y,z) | x + (y * z) $f73(x,y,z,w) | (x * y) - (z * w) $f26(x,y,z) | x - (y * z) $f74(x,y,z,w) | (x * y) - (z * w)
$f27(x,y,z) | x + (y / z) $f74(x,y,z,w) | (x * y) + (z / w) $f27(x,y,z) | x + (y * z) $f75(x,y,z,w) | (x * y) + (z / w)
$f28(x,y,z) | x + (y + z) $f75(x,y,z,w) | (x * y) - (z / w) $f28(x,y,z) | x + (y / z) $f76(x,y,z,w) | (x * y) - (z / w)
$f29(x,y,z) | x + (y - z) $f76(x,y,z,w) | (x / y) + (z / w) $f29(x,y,z) | x + (y + z) $f77(x,y,z,w) | (x / y) + (z / w)
$f30(x,y,z) | x * y^2 + z $f77(x,y,z,w) | (x / y) - (z / w) $f30(x,y,z) | x + (y - z) $f78(x,y,z,w) | (x / y) - (z / w)
$f31(x,y,z) | x * y^3 + z $f78(x,y,z,w) | (x / y) - (z * w) $f31(x,y,z) | x * y^2 + z $f79(x,y,z,w) | (x / y) - (z * w)
$f32(x,y,z) | x * y^4 + z $f79(x,y,z,w) | x / (y + (z * w)) $f32(x,y,z) | x * y^3 + z $f80(x,y,z,w) | x / (y + (z * w))
$f33(x,y,z) | x * y^5 + z $f80(x,y,z,w) | x / (y - (z * w)) $f33(x,y,z) | x * y^4 + z $f81(x,y,z,w) | x / (y - (z * w))
$f34(x,y,z) | x * y^6 + z $f81(x,y,z,w) | x * (y + (z * w)) $f34(x,y,z) | x * y^5 + z $f82(x,y,z,w) | x * (y + (z * w))
$f35(x,y,z) | x * y^7 + z $f82(x,y,z,w) | x * (y - (z * w)) $f35(x,y,z) | x * y^6 + z $f83(x,y,z,w) | x * (y - (z * w))
$f36(x,y,z) | x * y^8 + z $f83(x,y,z,w) | x*y^2 + z*w^2 $f36(x,y,z) | x * y^7 + z $f84(x,y,z,w) | x*y^2 + z*w^2
$f37(x,y,z) | x * y^9 + z $f84(x,y,z,w) | x*y^3 + z*w^3 $f37(x,y,z) | x * y^8 + z $f85(x,y,z,w) | x*y^3 + z*w^3
$f38(x,y,z) | x * log(y)+z $f85(x,y,z,w) | x*y^4 + z*w^4 $f38(x,y,z) | x * y^9 + z $f86(x,y,z,w) | x*y^4 + z*w^4
$f39(x,y,z) | x * log(y)-z $f86(x,y,z,w) | x*y^5 + z*w^5 $f39(x,y,z) | x * log(y)+z $f87(x,y,z,w) | x*y^5 + z*w^5
$f40(x,y,z) | x * log10(y)+z $f87(x,y,z,w) | x*y^6 + z*w^6 $f40(x,y,z) | x * log(y)-z $f88(x,y,z,w) | x*y^6 + z*w^6
$f41(x,y,z) | x * log10(y)-z $f88(x,y,z,w) | x*y^7 + z*w^7 $f41(x,y,z) | x * log10(y)+z $f89(x,y,z,w) | x*y^7 + z*w^7
$f42(x,y,z) | x * sin(y)+z $f89(x,y,z,w) | x*y^8 + z*w^8 $f42(x,y,z) | x * log10(y)-z $f90(x,y,z,w) | x*y^8 + z*w^8
$f43(x,y,z) | x * sin(y)-z $f90(x,y,z,w) | x*y^9 + z*w^9 $f43(x,y,z) | x * sin(y)+z $f91(x,y,z,w) | x*y^9 + z*w^9
$f44(x,y,z) | x * cos(y)+z $f91(x,y,z,w) | (x and y) ? z : w $f44(x,y,z) | x * sin(y)-z $f92(x,y,z,w) | (x and y) ? z : w
$f45(x,y,z) | x * cos(y)-z $f92(x,y,z,w) | (x or y) ? z : w $f45(x,y,z) | x * cos(y)+z $f93(x,y,z,w) | (x or y) ? z : w
$f46(x,y,z) | x ? y : z $f93(x,y,z,w) | (x < y) ? z : w $f46(x,y,z) | x * cos(y)-z $f94(x,y,z,w) | (x < y) ? z : w
$f94(x,y,z,w) | (x <= y) ? z : w $f47(x,y,z) | x ? y : z $f95(x,y,z,w) | (x <= y) ? z : w
$f95(x,y,z,w) | (x > y) ? z : w $f96(x,y,z,w) | (x > y) ? z : w
$f96(x,y,z,w) | (x >= y) ? z : w $f97(x,y,z,w) | (x >= y) ? z : w
$f97(x,y,z,w) | (x == y) ? z : w $f98(x,y,z,w) | (x == y) ? z : w
$f98(x,y,z,w) | x * sin(y) + z * cos(w) $f99(x,y,z,w) | x * sin(y) + z * cos(w)
@ -604,14 +604,26 @@ correctly optimize such expressions for a given architecture.
(18) Recursive calls made from within composited functions will have (18) Recursive calls made from within composited functions will have
a stack size bound by the stack of the executing architecture. a stack size bound by the stack of the executing architecture.
(19) The following are examples of compliant floating point value (19) The entity relationship between symbol_table and an expression
is one-to-many. Hence the intended use case is to have a single
symbol table manage the variable and function requirements of
multiple expressions. An inappropriate approach would be to have
a unique symbol table for each unique expression.
(20) The common use-case for an expression is to have it compiled
only once and then subsequently have it evaluated multiple
times. An extremely inefficient approach would be to recompile
an expression from its string form every time it requires
evaluating.
(21) The following are examples of compliant floating point value
representations: representations:
(a) 12345 (b) -123.456 (a) 12345 (b) -123.456
(c) +123.456e+12 (d) 123.456E-12 (c) +123.456e+12 (d) 123.456E-12
(e) +012.045e+07 (f) .1234 (e) +012.045e+07 (f) .1234
(g) 123.456f (h) -321.654E+3L (g) 123.456f (h) -321.654E+3L
(20) Expressions may contain any of the following comment styles: (22) Expressions may contain any of the following comment styles:
1. // .... \n 1. // .... \n
2. # .... \n 2. # .... \n
3. /* .... */ 3. /* .... */