From 26f17458a4021dbb36fb61b6b4b1c90105a1efe6 Mon Sep 17 00:00:00 2001 From: Arash Partow Date: Fri, 18 May 2012 07:31:29 +1000 Subject: [PATCH] C++ Mathematical Expression Library (ExprTk) http://www.partow.net/programming/exprtk/index.html --- exprtk.hpp | 151 +++++++++++++++++++++++-------------------- exprtk_benchmark.cpp | 15 ++--- readme.txt | 4 +- 3 files changed, 88 insertions(+), 82 deletions(-) diff --git a/exprtk.hpp b/exprtk.hpp index 49edaf2..5311ec7 100644 --- a/exprtk.hpp +++ b/exprtk.hpp @@ -546,57 +546,57 @@ namespace exprtk return erfc_impl(static_cast(v),real_type_tag()); } - template inline T abs_impl (const T v, real_type_tag) { return std::abs (v); } - template inline T acos_impl (const T v, real_type_tag) { return std::acos (v); } - template inline T asin_impl (const T v, real_type_tag) { return std::asin (v); } - template inline T atan_impl (const T v, real_type_tag) { return std::atan (v); } - template inline T ceil_impl (const T v, real_type_tag) { return std::ceil (v); } - template inline T cos_impl (const T v, real_type_tag) { return std::cos (v); } - template inline T cosh_impl (const T v, real_type_tag) { return std::cosh (v); } - template inline T exp_impl (const T v, real_type_tag) { return std::exp (v); } - template inline T floor_impl(const T v, real_type_tag) { return std::floor(v); } - template inline T log_impl (const T v, real_type_tag) { return std::log (v); } - template inline T log10_impl(const T v, real_type_tag) { return std::log10(v); } - template inline T neg_impl (const T v, real_type_tag) { return -v; } - template inline T pos_impl (const T v, real_type_tag) { return +v; } - template inline T round_impl(const T v, real_type_tag) { return std::floor(v + T(0.5)); } - template inline T sin_impl (const T v, real_type_tag) { return std::sin (v); } - template inline T sinh_impl (const T v, real_type_tag) { return std::sinh (v); } - template inline T sqrt_impl (const T v, real_type_tag) { return std::sqrt (v); } - template inline T tan_impl (const T v, real_type_tag) { return std::tan (v); } - template inline T tanh_impl (const T v, real_type_tag) { return std::tanh (v); } - template inline T cot_impl (const T v, real_type_tag) { return T(1) / std::tan(v); } - template inline T sec_impl (const T v, real_type_tag) { return T(1) / std::cos(v); } - template inline T csc_impl (const T v, real_type_tag) { return T(1) / std::sin(v); } - template inline T r2d_impl (const T v, real_type_tag) { return (v * T(numeric::constant::_180_pi)); } - template inline T d2r_impl (const T v, real_type_tag) { return (v * T(numeric::constant::pi_180)); } - template inline T d2g_impl (const T v, real_type_tag) { return (v * T(20.0/9.0)); } - template inline T g2d_impl (const T v, real_type_tag) { return (v * T(9.0/20.0)); } - template inline T notl_impl (const T v, real_type_tag) { return (v != T(0) ? T(0) : T(1)); } + template inline T abs_impl(const T& v, real_type_tag) { return std::abs (v); } + template inline T acos_impl(const T& v, real_type_tag) { return std::acos (v); } + template inline T asin_impl(const T& v, real_type_tag) { return std::asin (v); } + template inline T atan_impl(const T& v, real_type_tag) { return std::atan (v); } + template inline T ceil_impl(const T& v, real_type_tag) { return std::ceil (v); } + template inline T cos_impl(const T& v, real_type_tag) { return std::cos (v); } + template inline T cosh_impl(const T& v, real_type_tag) { return std::cosh (v); } + template inline T exp_impl(const T& v, real_type_tag) { return std::exp (v); } + template inline T floor_impl(const T& v, real_type_tag) { return std::floor(v); } + template inline T log_impl(const T& v, real_type_tag) { return std::log (v); } + template inline T log10_impl(const T& v, real_type_tag) { return std::log10(v); } + template inline T neg_impl(const T& v, real_type_tag) { return -v; } + template inline T pos_impl(const T& v, real_type_tag) { return +v; } + template inline T round_impl(const T& v, real_type_tag) { return std::floor(v + T(0.5)); } + template inline T sin_impl(const T& v, real_type_tag) { return std::sin (v); } + template inline T sinh_impl(const T& v, real_type_tag) { return std::sinh (v); } + template inline T sqrt_impl(const T& v, real_type_tag) { return std::sqrt (v); } + template inline T tan_impl(const T& v, real_type_tag) { return std::tan (v); } + template inline T tanh_impl(const T& v, real_type_tag) { return std::tanh (v); } + template inline T cot_impl(const T& v, real_type_tag) { return T(1) / std::tan(v); } + template inline T sec_impl(const T& v, real_type_tag) { return T(1) / std::cos(v); } + template inline T csc_impl(const T& v, real_type_tag) { return T(1) / std::sin(v); } + template inline T r2d_impl(const T& v, real_type_tag) { return (v * T(numeric::constant::_180_pi)); } + template inline T d2r_impl(const T& v, real_type_tag) { return (v * T(numeric::constant::pi_180)); } + template inline T d2g_impl(const T& v, real_type_tag) { return (v * T(20.0/9.0)); } + template inline T g2d_impl(const T& v, real_type_tag) { return (v * T(9.0/20.0)); } + template inline T notl_impl(const T& v, real_type_tag) { return (v != T(0) ? T(0) : T(1)); } - template inline T abs_impl (const T v, int_type_tag) { return std::abs (v); } - template inline T exp_impl (const T v, int_type_tag) { return std::exp (v); } - template inline T log_impl (const T v, int_type_tag) { return std::log (v); } - template inline T log10_impl(const T v, int_type_tag) { return std::log10(v); } - template inline T neg_impl (const T v, int_type_tag) { return -v; } - template inline T pos_impl (const T v, int_type_tag) { return +v; } - template inline T ceil_impl (const T v, int_type_tag) { return v; } - template inline T floor_impl(const T v, int_type_tag) { return v; } - template inline T round_impl(const T v, int_type_tag) { return v; } - template inline T notl_impl (const T v, int_type_tag) { return !v; } - template inline T sqrt_impl (const T v, int_type_tag) { return std::sqrt (v); } - template inline T acos_impl (const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } - template inline T asin_impl (const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } - template inline T atan_impl (const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } - template inline T cos_impl (const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } - template inline T cosh_impl (const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } - template inline T sin_impl (const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } - template inline T sinh_impl (const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } - template inline T tan_impl (const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } - template inline T tanh_impl (const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } - template inline T cot_impl (const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } - template inline T sec_impl (const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } - template inline T csc_impl (const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } + template inline T abs_impl(const T& v, int_type_tag) { return std::abs (v); } + template inline T exp_impl(const T& v, int_type_tag) { return std::exp (v); } + template inline T log_impl(const T& v, int_type_tag) { return std::log (v); } + template inline T log10_impl(const T& v, int_type_tag) { return std::log10(v); } + template inline T neg_impl(const T& v, int_type_tag) { return -v; } + template inline T pos_impl(const T& v, int_type_tag) { return +v; } + template inline T ceil_impl(const T& v, int_type_tag) { return v; } + template inline T floor_impl(const T& v, int_type_tag) { return v; } + template inline T round_impl(const T& v, int_type_tag) { return v; } + template inline T notl_impl(const T& v, int_type_tag) { return !v; } + template inline T sqrt_impl(const T& v, int_type_tag) { return std::sqrt (v); } + template inline T acos_impl(const T& , int_type_tag) { return std::numeric_limits::quiet_NaN(); } + template inline T asin_impl(const T& , int_type_tag) { return std::numeric_limits::quiet_NaN(); } + template inline T atan_impl(const T& , int_type_tag) { return std::numeric_limits::quiet_NaN(); } + template inline T cos_impl(const T& , int_type_tag) { return std::numeric_limits::quiet_NaN(); } + template inline T cosh_impl(const T& , int_type_tag) { return std::numeric_limits::quiet_NaN(); } + template inline T sin_impl(const T& , int_type_tag) { return std::numeric_limits::quiet_NaN(); } + template inline T sinh_impl(const T& , int_type_tag) { return std::numeric_limits::quiet_NaN(); } + template inline T tan_impl(const T& , int_type_tag) { return std::numeric_limits::quiet_NaN(); } + template inline T tanh_impl(const T& , int_type_tag) { return std::numeric_limits::quiet_NaN(); } + template inline T cot_impl(const T& , int_type_tag) { return std::numeric_limits::quiet_NaN(); } + template inline T sec_impl(const T& , int_type_tag) { return std::numeric_limits::quiet_NaN(); } + template inline T csc_impl(const T& , int_type_tag) { return std::numeric_limits::quiet_NaN(); } template inline bool is_integer_impl(const T& v, real_type_tag) @@ -2077,8 +2077,24 @@ namespace exprtk bool branch_deletable_; }; + template + struct construct_branch_pair + { + template + static inline void process(std::pair*,bool> (&)[N], expression_node*) + {} + }; + + template + struct construct_branch_pair + { + template + static inline void process(std::pair*,bool> (&branch)[N], expression_node* b) + { if (b) branch[D] = std::make_pair(b,branch_deletable(b)); } + }; + template - inline void init_branches(std::pair< expression_node*,bool> (&branch)[N], + inline void init_branches(std::pair*,bool> (&branch)[N], expression_node* b0, expression_node* b1 = reinterpret_cast*>(0), expression_node* b2 = reinterpret_cast*>(0), @@ -2090,25 +2106,16 @@ namespace exprtk expression_node* b8 = reinterpret_cast*>(0), expression_node* b9 = reinterpret_cast*>(0)) { - typedef expression_node Node; - //Needed for incompetent and broken msvc compiler versions - #ifdef _MSC_VER - #pragma warning(push) - #pragma warning(disable: 4127) - #endif - if (b0 && (N > 0)) { branch[0] = std::make_pair(b0,branch_deletable(b0)); } - if (b1 && (N > 1)) { branch[1] = std::make_pair(b1,branch_deletable(b1)); } - if (b2 && (N > 2)) { branch[2] = std::make_pair(b2,branch_deletable(b2)); } - if (b3 && (N > 3)) { branch[3] = std::make_pair(b3,branch_deletable(b3)); } - if (b4 && (N > 4)) { branch[4] = std::make_pair(b4,branch_deletable(b4)); } - if (b5 && (N > 5)) { branch[5] = std::make_pair(b5,branch_deletable(b5)); } - if (b6 && (N > 6)) { branch[6] = std::make_pair(b6,branch_deletable(b6)); } - if (b7 && (N > 7)) { branch[7] = std::make_pair(b7,branch_deletable(b7)); } - if (b8 && (N > 8)) { branch[8] = std::make_pair(b8,branch_deletable(b8)); } - if (b9 && (N > 9)) { branch[9] = std::make_pair(b9,branch_deletable(b9)); } - #ifdef _MSC_VER - #pragma warning(pop) - #endif + construct_branch_pair 0)>::process(branch,b0); + construct_branch_pair 1)>::process(branch,b1); + construct_branch_pair 2)>::process(branch,b2); + construct_branch_pair 3)>::process(branch,b3); + construct_branch_pair 4)>::process(branch,b4); + construct_branch_pair 5)>::process(branch,b5); + construct_branch_pair 6)>::process(branch,b6); + construct_branch_pair 7)>::process(branch,b7); + construct_branch_pair 8)>::process(branch,b8); + construct_branch_pair 9)>::process(branch,b9); } template @@ -7892,6 +7899,7 @@ namespace exprtk "1 - sin(2 * x) + cos(pi / y)", "sqrt(1 - sin(2 * x) + cos(pi / y) / 3)", "(x^2 / sin(2 * pi / y)) -x / 2", + "x + (cos(y - sin(2 / x * pi)) - sin(x - cos(2 * y / pi))) - y", "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", @@ -7906,10 +7914,11 @@ namespace exprtk "1 - sin(2 * xx) + cos(pi / yy)", "sqrt(1 - sin(2 * xx) + cos(pi / yy) / 3)", "(xx^2 / sin(2 * pi / yy)) -xx / 2", + "xx + (cos(yy - sin(2 / xx * pi)) - sin(xx - cos(2 * yy / pi))) - yy", "clamp(-1.0, sin(2 * pi * xx) + cos(yy / 2 * pi), +1.0)", "max(3.33, min(sqrt(1 - sin(2 * xx) + cos(pi / yy) / 3), 1.11))", "if(avg(xx,yy) <= xx + yy, xx - yy, xx * yy) + 2 * pi / xx", - "1.1xx^1 + 2.2yy^2 - 3.3xx^3 + 4.4yy^4 - 5.5xx^5 + 6.6yy^6 - 7.7xx^27 + 8.8yy^55", + "1.1xx^1 + 2.2yy^2 - 3.3xx^3 + 4.4yy^4 - 5.5xx^5 + 6.6yy^6 - 7.7xx^27 + 8.8yy^55" }; static const std::size_t expression_list_size = sizeof(expression_list) / sizeof(std::string); diff --git a/exprtk_benchmark.cpp b/exprtk_benchmark.cpp index cc4f5a2..ef6e91e 100644 --- a/exprtk_benchmark.cpp +++ b/exprtk_benchmark.cpp @@ -33,7 +33,7 @@ const std::string expression_list[] = { "1.1x^1 + 2.2y^2 - 3.3x^3 + 4.4y^15 - 5.5x^23 + 6.6y^55", "sin(2 * x) + cos(pi / y)", "1 - sin(2 * x) + cos(pi / y)", - "sqrt(1 - sin(2 * x) + cos(pi / y) / 3)", + "sqrt(111.111 - sin(2 * x) + cos(pi / y) / 333.333)", "(x^2 / sin(2 * pi / y)) -x / 2", "x + (cos(y - sin(2 / x * pi)) - sin(x - cos(2 * y / pi))) - y", "clamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)", @@ -97,18 +97,15 @@ void run_benchmark(T& x, T& y, const double pi = 3.14159265358979323846; template -inline T avg(const T& v1, const T& v2) +inline T avg(const T v1, const T v2) { - return v1 + v2 / T(2.0); + return (v1 + v2) / T(2.0); } template -inline T clamp(const T& l, const T& v, const T& u) +inline T clamp(const T l, const T v, const T u) { - if (v < l) - return l; - else - return (v > u) ? u : v; + return ((v < l) ? l : ((v > u) ? u : v)); } template inline T func00(const T x, const T y) { return (y + x); } @@ -120,7 +117,7 @@ template inline T func05(const T x, const T y) { return T(1.0) - (( template inline T func06(const T x, const T y) { return (1.1*pow(x,T(1.0))+2.2*pow(y,T(2.0))-3.3*pow(x,T(3.0))+4.4*pow(y,T(15.0))-5.5*pow(x,T(23.0))+6.6*pow(y,T(55.0))); } template inline T func07(const T x, const T y) { return std::sin(T(2.0) * x) + std::cos(pi / y); } template inline T func08(const T x, const T y) { return T(1.0) - std::sin(2.0 * x) + std::cos(pi / y); } -template inline T func09(const T x, const T y) { return std::sqrt(T(1.0) - std::sin(T(2.0) * x) + std::cos(pi / y) / T(3.0)); } +template inline T func09(const T x, const T y) { return std::sqrt(T(111.111) - std::sin(T(2.0) * x) + std::cos(pi / y) / T(333.333)); } template inline T func10(const T x, const T y) { return (std::pow(x,T(2.0)) / std::sin(T(2.0) * pi / y)) -x / T(2.0); } template inline T func11(const T x, const T y) { return (x + (std::cos(y - std::sin(2 / x * pi)) - std::sin(x - std::cos(2 * y / pi))) - y); } template inline T func12(const T x, const T y) { return clamp(T(-1.0), std::sin(T(2.0) * pi * x) + std::cos(y / T(2.0) * pi), + T(1.0)); } diff --git a/readme.txt b/readme.txt index 4e6000c..94c200a 100644 --- a/readme.txt +++ b/readme.txt @@ -20,8 +20,8 @@ operations, functions and processes: 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 + cot, csc, sec, sinh, tanh, rad2deg, deg2rad, + deg2grad, grad2deg, hyp (4) Equalities & Inequalities: =, ==, <>, !=, <, <=, >, >=,