diff --git a/exprtk.hpp b/exprtk.hpp index 12d4d0d..1fc1bd7 100644 --- a/exprtk.hpp +++ b/exprtk.hpp @@ -1562,7 +1562,24 @@ namespace exprtk e_sf39 = 1039, e_sf40 = 1040, e_sf41 = 1041, - e_sf42 = 1042 + e_sf42 = 1042, + e_sf43 = 1043, + e_sf44 = 1044, + e_sf45 = 1045, + e_sf46 = 1046, + e_sf47 = 1047, + e_sf48 = 1048, + e_sf49 = 1049, + e_sf50 = 1050, + e_sf51 = 1051, + e_sf52 = 1052, + e_sf53 = 1053, + e_sf54 = 1054, + e_sf55 = 1055, + e_sf56 = 1056, + e_sf57 = 1057, + e_sf58 = 1058 + }; namespace numeric @@ -1983,18 +2000,21 @@ namespace exprtk #endif } - template - inline void cleanup_branches(std::pair*,bool> (&branch)[N]) + template + struct cleanup_branches { - for (std::size_t i = 0; i < N; ++i) + static inline void execute(std::pair*,bool> (&branch)[N]) { - if (branch[i].first && branch[i].second) + for (std::size_t i = 0; i < N; ++i) { - delete branch[i].first; - branch[i].first = 0; + if (branch[i].first && branch[i].second) + { + delete branch[i].first; + branch[i].first = 0; + } } } - } + }; template class binary_node : public expression_node @@ -2014,7 +2034,7 @@ namespace exprtk ~binary_node() { - cleanup_branches<2>(branch_); + cleanup_branches::execute(branch_); } inline T value() const @@ -2069,7 +2089,7 @@ namespace exprtk ~trinary_node() { - cleanup_branches<3>(branch_); + cleanup_branches::execute(branch_); } inline T value() const @@ -2121,7 +2141,7 @@ namespace exprtk ~quaternary_node() { - cleanup_branches<4>(branch_); + cleanup_branches::execute(branch_); } inline T value() const @@ -2173,7 +2193,7 @@ namespace exprtk ~quinary_node() { - cleanup_branches<5>(branch_); + cleanup_branches::execute(branch_); } inline T value() const @@ -2227,7 +2247,7 @@ namespace exprtk ~senary_node() { - cleanup_branches<6>(branch_); + cleanup_branches::execute(branch_); } inline T value() const @@ -2456,6 +2476,9 @@ namespace exprtk std::string stringvar_node::null_value = std::string(""); #endif + template inline T axn(T a, T x) { return a * exprtk::details::numeric::fast_exp::result(x); } // a*x^n + template inline T axnb(T a, T x, T b) { return a * exprtk::details::numeric::fast_exp::result(x) + b; } // a*x^n+b + template struct sf00_op { static inline T process(const T& x, const T& y, const T& z) { return (x + y) / z; } }; template struct sf01_op { static inline T process(const T& x, const T& y, const T& z) { return (x + y) * z; } }; template struct sf02_op { static inline T process(const T& x, const T& y, const T& z) { return (x - y) / z; } }; @@ -2474,31 +2497,47 @@ namespace exprtk template struct sf15_op { static inline T process(const T& x, const T& y, const T& z) { return z / (x / y); } }; template struct sf16_op { static inline T process(const T& x, const T& y, const T& z) { return z - (x / y); } }; template struct sf17_op { static inline T process(const T& x, const T& y, const T& z) { return z - (x / y); } }; - template struct sf18_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w + ((x + y) / z); } }; - template struct sf19_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w + ((x + y) * z); } }; - template struct sf20_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w + ((x - y) / z); } }; - template struct sf21_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w + ((x - y) * z); } }; - template struct sf22_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w + ((x * y) / z); } }; - template struct sf23_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w + ((x * y) * z); } }; - template struct sf24_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w + ((x / y) + z); } }; - template struct sf25_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w + ((x / y) / z); } }; - template struct sf26_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w + ((x / y) * z); } }; - template struct sf27_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w - ((x + y) / z); } }; - template struct sf28_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w - ((x + y) * z); } }; - template struct sf29_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w - ((x - y) / z); } }; - template struct sf30_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w - ((x - y) * z); } }; - template struct sf31_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w - ((x * y) / z); } }; - template struct sf32_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w - ((x * y) * z); } }; - template struct sf33_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w - ((x / y) / z); } }; - template struct sf34_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w - ((x / y) * z); } }; - template struct sf35_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return ((x + y) * z) - w; } }; - template struct sf36_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return ((x - y) * z) - w; } }; - template struct sf37_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return ((x * y) * z) - w; } }; - template struct sf38_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return ((x / y) * z) - w; } }; - template struct sf39_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return ((x + y) / z) - w; } }; - template struct sf40_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return ((x - y) / z) - w; } }; - template struct sf41_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return ((x * y) / z) - w; } }; - template struct sf42_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return ((x / y) / z) - w; } }; + template struct sf18_op { static inline T process(const T& x, const T& y, const T& z) { return axnb(x,y,z); } }; //x * y^2 + z + template struct sf19_op { static inline T process(const T& x, const T& y, const T& z) { return axnb(x,y,z); } }; //x * y^3 + z + template struct sf20_op { static inline T process(const T& x, const T& y, const T& z) { return axnb(x,y,z); } }; //x * y^4 + z + template struct sf21_op { static inline T process(const T& x, const T& y, const T& z) { return axnb(x,y,z); } }; //x * y^5 + z + template struct sf22_op { static inline T process(const T& x, const T& y, const T& z) { return axnb(x,y,z); } }; //x * y^6 + z + template struct sf23_op { static inline T process(const T& x, const T& y, const T& z) { return axnb(x,y,z); } }; //x * y^7 + z + template struct sf24_op { static inline T process(const T& x, const T& y, const T& z) { return axnb(x,y,z); } }; //x * y^8 + z + template struct sf25_op { static inline T process(const T& x, const T& y, const T& z) { return axnb(x,y,z); } }; //x * y^9 + z + template struct sf26_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w + ((x + y) / z); } }; + template struct sf27_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w + ((x + y) * z); } }; + template struct sf28_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w + ((x - y) / z); } }; + template struct sf29_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w + ((x - y) * z); } }; + template struct sf30_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w + ((x * y) / z); } }; + template struct sf31_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w + ((x * y) * z); } }; + template struct sf32_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w + ((x / y) + z); } }; + template struct sf33_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w + ((x / y) / z); } }; + template struct sf34_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w + ((x / y) * z); } }; + template struct sf35_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w - ((x + y) / z); } }; + template struct sf36_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w - ((x + y) * z); } }; + template struct sf37_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w - ((x - y) / z); } }; + template struct sf38_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w - ((x - y) * z); } }; + template struct sf39_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w - ((x * y) / z); } }; + template struct sf40_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w - ((x * y) * z); } }; + template struct sf41_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w - ((x / y) / z); } }; + template struct sf42_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w - ((x / y) * z); } }; + template struct sf43_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return ((x + y) * z) - w; } }; + template struct sf44_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return ((x - y) * z) - w; } }; + template struct sf45_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return ((x * y) * z) - w; } }; + template struct sf46_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return ((x / y) * z) - w; } }; + template struct sf47_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return ((x + y) / z) - w; } }; + template struct sf48_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return ((x - y) / z) - w; } }; + template struct sf49_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return ((x * y) / z) - w; } }; + template struct sf50_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return ((x / y) / z) - w; } }; + template struct sf51_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return axn(x,y) + axn(z,w); } }; //x*y^2+z*w^2 + template struct sf52_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return axn(x,y) + axn(z,w); } }; //x*y^3+z*w^3 + template struct sf53_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return axn(x,y) + axn(z,w); } }; //x*y^4+z*w^4 + template struct sf54_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return axn(x,y) + axn(z,w); } }; //x*y^5+z*w^5 + template struct sf55_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return axn(x,y) + axn(z,w); } }; //x*y^6+z*w^6 + template struct sf56_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return axn(x,y) + axn(z,w); } }; //x*y^7+z*w^7 + template struct sf57_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return axn(x,y) + axn(z,w); } }; //x*y^8+z*w^8 + template struct sf58_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return axn(x,y) + axn(z,w); } }; //x*y^9+z*w^9 template class sf3_node : public trinary_node @@ -2577,70 +2616,192 @@ namespace exprtk } }; - template - class function_node : public expression_node + template + class function_N_node : public expression_node { public: - + //function of N paramters. typedef expression_node* expression_ptr; typedef std::pair branch_t; typedef IFunction ifunction; - static const std::size_t N = 10; - - function_node(ifunction* func) - : function(func) + function_N_node(ifunction* func) + : function_((N == func->param_count) ? func : reinterpret_cast(0)), + parameter_count_(func->param_count) {} - ~function_node() + ~function_N_node() { - cleanup_branches(branch_); + cleanup_branches::execute(branch_); } template bool init_branches(expression_ptr (&b)[NumBranches]) { - for (std::size_t i = 0; i < NumBranches; ++i) + //Needed for incompetent and broken msvc compiler versions + #ifdef _MSC_VER + #pragma warning(push) + #pragma warning(disable: 4127) + #endif + if (N != NumBranches) + return false; + else { - if (b[i]) - branch_[i] = std::make_pair(b[i],branch_deletable(b[i])); - else - return false; + for (std::size_t i = 0; i < NumBranches; ++i) + { + if (b[i]) + branch_[i] = std::make_pair(b[i],branch_deletable(b[i])); + else + return false; + } + return true; } - return true; + #ifdef _MSC_VER + #pragma warning(pop) + #endif } - inline bool operator <(const function_node& fn) const + inline bool operator <(const function_N_node& fn) const { return this < (&fn); } inline T value() const { - T v[N]; - if (function->param_count) + //Needed for incompetent and broken msvc compiler versions + #ifdef _MSC_VER + #pragma warning(push) + #pragma warning(disable: 4127) + #endif + if ((0 == function_) || (0 == N)) + return std::numeric_limits::quiet_NaN(); + else { - for (std::size_t i = 0; i < function->param_count; ++i) + T v[N]; + evaluate_branches::execute(v,branch_); + return invoke::execute(*function_,v); + } + #ifdef _MSC_VER + #pragma warning(pop) + #endif + } + + template + struct evaluate_branches + { + static inline void execute(T_ (&v)[BranchCount], const branch_t (&b)[BranchCount]) + { + for (std::size_t i = 0; i < BranchCount; ++i) { - v[i] = branch_[i].first->value(); - } - switch (function->param_count) - { - case 1 : return (*function)(v[0]); - case 2 : return (*function)(v[0],v[1]); - case 3 : return (*function)(v[0],v[1],v[2]); - case 4 : return (*function)(v[0],v[1],v[2],v[3]); - case 5 : return (*function)(v[0],v[1],v[2],v[3],v[4]); - case 6 : return (*function)(v[0],v[1],v[2],v[3],v[4],v[5]); - case 7 : return (*function)(v[0],v[1],v[2],v[3],v[4],v[5],v[6]); - case 8 : return (*function)(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]); - case 9 : return (*function)(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8]); - case 10 : return (*function)(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9]); - default : return std::numeric_limits::quiet_NaN(); + v[i] = b[i].first->value(); } } + }; + + template + struct evaluate_branches + { + static inline void execute(T_ (&v)[5], const branch_t (&b)[5]) + { + v[0] = b[0].first->value(); + v[1] = b[1].first->value(); + v[2] = b[2].first->value(); + v[3] = b[3].first->value(); + v[4] = b[4].first->value(); + } + }; + + template + struct evaluate_branches + { + static inline void execute(T_ (&v)[4], const branch_t (&b)[4]) + { + v[0] = b[0].first->value(); + v[1] = b[1].first->value(); + v[2] = b[2].first->value(); + v[3] = b[3].first->value(); + } + }; + + template + struct evaluate_branches + { + static inline void execute(T_ (&v)[3], const branch_t (&b)[3]) + { + v[0] = b[0].first->value(); + v[1] = b[1].first->value(); + v[2] = b[2].first->value(); + } + }; + + template + struct evaluate_branches + { + static inline void execute(T_ (&v)[2], const branch_t (&b)[2]) + { + v[0] = b[0].first->value(); + v[1] = b[1].first->value(); + } + }; + + template + struct evaluate_branches + { + static inline void execute(T_ (&v)[1], const branch_t (&b)[1]) + { + v[0] = b[0].first->value(); + } + }; + + template + struct invoke { static inline T execute(ifunction*, branch_t (&)[ParamCount]) { return std::numeric_limits::quiet_NaN(); } }; + + template struct invoke { static inline T_ execute(ifunction& f, T_ (&v)[10]) { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9]); } }; + template struct invoke { static inline T_ execute(ifunction& f, T_ (&v)[ 9]) { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8]); } }; + template struct invoke { static inline T_ execute(ifunction& f, T_ (&v)[ 8]) { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]); } }; + template struct invoke { static inline T_ execute(ifunction& f, T_ (&v)[ 7]) { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6]); } }; + template struct invoke { static inline T_ execute(ifunction& f, T_ (&v)[ 6]) { return f(v[0],v[1],v[2],v[3],v[4],v[5]); } }; + template struct invoke { static inline T_ execute(ifunction& f, T_ (&v)[ 5]) { return f(v[0],v[1],v[2],v[3],v[4]); } }; + template struct invoke { static inline T_ execute(ifunction& f, T_ (&v)[ 4]) { return f(v[0],v[1],v[2],v[3]); } }; + template struct invoke { static inline T_ execute(ifunction& f, T_ (&v)[ 3]) { return f(v[0],v[1],v[2]); } }; + template struct invoke { static inline T_ execute(ifunction& f, T_ (&v)[ 2]) { return f(v[0],v[1]); } }; + template struct invoke { static inline T_ execute(ifunction& f, T_ (&v)[ 1]) { return f(v[0]); } }; + + inline typename expression_node::node_type type() const + { + return expression_node::e_function; + } + + private: + + ifunction* function_; + std::size_t parameter_count_; + branch_t branch_[N]; + }; + + template + class function_N_node : public expression_node + { + public: + + typedef expression_node* expression_ptr; + typedef IFunction ifunction; + + function_N_node(ifunction* func) + : function_((0 == func->param_count) ? func : reinterpret_cast(0)) + {} + + inline bool operator <(const function_N_node& fn) const + { + return this < (&fn); + } + + inline T value() const + { + if (0 == function_) + return std::numeric_limits::quiet_NaN(); else - return (*function)(); + return (*function_)(); } inline typename expression_node::node_type type() const @@ -2650,8 +2811,8 @@ namespace exprtk private: - ifunction* function; - branch_t branch_[N]; + ifunction* function_; + std::size_t parameter_count_; }; template @@ -3843,7 +4004,7 @@ namespace exprtk } }; - template + template struct type_store { typedef typename details::variable_node variable_node_t; @@ -4745,6 +4906,7 @@ namespace exprtk }; typedef ifunction F; + typedef ifunction ifunction_t; typedef details::expression_node expression_node_t; typedef details::literal_node literal_node_t; typedef details::string_literal_node string_literal_node_t; @@ -4761,7 +4923,6 @@ namespace exprtk typedef details::stringvar_node stringvar_node_t; #endif typedef details::assignment_node assignment_node_t; - typedef details::function_node function_node_t; typedef details::token token_t; typedef expression_node_t* expression_node_ptr; @@ -5139,10 +5300,10 @@ namespace exprtk { //Expect: $fDD(expr0,expr1,expr2) or $fDD(expr0,expr1,expr2,expr3) const details::operator_type opt_type = details::operator_type(id + 1000); - const std::size_t NumberOfParameters = (id < (details::e_sf18 - 1000)) ? 3 : 4; + const std::size_t NumberOfParameters = (id < (details::e_sf26 - 1000)) ? 3 : 4; expression_node_ptr branch3[3]; expression_node_ptr branch4[4]; - expression_node_ptr* branch = (id < (details::e_sf18 - 1000)) ? &branch3[0] : &branch4[0]; + expression_node_ptr* branch = (id < (details::e_sf26 - 1000)) ? &branch3[0] : &branch4[0]; expression_node_ptr result = 0; std::fill_n(branch3,3,reinterpret_cast(0)); std::fill_n(branch4,4,reinterpret_cast(0)); @@ -5772,6 +5933,14 @@ namespace exprtk case_stmt(details::e_sf15,details::sf15_op) case_stmt(details::e_sf16,details::sf16_op) case_stmt(details::e_sf17,details::sf17_op) + case_stmt(details::e_sf18,details::sf18_op) + case_stmt(details::e_sf19,details::sf19_op) + case_stmt(details::e_sf20,details::sf20_op) + case_stmt(details::e_sf21,details::sf21_op) + case_stmt(details::e_sf22,details::sf22_op) + case_stmt(details::e_sf23,details::sf23_op) + case_stmt(details::e_sf24,details::sf24_op) + case_stmt(details::e_sf25,details::sf25_op) default : return error_node(); #undef case_stmt } @@ -5784,14 +5953,6 @@ namespace exprtk switch (operation) { #define case_stmt(op0,op1) case op0 : return node_allocator_->allocate > >(operation,branch); - case_stmt(details::e_sf18,details::sf18_op) - case_stmt(details::e_sf19,details::sf19_op) - case_stmt(details::e_sf20,details::sf20_op) - case_stmt(details::e_sf21,details::sf21_op) - case_stmt(details::e_sf22,details::sf22_op) - case_stmt(details::e_sf23,details::sf23_op) - case_stmt(details::e_sf24,details::sf24_op) - case_stmt(details::e_sf25,details::sf25_op) case_stmt(details::e_sf26,details::sf26_op) case_stmt(details::e_sf27,details::sf27_op) case_stmt(details::e_sf28,details::sf28_op) @@ -5809,15 +5970,33 @@ namespace exprtk case_stmt(details::e_sf40,details::sf40_op) case_stmt(details::e_sf41,details::sf41_op) case_stmt(details::e_sf42,details::sf42_op) + case_stmt(details::e_sf43,details::sf43_op) + case_stmt(details::e_sf44,details::sf44_op) + case_stmt(details::e_sf45,details::sf45_op) + case_stmt(details::e_sf46,details::sf46_op) + case_stmt(details::e_sf47,details::sf47_op) + case_stmt(details::e_sf48,details::sf48_op) + case_stmt(details::e_sf49,details::sf49_op) + case_stmt(details::e_sf50,details::sf50_op) + case_stmt(details::e_sf51,details::sf51_op) + case_stmt(details::e_sf52,details::sf52_op) + case_stmt(details::e_sf53,details::sf53_op) + case_stmt(details::e_sf54,details::sf54_op) + case_stmt(details::e_sf55,details::sf55_op) + case_stmt(details::e_sf56,details::sf56_op) + case_stmt(details::e_sf57,details::sf57_op) + case_stmt(details::e_sf58,details::sf58_op) default : return error_node(); #undef case_stmt } } template - inline expression_node_ptr function(typename function_node_t::ifunction* f, expression_node_ptr (&b)[N]) + inline expression_node_ptr function(ifunction_t* f, expression_node_ptr (&b)[N]) { - expression_node_ptr result = synthesize_expression(f,b); + typedef typename details::function_N_node function_N_node_t; + + expression_node_ptr result = synthesize_expression(f,b); if (0 == result) return error_node(); else @@ -5829,7 +6008,7 @@ namespace exprtk return error_node(); else if (N != f->param_count) return error_node(); - function_node_t* func_node_ptr = dynamic_cast(result); + function_N_node_t* func_node_ptr = dynamic_cast(result); if (func_node_ptr) { if (func_node_ptr->init_branches(b)) @@ -5842,9 +6021,10 @@ namespace exprtk } } - inline expression_node_ptr function(typename function_node_t::ifunction* f) + inline expression_node_ptr function(ifunction_t* f) { - return node_allocator_->allocate(f); + typedef typename details::function_N_node function_N_node_t; + return node_allocator_->allocate(f); } private: @@ -6616,9 +6796,10 @@ namespace exprtk { if (all_nodes_valid(branch)) { + typedef typename details::function_N_node function_N_node_t; //Attempt simple constant folding optimization. expression_node_ptr expression_point = node_allocator_->allocate(f); - dynamic_cast(expression_point)->init_branches(branch); + dynamic_cast(expression_point)->init_branches(branch); if (is_constant_foldable(branch)) { Type v = expression_point->value(); @@ -6743,11 +6924,19 @@ namespace exprtk //Check for certain illegal sequences of characters. std::stack bracket_stack; + bool in_string = false; for (std::size_t i = 0; i < (expression_string.size() - 1); ++i) { char c0 = expression_string[i]; char c1 = expression_string[i + 1]; - if (details::is_invalid(c0)) + if ('\'' == c0) + { + in_string = !in_string; + continue; + } + else if (in_string) + continue; + else if (details::is_invalid(c0)) { set_error(std::string("parser::validate_expression() - invalid character: ") + c0); return false; @@ -7022,6 +7211,175 @@ namespace exprtk return false; } + template + class polynomial : public ifunction + { + private: + + template + struct poly_impl { }; + + template + struct poly_impl + { + static inline T evaluate(const Type x, + const Type c9, const Type c8, const Type c7, const Type c6, const Type c5, + const Type c4, const Type c3, const Type c2, const Type c1, const Type c0) + { + //p(x) = c_9x^9 + c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0 + return (((((((((c9 * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); + } + }; + + template + struct poly_impl + { + static inline T evaluate(const Type x, + const Type c8, const Type c7, const Type c6, const Type c5, const Type c4, + const Type c3, const Type c2, const Type c1, const Type c0) + { + //p(x) = c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0 + return ((((((((c8 * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); + } + }; + + template + struct poly_impl + { + static inline T evaluate(const Type x, + const Type c7, const Type c6, const Type c5, const Type c4, const Type c3, + const Type c2, const Type c1, const Type c0) + { + //p(x) = c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0 + return (((((((c7 * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); + } + }; + + template + struct poly_impl + { + static inline T evaluate(const Type x, + const Type c6, const Type c5, const Type c4, const Type c3, const Type c2, + const Type c1, const Type c0) + { + //p(x) = c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0 + return ((((((c6 * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); + } + }; + + template + struct poly_impl + { + static inline T evaluate(const Type x, + const Type c5, const Type c4, const Type c3, const Type c2, + const Type c1, const Type c0) + { + //p(x) = c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0 + return (((((c5 * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); + } + }; + + template + struct poly_impl + { + static inline T evaluate(const Type x, const Type c4, const Type c3, const Type c2, const Type c1, const Type c0) + { + //p(x) = c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0 + return ((((c4 * x + c3) * x + c2) * x + c1) * x + c0); + } + }; + + template + struct poly_impl + { + static inline T evaluate(const Type x, const Type c3, const Type c2, const Type c1, const Type c0) + { + //p(x) = c_3x^3 + c_2x^2 + c_1x^1 + c_0 + return (((c3 * x + c2) * x + c1) * x + c0); + } + }; + + template + struct poly_impl + { + static inline T evaluate(const Type x, const Type c2, const Type c1, const Type c0) + { + //p(x) = c_2x^2 + c_1x^1 + c_0 + return ((c2 * x + c1) * x + c0); + } + }; + + template + struct poly_impl + { + static inline T evaluate(const Type x, const Type c1, const Type c0) + { + //p(x) = c_1x^1 + c_0 + return (c1 * x + c0); + } + }; + + public: + + polynomial() : exprtk::ifunction(N) {} + + inline virtual T operator()(const T& x, const T& c1, const T& c0) + { + return ((1 == N) ? poly_impl::evaluate(x,c1,c0) : std::numeric_limits::quiet_NaN()); + } + + inline virtual T operator()(const T& x, const T& c2, const T& c1, const T& c0) + { + return ((2 == N) ? poly_impl::evaluate(x,c2,c1,c0) : std::numeric_limits::quiet_NaN()); + } + + inline virtual T operator()(const T& x, const T& c3, const T& c2, const T& c1, const T& c0) + { + return ((3 == N) ? poly_impl::evaluate(x,c3,c2,c1,c0) : std::numeric_limits::quiet_NaN()); + } + + inline virtual T operator()(const T& x, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) + { + return ((4 == N) ? poly_impl::evaluate(x,c4,c3,c2,c1,c0) : std::numeric_limits::quiet_NaN()); + } + + inline virtual T operator()(const T& x, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) + { + return ((5 == N) ? poly_impl::evaluate(x,c5,c4,c3,c2,c1,c0) : std::numeric_limits::quiet_NaN()); + } + + inline virtual T operator()(const T& x, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) + { + return ((6 == N) ? poly_impl::evaluate(x,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits::quiet_NaN()); + } + + inline virtual T operator()(const T& x, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) + { + return ((7 == N) ? poly_impl::evaluate(x,c7,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits::quiet_NaN()); + } + + inline virtual T operator()(const T& x, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) + { + return ((8 == N) ? poly_impl::evaluate(x,c8,c7,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits::quiet_NaN()); + } + + inline virtual T operator()() + { + return std::numeric_limits::quiet_NaN(); + } + + inline virtual T operator()(const T&) + { + return std::numeric_limits::quiet_NaN(); + } + + inline virtual T operator()(const T&, const T&) + { + return std::numeric_limits::quiet_NaN(); + } + + }; + template inline bool pgo_primer() { @@ -7326,7 +7684,7 @@ namespace exprtk { static const char* library = "Mathematical Expression Toolkit"; static const char* version = "2.71828182845904523536028"; - static const char* date = "20120408"; + static const char* date = "20120505"; static inline std::string data() { diff --git a/exprtk_test.cpp b/exprtk_test.cpp index cbfdfd5..ef0c42d 100644 --- a/exprtk_test.cpp +++ b/exprtk_test.cpp @@ -635,31 +635,47 @@ static const test_t test_list[] = test_t("equal($f15(1.1,2.2,3.3),(3.3/(1.1/2.2)))",1.0), test_t("equal($f16(1.1,2.2,3.3),(3.3-(1.1/2.2)))",1.0), test_t("equal($f17(1.1,2.2,3.3),(3.3-(1.1/2.2)))",1.0), - test_t("equal($f18(1.1,2.2,3.3,4.4),(4.4+((1.1+2.2)/3.3)))",1.0), - test_t("equal($f19(1.1,2.2,3.3,4.4),(4.4+((1.1+2.2)*3.3)))",1.0), - test_t("equal($f20(1.1,2.2,3.3,4.4),(4.4+((1.1-2.2)/3.3)))",1.0), - test_t("equal($f21(1.1,2.2,3.3,4.4),(4.4+((1.1-2.2)*3.3)))",1.0), - test_t("equal($f22(1.1,2.2,3.3,4.4),(4.4+((1.1*2.2)/3.3)))",1.0), - test_t("equal($f23(1.1,2.2,3.3,4.4),(4.4+((1.1*2.2)*3.3)))",1.0), - test_t("equal($f24(1.1,2.2,3.3,4.4),(4.4+((1.1/2.2)+3.3)))",1.0), - test_t("equal($f25(1.1,2.2,3.3,4.4),(4.4+((1.1/2.2)/3.3)))",1.0), - test_t("equal($f26(1.1,2.2,3.3,4.4),(4.4+((1.1/2.2)*3.3)))",1.0), - test_t("equal($f27(1.1,2.2,3.3,4.4),(4.4-((1.1+2.2)/3.3)))",1.0), - test_t("equal($f28(1.1,2.2,3.3,4.4),(4.4-((1.1+2.2)*3.3)))",1.0), - test_t("equal($f29(1.1,2.2,3.3,4.4),(4.4-((1.1-2.2)/3.3)))",1.0), - test_t("equal($f30(1.1,2.2,3.3,4.4),(4.4-((1.1-2.2)*3.3)))",1.0), - test_t("equal($f31(1.1,2.2,3.3,4.4),(4.4-((1.1*2.2)/3.3)))",1.0), - test_t("equal($f32(1.1,2.2,3.3,4.4),(4.4-((1.1*2.2)*3.3)))",1.0), - test_t("equal($f33(1.1,2.2,3.3,4.4),(4.4-((1.1/2.2)/3.3)))",1.0), - test_t("equal($f34(1.1,2.2,3.3,4.4),(4.4-((1.1/2.2)*3.3)))",1.0), - test_t("equal($f35(1.1,2.2,3.3,4.4),(((1.1+2.2)*3.3)-4.4))",1.0), - test_t("equal($f36(1.1,2.2,3.3,4.4),(((1.1-2.2)*3.3)-4.4))",1.0), - test_t("equal($f37(1.1,2.2,3.3,4.4),(((1.1*2.2)*3.3)-4.4))",1.0), - test_t("equal($f38(1.1,2.2,3.3,4.4),(((1.1/2.2)*3.3)-4.4))",1.0), - test_t("equal($f39(1.1,2.2,3.3,4.4),(((1.1+2.2)/3.3)-4.4))",1.0), - test_t("equal($f40(1.1,2.2,3.3,4.4),(((1.1-2.2)/3.3)-4.4))",1.0), - test_t("equal($f41(1.1,2.2,3.3,4.4),(((1.1*2.2)/3.3)-4.4))",1.0), - test_t("equal($f42(1.1,2.2,3.3,4.4),(((1.1/2.2)/3.3)-4.4))",1.0), + test_t("equal($f18(1.1,2.2,3.3),(1.1*2.2^2+3.3))",1.0), + test_t("equal($f19(1.1,2.2,3.3),(1.1*2.2^3+3.3))",1.0), + test_t("equal($f20(1.1,2.2,3.3),(1.1*2.2^4+3.3))",1.0), + test_t("equal($f21(1.1,2.2,3.3),(1.1*2.2^5+3.3))",1.0), + test_t("equal($f22(1.1,2.2,3.3),(1.1*2.2^6+3.3))",1.0), + test_t("equal($f23(1.1,2.2,3.3),(1.1*2.2^7+3.3))",1.0), + test_t("equal($f24(1.1,2.2,3.3),(1.1*2.2^8+3.3))",1.0), + test_t("equal($f25(1.1,2.2,3.3),(1.1*2.2^9+3.3))",1.0), + test_t("equal($f26(1.1,2.2,3.3,4.4),(4.4+((1.1+2.2)/3.3)))",1.0), + test_t("equal($f27(1.1,2.2,3.3,4.4),(4.4+((1.1+2.2)*3.3)))",1.0), + test_t("equal($f28(1.1,2.2,3.3,4.4),(4.4+((1.1-2.2)/3.3)))",1.0), + test_t("equal($f29(1.1,2.2,3.3,4.4),(4.4+((1.1-2.2)*3.3)))",1.0), + test_t("equal($f30(1.1,2.2,3.3,4.4),(4.4+((1.1*2.2)/3.3)))",1.0), + test_t("equal($f31(1.1,2.2,3.3,4.4),(4.4+((1.1*2.2)*3.3)))",1.0), + test_t("equal($f32(1.1,2.2,3.3,4.4),(4.4+((1.1/2.2)+3.3)))",1.0), + test_t("equal($f33(1.1,2.2,3.3,4.4),(4.4+((1.1/2.2)/3.3)))",1.0), + test_t("equal($f34(1.1,2.2,3.3,4.4),(4.4+((1.1/2.2)*3.3)))",1.0), + test_t("equal($f35(1.1,2.2,3.3,4.4),(4.4-((1.1+2.2)/3.3)))",1.0), + test_t("equal($f36(1.1,2.2,3.3,4.4),(4.4-((1.1+2.2)*3.3)))",1.0), + test_t("equal($f37(1.1,2.2,3.3,4.4),(4.4-((1.1-2.2)/3.3)))",1.0), + test_t("equal($f38(1.1,2.2,3.3,4.4),(4.4-((1.1-2.2)*3.3)))",1.0), + test_t("equal($f39(1.1,2.2,3.3,4.4),(4.4-((1.1*2.2)/3.3)))",1.0), + test_t("equal($f40(1.1,2.2,3.3,4.4),(4.4-((1.1*2.2)*3.3)))",1.0), + test_t("equal($f41(1.1,2.2,3.3,4.4),(4.4-((1.1/2.2)/3.3)))",1.0), + test_t("equal($f42(1.1,2.2,3.3,4.4),(4.4-((1.1/2.2)*3.3)))",1.0), + test_t("equal($f43(1.1,2.2,3.3,4.4),(((1.1+2.2)*3.3)-4.4))",1.0), + test_t("equal($f44(1.1,2.2,3.3,4.4),(((1.1-2.2)*3.3)-4.4))",1.0), + test_t("equal($f45(1.1,2.2,3.3,4.4),(((1.1*2.2)*3.3)-4.4))",1.0), + test_t("equal($f46(1.1,2.2,3.3,4.4),(((1.1/2.2)*3.3)-4.4))",1.0), + test_t("equal($f47(1.1,2.2,3.3,4.4),(((1.1+2.2)/3.3)-4.4))",1.0), + test_t("equal($f48(1.1,2.2,3.3,4.4),(((1.1-2.2)/3.3)-4.4))",1.0), + test_t("equal($f49(1.1,2.2,3.3,4.4),(((1.1*2.2)/3.3)-4.4))",1.0), + test_t("equal($f50(1.1,2.2,3.3,4.4),(((1.1/2.2)/3.3)-4.4))",1.0), + test_t("equal($f51(1.1,2.2,3.3,4.4),(1.1*2.2^2+3.3*4.4^2))",1.0), + test_t("equal($f52(1.1,2.2,3.3,4.4),(1.1*2.2^3+3.3*4.4^3))",1.0), + test_t("equal($f53(1.1,2.2,3.3,4.4),(1.1*2.2^4+3.3*4.4^4))",1.0), + test_t("equal($f54(1.1,2.2,3.3,4.4),(1.1*2.2^5+3.3*4.4^5))",1.0), + test_t("equal($f55(1.1,2.2,3.3,4.4),(1.1*2.2^6+3.3*4.4^6))",1.0), + test_t("equal($f56(1.1,2.2,3.3,4.4),(1.1*2.2^7+3.3*4.4^7))",1.0), + test_t("equal($f57(1.1,2.2,3.3,4.4),(1.1*2.2^8+3.3*4.4^8))",1.0), + test_t("equal($f58(1.1,2.2,3.3,4.4),(1.1*2.2^9+3.3*4.4^9))",1.0), test_t("1+2+3+4+5+6+7+8+9+0",45.0), test_t("1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 0",45.0), test_t("1.0 + 2.0 + 3.0 + 4.0 + 5.0 + 6.0 + 7.0 + 8.0 + 9.0 + 0.0",45.0), @@ -697,7 +713,9 @@ inline bool not_equal(const T& t1, { if (t1 != t1) return true; if (t2 != t2) return true; - return std::abs(t1 - t2) > (std::max(T(1.0),std::max(std::abs(t1),std::abs(t2))) * epsilon); + T diff = std::abs(t1 - t2); + T eps_norm = (std::max(T(1.0),std::max(std::abs(t1),std::abs(t2))) * epsilon); + return diff > eps_norm; } template @@ -746,7 +764,7 @@ inline bool run_test00() return true; } -template +template struct test_xy { test_xy(std::string e, const T& v0, const T& v1, const T& r) @@ -924,7 +942,7 @@ inline bool run_test01() static const std::size_t test_list_size = sizeof(test_list) / sizeof(test_xy); - const std::size_t rounds = 1000; + const std::size_t rounds = 100; for (std::size_t r = 0; r < rounds; ++r) { for (std::size_t i = 0; i < test_list_size; ++i) @@ -961,7 +979,7 @@ inline bool run_test01() return true; } -template +template struct test_ab { test_ab(std::string e, const std::string& v0, const std::string& v1, const T& r) @@ -1040,12 +1058,19 @@ inline bool run_test02() test_ab("inrange(a,b,c)" ,"aaa","bbb",T(1.0)), test_ab("inrange(a,b,'ccc')" ,"aaa","bbb",T(1.0)), test_ab("inrange('aaa',b,c)" ,"aaa","bbb",T(1.0)), + test_ab("inrange('aaa',b,c)" ,"aaa","bbb",T(1.0)), + test_ab("'!@#$%^&*([{}])-=' != ')]}{[(*&^%$#@!'","","",T(1.0)), + test_ab("('!@#$%^&*([{}])-=') != (')]}{[(*&^%$#@!')","","",T(1.0)), + test_ab("{[('a')]} == [{('a')}]","","",T(1.0)), + test_ab("{[('!@#$%^&*([{}])-=')]} != [{(')]}{[(*&^%$#@!')}]","","",T(1.0)), + test_ab("'!@#$%^&*([{}])-=' == '!@#$%^&*([{}])-='","","",T(1.0)), + test_ab("('!@#$%^&*([{}])-=') == ('!@#$%^&*([{}])-=')","","",T(1.0)), + test_ab("{[('!@#$%^&*([{}])-=')]} == [{('!@#$%^&*([{}])-=')}]","","",T(1.0)) }; - static const std::size_t test_list_size = sizeof(test_list) / sizeof(test_ab); - const std::size_t rounds = 10000; + const std::size_t rounds = 1000; for (std::size_t r = 0; r < rounds; ++r) { for (std::size_t i = 0; i < test_list_size; ++i) @@ -1122,7 +1147,7 @@ inline bool run_test03() static const std::size_t variable_list_size = sizeof(variable_list) / sizeof(std::string); - static const std::size_t rounds = 10000; + static const std::size_t rounds = 1000; for (std::size_t r = 0; r < rounds; ++r) { @@ -1409,46 +1434,62 @@ inline bool run_test08() "equal($f15(x,y,z),(z/(x/y)))", "equal($f16(x,y,z),(z-(x/y)))", "equal($f17(x,y,z),(z-(x/y)))", - "equal($f18(x,y,z,w),(w+((x+y)/z)))", - "equal($f19(x,y,z,w),(w+((x+y)*z)))", - "equal($f20(x,y,z,w),(w+((x-y)/z)))", - "equal($f21(x,y,z,w),(w+((x-y)*z)))", - "equal($f22(x,y,z,w),(w+((x*y)/z)))", - "equal($f23(x,y,z,w),(w+((x*y)*z)))", - "equal($f24(x,y,z,w),(w+((x/y)+z)))", - "equal($f25(x,y,z,w),(w+((x/y)/z)))", - "equal($f26(x,y,z,w),(w+((x/y)*z)))", - "equal($f27(x,y,z,w),(w-((x+y)/z)))", - "equal($f28(x,y,z,w),(w-((x+y)*z)))", - "equal($f29(x,y,z,w),(w-((x-y)/z)))", - "equal($f30(x,y,z,w),(w-((x-y)*z)))", - "equal($f31(x,y,z,w),(w-((x*y)/z)))", - "equal($f32(x,y,z,w),(w-((x*y)*z)))", - "equal($f33(x,y,z,w),(w-((x/y)/z)))", - "equal($f34(x,y,z,w),(w-((x/y)*z)))", - "equal($f35(x,y,z,w),(((x+y)*z)-w))", - "equal($f36(x,y,z,w),(((x-y)*z)-w))", - "equal($f37(x,y,z,w),(((x*y)*z)-w))", - "equal($f38(x,y,z,w),(((x/y)*z)-w))", - "equal($f39(x,y,z,w),(((x+y)/z)-w))", - "equal($f40(x,y,z,w),(((x-y)/z)-w))", - "equal($f41(x,y,z,w),(((x*y)/z)-w))", - "equal($f42(x,y,z,w),(((x/y)/z)-w))", + "equal($f18(x,y,z),(x*y^2+z))", + "equal($f19(x,y,z),(x*y^3+z))", + "equal($f20(x,y,z),(x*y^4+z))", + "equal($f21(x,y,z),(x*y^5+z))", + "equal($f22(x,y,z),(x*y^6+z))", + "equal($f23(x,y,z),(x*y^7+z))", + "equal($f24(x,y,z),(x*y^8+z))", + "equal($f25(x,y,z),(x*y^9+z))", + "equal($f26(x,y,z,w),(w+((x+y)/z)))", + "equal($f27(x,y,z,w),(w+((x+y)*z)))", + "equal($f28(x,y,z,w),(w+((x-y)/z)))", + "equal($f29(x,y,z,w),(w+((x-y)*z)))", + "equal($f30(x,y,z,w),(w+((x*y)/z)))", + "equal($f31(x,y,z,w),(w+((x*y)*z)))", + "equal($f32(x,y,z,w),(w+((x/y)+z)))", + "equal($f33(x,y,z,w),(w+((x/y)/z)))", + "equal($f34(x,y,z,w),(w+((x/y)*z)))", + "equal($f35(x,y,z,w),(w-((x+y)/z)))", + "equal($f36(x,y,z,w),(w-((x+y)*z)))", + "equal($f37(x,y,z,w),(w-((x-y)/z)))", + "equal($f38(x,y,z,w),(w-((x-y)*z)))", + "equal($f39(x,y,z,w),(w-((x*y)/z)))", + "equal($f40(x,y,z,w),(w-((x*y)*z)))", + "equal($f41(x,y,z,w),(w-((x/y)/z)))", + "equal($f42(x,y,z,w),(w-((x/y)*z)))", + "equal($f43(x,y,z,w),(((x+y)*z)-w))", + "equal($f44(x,y,z,w),(((x-y)*z)-w))", + "equal($f45(x,y,z,w),(((x*y)*z)-w))", + "equal($f46(x,y,z,w),(((x/y)*z)-w))", + "equal($f47(x,y,z,w),(((x+y)/z)-w))", + "equal($f48(x,y,z,w),(((x-y)/z)-w))", + "equal($f49(x,y,z,w),(((x*y)/z)-w))", + "equal($f50(x,y,z,w),(((x/y)/z)-w))", + "equal($f51(x,y,z,w),(x*y^2+z*w^2))", + "equal($f52(x,y,z,w),(x*y^3+z*w^3))", + "equal($f53(x,y,z,w),(x*y^4+z*w^4))", + "equal($f54(x,y,z,w),(x*y^5+z*w^5))", + "equal($f55(x,y,z,w),(x*y^6+z*w^6))", + "equal($f56(x,y,z,w),(x*y^7+z*w^7))", + "equal($f57(x,y,z,w),(x*y^8+z*w^8))", + "equal($f58(x,y,z,w),(x*y^9+z*w^9))" }; static const std::size_t expr_str_size = sizeof(expr_str) / sizeof(std::string); - static const std::size_t rounds = 1000; + static const std::size_t rounds = 100; for (std::size_t i = 0; i < rounds; ++i) { for (std::size_t j = 0; j < expr_str_size; ++j) { typedef exprtk::expression expression_t; - T x = T(1.0); - T y = T(2.0); - T z = T(3.0); - T w = T(4.0); - T u = T(5.0); + T x = T(1.123); + T y = T(2.123); + T z = T(3.123); + T w = T(4.123); + T u = T(5.123); exprtk::symbol_table symbol_table; symbol_table.add_variable("x",x); @@ -1470,6 +1511,7 @@ inline bool run_test08() expression.value(); } } + return true; } @@ -1487,7 +1529,7 @@ struct myfunc : public exprtk::ifunction template inline bool run_test09() { - static const std::size_t rounds = 100000; + static const std::size_t rounds = 10000; for (std::size_t i = 0; i < rounds; ++i) { typedef exprtk::expression expression_t; @@ -1496,24 +1538,24 @@ inline bool run_test09() "myfunc4(sin(x*pi),y/2)+myfunc5(sin(x*pi),y/2)+" "myfunc6(sin(x*pi),y/2)+myfunc7(sin(x*pi),y/2)+" "myfunc8(sin(x*pi),y/2)+myfunc9(sin(x*pi),y/2)+" - "myfunc0(sin(1*pi),y/2)+myfunc1(sin(1*pi),y/2)+" - "myfunc2(sin(1*pi),y/2)+myfunc3(sin(1*pi),y/2)+" - "myfunc4(sin(1*pi),y/2)+myfunc5(sin(1*pi),y/2)+" - "myfunc6(sin(1*pi),y/2)+myfunc7(sin(1*pi),y/2)+" - "myfunc8(sin(1*pi),y/2)+myfunc9(sin(1*pi),y/2)+" - "myfunc0(sin(x*pi),2/2)+myfunc1(sin(x*pi),2/2)+" - "myfunc2(sin(x*pi),2/2)+myfunc3(sin(x*pi),2/2)+" - "myfunc4(sin(x*pi),2/2)+myfunc5(sin(x*pi),2/2)+" - "myfunc6(sin(x*pi),2/2)+myfunc7(sin(x*pi),2/2)+" - "myfunc8(sin(x*pi),2/2)+myfunc9(sin(x*pi),2/2)+" - "myfunc0(sin(1*pi),2/2)+myfunc1(sin(1*pi),2/2)+" - "myfunc2(sin(1*pi),2/2)+myfunc3(sin(1*pi),2/2)+" - "myfunc4(sin(1*pi),2/2)+myfunc5(sin(1*pi),2/2)+" - "myfunc6(sin(1*pi),2/2)+myfunc7(sin(1*pi),2/2)+" - "myfunc8(sin(1*pi),2/2)+myfunc9(sin(1*pi),2/2)"; + "myfunc0(sin(x*pi),y/2)+myfunc1(sin(x*pi),y/2)+" + "myfunc2(sin(x*pi),y/2)+myfunc3(sin(x*pi),y/2)+" + "myfunc4(sin(x*pi),y/2)+myfunc5(sin(x*pi),y/2)+" + "myfunc6(sin(x*pi),y/2)+myfunc7(sin(x*pi),y/2)+" + "myfunc8(sin(x*pi),y/2)+myfunc9(sin(x*pi),y/2)+" + "myfunc0(sin(x*pi),y/2)+myfunc1(sin(x*pi),y/2)+" + "myfunc2(sin(x*pi),y/2)+myfunc3(sin(x*pi),y/2)+" + "myfunc4(sin(x*pi),y/2)+myfunc5(sin(x*pi),y/2)+" + "myfunc6(sin(x*pi),y/2)+myfunc7(sin(x*pi),y/2)+" + "myfunc8(sin(x*pi),y/2)+myfunc9(sin(x*pi),y/2)+" + "myfunc0(sin(x*pi),y/2)+myfunc1(sin(x*pi),y/2)+" + "myfunc2(sin(x*pi),y/2)+myfunc3(sin(x*pi),y/2)+" + "myfunc4(sin(x*pi),y/2)+myfunc5(sin(x*pi),y/2)+" + "myfunc6(sin(x*pi),y/2)+myfunc7(sin(x*pi),y/2)+" + "myfunc8(sin(x*pi),y/2)+myfunc9(sin(x*pi),y/2)"; - T x = T(1.0); - T y = T(2.0); + T x = T(1.0) + (i/10000.0); + T y = T(2.0) + (i/10000.0); myfunc mf; exprtk::symbol_table symbol_table; @@ -1541,7 +1583,7 @@ inline bool run_test09() std::cout << "run_test09() - Error: " << parser.error() << "\tExpression: " << expression_string << std::endl; return false; } - const T pi = T(3.14159265358979323846); + const T pi = T(3.141592653589793238462); T result = expression.value(); T expected = T(4.0) * @@ -1607,7 +1649,7 @@ inline bool run_test10() } }; - static const std::size_t rounds = 1000; + static const std::size_t rounds = 100; for (std::size_t r = 0; r < rounds; ++r) { @@ -1964,7 +2006,7 @@ inline bool run_test10() T y0 = T(0); T z0 = T(0); std::string expression_string = "(x0 + y0) / z0"; - static const std::size_t rounds = 10000000; + static const std::size_t rounds = 1000000; for (std::size_t i = 0; i < rounds; ++i) { expression_t expression0; @@ -2023,7 +2065,7 @@ inline bool run_test11() expression_t expression; expression.register_symbol_table(symbol_table); - static const std::size_t rounds = 100000; + static const std::size_t rounds = 10000; for (std::size_t i = 0; i < rounds; ++i) { diff --git a/readme.txt b/readme.txt index 0dd7e0c..8e62a08 100644 --- a/readme.txt +++ b/readme.txt @@ -30,7 +30,7 @@ operations, functions and processes: (6) Conditional & Loop statement: if-then-else, while -(7) Assigment: :=, <- +(7) Assigment: := [EXAMPLE EXPRESSIONS] @@ -93,6 +93,56 @@ Expression Library can be found at: (*) Comeau C++ Compiler (4.3+) +[SPECIAL FUNCTIONS] +The purpose of special functions in ExprTk is to provide compiler +generated equivalents of common mathematical expressions which can be +invoked by using the 'special function' syntax (eg: $f12(x,y,z) or +$f24(x,y,z,w)). + +Special functions dramatically decrease the total evaluation time of +expressions which would otherwise have been written using the common +form by reducing the total number of nodes in the evaluation tree of +an expression and by also leveraging the compiler's ability to +correctly optimize such expressions for a given architecture. + + 3-Parameter 4-Parameter + | Prototype | Operation | | Prototype | Operation | + +------------+-------------+ +--------------+------------------+ + sf00(x,y,z) | (x + y) / z sf26(x,y,z,w) | w + ((x + y) / z) + sf01(x,y,z) | (x + y) * z sf27(x,y,z,w) | w + ((x + y) * z) + sf02(x,y,z) | (x - y) / z sf28(x,y,z,w) | w + ((x - y) / z) + sf03(x,y,z) | (x - y) * z sf29(x,y,z,w) | w + ((x - y) * z) + sf04(x,y,z) | (x * y) + z sf30(x,y,z,w) | w + ((x * y) / z) + sf05(x,y,z) | (x * y) - z sf31(x,y,z,w) | w + ((x * y) * z) + sf06(x,y,z) | (x * y) / z sf32(x,y,z,w) | w + ((x / y) + z) + sf07(x,y,z) | (x * y) * z sf33(x,y,z,w) | w + ((x / y) / z) + sf08(x,y,z) | (x / y) + z sf34(x,y,z,w) | w + ((x / y) * z) + sf09(x,y,z) | (x / y) - z sf35(x,y,z,w) | w - ((x + y) / z) + sf10(x,y,z) | (x / y) / z sf36(x,y,z,w) | w - ((x + y) * z) + sf11(x,y,z) | (x / y) * z sf37(x,y,z,w) | w - ((x - y) / z) + sf12(x,y,z) | z / (x + y) sf38(x,y,z,w) | w - ((x - y) * z) + sf13(x,y,z) | z / (x - y) sf39(x,y,z,w) | w - ((x * y) / z) + sf14(x,y,z) | z / (x * y) sf40(x,y,z,w) | w - ((x * y) * z) + sf15(x,y,z) | z / (x / y) sf41(x,y,z,w) | w - ((x / y) / z) + sf16(x,y,z) | z - (x / y) sf42(x,y,z,w) | w - ((x / y) * z) + sf17(x,y,z) | z - (x / y) sf43(x,y,z,w) | ((x + y) * z) - w + sf18(x,y,z) | x * y^2 + z sf44(x,y,z,w) | ((x - y) * z) - w + sf19(x,y,z) | x * y^3 + z sf45(x,y,z,w) | ((x * y) * z) - w + sf20(x,y,z) | x * y^4 + z sf46(x,y,z,w) | ((x / y) * z) - w + sf21(x,y,z) | x * y^5 + z sf47(x,y,z,w) | ((x + y) / z) - w + sf22(x,y,z) | x * y^6 + z sf48(x,y,z,w) | ((x - y) / z) - w + sf23(x,y,z) | x * y^7 + z sf49(x,y,z,w) | ((x * y) / z) - w + sf24(x,y,z) | x * y^8 + z sf50(x,y,z,w) | ((x / y) / z) - w + sf25(x,y,z) | x * y^9 + z sf51(x,y,z,w) | x * y^2 + z * w^2 + sf52(x,y,z,w) | x * y^3 + z * w^3 + sf53(x,y,z,w) | x * y^4 + z * w^4 + sf54(x,y,z,w) | x * y^5 + z * w^5 + sf55(x,y,z,w) | x * y^6 + z * w^6 + sf56(x,y,z,w) | x * y^7 + z * w^7 + sf57(x,y,z,w) | x * y^8 + z * w^8 + sf58(x,y,z,w) | x * y^9 + z * w^9 + + [MACROS] ExprTk utilizes certain macros to modify the underlying behaviour of the parser and the evaluation engine. The following macros are used to