The C++ Mathematical Expression Library (ExprTk) is a simple to use, easy to integrate
and extremely efficient and fast mathematical expression parsing and evaluation engine.
The parsing engine supports various kinds of functional, logic processing semantics
and is very easily extendible.
Capabilities
The ExprTk library has the following capabilities:
Simple optimizations of expressions (constant folding and special functions for common arithmetic sequences)
Numeric integration and differentiation
Multiple and custom variable support
User defined function support
Template type support for numeric POD types(double, float, long double, int, long long)
Single header implementation, no building required.
C++ Mathematical Expression Library License
Free use of the C++ Mathematical Expression Library is permitted under the guidelines and in accordance with the most current
version of the "Common Public License."
Compatability
The C++ Mathematical Expression Library implementation is fully compatible with the following C++ compilers:
fib_i := fib_i + (x := y + 0 * (fib_i := x + (y := fib_i)))
while(x <= 100) { x := x + 1 }
Simple Example 1
The following is an example where a given single variable function is evaluated
between a specified range[-5,+5]. The graph below shows the clamped
(red) and non-clamped (blue) versions of the specified function.
template<typename T>
void trig_function()
{
std::string expression_string = "clamp(-1.0,sin(2 * pi * x) + cos(x / 2 * pi),+1.0)";
T x;
exprtk::expression<T> expression;
exprtk::symbol_table<T> symbol_table;
symbol_table.add_variable("x",x);
symbol_table.add_constants();
expression.assign_symbol_table(symbol_table);
exprtk::parser<T> parser;
parser.compile(expression_string,expression);
for (x = T(-5.0); x <= T(+5.0); x += 0.001)
{
T y = expression.value();
printf("%19.15f\t%19.15f\n",x,y);
}
}
Simple Example 2
The following example generates a square wave form based on Fourier series
accumulations - 14 harmonics. Theta-approximation is not applied hence Gibbs
phenomenon based ringing is observed on the edges of the square, as is
demonstrated in the graph below.
template<typename T>
void square_wave()
{
std::string expr_string = "a*(4/pi)*"
"((1 /1)*sin( 2*pi*f*t)+(1 /3)*sin( 6*pi*f*t)+"
" (1 /5)*sin(10*pi*f*t)+(1 /7)*sin(14*pi*f*t)+"
" (1 /9)*sin(18*pi*f*t)+(1/11)*sin(22*pi*f*t)+"
" (1/13)*sin(26*pi*f*t)+(1/15)*sin(30*pi*f*t)+"
" (1/17)*sin(34*pi*f*t)+(1/19)*sin(38*pi*f*t)+"
" (1/21)*sin(42*pi*f*t)+(1/23)*sin(46*pi*f*t)+"
" (1/25)*sin(50*pi*f*t)+(1/27)*sin(54*pi*f*t))";
static const T pi = T(3.14159265358979323846);
T f = pi/10.0;
T t = T(0.0);
T a = T(10.0);
exprtk::expression<T> expression;
exprtk::symbol_table<T> symbol_table;
symbol_table.add_variable("f",f);
symbol_table.add_variable("t",t);
symbol_table.add_variable("a",a);
symbol_table.add_constants();
expression.register_symbol_table(symbol_table);
exprtk::parser<T> parser;
parser.compile(expr_string,expression)
const T delta = (4.0*pi)/1000.0;
for (t = -2.0*pi; t <= +2.0*pi; t+=delta)
{
T result = expression.value();
printf("%19.15f\t%19.15f\n",t,result);
}
}
Simple Example 3
The following example generates the first 16 Fibonacci numbers
using a simple iterative method. The example demonstrates multiple
assignment points within a single expression.
template<typename T>
void fibonacci()
{
typedef exprtk::expression<T> expression_t;
std::string expression_string = "fib_i := fib_i + (x := y + 0 * (fib_i := x + (y := fib_i)))";
T x = T(0.0);
T y = T(1.0);
T fib_i = T(0.0);
exprtk::symbol_table<T> symbol_table;
symbol_table.add_variable("x",x);
symbol_table.add_variable("y",y);
symbol_table.add_variable("fib_i",fib_i);
expression_t expression;
expression.register_symbol_table(symbol_table);
exprtk::parser<T> parser;
parser.compile(expression_string,expression);
for (std::size_t i = 1; i <= 16; ++i)
{
expression.value();
printf("fib_%02d = %4.0f\n",i,fib_i);
}
}
Simple Example 4
The following example demonstrates how one can easily register a custom
user defined function to be used within expression evaluations. In this
example the custom function myfunc takes 2 parameters and returns
a result. At the moment an upper limit of 10 parameters is in place.
template<typename T>
struct myfunc : public exprtk::ifunction<T>
{
myfunc()
: exprtk::ifunction<T>(2)
{}
inline T operator()(const T& v1, const T& v2)
{
return T(1) + (v1 * v2) / T(3);
}
};
template<typename T>
void custom_function()
{
typedef exprtk::expression<T> expression_t;
std::string expression_string = "myfunc(sin(x*pi),y/2)";
T x = T(1.0);
T y = T(2.0);
myfunc<T> mf;
exprtk::symbol_table<T> symbol_table;
symbol_table.add_variable("x",x);
symbol_table.add_variable("y",y);
symbol_table.add_function("myfunc",mf);
symbol_table.add_constants();
expression_t expression;
expression.register_symbol_table(symbol_table);
exprtk::parser<T> parser;
parser.compile(expression_string,expression);
T result = expression.value();
}
Benchmarks
The graph below depicts the rate of expression evaluations per second
for an assortment of expressions as denoted below. It should be noted
each expression is specialised upon the double type and comprised
of two variables that are varied before each evaluation point. The
benchmark was compiled using GCC 4.7 with O3 and PGO settings, and
executed upon a 64-Bit Intel Quad Core Extreme i7-920XM 2.0GHz, 16GB RAM,
Ubuntu 10.10 kernel 2.6.35 system.