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

This commit is contained in:
Arash Partow 2012-04-21 09:15:01 +10:00
parent a0872d7a6d
commit a60b7646c1
2 changed files with 68 additions and 22 deletions

View File

@ -142,7 +142,7 @@ namespace exprtk
"floor", "for", "grad2deg", "hyp", "if", "ilike", "in", "inrange", "floor", "for", "grad2deg", "hyp", "if", "ilike", "in", "inrange",
"like", "log", "log10", "logn", "max", "min", "mod", "mul", "nand", "like", "log", "log10", "logn", "max", "min", "mod", "mul", "nand",
"nor", "not", "not_equal", "or", "rad2deg", "root", "round", "roundn", "nor", "not", "not_equal", "or", "rad2deg", "root", "round", "roundn",
"sec", "shl", "shr", "sin", "sinh", "sqrt", "sum", "tan", "tanh", "sec", "sgn", "shl", "shr", "sin", "sinh", "sqrt", "sum", "tan", "tanh",
"while", "xor" "while", "xor"
}; };
static const std::size_t reserved_symbols_size = sizeof(reserved_symbols) / sizeof(std::string); static const std::size_t reserved_symbols_size = sizeof(reserved_symbols) / sizeof(std::string);
@ -447,6 +447,22 @@ namespace exprtk
return v0 << v1; return v0 << v1;
} }
template <typename T>
inline T sgn_impl(const T& v, real_type_tag)
{
if (v > T(0.0)) return T(+1.0);
else if (v < T(0.0)) return T(-1.0);
else return T( 0.0);
}
template <typename T>
inline T sgn_impl(const T& v, int_type_tag)
{
if (v > T(0)) return T(+1);
else if (v < T(0)) return T(-1);
else return T( 0);
}
template <typename T> template <typename T>
inline T xor_impl(const T& v0, const T& v1, real_type_tag) inline T xor_impl(const T& v0, const T& v1, real_type_tag)
{ {
@ -546,6 +562,13 @@ namespace exprtk
return details::shl_impl(v0,v1,num_type); return details::shl_impl(v0,v1,num_type);
} }
template <typename T>
inline T sgn(const T& v)
{
typename details::number_type<T>::type num_type;
return details::sgn_impl(v,num_type);
}
template <typename T> template <typename T>
inline T xor_opr(const T& v0, const T& v1) inline T xor_opr(const T& v0, const T& v1)
{ {
@ -1344,6 +1367,7 @@ namespace exprtk
e_cot , e_cot ,
e_clamp , e_clamp ,
e_inrange, e_inrange,
e_sgn ,
e_r2d , e_r2d ,
e_d2r , e_d2r ,
e_d2g , e_d2g ,
@ -1437,6 +1461,7 @@ namespace exprtk
case e_d2g : return (arg * T(20/9)); case e_d2g : return (arg * T(20/9));
case e_g2d : return (arg * T(9/20)); case e_g2d : return (arg * T(9/20));
case e_not : return (arg != T(0) ? T(0) : T(1)); case e_not : return (arg != T(0) ? T(0) : T(1));
case e_sgn : return numeric::sgn(arg);
default : return std::numeric_limits<T>::quiet_NaN(); default : return std::numeric_limits<T>::quiet_NaN();
} }
} }
@ -1454,6 +1479,7 @@ namespace exprtk
case e_pos : return +arg; case e_pos : return +arg;
case e_sqrt : return std::sqrt (arg); case e_sqrt : return std::sqrt (arg);
case e_not : return !arg; case e_not : return !arg;
case e_sgn : return numeric::sgn(arg);
default : return std::numeric_limits<T>::quiet_NaN(); default : return std::numeric_limits<T>::quiet_NaN();
} }
} }
@ -3403,6 +3429,7 @@ namespace exprtk
operation_t( "deg2rad" , e_d2r , 1), operation_t( "deg2rad" , e_d2r , 1),
operation_t( "deg2grad" , e_d2g , 1), operation_t( "deg2grad" , e_d2g , 1),
operation_t( "grad2deg" , e_g2d , 1), operation_t( "grad2deg" , e_g2d , 1),
operation_t( "sgn" , e_sgn , 1),
operation_t( "not" , e_not , 1), operation_t( "not" , e_not , 1),
operation_t( "atan2", e_atan2 , 2), operation_t( "atan2", e_atan2 , 2),
operation_t( "min", e_min , 2), operation_t( "min", e_min , 2),
@ -5418,7 +5445,10 @@ namespace exprtk
return error_node(); return error_node();
else else
{ {
if (!all_nodes_valid(b)) //has the function call been completely optimized?
if (details::is_constant_node(result))
return result;
else if (!all_nodes_valid(b))
return error_node(); return error_node();
else if (N != f->param_count) else if (N != f->param_count)
return error_node(); return error_node();

View File

@ -600,6 +600,9 @@ static const test_t test_list[] =
test_t("clamp(-1,-1.5,+1.0) + clamp(-1,+1.5,+1.0)",0.0), test_t("clamp(-1,-1.5,+1.0) + clamp(-1,+1.5,+1.0)",0.0),
test_t("inrange(-2,1,+2) == ((-2 <= 1) and (1 <= +2))",1.0), test_t("inrange(-2,1,+2) == ((-2 <= 1) and (1 <= +2))",1.0),
test_t("inrange(-2,1,+2) == if(({-2 <= 1} and [1 <= +2]),1.0,0.0)",1.0), test_t("inrange(-2,1,+2) == if(({-2 <= 1} and [1 <= +2]),1.0,0.0)",1.0),
test_t("sgn( 0)", 0.0),
test_t("sgn(+3)",+1.0),
test_t("sgn(-3)",-1.0),
test_t("equal($f00(1.1,2.2,3.3),((1.1+2.2)/3.3))",1.0), test_t("equal($f00(1.1,2.2,3.3),((1.1+2.2)/3.3))",1.0),
test_t("equal($f01(1.1,2.2,3.3),((1.1+2.2)*3.3))",1.0), test_t("equal($f01(1.1,2.2,3.3),((1.1+2.2)*3.3))",1.0),
test_t("equal($f02(1.1,2.2,3.3),((1.1-2.2)/3.3))",1.0), test_t("equal($f02(1.1,2.2,3.3),((1.1-2.2)/3.3))",1.0),
@ -1365,16 +1368,26 @@ inline bool run_test09()
for (std::size_t i = 0; i < rounds; ++i) for (std::size_t i = 0; i < rounds; ++i)
{ {
typedef exprtk::expression<T> expression_t; typedef exprtk::expression<T> expression_t;
std::string expression_string = "myfunc0(sin(x*pi),y/2)+" std::string expression_string = "myfunc0(sin(x*pi),y/2)+myfunc1(sin(x*pi),y/2)+"
"myfunc1(sin(x*pi),y/2)+" "myfunc2(sin(x*pi),y/2)+myfunc3(sin(x*pi),y/2)+"
"myfunc2(sin(x*pi),y/2)+" "myfunc4(sin(x*pi),y/2)+myfunc5(sin(x*pi),y/2)+"
"myfunc3(sin(x*pi),y/2)+" "myfunc6(sin(x*pi),y/2)+myfunc7(sin(x*pi),y/2)+"
"myfunc4(sin(x*pi),y/2)+" "myfunc8(sin(x*pi),y/2)+myfunc9(sin(x*pi),y/2)+"
"myfunc5(sin(x*pi),y/2)+" "myfunc0(sin(1*pi),y/2)+myfunc1(sin(1*pi),y/2)+"
"myfunc6(sin(x*pi),y/2)+" "myfunc2(sin(1*pi),y/2)+myfunc3(sin(1*pi),y/2)+"
"myfunc7(sin(x*pi),y/2)+" "myfunc4(sin(1*pi),y/2)+myfunc5(sin(1*pi),y/2)+"
"myfunc8(sin(x*pi),y/2)+" "myfunc6(sin(1*pi),y/2)+myfunc7(sin(1*pi),y/2)+"
"myfunc9(sin(x*pi),y/2)"; "myfunc8(sin(1*pi),y/2)+myfunc9(sin(1*pi),y/2)+"
"myfunc0(sin(x*pi),2/2)+myfunc1(sin(x*pi),2/2)+"
"myfunc2(sin(x*pi),2/2)+myfunc3(sin(x*pi),2/2)+"
"myfunc4(sin(x*pi),2/2)+myfunc5(sin(x*pi),2/2)+"
"myfunc6(sin(x*pi),2/2)+myfunc7(sin(x*pi),2/2)+"
"myfunc8(sin(x*pi),2/2)+myfunc9(sin(x*pi),2/2)+"
"myfunc0(sin(1*pi),2/2)+myfunc1(sin(1*pi),2/2)+"
"myfunc2(sin(1*pi),2/2)+myfunc3(sin(1*pi),2/2)+"
"myfunc4(sin(1*pi),2/2)+myfunc5(sin(1*pi),2/2)+"
"myfunc6(sin(1*pi),2/2)+myfunc7(sin(1*pi),2/2)+"
"myfunc8(sin(1*pi),2/2)+myfunc9(sin(1*pi),2/2)";
T x = T(1.0); T x = T(1.0);
T y = T(2.0); T y = T(2.0);
@ -1408,16 +1421,19 @@ inline bool run_test09()
const T pi = T(3.14159265358979323846); const T pi = T(3.14159265358979323846);
T result = expression.value(); T result = expression.value();
T expected = mf(sin(x*pi),y/2.0) + T expected = T(4.0) *
mf(sin(x*pi),y/2.0) + (
mf(sin(x*pi),y/2.0) + mf(sin(x*pi),y/2.0) +
mf(sin(x*pi),y/2.0) + mf(sin(x*pi),y/2.0) +
mf(sin(x*pi),y/2.0) + mf(sin(x*pi),y/2.0) +
mf(sin(x*pi),y/2.0) + mf(sin(x*pi),y/2.0) +
mf(sin(x*pi),y/2.0) + mf(sin(x*pi),y/2.0) +
mf(sin(x*pi),y/2.0) + mf(sin(x*pi),y/2.0) +
mf(sin(x*pi),y/2.0) + mf(sin(x*pi),y/2.0) +
mf(sin(x*pi),y/2.0); mf(sin(x*pi),y/2.0) +
mf(sin(x*pi),y/2.0) +
mf(sin(x*pi),y/2.0)
);
if (not_equal<T>(result,expected,0.0000001)) if (not_equal<T>(result,expected,0.0000001))
{ {