C++ Mathematical Expression Library

 www.partow.net  .: Home :.   .: Links :.   .: Search :.   .: Contact :. 


Description

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:

  • Mathematical operators (+, -, *, /, %, ^)
  • Functions (min, max, avg, sum, abs, ceil, floor, round, roundn, exp, log, log10, logn, root, sqrt, clamp, range)
  • Trigonometry (sin, cos, tan, acos, asin, atan, atan2, cosh, cot, csc, sec, sinh, tanh, d2r, r2d, d2g, g2d, hyp)
  • Equalities, Inequalities and Assigment (=, ==, <>, !=, <, <=, >, >=, :=, <-)
  • Boolean logic, conditional statements and while-loop construct (and, or, xor, not, nand, nor, if-then-else, while)
  • 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:

  • GNU Compiler Collection (4.1+)
  • Intel® C++ Compiler (9.x+)
  • Clang/LLVM (1.1+)
  • Microsoft Visual Studio C++ Compiler (8.1+)

Download

The C++ Mathematical Expression Library Download - Copyright Arash Partow C++ Mathematical Expression Library Source Code and Examples

Example Expressions

The C++ Mathematical Expression Library Example - Copyright Arash Partow

  • sqrt(1 - (x^2))
  • clamp(-1,sin(2 * pi * x) + cos(y / 2 * pi),+1)
  • sin(2 * x)
  • if(((x + 2) == 3) and ((y + 5) <= 9),1 + w, 2 / z)
  • inrange(-2,m,+2) == if(({-2 <= m} and [m <= +2]),1,0)
  • ({1 / 1} * [1 / 2] + (1 / 3)) - {1 / 4} ^ [1 / 5] + (1 / 6) -({1 / 7} + [1 / 8]*(1 / 9))
  • a * exp(2 * t) + c
  • z := x + sin(2 * pi / y)
  • u <- 2 * (pi * z) / (w := x + cos(y / pi))
  • 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
  • (sin(x/pi)cos(2y) + 1)==(sin(x / pi) * cos(2 * y) + 1)
  • 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);
   }
}
                     

The C++ Mathematical Expression Library Graph - Copyright Arash Partow

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);
   }
}
                     

The C++ Mathematical Expression Library Sqaure Wave Graph - Copyright Arash Partow

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.

  • (y + x / y) * (x - y / x)
  • x / ((x + y) * (x - y)) / y
  • sin(2 * x) + cos(pi / y)
  • 1 - sin(2 * x) + cos(pi / y)
  • sqrt(1 - sin(2 * x) + cos(pi / y) / 3)
  • (x^2 / sin(2 * pi / y)) -x / 2
  • clamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)
  • max(3.33, min(sqrt(1 - sin(2 * x) + cos(pi / y) / 3), 1.11))
  • if(avg(x,y) <= x + y, x - y, x * y) + 2 * pi / x

The C++ Mathematical Expression Library Benchmark Result - Copyright Arash Partow




Copyright Arash Partow