C++ Mathematical Expression Library (ExprTk) http://www.partow.net/programming/exprtk/index.html
This commit is contained in:
parent
ce23204895
commit
334953ee4d
1750
exprtk.hpp
1750
exprtk.hpp
File diff suppressed because it is too large
Load Diff
577
exprtk_test.cpp
577
exprtk_test.cpp
|
@ -4419,87 +4419,534 @@ struct va_func : public exprtk::ivararg_function<T>
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct gen_func : public exprtk::igeneric_function<T>
|
||||||
|
{
|
||||||
|
typedef typename exprtk::igeneric_function<T>::generic_type generic_type;
|
||||||
|
typedef typename exprtk::igeneric_function<T>::parameter_list_t parameter_list_t;
|
||||||
|
|
||||||
|
typedef typename generic_type::scalar_view scalar_t;
|
||||||
|
typedef typename generic_type::vector_view vector_t;
|
||||||
|
typedef typename generic_type::string_view string_t;
|
||||||
|
|
||||||
|
gen_func()
|
||||||
|
: scalar_count(0),
|
||||||
|
vector_count(0),
|
||||||
|
string_count(0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
inline T operator()(parameter_list_t& params)
|
||||||
|
{
|
||||||
|
for (std::size_t i = 0; i < params.size(); ++i)
|
||||||
|
{
|
||||||
|
generic_type& gt = params[i];
|
||||||
|
|
||||||
|
switch (gt.type)
|
||||||
|
{
|
||||||
|
case generic_type::e_scalar : scalar_count++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case generic_type::e_vector : vector_count++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case generic_type::e_string : {
|
||||||
|
if (
|
||||||
|
("CdEf" != exprtk::to_str(string_t(gt))) &&
|
||||||
|
("abc123" != exprtk::to_str(string_t(gt)))
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return std::numeric_limits<T>::quiet_NaN();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
string_count++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default : return std::numeric_limits<T>::quiet_NaN();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return T(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t scalar_count;
|
||||||
|
std::size_t vector_count;
|
||||||
|
std::size_t string_count;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct gen_func2 : public exprtk::igeneric_function<T>
|
||||||
|
{
|
||||||
|
typedef typename exprtk::igeneric_function<T>::parameter_list_t parameter_list_t;
|
||||||
|
|
||||||
|
gen_func2()
|
||||||
|
{}
|
||||||
|
|
||||||
|
inline T operator()(parameter_list_t&)
|
||||||
|
{
|
||||||
|
return T(0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct inc_func : public exprtk::igeneric_function<T>
|
||||||
|
{
|
||||||
|
typedef typename exprtk::igeneric_function<T>::generic_type generic_type;
|
||||||
|
typedef typename exprtk::igeneric_function<T>::parameter_list_t parameter_list_t;
|
||||||
|
|
||||||
|
typedef typename generic_type::scalar_view scalar_t;
|
||||||
|
typedef typename generic_type::vector_view vector_t;
|
||||||
|
typedef typename generic_type::string_view string_t;
|
||||||
|
|
||||||
|
inc_func()
|
||||||
|
{}
|
||||||
|
|
||||||
|
inline T operator()(parameter_list_t& params)
|
||||||
|
{
|
||||||
|
for (std::size_t i = 0; i < params.size(); ++i)
|
||||||
|
{
|
||||||
|
generic_type& gt = params[i];
|
||||||
|
|
||||||
|
switch (gt.type)
|
||||||
|
{
|
||||||
|
case generic_type::e_scalar : {
|
||||||
|
scalar_t scalar(gt);
|
||||||
|
scalar() += T(1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case generic_type::e_vector : {
|
||||||
|
vector_t vector(gt);
|
||||||
|
for (std::size_t x = 0; x < vector.size(); ++x)
|
||||||
|
{
|
||||||
|
vector[x] += T(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case generic_type::e_string : {
|
||||||
|
string_t string(gt);
|
||||||
|
for (std::size_t x = 0; x < string.size(); ++x)
|
||||||
|
{
|
||||||
|
string[x] += static_cast<typename string_t::value_t>(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default : return std::numeric_limits<T>::quiet_NaN();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return T(0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline bool run_test18()
|
inline bool run_test18()
|
||||||
{
|
{
|
||||||
typedef exprtk::expression<T> expression_t;
|
|
||||||
|
|
||||||
T x = T(1.1);
|
|
||||||
T y = T(2.2);
|
|
||||||
T z = T(3.3);
|
|
||||||
T w = T(4.4);
|
|
||||||
T u = T(5.5);
|
|
||||||
T v = T(6.6);
|
|
||||||
T t = T(7.7);
|
|
||||||
|
|
||||||
va_func<T> vaf;
|
|
||||||
|
|
||||||
exprtk::symbol_table<T> symbol_table;
|
|
||||||
symbol_table.add_constants();
|
|
||||||
symbol_table.add_variable("x",x);
|
|
||||||
symbol_table.add_variable("y",y);
|
|
||||||
symbol_table.add_variable("z",z);
|
|
||||||
symbol_table.add_variable("w",w);
|
|
||||||
symbol_table.add_variable("u",u);
|
|
||||||
symbol_table.add_variable("v",v);
|
|
||||||
symbol_table.add_variable("t",t);
|
|
||||||
symbol_table.add_vararg_function("va_func",vaf);
|
|
||||||
|
|
||||||
static const std::string expr_str_list[] =
|
|
||||||
{
|
|
||||||
"equal(va_func,(0))",
|
|
||||||
"equal(va_func(),(0))",
|
|
||||||
"equal(va_func(1,2,3,4,5,6,7,8,9),(1+2+3+4+5+6+7+8+9))",
|
|
||||||
"equal(va_func(1,x,3,y,5,z,7,w,9),(1+x+3+y+5+z+7+w+9))",
|
|
||||||
"equal(va_func(x,2,y,4,z,6,w,8,u),(x+2+y+4+z+6+w+8+u))",
|
|
||||||
"equal(va_func(x,y,z,w,u,v,t,1,2,3),(x+y+z+w+u+v+t+1+2+3))",
|
|
||||||
"equal(va_func(x,y,z,w,u,v,t),(x+y+z+w+u+v+t))",
|
|
||||||
"equal(va_func(x+t,y+v,z+u,w+w,u+z,v+y,t+x),2*(x+y+z+w+u+v+t))",
|
|
||||||
"equal(1+va_func(1,x,3,y,5,z,7,w,9),(1+x+3+y+5+z+7+w+9)+1)",
|
|
||||||
"equal(va_func(va_func(x,y,z,w,u,v,t),va_func(x,y,z,w,u,v,t)),2*(x+y+z+w+u+v+t))",
|
|
||||||
"equal(va_func(va_func(x),va_func(y),va_func(z)),va_func(x,y,z))",
|
|
||||||
"equal(va_func(va_func(va_func(va_func(va_func(va_func(va_func(va_func(x)))))))),x)",
|
|
||||||
"equal(va_func(va_func(va_func(va_func(va_func(va_func(va_func(va_func(123.456)))))))),123.456)",
|
|
||||||
"equal(va_func(va_func(va_func(va_func(va_func(va_func(va_func(va_func(x+1)))))))),x+1)",
|
|
||||||
"equal(va_func(va_func(va_func(va_func(va_func(va_func(va_func(va_func(x+y)))))))),x+y)"
|
|
||||||
};
|
|
||||||
static const std::size_t expr_str_list_size = sizeof(expr_str_list) / sizeof(std::string);
|
|
||||||
|
|
||||||
std::deque<expression_t> expression_list;
|
|
||||||
|
|
||||||
for (std::size_t i = 0; i < expr_str_list_size; ++i)
|
|
||||||
{
|
{
|
||||||
expression_t expression;
|
typedef exprtk::expression<T> expression_t;
|
||||||
expression.register_symbol_table(symbol_table);
|
|
||||||
|
|
||||||
exprtk::parser<T> parser;
|
T x = T(1.1);
|
||||||
|
T y = T(2.2);
|
||||||
|
T z = T(3.3);
|
||||||
|
T w = T(4.4);
|
||||||
|
T u = T(5.5);
|
||||||
|
T v = T(6.6);
|
||||||
|
T t = T(7.7);
|
||||||
|
|
||||||
if (!parser.compile(expr_str_list[i],expression))
|
va_func<T> vaf;
|
||||||
|
|
||||||
|
exprtk::symbol_table<T> symbol_table;
|
||||||
|
symbol_table.add_constants();
|
||||||
|
symbol_table.add_variable("x",x);
|
||||||
|
symbol_table.add_variable("y",y);
|
||||||
|
symbol_table.add_variable("z",z);
|
||||||
|
symbol_table.add_variable("w",w);
|
||||||
|
symbol_table.add_variable("u",u);
|
||||||
|
symbol_table.add_variable("v",v);
|
||||||
|
symbol_table.add_variable("t",t);
|
||||||
|
symbol_table.add_function("va_func",vaf);
|
||||||
|
|
||||||
|
static const std::string expr_str_list[] =
|
||||||
|
{
|
||||||
|
"equal(va_func,(0))",
|
||||||
|
"equal(va_func(),(0))",
|
||||||
|
"equal(va_func(1,2,3,4,5,6,7,8,9),(1+2+3+4+5+6+7+8+9))",
|
||||||
|
"equal(va_func(1,x,3,y,5,z,7,w,9),(1+x+3+y+5+z+7+w+9))",
|
||||||
|
"equal(va_func(x,2,y,4,z,6,w,8,u),(x+2+y+4+z+6+w+8+u))",
|
||||||
|
"equal(va_func(x,y,z,w,u,v,t,1,2,3),(x+y+z+w+u+v+t+1+2+3))",
|
||||||
|
"equal(va_func(x,y,z,w,u,v,t),(x+y+z+w+u+v+t))",
|
||||||
|
"equal(va_func(x+t,y+v,z+u,w+w,u+z,v+y,t+x),2*(x+y+z+w+u+v+t))",
|
||||||
|
"equal(1+va_func(1,x,3,y,5,z,7,w,9),(1+x+3+y+5+z+7+w+9)+1)",
|
||||||
|
"equal(va_func(va_func(x,y,z,w,u,v,t),va_func(x,y,z,w,u,v,t)),2*(x+y+z+w+u+v+t))",
|
||||||
|
"equal(va_func(va_func(x),va_func(y),va_func(z)),va_func(x,y,z))",
|
||||||
|
"equal(va_func(va_func(va_func(va_func(va_func(va_func(va_func(va_func(x)))))))),x)",
|
||||||
|
"equal(va_func(va_func(va_func(va_func(va_func(va_func(va_func(va_func(123.456)))))))),123.456)",
|
||||||
|
"equal(va_func(va_func(va_func(va_func(va_func(va_func(va_func(va_func(x+1)))))))),x+1)",
|
||||||
|
"equal(va_func(va_func(va_func(va_func(va_func(va_func(va_func(va_func(x+y)))))))),x+y)"
|
||||||
|
};
|
||||||
|
static const std::size_t expr_str_list_size = sizeof(expr_str_list) / sizeof(std::string);
|
||||||
|
|
||||||
|
std::deque<expression_t> expression_list;
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < expr_str_list_size; ++i)
|
||||||
{
|
{
|
||||||
printf("run_test18() - Error: %s Expression: %s\n",
|
expression_t expression;
|
||||||
parser.error().c_str(),
|
expression.register_symbol_table(symbol_table);
|
||||||
expr_str_list[i].c_str());
|
|
||||||
|
|
||||||
|
exprtk::parser<T> parser;
|
||||||
|
|
||||||
|
if (!parser.compile(expr_str_list[i],expression))
|
||||||
|
{
|
||||||
|
printf("run_test18() - VarArg Error: %s Expression: %s\n",
|
||||||
|
parser.error().c_str(),
|
||||||
|
expr_str_list[i].c_str());
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
expression_list.push_back(expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool failure = false;
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < expression_list.size(); ++i)
|
||||||
|
{
|
||||||
|
if (T(1) != expression_list[i].value())
|
||||||
|
{
|
||||||
|
printf("run_test18() - Error in evaluation! (1) Expression: %s\n",
|
||||||
|
expr_str_list[i].c_str());
|
||||||
|
|
||||||
|
failure = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (failure)
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
else
|
|
||||||
expression_list.push_back(expression);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool failure = false;
|
|
||||||
|
|
||||||
for (std::size_t i = 0; i < expression_list.size(); ++i)
|
|
||||||
{
|
{
|
||||||
if (T(1) != expression_list[i].value())
|
typedef exprtk::symbol_table<T> symbol_table_t;
|
||||||
{
|
typedef exprtk::expression<T> expression_t;
|
||||||
printf("run_test18() - Error in evaluation! (1) Expression: %s\n",
|
typedef exprtk::parser<T> parser_t;
|
||||||
expr_str_list[i].c_str());
|
|
||||||
|
|
||||||
failure = true;
|
T x = T(33);
|
||||||
|
T y = T(77);
|
||||||
|
|
||||||
|
T v0[] = { T(1), T(1), T(1), T(1) };
|
||||||
|
T v1[] = { T(1), T(2), T(3), T(4) };
|
||||||
|
|
||||||
|
std::vector<T> v2;
|
||||||
|
|
||||||
|
v2.push_back(T(5));
|
||||||
|
v2.push_back(T(6));
|
||||||
|
v2.push_back(T(7));
|
||||||
|
v2.push_back(T(8));
|
||||||
|
|
||||||
|
std::string s0 = "AbCdEfGhIj";
|
||||||
|
|
||||||
|
gen_func<T> f;
|
||||||
|
|
||||||
|
symbol_table_t symbol_table;
|
||||||
|
|
||||||
|
symbol_table.add_constants();
|
||||||
|
|
||||||
|
symbol_table.add_variable ("x" , x);
|
||||||
|
symbol_table.add_variable ("y" , y);
|
||||||
|
symbol_table.add_vector ("v0" ,v0);
|
||||||
|
symbol_table.add_vector ("v1" ,v1);
|
||||||
|
symbol_table.add_vector ("v2" ,v2);
|
||||||
|
symbol_table.add_stringvar("s0", s0);
|
||||||
|
symbol_table.add_function ("gen_func", f);
|
||||||
|
|
||||||
|
std::string expression_list[] =
|
||||||
|
{
|
||||||
|
"var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; gen_func(v0,v1 + v2, v0[2], x, 2x + y, z, 2w / 3, 'abc123',s0[2:5]);",
|
||||||
|
"var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; gen_func(v0,v1 + v2, v0[2], x, 2x + y, z, 2w / 3, 'abc123',s0[2:5]);",
|
||||||
|
"var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; gen_func(v1 + v2, v0[2], x, 2x + y, z, 2w / 3, 'abc123',s0[2:5],v0);",
|
||||||
|
"var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; gen_func(v0[2], x, 2x + y, z, 2w / 3, 'abc123',s0[2:5],v0, v1 + v2);",
|
||||||
|
"var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; gen_func(x, 2x + y, z, 2w / 3, 'abc123',s0[2:5],v0, v1 + v2, v0[2]);",
|
||||||
|
"var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; gen_func(2x + y, z, 2w / 3, 'abc123',s0[2:5],v0, v1 + v2, v0[2], x);",
|
||||||
|
"var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; gen_func(z, 2w / 3, 'abc123',s0[2:5],v0, v1 + v2, v0[2], x, 2x + y);",
|
||||||
|
"var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; gen_func(2w / 3, 'abc123',s0[2:5],v0, v1 + v2, v0[2], x, 2x + y, z);",
|
||||||
|
"var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; gen_func('abc123', s0[2:5],v0, v1 + v2, v0[2], x, 2x + y, z,2w / 3);",
|
||||||
|
"var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; gen_func(s0[2:5],v0, v1 + v2, v0[2], x, 2x + y, z,2w / 3, 'abc123');"
|
||||||
|
};
|
||||||
|
|
||||||
|
static const std::size_t expression_list_size = sizeof(expression_list) / sizeof(std::string);
|
||||||
|
|
||||||
|
|
||||||
|
bool failure = false;
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < expression_list_size; ++i)
|
||||||
|
{
|
||||||
|
expression_t expression;
|
||||||
|
|
||||||
|
expression.register_symbol_table(symbol_table);
|
||||||
|
|
||||||
|
parser_t parser;
|
||||||
|
|
||||||
|
if (!parser.compile(expression_list[i],expression))
|
||||||
|
{
|
||||||
|
printf("run_test18() - GenFunc Error: %s Expression: %s\n",
|
||||||
|
parser.error().c_str(),
|
||||||
|
expression_list[i].c_str());
|
||||||
|
|
||||||
|
failure = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
f.scalar_count = 0;
|
||||||
|
f.vector_count = 0;
|
||||||
|
f.string_count = 0;
|
||||||
|
|
||||||
|
expression.value();
|
||||||
|
|
||||||
|
if (
|
||||||
|
(4 != f.scalar_count) ||
|
||||||
|
(3 != f.vector_count) ||
|
||||||
|
(2 != f.string_count)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
printf("run_test18() - Error in evaluation! (2) Expression: %s "
|
||||||
|
"sc_count = %d "
|
||||||
|
"vr_count = %d "
|
||||||
|
"st_count = %d\n",
|
||||||
|
expression_list[i].c_str(),
|
||||||
|
static_cast<int>(f.scalar_count),
|
||||||
|
static_cast<int>(f.vector_count),
|
||||||
|
static_cast<int>(f.string_count));
|
||||||
|
|
||||||
|
failure = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (failure)
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return !failure;
|
{
|
||||||
|
typedef exprtk::symbol_table<T> symbol_table_t;
|
||||||
|
typedef exprtk::expression<T> expression_t;
|
||||||
|
typedef exprtk::parser<T> parser_t;
|
||||||
|
|
||||||
|
T x = T(33);
|
||||||
|
T y = T(77);
|
||||||
|
|
||||||
|
T v0[] = { T(1), T(1), T(1), T(1) };
|
||||||
|
T v1[] = { T(1), T(2), T(3), T(4) };
|
||||||
|
T v2[] = { T(5), T(6), T(7), T(8) };
|
||||||
|
|
||||||
|
std::string s0 = "AbCdEfGhIj";
|
||||||
|
|
||||||
|
gen_func2<T> f;
|
||||||
|
|
||||||
|
symbol_table_t symbol_table;
|
||||||
|
|
||||||
|
symbol_table.add_constants();
|
||||||
|
|
||||||
|
symbol_table.add_variable ("x" , x);
|
||||||
|
symbol_table.add_variable ("y" , y);
|
||||||
|
symbol_table.add_vector ("v0" ,v0);
|
||||||
|
symbol_table.add_vector ("v1" ,v1);
|
||||||
|
symbol_table.add_vector ("v2" ,v2);
|
||||||
|
symbol_table.add_stringvar("s0", s0);
|
||||||
|
symbol_table.add_function ("foo", f);
|
||||||
|
|
||||||
|
std::string expression_list[] =
|
||||||
|
{
|
||||||
|
"var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(v0,v1 + v2, v0[2], x, 2x + y, z, 2w / 3, 'abc123',s0[2:5]);",
|
||||||
|
"var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(v1 + v2, v0[2], x, 2x + y, z, 2w / 3, 'abc123',s0[2:5],v0);",
|
||||||
|
"var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(v0[2], x, 2x + y, z, 2w / 3, 'abc123',s0[2:5],v0, v1 + v2);",
|
||||||
|
"var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(x, 2x + y, z, 2w / 3, 'abc123',s0[2:5],v0, v1 + v2, v0[2]);",
|
||||||
|
"var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(2x + y, z, 2w / 3, 'abc123',s0[2:5],v0, v1 + v2, v0[2], x);",
|
||||||
|
"var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(z, 2w / 3, 'abc123',s0[2:5],v0, v1 + v2, v0[2], x, 2x + y);",
|
||||||
|
"var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(2w / 3, 'abc123',s0[2:5],v0, v1 + v2, v0[2], x, 2x + y, z);",
|
||||||
|
"var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo('abc123', s0[2:5],v0, v1 + v2, v0[2], x, 2x + y, z,2w / 3);",
|
||||||
|
"var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(s0[2:5],v0, v1 + v2, v0[2], x, 2x + y, z,2w / 3, 'abc123');"
|
||||||
|
};
|
||||||
|
|
||||||
|
static const std::size_t expression_list_size = sizeof(expression_list) / sizeof(std::string);
|
||||||
|
|
||||||
|
std::string parameter_type_list[] =
|
||||||
|
{
|
||||||
|
"VVTTTTVSS",
|
||||||
|
"VTTTTVSSV",
|
||||||
|
"TTTTVSSVV",
|
||||||
|
"TTTVSSVVT",
|
||||||
|
"TTVSSVVT*",
|
||||||
|
"TVSSVVT*" ,
|
||||||
|
"VSSVVT*" ,
|
||||||
|
"SSVVTTTTV",
|
||||||
|
"SVVTTTTVS",
|
||||||
|
};
|
||||||
|
|
||||||
|
bool failure = false;
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < expression_list_size; ++i)
|
||||||
|
{
|
||||||
|
expression_t expression;
|
||||||
|
|
||||||
|
expression.register_symbol_table(symbol_table);
|
||||||
|
|
||||||
|
parser_t parser;
|
||||||
|
|
||||||
|
f.parameter_sequence = parameter_type_list[i];
|
||||||
|
|
||||||
|
if (!parser.compile(expression_list[i],expression))
|
||||||
|
{
|
||||||
|
printf("run_test18() - GenFunc2 Error: %s Expression: %s Parameter Sequence: %s\n",
|
||||||
|
parser.error().c_str(),
|
||||||
|
expression_list[i].c_str(),
|
||||||
|
parameter_type_list[i].c_str());
|
||||||
|
|
||||||
|
failure = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
expression.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (failure)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
bool failure = false;
|
||||||
|
|
||||||
|
std::string expression_list[] =
|
||||||
|
{
|
||||||
|
"foo(v0,v1,v2,x,y,s0);",
|
||||||
|
"foo(v1,v2,x,y,s0,v0);",
|
||||||
|
"foo(v2,x,y,s0,v0,v1);",
|
||||||
|
"foo(x,y,s0,v0,v1,v2);",
|
||||||
|
"foo(y,s0,v0,v1,v2,x);",
|
||||||
|
"foo(s0,v0,v1,v2,x,y);"
|
||||||
|
};
|
||||||
|
|
||||||
|
static const std::size_t expression_list_size = sizeof(expression_list) / sizeof(std::string);
|
||||||
|
|
||||||
|
std::string parameter_type_list[] =
|
||||||
|
{
|
||||||
|
"VVVTTS",
|
||||||
|
"VVTTSV",
|
||||||
|
"VTTSVV",
|
||||||
|
"TTSVVV",
|
||||||
|
"TSVVVT",
|
||||||
|
"SVVVTT"
|
||||||
|
};
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < expression_list_size; ++i)
|
||||||
|
{
|
||||||
|
typedef exprtk::symbol_table<T> symbol_table_t;
|
||||||
|
typedef exprtk::expression<T> expression_t;
|
||||||
|
typedef exprtk::parser<T> parser_t;
|
||||||
|
|
||||||
|
T x = T(33);
|
||||||
|
T y = T(77);
|
||||||
|
|
||||||
|
T v0[] = { T(1), T(1), T(1), T(1) };
|
||||||
|
T v1[] = { T(1), T(2), T(3), T(4) };
|
||||||
|
T v2[] = { T(5), T(6), T(7), T(8) };
|
||||||
|
|
||||||
|
std::string s0 = "AbCdEfGhIj";
|
||||||
|
|
||||||
|
T x_inc = T(34);
|
||||||
|
T y_inc = T(78);
|
||||||
|
|
||||||
|
T v0_inc[] = { T(2), T(2), T(2), T(2) };
|
||||||
|
T v1_inc[] = { T(2), T(3), T(4), T(5) };
|
||||||
|
T v2_inc[] = { T(6), T(7), T(8), T(9) };
|
||||||
|
|
||||||
|
std::size_t sizeof_vec = sizeof(v0) / sizeof(T);
|
||||||
|
|
||||||
|
std::string s0_inc = "BcDeFgHiJk";
|
||||||
|
|
||||||
|
inc_func<T> f;
|
||||||
|
|
||||||
|
symbol_table_t symbol_table;
|
||||||
|
|
||||||
|
symbol_table.add_constants();
|
||||||
|
|
||||||
|
symbol_table.add_variable ("x" , x);
|
||||||
|
symbol_table.add_variable ("y" , y);
|
||||||
|
symbol_table.add_vector ("v0" ,v0);
|
||||||
|
symbol_table.add_vector ("v1" ,v1);
|
||||||
|
symbol_table.add_vector ("v2" ,v2);
|
||||||
|
symbol_table.add_stringvar("s0", s0);
|
||||||
|
symbol_table.add_function ("foo", f);
|
||||||
|
|
||||||
|
expression_t expression;
|
||||||
|
|
||||||
|
expression.register_symbol_table(symbol_table);
|
||||||
|
|
||||||
|
parser_t parser;
|
||||||
|
|
||||||
|
f.parameter_sequence = parameter_type_list[i];
|
||||||
|
|
||||||
|
if (!parser.compile(expression_list[i],expression))
|
||||||
|
{
|
||||||
|
printf("run_test18() - IncFunc Error: %s Expression: %s Parameter Sequence: %s\n",
|
||||||
|
parser.error().c_str(),
|
||||||
|
expression_list[i].c_str(),
|
||||||
|
parameter_type_list[i].c_str());
|
||||||
|
|
||||||
|
failure = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
expression.value();
|
||||||
|
|
||||||
|
if (x != x_inc)
|
||||||
|
{
|
||||||
|
printf("run_test18() - Error in evaluation! (3) Expression: %s Check: x\n",
|
||||||
|
expression_list[i].c_str());
|
||||||
|
failure = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (y != y_inc)
|
||||||
|
{
|
||||||
|
printf("run_test18() - Error in evaluation! (3) Expression: %s Check: y\n",
|
||||||
|
expression_list[i].c_str());
|
||||||
|
failure = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s0 != s0_inc)
|
||||||
|
{
|
||||||
|
printf("run_test18() - Error in evaluation! (3) Expression: %s Check: y\n",
|
||||||
|
expression_list[i].c_str());
|
||||||
|
failure = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!std::equal(v0,v0 + sizeof_vec,v0_inc))
|
||||||
|
{
|
||||||
|
printf("run_test18() - Error in evaluation! (3) Expression: %s Check: v0\n",
|
||||||
|
expression_list[i].c_str());
|
||||||
|
failure = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!std::equal(v1,v1 + sizeof_vec,v1_inc))
|
||||||
|
{
|
||||||
|
printf("run_test18() - Error in evaluation! (3) Expression: %s Check: v1\n",
|
||||||
|
expression_list[i].c_str());
|
||||||
|
failure = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!std::equal(v2,v2 + sizeof_vec,v2_inc))
|
||||||
|
{
|
||||||
|
printf("run_test18() - Error in evaluation! (3) Expression: %s Check: v2\n",
|
||||||
|
expression_list[i].c_str());
|
||||||
|
failure = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (failure)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
|
141
readme.txt
141
readme.txt
|
@ -618,7 +618,7 @@ current values assigned to the variables will be used.
|
||||||
y = -9.0;
|
y = -9.0;
|
||||||
expression.value(); // 3.7 * -9 + 3
|
expression.value(); // 3.7 * -9 + 3
|
||||||
|
|
||||||
// 'x * -9 + 3' for x in range of [0,100] in steps of 0.0001
|
// 'x * -9 + 3' for x in range of [0,100) in steps of 0.0001
|
||||||
for (var x = 0; x < 100; x += 0.0001)
|
for (var x = 0; x < 100; x += 0.0001)
|
||||||
{
|
{
|
||||||
expression.value(); // x * -9 + 3
|
expression.value(); // x * -9 + 3
|
||||||
|
@ -703,7 +703,7 @@ incorrectly disjoint in the string representation of the specified
|
||||||
expression. For example the consecutive tokens of ">" "=" will become
|
expression. For example the consecutive tokens of ">" "=" will become
|
||||||
">=" representing the "greater than or equal to" operator. If not
|
">=" representing the "greater than or equal to" operator. If not
|
||||||
properly resolved the original form will cause a compilation error.
|
properly resolved the original form will cause a compilation error.
|
||||||
The following is a listing of the scenarios that the joiner can
|
The following is a listing of the scenarios that the joiner can
|
||||||
handle:
|
handle:
|
||||||
|
|
||||||
(a) '>' '=' ---> '>=' (gte)
|
(a) '>' '=' ---> '>=' (gte)
|
||||||
|
@ -1029,7 +1029,8 @@ There are two types of function interface:
|
||||||
|
|
||||||
(1) ifunction
|
(1) ifunction
|
||||||
(2) ivararg_function
|
(2) ivararg_function
|
||||||
(3) function_compositor
|
(3) igeneric_function
|
||||||
|
(4) function_compositor
|
||||||
|
|
||||||
|
|
||||||
(1) ifunction
|
(1) ifunction
|
||||||
|
@ -1075,7 +1076,56 @@ example defines a vararg function called 'boo':
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
(3) function_compositor
|
(3) igeneric_function
|
||||||
|
This interface supports a variable number of arguments and types as
|
||||||
|
input into the function. The function operator interface uses a
|
||||||
|
std::vector specialized upon the type_store type to facilitate
|
||||||
|
parameter passing.
|
||||||
|
|
||||||
|
The fundamental types that can be passed into the function as
|
||||||
|
parameters and their views are as follows:
|
||||||
|
|
||||||
|
(1) scalar - scalar_view
|
||||||
|
(2) vector - vector_view
|
||||||
|
(3) string - string_view
|
||||||
|
|
||||||
|
The following example defines a generic function called 'too':
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct too : public exprtk::igeneric_function<T>
|
||||||
|
{
|
||||||
|
typedef typename exprtk::igeneric_function<T>::parameter_list_t
|
||||||
|
parameter_list_t;
|
||||||
|
|
||||||
|
too()
|
||||||
|
{}
|
||||||
|
|
||||||
|
inline T operator()(parameter_list_t& parameters)
|
||||||
|
{
|
||||||
|
for (std::size_t i = 0; i < parameters.size(); ++i)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
return T(0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
In the above example, the parameter_list_t type is a type of
|
||||||
|
std::vector of type_store. Each type_store instance has a member
|
||||||
|
called 'type' which holds the enumeration pertaining the underlying
|
||||||
|
type of the type_store. There are three type enumerations:
|
||||||
|
|
||||||
|
(1) e_scalar - variables, vector elements, general expressions
|
||||||
|
eg: x, y, z, vec[3x + 1], 2x + 3
|
||||||
|
|
||||||
|
(2) e_vector - vectors, vector expressions
|
||||||
|
eg: vec1, 2 * vec1 + vec2 / 3
|
||||||
|
|
||||||
|
(3) e_string - string, string literal and range variants of both
|
||||||
|
eg: 'AString', s0, 'AString'[x:y], s1[1+x:]
|
||||||
|
|
||||||
|
|
||||||
|
(4) function_compositor
|
||||||
The function compositor interface allows a user to define a function
|
The function compositor interface allows a user to define a function
|
||||||
using ExprTk syntax. The functions are limited to returning a single
|
using ExprTk syntax. The functions are limited to returning a single
|
||||||
scalar value and consuming up to six parameters as input.
|
scalar value and consuming up to six parameters as input.
|
||||||
|
@ -1126,7 +1176,7 @@ The following demonstrates how all the pieces are put together:
|
||||||
|
|
||||||
symbol_table_t symbol_table;
|
symbol_table_t symbol_table;
|
||||||
symbol_table.add_function("foo",f);
|
symbol_table.add_function("foo",f);
|
||||||
symbol_table.add_vararg_function("boo",b);
|
symbol_table.add_function("boo",b);
|
||||||
|
|
||||||
compositor
|
compositor
|
||||||
.add(function_t()
|
.add(function_t()
|
||||||
|
@ -1293,48 +1343,48 @@ via the 'unknown symbol resolver' mechanism.
|
||||||
The following is a list of facts and suggestions one may want to take
|
The following is a list of facts and suggestions one may want to take
|
||||||
into account when using Exprtk:
|
into account when using Exprtk:
|
||||||
|
|
||||||
(00) Precision and performance of expression evaluations are the
|
(00) Precision and performance of expression evaluations are the
|
||||||
dominant principles of the ExprTk library.
|
dominant principles of the ExprTk library.
|
||||||
|
|
||||||
(01) ExprTk uses a rudimentary imperative programming model with
|
(01) ExprTk uses a rudimentary imperative programming model with
|
||||||
syntax based on languages such as Pascal and C.
|
syntax based on languages such as Pascal and C.
|
||||||
|
|
||||||
(02) Supported types are float, double, long double and MPFR/GMP.
|
(02) Supported types are float, double, long double and MPFR/GMP.
|
||||||
|
|
||||||
(03) Standard mathematical operator precedence is applied (BEDMAS).
|
(03) Standard mathematical operator precedence is applied (BEDMAS).
|
||||||
|
|
||||||
(04) Results of expressions that are deemed as being 'valid' are to
|
(04) Results of expressions that are deemed as being 'valid' are to
|
||||||
exist within the set of Real numbers. All other results will be
|
exist within the set of Real numbers. All other results will be
|
||||||
of the value: Not-A-Number (NaN).
|
of the value: Not-A-Number (NaN).
|
||||||
|
|
||||||
(05) Supported user defined types are numeric and string variables
|
(05) Supported user defined types are numeric and string variables
|
||||||
and functions.
|
and functions.
|
||||||
|
|
||||||
(06) All reserved and key words, variable, vector and function names
|
(06) All reserved and key words, variable, vector and function names
|
||||||
are case-insensitive.
|
are case-insensitive.
|
||||||
|
|
||||||
(07) Variable, vector and function names must begin with a letter
|
(07) Variable, vector and function names must begin with a letter
|
||||||
(A-Z or a-z), then can be comprised of any combination of
|
(A-Z or a-z), then can be comprised of any combination of
|
||||||
letters, digits and underscores. (eg: x, var1 or power_func99)
|
letters, digits and underscores. (eg: x, var1 or power_func99)
|
||||||
|
|
||||||
(08) Expression lengths and sub-expression lists are limited only by
|
(08) Expression lengths and sub-expression lists are limited only by
|
||||||
storage capacity.
|
storage capacity.
|
||||||
|
|
||||||
(09) The life-time of objects registered with or created from a
|
(09) The life-time of objects registered with or created from a
|
||||||
specific symbol-table must span at least the life-time of the
|
specific symbol-table must span at least the life-time of the
|
||||||
compiled expressions which utilize objects, such as variables,
|
compiled expressions which utilize objects, such as variables,
|
||||||
of that symbol-table, otherwise the result will be undefined
|
of that symbol-table, otherwise the result will be undefined
|
||||||
behavior.
|
behavior.
|
||||||
|
|
||||||
(10) Equal/Nequal are normalized equality routines, which use
|
(10) Equal/Nequal are normalized equality routines, which use
|
||||||
epsilons of 0.0000000001 and 0.000001 for double and float
|
epsilons of 0.0000000001 and 0.000001 for double and float
|
||||||
types respectively.
|
types respectively.
|
||||||
|
|
||||||
(11) All trigonometric functions assume radian input unless
|
(11) All trigonometric functions assume radian input unless stated
|
||||||
stated otherwise.
|
otherwise.
|
||||||
|
|
||||||
(12) Expressions may contain white-space characters such as
|
(12) Expressions may contain white-space characters such as space,
|
||||||
space, tabs, new-lines, control-feed et al.
|
tabs, new-lines, control-feed et al.
|
||||||
('\n', '\r', '\t', '\b', '\v', '\f')
|
('\n', '\r', '\t', '\b', '\v', '\f')
|
||||||
|
|
||||||
(13) Strings may be comprised of any combination of letters, digits
|
(13) Strings may be comprised of any combination of letters, digits
|
||||||
|
@ -1342,22 +1392,22 @@ into account when using Exprtk:
|
||||||
and must be enclosed with single-quotes.
|
and must be enclosed with single-quotes.
|
||||||
eg: 'Frankly my dear, 1 do n0t give a damn!'
|
eg: 'Frankly my dear, 1 do n0t give a damn!'
|
||||||
|
|
||||||
(14) User defined normal functions can have up to 20 parameters,
|
(14) User defined normal functions can have up to 20 parameters,
|
||||||
where as user defined vararg-functions can have an unlimited
|
where as user defined vararg-functions can have an unlimited
|
||||||
number of parameters.
|
number of parameters.
|
||||||
|
|
||||||
(15) The inbuilt polynomial functions can be at most of degree 12.
|
(15) The inbuilt polynomial functions can be at most of degree 12.
|
||||||
|
|
||||||
(16) Where appropriate constant folding optimisations may be
|
(16) Where appropriate constant folding optimisations may be
|
||||||
applied. (eg: The expression '2+(3-(x/y))' becomes '5-(x/y)')
|
applied. (eg: The expression '2+(3-(x/y))' becomes '5-(x/y)')
|
||||||
|
|
||||||
(17) If the strength reduction compilation option has been enabled,
|
(17) If the strength reduction compilation option has been enabled,
|
||||||
then where applicable strength reduction optimisations may be
|
then where applicable strength reduction optimisations may be
|
||||||
applied.
|
applied.
|
||||||
|
|
||||||
(18) String processing capabilities are available by default.
|
(18) String processing capabilities are available by default. To
|
||||||
To turn them off, the following needs to be defined at
|
turn them off, the following needs to be defined at compile
|
||||||
compile time: exprtk_disable_string_capabilities
|
time: exprtk_disable_string_capabilities
|
||||||
|
|
||||||
(19) Composited functions can call themselves or any other functions
|
(19) Composited functions can call themselves or any other functions
|
||||||
that have been defined prior to their own definition.
|
that have been defined prior to their own definition.
|
||||||
|
@ -1365,11 +1415,11 @@ into account when using Exprtk:
|
||||||
(20) Recursive calls made from within composited functions will have
|
(20) 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.
|
||||||
|
|
||||||
(21) User defined functions by default are assumed to have side
|
(21) User defined functions by default are assumed to have side
|
||||||
effects. As such an "all constant parameter" invocation of such
|
effects. As such an "all constant parameter" invocation of such
|
||||||
functions wont result in constant folding. If the function has
|
functions wont result in constant folding. If the function has
|
||||||
no side effects then that can be noted during the constructor
|
no side effects then that can be noted during the constructor
|
||||||
of the ifunction allowing it to be constant folded where
|
of the ifunction allowing it to be constant folded where
|
||||||
appropriate.
|
appropriate.
|
||||||
|
|
||||||
(22) The entity relationship between symbol_table and an expression
|
(22) The entity relationship between symbol_table and an expression
|
||||||
|
@ -1377,10 +1427,10 @@ into account when using Exprtk:
|
||||||
to have a single symbol table manage the variable and function
|
to have a single symbol table manage the variable and function
|
||||||
requirements of multiple expressions.
|
requirements of multiple expressions.
|
||||||
|
|
||||||
(23) The common use-case for an expression is to have it compiled
|
(23) The common use-case for an expression is to have it compiled
|
||||||
only ONCE and then subsequently have it evaluated multiple
|
only ONCE and then subsequently have it evaluated multiple
|
||||||
times. An extremely inefficient and suboptimal approach would
|
times. An extremely inefficient and suboptimal approach would
|
||||||
be to recompile an expression from its string form every time
|
be to recompile an expression from its string form every time
|
||||||
it requires evaluating.
|
it requires evaluating.
|
||||||
|
|
||||||
(24) The following are examples of compliant floating point value
|
(24) The following are examples of compliant floating point value
|
||||||
|
@ -1395,10 +1445,11 @@ into account when using Exprtk:
|
||||||
2. # .... \n
|
2. # .... \n
|
||||||
3. /* .... */
|
3. /* .... */
|
||||||
|
|
||||||
(26) The 'null' value type is a special non-zero type that
|
(26) The 'null' value type is a special non-zero type that
|
||||||
incorporates specific semantics when undergoing operations
|
incorporates specific semantics when undergoing operations with
|
||||||
with the standard numeric type. The following is a list of
|
the standard numeric type. The following is a list of type and
|
||||||
type and boolean results associated with the use of 'null':
|
boolean results associated with the use of 'null':
|
||||||
|
|
||||||
1. null +,-,*,/,% x --> x
|
1. null +,-,*,/,% x --> x
|
||||||
2. x +,-,*,/,% null --> x
|
2. x +,-,*,/,% null --> x
|
||||||
3. null +,-,*,/,% null --> null
|
3. null +,-,*,/,% null --> null
|
||||||
|
@ -1409,10 +1460,10 @@ into account when using Exprtk:
|
||||||
8. null != null --> false
|
8. null != null --> false
|
||||||
9. null != x --> false
|
9. null != x --> false
|
||||||
|
|
||||||
(27) The following is a list of reserved words and symbols used by
|
(27) The following is a list of reserved words and symbols used by
|
||||||
ExprTk. Attempting to add a variable or custom function to a
|
ExprTk. Attempting to add a variable or custom function to a
|
||||||
symbol table using any of the reserved words will result in
|
symbol table using any of the reserved words will result in a
|
||||||
a failure.
|
failure.
|
||||||
|
|
||||||
abs, acos, acosh, and, asin, asinh, atan, atan2, atanh, avg,
|
abs, acos, acosh, and, asin, asinh, atan, atan2, atanh, avg,
|
||||||
break, case, ceil, clamp, continue, cosh, cos, cot, csc,
|
break, case, ceil, clamp, continue, cosh, cos, cot, csc,
|
||||||
|
@ -1426,8 +1477,8 @@ into account when using Exprtk:
|
||||||
while, xnor, xor, xor
|
while, xnor, xor, xor
|
||||||
|
|
||||||
(28) Every valid ExprTk statement is a "value returning" expression.
|
(28) Every valid ExprTk statement is a "value returning" expression.
|
||||||
Unlike some languages that limit the types of expressions that
|
Unlike some languages that limit the types of expressions that
|
||||||
can be performed in certain situations, in ExprTk any valid
|
can be performed in certain situations, in ExprTk any valid
|
||||||
expression can be used in any "value consuming" context. Eg:
|
expression can be used in any "value consuming" context. Eg:
|
||||||
|
|
||||||
var y := 3;
|
var y := 3;
|
||||||
|
|
Loading…
Reference in New Issue