C++ Mathematical Expression Library (ExprTk) http://www.partow.net/programming/exprtk/index.html
This commit is contained in:
parent
a420147e7a
commit
64a4f623a3
10
Makefile
10
Makefile
|
@ -23,15 +23,23 @@ OPTIONS = $(BASE_OPTIONS) $(OPTIMIZATION_OPT) -o
|
||||||
LINKER_OPT = -L/usr/lib -lstdc++
|
LINKER_OPT = -L/usr/lib -lstdc++
|
||||||
|
|
||||||
BUILD_LIST+=exprtk_test
|
BUILD_LIST+=exprtk_test
|
||||||
|
BUILD_LIST+=exprtk_benchmark
|
||||||
|
|
||||||
all: $(BUILD_LIST)
|
all: $(BUILD_LIST)
|
||||||
|
|
||||||
exprtk_test: exprtk_test.cpp exprtk.hpp
|
exprtk_test: exprtk_test.cpp exprtk.hpp
|
||||||
$(COMPILER) $(OPTIONS) exprtk_test exprtk_test.cpp $(LINKER_OPT)
|
$(COMPILER) $(OPTIONS) exprtk_test exprtk_test.cpp $(LINKER_OPT)
|
||||||
|
|
||||||
|
exprtk_benchmark: exprtk_benchmark.cpp exprtk.hpp
|
||||||
|
$(COMPILER) $(OPTIONS) exprtk_benchmark exprtk_benchmark.cpp $(LINKER_OPT)
|
||||||
|
|
||||||
pgo: exprtk_test.cpp exprtk.hpp
|
pgo: exprtk_test.cpp exprtk_benchmark.cpp exprtk.hpp
|
||||||
$(COMPILER) $(BASE_OPTIONS) -O3 -march=native -fprofile-generate -o exprtk_test exprtk_test.cpp $(LINKER_OPT)
|
$(COMPILER) $(BASE_OPTIONS) -O3 -march=native -fprofile-generate -o exprtk_test exprtk_test.cpp $(LINKER_OPT)
|
||||||
|
$(COMPILER) $(BASE_OPTIONS) -O3 -march=native -fprofile-generate -o exprtk_benchmark exprtk_benchmark.cpp $(LINKER_OPT)
|
||||||
|
./exprtk_test
|
||||||
|
./exprtk_benchmark
|
||||||
|
$(COMPILER) $(BASE_OPTIONS) -O3 -march=native -fprofile-use -o exprtk_test exprtk_test.cpp $(LINKER_OPT)
|
||||||
|
$(COMPILER) $(BASE_OPTIONS) -O3 -march=native -fprofile-use -o exprtk_benchmark exprtk_benchmark.cpp $(LINKER_OPT)
|
||||||
|
|
||||||
strip_bin:
|
strip_bin:
|
||||||
strip -s exprtk_test
|
strip -s exprtk_test
|
||||||
|
|
2990
exprtk.hpp
2990
exprtk.hpp
File diff suppressed because it is too large
Load Diff
174
exprtk_test.cpp
174
exprtk_test.cpp
|
@ -27,6 +27,8 @@ typedef std::pair<std::string,double> test_t;
|
||||||
|
|
||||||
static const test_t test_list[] =
|
static const test_t test_list[] =
|
||||||
{
|
{
|
||||||
|
// Note: The each of following tests should
|
||||||
|
// all compile down to a single literal node.
|
||||||
test_t("0",0.0),
|
test_t("0",0.0),
|
||||||
test_t("1",1.0),
|
test_t("1",1.0),
|
||||||
test_t("2",2.0),
|
test_t("2",2.0),
|
||||||
|
@ -37,6 +39,11 @@ static const test_t test_list[] =
|
||||||
test_t("7",7.0),
|
test_t("7",7.0),
|
||||||
test_t("8",8.0),
|
test_t("8",8.0),
|
||||||
test_t("9",9.0),
|
test_t("9",9.0),
|
||||||
|
test_t("12.12",12.12),
|
||||||
|
test_t("123.123",123.123),
|
||||||
|
test_t("1234.1234",1234.1234),
|
||||||
|
test_t("12345.12345",12345.12345),
|
||||||
|
test_t("123456.123456",123456.123456),
|
||||||
test_t("0.0",0.0),
|
test_t("0.0",0.0),
|
||||||
test_t("1.0",1.0),
|
test_t("1.0",1.0),
|
||||||
test_t("2.0",2.0),
|
test_t("2.0",2.0),
|
||||||
|
@ -710,7 +717,7 @@ inline bool test_expression(const std::string& expression_string, const T& expec
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline bool run_test0()
|
inline bool run_test0()
|
||||||
{
|
{
|
||||||
const std::size_t rounds = 10000;
|
const std::size_t rounds = 100;
|
||||||
for (std::size_t r = 0; r < rounds; ++r)
|
for (std::size_t r = 0; r < rounds; ++r)
|
||||||
{
|
{
|
||||||
for (std::size_t i = 0; i < test_list_size; ++i)
|
for (std::size_t i = 0; i < test_list_size; ++i)
|
||||||
|
@ -722,8 +729,112 @@ inline bool run_test0()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct test_xy
|
||||||
|
{
|
||||||
|
test_xy(std::string e, const T& v0, const T& v1, const T& r)
|
||||||
|
: expr(e),
|
||||||
|
x(v0),
|
||||||
|
y(v1),
|
||||||
|
result(r)
|
||||||
|
{}
|
||||||
|
|
||||||
|
std::string expr;
|
||||||
|
T x;
|
||||||
|
T y;
|
||||||
|
T result;
|
||||||
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline bool run_test1()
|
inline bool run_test1()
|
||||||
|
{
|
||||||
|
static const test_xy<T> test_list[] =
|
||||||
|
{
|
||||||
|
test_xy<T>("x + y" ,T(2.2),T(3.3),T(5.5 )),
|
||||||
|
test_xy<T>("x - y" ,T(3.3),T(2.2),T(1.1 )),
|
||||||
|
test_xy<T>("x * y" ,T(3.3),T(2.2),T(7.26 )),
|
||||||
|
test_xy<T>("x / y" ,T(3.3),T(2.2),T(1.5 )),
|
||||||
|
test_xy<T>("(x + y) * (x + y)" ,T(2.2),T(3.3),T(30.25)),
|
||||||
|
test_xy<T>("(x + y) / (x + y)" ,T(2.2),T(3.3),T(1.0 )),
|
||||||
|
test_xy<T>("x + y > x and x + y > y" ,T(2.2),T(3.3),T(1.0)),
|
||||||
|
test_xy<T>("1 + (x + y)" ,T(2.2),T(3.3),T(6.5 )),
|
||||||
|
test_xy<T>("(x + y) - 1" ,T(2.2),T(3.3),T(4.5 )),
|
||||||
|
test_xy<T>("1 + (x + y) * 2" ,T(2.2),T(3.3),T(12.0 )),
|
||||||
|
test_xy<T>("2 * (x + y) - 1" ,T(2.2),T(3.3),T(10.0 )),
|
||||||
|
test_xy<T>("y + (x + 1)" ,T(2.2),T(3.3),T(6.5 )),
|
||||||
|
test_xy<T>("(x + 1) + y" ,T(2.2),T(3.3),T(6.5 )),
|
||||||
|
test_xy<T>("2 * x" ,T(2.2),T(0.0),T(4.4)),
|
||||||
|
test_xy<T>("x * 2" ,T(2.2),T(0.0),T(4.4)),
|
||||||
|
test_xy<T>("1.1 + x",T(2.2),T(0.0),T(3.3)),
|
||||||
|
test_xy<T>("x + 1.1",T(2.2),T(0.0),T(3.3)),
|
||||||
|
test_xy<T>("x * 1 == x" ,T(2.0),T(3.0),T(1.0)),
|
||||||
|
test_xy<T>("1 * x == x" ,T(2.0),T(3.0),T(1.0)),
|
||||||
|
test_xy<T>("y * 1 == y" ,T(2.0),T(3.0),T(1.0)),
|
||||||
|
test_xy<T>("1 * y == y" ,T(2.0),T(3.0),T(1.0)),
|
||||||
|
test_xy<T>("x * 0 == 0" ,T(2.0),T(3.0),T(1.0)),
|
||||||
|
test_xy<T>("0 * x == 0" ,T(2.0),T(3.0),T(1.0)),
|
||||||
|
test_xy<T>("y * 0 == 0" ,T(2.0),T(3.0),T(1.0)),
|
||||||
|
test_xy<T>("0 * y == 0" ,T(2.0),T(3.0),T(1.0)),
|
||||||
|
test_xy<T>("x + 1 == 1 + x",T(2.0),T(3.0),T(1.0)),
|
||||||
|
test_xy<T>("y + 1 == 1 + y",T(2.0),T(3.0),T(1.0)),
|
||||||
|
test_xy<T>("x + y == y + x",T(2.0),T(3.0),T(1.0)),
|
||||||
|
test_xy<T>("x * y == y * x",T(2.0),T(3.0),T(1.0)),
|
||||||
|
test_xy<T>("x < y" ,T(2.0),T(3.0),T(1.0)),
|
||||||
|
test_xy<T>("y > x" ,T(2.0),T(3.0),T(1.0)),
|
||||||
|
test_xy<T>("x <= y" ,T(2.0),T(3.0),T(1.0)),
|
||||||
|
test_xy<T>("y >= x" ,T(2.0),T(3.0),T(1.0)),
|
||||||
|
test_xy<T>("x + y > y" ,T(2.0),T(3.0),T(1.0)),
|
||||||
|
test_xy<T>("x + y > x" ,T(2.0),T(3.0),T(1.0)),
|
||||||
|
test_xy<T>("x * y > y" ,T(2.0),T(3.0),T(1.0)),
|
||||||
|
test_xy<T>("x * y > x" ,T(2.0),T(3.0),T(1.0)),
|
||||||
|
test_xy<T>("(x + y) > y" ,T(2.0),T(3.0),T(1.0)),
|
||||||
|
test_xy<T>("(x + y) > x" ,T(2.0),T(3.0),T(1.0)),
|
||||||
|
test_xy<T>("(x * y) > y" ,T(2.0),T(3.0),T(1.0)),
|
||||||
|
test_xy<T>("(x * y) > x" ,T(2.0),T(3.0),T(1.0))
|
||||||
|
};
|
||||||
|
|
||||||
|
static const std::size_t test_list_size = sizeof(test_list) / sizeof(test_xy<T>);
|
||||||
|
|
||||||
|
const std::size_t rounds = 10000;
|
||||||
|
for (std::size_t r = 0; r < rounds; ++r)
|
||||||
|
{
|
||||||
|
for (std::size_t i = 0; i < test_list_size; ++i)
|
||||||
|
{
|
||||||
|
test_xy<T>& test = const_cast<test_xy<T>&>(test_list[i]);
|
||||||
|
|
||||||
|
exprtk::symbol_table<T> symbol_table;
|
||||||
|
symbol_table.add_variable("x",test.x);
|
||||||
|
symbol_table.add_variable("y",test.y);
|
||||||
|
|
||||||
|
exprtk::expression<T> expression;
|
||||||
|
expression.register_symbol_table(symbol_table);
|
||||||
|
|
||||||
|
{
|
||||||
|
exprtk::parser<T> parser;
|
||||||
|
if (!parser.compile(test.expr,expression))
|
||||||
|
{
|
||||||
|
std::cout << "test_expression() - Error: " << parser.error() << "\tExpression: " << test.expr << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
T result = expression.value();
|
||||||
|
if (not_equal<T>(result,test.result))
|
||||||
|
{
|
||||||
|
printf("Computation Error: Expression: [%s]\tExpected: %19.15f\tResult: %19.15f\n",
|
||||||
|
test.expr.c_str(),
|
||||||
|
test.result,
|
||||||
|
result);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline bool run_test2()
|
||||||
{
|
{
|
||||||
std::string expression_string = "a+b+c+d+e+f+g+h+i+j+k+l+m+n+o+p+q+r+s+t+u+v+w+x+y+z+"
|
std::string expression_string = "a+b+c+d+e+f+g+h+i+j+k+l+m+n+o+p+q+r+s+t+u+v+w+x+y+z+"
|
||||||
"A+B+C+D+E+F+G+H+I+J+K+L+M+N+O+P+Q+R+S+T+U+V+W+X+Y+Z+"
|
"A+B+C+D+E+F+G+H+I+J+K+L+M+N+O+P+Q+R+S+T+U+V+W+X+Y+Z+"
|
||||||
|
@ -761,6 +872,10 @@ inline bool run_test1()
|
||||||
|
|
||||||
static const std::size_t variable_list_size = sizeof(variable_list) / sizeof(std::string);
|
static const std::size_t variable_list_size = sizeof(variable_list) / sizeof(std::string);
|
||||||
|
|
||||||
|
static const std::size_t rounds = 10000;
|
||||||
|
|
||||||
|
for (std::size_t r = 0; r < rounds; ++r)
|
||||||
|
{
|
||||||
exprtk::expression<T> expression;
|
exprtk::expression<T> expression;
|
||||||
exprtk::symbol_table<T> symbol_table;
|
exprtk::symbol_table<T> symbol_table;
|
||||||
|
|
||||||
|
@ -785,6 +900,7 @@ inline bool run_test1()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
expression.value();
|
expression.value();
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -795,7 +911,7 @@ inline T clamp(const T& l, const T& v, const T& u)
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline bool run_test2()
|
inline bool run_test3()
|
||||||
{
|
{
|
||||||
std::string expression_string = "clamp(-1.0,sin(2 * pi * x) + cos(y / 2 * pi),+1.0)";
|
std::string expression_string = "clamp(-1.0,sin(2 * pi * x) + cos(y / 2 * pi),+1.0)";
|
||||||
|
|
||||||
|
@ -822,6 +938,7 @@ inline bool run_test2()
|
||||||
}
|
}
|
||||||
|
|
||||||
const T pi = T(3.14159265358979323846);
|
const T pi = T(3.14159265358979323846);
|
||||||
|
const T increment = T(0.0001);
|
||||||
|
|
||||||
while ((x <= T(+1000.0)) && (y <= T(+1000.0)))
|
while ((x <= T(+1000.0)) && (y <= T(+1000.0)))
|
||||||
{
|
{
|
||||||
|
@ -837,14 +954,14 @@ inline bool run_test2()
|
||||||
y);
|
y);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
x += 0.001;
|
x += increment;
|
||||||
y += 0.001;
|
y += increment;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline bool run_test3()
|
inline bool run_test4()
|
||||||
{
|
{
|
||||||
typedef exprtk::expression<T> expression_t;
|
typedef exprtk::expression<T> expression_t;
|
||||||
std::string expression_string = "clamp(-1.0,sin(2 * pi * x_var123) + cos(y_var123 / 2 * pi),+1.0)";
|
std::string expression_string = "clamp(-1.0,sin(2 * pi * x_var123) + cos(y_var123 / 2 * pi),+1.0)";
|
||||||
|
@ -875,6 +992,7 @@ inline bool run_test3()
|
||||||
}
|
}
|
||||||
|
|
||||||
const T pi = T(3.14159265358979323846);
|
const T pi = T(3.14159265358979323846);
|
||||||
|
const T increment = T(0.0001);
|
||||||
|
|
||||||
while ((x <= T(+1000.0)) && (y <= T(+1000.0)))
|
while ((x <= T(+1000.0)) && (y <= T(+1000.0)))
|
||||||
{
|
{
|
||||||
|
@ -896,14 +1014,14 @@ inline bool run_test3()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
x += 0.001;
|
x += increment;
|
||||||
y += 0.001;
|
y += increment;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline bool run_test4()
|
inline bool run_test5()
|
||||||
{
|
{
|
||||||
typedef exprtk::expression<T> expression_t;
|
typedef exprtk::expression<T> expression_t;
|
||||||
std::string expression_string = "sqrt(1 - (x^2))";
|
std::string expression_string = "sqrt(1 - (x^2))";
|
||||||
|
@ -945,10 +1063,10 @@ inline bool run_test4()
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline bool run_test5()
|
inline bool run_test6()
|
||||||
{
|
{
|
||||||
typedef exprtk::expression<T> expression_t;
|
typedef exprtk::expression<T> expression_t;
|
||||||
std::string expression_string = "sin(2*x)";
|
std::string expression_string = "sin(2x+1/3)";
|
||||||
|
|
||||||
T x = T(0.0);
|
T x = T(0.0);
|
||||||
|
|
||||||
|
@ -970,7 +1088,7 @@ inline bool run_test5()
|
||||||
{
|
{
|
||||||
T result1 = exprtk::derivative(expression,x);
|
T result1 = exprtk::derivative(expression,x);
|
||||||
T result2 = exprtk::derivative(expression,"x");
|
T result2 = exprtk::derivative(expression,"x");
|
||||||
T real_result = T(2.0) * std::cos(T(2.0) * x);
|
T real_result = T(2.0) * std::cos(T(2.0) * x + T(1.0/3.0));
|
||||||
|
|
||||||
if (not_equal<T>(result1,result2,0.000000001))
|
if (not_equal<T>(result1,result2,0.000000001))
|
||||||
{
|
{
|
||||||
|
@ -990,7 +1108,7 @@ inline bool run_test5()
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline bool run_test6()
|
inline bool run_test7()
|
||||||
{
|
{
|
||||||
|
|
||||||
static const std::string expr_str[] =
|
static const std::string expr_str[] =
|
||||||
|
@ -1021,6 +1139,13 @@ inline bool run_test6()
|
||||||
"avg(x,y,z,w)",
|
"avg(x,y,z,w)",
|
||||||
"avg(x,y,z,w,u)",
|
"avg(x,y,z,w,u)",
|
||||||
"(u := u <- min(x:=1,y:=2,z:=3)) == 1",
|
"(u := u <- min(x:=1,y:=2,z:=3)) == 1",
|
||||||
|
"(2x+3y+4z+5w)==(2*x+3*y+4*z+5*w)",
|
||||||
|
"(3(x+y)/2+1)==(3*(x+y)/2+1)",
|
||||||
|
"((x+y)3+1/4)==((x+y)*3+1/4)",
|
||||||
|
"((x+y)z+1/2)==((x+y)*z+1/2)",
|
||||||
|
"(3min(x,y))==(3*min(x,y))",
|
||||||
|
"(sin(x)y)==(sin(x)*y)",
|
||||||
|
"(sin(x)cos(y)+1)==(sin(x)*cos(y)+1)",
|
||||||
"equal($f00(x,y,z),((x+y)/z))",
|
"equal($f00(x,y,z),((x+y)/z))",
|
||||||
"equal($f01(x,y,z),((x+y)*z))",
|
"equal($f01(x,y,z),((x+y)*z))",
|
||||||
"equal($f02(x,y,z),((x-y)/z))",
|
"equal($f02(x,y,z),((x-y)/z))",
|
||||||
|
@ -1115,7 +1240,7 @@ struct myfunc : public exprtk::ifunction<T>
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline bool run_test7()
|
inline bool run_test8()
|
||||||
{
|
{
|
||||||
static const std::size_t rounds = 100000;
|
static const std::size_t rounds = 100000;
|
||||||
for (std::size_t i = 0; i < rounds; ++i)
|
for (std::size_t i = 0; i < rounds; ++i)
|
||||||
|
@ -1164,16 +1289,16 @@ inline bool run_test7()
|
||||||
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) +
|
T expected = mf(sin(x*pi),y/2.0) +
|
||||||
mf(sin(x*pi),y/2) +
|
mf(sin(x*pi),y/2.0) +
|
||||||
mf(sin(x*pi),y/2) +
|
mf(sin(x*pi),y/2.0) +
|
||||||
mf(sin(x*pi),y/2) +
|
mf(sin(x*pi),y/2.0) +
|
||||||
mf(sin(x*pi),y/2) +
|
mf(sin(x*pi),y/2.0) +
|
||||||
mf(sin(x*pi),y/2) +
|
mf(sin(x*pi),y/2.0) +
|
||||||
mf(sin(x*pi),y/2) +
|
mf(sin(x*pi),y/2.0) +
|
||||||
mf(sin(x*pi),y/2) +
|
mf(sin(x*pi),y/2.0) +
|
||||||
mf(sin(x*pi),y/2) +
|
mf(sin(x*pi),y/2.0) +
|
||||||
mf(sin(x*pi),y/2);
|
mf(sin(x*pi),y/2.0);
|
||||||
|
|
||||||
if (not_equal<T>(result,expected,0.0000001))
|
if (not_equal<T>(result,expected,0.0000001))
|
||||||
{
|
{
|
||||||
|
@ -1196,7 +1321,8 @@ int main()
|
||||||
run_test4<double>() &&
|
run_test4<double>() &&
|
||||||
run_test5<double>() &&
|
run_test5<double>() &&
|
||||||
run_test6<double>() &&
|
run_test6<double>() &&
|
||||||
run_test7<double>()
|
run_test7<double>() &&
|
||||||
|
run_test8<double>()
|
||||||
)
|
)
|
||||||
? 0 : 1;
|
? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,3 +46,4 @@ Expression Library can be found at:
|
||||||
(01) readme.txt
|
(01) readme.txt
|
||||||
(02) exprtk.hpp
|
(02) exprtk.hpp
|
||||||
(03) exprtk_test.cpp
|
(03) exprtk_test.cpp
|
||||||
|
(04) exprtk_benchmark.cpp
|
||||||
|
|
Loading…
Reference in New Issue