From 3c933cd8cfcbb8969e5d2cc86f8c725d95c22f27 Mon Sep 17 00:00:00 2001 From: Arash Partow Date: Mon, 9 Dec 2013 09:30:01 +1100 Subject: [PATCH] C++ Mathematical Expression Library (ExprTk) http://www.partow.net/programming/exprtk/index.html --- Makefile | 2 +- exprtk.hpp | 426 ++++++++++++++++++++++++++++++------------------ exprtk_test.cpp | 26 +-- readme.txt | 17 +- 4 files changed, 297 insertions(+), 174 deletions(-) diff --git a/Makefile b/Makefile index 2561cf5..71c85d0 100644 --- a/Makefile +++ b/Makefile @@ -20,7 +20,7 @@ COMPILER = -c++ OPTIMIZATION_OPT = -O1 BASE_OPTIONS = -ansi -pedantic-errors -Wall -Wextra -Werror -Wno-long-long OPTIONS = $(BASE_OPTIONS) $(OPTIMIZATION_OPT) -o -LINKER_OPT = -L/usr/lib -lstdc++ +LINKER_OPT = -L/usr/lib -lstdc++ -lm BUILD_LIST+=exprtk_test BUILD_LIST+=exprtk_benchmark diff --git a/exprtk.hpp b/exprtk.hpp index 8229211..82413ad 100644 --- a/exprtk.hpp +++ b/exprtk.hpp @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -438,11 +439,11 @@ namespace exprtk template struct number_type { typedef unknown_type_tag type; }; - #define exprtk_register_real_type_tag(T)\ - template<> struct number_type { typedef real_type_tag type; }; + #define exprtk_register_real_type_tag(T) \ + template<> struct number_type { typedef real_type_tag type; }; \ - #define exprtk_register_int_type_tag(T)\ - template<> struct number_type { typedef int_type_tag type; }; + #define exprtk_register_int_type_tag(T) \ + template<> struct number_type { typedef int_type_tag type; }; \ exprtk_register_real_type_tag(double) exprtk_register_real_type_tag(long double) @@ -609,7 +610,10 @@ namespace exprtk { const int index = std::max(0, std::min(pow10_size - 1, (int)std::floor(v1))); const T p10 = T(pow10[index]); - return T(std::floor((v0 * p10) + T(0.5)) / p10); + if (v0 < T(0)) + return T(std::ceil ((v0 * p10) - T(0.5)) / p10); + else + return T(std::floor((v0 * p10) + T(0.5)) / p10); } template @@ -1049,13 +1053,13 @@ namespace exprtk template struct fast_exp { static inline T result(T v) { return v; } }; template struct fast_exp { static inline T result(T ) { return T(1); } }; - #define exprtk_define_unary_function(FunctionName) \ - template \ - inline T FunctionName (const T v) \ - { \ - typename details::number_type::type num_type; \ + #define exprtk_define_unary_function(FunctionName) \ + template \ + inline T FunctionName (const T v) \ + { \ + typename details::number_type::type num_type; \ return details:: FunctionName##_impl(v,num_type); \ - } + } \ exprtk_define_unary_function(abs ) exprtk_define_unary_function(acos ) @@ -5156,52 +5160,52 @@ namespace exprtk mutable std::vector value_list_; }; - #define exprtk_def_unary_op(OpName) \ - template \ - struct OpName##_op \ - { \ - typedef typename functor_t::Type Type; \ - static inline T process(Type v) { return numeric:: OpName (v); } \ + #define exprtk_define_unary_op(OpName) \ + template \ + struct OpName##_op \ + { \ + typedef typename functor_t::Type Type; \ + static inline T process(Type v) { return numeric:: OpName (v); } \ static inline typename expression_node::node_type type() { return expression_node::e_##OpName; } \ - static inline details::operator_type operation() { return details::e_##OpName; } \ - }; + static inline details::operator_type operation() { return details::e_##OpName; } \ + }; \ - exprtk_def_unary_op(abs ) - exprtk_def_unary_op(acos ) - exprtk_def_unary_op(asin ) - exprtk_def_unary_op(atan ) - exprtk_def_unary_op(ceil ) - exprtk_def_unary_op(cos ) - exprtk_def_unary_op(cosh ) - exprtk_def_unary_op(cot ) - exprtk_def_unary_op(csc ) - exprtk_def_unary_op(d2g ) - exprtk_def_unary_op(d2r ) - exprtk_def_unary_op(erf ) - exprtk_def_unary_op(erfc ) - exprtk_def_unary_op(exp ) - exprtk_def_unary_op(expm1) - exprtk_def_unary_op(floor) - exprtk_def_unary_op(frac ) - exprtk_def_unary_op(g2d ) - exprtk_def_unary_op(log ) - exprtk_def_unary_op(log10) - exprtk_def_unary_op(log2 ) - exprtk_def_unary_op(log1p) - exprtk_def_unary_op(neg ) - exprtk_def_unary_op(notl ) - exprtk_def_unary_op(pos ) - exprtk_def_unary_op(r2d ) - exprtk_def_unary_op(round) - exprtk_def_unary_op(sec ) - exprtk_def_unary_op(sgn ) - exprtk_def_unary_op(sin ) - exprtk_def_unary_op(sinh ) - exprtk_def_unary_op(sqrt ) - exprtk_def_unary_op(tan ) - exprtk_def_unary_op(tanh ) - exprtk_def_unary_op(trunc) - #undef exprtk_def_unary_op + exprtk_define_unary_op(abs ) + exprtk_define_unary_op(acos ) + exprtk_define_unary_op(asin ) + exprtk_define_unary_op(atan ) + exprtk_define_unary_op(ceil ) + exprtk_define_unary_op(cos ) + exprtk_define_unary_op(cosh ) + exprtk_define_unary_op(cot ) + exprtk_define_unary_op(csc ) + exprtk_define_unary_op(d2g ) + exprtk_define_unary_op(d2r ) + exprtk_define_unary_op(erf ) + exprtk_define_unary_op(erfc ) + exprtk_define_unary_op(exp ) + exprtk_define_unary_op(expm1) + exprtk_define_unary_op(floor) + exprtk_define_unary_op(frac ) + exprtk_define_unary_op(g2d ) + exprtk_define_unary_op(log ) + exprtk_define_unary_op(log10) + exprtk_define_unary_op(log2 ) + exprtk_define_unary_op(log1p) + exprtk_define_unary_op(neg ) + exprtk_define_unary_op(notl ) + exprtk_define_unary_op(pos ) + exprtk_define_unary_op(r2d ) + exprtk_define_unary_op(round) + exprtk_define_unary_op(sec ) + exprtk_define_unary_op(sgn ) + exprtk_define_unary_op(sin ) + exprtk_define_unary_op(sinh ) + exprtk_define_unary_op(sqrt ) + exprtk_define_unary_op(tan ) + exprtk_define_unary_op(tanh ) + exprtk_define_unary_op(trunc) + #undef exprtk_define_unary_op template struct opr_base @@ -6520,73 +6524,73 @@ namespace exprtk template const typename expression_node::node_type nodetype_T0oT1::result = expression_node::e_none; - #define synthnode_type_def(T0_,T1_,v_) \ - template \ - struct nodetype_T0oT1 { static const typename expression_node::node_type result; }; \ - template \ + #define synthnode_type_define(T0_,T1_,v_) \ + template \ + struct nodetype_T0oT1 { static const typename expression_node::node_type result; }; \ + template \ const typename expression_node::node_type nodetype_T0oT1::result = expression_node:: v_; \ - synthnode_type_def(const T0&,const T1&, e_vov) - synthnode_type_def(const T0&,const T1 , e_voc) - synthnode_type_def(const T0 ,const T1&, e_cov) - synthnode_type_def( T0&, T1&,e_none) - synthnode_type_def(const T0 ,const T1 ,e_none) - synthnode_type_def( T0&,const T1 ,e_none) - synthnode_type_def(const T0 , T1&,e_none) - synthnode_type_def(const T0&, T1&,e_none) - synthnode_type_def( T0&,const T1&,e_none) - #undef synthnode_type_def + synthnode_type_define(const T0&,const T1&, e_vov) + synthnode_type_define(const T0&,const T1 , e_voc) + synthnode_type_define(const T0 ,const T1&, e_cov) + synthnode_type_define( T0&, T1&,e_none) + synthnode_type_define(const T0 ,const T1 ,e_none) + synthnode_type_define( T0&,const T1 ,e_none) + synthnode_type_define(const T0 , T1&,e_none) + synthnode_type_define(const T0&, T1&,e_none) + synthnode_type_define( T0&,const T1&,e_none) + #undef synthnode_type_define template struct nodetype_T0oT1oT2 { static const typename expression_node::node_type result; }; template const typename expression_node::node_type nodetype_T0oT1oT2::result = expression_node::e_none; - #define synthnode_type_def(T0_,T1_,T2_,v_) \ - template \ - struct nodetype_T0oT1oT2 { static const typename expression_node::node_type result; }; \ - template \ + #define synthnode_type_define(T0_,T1_,T2_,v_) \ + template \ + struct nodetype_T0oT1oT2 { static const typename expression_node::node_type result; }; \ + template \ const typename expression_node::node_type nodetype_T0oT1oT2::result = expression_node:: v_; \ - synthnode_type_def(const T0&,const T1&,const T2&, e_vovov) - synthnode_type_def(const T0&,const T1&,const T2 , e_vovoc) - synthnode_type_def(const T0&,const T1 ,const T2&, e_vocov) - synthnode_type_def(const T0 ,const T1&,const T2&, e_covov) - synthnode_type_def(const T0 ,const T1&,const T2 , e_covoc) - synthnode_type_def(const T0 ,const T1 ,const T2 , e_none ) - synthnode_type_def(const T0 ,const T1 ,const T2&, e_none ) - synthnode_type_def(const T0&,const T1 ,const T2 , e_none ) - synthnode_type_def( T0&, T1&, T2&, e_none ) - #undef synthnode_type_def + synthnode_type_define(const T0&,const T1&,const T2&, e_vovov) + synthnode_type_define(const T0&,const T1&,const T2 , e_vovoc) + synthnode_type_define(const T0&,const T1 ,const T2&, e_vocov) + synthnode_type_define(const T0 ,const T1&,const T2&, e_covov) + synthnode_type_define(const T0 ,const T1&,const T2 , e_covoc) + synthnode_type_define(const T0 ,const T1 ,const T2 , e_none ) + synthnode_type_define(const T0 ,const T1 ,const T2&, e_none ) + synthnode_type_define(const T0&,const T1 ,const T2 , e_none ) + synthnode_type_define( T0&, T1&, T2&, e_none ) + #undef synthnode_type_define template struct nodetype_T0oT1oT2oT3 { static const typename expression_node::node_type result; }; template const typename expression_node::node_type nodetype_T0oT1oT2oT3::result = expression_node::e_none; - #define synthnode_type_def(T0_,T1_,T2_,T3_,v_) \ - template \ - struct nodetype_T0oT1oT2oT3 { static const typename expression_node::node_type result; }; \ - template \ + #define synthnode_type_define(T0_,T1_,T2_,T3_,v_) \ + template \ + struct nodetype_T0oT1oT2oT3 { static const typename expression_node::node_type result; }; \ + template \ const typename expression_node::node_type nodetype_T0oT1oT2oT3::result = expression_node:: v_; \ - synthnode_type_def(const T0&,const T1&,const T2&, const T3&,e_vovovov) - synthnode_type_def(const T0&,const T1&,const T2&, const T3 ,e_vovovoc) - synthnode_type_def(const T0&,const T1&,const T2 , const T3&,e_vovocov) - synthnode_type_def(const T0&,const T1 ,const T2&, const T3&,e_vocovov) - synthnode_type_def(const T0 ,const T1&,const T2&, const T3&,e_covovov) - synthnode_type_def(const T0 ,const T1&,const T2 , const T3&,e_covocov) - synthnode_type_def(const T0&,const T1 ,const T2&, const T3 ,e_vocovoc) - synthnode_type_def(const T0 ,const T1&,const T2&, const T3 ,e_covovoc) - synthnode_type_def(const T0&,const T1 ,const T2 , const T3&,e_vococov) - synthnode_type_def(const T0 ,const T1 ,const T2 , const T3 ,e_none ) - synthnode_type_def(const T0 ,const T1 ,const T2 , const T3&,e_none ) - synthnode_type_def(const T0 ,const T1 ,const T2&, const T3 ,e_none ) - synthnode_type_def(const T0 ,const T1&,const T2 , const T3 ,e_none ) - synthnode_type_def(const T0&,const T1 ,const T2 , const T3 ,e_none ) - synthnode_type_def(const T0 ,const T1 ,const T2&, const T3&,e_none ) - synthnode_type_def(const T0&,const T1&,const T2 , const T3 ,e_none ) - #undef synthnode_type_def + synthnode_type_define(const T0&,const T1&,const T2&, const T3&,e_vovovov) + synthnode_type_define(const T0&,const T1&,const T2&, const T3 ,e_vovovoc) + synthnode_type_define(const T0&,const T1&,const T2 , const T3&,e_vovocov) + synthnode_type_define(const T0&,const T1 ,const T2&, const T3&,e_vocovov) + synthnode_type_define(const T0 ,const T1&,const T2&, const T3&,e_covovov) + synthnode_type_define(const T0 ,const T1&,const T2 , const T3&,e_covocov) + synthnode_type_define(const T0&,const T1 ,const T2&, const T3 ,e_vocovoc) + synthnode_type_define(const T0 ,const T1&,const T2&, const T3 ,e_covovoc) + synthnode_type_define(const T0&,const T1 ,const T2 , const T3&,e_vococov) + synthnode_type_define(const T0 ,const T1 ,const T2 , const T3 ,e_none ) + synthnode_type_define(const T0 ,const T1 ,const T2 , const T3&,e_none ) + synthnode_type_define(const T0 ,const T1 ,const T2&, const T3 ,e_none ) + synthnode_type_define(const T0 ,const T1&,const T2 , const T3 ,e_none ) + synthnode_type_define(const T0&,const T1 ,const T2 , const T3 ,e_none ) + synthnode_type_define(const T0 ,const T1 ,const T2&, const T3&,e_none ) + synthnode_type_define(const T0&,const T1&,const T2 , const T3 ,e_none ) + #undef synthnode_type_define template class T0oT1 : public expression_node @@ -8326,7 +8330,9 @@ namespace exprtk inline void load_operations_map(std::multimap& m) { - #define register_op(Symbol,Type,Args) m.insert(std::make_pair(std::string(Symbol),details::base_operation_t(Type,Args))); + #define register_op(Symbol,Type,Args) \ + m.insert(std::make_pair(std::string(Symbol),details::base_operation_t(Type,Args))); \ + register_op( "abs",e_abs , 1) register_op( "acos",e_acos , 1) register_op( "asin",e_asin , 1) @@ -12085,8 +12091,8 @@ namespace exprtk synthesize_map_["(c)o(v)"] = synthesize_cov_expression::process; synthesize_map_["(v)o(c)"] = synthesize_voc_expression::process; - #define register_synthezier(S) \ - synthesize_map_[S ::node_type::id()] = S ::process;\ + #define register_synthezier(S) \ + synthesize_map_[S ::node_type::id()] = S ::process; \ register_synthezier(synthesize_vovov_expression0) register_synthezier(synthesize_vovov_expression1) @@ -12727,23 +12733,25 @@ namespace exprtk if ((0 == result) && details::is_true(condition)) { result = consequent; - free_node(*node_allocator_,arglist[2 * i]); break; } - else - { - free_node(*node_allocator_,arglist[(2 * i) ]); - free_node(*node_allocator_,arglist[(2 * i) + 1]); - } } - if (result) + if (0 == result) { - free_node(*node_allocator_,arglist.back()); - return result; + result = arglist.back(); } - else - return arglist.back(); + + for (std::size_t i = 0; i < arglist.size(); ++i) + { + expression_node_ptr current_expr = arglist[i]; + if (current_expr && (current_expr != result)) + { + free_node(*node_allocator_,current_expr); + } + } + + return result; } template allocate >(arglist); } - #define unary_opr_switch_statements \ + #define unary_opr_switch_statements \ case_stmt(details:: e_abs,details:: abs_op) \ case_stmt(details:: e_acos,details:: acos_op) \ case_stmt(details:: e_asin,details:: asin_op) \ @@ -12803,7 +12811,10 @@ namespace exprtk T& v = dynamic_cast*>(branch[0])->ref(); switch (operation) { - #define case_stmt(op0,op1) case op0 : return node_allocator_->allocate > >(v); + #define case_stmt(op0,op1) \ + case op0 : return node_allocator_-> \ + allocate > >(v); \ + unary_opr_switch_statements #undef case_stmt default : return error_node(); @@ -12814,7 +12825,10 @@ namespace exprtk { switch (operation) { - #define case_stmt(op0,op1) case op0 : return node_allocator_->allocate > >(branch[0]); + #define case_stmt(op0,op1) \ + case op0 : return node_allocator_-> \ + allocate > >(branch[0]); \ + unary_opr_switch_statements #undef case_stmt default : return error_node(); @@ -12826,7 +12840,12 @@ namespace exprtk expression_node_ptr temp_node = error_node(); switch (operation) { - #define case_stmt(op0,op1) case op0 : temp_node = node_allocator_->allocate > >(operation,branch); break; + #define case_stmt(op0,op1) \ + case op0 : temp_node = node_allocator_-> \ + allocate > > \ + (operation,branch); \ + break; \ + case_stmt(details::e_sf00,details::sf00_op) case_stmt(details::e_sf01,details::sf01_op) case_stmt(details::e_sf02,details::sf02_op) case_stmt(details::e_sf03,details::sf03_op) case_stmt(details::e_sf04,details::sf04_op) case_stmt(details::e_sf05,details::sf05_op) @@ -12867,7 +12886,11 @@ namespace exprtk const Type& v2 = dynamic_cast*>(branch[2])->ref(); switch (operation) { - #define case_stmt(op0,op1) case op0 : return node_allocator_->allocate_rrr > >(v0,v1,v2); + #define case_stmt(op0,op1) \ + case op0 : return node_allocator_-> \ + allocate_rrr > > \ + (v0,v1,v2); \ + case_stmt(details::e_sf00,details::sf00_op) case_stmt(details::e_sf01,details::sf01_op) case_stmt(details::e_sf02,details::sf02_op) case_stmt(details::e_sf03,details::sf03_op) case_stmt(details::e_sf04,details::sf04_op) case_stmt(details::e_sf05,details::sf05_op) @@ -12909,7 +12932,10 @@ namespace exprtk { switch (operation) { - #define case_stmt(op0,op1) case op0 : return node_allocator_->allocate > >(operation,branch); + #define case_stmt(op0,op1) \ + case op0 : return node_allocator_-> \ + allocate > >(operation,branch); \ + case_stmt(details::e_sf00,details::sf00_op) case_stmt(details::e_sf01,details::sf01_op) case_stmt(details::e_sf02,details::sf02_op) case_stmt(details::e_sf03,details::sf03_op) case_stmt(details::e_sf04,details::sf04_op) case_stmt(details::e_sf05,details::sf05_op) @@ -12945,7 +12971,11 @@ namespace exprtk expression_node_ptr temp_node = error_node(); switch (operation) { - #define case_stmt(op0,op1) case op0 : temp_node = node_allocator_->allocate > >(operation,branch); break; + #define case_stmt(op0,op1) \ + case op0 : temp_node = node_allocator_-> \ + allocate > >(operation,branch); \ + break; \ + 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) @@ -12988,7 +13018,10 @@ namespace exprtk const Type& v3 = dynamic_cast*>(branch[3])->ref(); switch (operation) { - #define case_stmt(op0,op1) case op0 : return node_allocator_->allocate_rrrr > >(v0,v1,v2,v3); + #define case_stmt(op0,op1) \ + case op0 : return node_allocator_-> \ + allocate_rrrr > >(v0,v1,v2,v3); \ + 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) @@ -13030,7 +13063,10 @@ namespace exprtk return varnode_optimize_sf4(operation,branch); switch (operation) { - #define case_stmt(op0,op1) case op0 : return node_allocator_->allocate > >(operation,branch); + #define case_stmt(op0,op1) \ + case op0 : return node_allocator_-> \ + allocate > >(operation,branch); \ + 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) @@ -13069,7 +13105,12 @@ namespace exprtk expression_node_ptr temp_node = error_node(); switch (operation) { - #define case_stmt(op0,op1) case op0 : temp_node = node_allocator_->allocate > >(arglist); break; + #define case_stmt(op0,op1) \ + case op0 : temp_node = node_allocator_-> \ + allocate > > \ + (arglist); \ + break; \ + case_stmt(details::e_sum, details::vararg_add_op ) case_stmt(details::e_prod, details::vararg_mul_op ) case_stmt(details::e_avg, details::vararg_avg_op ) @@ -13092,7 +13133,10 @@ namespace exprtk { switch (operation) { - #define case_stmt(op0,op1) case op0 : return node_allocator_->allocate > >(arglist); + #define case_stmt(op0,op1) \ + case op0 : return node_allocator_-> \ + allocate > >(arglist); \ + case_stmt(details::e_sum, details::vararg_add_op ) case_stmt(details::e_prod, details::vararg_mul_op ) case_stmt(details::e_avg, details::vararg_avg_op ) @@ -13121,7 +13165,10 @@ namespace exprtk return varnode_optimize_varargfunc(operation,arglist); switch (operation) { - #define case_stmt(op0,op1) case op0 : return node_allocator_->allocate > >(arglist); + #define case_stmt(op0,op1) \ + case op0 : return node_allocator_-> \ + allocate > >(arglist); \ + case_stmt(details::e_sum, details::vararg_add_op ) case_stmt(details::e_prod, details::vararg_mul_op ) case_stmt(details::e_avg, details::vararg_avg_op ) @@ -13277,7 +13324,7 @@ namespace exprtk } #endif - #define basic_opr_switch_statements \ + #define basic_opr_switch_statements \ case_stmt(details:: e_add,details:: add_op) \ case_stmt(details:: e_sub,details:: sub_op) \ case_stmt(details:: e_mul,details:: mul_op) \ @@ -13285,7 +13332,7 @@ namespace exprtk case_stmt(details:: e_mod,details:: mod_op) \ case_stmt(details:: e_pow,details:: pow_op) \ - #define extended_opr_switch_statements \ + #define extended_opr_switch_statements \ case_stmt(details:: e_lt,details:: lt_op) \ case_stmt(details:: e_lte,details:: lte_op) \ case_stmt(details:: e_gt,details:: gt_op) \ @@ -13305,7 +13352,10 @@ namespace exprtk { switch (p) { - #define case_stmt(cp) case cp : return node_allocator_->allocate > >(v); + #define case_stmt(cp) \ + case cp : return node_allocator_-> \ + allocate > >(v); \ + case_stmt( 1) case_stmt( 2) case_stmt( 3) case_stmt( 4) case_stmt( 5) case_stmt( 6) case_stmt( 7) case_stmt( 8) case_stmt( 9) case_stmt(10) case_stmt(11) case_stmt(12) @@ -13365,7 +13415,11 @@ namespace exprtk { switch (operation) { - #define case_stmt(op0,op1) case op0 : return expr_gen.node_allocator_->template allocate > >(branch[0],branch[1]); + #define case_stmt(op0,op1) \ + case op0 : return expr_gen.node_allocator_-> \ + template allocate > > \ + (branch[0],branch[1]); \ + basic_opr_switch_statements extended_opr_switch_statements #undef case_stmt @@ -13392,7 +13446,11 @@ namespace exprtk } switch (operation) { - #define case_stmt(op0,op1) case op0 : return expr_gen.node_allocator_->template allocate_rc > >(v,branch[1]); + #define case_stmt(op0,op1) \ + case op0 : return expr_gen.node_allocator_-> \ + template allocate_rc > > \ + (v,branch[1]); \ + basic_opr_switch_statements extended_opr_switch_statements #undef case_stmt @@ -13419,7 +13477,11 @@ namespace exprtk } switch (operation) { - #define case_stmt(op0,op1) case op0 : return expr_gen.node_allocator_->template allocate_cr > >(branch[0],v); + #define case_stmt(op0,op1) \ + case op0 : return expr_gen.node_allocator_-> \ + template allocate_cr > > \ + (branch[0],v); \ + basic_opr_switch_statements extended_opr_switch_statements #undef case_stmt @@ -13470,7 +13532,11 @@ namespace exprtk } switch (operation) { - #define case_stmt(op0,op1) case op0 : return expr_gen.node_allocator_->template allocate_rc > >(c,branch[1]); + #define case_stmt(op0,op1) \ + case op0 : return expr_gen.node_allocator_-> \ + template allocate_rc > > \ + (c,branch[1]); \ + basic_opr_switch_statements extended_opr_switch_statements #undef case_stmt @@ -13521,7 +13587,11 @@ namespace exprtk } switch (operation) { - #define case_stmt(op0,op1) case op0 : return expr_gen.node_allocator_->template allocate_cr > >(branch[0],c); + #define case_stmt(op0,op1) \ + case op0 : return expr_gen.node_allocator_-> \ + template allocate_cr > > \ + (branch[0],c); \ + basic_opr_switch_statements extended_opr_switch_statements #undef case_stmt @@ -13556,7 +13626,11 @@ namespace exprtk const Type& v2 = dynamic_cast*>(branch[1])->ref(); switch (operation) { - #define case_stmt(op0,op1) case op0 : return expr_gen.node_allocator_->template allocate_rr > >(v1,v2); + #define case_stmt(op0,op1) \ + case op0 : return expr_gen.node_allocator_-> \ + template allocate_rr > > \ + (v1,v2); \ + basic_opr_switch_statements extended_opr_switch_statements #undef case_stmt @@ -13576,7 +13650,11 @@ namespace exprtk details::free_node(*(expr_gen.node_allocator_),branch[0]); switch (operation) { - #define case_stmt(op0,op1) case op0 : return expr_gen.node_allocator_->template allocate_cr > >(c,v); + #define case_stmt(op0,op1) \ + case op0 : return expr_gen.node_allocator_-> \ + template allocate_cr > > \ + (c,v); \ + basic_opr_switch_statements extended_opr_switch_statements #undef case_stmt @@ -13600,7 +13678,11 @@ namespace exprtk } switch (operation) { - #define case_stmt(op0,op1) case op0 : return expr_gen.node_allocator_->template allocate_rc > >(v,c); + #define case_stmt(op0,op1) \ + case op0 : return expr_gen.node_allocator_-> \ + template allocate_rc > > \ + (v,c); \ + basic_opr_switch_statements extended_opr_switch_statements #undef case_stmt @@ -13618,7 +13700,10 @@ namespace exprtk { switch (sf3opr) { - #define case_stmt(op0,op1) case op0 : return details::T0oT1oT2_sf3ext >::allocate(*(expr_gen.node_allocator_),t0,t1,t2); + #define case_stmt(op0,op1) \ + case op0 : return details::T0oT1oT2_sf3ext >:: \ + allocate(*(expr_gen.node_allocator_),t0,t1,t2); \ + case_stmt(details::e_sf00,details::sf00_op) case_stmt(details::e_sf01,details::sf01_op) case_stmt(details::e_sf02,details::sf02_op) case_stmt(details::e_sf03,details::sf03_op) case_stmt(details::e_sf04,details::sf04_op) case_stmt(details::e_sf05,details::sf05_op) @@ -13663,7 +13748,10 @@ namespace exprtk { switch (sf4opr) { - #define case_stmt(op0,op1) case op0 : return details::T0oT1oT2oT3_sf4ext >::allocate(*(expr_gen.node_allocator_),t0,t1,t2,t3); + #define case_stmt(op0,op1) \ + case op0 : return details::T0oT1oT2oT3_sf4ext >:: \ + allocate(*(expr_gen.node_allocator_),t0,t1,t2,t3); \ + 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) @@ -16215,7 +16303,7 @@ namespace exprtk #ifndef exprtk_disable_string_capabilities - #define string_opr_switch_statements \ + #define string_opr_switch_statements \ case_stmt(details:: e_lt ,details:: lt_op) \ case_stmt(details:: e_lte ,details:: lte_op) \ case_stmt(details:: e_gt ,details:: gt_op) \ @@ -16231,7 +16319,11 @@ namespace exprtk { switch (opr) { - #define case_stmt(op0,op1) case op0 : return node_allocator_->allocate_ttt >,T0,T1>(s0,s1,rp0); + #define case_stmt(op0,op1) \ + case op0 : return node_allocator_-> \ + allocate_ttt >,T0,T1> \ + (s0,s1,rp0); \ + string_opr_switch_statements #undef case_stmt default : return error_node(); @@ -16243,7 +16335,11 @@ namespace exprtk { switch (opr) { - #define case_stmt(op0,op1) case op0 : return node_allocator_->allocate_ttt >,T0,T1>(s0,s1,rp1); + #define case_stmt(op0,op1) \ + case op0 : return node_allocator_-> \ + allocate_ttt >,T0,T1> \ + (s0,s1,rp1); \ + string_opr_switch_statements #undef case_stmt default : return error_node(); @@ -16255,7 +16351,11 @@ namespace exprtk { switch (opr) { - #define case_stmt(op0,op1) case op0 : return node_allocator_->allocate_tttt >,T0,T1>(s0,s1,rp0,rp1); + #define case_stmt(op0,op1) \ + case op0 : return node_allocator_-> \ + allocate_tttt >,T0,T1> \ + (s0,s1,rp0,rp1); \ + string_opr_switch_statements #undef case_stmt default : return error_node(); @@ -16267,7 +16367,10 @@ namespace exprtk { switch (opr) { - #define case_stmt(op0,op1) case op0 : return node_allocator_->allocate_tt >,T0,T1>(s0,s1); + #define case_stmt(op0,op1) \ + case op0 : return node_allocator_-> \ + allocate_tt >,T0,T1>(s0,s1); \ + string_opr_switch_statements #undef case_stmt default : return error_node(); @@ -16737,7 +16840,9 @@ namespace exprtk inline void load_unary_operations_map(unary_op_map_t& m) { - #define register_unary_op(Op,UnaryFunctor) m.insert(std::make_pair(Op,UnaryFunctor::process)); + #define register_unary_op(Op,UnaryFunctor) \ + m.insert(std::make_pair(Op,UnaryFunctor::process)); \ + register_unary_op(details:: e_abs,details:: abs_op) register_unary_op(details:: e_acos,details:: acos_op) register_unary_op(details:: e_asin,details:: asin_op) @@ -16778,7 +16883,9 @@ namespace exprtk inline void load_binary_operations_map(binary_op_map_t& m) { - #define register_binary_op(Op,BinaryFunctor) m.insert(typename binary_op_map_t::value_type(Op,BinaryFunctor::process)); + #define register_binary_op(Op,BinaryFunctor) \ + m.insert(typename binary_op_map_t::value_type(Op,BinaryFunctor::process)); \ + register_binary_op(details:: e_add,details:: add_op) register_binary_op(details:: e_sub,details:: sub_op) register_binary_op(details:: e_mul,details:: mul_op) @@ -16802,7 +16909,9 @@ namespace exprtk inline void load_inv_binary_operations_map(inv_binary_op_map_t& m) { - #define register_binary_op(Op,BinaryFunctor) m.insert(typename inv_binary_op_map_t::value_type(BinaryFunctor::process,Op)); + #define register_binary_op(Op,BinaryFunctor) \ + m.insert(typename inv_binary_op_map_t::value_type(BinaryFunctor::process,Op)); \ + register_binary_op(details:: e_add,details:: add_op) register_binary_op(details:: e_sub,details:: sub_op) register_binary_op(details:: e_mul,details:: mul_op) @@ -16827,7 +16936,10 @@ namespace exprtk inline void load_sf3_map(sf3_map_t& sf3_map) { typedef std::pair pair_t; - #define register_sf3(Op) sf3_map[details::sf##Op##_op::id()] = pair_t(details::sf##Op##_op::process,details::e_sf##Op); + + #define register_sf3(Op) \ + sf3_map[details::sf##Op##_op::id()] = pair_t(details::sf##Op##_op::process,details::e_sf##Op); \ + register_sf3(00) register_sf3(01) register_sf3(02) register_sf3(03) register_sf3(04) register_sf3(05) register_sf3(06) register_sf3(07) register_sf3(08) register_sf3(09) register_sf3(10) register_sf3(11) @@ -16842,7 +16954,10 @@ namespace exprtk inline void load_sf4_map(sf4_map_t& sf4_map) { typedef std::pair pair_t; - #define register_sf4(Op) sf4_map[details::sf##Op##_op::id()] = pair_t(details::sf##Op##_op::process,details::e_sf##Op); + + #define register_sf4(Op) \ + sf4_map[details::sf##Op##_op::id()] = pair_t(details::sf##Op##_op::process,details::e_sf##Op); \ + register_sf4(47) register_sf4(48) register_sf4(49) register_sf4(50) register_sf4(51) register_sf4(52) register_sf4(53) register_sf4(54) register_sf4(55) register_sf4(56) register_sf4(57) register_sf4(58) @@ -16854,8 +16969,9 @@ namespace exprtk register_sf4(79) register_sf4(80) register_sf4(81) register_sf4(82) #undef register_sf4 - typedef std::pair pair_t; - #define register_sf4ext(Op) sf4_map[details::sfext##Op##_op::id()] = pair_t(details::sfext##Op##_op::process,details::e_sf4ext##Op); + #define register_sf4ext(Op) \ + sf4_map[details::sfext##Op##_op::id()] = pair_t(details::sfext##Op##_op::process,details::e_sf4ext##Op); \ + register_sf4ext(00) register_sf4ext(01) register_sf4ext(02) register_sf4ext(03) register_sf4ext(04) register_sf4ext(05) register_sf4ext(06) register_sf4ext(07) register_sf4ext(08) register_sf4ext(09) register_sf4ext(10) register_sf4ext(11) diff --git a/exprtk_test.cpp b/exprtk_test.cpp index 97e510b..ce8023c 100644 --- a/exprtk_test.cpp +++ b/exprtk_test.cpp @@ -4322,20 +4322,20 @@ inline bool run_test20() int main() { - #define perform_test(Type,Number) \ - { \ - exprtk::timer timer; \ - timer.start(); \ - if (!run_test##Number()) \ - { \ - printf("run_test"#Number" ("#Type") *** FAILED! ***\n"); \ - } \ - else \ - { \ - timer.stop(); \ + #define perform_test(Type,Number) \ + { \ + exprtk::timer timer; \ + timer.start(); \ + if (!run_test##Number()) \ + { \ + printf("run_test"#Number" ("#Type") *** FAILED! ***\n"); \ + } \ + else \ + { \ + timer.stop(); \ printf("run_test"#Number" ("#Type") - Result: SUCCESS Time: %8.4fsec\n",timer.time()); \ - } \ - } \ + } \ + } \ perform_test(double,00) perform_test(double,01) diff --git a/readme.txt b/readme.txt index 9fd0706..41e7a23 100644 --- a/readme.txt +++ b/readme.txt @@ -15,10 +15,10 @@ operations, functions and processes: (0) Basic operators: +, -, *, /, %, ^ -(1) Functions: abs, avg, ceil, clamp, erf, erfc, exp, expm1, - floor, frac, inrange, log, log10, log1p, log2, - logn, max, min, root, round, roundn, sgn, sqrt, - sum, trunc +(1) Functions: abs, avg, ceil, clamp, equal, erf, erfc, exp, + expm1, floor, frac, log, log10, log1p, log2, + logn, max, min, mul, nequal, root, round, + roundn, sgn, sqrt, sum, trunc (2) Trigonometry: acos, asin, atan, atan2, cos, cosh, cot, csc, deg2grad, deg2rad, grad2deg, hypot, rad2deg, @@ -557,7 +557,14 @@ correctly optimize such expressions for a given architecture. (18) Recursive calls made from within composited functions will have a stack size bound by the stack of the executing architecture. - (19) Expressions may contain any of the following comment styles: + (19) The following are examples of floating point value represenations + that are supported: + (a) 12345 (b) -123.456 + (c) +123.456e+12 (d) 123.456E-12 + (c) +012.045e+07 (e) .1234 + (f) 123.456f (f) -321.654E+3L + + (20) Expressions may contain any of the following comment styles: 1. // .... \n 2. # .... \n 3. /* .... */