From b369bc342cc2246d8e58206d434479a41ab5a741 Mon Sep 17 00:00:00 2001 From: Arash Partow Date: Wed, 17 Jul 2013 08:21:06 +1000 Subject: [PATCH] C++ Mathematical Expression Library (ExprTk) http://www.partow.net/programming/exprtk/index.html --- exprtk.hpp | 12 ++++++++---- exprtk_test.cpp | 29 +++++++++++++++++++++++++++-- readme.txt | 25 +++++++++++++------------ 3 files changed, 48 insertions(+), 18 deletions(-) diff --git a/exprtk.hpp b/exprtk.hpp index bf9ca38..fd22846 100644 --- a/exprtk.hpp +++ b/exprtk.hpp @@ -763,7 +763,7 @@ namespace exprtk inline T erf_impl(T v, real_type_tag) { #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) - //Credits: Abramowitz & Stegun Equations 7.1.25–28 + //Credits: Abramowitz & Stegun Equations 7.1.25-28 const T t = T(1) / (T(1) + T(0.5) * std::abs(v)); static const T c[] = { T( 1.26551223), T(1.00002368), @@ -10458,7 +10458,7 @@ namespace exprtk inline expression_node_ptr parse_expression(precedence_level precedence = e_level00) { - expression_node_ptr expr = parse_branch(); + expression_node_ptr expr = parse_branch(precedence); if (0 == expr) { @@ -11961,7 +11961,7 @@ namespace exprtk } } - inline expression_node_ptr parse_branch() + inline expression_node_ptr parse_branch(precedence_level precedence = e_level00) { if (token_t::e_number == current_token_.type) { @@ -12017,7 +12017,11 @@ namespace exprtk else if (token_t::e_sub == current_token_.type) { next_token(); - return expression_generator_(details::e_neg,parse_expression(e_level09)); + return expression_generator_(details::e_neg, + // Was the previous operation exponentiation? + (e_level12 == precedence) ? + parse_branch (e_level09) : + parse_expression(e_level09)); } else if (token_t::e_add == current_token_.type) { diff --git a/exprtk_test.cpp b/exprtk_test.cpp index 4a0c105..5d1d00a 100644 --- a/exprtk_test.cpp +++ b/exprtk_test.cpp @@ -360,14 +360,33 @@ static const test_t test_list[] = test_t("-2^4",-16.0), test_t("(-2)^3",-8.0), test_t("(-2)^4",+16.0), - test_t("3^2^1",9.0), + test_t("3^2^4",43046721.0), test_t("1.1^2.2",1.23328630055466251099), test_t("2.2^1.1",2.3804822576003541627), test_t("2.2^3.3",13.48946876053338489127), test_t("3.3^2.2^1.1",17.15193942371376191362), - test_t("1.1^(1.1 * 2.2)", 1.25941916576299080582), + test_t("+3.3^2.2^1.1",17.15193942371376191362), + test_t("3.3^+2.2^1.1",17.15193942371376191362), + test_t("3.3^2.2^+1.1",17.15193942371376191362), + test_t("3.3^2.2^-1.1",1.65127293793867959137), + test_t("+3.3^+2.2^-1.1",1.65127293793867959137), + test_t("1.1^(1.1 * 2.2)",1.25941916576299080582), test_t("2.2^(1.1 * 3.3)",17.49823848953534759743), test_t("3.3^(1.1 * 2.2)",17.98058156638874965269), + test_t("1.1^-2.2/1.1",0.73712884727743375853), + test_t("1.1^+2.2/1.1",1.121169364140602282717273261774), + test_t("1.1^2.2/+1.1",1.121169364140602282717273261774), + test_t("1.1^+2.2/+1.1",1.121169364140602282717273261774), + test_t("1.1^+2.2/-1.1",-1.121169364140602282717273261774), + test_t("1.1^2.2/-1.1",-1.121169364140602282717273261774), + test_t("1.1^+2.2/-1.1",-1.121169364140602282717273261774), + test_t("+1.1^-2.2/1.1",0.73712884727743375853), + test_t("+1.1^+2.2/1.1",1.121169364140602282717273261774), + test_t("+1.1^2.2/+1.1",1.121169364140602282717273261774), + test_t("+1.1^+2.2/+1.1",1.121169364140602282717273261774), + test_t("+1.1^+2.2/-1.1",-1.121169364140602282717273261774), + test_t("+1.1^2.2/-1.1",-1.121169364140602282717273261774), + test_t("+1.1^+2.2/-1.1",-1.121169364140602282717273261774), test_t("equal(1.23^3,(1.23 * 1.23 * 1.23))",1.0), test_t("equal(1.23^-3,1/(1.23 * 1.23 * 1.23))",1.0), test_t("equal((2.1 + 1.23^3),(2.1 + [1.23 * 1.23 * 1.23]))",1.0), @@ -1158,6 +1177,12 @@ inline bool run_test01() test_xy("2x + 3y == 2*x + 3*y" ,T(2.0),T(3.0),T(1.0)), test_xy("2(x + y) == 2*x + 2*y" ,T(2.0),T(3.0),T(1.0)), test_xy(" (x + y)3 == 3*x + 3*y" ,T(2.0),T(3.0),T(1.0)), + test_xy("equal(x^2.2^1.1,17.15193942371376191362)" ,T(3.3),T(0.0),T(1.0)), + test_xy("equal(3.3^x^1.1,17.15193942371376191362)" ,T(2.2),T(0.0),T(1.0)), + test_xy("equal(3.3^2.2^x,17.15193942371376191362)" ,T(1.1),T(0.0),T(1.0)), + test_xy("equal(x^2.2^y,17.15193942371376191362)" ,T(3.3),T(1.1),T(1.0)), + test_xy("equal(x^y^1.1,17.15193942371376191362)" ,T(3.3),T(2.2),T(1.0)), + test_xy("equal(3.3^x^y,17.15193942371376191362)" ,T(2.2),T(1.1),T(1.0)), test_xy("equal(x+y^3/7,x+(y*y*y)/7)",T(2.0),T(3.0),T(1.0)), test_xy("equal(1-x^3+y^2*7,1-(x*x*x)+(y*y)*7)",T(2.0),T(3.0),T(1.0)), test_xy("equal( x^0,1)",T(12.34),T(0.0),T(1.0)), diff --git a/readme.txt b/readme.txt index fee621b..9a6b2c2 100644 --- a/readme.txt +++ b/readme.txt @@ -23,6 +23,7 @@ operations, functions and processes: (2) Trigonometry: acos, asin, atan, atan2, cos, cosh, cot, csc, deg2grad, deg2rad, grad2deg, hypot, rad2deg, sec, sin, sinh, tan, tanh + (3) Equalities & Inequalities: =, ==, <>, !=, <, <=, >, >= @@ -47,21 +48,21 @@ The following is a short listing of the types of mathematical expressions that can be parsed and evaluated using the ExprTk library. (01) sqrt(1 - (x^2)) -(02) clamp(-1,sin(2 * pi * x) + cos(y / 2 * pi),+1) -(03) sin(2 * x) +(02) clamp(-1, sin(2 * pi * x) + cos(y / 2 * pi), +1) +(03) sin(2.34e-3 * x) (04) if(((x + 2) == 3) and ((y + 5) <= 9),1 + w, 2 / z) (05) inrange(-2,m,+2) == if(({-2 <= m} and [m <= +2]),1,0) (06) ({1/1}*[1/2]+(1/3))-{1/4}^[1/5]+(1/6)-({1/7}+[1/8]*(1/9)) -(07) a * exp(2 * t) + c -(08) z := x + sin(2 * pi / y) -(09) u := 2 * (pi * z) / (w := x + cos(y / pi)) +(07) a * exp(2.2 / 3.3 * t) + c +(08) z := x + sin(2.567 * pi / y) +(09) u := 2.123 * (pi * z) / (w := x + cos(y / pi)) (10) 2x + 3y + 4z + 5w == 2 * x + 3 * y + 4 * z + 5 * w -(11) 3(x + y) / 2 + 1 == 3 * (x + y) / 2 + 1 -(12) (x + y)3 + 1 / 4 == (x + y) * 3 + 1 / 4 -(13) (x + y)z + 1 / 2 == (x + y) * z + 1 / 2 -(14) (sin(x/pi)cos(2y) + 1)==(sin(x / pi) * cos(2 * y) + 1) +(11) 3(x + y) / 2.9 + 1.234e+12 == 3 * (x + y) / 2.9 + 1.234e+12 +(12) (x + y)3.3 + 1 / 4.5 == (x + y) * 3.3 + 1 / 4.5 +(13) (x + y)z + 1.1 / 2.7 == (x + y) * z + 1.1 / 2.7 +(14) (sin(x / pi) cos(2y) + 1) == (sin(x / pi) * cos(2 * y) + 1) (15) 25x^5 - 35x^4 - 15x^3 + 40x^2 - 15x + 1 -(16) if (avg(x,y) <= x + y, x - y, x * y) + 2 * pi / x +(16) if (avg(x,y) <= x + y, x - y, x * y) + 2.345 * pi / x (17) fib_i := fib_i + (x := y + 0 * (fib_i := x + (y := fib_i))) (18) while (x <= 100) { x := x + 1 } (19) x <= 'abc123' and (y in 'AString') or ('1x2y3z' != z) @@ -103,7 +104,7 @@ include path (e.g: /usr/include/). [07 - COMPILER COMPATIBILITY] (*) GNU Compiler Collection (4.1+) -(*) Intel® C++ Compiler (9.x+) +(*) Intel C++ Compiler (9.x+) (*) Clang/LLVM (1.1+) (*) PGI C++ (10.x+) (*) Microsoft Visual Studio C++ Compiler (8.1+) @@ -171,7 +172,7 @@ include path (e.g: /usr/include/). +----------+---------------------------------------------------------+ | mor | Multi-input logical OR, True if at least one of the | | | inputs are true. Left to right short-circuiting of | -| | expressions. (eg: mand(x > y,z < w,u or v,w and x)) | +| | expressions. (eg: mor(x > y,z < w,u or v,w and x)) | +----------+---------------------------------------------------------+ | nand | Logical NAND, True only if either x or y is false. | | | (eg: x nand y) |