diff --git a/exprtk.hpp b/exprtk.hpp index 78ba31c..12d4d0d 100644 --- a/exprtk.hpp +++ b/exprtk.hpp @@ -20,7 +20,7 @@ * (05) if(((x+2)==3)and((y+5)<=9),1+w,2/z) * * (06) if(avg(x,y)<=x+y,x-y,x*y)+2*pi/x * * (07) z:=x+sin(2*pi/y) * - * (08) u<-2*(pi*z)/(w:=x+cos(y/pi)) * + * (08) u:=2*(pi*z)/(w:=x+cos(y/pi)) * * (09) clamp(-1,sin(2*pi*x)+cos(y/2*pi),+1) * * (10) inrange(-2,m,+2)==if(({-2<=m}and[m<=+2]),1,0) * * (11) (12.34sin(x)cos(2y)7+1)==(12.34*sin(x)*cos(2*y)*7+1) * @@ -160,8 +160,8 @@ namespace exprtk static const std::string reserved_symbols[] = { "abs", "acos", "and", "asin", "atan", "atan2", "avg", "ceil", "clamp", - "cos", "cosh", "cot", "csc", "deg2grad", "deg2rad", "equal", "exp", - "floor", "for", "grad2deg", "hyp", "if", "ilike", "in", "inrange", + "cos", "cosh", "cot", "csc", "deg2grad", "deg2rad", "equal", "erf", "erfc", + "exp", "floor", "for", "grad2deg", "hyp", "if", "ilike", "in", "inrange", "like", "log", "log10", "logn", "max", "min", "mod", "mul", "nand", "nor", "not", "not_equal", "or", "rad2deg", "root", "round", "roundn", "sec", "sgn", "shl", "shr", "sin", "sinh", "sqrt", "sum", "tan", "tanh", @@ -412,7 +412,7 @@ namespace exprtk template inline T roundn_impl(const T& v0, const T& v1, real_type_tag) { - return std::floor((v0 * pow10[(int)std::floor(v1)]) + T(0.5)) / T(pow10[(int)std::floor(v1)]); + return T(std::floor((v0 * pow10[(int)std::floor(v1)]) + T(0.5)) / T(pow10[(int)std::floor(v1)])); } template @@ -448,7 +448,7 @@ namespace exprtk template inline T shr_impl(const T& v0, const T& v1, real_type_tag) { - return v0 * (T(1) / std::pow(T(2),static_cast(static_cast(v1)))); + return v0 * (T(1) / std::pow(T(2),static_cast(static_cast(v1)))); } template @@ -460,7 +460,7 @@ namespace exprtk template inline T shl_impl(const T& v0, const T& v1, real_type_tag) { - return v0 * std::pow(T(2),static_cast(static_cast(v1))); + return v0 * std::pow(T(2),static_cast(static_cast(v1))); } template @@ -497,6 +497,53 @@ namespace exprtk return v0 ^ v1; } + template + inline T erf_impl(T v, real_type_tag) + { + #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) + //Note: This should not be required for mscv 11.+ + T a1 = T(+0.254829592); + T a2 = T(-0.284496736); + T a3 = T(+1.421413741); + T a4 = T(-1.453152027); + T a5 = T(+1.061405429); + T p = T( 0.327591100); + T sign = T(1.0); + if (v < 0) + { + sign = -1; + v = abs(v); + } + T t = T(1.0) / (T(1.0) + p * v); + T y = T(1.0) - (((((a5 * t + a4) * t) + a3) * t + a2) * t + a1) * t * std::exp(-v * v); + return sign * y; + #else + return ::erf(v); + #endif + } + + template + inline T erf_impl(T v, int_type_tag) + { + return erf_impl(static_cast(v),real_type_tag()); + } + + template + inline T erfc_impl(T v, real_type_tag) + { + #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) + return T(1.0) - erf_impl(v,real_type_tag()); + #else + return ::erfc(v); + #endif + } + + template + inline T erfc_impl(T v, int_type_tag) + { + return erfc_impl(static_cast(v),real_type_tag()); + } + template inline bool is_integer_impl(const T& v, real_type_tag) { @@ -610,6 +657,20 @@ namespace exprtk return details::xor_impl(v0,v1,num_type); } + template + inline T erf(const T& v) + { + typename details::number_type::type num_type; + return details::erf_impl(v,num_type); + } + + template + inline T erfc(const T& v) + { + typename details::number_type::type num_type; + return details::erfc_impl(v,num_type); + } + template inline bool is_integer(const T& v) { @@ -834,7 +895,6 @@ namespace exprtk else if ((c0 == '!') && (c1 == '=')) ttype = token_t::ne; else if ((c0 == '=') && (c1 == '=')) ttype = token_t::eq; else if ((c0 == ':') && (c1 == '=')) ttype = token_t::assign; - else if ((c0 == '<') && (c1 == '-')) ttype = token_t::assign; else if ((c0 == '<') && (c1 == '<')) ttype = token_t::shl; else if ((c0 == '>') && (c1 == '>')) ttype = token_t::shr; if (token_t::none != ttype) @@ -1452,6 +1512,8 @@ namespace exprtk e_g2d , e_hyp , e_not , + e_erf , + e_erfc , e_assign , e_in , e_like , @@ -1540,6 +1602,8 @@ namespace exprtk case e_g2d : return (arg * T(9/20)); case e_not : return (arg != T(0) ? T(0) : T(1)); case e_sgn : return numeric::sgn(arg); + case e_erf : return numeric::erf(arg); + case e_erfc : return numeric::erfc(arg); default : return std::numeric_limits::quiet_NaN(); } } @@ -3643,6 +3707,8 @@ namespace exprtk operation_t( "grad2deg" , e_g2d , 1), operation_t( "sgn" , e_sgn , 1), operation_t( "not" , e_not , 1), + operation_t( "erf" , e_erf , 1), + operation_t( "erfc" , e_erfc , 1), operation_t( "atan2", e_atan2 , 2), operation_t( "min", e_min , 2), operation_t( "max", e_max , 2), diff --git a/exprtk_test.cpp b/exprtk_test.cpp index 05beeec..cbfdfd5 100644 --- a/exprtk_test.cpp +++ b/exprtk_test.cpp @@ -1367,28 +1367,20 @@ inline bool run_test08() "x + y + z + w + u", "x + y / z * w ^ u", "x:=1.1", "y:=2.2", "z:=3.3", "w:=4.4", "u:=5.5", - "x<-1.1", "y<-2.2", "z<-3.3", "w<-4.4", "u<-5.5", "x:=x+1.1", "y:=y+2.2", "z:=z+3.3", "w:=w+4.4", "u:=u+5.5", - "x<-x+1.1", "y<-y+2.2", "z<-z+3.3", "w<-w+4.4", "u<-u+5.5", "x:=1.1+x", "y:=2.2+y", "z:=3.3+z", "w:=4.4+w", "u:=5.5+u", - "x<-1.1+x", "y<-2.2+y", "z<-3.3+z", "w<-4.4+w", "u<-5.5+u", "x:=(x <= 1.1)", "y:=(2.2 >= y)", "z:=(3.3 and z)", "w:=(4.4 or w)", "u:=(u xor 5.5)", - "x<-(x <= 1.1)", - "y<-(2.2 >= y)", - "z<-(3.3 and z)", - "w<-(4.4 or w)", - "u<-(u xor 5.5)", "min(x,y) + min(x,y,z) + min(x,y,z,w) + min(x,y,z,w,y)", "max(x,y) + max(x,y,z) + max(x,y,z,w) + max(x,y,z,w,y)", "avg(x,y)", "avg(x,y,z)", "avg(x,y,z,w)", "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)", diff --git a/readme.txt b/readme.txt index 1ba150b..0dd7e0c 100644 --- a/readme.txt +++ b/readme.txt @@ -10,21 +10,22 @@ extendible. [CAPABILITIES] The ExprTk evaluator supports the following fundamental mathematical -operations, function and processes: +operations, functions and processes: (1) Basic operators: +, -, *, /, %, ^ (2) Functions: min, max, avg, sum, abs, ceil, floor, round, roundn, exp, log, log10, logn, root, sqrt, - clamp, inrange, sgn + clamp, inrange, sgn, erf, erfc -(3) Trigonometry: sin, cos, tan, acos, asin, atan, atan2, cosh, cot - csc, sec, sinh, tanh, d2r, r2d, d2g, g2d, hyp +(3) Trigonometry: sin, cos, tan, acos, asin, atan, atan2, cosh, + cot, csc, sec, sinh, tanh, d2r, r2d, d2g, g2d, + hyp (4) Equalities & Inequalities: =, ==, <>, !=, <, <=, >, >=, -(5) Boolean logic: and, or, xor, not, nand, nor +(5) Boolean logic: and, or, xor, not, nand, nor, shr, shl (6) Conditional & Loop statement: if-then-else, while