C++ Mathematical Expression Library (ExprTk) http://www.partow.net/programming/exprtk/index.html
diff --git a/exprtk.hpp b/exprtk.hpp index 544cf81..5726160 100644 --- a/exprtk.hpp +++ b/exprtk.hpp
@@ -57,7 +57,7 @@ namespace exprtk { - #if exprtk_enable_debugging + #ifdef exprtk_enable_debugging #define exprtk_debug(params) printf params #else #define exprtk_debug(params) (void)0 @@ -678,16 +678,16 @@ { namespace constant { - static const double e = 2.718281828459045235360; - static const double pi = 3.141592653589793238462; - static const double pi_2 = 1.570796326794896619231; - static const double pi_4 = 0.785398163397448309616; - static const double pi_180 = 0.017453292519943295769; - static const double _1_pi = 0.318309886183790671538; - static const double _2_pi = 0.636619772367581343076; - static const double _180_pi = 57.295779513082320876798; - static const double log2 = 0.693147180559945309417; - static const double sqrt2 = 1.414213562373095048801; + static const double e = 2.71828182845904523536028747135266249775724709369996; + static const double pi = 3.14159265358979323846264338327950288419716939937510; + static const double pi_2 = 1.57079632679489661923132169163975144209858469968755; + static const double pi_4 = 0.78539816339744830961566084581987572104929234984378; + static const double pi_180 = 0.01745329251994329576923690768488612713442871888542; + static const double _1_pi = 0.31830988618379067153776752674502872406891929148091; + static const double _2_pi = 0.63661977236758134307553505349005744813783858296183; + static const double _180_pi = 57.29577951308232087679815481410517033240547246656443; + static const double log2 = 0.69314718055994530941723212145817656807550013436026; + static const double sqrt2 = 1.41421356237309504880168872420969807856967187537695; } namespace details @@ -1760,7 +1760,7 @@ if (curr != itr) { instate = true; - d += compute_pow10(tmp_d,-std::distance(curr,itr)); + d += compute_pow10(tmp_d,static_cast<int>(-std::distance(curr,itr))); } #undef parse_digit_1 @@ -6733,9 +6733,9 @@ std::string stringvar_node<T>::null_value = std::string(""); template <typename T> - class string_range_node : public expression_node <T>, - public string_base_node<T>, - public range_interface <T> + class string_range_node : public expression_node <T>, + public string_base_node<T>, + public range_interface <T> { public: @@ -11600,7 +11600,7 @@ public: virtual ~boc_base_node() - {} + {} inline virtual operator_type operation() const { @@ -13555,6 +13555,43 @@ }; template <typename T, typename PowOp> + class bipow_node : public expression_node<T> + { + public: + + typedef expression_node<T>* expression_ptr; + typedef std::pair<expression_ptr, bool> branch_t; + typedef PowOp operation_t; + + explicit bipow_node(expression_ptr brnch) + { + init_branches<1>(branch_, brnch); + } + + ~bipow_node() + { + cleanup_branches::execute<T,1>(branch_); + } + + inline T value() const + { + return PowOp::result(branch_[0].first->value()); + } + + inline typename expression_node<T>::node_type type() const + { + return expression_node<T>::e_ipow; + } + + private: + + bipow_node(const bipow_node<T,PowOp>&); + bipow_node<T,PowOp>& operator=(const bipow_node<T,PowOp>&); + + branch_t branch_[1]; + }; + + template <typename T, typename PowOp> class ipowinv_node : public expression_node<T> { public: @@ -13584,6 +13621,43 @@ const T& v_; }; + template <typename T, typename PowOp> + class bipowninv_node : public expression_node<T> + { + public: + + typedef expression_node<T>* expression_ptr; + typedef std::pair<expression_ptr, bool> branch_t; + typedef PowOp operation_t; + + explicit bipowninv_node(expression_ptr brnch) + { + init_branches<1>(branch_, brnch); + } + + ~bipowninv_node() + { + cleanup_branches::execute<T,1>(branch_); + } + + inline T value() const + { + return (T(1) / PowOp::result(branch_[0].first->value())); + } + + inline typename expression_node<T>::node_type type() const + { + return expression_node<T>::e_ipowinv; + } + + private: + + bipowninv_node(const bipowninv_node<T,PowOp>&); + bipowninv_node<T,PowOp>& operator=(const bipowninv_node<T,PowOp>&); + + branch_t branch_[1]; + }; + template <typename T> inline bool is_vov_node(const expression_node<T>* node) { @@ -17139,7 +17213,7 @@ { st = e_usr_variable_type; default_value = T(0); - error_message = ""; + error_message.clear(); return true; } @@ -17698,7 +17772,7 @@ settings_store& disable_inequality_operation(settings_inequality_opr inequality) { if ( - (e_assign_unknown != inequality) && + (e_ineq_unknown != inequality) && (static_cast<std::size_t>(inequality) < details::inequality_ops_list_size) ) { @@ -20039,7 +20113,7 @@ return error_node(); } - // Can we optimize away the case statement? + // Can we optimise away the case statement? if (is_constant_node(condition) && is_false(condition)) { free_node(node_allocator_, condition); @@ -20183,7 +20257,7 @@ return error_node(); } - // Can we optimize away the case statement? + // Can we optimise away the case statement? if (is_constant_node(condition) && is_false(condition)) { free_node(node_allocator_, condition); @@ -23259,7 +23333,7 @@ } #endif - inline bool unary_optimizable(const details::operator_type& operation) const + inline bool unary_optimisable(const details::operator_type& operation) const { return (details::e_abs == operation) || (details::e_acos == operation) || (details::e_acosh == operation) || (details::e_asin == operation) || @@ -23283,7 +23357,7 @@ (details::e_frac == operation) || (details::e_trunc == operation); } - inline bool sf3_optimizable(const std::string& sf3id, trinary_functor_t& tfunc) + inline bool sf3_optimisable(const std::string& sf3id, trinary_functor_t& tfunc) { typename sf3_map_t::iterator itr = sf3_map_->find(sf3id); @@ -23295,7 +23369,7 @@ return true; } - inline bool sf4_optimizable(const std::string& sf4id, quaternary_functor_t& qfunc) + inline bool sf4_optimisable(const std::string& sf4id, quaternary_functor_t& qfunc) { typename sf4_map_t::iterator itr = sf4_map_->find(sf4id); @@ -23307,7 +23381,7 @@ return true; } - inline bool sf3_optimizable(const std::string& sf3id, details::operator_type& operation) + inline bool sf3_optimisable(const std::string& sf3id, details::operator_type& operation) { typename sf3_map_t::iterator itr = sf3_map_->find(sf3id); @@ -23319,7 +23393,7 @@ return true; } - inline bool sf4_optimizable(const std::string& sf4id, details::operator_type& operation) + inline bool sf4_optimisable(const std::string& sf4id, details::operator_type& operation) { typename sf4_map_t::iterator itr = sf4_map_->find(sf4id); @@ -23343,9 +23417,9 @@ return error_node(); else if (details::is_constant_node(branch[0])) return synthesize_expression<unary_node_t,1>(operation,branch); - else if (unary_optimizable(operation) && details::is_variable_node(branch[0])) + else if (unary_optimisable(operation) && details::is_variable_node(branch[0])) return synthesize_uv_expression(operation,branch); - else if (unary_optimizable(operation) && details::is_ivector_node(branch[0])) + else if (unary_optimisable(operation) && details::is_ivector_node(branch[0])) return synthesize_uvec_expression(operation,branch); else return synthesize_unary_expression(operation,branch); @@ -23413,7 +23487,7 @@ } } - inline bool operation_optimizable(const details::operator_type& operation) const + inline bool operation_optimisable(const details::operator_type& operation) const { return (details::e_add == operation) || (details::e_sub == operation) || @@ -23481,47 +23555,47 @@ return branch_to_id(branch[0]) + std::string("o") + branch_to_id(branch[1]); } - inline bool cov_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const + inline bool cov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const { - if (!operation_optimizable(operation)) + if (!operation_optimisable(operation)) return false; else return (details::is_constant_node(branch[0]) && details::is_variable_node(branch[1])); } - inline bool voc_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const + inline bool voc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const { - if (!operation_optimizable(operation)) + if (!operation_optimisable(operation)) return false; else return (details::is_variable_node(branch[0]) && details::is_constant_node(branch[1])); } - inline bool vov_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const + inline bool vov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const { - if (!operation_optimizable(operation)) + if (!operation_optimisable(operation)) return false; else return (details::is_variable_node(branch[0]) && details::is_variable_node(branch[1])); } - inline bool cob_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const + inline bool cob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const { - if (!operation_optimizable(operation)) + if (!operation_optimisable(operation)) return false; else return (details::is_constant_node(branch[0]) && !details::is_constant_node(branch[1])); } - inline bool boc_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const + inline bool boc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const { - if (!operation_optimizable(operation)) + if (!operation_optimisable(operation)) return false; else return (!details::is_constant_node(branch[0]) && details::is_constant_node(branch[1])); } - inline bool cocob_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const + inline bool cocob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const { if ( (details::e_add == operation) || @@ -23537,7 +23611,7 @@ return false; } - inline bool coboc_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const + inline bool coboc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const { if ( (details::e_add == operation) || @@ -23553,33 +23627,33 @@ return false; } - inline bool uvouv_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const + inline bool uvouv_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const { - if (!operation_optimizable(operation)) + if (!operation_optimisable(operation)) return false; else return (details::is_uv_node(branch[0]) && details::is_uv_node(branch[1])); } - inline bool vob_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const + inline bool vob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const { - if (!operation_optimizable(operation)) + if (!operation_optimisable(operation)) return false; else return (details::is_variable_node(branch[0]) && !details::is_variable_node(branch[1])); } - inline bool bov_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const + inline bool bov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const { - if (!operation_optimizable(operation)) + if (!operation_optimisable(operation)) return false; else return (!details::is_variable_node(branch[0]) && details::is_variable_node(branch[1])); } - inline bool binext_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const + inline bool binext_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const { - if (!operation_optimizable(operation)) + if (!operation_optimisable(operation)) return false; else return (!details::is_constant_node(branch[0]) || !details::is_constant_node(branch[1])); @@ -23605,6 +23679,22 @@ return false; } + inline bool is_constpow_operation(const details::operator_type& operation, expression_node_ptr(&branch)[2]) + { + if ( + !is_constant_node(branch[1]) || + is_constant_node(branch[0]) || + is_variable_node(branch[0]) || + is_vector_node (branch[0]) || + is_generally_string_node(branch[0]) + ) + return false; + + const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); + + return cardinal_pow_optimisable(operation, c); + } + inline bool is_invalid_break_continue_op(expression_node_ptr (&branch)[2]) { return ( @@ -23750,7 +23840,11 @@ else if (is_string_operation(operation,branch)) return synthesize_string_expression(operation,branch); else if (is_null_present(branch)) - return synthesize_null_expression(operation,branch); + return synthesize_null_expression(operation, branch); + #ifndef exprtk_disable_cardinal_pow_optimisation + else if (is_constpow_operation(operation, branch)) + return cardinal_pow_optimisation(branch); + #endif expression_node_ptr result = error_node(); @@ -23770,30 +23864,30 @@ */ result = error_node(); - if (cocob_optimizable(operation,branch)) + if (cocob_optimisable(operation,branch)) result = synthesize_cocob_expression::process(*this,operation,branch); - else if (coboc_optimizable(operation,branch) && (0 == result)) + else if (coboc_optimisable(operation,branch) && (0 == result)) result = synthesize_coboc_expression::process(*this,operation,branch); if (result) return result; } - if (uvouv_optimizable(operation,branch)) + if (uvouv_optimisable(operation,branch)) return synthesize_uvouv_expression(operation,branch); - else if (vob_optimizable(operation,branch)) + else if (vob_optimisable(operation,branch)) return synthesize_vob_expression::process(*this,operation,branch); - else if (bov_optimizable(operation,branch)) + else if (bov_optimisable(operation,branch)) return synthesize_bov_expression::process(*this,operation,branch); - else if (cob_optimizable(operation,branch)) + else if (cob_optimisable(operation,branch)) return synthesize_cob_expression::process(*this,operation,branch); - else if (boc_optimizable(operation,branch)) + else if (boc_optimisable(operation,branch)) return synthesize_boc_expression::process(*this,operation,branch); #ifndef exprtk_disable_enhanced_features - else if (cov_optimizable(operation,branch)) + else if (cov_optimisable(operation,branch)) return synthesize_cov_expression::process(*this,operation,branch); #endif - else if (binext_optimizable(operation,branch)) + else if (binext_optimisable(operation,branch)) return synthesize_binary_ext_expression::process(*this,operation,branch); else return synthesize_expression<binary_node_t,2>(operation,branch); @@ -23853,7 +23947,7 @@ return error_node(); } - // Can the condition be immediately evaluated? if so optimize. + // Can the condition be immediately evaluated? if so optimise. else if (details::is_constant_node(condition)) { // True branch @@ -23899,7 +23993,7 @@ return error_node(); } - // Can the condition be immediately evaluated? if so optimize. + // Can the condition be immediately evaluated? if so optimise. else if (details::is_constant_node(condition)) { // True branch @@ -23930,9 +24024,9 @@ return error_node(); } #else - inline expression_node_ptr conditional_string(expression_node_ptr , - expression_node_ptr , - expression_node_ptr ) const + inline expression_node_ptr conditional_string(expression_node_ptr, + expression_node_ptr, + expression_node_ptr) const { return error_node(); } @@ -24055,7 +24149,7 @@ template <typename Allocator, template <typename,typename> class Sequence> - inline expression_node_ptr const_optimize_switch(Sequence<expression_node_ptr,Allocator>& arg_list) + inline expression_node_ptr const_optimise_switch(Sequence<expression_node_ptr,Allocator>& arg_list) { expression_node_ptr result = error_node(); @@ -24091,7 +24185,7 @@ template <typename Allocator, template <typename,typename> class Sequence> - inline expression_node_ptr const_optimize_mswitch(Sequence<expression_node_ptr,Allocator>& arg_list) + inline expression_node_ptr const_optimise_mswitch(Sequence<expression_node_ptr,Allocator>& arg_list) { expression_node_ptr result = error_node(); @@ -24224,7 +24318,7 @@ return error_node(); } else if (is_constant_foldable(arg_list)) - return const_optimize_switch(arg_list); + return const_optimise_switch(arg_list); switch ((arg_list.size() - 1) / 2) { @@ -24258,7 +24352,7 @@ return error_node(); } else if (is_constant_foldable(arg_list)) - return const_optimize_mswitch(arg_list); + return const_optimise_mswitch(arg_list); else return node_allocator_->allocate<details::multi_switch_node<Type> >(arg_list); } @@ -24353,7 +24447,7 @@ } } - inline expression_node_ptr const_optimize_sf3(const details::operator_type& operation, + inline expression_node_ptr const_optimise_sf3(const details::operator_type& operation, expression_node_ptr (&branch)[3]) { expression_node_ptr temp_node = error_node(); @@ -24401,7 +24495,7 @@ return node_allocator_->allocate<literal_node_t>(v); } - inline expression_node_ptr varnode_optimize_sf3(const details::operator_type& operation, expression_node_ptr (&branch)[3]) + inline expression_node_ptr varnode_optimise_sf3(const details::operator_type& operation, expression_node_ptr (&branch)[3]) { typedef details::variable_node<Type>* variable_ptr; @@ -24450,9 +24544,9 @@ if (!all_nodes_valid(branch)) return error_node(); else if (is_constant_foldable(branch)) - return const_optimize_sf3(operation,branch); + return const_optimise_sf3(operation,branch); else if (all_nodes_variables(branch)) - return varnode_optimize_sf3(operation,branch); + return varnode_optimise_sf3(operation,branch); else { switch (operation) @@ -24491,7 +24585,7 @@ } } - inline expression_node_ptr const_optimize_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4]) + inline expression_node_ptr const_optimise_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4]) { expression_node_ptr temp_node = error_node(); @@ -24538,7 +24632,7 @@ return node_allocator_->allocate<literal_node_t>(v); } - inline expression_node_ptr varnode_optimize_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4]) + inline expression_node_ptr varnode_optimise_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4]) { typedef details::variable_node<Type>* variable_ptr; @@ -24589,9 +24683,9 @@ if (!all_nodes_valid(branch)) return error_node(); else if (is_constant_foldable(branch)) - return const_optimize_sf4(operation,branch); + return const_optimise_sf4(operation,branch); else if (all_nodes_variables(branch)) - return varnode_optimize_sf4(operation,branch); + return varnode_optimise_sf4(operation,branch); switch (operation) { #define case_stmt(op0,op1) \ @@ -24631,7 +24725,7 @@ template <typename Allocator, template <typename,typename> class Sequence> - inline expression_node_ptr const_optimize_varargfunc(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list) + inline expression_node_ptr const_optimise_varargfunc(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list) { expression_node_ptr temp_node = error_node(); @@ -24674,7 +24768,7 @@ template <typename Allocator, template <typename,typename> class Sequence> - inline expression_node_ptr varnode_optimize_varargfunc(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list) + inline expression_node_ptr varnode_optimise_varargfunc(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list) { switch (operation) { @@ -24731,13 +24825,13 @@ return error_node(); } else if (is_constant_foldable(arg_list)) - return const_optimize_varargfunc(operation,arg_list); + return const_optimise_varargfunc(operation,arg_list); else if ((arg_list.size() == 1) && details::is_ivector_node(arg_list[0])) return vectorize_func(operation,arg_list); else if ((arg_list.size() == 1) && special_one_parameter_vararg(operation)) return arg_list[0]; else if (all_nodes_variables(arg_list)) - return varnode_optimize_varargfunc(operation,arg_list); + return varnode_optimise_varargfunc(operation,arg_list); switch (operation) { @@ -24768,7 +24862,7 @@ return error_node(); else { - // Can the function call be completely optimized? + // Can the function call be completely optimised? if (details::is_constant_node(result)) return result; else if (!all_nodes_valid(b)) @@ -25519,8 +25613,8 @@ case_stmt(details::e_xnor,details::xnor_op) \ #ifndef exprtk_disable_cardinal_pow_optimisation - template <template <typename,typename> class IPowNode> - inline expression_node_ptr cardinal_pow_optimization_impl(const T& v, const unsigned int& p) + template <typename TType, template <typename,typename> class IPowNode> + inline expression_node_ptr cardinal_pow_optimisation_impl(const TType& v, const unsigned int& p) { switch (p) { @@ -25548,7 +25642,7 @@ } } - inline expression_node_ptr cardinal_pow_optimization(const T& v, const T& c) + inline expression_node_ptr cardinal_pow_optimisation(const T& v, const T& c) { const bool not_recipricol = (c >= T(0)); const int p = details::numeric::to_int32(details::numeric::abs(c)); @@ -25563,26 +25657,50 @@ else { if (not_recipricol) - return cardinal_pow_optimization_impl<details::ipow_node>(v,p); + return cardinal_pow_optimisation_impl<T,details::ipow_node>(v,p); else - return cardinal_pow_optimization_impl<details::ipowinv_node>(v,p); + return cardinal_pow_optimisation_impl<T,details::ipowinv_node>(v,p); } } - inline bool cardinal_pow_optimizable(const details::operator_type& operation, const T& c) + inline bool cardinal_pow_optimisable(const details::operator_type& operation, const T& c) { return (details::e_pow == operation) && (details::numeric::abs(c) <= T(60)) && details::numeric::is_integer(c); } + + inline expression_node_ptr cardinal_pow_optimisation(expression_node_ptr (&branch)[2]) + { + const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); + const bool not_recipricol = (c >= T(0)); + const int p = details::numeric::to_int32(details::numeric::abs(c)); + + node_allocator_->free(branch[1]); + + if (0 == p) + { + details::free_all_nodes(*node_allocator_, branch); + return node_allocator_->allocate_c<literal_node_t>(T(1)); + } + else if (not_recipricol) + return cardinal_pow_optimisation_impl<expression_node_ptr,details::bipow_node>(branch[0],p); + else + return cardinal_pow_optimisation_impl<expression_node_ptr,details::bipowninv_node>(branch[0],p); + } #else - inline expression_node_ptr cardinal_pow_optimization(T&, const T&) + inline expression_node_ptr cardinal_pow_optimisation(T&, const T&) { return error_node(); } - inline bool cardinal_pow_optimizable(const details::operator_type&, const T&) + inline bool cardinal_pow_optimisable(const details::operator_type&, const T&) { return false; } + + inline expression_node_ptr cardinal_pow_optimisation(expression_node_ptr(&)[2]) + { + return error_node(); + } #endif struct synthesize_binary_ext_expression @@ -26092,6 +26210,18 @@ return bocnode; } } + else if (operation == details::e_pow) + { + // (v ^ c0) ^ c1 --> v ^(c0 * c1) + details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]); + details::operator_type boc_opr = bocnode->operation(); + + if (details::e_pow == boc_opr) + { + bocnode->set_c(bocnode->c() * c); + return bocnode; + } + } } #ifndef exprtk_disable_enhanced_features @@ -26471,7 +26601,7 @@ { result = error_node(); - if (!operation_optimizable(operation)) + if (!operation_optimisable(operation)) return false; const std::string node_id = branch_to_id(branch); @@ -26557,12 +26687,12 @@ details::free_node(*(expr_gen.node_allocator_),branch[1]); - if (expr_gen.cardinal_pow_optimizable(operation,c)) + if (expr_gen.cardinal_pow_optimisable(operation,c)) { if (std::equal_to<T>()(T(1),c)) return branch[0]; else - return expr_gen.cardinal_pow_optimization(v,c); + return expr_gen.cardinal_pow_optimisation(v,c); } else if ((T(0) == c) && (details::e_mul == operation)) return expr_gen(T(0)); @@ -26631,7 +26761,7 @@ { details::operator_type sf3opr; - if (!expr_gen.sf3_optimizable(id,sf3opr)) + if (!expr_gen.sf3_optimisable(id,sf3opr)) return false; else result = synthesize_sf3ext_expression::template process<T0,T1,T2>(expr_gen,sf3opr,t0,t1,t2); @@ -26715,7 +26845,7 @@ { details::operator_type sf4opr; - if (!expr_gen.sf4_optimizable(id,sf4opr)) + if (!expr_gen.sf4_optimisable(id,sf4opr)) return false; else result = synthesize_sf4ext_expression::template process<T0,T1,T2,T3>(expr_gen,sf4opr,t0,t1,t2,t3); @@ -27731,6 +27861,14 @@ return expr_gen.node_allocator_-> template allocate_rc<typename details::voc_node<Type,details::div_op<Type> > >(v,c0 * c1); } + // (v ^ c0) ^ c1 --> (voc) v ^ (c0 * c1) + else if ((details::e_pow == o0) && (details::e_pow == o1)) + { + exprtk_debug(("(v ^ c0) ^ c1 --> (voc) v ^ (c0 * c1)\n")); + + return expr_gen.node_allocator_-> + template allocate_rc<typename details::voc_node<Type,details::pow_op<Type> > >(v,c0 * c1); + } } if (synthesize_sf3ext_expression::template compile<vtype,ctype,ctype>(expr_gen,id(expr_gen,o0,o1),v,c0,c1,result)) @@ -31508,7 +31646,7 @@ } else if ((details::e_default != operation)) { - // Attempt simple constant folding optimization. + // Attempt simple constant folding optimisation. expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(operation,branch); if (is_constant_foldable<N>(branch)) @@ -31537,7 +31675,7 @@ typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t; - // Attempt simple constant folding optimization. + // Attempt simple constant folding optimisation. expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(f); function_N_node_t* func_node_ptr = dynamic_cast<function_N_node_t*>(expression_point);
diff --git a/exprtk_test.cpp b/exprtk_test.cpp index e5f7b32..0826c1e 100644 --- a/exprtk_test.cpp +++ b/exprtk_test.cpp
@@ -2348,8 +2348,8 @@ if (!parser.compile(test.expr, expression)) { printf("run_test02() - Error: %s Expression: %s\n", - parser.error().c_str(), - test.expr.c_str()); + parser.error().c_str(), + test.expr.c_str()); result = false; continue; @@ -2365,13 +2365,13 @@ if (not_equal(expr_result, test.result)) { printf("run_test02() - Computation Error: Expression: [%s]\tExpected: %19.15f\tResult: %19.15f\t" - "a='%s'\tb='%s'\tc='%s'\n", - test.expr.c_str(), - (double)test.result, - (double)expr_result, - str_a.c_str(), - str_b.c_str(), - str_c.c_str()); + "a='%s'\tb='%s'\tc='%s'\n", + test.expr.c_str(), + (double)test.result, + (double)expr_result, + str_a.c_str(), + str_b.c_str(), + str_c.c_str()); result = false; continue; @@ -6325,11 +6325,13 @@ 104683, 104693, 104701, 104707, 104711, 104717, 104723, 104729, 1000621, 1000639, 1000651, 1000667, 1000669, 1001023, 1001027, 1001041 }; + const std::size_t prime_list_size = sizeof(prime_list) / sizeof(std::size_t); for (std::size_t i = 0; (i < prime_list_size) && (!failure); ++i) { - x = prime_list[i]; + x = static_cast<T>(prime_list[i]); + std::vector<T> result(expression_count,T(0)); for (std::size_t j = 0; j < expression_list.size(); ++j) @@ -6467,6 +6469,7 @@ "x")); symbol_table_t& symbol_table = compositor.symbol_table(); + symbol_table.add_constants(); symbol_table.add_variable("x",x); @@ -6515,11 +6518,13 @@ 46368, 75025, 121393, 196418, 317811, 514229, 832040, 1346269 }; + const std::size_t fibonacci_list_size = sizeof(fibonacci_list) / sizeof(std::size_t); for (std::size_t i = 0; (i < fibonacci_list_size) && (!failure); ++i) { - x = i; + x = static_cast<T>(i); + std::vector<T> result(expression_count,T(0)); for (std::size_t j = 0; j < expression_list.size(); ++j) @@ -6629,7 +6634,8 @@ for (std::size_t i = 0; i < 100; ++i) { - x = i; + x = static_cast<T>(i); + T result = expression.value(); if (not_equal(result,std::sqrt(x),T(0.0000001))) @@ -6757,7 +6763,9 @@ for (std::size_t i = 0; i < 100; ++i) { x = T(i); + sum += x; + T result = expression.value(); if (result != sum) @@ -6847,7 +6855,7 @@ { st = usr_t::e_usr_variable_type; default_value = next_value(); - error_message = ""; + error_message.clear(); return true; } @@ -6855,7 +6863,7 @@ { st = usr_t::e_usr_constant_type; default_value = next_value(); - error_message = ""; + error_message.clear(); return true; }
diff --git a/readme.txt b/readme.txt index ce2c8d1..845b689 100644 --- a/readme.txt +++ b/readme.txt
@@ -7,7 +7,7 @@ engine supports numerous forms of functional and logic processing semantics and is easily extendible. - + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [01 - CAPABILITIES] The ExprTk expression evaluator supports the following fundamental @@ -49,7 +49,7 @@ (11) Calculus: numerical integration and differentiation - + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [02 - EXAMPLE EXPRESSIONS] The following is a short listing of the types of mathematical @@ -76,7 +76,7 @@ (19) ((x + 'abc') like '*123*') or ('a123b' ilike y) (20) sgn(+1.2^3.4z / -5.6y) <= {-7.8^9 / -10.11x } - + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [03 - COPYRIGHT NOTICE] Free use of the C++ Mathematical Expression Toolkit Library is @@ -85,7 +85,7 @@ http://www.opensource.org/licenses/cpl1.0.php - + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [04 - DOWNLOADS & UPDATES] The most recent version of the C++ Mathematical Expression Toolkit @@ -95,13 +95,13 @@ (a) Download: http://www.partow.net/programming/exprtk/index.html (b) Repository: https://github.com/ArashPartow/exprtk - + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [05 - INSTALLATION] The header file exprtk.hpp should be placed in a project or system include path (e.g: /usr/include/). - + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [06 - COMPILATION] (a) For a complete build: make clean all @@ -109,7 +109,7 @@ (c) To strip executables: make strip_bin (d) Execute valgrind check: make valgrind_check - + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [07 - COMPILER COMPATIBILITY] ExprTk has been built error and warning free using the following set @@ -120,11 +120,10 @@ (*) Clang/LLVM (1.1+) (*) PGI C++ (10.x+) (*) Microsoft Visual Studio C++ Compiler (8.1+) - (*) Comeau C++ Compiler (4.3+) (*) IBM XL C/C++ (9.x+) (*) C++ Builder (XE4+) - + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [08 - BUILT-IN OPERATIONS & FUNCTIONS] @@ -604,7 +603,7 @@ 5. A string 6. An expression comprised of [1], [2] or [3] (eg: 2 + x / vec[3]) - + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [09 - Fundamental Types] ExprTk supports three fundamental types which can be used freely in @@ -635,7 +634,7 @@ manipulated via sub-ranges using the range definition syntax. Strings however can not interact with scalar or vector types. - + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [10 - COMPONENTS] There are three primary components, that are specialized upon a given @@ -794,7 +793,7 @@ (3) Parser -A structure which takes as input a string representation of an +A component which takes as input a string representation of an expression and attempts to compile said input with the result being an instance of Expression. If an error is encountered during the compilation process, the parser will stop compiling and return an @@ -802,7 +801,7 @@ and its location within the input provided by the 'get_error' interface. - + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [11 - COMPILATION OPTIONS] The exprtk::parser when being instantiated takes as input a set of @@ -937,7 +936,7 @@ to turn off strength reduction optimisations or to use a type with a larger numerical bound. - + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [12 - SPECIAL FUNCTIONS] The purpose of special functions in ExprTk is to provide compiler @@ -1008,7 +1007,7 @@ $f98(x,y,z,w) | (x == y) ? z : w $f99(x,y,z,w) | x*sin(y)+z*cos(w) - + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [13 - VARIABLE , VECTOR & STRING DEFINITION] ExprTk supports the definition of expression local variables, vectors @@ -1127,7 +1126,7 @@ (e) Symbol table functions (f) Unknown symbol resolver based variables - + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [14 - VECTOR PROCESSING] ExprTk provides support for various forms of vector oriented @@ -1203,7 +1202,7 @@ min(1 / x) == (1 / 3) max(x / 2) == (3 / 2) - + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [15 - USER DEFINED FUNCTIONS] ExprTk provides a means whereby custom functions can be defined and @@ -1310,6 +1309,7 @@ { ... } + return T(0); } }; @@ -1735,7 +1735,7 @@ { ... } }; - + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [16 - EXPRESSION DEPENDENTS] Any expression that is not a literal (aka constant) will have @@ -1881,7 +1881,7 @@ Note: The assignments will only consist of variable types and as such will not contain symbols denoting functions. - + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [17 - ENABLING AND DISABLING FEATURES] The parser can be configured via its settings instance to either allow @@ -2239,7 +2239,7 @@ Normally if a user specified symbol name conflicts with any of the ExprTk reserved words, the add_function call will fail. - + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [18 - EXPRESSION RETURN VALUES] ExprTk expressions can return immediately from any point by utilizing @@ -2291,7 +2291,7 @@ typedef typename type_t::vector_view vector_t; typedef typename type_t::string_view string_t; - const results_context_t& result = expression.results(); + const results_context_t& results = expression.results(); for (std::size_t i = 0; i < results.count(); ++i) { @@ -2313,10 +2313,10 @@ } -Note: Processing of the return results is very similar to that of the +Note: Processing of the return results is similar to that of the generic function call parameters. - + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [19 - COMPILATION ERRORS] When attempting to compile a malformed or otherwise erroneous ExprTk @@ -2426,7 +2426,7 @@ functions, to being unable to create new variables in the symbol_table via the 'unknown symbol resolver' mechanism. - + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [20 - EXPRTK NOTES] The following is a list of facts and suggestions one may want to take @@ -2604,7 +2604,7 @@ (x + y) / (x - y); } - + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [21 - SIMPLE EXPRTK EXAMPLE] --- snip --- @@ -2692,7 +2692,7 @@ } --- snip --- - + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [22 - BUILD OPTIONS] When building ExprTk there are a number of defines that will enable or @@ -2738,7 +2738,7 @@ expression that contains a string or string related syntax will result in a compilation failure. - + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [23 - FILES] The source distribution of ExprTk is comprised of the following set of @@ -2766,7 +2766,7 @@ (19) exprtk_simple_example_15.cpp (20) exprtk_simple_example_16.cpp - + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [24 - LANGUAGE STRUCTURE] +-------------------------------------------------------------+