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

This commit is contained in:
Arash Partow
2013-03-05 00:21:28 +11:00
parent 2a0be4d5a3
commit 6431bf3b0e
5 changed files with 5510 additions and 2338 deletions

View File

@ -28,8 +28,9 @@ const std::string expression_list[] = {
"(y + x)",
"2 * (y + x)",
"(2 * y + 2 * x)",
"((1.23 * x^2) / y) - 123.123",
"(y + x / y) * (x - y / x)",
"x / ((x + y) * (x - y)) / y",
"x / ((x + y) + (x - y)) / y",
"1 - ((x * y) + (y / x)) - 3",
"1.1x^1 + 2.2y^2 - 3.3x^3 + 4.4y^15 - 5.5x^23 + 6.6y^55",
"sin(2 * x) + cos(pi / y)",
@ -49,31 +50,27 @@ static const double lower_bound_x = -100.0;
static const double lower_bound_y = -100.0;
static const double upper_bound_x = +100.0;
static const double upper_bound_y = +100.0;
static const double delta = 0.0173;
static const double delta = 0.0111;
template <typename T,
typename Allocator,
template <typename,typename> class Sequence>
bool load_expression(exprtk::symbol_table<T>& symbol_table,
Sequence<exprtk::expression<T>,Allocator>& expr_seq,
const typename exprtk::parser<T>::optimization_level& opt_level)
Sequence<exprtk::expression<T>,Allocator>& expr_seq)
{
exprtk::parser<double> parser;
for (std::size_t i = 0; i < expression_list_size; ++i)
{
exprtk::expression<double> expression;
expression.register_symbol_table(symbol_table);
if (!parser.compile(expression_list[i],expression,opt_level))
if (!parser.compile(expression_list[i],expression))
{
printf("[load_expression] - Parser Error: %s\tExpression: %s\n",
parser.error().c_str(),
expression_list[i].c_str());
return false;
}
expr_seq.push_back(expression);
}
return true;
@ -84,12 +81,10 @@ void run_exprtk_benchmark(T& x, T& y,
exprtk::expression<T>& expression,
const std::string& expr_string)
{
double total = 0.0;
T total = 0.0;
unsigned int count = 0;
exprtk::timer timer;
timer.start();
for (x = lower_bound_x; x <= upper_bound_x; x += delta)
{
for (y = lower_bound_y; y <= upper_bound_y; y += delta)
@ -98,9 +93,7 @@ void run_exprtk_benchmark(T& x, T& y,
++count;
}
}
timer.stop();
if (T(0.0) != total)
printf("[exprtk] Total Time:%12.8f Rate:%14.3fevals/sec Expression: %s\n",
timer.time(),
@ -110,31 +103,15 @@ void run_exprtk_benchmark(T& x, T& y,
printf("run_exprtk_benchmark() - Error running benchmark for expression: %s\n",expr_string.c_str());
}
template <typename T> inline T func00(const T x, const T y);
template <typename T> inline T func01(const T x, const T y);
template <typename T> inline T func02(const T x, const T y);
template <typename T> inline T func03(const T x, const T y);
template <typename T> inline T func04(const T x, const T y);
template <typename T> inline T func05(const T x, const T y);
template <typename T> inline T func06(const T x, const T y);
template <typename T> inline T func07(const T x, const T y);
template <typename T> inline T func08(const T x, const T y);
template <typename T> inline T func09(const T x, const T y);
template <typename T> inline T func10(const T x, const T y);
template <typename T> inline T func11(const T x, const T y);
template <typename T> inline T func12(const T x, const T y);
template <typename T> inline T func13(const T x, const T y);
template <typename T> inline T func14(const T x, const T y);
template <typename T> struct native;
template <typename T, typename NativeFunction>
void run_native_benchmark(T& x, T& y, NativeFunction f, const std::string& expr_string)
{
double total = 0.0;
T total = 0.0;
unsigned int count = 0;
exprtk::timer timer;
timer.start();
for (x = lower_bound_x; x <= upper_bound_x; x += delta)
{
for (y = lower_bound_y; y <= upper_bound_y; y += delta)
@ -143,9 +120,7 @@ void run_native_benchmark(T& x, T& y, NativeFunction f, const std::string& expr_
++count;
}
}
timer.stop();
if (T(0.0) != total)
printf("[native] Total Time:%12.8f Rate:%14.3fevals/sec Expression: %s\n",
timer.time(),
@ -158,7 +133,7 @@ void run_native_benchmark(T& x, T& y, NativeFunction f, const std::string& expr_
template <typename T>
bool run_parse_benchmark(exprtk::symbol_table<T>& symbol_table)
{
static const std::size_t rounds = 1000000;
static const std::size_t rounds = 100000;
exprtk::parser<double> parser;
exprtk::expression<double> expression;
@ -168,7 +143,6 @@ bool run_parse_benchmark(exprtk::symbol_table<T>& symbol_table)
{
exprtk::timer timer;
timer.start();
for (std::size_t r = 0; r < rounds; ++r)
{
if (!parser.compile(expression_list[i],expression))
@ -176,13 +150,10 @@ bool run_parse_benchmark(exprtk::symbol_table<T>& symbol_table)
printf("[run_parse_benchmark] - Parser Error: %s\tExpression: %s\n",
parser.error().c_str(),
expression_list[i].c_str());
return false;
}
}
timer.stop();
printf("[parse] Total Time:%12.8f Rate:%14.3fparse/sec Expression: %s\n",
timer.time(),
rounds / timer.time(),
@ -191,6 +162,105 @@ bool run_parse_benchmark(exprtk::symbol_table<T>& symbol_table)
return true;
}
const double pi = 3.14159265358979323846;
template <typename T>
struct native
{
typedef typename exprtk::details::functor_t<T> functor_t;
typedef typename functor_t::Type Type;
static inline T avg(Type x, Type y)
{
return (x + y) / T(2.0);
}
static inline T clamp(const Type l, const Type v, const Type u)
{
return ((v < l) ? l : ((v > u) ? u : v));
}
static inline T func00(Type x, Type y)
{
return (y + x);
}
static inline T func01(Type x, Type y)
{
return T(2.0) * (y + x);
}
static inline T func02(Type x, Type y)
{
return (T(2.0) * y + T(2.0) * x);
}
static inline T func03(Type x, Type y)
{
return ((T(1.23) * (x * x)) / y) - T(123.123);
}
static inline T func04(Type x, Type y)
{
return (y + x / y) * (x - y / x);
}
static inline T func05(Type x, Type y)
{
return x / ((x + y) + (x - y)) / y;
}
static inline T func06(Type x, Type y)
{
return T(1.0) - ((x * y) + (y / x)) - T(3.0);
}
static inline T func07(Type x, Type y)
{
return (1.1*pow(x,T(1.0))+2.2*pow(y,T(2.0))-3.3*pow(x,T(3.0))+4.4*pow(y,T(15.0))-5.5*pow(x,T(23.0))+6.6*pow(y,T(55.0)));
}
static inline T func08(Type x, Type y)
{
return std::sin(T(2.0) * x) + std::cos(pi / y);
}
static inline T func09(Type x, Type y)
{
return T(1.0) - std::sin(2.0 * x) + std::cos(pi / y);
}
static inline T func10(Type x, Type y)
{
return std::sqrt(T(111.111) - std::sin(T(2.0) * x) + std::cos(pi / y) / T(333.333));
}
static inline T func11(Type x, Type y)
{
return ((x * x) / std::sin(T(2.0) * pi / y)) -x / T(2.0);
}
static inline T func12(Type x, Type y)
{
return (x + (std::cos(y - std::sin(2 / x * pi)) - std::sin(x - std::cos(2 * y / pi))) - y);
}
static inline T func13(Type x, Type y)
{
return clamp(T(-1.0), std::sin(T(2.0) * pi * x) + std::cos(y / T(2.0) * pi), + T(1.0));
}
static inline T func14(Type x, Type y)
{
return std::max(T(3.33), std::min(sqrt(T(1.0) - std::sin(T(2.0) * x) + std::cos(pi / y) / T(3.0)), T(1.11)));
}
static inline T func15(Type x, Type y)
{
return ((avg(x,y) <= x + y) ? x - y : x * y) + T(2.0) * pi / x;
}
};
void pgo_primer();
int main()
@ -205,27 +275,15 @@ int main()
symbol_table.add_variable("x",x);
symbol_table.add_variable("y",y);
std::deque<exprtk::expression<double> > optimized_expr_list;
std::deque<exprtk::expression<double> > expr_list;
if (!load_expression(symbol_table,optimized_expr_list,exprtk::parser<double>::e_all))
{
return 1;
}
if (!load_expression(symbol_table,expr_list,exprtk::parser<double>::e_none))
if (!load_expression(symbol_table,expr_list))
{
return 1;
}
{
std::cout << "--- EXPRTK [All Optimisations] ---" << std::endl;
for (std::size_t i = 0; i < optimized_expr_list.size(); ++i)
{
run_exprtk_benchmark(x,y,optimized_expr_list[i],expression_list[i]);
}
std::cout << "--- EXPRTK [No Optimisations] ---" << std::endl;
std::cout << "--- EXPRTK ---" << std::endl;
for (std::size_t i = 0; i < expr_list.size(); ++i)
{
run_exprtk_benchmark(x,y,expr_list[i],expression_list[i]);
@ -234,21 +292,22 @@ int main()
{
std::cout << "--- NATIVE ---" << std::endl;
run_native_benchmark(x,y,func00<double>,expression_list[ 0]);
run_native_benchmark(x,y,func01<double>,expression_list[ 1]);
run_native_benchmark(x,y,func02<double>,expression_list[ 2]);
run_native_benchmark(x,y,func03<double>,expression_list[ 3]);
run_native_benchmark(x,y,func04<double>,expression_list[ 4]);
run_native_benchmark(x,y,func05<double>,expression_list[ 5]);
run_native_benchmark(x,y,func06<double>,expression_list[ 6]);
run_native_benchmark(x,y,func07<double>,expression_list[ 7]);
run_native_benchmark(x,y,func08<double>,expression_list[ 8]);
run_native_benchmark(x,y,func09<double>,expression_list[ 9]);
run_native_benchmark(x,y,func10<double>,expression_list[10]);
run_native_benchmark(x,y,func11<double>,expression_list[11]);
run_native_benchmark(x,y,func12<double>,expression_list[12]);
run_native_benchmark(x,y,func13<double>,expression_list[13]);
run_native_benchmark(x,y,func14<double>,expression_list[14]);
run_native_benchmark(x,y,native<double>::func00,expression_list[ 0]);
run_native_benchmark(x,y,native<double>::func01,expression_list[ 1]);
run_native_benchmark(x,y,native<double>::func02,expression_list[ 2]);
run_native_benchmark(x,y,native<double>::func03,expression_list[ 3]);
run_native_benchmark(x,y,native<double>::func04,expression_list[ 4]);
run_native_benchmark(x,y,native<double>::func05,expression_list[ 5]);
run_native_benchmark(x,y,native<double>::func06,expression_list[ 6]);
run_native_benchmark(x,y,native<double>::func07,expression_list[ 7]);
run_native_benchmark(x,y,native<double>::func08,expression_list[ 8]);
run_native_benchmark(x,y,native<double>::func09,expression_list[ 9]);
run_native_benchmark(x,y,native<double>::func10,expression_list[10]);
run_native_benchmark(x,y,native<double>::func11,expression_list[11]);
run_native_benchmark(x,y,native<double>::func12,expression_list[12]);
run_native_benchmark(x,y,native<double>::func13,expression_list[13]);
run_native_benchmark(x,y,native<double>::func14,expression_list[14]);
run_native_benchmark(x,y,native<double>::func15,expression_list[15]);
}
{
@ -267,7 +326,7 @@ void pgo_primer()
static const double lower_bound_y = -50.0;
static const double upper_bound_x = +50.0;
static const double upper_bound_y = +50.0;
static const double delta = 0.03;
static const double delta = 0.07;
double total = 0.0;
@ -275,125 +334,23 @@ void pgo_primer()
{
for (double y = lower_bound_y; y <= upper_bound_y; y += delta)
{
total += func00<double>(x,y);
total += func01<double>(x,y);
total += func02<double>(x,y);
total += func03<double>(x,y);
total += func04<double>(x,y);
total += func05<double>(x,y);
total += func06<double>(x,y);
total += func07<double>(x,y);
total += func08<double>(x,y);
total += func09<double>(x,y);
total += func10<double>(x,y);
total += func11<double>(x,y);
total += func12<double>(x,y);
total += func13<double>(x,y);
total += func14<double>(x,y);
total += native<double>::func00(x,y);
total += native<double>::func01(x,y);
total += native<double>::func02(x,y);
total += native<double>::func03(x,y);
total += native<double>::func04(x,y);
total += native<double>::func05(x,y);
total += native<double>::func06(x,y);
total += native<double>::func07(x,y);
total += native<double>::func08(x,y);
total += native<double>::func09(x,y);
total += native<double>::func10(x,y);
total += native<double>::func11(x,y);
total += native<double>::func12(x,y);
total += native<double>::func13(x,y);
total += native<double>::func14(x,y);
total += native<double>::func15(x,y);
}
}
}
const double pi = 3.14159265358979323846;
template <typename T>
inline T avg(const T v1, const T v2)
{
return (v1 + v2) / T(2.0);
}
template <typename T>
inline T clamp(const T l, const T v, const T u)
{
return ((v < l) ? l : ((v > u) ? u : v));
}
template <typename T>
inline T func00(const T x, const T y)
{
return (y + x);
}
template <typename T>
inline T func01(const T x, const T y)
{
return T(2.0) * (y + x);
}
template <typename T>
inline T func02(const T x, const T y)
{
return (T(2.0) * y + T(2.0) * x);
}
template <typename T>
inline T func03(const T x, const T y)
{
return (y + x / y) * (x - y / x);
}
template <typename T>
inline T func04(const T x, const T y)
{
return x / ((x + y) * (x - y)) / y;
}
template <typename T>
inline T func05(const T x, const T y)
{
return T(1.0) - ((x * y) + (y / x)) - T(3.0);
}
template <typename T>
inline T func06(const T x, const T y)
{
return (1.1*pow(x,T(1.0))+2.2*pow(y,T(2.0))-3.3*pow(x,T(3.0))+4.4*pow(y,T(15.0))-5.5*pow(x,T(23.0))+6.6*pow(y,T(55.0)));
}
template <typename T>
inline T func07(const T x, const T y)
{
return std::sin(T(2.0) * x) + std::cos(pi / y);
}
template <typename T>
inline T func08(const T x, const T y)
{
return T(1.0) - std::sin(2.0 * x) + std::cos(pi / y);
}
template <typename T>
inline T func09(const T x, const T y)
{
return std::sqrt(T(111.111) - std::sin(T(2.0) * x) + std::cos(pi / y) / T(333.333));
}
template <typename T>
inline T func10(const T x, const T y)
{
return (std::pow(x,T(2.0)) / std::sin(T(2.0) * pi / y)) -x / T(2.0);
}
template <typename T>
inline T func11(const T x, const T y)
{
return (x + (std::cos(y - std::sin(2 / x * pi)) - std::sin(x - std::cos(2 * y / pi))) - y);
}
template <typename T>
inline T func12(const T x, const T y)
{
return clamp(T(-1.0), std::sin(T(2.0) * pi * x) + std::cos(y / T(2.0) * pi), + T(1.0));
}
template <typename T>
inline T func13(const T x, const T y)
{
return std::max(T(3.33), std::min(sqrt(T(1.0) - std::sin(T(2.0) * x) + std::cos(pi / y) / T(3.0)), T(1.11)));
}
template <typename T>
inline T func14(const T x, const T y)
{
return ((avg(x,y) <= x + y) ? x - y : x * y) + T(2.0) * pi / x;
}