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>
|
||||
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;
|
||||
expression.register_symbol_table(symbol_table);
|
||||
typedef exprtk::expression<T> expression_t;
|
||||
|
||||
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",
|
||||
parser.error().c_str(),
|
||||
expr_str_list[i].c_str());
|
||||
expression_t expression;
|
||||
expression.register_symbol_table(symbol_table);
|
||||
|
||||
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;
|
||||
}
|
||||
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());
|
||||
typedef exprtk::symbol_table<T> symbol_table_t;
|
||||
typedef exprtk::expression<T> expression_t;
|
||||
typedef exprtk::parser<T> parser_t;
|
||||
|
||||
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>
|
||||
|
|
141
readme.txt
141
readme.txt
|
@ -618,7 +618,7 @@ current values assigned to the variables will be used.
|
|||
y = -9.0;
|
||||
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)
|
||||
{
|
||||
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
|
||||
">=" representing the "greater than or equal to" operator. If not
|
||||
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:
|
||||
|
||||
(a) '>' '=' ---> '>=' (gte)
|
||||
|
@ -1029,7 +1029,8 @@ There are two types of function interface:
|
|||
|
||||
(1) ifunction
|
||||
(2) ivararg_function
|
||||
(3) function_compositor
|
||||
(3) igeneric_function
|
||||
(4) function_compositor
|
||||
|
||||
|
||||
(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
|
||||
using ExprTk syntax. The functions are limited to returning a single
|
||||
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.add_function("foo",f);
|
||||
symbol_table.add_vararg_function("boo",b);
|
||||
symbol_table.add_function("boo",b);
|
||||
|
||||
compositor
|
||||
.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
|
||||
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.
|
||||
|
||||
(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.
|
||||
|
||||
(02) Supported types are float, double, long double and MPFR/GMP.
|
||||
|
||||
(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
|
||||
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.
|
||||
|
||||
(06) All reserved and key words, variable, vector and function names
|
||||
are case-insensitive.
|
||||
|
||||
(07) Variable, vector and function names must begin with a letter
|
||||
(A-Z or a-z), then can be comprised of any combination of
|
||||
(07) Variable, vector and function names must begin with a letter
|
||||
(A-Z or a-z), then can be comprised of any combination of
|
||||
letters, digits and underscores. (eg: x, var1 or power_func99)
|
||||
|
||||
(08) Expression lengths and sub-expression lists are limited only by
|
||||
storage capacity.
|
||||
|
||||
(09) The life-time of objects registered with or created from a
|
||||
specific symbol-table must span at least the life-time of the
|
||||
compiled expressions which utilize objects, such as variables,
|
||||
of that symbol-table, otherwise the result will be undefined
|
||||
(09) The life-time of objects registered with or created from a
|
||||
specific symbol-table must span at least the life-time of the
|
||||
compiled expressions which utilize objects, such as variables,
|
||||
of that symbol-table, otherwise the result will be undefined
|
||||
behavior.
|
||||
|
||||
(10) Equal/Nequal are normalized equality routines, which use
|
||||
epsilons of 0.0000000001 and 0.000001 for double and float
|
||||
(10) Equal/Nequal are normalized equality routines, which use
|
||||
epsilons of 0.0000000001 and 0.000001 for double and float
|
||||
types respectively.
|
||||
|
||||
(11) All trigonometric functions assume radian input unless
|
||||
stated otherwise.
|
||||
(11) All trigonometric functions assume radian input unless stated
|
||||
otherwise.
|
||||
|
||||
(12) Expressions may contain white-space characters such as
|
||||
space, tabs, new-lines, control-feed et al.
|
||||
(12) Expressions may contain white-space characters such as space,
|
||||
tabs, new-lines, control-feed et al.
|
||||
('\n', '\r', '\t', '\b', '\v', '\f')
|
||||
|
||||
(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.
|
||||
eg: 'Frankly my dear, 1 do n0t give a damn!'
|
||||
|
||||
(14) User defined normal functions can have up to 20 parameters,
|
||||
where as user defined vararg-functions can have an unlimited
|
||||
(14) User defined normal functions can have up to 20 parameters,
|
||||
where as user defined vararg-functions can have an unlimited
|
||||
number of parameters.
|
||||
|
||||
(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)')
|
||||
|
||||
(17) If the strength reduction compilation option has been enabled,
|
||||
then where applicable strength reduction optimisations may be
|
||||
applied.
|
||||
|
||||
(18) String processing capabilities are available by default.
|
||||
To turn them off, the following needs to be defined at
|
||||
compile time: exprtk_disable_string_capabilities
|
||||
(18) String processing capabilities are available by default. To
|
||||
turn them off, the following needs to be defined at compile
|
||||
time: exprtk_disable_string_capabilities
|
||||
|
||||
(19) Composited functions can call themselves or any other functions
|
||||
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
|
||||
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
|
||||
functions wont result in constant folding. If the function has
|
||||
no side effects then that can be noted during the constructor
|
||||
of the ifunction allowing it to be constant folded where
|
||||
functions wont result in constant folding. If the function has
|
||||
no side effects then that can be noted during the constructor
|
||||
of the ifunction allowing it to be constant folded where
|
||||
appropriate.
|
||||
|
||||
(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
|
||||
requirements of multiple expressions.
|
||||
|
||||
(23) 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 and suboptimal approach would
|
||||
be to recompile an expression from its string form every time
|
||||
(23) 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 and suboptimal approach would
|
||||
be to recompile an expression from its string form every time
|
||||
it requires evaluating.
|
||||
|
||||
(24) The following are examples of compliant floating point value
|
||||
|
@ -1395,10 +1445,11 @@ into account when using Exprtk:
|
|||
2. # .... \n
|
||||
3. /* .... */
|
||||
|
||||
(26) The 'null' value type is a special non-zero type that
|
||||
incorporates specific semantics when undergoing operations
|
||||
with the standard numeric type. The following is a list of
|
||||
type and boolean results associated with the use of 'null':
|
||||
(26) The 'null' value type is a special non-zero type that
|
||||
incorporates specific semantics when undergoing operations with
|
||||
the standard numeric type. The following is a list of type and
|
||||
boolean results associated with the use of 'null':
|
||||
|
||||
1. null +,-,*,/,% x --> x
|
||||
2. x +,-,*,/,% null --> x
|
||||
3. null +,-,*,/,% null --> null
|
||||
|
@ -1409,10 +1460,10 @@ into account when using Exprtk:
|
|||
8. null != null --> false
|
||||
9. null != x --> false
|
||||
|
||||
(27) The following is a list of reserved words and symbols used by
|
||||
ExprTk. Attempting to add a variable or custom function to a
|
||||
symbol table using any of the reserved words will result in
|
||||
a failure.
|
||||
(27) The following is a list of reserved words and symbols used by
|
||||
ExprTk. Attempting to add a variable or custom function to a
|
||||
symbol table using any of the reserved words will result in a
|
||||
failure.
|
||||
|
||||
abs, acos, acosh, and, asin, asinh, atan, atan2, atanh, avg,
|
||||
break, case, ceil, clamp, continue, cosh, cos, cot, csc,
|
||||
|
@ -1426,8 +1477,8 @@ into account when using Exprtk:
|
|||
while, xnor, xor, xor
|
||||
|
||||
(28) Every valid ExprTk statement is a "value returning" expression.
|
||||
Unlike some languages that limit the types of expressions that
|
||||
can be performed in certain situations, in ExprTk any valid
|
||||
Unlike some languages that limit the types of expressions that
|
||||
can be performed in certain situations, in ExprTk any valid
|
||||
expression can be used in any "value consuming" context. Eg:
|
||||
|
||||
var y := 3;
|
||||
|
|
Loading…
Reference in New Issue