From 6431bf3b0e951d766e8ad134a17cd091d1d2614d Mon Sep 17 00:00:00 2001 From: Arash Partow Date: Tue, 5 Mar 2013 00:21:28 +1100 Subject: [PATCH] C++ Mathematical Expression Library (ExprTk) http://www.partow.net/programming/exprtk/index.html --- Makefile | 2 +- exprtk.hpp | 6811 +++++++++++++++++++++++++++++++----------- exprtk_benchmark.cpp | 329 +- exprtk_test.cpp | 526 ++-- readme.txt | 180 +- 5 files changed, 5510 insertions(+), 2338 deletions(-) diff --git a/Makefile b/Makefile index 96a474f..03d8c68 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ # ************************************************************** # * C++ Mathematical Expression Toolkit Library * # * * -# * Author: Arash Partow (1999-2012) * +# * Author: Arash Partow (1999-2013) * # * URL: http://www.partow.net/programming/exprtk/index.html * # * * # * Copyright notice: * diff --git a/exprtk.hpp b/exprtk.hpp index 5cba84f..21c470a 100644 --- a/exprtk.hpp +++ b/exprtk.hpp @@ -1,6 +1,6 @@ /* **************************************************************** - * C++ Mathematical Expression Toolkit Library * + * C++ Mathematical Expression Toolkit Library * * * * Author: Arash Partow (1999-2013) * * URL: http://www.partow.net/programming/exprtk/index.html * @@ -45,27 +45,7 @@ #include #include #include - - -#ifndef exprtk_enable_all_optimizations -# define exprtk_lean_and_mean -# ifdef exprtk_lean_and_mean_numeric_only -# ifndef exprtk_lean_and_mean -# define exprtk_lean_and_mean -# endif -# ifndef exprtk_disable_string_capabilities -# define exprtk_disable_string_capabilities -# endif -# endif -# ifdef exprtk_lean_and_mean -# ifndef exprtk_disable_extended_operator_optimizations -# define exprtk_disable_extended_operator_optimizations -# endif -# ifndef exprtk_disable_extended_optimisations -# define exprtk_disable_extended_optimisations -# endif -# endif -#endif +#include namespace exprtk @@ -190,12 +170,46 @@ namespace exprtk return result; } + class build_string + { + public: + + build_string(const std::size_t& initial_size = 64) + { + data_.reserve(initial_size); + } + + inline build_string& operator << (const std::string& s) + { + data_ += s; + return (*this); + } + + inline operator std::string () const + { + return data_; + } + + inline std::string as_string() const + { + return data_; + } + + inline operator const char* () const + { + return data_.data(); + } + + private: + + std::string data_; + }; + struct ilesscompare { inline bool operator()(const std::string& s1, const std::string& s2) const { const std::size_t length = std::min(s1.size(),s2.size()); - for (std::size_t i = 0; i < length; ++i) { if (std::tolower(s1[i]) > std::tolower(s2[i])) @@ -203,7 +217,6 @@ namespace exprtk else if (std::tolower(s1[i]) < std::tolower(s2[i])) return true; } - return s1.size() < s2.size(); } }; @@ -238,7 +251,6 @@ namespace exprtk return true; } } - return false; } @@ -251,7 +263,6 @@ namespace exprtk return true; } } - return false; } @@ -267,20 +278,16 @@ namespace exprtk const typename std::iterator_traits::value_type& zero_or_one) { if (0 == std::distance(data_begin,data_end)) return false; - Iterator d_itr = data_begin; Iterator p_itr = pattern_begin; Iterator c_itr = data_begin; Iterator m_itr = data_begin; - while ((data_end != d_itr) && (zero_or_more != (*p_itr))) { - if ((!Compare::cmp((*p_itr),(*d_itr))) && (zero_or_one != (*p_itr))) { return false; } - ++p_itr; ++d_itr; } @@ -293,7 +300,6 @@ namespace exprtk { return true; } - m_itr = p_itr; c_itr = d_itr; ++c_itr; @@ -309,9 +315,7 @@ namespace exprtk d_itr = c_itr++; } } - while ((p_itr != pattern_end) && (zero_or_more == (*p_itr))) ++p_itr; - return (p_itr == pattern_end); } @@ -400,141 +404,153 @@ namespace exprtk #undef exprtk_register_int_type_tag template - inline T equal_impl(const T& v0, const T& v1, real_type_tag) + inline T equal_impl(const T v0, const T v1, real_type_tag) { static const T epsilon = T(0.00000000001); return (std::abs(v0 - v1) <= (std::max(T(1),std::max(std::abs(v0),std::abs(v1))) * epsilon)) ? T(1) : T(0); } + inline float equal_impl(const float v0, const float v1, real_type_tag) + { + static const float epsilon = float(0.000001f); + return (std::abs(v0 - v1) <= (std::max(1.0f,std::max(std::abs(v0),std::abs(v1))) * epsilon)) ? 1.0f : 0.0f; + } + template - inline T equal_impl(const T& v0, const T& v1, int_type_tag) + inline T equal_impl(const T v0, const T v1, int_type_tag) { return (v0 == v1) ? 1 : 0; } template - inline T nequal_impl(const T& v0, const T& v1, real_type_tag) + inline T nequal_impl(const T v0, const T v1, real_type_tag) { static const T epsilon = T(0.0000000001); return (std::abs(v0 - v1) > (std::max(T(1),std::max(std::abs(v0),std::abs(v1))) * epsilon)) ? T(1) : T(0); } + inline float nequal_impl(const float v0, const float v1, real_type_tag) + { + static const float epsilon = float(0.000001f); + return (std::abs(v0 - v1) > (std::max(1.0f,std::max(std::abs(v0),std::abs(v1))) * epsilon)) ? 1.0f : 0.0f; + } + template - inline T nequal_impl(const T& v0, const T& v1, int_type_tag) + inline T nequal_impl(const T v0, const T v1, int_type_tag) { return (v0 != v1) ? 1 : 0; } template - inline T modulus_impl(const T& v0, const T& v1, real_type_tag) + inline T modulus_impl(const T v0, const T v1, real_type_tag) { return std::fmod(v0,v1); } template - inline T modulus_impl(const T& v0, const T& v1, int_type_tag) + inline T modulus_impl(const T v0, const T v1, int_type_tag) { return v0 % v1; } template - inline T pow_impl(const T& v0, const T& v1, real_type_tag) + inline T pow_impl(const T v0, const T v1, real_type_tag) { return std::pow(v0,v1); } template - inline T pow_impl(const T& v0, const T& v1, int_type_tag) + inline T pow_impl(const T v0, const T v1, int_type_tag) { return std::pow(static_cast(v0),static_cast(v1)); } template - inline T logn_impl(const T& v0, const T& v1, real_type_tag) + inline T logn_impl(const T v0, const T v1, real_type_tag) { return std::log(v0) / std::log(v1); } template - inline T logn_impl(const T& v0, const T& v1, int_type_tag) + inline T logn_impl(const T v0, const T v1, int_type_tag) { return static_cast(logn_impl(static_cast(v0),static_cast(v1),real_type_tag())); } template - inline T root_impl(const T& v0, const T& v1, real_type_tag) + inline T root_impl(const T v0, const T v1, real_type_tag) { return std::pow(v0,T(1)/v1); } template - inline T root_impl(const T& v0, const T& v1, int_type_tag) + inline T root_impl(const T v0, const T v1, int_type_tag) { return root_impl(static_cast(v0),static_cast(v1),real_type_tag()); } template - inline T roundn_impl(const T& v0, const T& v1, real_type_tag) + inline T roundn_impl(const T v0, const T v1, real_type_tag) { return T(std::floor((v0 * pow10[(int)std::floor(v1)]) + T(0.5)) / T(pow10[(int)std::floor(v1)])); } template - inline T roundn_impl(const T& v0, const T&, int_type_tag) + inline T roundn_impl(const T v0, const T, int_type_tag) { return v0; } template - inline T hyp_impl(const T& v0, const T& v1, real_type_tag) + inline T hyp_impl(const T v0, const T v1, real_type_tag) { return std::sqrt((v0 * v0) + (v1 * v1)); } template - inline T hyp_impl(const T& v0, const T& v1, int_type_tag) + inline T hyp_impl(const T v0, const T v1, int_type_tag) { return static_cast(std::sqrt(static_cast((v0 * v0) + (v1 * v1)))); } template - inline T atan2_impl(const T& v0, const T& v1, real_type_tag) + inline T atan2_impl(const T v0, const T v1, real_type_tag) { return std::atan2(v0,v1); } template - inline T atan2_impl(const T&, const T&, int_type_tag) + inline T atan2_impl(const T, const T, int_type_tag) { return 0; } template - inline T shr_impl(const T& v0, const T& v1, real_type_tag) + inline T shr_impl(const T v0, const T v1, real_type_tag) { return v0 * (T(1) / std::pow(T(2),static_cast(static_cast(v1)))); } template - inline T shr_impl(const T& v0, const T& v1, int_type_tag) + inline T shr_impl(const T v0, const T v1, int_type_tag) { return v0 >> v1; } template - inline T shl_impl(const T& v0, const T& v1, real_type_tag) + inline T shl_impl(const T v0, const T v1, real_type_tag) { return v0 * std::pow(T(2),static_cast(static_cast(v1))); } template - inline T shl_impl(const T& v0, const T& v1, int_type_tag) + inline T shl_impl(const T v0, const T v1, int_type_tag) { return v0 << v1; } template - inline T sgn_impl(const T& v, real_type_tag) + inline T sgn_impl(const T v, real_type_tag) { if (v > T(0.0)) return T(+1.0); else if (v < T(0.0)) return T(-1.0); @@ -542,7 +558,7 @@ namespace exprtk } template - inline T sgn_impl(const T& v, int_type_tag) + inline T sgn_impl(const T v, int_type_tag) { if (v > T(0)) return T(+1); else if (v < T(0)) return T(-1); @@ -550,13 +566,13 @@ namespace exprtk } template - inline T xor_impl(const T& v0, const T& v1, real_type_tag) + inline T xor_impl(const T v0, const T& v1, real_type_tag) { return v0 != v1; } template - inline T xor_impl(const T& v0, const T& v1, int_type_tag) + inline T xor_impl(const T v0, const T& v1, int_type_tag) { return v0 ^ v1; } @@ -652,7 +668,7 @@ namespace exprtk 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 frac_impl(const T v, int_type_tag) { return T(0); } + template inline T frac_impl(const T , int_type_tag) { return T(0); } template inline T trunc_impl(const T v, int_type_tag) { return 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(); } @@ -888,7 +904,6 @@ namespace exprtk return_result = false; break; } - if ((++digit_count) <= numeric::numeric_info::bound_length) { t *= 10; @@ -899,9 +914,7 @@ namespace exprtk typedef unsigned long long int base_type; static const base_type max_limit = +std::numeric_limits::max(); static const base_type min_limit = -std::numeric_limits::min(); - base_type tmp = static_cast(t) * 10 + digit; - if (negative && static_cast(tmp) > min_limit) return_result = false; else if (static_cast(tmp) > max_limit) @@ -910,9 +923,7 @@ namespace exprtk } ++itr; } - result = static_cast((negative) ? -t : t); - return return_result; } @@ -921,10 +932,8 @@ namespace exprtk { typedef typename std::iterator_traits::value_type type; static const std::size_t nan_length = 3; - if (std::distance(itr,end) != static_cast(nan_length)) return false; - if (static_cast('n') == (*itr)) { if ((static_cast('a') != *(itr + 1)) || (static_cast('n') != *(itr + 2))) @@ -936,9 +945,7 @@ namespace exprtk { return false; } - t = std::numeric_limits::quiet_NaN(); - return true; } @@ -949,12 +956,9 @@ namespace exprtk static const char inf_lc[] = "infinity"; static const std::size_t inf_length = 8; const std::size_t length = std::distance(itr,end); - if ((3 != length) && (inf_length != length)) return false; - const char* inf_itr = ('i' == (*itr)) ? inf_lc : inf_uc; - while (end != itr) { if (*inf_itr == static_cast(*itr)) @@ -966,12 +970,10 @@ namespace exprtk else return false; } - if (negative) t = -std::numeric_limits::infinity(); else t = std::numeric_limits::infinity(); - return true; } @@ -1039,7 +1041,6 @@ namespace exprtk } #undef parse_digit_1 #undef parse_digit_2 - if (curr != itr) instate = true; pre_decimal = static_cast(std::distance(post_zero_cull_itr,itr)); } @@ -1073,7 +1074,6 @@ namespace exprtk } #undef parse_digit_1 #undef parse_digit_2 - if (curr != itr) instate = true; exponent -= static_cast(std::distance(curr,itr)); } @@ -1099,7 +1099,6 @@ namespace exprtk (numeric::numeric_info::max_exp < exp) ) return false; - exponent += exp; } @@ -1132,12 +1131,11 @@ namespace exprtk if ((end != itr) || (!instate)) return false; - if (0 != exponent) { if ( - (std::numeric_limits::max_exponent10 < (exponent + pre_decimal)) || - (std::numeric_limits::min_exponent10 > (exponent + pre_decimal)) + (std::numeric_limits::max_exponent10 < (exponent + pre_decimal)) || + (std::numeric_limits::min_exponent10 > (exponent + pre_decimal)) ) { return false; @@ -1194,9 +1192,7 @@ namespace exprtk d *= std::pow(10.0, 1.0 * exponent); } } - t = static_cast((negative) ? -d : d); - return true; } @@ -1208,11 +1204,27 @@ namespace exprtk return string_to_real(begin,end,t); } + template + struct functor_t + { + /* + Note: The following definitions for Type, may require tweaking + based on the compiler and target architecture. The benchmark + should provide enough information to make the right choice. + */ + //typedef T Type + //typedef const T Type + typedef const T& Type; + typedef T (*qfunc_t)(Type t0, Type t1, Type t2, Type t3); + typedef T (*tfunc_t)(Type t0, Type t1, Type t2); + typedef T (*bfunc_t)(Type t0, Type t1); + typedef T (*ufunc_t)(Type t0); + }; + } // namespace details namespace lexer { - struct token { @@ -1271,10 +1283,8 @@ namespace exprtk { type = tt; value.assign(begin,end); - if (base_begin) position = std::distance(base_begin,begin); - return *this; } @@ -1283,10 +1293,8 @@ namespace exprtk { type = e_symbol; value.assign(begin,end); - if (base_begin) position = std::distance(base_begin,begin); - return *this; } @@ -1295,10 +1303,8 @@ namespace exprtk { type = e_number; value.assign(begin,end); - if (base_begin) position = std::distance(base_begin,begin); - return *this; } @@ -1307,10 +1313,8 @@ namespace exprtk { type = e_string; value.assign(begin,end); - if (base_begin) position = std::distance(base_begin,begin); - return *this; } @@ -1329,12 +1333,9 @@ namespace exprtk } else type = e_error; - value.assign(begin,end); - if (base_begin) position = std::distance(base_begin,begin); - return *this; } @@ -1427,7 +1428,6 @@ namespace exprtk s_end_ = str.data() + str.size(); eof_token_.set_operator(token_t::e_eof,s_end_,s_end_,base_itr_); token_list_.clear(); - while (s_end_ != s_itr_) { scan_token(); @@ -1436,7 +1436,6 @@ namespace exprtk return false; } } - return true; } @@ -1500,7 +1499,6 @@ namespace exprtk inline void scan_token() { skip_whitespace(); - if (s_end_ == s_itr_) { return; @@ -1548,10 +1546,8 @@ namespace exprtk if ((s_itr_ + 1) != s_end_) { token_t::token_type ttype = token_t::e_none; - char c0 = s_itr_[0]; char c1 = s_itr_[1]; - if ((c0 == '<') && (c1 == '=')) ttype = token_t::e_lte; else if ((c0 == '>') && (c1 == '=')) ttype = token_t::e_gte; else if ((c0 == '<') && (c1 == '>')) ttype = token_t::e_ne; @@ -1566,18 +1562,15 @@ namespace exprtk t.set_operator(ttype,s_itr_,s_itr_ + 2,base_itr_); token_list_.push_back(t); s_itr_ += 2; - return; } } - if ('<' == *s_itr_) t.set_operator(token_t::e_lt,s_itr_,s_itr_ + 1,base_itr_); else if ('>' == *s_itr_) t.set_operator(token_t::e_gt,s_itr_,s_itr_ + 1,base_itr_); else t.set_operator(token_t::token_type(*s_itr_),s_itr_,s_itr_ + 1,base_itr_); - token_list_.push_back(t); ++s_itr_; } @@ -1592,7 +1585,6 @@ namespace exprtk { ++s_itr_; } - token_t t; t.set_symbol(begin,s_itr_,base_itr_); token_list_.push_back(t); @@ -1625,10 +1617,8 @@ namespace exprtk { t.set_error(token::e_err_number,begin,s_itr_,base_itr_); token_list_.push_back(t); - return; } - dot_found = true; ++s_itr_; continue; @@ -1641,7 +1631,6 @@ namespace exprtk { t.set_error(token::e_err_number,begin,s_itr_,base_itr_); token_list_.push_back(t); - return; } else if ( @@ -1652,7 +1641,6 @@ namespace exprtk { t.set_error(token::e_err_number,begin,s_itr_,base_itr_); token_list_.push_back(t); - return; } @@ -1666,7 +1654,6 @@ namespace exprtk { t.set_error(token::e_err_number,begin,s_itr_,base_itr_); token_list_.push_back(t); - return; } @@ -1725,7 +1712,6 @@ namespace exprtk { const char* begin = s_itr_ + 1; token_t t; - if (std::distance(s_itr_,s_end_) < 2) { t.set_error(token::e_err_string,begin,s_itr_,base_itr_); @@ -1733,7 +1719,6 @@ namespace exprtk return; } - ++s_itr_; bool escaped = false; @@ -1761,13 +1746,10 @@ namespace exprtk { t.set_error(token::e_err_string,begin,s_itr_,base_itr_); token_list_.push_back(t); - return; } - t.set_string(begin,s_itr_,base_itr_); token_list_.push_back(t); - ++s_itr_; return; } @@ -1988,7 +1970,6 @@ namespace exprtk inline std::size_t process(generator& g) { std::size_t changes = 0; - for (std::size_t i = 0; i < g.token_list_.size() - 1; ++i) { token t; @@ -1999,7 +1980,6 @@ namespace exprtk ++changes; } } - return changes; } @@ -2061,7 +2041,6 @@ namespace exprtk return -1; } } - if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_symbol )) match = true; else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lbracket )) match = true; else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lcrlbracket)) match = true; @@ -2073,7 +2052,6 @@ namespace exprtk else if ((t0.type == lexer::token::e_rbracket ) && (t1.type == lexer::token::e_symbol )) match = true; else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_symbol )) match = true; else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_symbol )) match = true; - return (match) ? 1 : -1; } @@ -2238,9 +2216,7 @@ namespace exprtk error_list_.push_back(current_index_); } } - ++current_index_; - return true; } @@ -2276,14 +2252,11 @@ namespace exprtk const lexer::token::token_type token_type = lexer::token::e_symbol) { replace_map_t::iterator itr = replace_map_.find(target_symbol); - if (replace_map_.end() != itr) { return false; } - replace_map_[target_symbol] = std::make_pair(replace_symbol,token_type); - return true; } @@ -2300,9 +2273,7 @@ namespace exprtk { if (replace_map_.empty()) return false; - replace_map_t::iterator itr = replace_map_.find(t.value); - if (replace_map_.end() != itr) { t.value = itr->second.first; @@ -2310,7 +2281,6 @@ namespace exprtk return true; } } - return false; } @@ -2331,18 +2301,14 @@ namespace exprtk { add_invalid(lexer::token::e_number,lexer::token::e_number); add_invalid(lexer::token::e_string,lexer::token::e_string); - add_invalid(lexer::token::e_number,lexer::token::e_string); add_invalid(lexer::token::e_string,lexer::token::e_number); - add_invalid(lexer::token::e_number,lexer::token::e_colon); add_invalid(lexer::token::e_symbol,lexer::token::e_colon); add_invalid(lexer::token::e_string,lexer::token::e_colon); - add_invalid(lexer::token::e_colon,lexer::token::e_number); add_invalid(lexer::token::e_colon,lexer::token::e_symbol); add_invalid(lexer::token::e_colon,lexer::token::e_string); - add_invalid_set1(lexer::token::e_assign); add_invalid_set1(lexer::token::e_shr); add_invalid_set1(lexer::token::e_shl); @@ -2505,7 +2471,6 @@ namespace exprtk { return false; } - token_scanner_list.push_back(scanner); return true; } @@ -2518,7 +2483,6 @@ namespace exprtk { return false; } - token_modifier_list.push_back(modifier); return true; } @@ -2531,7 +2495,6 @@ namespace exprtk { return false; } - token_joiner_list.push_back(joiner); return true; } @@ -2544,7 +2507,6 @@ namespace exprtk { return false; } - token_inserter_list.push_back(inserter); return true; } @@ -2553,20 +2515,17 @@ namespace exprtk { error_token_modifier = reinterpret_cast(0); bool result = true; - for (std::size_t i = 0; i < token_modifier_list.size(); ++i) { lexer::token_modifier& modifier = (*token_modifier_list[i]); modifier.reset(); modifier.process(g); - if (!modifier.result()) { error_token_modifier = token_modifier_list[i]; return false; } } - return result; } @@ -2574,20 +2533,17 @@ namespace exprtk { error_token_joiner = reinterpret_cast(0); bool result = true; - for (std::size_t i = 0; i < token_joiner_list.size(); ++i) { lexer::token_joiner& joiner = (*token_joiner_list[i]); joiner.reset(); joiner.process(g); - if (!joiner.result()) { error_token_joiner = token_joiner_list[i]; return false; } } - return result; } @@ -2595,20 +2551,17 @@ namespace exprtk { error_token_inserter = reinterpret_cast(0); bool result = true; - for (std::size_t i = 0; i < token_inserter_list.size(); ++i) { lexer::token_inserter& inserter = (*token_inserter_list[i]); inserter.reset(); inserter.process(g); - if (!inserter.result()) { error_token_inserter = token_inserter_list[i]; return false; } } - return result; } @@ -2616,20 +2569,17 @@ namespace exprtk { error_token_scanner = reinterpret_cast(0); bool result = true; - for (std::size_t i = 0; i < token_scanner_list.size(); ++i) { lexer::token_scanner& scanner = (*token_scanner_list[i]); scanner.reset(); scanner.process(g); - if (!scanner.result()) { error_token_scanner = token_scanner_list[i]; return false; } } - return result; } @@ -2744,7 +2694,22 @@ namespace exprtk e_sf68 = 1068, e_sf69 = 1069, e_sf70 = 1070, e_sf71 = 1071, e_sf72 = 1072, e_sf73 = 1073, e_sf74 = 1074, e_sf75 = 1075, e_sf76 = 1076, e_sf77 = 1077, e_sf78 = 1078, e_sf79 = 1079, - e_sf80 = 1080, e_sf81 = 1081, e_sf82 = 1082 + e_sf80 = 1080, e_sf81 = 1081, e_sf82 = 1082, e_sf83 = 1083, + e_sf84 = 1084, e_sf85 = 1085, e_sf86 = 1086, e_sf87 = 1087, + e_sf88 = 1088, e_sf89 = 1089, e_sf90 = 1090, e_sf91 = 1091, + e_sf92 = 1092, e_sf93 = 1093, e_sf94 = 1094, e_sf95 = 1095, + e_sf96 = 1096, e_sf97 = 1097, + e_sffinal = 1098, + e_sf4ext00 = 2000, e_sf4ext01 = 2001, e_sf4ext02 = 2002, e_sf4ext03 = 2003, + e_sf4ext04 = 2004, e_sf4ext05 = 2005, e_sf4ext06 = 2006, e_sf4ext07 = 2007, + e_sf4ext08 = 2008, e_sf4ext09 = 2009, e_sf4ext10 = 2010, e_sf4ext11 = 2011, + e_sf4ext12 = 2012, e_sf4ext13 = 2013, e_sf4ext14 = 2014, e_sf4ext15 = 2015, + e_sf4ext16 = 2016, e_sf4ext17 = 2017, e_sf4ext18 = 2018, e_sf4ext19 = 2019, + e_sf4ext20 = 2020, e_sf4ext21 = 2021, e_sf4ext22 = 2022, e_sf4ext23 = 2023, + e_sf4ext24 = 2024, e_sf4ext25 = 2025, e_sf4ext26 = 2026, e_sf4ext27 = 2027, + e_sf4ext28 = 2028, e_sf4ext29 = 2029, e_sf4ext30 = 2030, e_sf4ext31 = 2031, + e_sf4ext32 = 2032, e_sf4ext33 = 2033, e_sf4ext34 = 2034, e_sf4ext35 = 2035, + e_sf4ext36 = 2036, e_sf4ext37 = 2037, e_sf4ext38 = 2038, e_sf4ext39 = 2039 }; struct base_operation_t @@ -2923,9 +2888,11 @@ namespace exprtk enum node_type { e_none , + e_null , e_constant , e_unary , e_binary , + e_binary_ext , e_trinary , e_quaternary , e_quinary , @@ -2959,7 +2926,6 @@ namespace exprtk e_inranges , e_ipow , e_ipowinv , - e_vov , e_abs , e_acos , e_asin , @@ -2991,7 +2957,29 @@ namespace exprtk e_erf , e_erfc , e_frac , - e_trunc + e_trunc , + e_uvouv , + e_vov , + e_cov , + e_voc , + e_vob , + e_bov , + e_cob , + e_boc , + e_vovov , + e_vovoc , + e_vocov , + e_covov , + e_covoc , + e_vovovov , + e_vovovoc , + e_vovocov , + e_vocovov , + e_covovov , + e_covocov , + e_vocovoc , + e_covovoc , + e_vococov }; typedef T value_type; @@ -3019,6 +3007,7 @@ namespace exprtk { return e_none; } + }; inline bool is_true(const double v) @@ -3091,7 +3080,7 @@ namespace exprtk inline typename expression_node::node_type type() const { - return expression_node::e_nul; + return expression_node::e_null; } }; @@ -3114,14 +3103,17 @@ namespace exprtk return expression_node::e_constant; } - inline expression_node* branch(const std::size_t& index = 0) const + inline expression_node* branch(const std::size_t&) const { - return reinterpret_cast*>(index * 0); + return reinterpret_cast*>(0); } private: - T value_; + literal_node(literal_node&) {} + literal_node& operator=(literal_node&) { return *this; } + + const T value_; }; template @@ -3143,9 +3135,9 @@ namespace exprtk return expression_node::e_stringconst; } - inline expression_node* branch(const std::size_t& index = 0) const + inline expression_node* branch(const std::size_t&) const { - return reinterpret_cast*>(index * 0); + return reinterpret_cast*>(0); } inline std::string str() @@ -3310,7 +3302,7 @@ namespace exprtk return expression_node::e_binary; } - inline operator_type operation() const + inline operator_type operation() { return operation_; } @@ -3331,6 +3323,56 @@ namespace exprtk branch_t branch_[2]; }; + template + class binary_ext_node : public expression_node + { + public: + + typedef expression_node* expression_ptr; + typedef std::pair branch_t; + + binary_ext_node(expression_ptr branch0, expression_ptr branch1) + { + init_branches<2>(branch_,branch0,branch1); + } + + ~binary_ext_node() + { + cleanup_branches::execute(branch_); + } + + inline T value() const + { + const T arg0 = branch_[0].first->value(); + const T arg1 = branch_[1].first->value(); + return Operation::process(arg0,arg1); + } + + inline typename expression_node::node_type type() const + { + return expression_node::e_binary_ext; + } + + inline operator_type operation() + { + return Operation::operation(); + } + + inline expression_node* branch(const std::size_t& index = 0) const + { + if (0 == index) + return branch_[0].first; + else if (1 == index) + return branch_[1].first; + else + return reinterpret_cast(0); + } + + protected: + + branch_t branch_[2]; + }; + template class trinary_node : public expression_node { @@ -3358,7 +3400,6 @@ namespace exprtk const T arg0 = branch_[0].first->value(); const T arg1 = branch_[1].first->value(); const T arg2 = branch_[2].first->value(); - switch (operation_) { case e_clamp : return (arg1 < arg0) ? arg0 : (arg1 > arg2 ? arg2 : arg1); @@ -3412,7 +3453,6 @@ namespace exprtk const T arg1 = branch_[1].first->value(); const T arg2 = branch_[2].first->value(); const T arg3 = branch_[3].first->value(); - switch (operation_) { case e_min : return std::min(std::min(arg0,arg1),std::min(arg2,arg3)); @@ -3522,7 +3562,6 @@ namespace exprtk const T arg3 = branch_[3].first->value(); const T arg4 = branch_[4].first->value(); const T arg5 = branch_[5].first->value(); - switch (operation_) { case e_min : return std::min(std::min(std::min(arg0,arg1),std::min(arg2,arg3)),std::min(arg4,arg5)); @@ -3744,89 +3783,156 @@ namespace exprtk 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; } }; - template struct sf03_op { static inline T process(const T x, const T y, const T z) { return (x - y) * z; } }; - template struct sf04_op { static inline T process(const T x, const T y, const T z) { return (x * y) + z; } }; - template struct sf05_op { static inline T process(const T x, const T y, const T z) { return (x * y) - z; } }; - template struct sf06_op { static inline T process(const T x, const T y, const T z) { return (x * y) / z; } }; - template struct sf07_op { static inline T process(const T x, const T y, const T z) { return (x * y) * z; } }; - template struct sf08_op { static inline T process(const T x, const T y, const T z) { return (x / y) + z; } }; - template struct sf09_op { static inline T process(const T x, const T y, const T z) { return (x / y) - z; } }; - template struct sf10_op { static inline T process(const T x, const T y, const T z) { return (x / y) / z; } }; - template struct sf11_op { static inline T process(const T x, const T y, const T z) { return (x / y) * z; } }; - template struct sf12_op { static inline T process(const T x, const T y, const T z) { return x / (y + z); } }; - template struct sf13_op { static inline T process(const T x, const T y, const T z) { return x / (y - z); } }; - template struct sf14_op { static inline T process(const T x, const T y, const T z) { return x / (y * z); } }; - template struct sf15_op { static inline T process(const T x, const T y, const T z) { return x / (y / z); } }; - template struct sf16_op { static inline T process(const T x, const T y, const T z) { return x - (y / z); } }; - template struct sf17_op { static inline T process(const T x, const T y, const T z) { return x - (y / z); } }; - 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) { return x * numeric::log(y) + z; } }; - template struct sf27_op { static inline T process(const T x, const T y, const T z) { return x * numeric::log(y) - z; } }; - template struct sf28_op { static inline T process(const T x, const T y, const T z) { return x * numeric::log10(y) + z; } }; - template struct sf29_op { static inline T process(const T x, const T y, const T z) { return x * numeric::log10(y) - z; } }; - template struct sf30_op { static inline T process(const T x, const T y, const T z) { return x * numeric::sin(y) + z; } }; - template struct sf31_op { static inline T process(const T x, const T y, const T z) { return x * numeric::sin(y) - z; } }; - template struct sf32_op { static inline T process(const T x, const T y, const T z) { return x * numeric::cos(y) + z; } }; - template struct sf33_op { static inline T process(const T x, const T y, const T z) { return x * numeric::cos(y) - z; } }; - template struct sf34_op { static inline T process(const T x, const T y, const T z) { return is_true(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 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 x - ((y / z) * w); } }; - template struct sf52_op { static inline T process(const T x, const T y, const T z, const T w) { return ((x + y) * z) - w; } }; - template struct sf53_op { static inline T process(const T x, const T y, const T z, const T w) { return ((x - y) * z) - w; } }; - template struct sf54_op { static inline T process(const T x, const T y, const T z, const T w) { return ((x * y) * z) - w; } }; - template struct sf55_op { static inline T process(const T x, const T y, const T z, const T w) { return ((x / y) * z) - w; } }; - template struct sf56_op { static inline T process(const T x, const T y, const T z, const T w) { return ((x + y) / z) - w; } }; - template struct sf57_op { static inline T process(const T x, const T y, const T z, const T w) { return ((x - y) / z) - w; } }; - template struct sf58_op { static inline T process(const T x, const T y, const T z, const T w) { return ((x * y) / z) - w; } }; - template struct sf59_op { static inline T process(const T x, const T y, const T z, const T w) { return ((x / y) / z) - w; } }; - template struct sf60_op { static inline T process(const T x, const T y, const T z, const T w) { return (x * y) + (z * w); } }; - template struct sf61_op { static inline T process(const T x, const T y, const T z, const T w) { return (x * y) - (z * w); } }; - template struct sf62_op { static inline T process(const T x, const T y, const T z, const T w) { return (x * y) + (z / w); } }; - template struct sf63_op { static inline T process(const T x, const T y, const T z, const T w) { return (x * y) - (z / w); } }; - template struct sf64_op { static inline T process(const T x, const T y, const T z, const T w) { return (x / y) + (z / w); } }; - template struct sf65_op { static inline T process(const T x, const T y, const T z, const T w) { return (x / y) - (z / w); } }; - template struct sf66_op { static inline T process(const T x, const T y, const T z, const T w) { return (x / y) - (z * w); } }; - template struct sf67_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 sf68_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 sf69_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 sf70_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 sf71_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 sf72_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 sf73_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 sf74_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 struct sf75_op { static inline T process(const T x, const T y, const T z, const T w) { return (is_true(x) && is_true(y)) ? z : w; } }; - template struct sf76_op { static inline T process(const T x, const T y, const T z, const T w) { return (is_true(x) || is_true(y)) ? z : w; } }; - template struct sf77_op { static inline T process(const T x, const T y, const T z, const T w) { return (x < y) ? z : w; } }; - template struct sf78_op { static inline T process(const T x, const T y, const T z, const T w) { return (x <= y) ? z : w; } }; - template struct sf79_op { static inline T process(const T x, const T y, const T z, const T w) { return (x > y) ? z : w; } }; - template struct sf80_op { static inline T process(const T x, const T y, const T z, const T w) { return (x >= y) ? z : w; } }; - template struct sf81_op { static inline T process(const T x, const T y, const T z, const T w) { return numeric::equal(x,y) ? z : w; } }; - template struct sf82_op { static inline T process(const T x, const T y, const T z, const T w) { return x * numeric::sin(y) + z * numeric::cos(w); } }; + template + struct sf_base + { + typedef typename details::functor_t::Type Type; + typedef typename details::functor_t functor_t; + typedef typename functor_t::qfunc_t quaternary_functor_t; + typedef typename functor_t::tfunc_t trinary_functor_t; + typedef typename functor_t::bfunc_t binary_functor_t; + typedef typename functor_t::ufunc_t unary_functor_t; + }; + + template struct sf00_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z) { return (x + y) / z; } static inline std::string id() { return "(t+t)/t";} }; + template struct sf01_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z) { return (x + y) * z; } static inline std::string id() { return "(t+t)*t";} }; + template struct sf02_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z) { return (x + y) - z; } static inline std::string id() { return "(t+t)-t";} }; + template struct sf03_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z) { return (x + y) + z; } static inline std::string id() { return "(t+t)+t";} }; + template struct sf04_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z) { return (x - y) / z; } static inline std::string id() { return "(t-t)/t";} }; + template struct sf05_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z) { return (x - y) * z; } static inline std::string id() { return "(t-t)*t";} }; + template struct sf06_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z) { return (x * y) + z; } static inline std::string id() { return "(t*t)+t";} }; + template struct sf07_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z) { return (x * y) - z; } static inline std::string id() { return "(t*t)-t";} }; + template struct sf08_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z) { return (x * y) / z; } static inline std::string id() { return "(t*t)/t";} }; + template struct sf09_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z) { return (x * y) * z; } static inline std::string id() { return "(t*t)*t";} }; + template struct sf10_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z) { return (x / y) + z; } static inline std::string id() { return "(t/t)+t";} }; + template struct sf11_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z) { return (x / y) - z; } static inline std::string id() { return "(t/t)-t";} }; + template struct sf12_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z) { return (x / y) / z; } static inline std::string id() { return "(t/t)/t";} }; + template struct sf13_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z) { return (x / y) * z; } static inline std::string id() { return "(t/t)*t";} }; + template struct sf14_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z) { return x / (y + z); } static inline std::string id() { return "t/(t+t)";} }; + template struct sf15_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z) { return x / (y - z); } static inline std::string id() { return "t/(t-t)";} }; + template struct sf16_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z) { return x / (y * z); } static inline std::string id() { return "t/(t*t)";} }; + template struct sf17_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z) { return x / (y / z); } static inline std::string id() { return "t/(t/t)";} }; + template struct sf18_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z) { return x * (y + z); } static inline std::string id() { return "t*(t+t)";} }; + template struct sf19_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z) { return x * (y - z); } static inline std::string id() { return "t*(t-t)";} }; + template struct sf20_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z) { return x * (y * z); } static inline std::string id() { return "t*(t*t)";} }; + template struct sf21_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z) { return x * (y / z); } static inline std::string id() { return "t*(t/t)";} }; + template struct sf22_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z) { return x - (y / z); } static inline std::string id() { return "t-(t/t)";} }; + template struct sf23_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z) { return x - (y / z); } static inline std::string id() { return "t-(t/t)";} }; + template struct sf24_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z) { return x - (y * z); } static inline std::string id() { return "t-(t*t)";} }; + template struct sf25_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z) { return x + (y * z); } static inline std::string id() { return "t+(t*t)";} }; + template struct sf26_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z) { return x + (y / z); } static inline std::string id() { return "t+(t/t)";} }; + template struct sf27_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z) { return x + (y + z); } static inline std::string id() { return "t+(t+t)";} }; + template struct sf28_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z) { return x + (y - z); } static inline std::string id() { return "t+(t-t)";} }; + template struct sf29_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z) { return axnb(x,y,z); } }; //x * y^2 + z + template struct sf30_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z) { return axnb(x,y,z); } }; //x * y^3 + z + template struct sf31_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z) { return axnb(x,y,z); } }; //x * y^4 + z + template struct sf32_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z) { return axnb(x,y,z); } }; //x * y^5 + z + template struct sf33_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z) { return axnb(x,y,z); } }; //x * y^6 + z + template struct sf34_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z) { return axnb(x,y,z); } }; //x * y^7 + z + template struct sf35_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z) { return axnb(x,y,z); } }; //x * y^8 + z + template struct sf36_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z) { return axnb(x,y,z); } }; //x * y^9 + z + template struct sf37_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z) { return x * numeric::log(y) + z; } }; + template struct sf38_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z) { return x * numeric::log(y) - z; } }; + template struct sf39_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z) { return x * numeric::log10(y) + z; } }; + template struct sf40_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z) { return x * numeric::log10(y) - z; } }; + template struct sf41_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z) { return x * numeric::sin(y) + z; } }; + template struct sf42_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z) { return x * numeric::sin(y) - z; } }; + template struct sf43_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z) { return x * numeric::cos(y) + z; } }; + template struct sf44_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z) { return x * numeric::cos(y) - z; } }; + template struct sf45_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z) { return is_true(x) ? y : z; } }; + template struct sf46_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x + ((y + z) / w); } static inline std::string id() { return "t+((t+t)/t)";} }; + template struct sf47_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x + ((y + z) * w); } static inline std::string id() { return "t+((t+t)*t)";} }; + template struct sf48_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x + ((y - z) / w); } static inline std::string id() { return "t+((t-t)/t)";} }; + template struct sf49_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x + ((y - z) * w); } static inline std::string id() { return "t+((t-t)*t)";} }; + template struct sf50_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x + ((y * z) / w); } static inline std::string id() { return "t+((t*t)/t)";} }; + template struct sf51_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x + ((y * z) * w); } static inline std::string id() { return "t+((t*t)*t)";} }; + template struct sf52_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x + ((y / z) + w); } static inline std::string id() { return "t+((t/t)+t)";} }; + template struct sf53_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x + ((y / z) / w); } static inline std::string id() { return "t+((t/t)/t)";} }; + template struct sf54_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x + ((y / z) * w); } static inline std::string id() { return "t+((t/t)*t)";} }; + template struct sf55_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x - ((y + z) / w); } static inline std::string id() { return "t-((t+t)/t)";} }; + template struct sf56_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x - ((y + z) * w); } static inline std::string id() { return "t-((t+t)*t)";} }; + template struct sf57_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x - ((y - z) / w); } static inline std::string id() { return "t-((t-t)/t)";} }; + template struct sf58_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x - ((y - z) * w); } static inline std::string id() { return "t-((t-t)*t)";} }; + template struct sf59_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x - ((y * z) / w); } static inline std::string id() { return "t-((t*t)/t)";} }; + template struct sf60_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x - ((y * z) * w); } static inline std::string id() { return "t-((t*t)*t)";} }; + template struct sf61_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x - ((y / z) / w); } static inline std::string id() { return "t-((t/t)/t)";} }; + template struct sf62_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x - ((y / z) * w); } static inline std::string id() { return "t-((t/t)*t)";} }; + template struct sf63_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return ((x + y) * z) - w; } static inline std::string id() { return "((t+t)*t)-t";} }; + template struct sf64_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return ((x - y) * z) - w; } static inline std::string id() { return "((t-t)*t)-t";} }; + template struct sf65_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return ((x * y) * z) - w; } static inline std::string id() { return "((t*t)*t)-t";} }; + template struct sf66_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return ((x / y) * z) - w; } static inline std::string id() { return "((t/t)*t)-t";} }; + template struct sf67_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return ((x + y) / z) - w; } static inline std::string id() { return "((t+t)/t)-t";} }; + template struct sf68_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return ((x - y) / z) - w; } static inline std::string id() { return "((t-t)/t)-t";} }; + template struct sf69_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return ((x * y) / z) - w; } static inline std::string id() { return "((t*t)/t)-t";} }; + template struct sf70_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return ((x / y) / z) - w; } static inline std::string id() { return "((t/t)/t)-t";} }; + template struct sf71_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x * y) + (z * w); } static inline std::string id() { return "(t*t)+(t*t)";} }; + template struct sf72_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x * y) - (z * w); } static inline std::string id() { return "(t*t)-(t*t)";} }; + template struct sf73_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x * y) + (z / w); } static inline std::string id() { return "(t*t)+(t/t)";} }; + template struct sf74_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x * y) - (z / w); } static inline std::string id() { return "(t*t)-(t/t)";} }; + template struct sf75_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x / y) + (z / w); } static inline std::string id() { return "(t/t)+(t/t)";} }; + template struct sf76_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x / y) - (z / w); } static inline std::string id() { return "(t/t)-(t/t)";} }; + template struct sf77_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x / y) - (z * w); } static inline std::string id() { return "(t/t)-(t*t)";} }; + template struct sf78_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x / (y + (z * w)); } static inline std::string id() { return "t/(t+(t*t))";} }; + template struct sf79_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x / (y - (z * w)); } static inline std::string id() { return "t/(t-(t*t))";} }; + template struct sf80_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x * (y + (z * w)); } static inline std::string id() { return "t*(t+(t*t))";} }; + template struct sf81_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x * (y - (z * w)); } static inline std::string id() { return "t*(t-(t*t))";} }; + template struct sf82_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return axn(x,y) + axn(z,w); } }; //x*y^2+z*w^2 + template struct sf83_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return axn(x,y) + axn(z,w); } }; //x*y^3+z*w^3 + template struct sf84_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return axn(x,y) + axn(z,w); } }; //x*y^4+z*w^4 + template struct sf85_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return axn(x,y) + axn(z,w); } }; //x*y^5+z*w^5 + template struct sf86_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return axn(x,y) + axn(z,w); } }; //x*y^6+z*w^6 + template struct sf87_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return axn(x,y) + axn(z,w); } }; //x*y^7+z*w^7 + template struct sf88_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return axn(x,y) + axn(z,w); } }; //x*y^8+z*w^8 + template struct sf89_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return axn(x,y) + axn(z,w); } }; //x*y^9+z*w^9 + template struct sf90_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (is_true(x) && is_true(y)) ? z : w; } }; + template struct sf91_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (is_true(x) || is_true(y)) ? z : w; } }; + template struct sf92_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x < y) ? z : w; } }; + template struct sf93_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x <= y) ? z : w; } }; + template struct sf94_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x > y) ? z : w; } }; + template struct sf95_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x >= y) ? z : w; } }; + template struct sf96_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return numeric::equal(x,y) ? z : w; } }; + template struct sf97_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return x * numeric::sin(y) + z * numeric::cos(w); } }; + + template struct sfext00_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x + y) - (z * w); } static inline std::string id() { return "(t+t)-(t*t)";} }; + template struct sfext01_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x + y) - (z / w); } static inline std::string id() { return "(t+t)-(t/t)";} }; + template struct sfext02_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x + y) + (z * w); } static inline std::string id() { return "(t+t)+(t*t)";} }; + template struct sfext03_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x + y) + (z / w); } static inline std::string id() { return "(t+t)+(t/t)";} }; + template struct sfext04_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x - y) + (z * w); } static inline std::string id() { return "(t-t)+(t*t)";} }; + template struct sfext05_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x - y) + (z / w); } static inline std::string id() { return "(t-t)+(t/t)";} }; + template struct sfext06_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x - y) - (z * w); } static inline std::string id() { return "(t-t)-(t*t)";} }; + template struct sfext07_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x - y) - (z / w); } static inline std::string id() { return "(t-t)-(t/t)";} }; + template struct sfext08_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x + y) - (z - w); } static inline std::string id() { return "(t+t)-(t-t)";} }; + template struct sfext09_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x + y) - (z - w); } static inline std::string id() { return "(t+t)-(t-t)";} }; + template struct sfext10_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x + y) + (z - w); } static inline std::string id() { return "(t+t)+(t-t)";} }; + template struct sfext11_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x + y) + (z - w); } static inline std::string id() { return "(t+t)+(t-t)";} }; + template struct sfext12_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x - y) - (z + w); } static inline std::string id() { return "(t-t)-(t+t)";} }; + template struct sfext13_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x - y) - (z + w); } static inline std::string id() { return "(t-t)-(t+t)";} }; + template struct sfext14_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x - y) + (z + w); } static inline std::string id() { return "(t-t)+(t+t)";} }; + template struct sfext15_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x - y) + (z + w); } static inline std::string id() { return "(t-t)+(t+t)";} }; + template struct sfext16_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x * y) - (z + w); } static inline std::string id() { return "(t*t)-(t+t)";} }; + template struct sfext17_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x / y) - (z + w); } static inline std::string id() { return "(t/t)-(t+t)";} }; + template struct sfext18_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x * y) + (z + w); } static inline std::string id() { return "(t*t)+(t+t)";} }; + template struct sfext19_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x / y) + (z + w); } static inline std::string id() { return "(t/t)+(t+t)";} }; + template struct sfext20_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x * y) + (z - w); } static inline std::string id() { return "(t*t)+(t-t)";} }; + template struct sfext21_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x / y) + (z - w); } static inline std::string id() { return "(t/t)+(t-t)";} }; + template struct sfext22_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x * y) - (z - w); } static inline std::string id() { return "(t*t)-(t-t)";} }; + template struct sfext23_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x / y) - (z - w); } static inline std::string id() { return "(t/t)-(t-t)";} }; + template struct sfext24_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x + y) * (z * w); } static inline std::string id() { return "(t+t)*(t*t)";} }; + template struct sfext25_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x + y) * (z / w); } static inline std::string id() { return "(t+t)*(t/t)";} }; + template struct sfext26_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x + y) / (z * w); } static inline std::string id() { return "(t+t)/(t*t)";} }; + template struct sfext27_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x + y) / (z / w); } static inline std::string id() { return "(t+t)/(t/t)";} }; + template struct sfext28_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x - y) / (z * w); } static inline std::string id() { return "(t-t)/(t*t)";} }; + template struct sfext29_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x - y) / (z / w); } static inline std::string id() { return "(t-t)/(t/t)";} }; + template struct sfext30_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x - y) * (z * w); } static inline std::string id() { return "(t-t)*(t*t)";} }; + template struct sfext31_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x - y) * (z / w); } static inline std::string id() { return "(t-t)*(t/t)";} }; + template struct sfext32_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x * y) * (z + w); } static inline std::string id() { return "(t*t)*(t+t)";} }; + template struct sfext33_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x / y) * (z + w); } static inline std::string id() { return "(t/t)*(t+t)";} }; + template struct sfext34_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x * y) / (z + w); } static inline std::string id() { return "(t*t)/(t+t)";} }; + template struct sfext35_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x / y) / (z + w); } static inline std::string id() { return "(t/t)/(t+t)";} }; + template struct sfext36_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x * y) / (z - w); } static inline std::string id() { return "(t*t)/(t-t)";} }; + template struct sfext37_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x / y) / (z - w); } static inline std::string id() { return "(t/t)/(t-t)";} }; + template struct sfext38_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x * y) * (z - w); } static inline std::string id() { return "(t*t)*(t-t)";} }; + template struct sfext39_op : public sf_base { typedef typename sf_base::Type Type; static inline T process(Type x, Type y, Type z, Type w) { return (x / y) * (z - w); } static inline std::string id() { return "(t/t)*(t-t)";} }; template class sf3_node : public trinary_node @@ -3847,7 +3953,6 @@ namespace exprtk const T x = trinary_node::branch_[0].first->value(); const T y = trinary_node::branch_[1].first->value(); const T z = trinary_node::branch_[2].first->value(); - return SpecialFunction::process(x,y,z); } }; @@ -3873,7 +3978,6 @@ namespace exprtk const T y = quaternary_node::branch_[1].first->value(); const T z = quaternary_node::branch_[2].first->value(); const T w = quaternary_node::branch_[3].first->value(); - return SpecialFunction::process(x,y,z,w); } }; @@ -3964,7 +4068,6 @@ namespace exprtk if (is_variable_node(binary_node::branch_[0].first)) { variable_node* var_node_ptr = dynamic_cast*>(binary_node::branch_[0].first); - if (var_node_ptr) { T& result = var_node_ptr->ref(); @@ -3982,7 +4085,7 @@ namespace exprtk { public: - //function of N paramters. + // Function of N paramters. typedef expression_node* expression_ptr; typedef std::pair branch_t; typedef IFunction ifunction; @@ -4000,7 +4103,7 @@ namespace exprtk template bool init_branches(expression_ptr (&b)[NumBranches]) { - //Needed for incompetent and broken msvc compiler versions + // Needed for incompetent and broken msvc compiler versions #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4127) @@ -4016,7 +4119,6 @@ namespace exprtk else return false; } - return true; } #ifdef _MSC_VER @@ -4031,7 +4133,7 @@ namespace exprtk inline T value() const { - //Needed for incompetent and broken msvc compiler versions + // Needed for incompetent and broken msvc compiler versions #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4127) @@ -4211,9 +4313,9 @@ namespace exprtk }; template - struct invoke + struct invoke { - static inline T_ execute(ifunction& f, T_ (&v)[ 7]) + 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]); } }; @@ -4311,7 +4413,8 @@ namespace exprtk template \ struct OpName##_op \ { \ - static inline T process(const T v) { return numeric:: OpName (v); } \ + 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; } \ }; @@ -4350,155 +4453,184 @@ namespace exprtk exprtk_def_unary_op(trunc) #undef exprtk_def_unary_op - template - struct add_op + template + struct opr_base { - static inline T process(const T t1, const T t2) { return t1 + t2; } - static inline T process(const T t1, const T t2, const T t3) { return t1 + t2 + t3; } + typedef typename details::functor_t::Type Type; + typedef typename details::functor_t functor_t; + typedef typename functor_t::qfunc_t quaternary_functor_t; + typedef typename functor_t::tfunc_t trinary_functor_t; + typedef typename functor_t::bfunc_t binary_functor_t; + typedef typename functor_t::ufunc_t unary_functor_t; + }; + + template + struct add_op : public opr_base + { + typedef typename opr_base::Type Type; + static inline T process(Type t1, Type t2) { return t1 + t2; } + static inline T process(Type t1, Type t2, Type t3) { return t1 + t2 + t3; } static inline typename expression_node::node_type type() { return expression_node::e_add; } static inline details::operator_type operation() { return details::e_add; } }; template - struct mul_op + struct mul_op : public opr_base { - static inline T process(const T t1, const T t2) { return t1 * t2; } - static inline T process(const T t1, const T t2, const T t3) { return t1 * t2 * t3; } + typedef typename opr_base::Type Type; + static inline T process(Type t1, Type t2) { return t1 * t2; } + static inline T process(Type t1, Type t2, Type t3) { return t1 * t2 * t3; } static inline typename expression_node::node_type type() { return expression_node::e_mul; } static inline details::operator_type operation() { return details::e_mul; } }; template - struct sub_op + struct sub_op : public opr_base { - static inline T process(const T t1, const T t2) { return t1 - t2; } - static inline T process(const T t1, const T t2, const T t3) { return t1 - t2 - t3; } + typedef typename opr_base::Type Type; + static inline T process(Type t1, Type t2) { return t1 - t2; } + static inline T process(Type t1, Type t2, Type t3) { return t1 - t2 - t3; } static inline typename expression_node::node_type type() { return expression_node::e_sub; } static inline details::operator_type operation() { return details::e_sub; } }; template - struct div_op + struct div_op : public opr_base { - static inline T process(const T t1, const T t2) { return t1 / t2; } - static inline T process(const T t1, const T t2, const T t3) { return t1 / t2 / t3; } + typedef typename opr_base::Type Type; + static inline T process(Type t1, Type t2) { return t1 / t2; } + static inline T process(Type t1, Type t2, Type t3) { return t1 / t2 / t3; } static inline typename expression_node::node_type type() { return expression_node::e_div; } static inline details::operator_type operation() { return details::e_div; } }; template - struct mod_op + struct mod_op : public opr_base { - static inline T process(const T t1, const T t2) { return numeric::modulus(t1,t2); } + typedef typename opr_base::Type Type; + static inline T process(Type t1, Type t2) { return numeric::modulus(t1,t2); } static inline typename expression_node::node_type type() { return expression_node::e_mod; } static inline details::operator_type operation() { return details::e_mod; } }; template - struct pow_op + struct pow_op : public opr_base { - static inline T process(const T t1, const T t2) { return numeric::pow(t1,t2); } + typedef typename opr_base::Type Type; + static inline T process(Type t1, Type t2) { return numeric::pow(t1,t2); } static inline typename expression_node::node_type type() { return expression_node::e_pow; } static inline details::operator_type operation() { return details::e_pow; } }; template - struct lt_op + struct lt_op : public opr_base { - static inline T process(const T t1, const T t2) { return ((t1 < t2) ? T(1) : T(0)); } + typedef typename opr_base::Type Type; + static inline T process(Type t1, Type t2) { return ((t1 < t2) ? T(1) : T(0)); } static inline T process(const std::string& t1, const std::string& t2) { return ((t1 < t2) ? T(1) : T(0)); } static inline typename expression_node::node_type type() { return expression_node::e_lt; } static inline details::operator_type operation() { return details::e_lt; } }; template - struct lte_op + struct lte_op : public opr_base { - static inline T process(const T t1, const T t2) { return ((t1 <= t2) ? T(1) : T(0)); } + typedef typename opr_base::Type Type; + static inline T process(Type t1, Type t2) { return ((t1 <= t2) ? T(1) : T(0)); } static inline T process(const std::string& t1, const std::string& t2) { return ((t1 <= t2) ? T(1) : T(0)); } static inline typename expression_node::node_type type() { return expression_node::e_lte; } static inline details::operator_type operation() { return details::e_lte; } }; template - struct gt_op + struct gt_op : public opr_base { - static inline T process(const T t1, const T t2) { return ((t1 > t2) ? T(1) : T(0)); } + typedef typename opr_base::Type Type; + static inline T process(Type t1, Type t2) { return ((t1 > t2) ? T(1) : T(0)); } static inline T process(const std::string& t1, const std::string& t2) { return ((t1 > t2) ? T(1) : T(0)); } static inline typename expression_node::node_type type() { return expression_node::e_gt; } static inline details::operator_type operation() { return details::e_gt; } }; template - struct gte_op + struct gte_op : public opr_base { - static inline T process(const T t1, const T t2) { return ((t1 >= t2) ? T(1) : T(0)); } + typedef typename opr_base::Type Type; + static inline T process(Type t1, Type t2) { return ((t1 >= t2) ? T(1) : T(0)); } static inline T process(const std::string& t1, const std::string& t2) { return ((t1 >= t2) ? T(1) : T(0)); } static inline typename expression_node::node_type type() { return expression_node::e_gte; } static inline details::operator_type operation() { return details::e_gte; } }; template - struct eq_op + struct eq_op : public opr_base { - static inline T process(const T t1, const T t2) { return ((t1 == t2) ? T(1) : T(0)); } + typedef typename opr_base::Type Type; + static inline T process(Type t1, Type t2) { return ((t1 == t2) ? T(1) : T(0)); } static inline T process(const std::string& t1, const std::string& t2) { return ((t1 == t2) ? T(1) : T(0)); } static inline typename expression_node::node_type type() { return expression_node::e_eq; } static inline details::operator_type operation() { return details::e_eq; } }; template - struct ne_op + struct ne_op : public opr_base { - static inline T process(const T t1, const T t2) { return ((t1 != t2) ? T(1) : T(0)); } + typedef typename opr_base::Type Type; + static inline T process(Type t1, Type t2) { return ((t1 != t2) ? T(1) : T(0)); } static inline T process(const std::string& t1, const std::string& t2) { return ((t1 != t2) ? T(1) : T(0)); } static inline typename expression_node::node_type type() { return expression_node::e_ne; } static inline details::operator_type operation() { return details::e_ne; } }; template - struct and_op + struct and_op : public opr_base { - static inline T process(const T t1, const T t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(1) : T(0); } + typedef typename opr_base::Type Type; + static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(1) : T(0); } static inline typename expression_node::node_type type() { return expression_node::e_and; } static inline details::operator_type operation() { return details::e_and; } }; template - struct nand_op + struct nand_op : public opr_base { - static inline T process(const T t1, const T t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(0) : T(1); } + typedef typename opr_base::Type Type; + static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(0) : T(1); } static inline typename expression_node::node_type type() { return expression_node::e_nand; } static inline details::operator_type operation() { return details::e_nand; } }; template - struct or_op + struct or_op : public opr_base { - static inline T process(const T t1, const T t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(1) : T(0); } + typedef typename opr_base::Type Type; + static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(1) : T(0); } static inline typename expression_node::node_type type() { return expression_node::e_or; } static inline details::operator_type operation() { return details::e_or; } }; template - struct nor_op + struct nor_op : public opr_base { - static inline T process(const T t1, const T t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(0) : T(1); } + typedef typename opr_base::Type Type; + static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(0) : T(1); } static inline typename expression_node::node_type type() { return expression_node::e_nor; } static inline details::operator_type operation() { return details::e_nor; } }; template - struct xor_op + struct xor_op : public opr_base { - static inline T process(const T t1, const T t2) { return numeric::xor_opr(t1,t2); } + typedef typename opr_base::Type Type; + static inline T process(Type t1, Type t2) { return numeric::xor_opr(t1,t2); } static inline typename expression_node::node_type type() { return expression_node::e_nor; } static inline details::operator_type operation() { return details::e_xor; } }; template - struct in_op + struct in_op : public opr_base { + typedef typename opr_base::Type Type; static inline T process(const T&, const T&) { return std::numeric_limits::quiet_NaN(); } static inline T process(const std::string& t1, const std::string& t2) { return ((std::string::npos != t2.find(t1)) ? T(1) : T(0)); } static inline typename expression_node::node_type type() { return expression_node::e_in; } @@ -4506,8 +4638,9 @@ namespace exprtk }; template - struct like_op + struct like_op : public opr_base { + typedef typename opr_base::Type Type; static inline T process(const T&, const T&) { return std::numeric_limits::quiet_NaN(); } static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_match(t2,t1) ? T(1) : T(0)); } static inline typename expression_node::node_type type() { return expression_node::e_like; } @@ -4515,8 +4648,9 @@ namespace exprtk }; template - struct ilike_op + struct ilike_op : public opr_base { + typedef typename opr_base::Type Type; static inline T process(const T&, const T&) { return std::numeric_limits::quiet_NaN(); } static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_imatch(t2,t1) ? T(1) : T(0)); } static inline typename expression_node::node_type type() { return expression_node::e_ilike; } @@ -4524,15 +4658,16 @@ namespace exprtk }; template - struct inrange_op + struct inrange_op : public opr_base { + typedef typename opr_base::Type Type; static inline T process(const T& t0, const T& t1, const T& t2) { return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0); } static inline T process(const std::string& t0, const std::string& t1, const std::string& t2) { return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0); } static inline typename expression_node::node_type type() { return expression_node::e_inranges; } - static inline details::operator_type operation() { return details::e_ilike; } + static inline details::operator_type operation() { return details::e_inrange; } }; template @@ -4544,6 +4679,10 @@ namespace exprtk { return details::e_default; } + + virtual const T& v0() const = 0; + + virtual const T& v1() const = 0; }; template @@ -4555,6 +4694,10 @@ namespace exprtk { return details::e_default; } + + virtual const T c() const = 0; + + virtual const T& v() const = 0; }; template @@ -4566,6 +4709,56 @@ namespace exprtk { return details::e_default; } + + virtual const T c() const = 0; + + virtual const T& v() const = 0; + }; + + template + class vob_base_node : public expression_node + { + public: + + virtual const T& v() const = 0; + }; + + template + class bov_base_node : public expression_node + { + public: + + virtual const T& v() const = 0; + }; + + template + class cob_base_node : public expression_node + { + public: + + inline virtual operator_type operation() const + { + return details::e_default; + } + + virtual const T c() const = 0; + + virtual void set_c(const T) = 0; + }; + + template + class boc_base_node : public expression_node + { + public: + + inline virtual operator_type operation() const + { + return details::e_default; + } + + virtual const T c() const = 0; + + virtual void set_c(const T) = 0; }; template @@ -4577,6 +4770,8 @@ namespace exprtk { return details::e_default; } + + virtual const T& v() const = 0; }; template @@ -4601,6 +4796,22 @@ namespace exprtk } }; + template + class T0oT1oT2_base_node : public expression_node + { + public: + + virtual std::string type_id() const = 0; + }; + + template + class T0oT1oT2oT3_base_node : public expression_node + { + public: + + virtual std::string type_id() const = 0; + }; + template class unary_variable_node : public uv_base_node { @@ -4610,7 +4821,7 @@ namespace exprtk typedef Operation operation_t; explicit unary_variable_node(const T& v) - : v_(v) + : v_(v) {} inline T value() const @@ -4628,7 +4839,7 @@ namespace exprtk return Operation::operation(); } - inline const T& v() + inline const T& v() const { return v_; } @@ -4641,7 +4852,7 @@ namespace exprtk const T& v_; }; - template + template class uvouv_node : public expression_node { public: @@ -4649,28 +4860,31 @@ namespace exprtk // UOpr1(v0) Op UOpr2(v1) typedef expression_node* expression_ptr; - typedef UOpr1 opr1_t; - typedef UOpr2 opr2_t; - typedef Operation op_t; + typedef typename details::functor_t functor_t; + typedef typename functor_t::bfunc_t bfunc_t; + typedef typename functor_t::ufunc_t ufunc_t; - explicit uvouv_node(const T& v0,const T& v1) + explicit uvouv_node(const T& v0,const T& v1, ufunc_t u0, ufunc_t u1, bfunc_t f) : v0_(v0), - v1_(v1) + v1_(v1), + u0_(u0), + u1_(u1), + f_ (f ) {} inline T value() const { - return Operation::process(UOpr1::process(v0_),UOpr2::process(v1_)); + return f_(u0_(v0_),u1_(v1_)); } inline typename expression_node::node_type type() const { - return Operation::type(); + return expression_node::e_uvouv; } inline operator_type operation() const { - return Operation::operation(); + return details::e_default; } inline const T& v0() @@ -4683,13 +4897,31 @@ namespace exprtk return v1_; } + inline ufunc_t u0() + { + return u0_; + } + + inline ufunc_t u1() + { + return u1_; + } + + inline ufunc_t f() + { + return f_; + } + private: - uvouv_node(uvouv_node&); - uvouv_node& operator=(uvouv_node&); + uvouv_node(uvouv_node&); + uvouv_node& operator=(uvouv_node&); const T& v0_; const T& v1_; + const ufunc_t u0_; + const ufunc_t u1_; + const bfunc_t f_; }; template @@ -4701,11 +4933,11 @@ namespace exprtk typedef Operation operation_t; explicit unary_branch_node(expression_ptr branch) - : branch_(branch), - branch_deletable_(branch_deletable(branch_)) + : branch_(branch), + branch_deletable_(branch_deletable(branch_)) {} - ~unary_branch_node() + ~unary_branch_node() { if (branch_ && branch_deletable_) { @@ -4738,6 +4970,832 @@ namespace exprtk bool branch_deletable_; }; + template struct is_const { enum {result = 0}; }; + template struct is_const { enum {result = 1}; }; + template struct is_const_ref { enum {result = 0}; }; + template struct is_const_ref { enum {result = 1}; }; + template struct is_ref { enum {result = 0}; }; + template struct is_ref { enum {result = 1}; }; + template struct is_ref { enum {result = 0}; }; + + template + struct param_to_str { static std::string result() { static const std::string r("v"); return r; } }; + + template <> + struct param_to_str<0> { static std::string result() { static const std::string r("c"); return r; } }; + + template + struct T0oT1oT2process + { + typedef typename details::functor_t functor_t; + typedef typename functor_t::bfunc_t bfunc_t; + + struct mode0 + { + static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1) + { + // (T0 o0 T1) o1 T2 + return bf1(bf0(t0,t1),t2); + } + + template + static inline std::string id() + { + static const std::string result = "(" + param_to_str::result>::result() + "o" + + param_to_str::result>::result() + ")o(" + + param_to_str::result>::result() + ")" ; + return result; + } + }; + + struct mode1 + { + static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1) + { + // T0 o0 (T1 o1 T2) + return bf0(t0,bf1(t1,t2)); + } + + template + static inline std::string id() + { + static const std::string result = "(" + param_to_str::result>::result() + ")o(" + + param_to_str::result>::result() + "o" + + param_to_str::result>::result() + ")" ; + return result; + } + }; + }; + + template + struct T0oT1oT20T3process + { + typedef typename details::functor_t functor_t; + typedef typename functor_t::bfunc_t bfunc_t; + + struct mode0 + { + static inline T process(const T& t0, const T& t1, const T& t2, const T& t3, const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) + { + // (T0 o0 T1) o1 (T2 o2 T3) + return bf1(bf0(t0,t1),bf2(t2,t3)); + } + + template + static inline std::string id() + { + static const std::string result = "(" + param_to_str::result>::result() + "o" + + param_to_str::result>::result() + ")o" + + "(" + param_to_str::result>::result() + "o" + + param_to_str::result>::result() + ")" ; + return result; + } + }; + + struct mode1 + { + static inline T process(const T& t0, const T& t1, const T& t2, const T& t3, const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) + { + // (T0 o0 (T1 o1 (T2 o2 T3)) + return bf0(t0,bf1(t1,bf2(t2,t3))); + } + template + static inline std::string id() + { + static const std::string result = "(" + param_to_str::result>::result() + ")o((" + + param_to_str::result>::result() + ")o(" + + param_to_str::result>::result() + "o" + + param_to_str::result>::result() + "))" ; + return result; + } + }; + + struct mode2 + { + static inline T process(const T& t0, const T& t1, const T& t2, const T& t3, const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) + { + // (T0 o0 ((T1 o1 T2) o2 T3) + return bf0(t0,bf2(bf1(t1,t2),t3)); + } + + template + static inline std::string id() + { + static const std::string result = "(" + param_to_str::result>::result() + ")o((" + + param_to_str::result>::result() + "o" + + param_to_str::result>::result() + ")o(" + + param_to_str::result>::result() + "))" ; + return result; + } + }; + + struct mode3 + { + static inline T process(const T& t0, const T& t1, const T& t2, const T& t3, const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) + { + // (((T0 o0 T1) o1 T2) o2 T3) + return bf2(bf1(bf0(t0,t1),t2),t3); + } + + template + static inline std::string id() + { + static const std::string result = "((" + param_to_str::result>::result() + "o" + + param_to_str::result>::result() + ")o(" + + param_to_str::result>::result() + "))o(" + + param_to_str::result>::result() + ")"; + return result; + } + }; + + struct mode4 + { + static inline T process(const T& t0, const T& t1, const T& t2, const T& t3, const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) + { + // ((T0 o0 (T1 o1 T2)) o2 T3 + return bf2(bf0(t0,bf1(t1,t2)),t3); + } + + template + static inline std::string id() + { + static const std::string result = "((" + param_to_str::result>::result() + ")o(" + + param_to_str::result>::result() + "o" + + param_to_str::result>::result() + "))o(" + + param_to_str::result>::result() + ")" ; + return result; + } + }; + }; + + template + struct nodetype_T0oT1 { static const typename expression_node::node_type result; }; + 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 \ + 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 + + 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 \ + 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 + + 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 \ + 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 + + template + class T0oT1 : public expression_node + { + public: + + typedef typename details::functor_t functor_t; + typedef typename functor_t::bfunc_t bfunc_t; + typedef T value_type; + typedef T0oT1 node_type; + + T0oT1(T0 t0, T1 t1, const bfunc_t f) + : t0_(t0), + t1_(t1), + f_(f) + {} + + inline typename expression_node::node_type type() const + { + static const typename expression_node::node_type result = nodetype_T0oT1::result; + return result; + } + + inline operator_type operation() const + { + return e_default; + } + + inline T value() const + { + return f_(t0_,t1_); + } + + inline T0 t0() const + { + return t0_; + } + + inline T1 t1() const + { + return t1_; + } + + inline bfunc_t f() const + { + return f_; + } + + template + static inline expression_node* allocate(Allocator& allocator, + T0 t0, T1 t1, + bfunc_t f) + { + return allocator.template allocate_type(t0,t1,f); + } + + private: + + T0oT1(T0oT1&) {} + T0oT1& operator=(T0oT1&) { return *this; } + + T0 t0_; + T1 t1_; + const bfunc_t f_; + }; + + template + class T0oT1oT2 : public T0oT1oT2_base_node + { + public: + + typedef typename details::functor_t functor_t; + typedef typename functor_t::bfunc_t bfunc_t; + typedef T value_type; + typedef T0oT1oT2 node_type; + typedef ProcessMode process_mode_t; + + T0oT1oT2(T0 t0, T1 t1, T2 t2, const bfunc_t f0, const bfunc_t f1) + : t0_(t0), + t1_(t1), + t2_(t2), + f0_(f0), + f1_(f1) + {} + + inline typename expression_node::node_type type() const + { + static const typename expression_node::node_type result = nodetype_T0oT1oT2::result; + return result; + } + + inline operator_type operation() const + { + return e_default; + } + + inline T value() const + { + return ProcessMode::process(t0_,t1_,t2_,f0_,f1_); + } + + inline T0 t0() const + { + return t0_; + } + + inline T1 t1() const + { + return t1_; + } + + inline T2 t2() const + { + return t2_; + } + + bfunc_t f0() const + { + return f0_; + } + + bfunc_t f1() const + { + return f1_; + } + + std::string type_id() const + { + return id(); + } + + static inline std::string id() + { + return process_mode_t::template id(); + } + + template + static inline expression_node* allocate(Allocator& allocator, T0 t0, T1 t1, T2 t2, bfunc_t f0, bfunc_t f1) + { + return allocator.template allocate_type(t0,t1,t2,f0,f1); + } + + private: + + T0oT1oT2(node_type&) {} + node_type& operator=(node_type&) { return *this; } + + T0 t0_; + T1 t1_; + T2 t2_; + const bfunc_t f0_; + const bfunc_t f1_; + }; + + template + class T0oT1oT2oT3 : public T0oT1oT2oT3_base_node + { + public: + + typedef typename details::functor_t functor_t; + typedef typename functor_t::bfunc_t bfunc_t; + typedef T value_type; + typedef T0_ T0; + typedef T1_ T1; + typedef T2_ T2; + typedef T3_ T3; + typedef T0oT1oT2oT3 node_type; + typedef ProcessMode process_mode_t; + + T0oT1oT2oT3(T0 t0, T1 t1, T2 t2, T3 t3, bfunc_t f0, bfunc_t f1, bfunc_t f2) + : t0_(t0), + t1_(t1), + t2_(t2), + t3_(t3), + f0_(f0), + f1_(f1), + f2_(f2) + {} + + inline T value() const + { + return ProcessMode::process(t0_,t1_,t2_,t3_,f0_,f1_,f2_); + } + + inline T0 t0() const + { + return t0_; + } + + inline T1 t1() const + { + return t1_; + } + + inline T2 t2() const + { + return t2_; + } + + inline T3 t3() const + { + return t3_; + } + + inline bfunc_t f0() const + { + return f0_; + } + + inline bfunc_t f1() const + { + return f1_; + } + + inline bfunc_t f2() const + { + return f2_; + } + + inline std::string type_id() const + { + return id(); + } + + static inline std::string id() + { + return process_mode_t::template id(); + } + + template + static inline expression_node* allocate(Allocator& allocator, + T0 t0, T1 t1, T2 t2, T3 t3, + bfunc_t f0, bfunc_t f1, bfunc_t f2) + { + return allocator.template allocate_type(t0,t1,t2,t3,f0,f1,f2); + } + + private: + + T0oT1oT2oT3(node_type&) {} + node_type& operator=(node_type&) { return *this; } + + T0 t0_; + T1 t1_; + T2 t2_; + T3 t3_; + const bfunc_t f0_; + const bfunc_t f1_; + const bfunc_t f2_; + }; + + template + class T0oT1oT2_sf3 : public T0oT1oT2_base_node + { + public: + + typedef typename details::functor_t functor_t; + typedef typename functor_t::tfunc_t tfunc_t; + typedef T value_type; + typedef T0oT1oT2_sf3 node_type; + + T0oT1oT2_sf3(T0 t0, T1 t1, T2 t2, const tfunc_t f) + : t0_(t0), + t1_(t1), + t2_(t2), + f_(f) + {} + + inline typename expression_node::node_type type() const + { + static const typename expression_node::node_type result = nodetype_T0oT1oT2::result; + return result; + } + + inline operator_type operation() const + { + return e_default; + } + + inline T value() const + { + return f_(t0_,t1_,t2_); + } + + inline T0 t0() const + { + return t0_; + } + + inline T1 t1() const + { + return t1_; + } + + inline T2 t2() const + { + return t2_; + } + + tfunc_t f() const + { + return f_; + } + + std::string type_id() const + { + return id(); + } + + static inline std::string id() + { + return "sf3"; + } + + template + static inline expression_node* allocate(Allocator& allocator, T0 t0, T1 t1, T2 t2, tfunc_t f) + { + return allocator.template allocate_type(t0,t1,t2,f); + } + + private: + + T0oT1oT2_sf3(node_type&) {} + node_type& operator=(node_type&) { return *this; } + + T0 t0_; + T1 t1_; + T2 t2_; + const tfunc_t f_; + }; + + template + class T0oT1oT2_sf3ext : public T0oT1oT2_base_node + { + public: + + typedef typename details::functor_t functor_t; + typedef typename functor_t::tfunc_t tfunc_t; + typedef T value_type; + typedef T0oT1oT2_sf3ext node_type; + + T0oT1oT2_sf3ext(T0 t0, T1 t1, T2 t2) + : t0_(t0), + t1_(t1), + t2_(t2) + {} + + inline typename expression_node::node_type type() const + { + static const typename expression_node::node_type result = nodetype_T0oT1oT2::result; + return result; + } + + inline operator_type operation() const + { + return e_default; + } + + inline T value() const + { + return SF3Operation::process(t0_,t1_,t2_); + } + + inline T0 t0() const + { + return t0_; + } + + inline T1 t1() const + { + return t1_; + } + + inline T2 t2() const + { + return t2_; + } + + std::string type_id() const + { + return id(); + } + + static inline std::string id() + { + return SF3Operation::id(); + } + + template + static inline expression_node* allocate(Allocator& allocator, T0 t0, T1 t1, T2 t2) + { + return allocator.template allocate_type(t0,t1,t2); + } + + private: + + T0oT1oT2_sf3ext(node_type&) {} + node_type& operator=(node_type&) { return *this; } + + T0 t0_; + T1 t1_; + T2 t2_; + }; + + template + class T0oT1oT2oT3_sf4 : public T0oT1oT2_base_node + { + public: + + typedef typename details::functor_t functor_t; + typedef typename functor_t::qfunc_t qfunc_t; + typedef T value_type; + typedef T0oT1oT2oT3_sf4 node_type; + + T0oT1oT2oT3_sf4(T0 t0, T1 t1, T2 t2, T3 t3, const qfunc_t f) + : t0_(t0), + t1_(t1), + t2_(t2), + t3_(t3), + f_(f) + {} + + inline typename expression_node::node_type type() const + { + static const typename expression_node::node_type result = nodetype_T0oT1oT2oT3::result; + return result; + } + + inline operator_type operation() const + { + return e_default; + } + + inline T value() const + { + return f_(t0_,t1_,t2_,t3_); + } + + inline T0 t0() const + { + return t0_; + } + + inline T1 t1() const + { + return t1_; + } + + inline T2 t2() const + { + return t2_; + } + + inline T3 t3() const + { + return t3_; + } + + qfunc_t f() const + { + return f_; + } + + std::string type_id() const + { + return id(); + } + + static inline std::string id() + { + return "sf4"; + } + + template + static inline expression_node* allocate(Allocator& allocator, T0 t0, T1 t1, T2 t2, T3 t3, qfunc_t f) + { + return allocator.template allocate_type(t0,t1,t2,t3,f); + } + + private: + + T0oT1oT2oT3_sf4(node_type&) {} + node_type& operator=(node_type&) { return *this; } + + T0 t0_; + T1 t1_; + T2 t2_; + T3 t3_; + const qfunc_t f_; + }; + + template + class T0oT1oT2oT3_sf4ext : public T0oT1oT2oT3_base_node + { + public: + + typedef typename details::functor_t functor_t; + typedef typename functor_t::tfunc_t tfunc_t; + typedef T value_type; + typedef T0oT1oT2oT3_sf4ext node_type; + + T0oT1oT2oT3_sf4ext(T0 t0, T1 t1, T2 t2, T3 t3) + : t0_(t0), + t1_(t1), + t2_(t2), + t3_(t3) + {} + + inline typename expression_node::node_type type() const + { + static const typename expression_node::node_type result = nodetype_T0oT1oT2oT3::result; + return result; + } + + inline operator_type operation() const + { + return e_default; + } + + inline T value() const + { + return SF4Operation::process(t0_,t1_,t2_,t3_); + } + + inline T0 t0() const + { + return t0_; + } + + inline T1 t1() const + { + return t1_; + } + + inline T2 t2() const + { + return t2_; + } + + inline T3 t3() const + { + return t2_; + } + + std::string type_id() const + { + return id(); + } + + static inline std::string id() + { + return SF4Operation::id(); + } + + template + static inline expression_node* allocate(Allocator& allocator, T0 t0, T1 t1, T2 t2, T3 t3) + { + return allocator.template allocate_type(t0,t1,t2,t3); + } + + private: + + T0oT1oT2oT3_sf4ext(node_type&) {} + node_type& operator=(node_type&) { return *this; } + + T0 t0_; + T1 t1_; + T2 t2_; + T3 t3_; + }; + + template + struct T0oT1_define + { + typedef details::T0oT1 type0; + }; + + template + struct T0oT1oT2_define + { + typedef details::T0oT1oT2::mode0> type0; + typedef details::T0oT1oT2::mode1> type1; + typedef details::T0oT1oT2_sf3 sf3_type; + }; + + template + struct T0oT1oT2oT3_define + { + typedef details::T0oT1oT2oT3::mode0> type0; + typedef details::T0oT1oT2oT3::mode1> type1; + typedef details::T0oT1oT2oT3::mode2> type2; + typedef details::T0oT1oT2oT3::mode3> type3; + typedef details::T0oT1oT2oT3::mode4> type4; + typedef details::T0oT1oT2oT3_sf4 sf4_type; + }; + template class vov_node : public vov_base_node { @@ -4746,7 +5804,7 @@ namespace exprtk typedef expression_node* expression_ptr; typedef Operation operation_t; - //variable op variable node + // variable op variable node explicit vov_node(const T& v0, const T& v1) : v0_(v0), v1_(v1) @@ -4796,7 +5854,7 @@ namespace exprtk typedef expression_node* expression_ptr; typedef Operation operation_t; - //constant op variable node + // constant op variable node explicit cov_node(const T& c, const T& v) : c_(c), v_(v) @@ -4817,7 +5875,7 @@ namespace exprtk return Operation::operation(); } - inline T c() + inline const T c() const { return c_; } @@ -4846,7 +5904,7 @@ namespace exprtk typedef expression_node* expression_ptr; typedef Operation operation_t; - //variable op constant node + // variable op constant node explicit voc_node(const T& v, const T& c) : v_(v), c_(c) @@ -4862,7 +5920,7 @@ namespace exprtk return Operation::operation(); } - inline T c() + inline const T c() const { return c_; } @@ -4883,523 +5941,214 @@ namespace exprtk voc_node& operator=(const voc_node&); }; - template - class vovov1_node : public expression_node + template + class vob_node : public vob_base_node { public: typedef expression_node* expression_ptr; typedef std::pair branch_t; + typedef Operation operation_t; - //variable0 op1 (variable1 op2 variable2) node - explicit vovov1_node(const T& v0, vov_node& vn) - : v0_(v0), - v1_(vn.v0()), - v2_(vn.v1()) - {} + // variable op constant node + explicit vob_node(const T& v, const expression_ptr branch) + : v_(v) + { + init_branches<1>(branch_,branch); + } + + ~vob_node() + { + cleanup_branches::execute(branch_); + } inline T value() const { - return Operation1::process(v0_,Operation2::process(v1_,v2_)); + return Operation::process(v_,branch_[0].first->value()); } - inline typename expression_node::node_type type() const + inline operator_type operation() const { - return expression_node::e_none; + return Operation::operation(); } - inline typename expression_node::node_type type1() const + inline const T& v() const { - return Operation1::type(); + return v_; } - inline typename expression_node::node_type type2() const + inline expression_node* branch(const std::size_t&) const { - return Operation2::type(); + return branch_[0].first; } - protected: - - const T& v0_; - const T& v1_; - const T& v2_; - private: - vovov1_node(const vovov1_node&); - vovov1_node& operator=(const vovov1_node&); + vob_node(const vob_node&); + vob_node& operator=(const vob_node&); + + const T& v_; + branch_t branch_[1]; }; - template - class vovov2_node : public expression_node + template + class bov_node : public bov_base_node { public: typedef expression_node* expression_ptr; typedef std::pair branch_t; + typedef Operation operation_t; - //(variable0 op1 variable1) op2 variable2 node - explicit vovov2_node(vov_node& vn, const T& v2) - : v0_(vn.v0()), - v1_(vn.v1()), - v2_(v2) - {} + // variable op constant node + explicit bov_node(const expression_ptr branch, const T& v) + : v_(v) + { + init_branches<1>(branch_,branch); + } + + ~bov_node() + { + cleanup_branches::execute(branch_); + } inline T value() const { - return Operation2::process(Operation1::process(v0_,v1_),v2_); + return Operation::process(branch_[0].first->value(),v_); } - inline typename expression_node::node_type type() const + inline operator_type operation() const { - return expression_node::e_none; + return Operation::operation(); } - inline typename expression_node::node_type type1() const + inline const T& v() const { - return Operation1::type(); + return v_; } - inline typename expression_node::node_type type2() const + inline expression_node* branch(const std::size_t&) const { - return Operation2::type(); + return branch_[0].first; } - protected: - - const T& v0_; - const T& v1_; - const T& v2_; - private: - vovov2_node(const vovov2_node&); - vovov2_node& operator=(const vovov2_node&); + bov_node(const bov_node&); + bov_node& operator=(const bov_node&); + + const T& v_; + branch_t branch_[1]; }; - template - class covov1_node : public expression_node + template + class cob_node : public cob_base_node { public: typedef expression_node* expression_ptr; typedef std::pair branch_t; + typedef Operation operation_t; - //constant op1 (variable0 op2 variable1) node - explicit covov1_node(const T& c, vov_node& vn) - : c_ (c), - v0_(vn.v0()), - v1_(vn.v1()) - {} + // variable op constant node + explicit cob_node(const T c, const expression_ptr branch) + : c_(c) + { + init_branches<1>(branch_,branch); + } + + ~cob_node() + { + cleanup_branches::execute(branch_); + } inline T value() const { - return Operation1::process(c_,Operation2::process(v0_,v1_)); + return Operation::process(c_,branch_[0].first->value()); } - inline typename expression_node::node_type type() const + inline operator_type operation() const { - return expression_node::e_none; + return Operation::operation(); } - inline typename expression_node::node_type type1() const + inline const T c() const { - return Operation1::type(); + return c_; } - inline typename expression_node::node_type type2() const + inline void set_c(const T new_c) { - return Operation2::type(); + (*const_cast(&c_)) = new_c; } - protected: - - const T c_; - const T& v0_; - const T& v1_; + inline expression_node* branch(const std::size_t&) const + { + return branch_[0].first; + } private: - covov1_node(const covov1_node&); - covov1_node& operator=(const covov1_node&); + cob_node(const cob_node&); + cob_node& operator=(const cob_node&); + + const T c_; + branch_t branch_[1]; }; - template - class covov2_node : public expression_node + template + class boc_node : public boc_base_node { public: typedef expression_node* expression_ptr; typedef std::pair branch_t; + typedef Operation operation_t; - //(constant op1 variable0) op2 variable1 node - explicit covov2_node(cov_node& cvn, const T& v1) - : c_ (cvn.c()), - v0_(cvn.v()), - v1_(v1) - {} + // variable op constant node + explicit boc_node(const expression_ptr branch, const T c) + : c_(c) + { + init_branches<1>(branch_,branch); + } + + ~boc_node() + { + cleanup_branches::execute(branch_); + } inline T value() const { - return Operation2::process(Operation1::process(c_,v0_),v1_); + return Operation::process(branch_[0].first->value(),c_); } - inline typename expression_node::node_type type() const + inline operator_type operation() const { - return expression_node::e_none; + return Operation::operation(); } - inline typename expression_node::node_type type1() const + inline const T c() const { - return Operation1::type(); + return c_; } - inline typename expression_node::node_type type2() const + inline void set_c(const T new_c) { - return Operation2::type(); + (*const_cast(&c_)) = new_c; } - protected: - - const T c_; - const T& v0_; - const T& v1_; + inline expression_node* branch(const std::size_t&) const + { + return branch_[0].first; + } private: - covov2_node(covov2_node&); - covov2_node& operator=(covov2_node&); - }; + boc_node(const boc_node&); + boc_node& operator=(const boc_node&); - template - class vovoc1_node : public expression_node - { - public: - - typedef expression_node* expression_ptr; - typedef std::pair branch_t; - - //variable0 op1 (variable1 op2 constant) node - explicit vovoc1_node(const T& v0, voc_node& vcn) - : v0_(v0), - v1_(vcn.v()), - c_ (vcn.c()) - {} - - inline T value() const - { - return Operation1::process(v0_,Operation2::process(v1_,c_)); - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_none; - } - - inline typename expression_node::node_type type1() const - { - return Operation1::type(); - } - - inline typename expression_node::node_type type2() const - { - return Operation2::type(); - } - - protected: - - const T& v0_; - const T& v1_; - const T c_; - - private: - - vovoc1_node(const vovoc1_node&); - vovoc1_node& operator=(const vovoc1_node&); - }; - - template - class vovoc2_node : public expression_node - { - public: - - typedef expression_node* expression_ptr; - typedef std::pair branch_t; - - //(variable0 op1 variable1) op2 constant node - explicit vovoc2_node(vov_node& vvn, const T& c) - : v0_(vvn.v0()), - v1_(vvn.v1()), - c_ (c) - {} - - inline T value() const - { - return Operation2::process(Operation1::process(v0_,v1_),c_); - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_none; - } - - inline typename expression_node::node_type type1() const - { - return Operation1::type(); - } - - inline typename expression_node::node_type type2() const - { - return Operation2::type(); - } - - protected: - - const T& v0_; - const T& v1_; - const T c_; - - private: - - vovoc2_node(vovoc2_node&); - vovoc2_node& operator=(vovoc2_node&); - }; - - template - class covoc1_node : public expression_node - { - public: - - typedef expression_node* expression_ptr; - typedef std::pair branch_t; - - //const0 op1 (variable op2 const1) node - explicit covoc1_node(const T& c0, voc_node& vcn) - : c0_(c0), - v_ (vcn.v()), - c1_(vcn.c()) - {} - - inline T value() const - { - return Operation1::process(c0_,Operation2::process(v_,c1_)); - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_none; - } - - inline typename expression_node::node_type type1() const - { - return Operation1::type(); - } - - inline typename expression_node::node_type type2() const - { - return Operation2::type(); - } - - protected: - - const T c0_; - const T& v_; - const T c1_; - - private: - - covoc1_node(const covoc1_node&); - covoc1_node& operator=(const covoc1_node&); - }; - - template - class covoc2_node : public expression_node - { - public: - - typedef expression_node* expression_ptr; - typedef std::pair branch_t; - - //(const0 op1 variable) op2 const1 node - explicit covoc2_node(cov_node& cvn, const T& c1) - : c0_(cvn.c()), - v_ (cvn.v()), - c1_(c1) - {} - - inline T value() const - { - return Operation2::process(Operation1::process(c0_,v_),c1_); - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_none; - } - - inline typename expression_node::node_type type1() const - { - return Operation1::type(); - } - - inline typename expression_node::node_type type2() const - { - return Operation2::type(); - } - - protected: - - const T c0_; - const T& v_; - const T c1_; - - private: - - covoc2_node(const covoc2_node&); - covoc2_node& operator=(const covoc2_node&); - }; - - template - class vocov1_node : public expression_node - { - public: - - typedef expression_node* expression_ptr; - typedef std::pair branch_t; - - //variable0 op1 (const op2 variable1) node - explicit vocov1_node(const T& v0, cov_node& cvn) - : v0_(v0), - c_ (cvn.c()), - v1_(cvn.v()) - {} - - inline T value() const - { - return Operation1::process(v0_,Operation2::process(c_,v1_)); - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_none; - } - - inline typename expression_node::node_type type1() const - { - return Operation1::type(); - } - - inline typename expression_node::node_type type2() const - { - return Operation2::type(); - } - - protected: - - const T& v0_; - const T c_; - const T& v1_; - - private: - - vocov1_node(const vocov1_node&); - vocov1_node& operator=(const vocov1_node&); - }; - - template - class vocov2_node : public expression_node - { - public: - - typedef expression_node* expression_ptr; - typedef std::pair branch_t; - - //(variable0 op1 constant) op2 variable1 node - explicit vocov2_node(voc_node& vcn, const T& v1) - : v0_(vcn.v()), - c_ (vcn.c()), - v1_(v1) - {} - - inline T value() const - { - return Operation2::process(Operation1::process(v0_,c_),v1_); - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_none; - } - - inline typename expression_node::node_type type1() const - { - return Operation1::type(); - } - - inline typename expression_node::node_type type2() const - { - return Operation2::type(); - } - - protected: - - const T& v0_; - const T c_; - const T& v1_; - - private: - - vocov2_node(const vocov2_node&); - vocov2_node& operator=(const vocov2_node&); - }; - - template - class vovovov_node : public expression_node - { - public: - - typedef expression_node* expression_ptr; - typedef std::pair branch_t; - - //(variable0 op1 variable1) op2 (variable2 op3 variable3) node - explicit vovovov_node(vov_node& vn0, vov_node& vn1) - : v0_(vn0.v0()), - v1_(vn0.v1()), - v2_(vn1.v0()), - v3_(vn1.v1()) - {} - - inline T value() const - { - return Operation2::process(Operation1::process(v0_,v1_),Operation3::process(v2_,v3_)); - } - - inline typename expression_node::node_type type() const - { - return expression_node::e_none; - } - - inline typename expression_node::node_type type1() const - { - return Operation1::type(); - } - - inline typename expression_node::node_type type2() const - { - return Operation2::type(); - } - - protected: - - const T& v0_; - const T& v1_; - const T& v2_; - const T& v3_; - - private: - - vovovov_node(vovovov_node&); - vovovov_node& operator=(const vovovov_node&); + const T c_; + branch_t branch_[1]; }; #ifndef exprtk_disable_string_capabilities @@ -5411,7 +6160,7 @@ namespace exprtk typedef expression_node* expression_ptr; typedef Operation operation_t; - //variable op variable node + // variable op variable node explicit sos_node(SType0 s0, SType1 s1) : s0_(s0), s1_(s1) @@ -5461,7 +6210,7 @@ namespace exprtk typedef expression_node* expression_ptr; typedef Operation operation_t; - //variable op variable node + // variable op variable node explicit sosos_node(SType0 s0, SType1 s1, SType2 s2) : s0_(s0), s1_(s1), @@ -5519,7 +6268,7 @@ namespace exprtk typedef expression_node* expression_ptr; typedef PowOp operation_t; - explicit ipow_node(T& v) + explicit ipow_node(const T& v) : v_(v) {} @@ -5549,7 +6298,7 @@ namespace exprtk typedef expression_node* expression_ptr; typedef PowOp operation_t; - explicit ipowinv_node(T& v) + explicit ipowinv_node(const T& v) : v_(v) {} @@ -5589,6 +6338,30 @@ namespace exprtk return (0 != dynamic_cast*>(node)); } + template + inline bool is_cob_node(const expression_node* node) + { + return (0 != dynamic_cast*>(node)); + } + + template + inline bool is_boc_node(const expression_node* node) + { + return (0 != dynamic_cast*>(node)); + } + + template + inline bool is_t0ot1ot2_node(const expression_node* node) + { + return (0 != dynamic_cast*>(node)); + } + + template + inline bool is_t0ot1ot2ot3_node(const expression_node* node) + { + return (0 != dynamic_cast*>(node)); + } + template inline bool is_uv_node(const expression_node* node) { @@ -5709,10 +6482,10 @@ namespace exprtk } template - inline expression_node* allocate_type(T1 t1, T2 t2, T3 t3) const + typename T1, typename T2, typename T3, typename T4, typename T5> + inline expression_node* allocate_rrrrr(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5) const { - return new node_type(t1,t2,t3); + return new node_type(t1,t2,t3,t4,t5); } template + inline expression_node* allocate_type(T1 t1, T2 t2, T3 t3) const + { + return new node_type(t1,t2,t3); + } + + template + inline expression_node* allocate_type(T1 t1, T2 t2, + T3 t3, T4 t4) const + { + return new node_type(t1,t2,t3,t4); + } + + template + inline expression_node* allocate_type(T1 t1, T2 t2, + T3 t3, T4 t4, + T5 t5) const + { + return new node_type(t1,t2,t3,t4,t5); + } + + template + inline expression_node* allocate_type(T1 t1, T2 t2, + T3 t3, T4 t4, + T5 t5, T6 t6, + T7 t7) const + { + return new node_type(t1,t2,t3,t4,t5,t6,t7); + } + template void inline free(expression_node*& e) const { @@ -6073,7 +6885,6 @@ namespace exprtk else { tm_const_itr_t itr = map.find(symbol_name); - if (map.end() == itr) return false; else @@ -6117,16 +6928,13 @@ namespace exprtk return false; } } - tm_itr_t itr = map.find(symbol_name); - if (map.end() == itr) { map[symbol_name] = tie::make(t,is_constant); ++size; } } - return true; } @@ -6155,10 +6963,8 @@ namespace exprtk if (1 == symbol_name.size()) { type_pair_t& tp = short_type_lut[static_cast(std::tolower(symbol_name[0]))]; - if (0 == tp.second) return false; - struct deleter { static inline void process(std::pair& n) { delete n.second; } @@ -6167,18 +6973,15 @@ namespace exprtk #endif static inline void process(std::pair&) { } }; - deleter::process(tp); tp.first = false; tp.second = 0; --size; - return true; } else { tm_itr_t itr = map.find(symbol_name); - if (map.end() != itr) { struct deleter @@ -6189,11 +6992,9 @@ namespace exprtk #endif static inline void process(std::pair&) { } }; - deleter::process((*itr).second); map.erase(itr); --size; - return true; } else @@ -6215,7 +7016,6 @@ namespace exprtk if (1 == symbol_name.size()) { type_pair_t& tp = short_type_lut[static_cast(std::tolower(symbol_name[0]))]; - if (tp.second) return tp->second.ref(); else @@ -6224,7 +7024,6 @@ namespace exprtk else { tm_const_itr_t itr = map.find(symbol_name); - if (map.end() == itr) return null_type; else @@ -6248,7 +7047,6 @@ namespace exprtk { tm_itr_t itr = map.begin(); tm_itr_t end = map.end(); - while (end != itr) { struct deleter @@ -6263,7 +7061,6 @@ namespace exprtk deleter::process((*itr).second); ++itr; } - map.clear(); } } @@ -6273,11 +7070,9 @@ namespace exprtk inline std::size_t get_list(Sequence,Allocator>& list) const { std::size_t count = 0; - for (std::size_t i = 0; i < lut_size; ++i) { const type_pair_t& tp = short_type_lut[static_cast(i)]; - if (0 != tp.second) { list.push_back(std::make_pair(std::string("") + static_cast(i),tp.second->ref())); @@ -6289,7 +7084,6 @@ namespace exprtk { tm_const_itr_t itr = map.begin(); tm_const_itr_t end = map.end(); - while (end != itr) { list.push_back(std::make_pair((*itr).first,itr->second.second->ref())); @@ -6297,7 +7091,6 @@ namespace exprtk ++count; } } - return count; } @@ -6306,23 +7099,19 @@ namespace exprtk inline std::size_t get_list(Sequence& vlist) const { std::size_t count = 0; - for (std::size_t i = 0; i < lut_size; ++i) { const type_pair_t& tp = short_type_lut[static_cast(i)]; - if (0 != tp.second) { vlist.push_back(std::string("") + static_cast(i)); ++count; } } - if (!map.empty()) { tm_const_itr_t itr = map.begin(); tm_const_itr_t end = map.end(); - while (end != itr) { vlist.push_back((*itr).first); @@ -6330,10 +7119,8 @@ namespace exprtk ++count; } } - return count; } - }; typedef typename details::variable_node variable_t; @@ -6364,7 +7151,6 @@ namespace exprtk { reserved_symbol_table_.insert(details::reserved_words[i]); } - for (std::size_t i = 0; i < details::reserved_symbols_size; ++i) { reserved_symbol_table_.insert(details::reserved_symbols[i]); @@ -6438,13 +7224,10 @@ namespace exprtk { delete holder_; } - holder_ = 0; } - holder_ = st.holder_; holder_->ref_count++; - return *this; } @@ -6873,7 +7656,9 @@ namespace exprtk expression() : expression_holder_(0) - {} + { + set_expression(new details::null_node()); + } expression(const expression& e) : expression_holder_(e.expression_holder_), @@ -6892,15 +7677,12 @@ namespace exprtk { delete expression_holder_; } - expression_holder_ = 0; } - expression_holder_ = e.expression_holder_; expression_holder_->ref_count++; symbol_table_ = e.symbol_table_; } - return *this; } @@ -6922,10 +7704,8 @@ namespace exprtk { delete expression_holder_; } - expression_holder_ = 0; } - return *this; } @@ -6988,7 +7768,6 @@ namespace exprtk delete expression_holder_; } } - expression_holder_ = new expression_holder(expr); } } @@ -7117,6 +7896,8 @@ namespace exprtk e_level13 }; + typedef const T& cref_t; + typedef const T const_t; typedef ifunction F; typedef ifunction ifunction_t; typedef details::expression_node expression_node_t; @@ -7138,16 +7919,43 @@ namespace exprtk typedef lexer::token token_t; typedef expression_node_t* expression_node_ptr; - public: + typedef typename details::functor_t functor_t; + typedef typename functor_t::qfunc_t quaternary_functor_t; + typedef typename functor_t::tfunc_t trinary_functor_t; + typedef typename functor_t::bfunc_t binary_functor_t; + typedef typename functor_t::ufunc_t unary_functor_t; + typedef std::map unary_op_map_t; + typedef std::map binary_op_map_t; + typedef std::map trinary_op_map_t; + typedef std::map > sf3_map_t; + typedef std::map > sf4_map_t; + typedef std::map inv_binary_op_map_t; + typedef std::multimap base_ops_map_t; - enum optimization_level - { - e_none = 0, - e_level1 = 1, - e_level2 = 2, - e_level3 = 4, - e_all = 7 - }; + typedef details::T0oT1_define vov_t; + typedef details::T0oT1_define cov_t; + typedef details::T0oT1_define voc_t; + + typedef details::T0oT1oT2_define vovov_t; + typedef details::T0oT1oT2_define vovoc_t; + typedef details::T0oT1oT2_define vocov_t; + typedef details::T0oT1oT2_define covov_t; + typedef details::T0oT1oT2_define covoc_t; + typedef details::T0oT1oT2_define cocov_t; + typedef details::T0oT1oT2_define vococ_t; + + typedef details::T0oT1oT2oT3_define vovovov_t; + typedef details::T0oT1oT2oT3_define vovovoc_t; + typedef details::T0oT1oT2oT3_define vovocov_t; + typedef details::T0oT1oT2oT3_define vocovov_t; + typedef details::T0oT1oT2oT3_define covovov_t; + + typedef details::T0oT1oT2oT3_define covocov_t; + typedef details::T0oT1oT2oT3_define vocovoc_t; + typedef details::T0oT1oT2oT3_define covovoc_t; + typedef details::T0oT1oT2oT3_define vococov_t; + + public: enum precompilation_step { @@ -7173,6 +7981,17 @@ namespace exprtk { init_precompilation(); load_operations_map(base_ops_map_); + load_unary_operations_map(unary_op_map_); + load_binary_operations_map(binary_op_map_); + load_inv_binary_operations_map(inv_binary_op_map_); + load_sf3_map(sf3_map_); + load_sf4_map(sf4_map_); + expression_generator_.init_synthesize_map(); + expression_generator_.set_uom(unary_op_map_); + expression_generator_.set_bom(binary_op_map_); + expression_generator_.set_ibom(inv_binary_op_map_); + expression_generator_.set_sf3m(sf3_map_); + expression_generator_.set_sf4m(sf4_map_); } inline void init_precompilation() @@ -7192,7 +8011,6 @@ namespace exprtk { commutative_inserter_.ignore_symbol(details::reserved_words[i]); } - helper_assembly_.token_inserter_list.clear(); helper_assembly_.register_inserter(&commutative_inserter_); } @@ -7209,7 +8027,6 @@ namespace exprtk sequence_check_enabled() ) { - helper_assembly_.token_scanner_list.clear(); if (numeric_check_enabled()) @@ -7229,10 +8046,9 @@ namespace exprtk } } - inline bool compile(const std::string& expression_string, expression& expr, const optimization_level& opt_level = e_all) + inline bool compile(const std::string& expression_string, expression& expr) { error_list_.clear(); - expression_generator_.set_optimization_level(opt_level); expression_generator_.set_allocator(node_allocator_); if (!lexer_.process(expression_string)) @@ -7263,7 +8079,10 @@ namespace exprtk { set_error(parser_error::make_error(parser_error::e_syntax, "ERR01 - Incomplete expression!")); symbol_name_cache_.clear(); - if (0 != e) delete e; + if (0 != e) + { + delete e; + } return false; } } @@ -7279,23 +8098,17 @@ namespace exprtk { case lexer::token::e_error : diagnostic + "General token error"; break; - case lexer::token::e_err_symbol : diagnostic + "Symbol error"; break; - case lexer::token::e_err_number : diagnostic + "Invalid numeric token"; break; - case lexer::token::e_err_string : diagnostic + "Invalid string token"; break; - case lexer::token::e_err_sfunc : diagnostic + "Invalid special function token"; break; - default : diagnostic + "Unknown compiler error"; break; } - set_error(make_error(parser_error::e_lexer,lexer_[i],diagnostic + ": " + lexer_[i].value)); } } @@ -7394,7 +8207,6 @@ namespace exprtk } } } - return false; } } @@ -7660,7 +8472,7 @@ namespace exprtk }; template - inline expression_node_ptr parse_function_call(const details::operator_type& opt_type) + inline expression_node_ptr parse_function_call(const details::operator_type& opt_type, bool& internal_error) { expression_node_ptr branch[NumberofParameters]; expression_node_ptr result = 0; @@ -7668,7 +8480,6 @@ namespace exprtk std::fill_n(branch,NumberofParameters,reinterpret_cast(0)); scoped_delete sd(*this,branch); - store_token(); next_token(); if (!token_is(token_t::e_lbracket)) @@ -7679,9 +8490,9 @@ namespace exprtk for (int i = 0; i < static_cast(NumberofParameters); ++i) { branch[i] = parse_expression(); - if (0 == branch[i]) { + internal_error = true; return error_node(); } else if (i < static_cast(NumberofParameters - 1)) @@ -7699,9 +8510,7 @@ namespace exprtk } else result = expression_generator_(opt_type,branch); - sd.delete_ptr = false; - return result; } @@ -7709,34 +8518,28 @@ namespace exprtk inline expression_node_ptr parse_function_call(ifunction* function, const std::string& function_name) { expression_node_ptr branch[NumberofParameters]; - expression_node_ptr result = 0; - + expression_node_ptr result = error_node(); std::fill_n(branch,NumberofParameters,reinterpret_cast(0)); scoped_delete sd(*this,branch); - next_token(); - if (!token_is(token_t::e_lbracket)) { set_error( make_error(parser_error::e_syntax, current_token_, "ERR06 - Expecting argument list for function: '" + function_name + "'")); - return error_node(); } for (int i = 0; i < static_cast(NumberofParameters); ++i) { branch[i] = parse_expression(); - if (0 == branch[i]) { set_error( make_error(parser_error::e_syntax, current_token_, "ERR07 - Failed to parse argument " + details::to_str(i) + " for function: '" + function_name + "'")); - return error_node(); } else if (i < static_cast(NumberofParameters - 1)) @@ -7747,7 +8550,6 @@ namespace exprtk make_error(parser_error::e_syntax, current_token_, "ERR08 - Invalid number of arguments for function: '" + function_name + "'")); - return error_node(); } } @@ -7759,51 +8561,43 @@ namespace exprtk make_error(parser_error::e_syntax, current_token_, "ERR09 - Invalid number of arguments for function: '" + function_name + "'")); - return error_node(); } else result = expression_generator_.function(function,branch); sd.delete_ptr = false; - return result; } inline expression_node_ptr parse_base_operation() { - typedef std::multimap map_t; - typedef std::pair map_range_t; - + typedef std::pair map_range_t; const std::string operation_name = current_token_.value; - map_range_t itr_range = base_ops_map_.equal_range(operation_name); - if (0 == std::distance(itr_range.first,itr_range.second)) { set_error( make_error(parser_error::e_syntax, current_token_, "ERR10 - No entries found for base operation: " + operation_name)); - return error_node(); } - for (map_t::iterator itr = itr_range.first; itr != itr_range.second; ++itr) + for (base_ops_map_t::iterator itr = itr_range.first; itr != itr_range.second; ++itr) { store_token(); - expression_node_ptr branch = reinterpret_cast(0); details::base_operation_t& operation = itr->second; - + bool internal_error = false; // Any error other than incorrect number of params. switch (operation.num_params) { - case 1 : branch = parse_function_call<1>(operation.type); break; - case 2 : branch = parse_function_call<2>(operation.type); break; - case 3 : branch = parse_function_call<3>(operation.type); break; - case 4 : branch = parse_function_call<4>(operation.type); break; - case 5 : branch = parse_function_call<5>(operation.type); break; - case 6 : branch = parse_function_call<6>(operation.type); break; + case 1 : branch = parse_function_call<1>(operation.type,internal_error); break; + case 2 : branch = parse_function_call<2>(operation.type,internal_error); break; + case 3 : branch = parse_function_call<3>(operation.type,internal_error); break; + case 4 : branch = parse_function_call<4>(operation.type,internal_error); break; + case 5 : branch = parse_function_call<5>(operation.type,internal_error); break; + case 6 : branch = parse_function_call<6>(operation.type,internal_error); break; default : { set_error( @@ -7819,7 +8613,10 @@ namespace exprtk { return branch; } - + else if (internal_error) + { + return error_node(); + } remove_last_error(); restore_token(); } @@ -7828,16 +8625,15 @@ namespace exprtk make_error(parser_error::e_syntax, current_token_, "ERR12 - Invalid parameter count for function: " + operation_name)); - return error_node(); } inline expression_node_ptr parse_conditional_statement() { - //Parse: [if][(][condition][,][consequent][,][alternative][)] - expression_node_ptr condition = 0; - expression_node_ptr consequent = 0; - expression_node_ptr alternative = 0; + // Parse: [if][(][condition][,][consequent][,][alternative][)] + expression_node_ptr condition = error_node(); + expression_node_ptr consequent = error_node(); + expression_node_ptr alternative = error_node(); next_token(); @@ -7849,7 +8645,6 @@ namespace exprtk make_error(parser_error::e_syntax, current_token_, "ERR13 - Failed to parse condition for if-statement")); - return error_node(); } else if (!token_is(token_t::e_comma)) @@ -7860,7 +8655,6 @@ namespace exprtk make_error(parser_error::e_syntax, current_token_, "ERR14 - Failed to parse consequent for if-statement")); - return error_node(); } else if (!token_is(token_t::e_comma)) @@ -7871,7 +8665,6 @@ namespace exprtk make_error(parser_error::e_syntax, current_token_, "ERR15 - Failed to parse alternative for if-statement")); - return error_node(); } else if (!token_is(token_t::e_rbracket)) @@ -7882,12 +8675,10 @@ namespace exprtk inline expression_node_ptr parse_while_loop() { - //Parse: [while][(][test expr][)][{][expression][}] - expression_node_ptr condition = 0; - expression_node_ptr branch = 0; - + // Parse: [while][(][test expr][)][{][expression][}] + expression_node_ptr condition = error_node(); + expression_node_ptr branch = error_node(); next_token(); - if (!token_is(token_t::e_lbracket)) return error_node(); else if (0 == (condition = parse_expression())) @@ -7896,7 +8687,6 @@ namespace exprtk make_error(parser_error::e_syntax, current_token_, "ERR16 - Failed to parse condition for while-loop")); - return error_node(); } else if (!token_is(token_t::e_rbracket)) @@ -7909,7 +8699,6 @@ namespace exprtk make_error(parser_error::e_syntax, current_token_, "ERR17 - Failed to parse branch for while-loop")); - return error_node(); } else if (!token_is(token_t::e_rcrlbracket)) @@ -7918,29 +8707,23 @@ namespace exprtk return expression_generator_.while_loop(condition,branch); } - template + template struct parse_special_function_impl { static inline expression_node_ptr process(parser& p,const details::operator_type opt_type) { expression_node_ptr branch[NumberOfParameters]; - expression_node_ptr result = 0; - + expression_node_ptr result = error_node(); std::fill_n(branch,NumberOfParameters,reinterpret_cast(0)); - scoped_delete sd(p,branch); - p.next_token(); - if (!p.token_is(token_t::e_lbracket)) { return error_node(); } - for (std::size_t i = 0; i < NumberOfParameters; ++i) { branch[i] = p.parse_expression(); - if (0 == branch[i]) { return p.error_node(); @@ -7958,16 +8741,14 @@ namespace exprtk return p.error_node(); else result = p.expression_generator_.special_function(opt_type,branch); - sd.delete_ptr = false; - return result; } }; inline expression_node_ptr parse_special_function() { - //Expect: $fDD(expr0,expr1,expr2) or $fDD(expr0,expr1,expr2,expr3) + // Expect: $fDD(expr0,expr1,expr2) or $fDD(expr0,expr1,expr2,expr3) if ( !details::is_digit(current_token_.value[2]) || !details::is_digit(current_token_.value[3]) @@ -7977,23 +8758,21 @@ namespace exprtk make_error(parser_error::e_token, current_token_, "ERR18 - Invalid special function[1]: " + current_token_.value)); - return error_node(); } const unsigned int id = (current_token_.value[2] - '0') * 10 + (current_token_.value[3] - '0'); - if (id > 82) + if (id >= details::e_sffinal) { set_error( make_error(parser_error::e_token, current_token_, "ERR19 - Invalid special function[2]: " + current_token_.value)); - return error_node(); } - const std::size_t sf_3_to_4 = details::e_sf35; + const std::size_t sf_3_to_4 = details::e_sf46; const details::operator_type opt_type = details::operator_type(id + 1000); const std::size_t NumberOfParameters = (id < (sf_3_to_4 - 1000)) ? 3 : 4; @@ -8008,56 +8787,46 @@ namespace exprtk inline expression_node_ptr parse_symtab_symbol() { const std::string symbol = current_token_.value; - - //Are we dealing with a variable or a special constant? + // Are we dealing with a variable or a special constant? expression_node_ptr variable = symbol_table_.get_variable(symbol); - if (variable) { if (symbol_name_caching_) { symbol_name_cache_.push_back(symbol); } - if (symbol_table_.is_constant_node(symbol)) { variable = expression_generator_(variable->value()); } - next_token(); - return variable; } #ifndef exprtk_disable_string_capabilities - //Are we dealing with a string variable? + // Are we dealing with a string variable? variable = symbol_table_.get_stringvar(symbol); - if (variable) { if (symbol_name_caching_) { symbol_name_cache_.push_back(symbol); } - if (symbol_table_.is_constant_node(symbol)) { variable = expression_generator_(dynamic_cast*>(variable)->str()); } - next_token(); - return variable; } #endif - //Are we dealing with a function? + // Are we dealing with a function? ifunction* function = symbol_table_.get_function(symbol); if (function) { expression_node_ptr func_node = reinterpret_cast(0); - switch (function->param_count) { case 0 : func_node = expression_generator_.function(function); break; @@ -8086,8 +8855,7 @@ namespace exprtk make_error(parser_error::e_syntax, current_token_, "ERR20 - Invalid number of parameters for function: " + symbol)); - - return expression_node_ptr(0); + return error_node(); } } @@ -8099,7 +8867,6 @@ namespace exprtk make_error(parser_error::e_syntax, current_token_, "ERR21 - Failed to generate node for function: '" + symbol + "'")); - return error_node(); } } @@ -8109,7 +8876,6 @@ namespace exprtk make_error(parser_error::e_syntax, current_token_, "ERR22 - Undefined variable or function: '" + symbol + "'")); - return error_node(); } } @@ -8145,7 +8911,6 @@ namespace exprtk make_error(parser_error::e_symtab, current_token_, "ERR23 - Variable or function detected, yet symbol-table is invalid, Symbol: " + current_token_.value)); - return error_node(); } } @@ -8160,7 +8925,6 @@ namespace exprtk { expression_node_ptr literal_exp = expression_generator_(numeric_value); next_token(); - return literal_exp; } else @@ -8175,7 +8939,6 @@ namespace exprtk { expression_node_ptr literal_exp = expression_generator_(current_token_.value); next_token(); - return literal_exp; } #endif @@ -8223,7 +8986,6 @@ namespace exprtk make_error(parser_error::e_syntax, current_token_, "ERR24 - Premature end of expression.[1]")); - return error_node(); } else @@ -8232,7 +8994,6 @@ namespace exprtk make_error(parser_error::e_syntax, current_token_, "ERR25 - Premature end of expression.[2]")); - return error_node(); } } @@ -8241,17 +9002,8 @@ namespace exprtk { if (current_token_.type != ttype) { - if (!((']' == current_token_.type) && (token_t::e_rbracket == ttype))) - { - set_error( - make_error(parser_error::e_token, - current_token_, - std::string("ERR26 - Expected token: '") + static_cast(ttype) + "'")); - - return false; - } + return false; } - next_token(); return true; } @@ -8262,10 +9014,105 @@ namespace exprtk public: typedef details::expression_node* expression_node_ptr; + typedef expression_node_ptr (*synthesize_functor_t)(expression_generator&, const details::operator_type& operation, expression_node_ptr (&branch)[2]); + typedef std::map synthesize_map_t; + typedef const Type& vtype; + typedef const Type ctype; - inline void set_optimization_level(const optimization_level& optimization_level) + inline void init_synthesize_map() { - optimization_level_ = optimization_level; + synthesize_map_["(v)o(v)"] = synthesize_vov_expression::process; + 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;\ + + register_synthezier(synthesize_vovov_expression0) + register_synthezier(synthesize_vovov_expression1) + register_synthezier(synthesize_vovoc_expression0) + register_synthezier(synthesize_vovoc_expression1) + register_synthezier(synthesize_vocov_expression0) + register_synthezier(synthesize_vocov_expression1) + register_synthezier(synthesize_covov_expression0) + register_synthezier(synthesize_covov_expression1) + register_synthezier(synthesize_covoc_expression0) + register_synthezier(synthesize_covoc_expression1) + register_synthezier(synthesize_cocov_expression1) + register_synthezier(synthesize_vococ_expression0) + + register_synthezier(synthesize_vovovov_expression0) + register_synthezier(synthesize_vovovoc_expression0) + register_synthezier(synthesize_vovocov_expression0) + register_synthezier(synthesize_vocovov_expression0) + register_synthezier(synthesize_covovov_expression0) + register_synthezier(synthesize_covocov_expression0) + register_synthezier(synthesize_vocovoc_expression0) + register_synthezier(synthesize_covovoc_expression0) + register_synthezier(synthesize_vococov_expression0) + + register_synthezier(synthesize_vovovov_expression1) + register_synthezier(synthesize_vovovoc_expression1) + register_synthezier(synthesize_vovocov_expression1) + register_synthezier(synthesize_vocovov_expression1) + register_synthezier(synthesize_covovov_expression1) + register_synthezier(synthesize_covocov_expression1) + register_synthezier(synthesize_vocovoc_expression1) + register_synthezier(synthesize_covovoc_expression1) + register_synthezier(synthesize_vococov_expression1) + + register_synthezier(synthesize_vovovov_expression2) + register_synthezier(synthesize_vovovoc_expression2) + register_synthezier(synthesize_vovocov_expression2) + register_synthezier(synthesize_vocovov_expression2) + register_synthezier(synthesize_covovov_expression2) + register_synthezier(synthesize_covocov_expression2) + register_synthezier(synthesize_vocovoc_expression2) + register_synthezier(synthesize_covovoc_expression2) + + register_synthezier(synthesize_vovovov_expression3) + register_synthezier(synthesize_vovovoc_expression3) + register_synthezier(synthesize_vovocov_expression3) + register_synthezier(synthesize_vocovov_expression3) + register_synthezier(synthesize_covovov_expression3) + register_synthezier(synthesize_covocov_expression3) + register_synthezier(synthesize_vocovoc_expression3) + register_synthezier(synthesize_covovoc_expression3) + register_synthezier(synthesize_vococov_expression3) + + register_synthezier(synthesize_vovovov_expression4) + register_synthezier(synthesize_vovovoc_expression4) + register_synthezier(synthesize_vovocov_expression4) + register_synthezier(synthesize_vocovov_expression4) + register_synthezier(synthesize_covovov_expression4) + register_synthezier(synthesize_covocov_expression4) + register_synthezier(synthesize_vocovoc_expression4) + register_synthezier(synthesize_covovoc_expression4) + } + + inline void set_uom(unary_op_map_t& unary_op_map) + { + unary_op_map_ = &unary_op_map; + } + + inline void set_bom(binary_op_map_t& binary_op_map) + { + binary_op_map_ = &binary_op_map; + } + + inline void set_ibom(inv_binary_op_map_t& inv_binary_op_map) + { + inv_binary_op_map_ = &inv_binary_op_map; + } + + inline void set_sf3m(sf3_map_t& sf3_map) + { + sf3_map_ = &sf3_map; + } + + inline void set_sf4m(sf4_map_t& sf4_map) + { + sf4_map_ = &sf4_map; } inline void set_allocator(details::node_allocator& na) @@ -8273,6 +9120,29 @@ namespace exprtk node_allocator_ = &na; } + inline bool valid_operator(const details::operator_type& operation, binary_functor_t& bop) + { + typename binary_op_map_t::iterator bop_itr = binary_op_map_->find(operation); + if ((*binary_op_map_).end() == bop_itr) + return false; + bop = bop_itr->second; + return true; + } + + inline bool valid_operator(const details::operator_type& operation, unary_functor_t& uop) + { + typename unary_op_map_t::iterator uop_itr = unary_op_map_->find(operation); + if ((*unary_op_map_).end() == uop_itr) + return false; + uop = uop_itr->second; + return true; + } + + inline details::operator_type get_operator(const binary_functor_t& bop) + { + return (*inv_binary_op_map_).find(bop)->second; + } + inline expression_node_ptr operator()(const Type& v) const { return node_allocator_->allocate(v); @@ -8303,6 +9173,46 @@ namespace exprtk (details::e_frac == operation) || (details::e_trunc == operation); } + inline bool sf3_optimizable(const std::string sf3id, trinary_functor_t& tfunc) + { + typename sf3_map_t::iterator itr = sf3_map_->find(sf3id); + if (sf3_map_->end() == itr) + return false; + else + tfunc = itr->second.first; + return true; + } + + inline bool sf4_optimizable(const std::string sf4id, quaternary_functor_t& qfunc) + { + typename sf4_map_t::iterator itr = sf4_map_->find(sf4id); + if (sf4_map_->end() == itr) + return false; + else + qfunc = itr->second.first; + return true; + } + + inline bool sf3_optimizable(const std::string sf3id, details::operator_type& operation) + { + typename sf3_map_t::iterator itr = sf3_map_->find(sf3id); + if (sf3_map_->end() == itr) + return false; + else + operation = itr->second.second; + return true; + } + + inline bool sf4_optimizable(const std::string sf4id, details::operator_type& operation) + { + typename sf4_map_t::iterator itr = sf4_map_->find(sf4id); + if (sf4_map_->end() == itr) + return false; + else + operation = itr->second.second; + return true; + } + inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr (&branch)[1]) { if (0 == branch[0]) @@ -8336,6 +9246,31 @@ namespace exprtk } #endif + inline std::string to_str(const details::operator_type& operation) const + { + switch (operation) + { + case details::e_add : return "+"; + case details::e_sub : return "-"; + case details::e_mul : return "*"; + case details::e_div : return "/"; + case details::e_mod : return "%"; + case details::e_pow : return "^"; + case details::e_lt : return "<"; + case details::e_lte : return "<="; + case details::e_gt : return ">"; + case details::e_gte : return ">="; + case details::e_eq : return "=="; + case details::e_ne : return "!="; + case details::e_and : return "and"; + case details::e_nand : return "nand"; + case details::e_or : return "or"; + case details::e_nor : return "nor"; + case details::e_xor : return "xor"; + default : return "UNKNOWN"; + } + } + inline bool operation_optimizable(const details::operator_type& operation) const { return (details::e_add == operation) || @@ -8344,7 +9279,6 @@ namespace exprtk (details::e_div == operation) || (details::e_mod == operation) || (details::e_pow == operation) || - #ifndef exprtk_disable_extended_operator_optimizations (details::e_lt == operation) || (details::e_lte == operation) || (details::e_gt == operation) || @@ -8356,28 +9290,42 @@ namespace exprtk (details::e_or == operation) || (details::e_nor == operation) || (details::e_xor == operation) || - #endif false; } - inline bool is_level_optimizable(const std::size_t& level = 0) const + inline std::string branch_to_id(expression_node_ptr branch) { - switch (level) - { - case 1 : return (e_level1 == (optimization_level_ & e_level1)); - case 2 : return (e_level2 == (optimization_level_ & e_level2)) && is_level_optimizable(1); - case 3 : return (e_level3 == (optimization_level_ & e_level3)) && is_level_optimizable(2); - case 0 : return (e_all == (optimization_level_ & e_all)); - default : return false; - } + if (details::is_constant_node(branch)) + return "(c)"; + else if (details::is_variable_node(branch)) + return "(v)"; + else if (details::is_vov_node(branch)) + return "(vov)"; + else if (details::is_cov_node(branch)) + return "(cov)"; + else if (details::is_voc_node(branch)) + return "(voc)"; + else if (details::is_string_node(branch)) + return "(s)"; + else if (details::is_const_string_node(branch)) + return "(cs)"; + else if (details::is_t0ot1ot2_node(branch)) + return "(" + dynamic_cast*>(branch)->type_id() + ")"; + else if (details::is_t0ot1ot2ot3_node(branch)) + return "(" + dynamic_cast*>(branch)->type_id() + ")"; + else + return "ERROR"; + } + + inline std::string branch_to_id(expression_node_ptr (&branch)[2]) + { + 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 { if (!operation_optimizable(operation)) return false; - else if (!is_level_optimizable(1)) - return false; else return (details::is_constant_node(branch[0]) && details::is_variable_node(branch[1])); } @@ -8386,8 +9334,6 @@ namespace exprtk { if (!operation_optimizable(operation)) return false; - else if (!is_level_optimizable(1)) - return false; else return (details::is_variable_node(branch[0]) && details::is_constant_node(branch[1])); } @@ -8396,127 +9342,62 @@ namespace exprtk { if (!operation_optimizable(operation)) return false; - else if (!is_level_optimizable(1)) - return false; else return (details::is_variable_node(branch[0]) && details::is_variable_node(branch[1])); } - inline bool vovov1_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const + inline bool cob_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const { if (!operation_optimizable(operation)) return false; - else if (!is_level_optimizable(2)) - return false; else - return (details::is_variable_node(branch[0]) && details::is_vov_node(branch[1])); + return (details::is_constant_node(branch[0]) && !details::is_constant_node(branch[1])); } - inline bool vovov2_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const + inline bool boc_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const { if (!operation_optimizable(operation)) return false; - else if (!is_level_optimizable(2)) - return false; else - return (details::is_vov_node(branch[0]) && details::is_variable_node(branch[1])); - } - - inline bool covov1_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const - { - if (!operation_optimizable(operation)) - return false; - else if (!is_level_optimizable(2)) - return false; - else - return (details::is_constant_node(branch[0]) && details::is_vov_node(branch[1])); - } - - inline bool covov2_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const - { - if (!operation_optimizable(operation)) - return false; - else if (!is_level_optimizable(2)) - return false; - else - return (details::is_cov_node(branch[0]) && details::is_variable_node(branch[1])); - } - - inline bool vovoc1_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const - { - if (!operation_optimizable(operation)) - return false; - else if (!is_level_optimizable(2)) - return false; - else - return (details::is_variable_node(branch[0]) && details::is_voc_node(branch[1])); - } - - inline bool vovoc2_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const - { - if (!operation_optimizable(operation)) - return false; - else if (!is_level_optimizable(2)) - return false; - else - return (details::is_vov_node(branch[0]) && details::is_constant_node(branch[1])); - } - - inline bool covoc1_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const - { - if (!operation_optimizable(operation)) - return false; - else if (!is_level_optimizable(2)) - return false; - else - return (details::is_constant_node(branch[0]) && details::is_voc_node(branch[1])); - } - - inline bool covoc2_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const - { - if (!operation_optimizable(operation)) - return false; - else if (!is_level_optimizable(2)) - return false; - else - return (details::is_cov_node(branch[0]) && details::is_constant_node(branch[1])); - } - - inline bool vocov1_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const - { - if (!operation_optimizable(operation)) - return false; - else if (!is_level_optimizable(2)) - return false; - else - return (details::is_variable_node(branch[0]) && details::is_cov_node(branch[1])); - } - - inline bool vocov2_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const - { - if (!operation_optimizable(operation)) - return false; - else if (!is_level_optimizable(2)) - return false; - else - return (details::is_voc_node(branch[0]) && details::is_variable_node(branch[1])); + return (!details::is_constant_node(branch[0]) && details::is_constant_node(branch[1])); } inline bool uvouv_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const { if (!operation_optimizable(operation)) return false; - else if (!is_level_optimizable(2)) - 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 + { + if (!operation_optimizable(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 + { + if (!operation_optimizable(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 + { + if (!operation_optimizable(operation)) + return false; + else + return (!details::is_constant_node(branch[0]) || !details::is_constant_node(branch[1])); + } + inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[2]) { const bool b0_string = details::is_string_node(branch[0]) || details::is_const_string_node(branch[0]); const bool b1_string = details::is_string_node(branch[1]) || details::is_const_string_node(branch[1]); - if ((b0_string || b1_string) && !(b0_string && b1_string)) return true; if (!valid_string_operation(operation) && b0_string && b1_string) @@ -8527,10 +9408,9 @@ namespace exprtk inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[3]) { - bool b0_string = details::is_string_node(branch[0]) || details::is_const_string_node(branch[0]); - bool b1_string = details::is_string_node(branch[1]) || details::is_const_string_node(branch[1]); - bool b2_string = details::is_string_node(branch[2]) || details::is_const_string_node(branch[2]); - + const bool b0_string = details::is_string_node(branch[0]) || details::is_const_string_node(branch[0]); + const bool b1_string = details::is_string_node(branch[1]) || details::is_const_string_node(branch[1]); + const bool b2_string = details::is_string_node(branch[2]) || details::is_const_string_node(branch[2]); if ((b0_string || b1_string || b2_string) && !(b0_string && b1_string && b2_string)) return true; if ((details::e_inrange != operation) && b0_string && b1_string && b2_string) @@ -8543,7 +9423,6 @@ namespace exprtk { const bool b0_string = details::is_string_node(branch[0]) || details::is_const_string_node(branch[0]); const bool b1_string = details::is_string_node(branch[1]) || details::is_const_string_node(branch[1]); - return (b0_string && b1_string && valid_string_operation(operation)); } @@ -8552,79 +9431,40 @@ namespace exprtk const bool b0_string = details::is_string_node(branch[0]) || details::is_const_string_node(branch[0]); const bool b1_string = details::is_string_node(branch[1]) || details::is_const_string_node(branch[1]); const bool b2_string = details::is_string_node(branch[2]) || details::is_const_string_node(branch[2]); - return (b0_string && b1_string && b2_string && (details::e_inrange == operation)); } - // Note: Extended Optimisations - // When using older C++ compilers due to the large number of type instantiations - // required by the extended optimisations the compiler may crash or not be able - // to compile this translation unit properly. - #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) - #if (defined(_MSC_VER) && (_MSC_VER <= 1400)) - #ifndef exprtk_disable_extended_optimisations - #define exprtk_disable_extended_optimisations - #endif - #endif - #endif - - #ifndef exprtk_disable_extended_optimisations - inline bool vovovov_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const - { - if (!operation_optimizable(operation)) - return false; - else if (!is_level_optimizable(3)) - return false; - else - return (details::is_vov_node(branch[0]) && details::is_vov_node(branch[1])); - } - #else - inline bool vovovov_optimizable(const details::operator_type&, expression_node_ptr (&)[2]) const - { - return false; - } - #endif - inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr (&branch)[2]) { if ((0 == branch[0]) || (0 == branch[1])) + { + if (0 != branch[0]) node_allocator_->free(branch[0]); + if (0 != branch[1]) node_allocator_->free(branch[1]); return error_node(); + } else if (is_invalid_string_op(operation,branch)) return error_node(); else if (details::e_assign == operation) return synthesize_assignment_expression(operation,branch); else if (is_string_operation(operation,branch)) return synthesize_string_expression(operation,branch); - else if (cov_optimizable(operation,branch)) - return synthesize_cov_expression(operation,branch); - else if (voc_optimizable(operation,branch)) - return synthesize_voc_expression(operation,branch); - else if (vov_optimizable(operation,branch)) - return synthesize_vov_expression(operation,branch); - else if (vovov1_optimizable(operation,branch)) - return synthesize_vovov1_expression(operation,branch); - else if (vovov2_optimizable(operation,branch)) - return synthesize_vovov2_expression(operation,branch); - else if (covov1_optimizable(operation,branch)) - return synthesize_covov1_expression(operation,branch); - else if (covov2_optimizable(operation,branch)) - return synthesize_covov2_expression(operation,branch); - else if (vovoc1_optimizable(operation,branch)) - return synthesize_vovoc1_expression(operation,branch); - else if (vovoc2_optimizable(operation,branch)) - return synthesize_vovoc2_expression(operation,branch); - else if (covoc1_optimizable(operation,branch)) - return synthesize_covoc1_expression(operation,branch); - else if (covoc2_optimizable(operation,branch)) - return synthesize_covoc2_expression(operation,branch); - else if (vocov1_optimizable(operation,branch)) - return synthesize_vocov1_expression(operation,branch); - else if (vocov2_optimizable(operation,branch)) - return synthesize_vocov2_expression(operation,branch); - else if (vovovov_optimizable(operation,branch)) - return synthesize_vovovov_expression(operation,branch); + expression_node_ptr result = error_node(); + if (synthesize_expression(operation,branch,result)) + return result; else if (uvouv_optimizable(operation,branch)) return synthesize_uvouv_expression(operation,branch); + else if (vob_optimizable(operation,branch)) + return synthesize_vob_expression::process(*this,operation,branch); + else if (bov_optimizable(operation,branch)) + return synthesize_bov_expression::process(*this,operation,branch); + else if (cob_optimizable(operation,branch)) + return synthesize_cob_expression::process(*this,operation,branch); + else if (boc_optimizable(operation,branch)) + return synthesize_boc_expression::process(*this,operation,branch); + else if (cov_optimizable(operation,branch)) + return synthesize_cov_expression::process(*this,operation,branch); + else if (binext_optimizable(operation,branch)) + return synthesize_binary_ext_expression::process(*this,operation,branch); else return synthesize_expression(operation,branch); } @@ -8632,7 +9472,12 @@ namespace exprtk inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr (&branch)[3]) { if ((0 == branch[0]) || (0 == branch[1]) || (0 == branch[2])) + { + if (0 != branch[0]) node_allocator_->free(branch[0]); + if (0 != branch[1]) node_allocator_->free(branch[1]); + if (0 != branch[2]) node_allocator_->free(branch[2]); return error_node(); + } else if (is_invalid_string_op(operation,branch)) return error_node(); else if (is_string_operation(operation,branch)) @@ -8665,7 +9510,11 @@ namespace exprtk inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr b0, expression_node_ptr b1) { if ((0 == b0) || (0 == b1)) + { + if (0 != b0) node_allocator_->free(b0); + if (0 != b1) node_allocator_->free(b1); return error_node(); + } else { expression_node_ptr branch[2] = { b0, b1 }; @@ -8678,8 +9527,13 @@ namespace exprtk expression_node_ptr alternative) const { if ((0 == condition) || (0 == consequent) || (0 == alternative)) + { + if (0 != condition ) node_allocator_->free(condition ); + if (0 != consequent ) node_allocator_->free(consequent ); + if (0 != alternative) node_allocator_->free(alternative); return error_node(); - //Can the condition be immediately evaluated? if so optimize. + } + // Can the condition be immediately evaluated? if so optimize. else if (details::is_constant_node(condition)) { // True branch @@ -8744,7 +9598,6 @@ namespace exprtk inline expression_node_ptr synthesize_uv_expression(const details::operator_type& operation, expression_node_ptr (&branch)[1]) { T& v = dynamic_cast*>(branch[0])->ref(); - switch (operation) { #define case_stmt(op0,op1) case op0 : return node_allocator_->allocate > >(v); @@ -8768,7 +9621,6 @@ namespace exprtk inline expression_node_ptr const_optimize_sf3(const details::operator_type& operation, expression_node_ptr (&branch)[3]) { expression_node_ptr temp_node = error_node(); - switch (operation) { #define case_stmt(op0,op1) case op0 : temp_node = node_allocator_->allocate > >(operation,branch); break; @@ -8807,22 +9659,30 @@ namespace exprtk case_stmt(details::e_sf32,details::sf32_op) case_stmt(details::e_sf33,details::sf33_op) case_stmt(details::e_sf34,details::sf34_op) + case_stmt(details::e_sf35,details::sf35_op) + case_stmt(details::e_sf36,details::sf36_op) + case_stmt(details::e_sf37,details::sf37_op) + case_stmt(details::e_sf38,details::sf38_op) + case_stmt(details::e_sf39,details::sf39_op) + 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) #undef case_stmt default : return error_node(); } - T v = temp_node->value(); node_allocator_->free(temp_node); - return node_allocator_->allocate(v); } inline expression_node_ptr varnode_optimize_sf3(const details::operator_type& operation, expression_node_ptr (&branch)[3]) { - Type& v0 = dynamic_cast*>(branch[0])->ref(); - Type& v1 = dynamic_cast*>(branch[1])->ref(); - Type& v2 = dynamic_cast*>(branch[2])->ref(); - + const Type& v0 = dynamic_cast*>(branch[0])->ref(); + const Type& v1 = dynamic_cast*>(branch[1])->ref(); + 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); @@ -8861,6 +9721,17 @@ namespace exprtk case_stmt(details::e_sf32,details::sf32_op) case_stmt(details::e_sf33,details::sf33_op) case_stmt(details::e_sf34,details::sf34_op) + case_stmt(details::e_sf35,details::sf35_op) + case_stmt(details::e_sf36,details::sf36_op) + case_stmt(details::e_sf37,details::sf37_op) + case_stmt(details::e_sf38,details::sf38_op) + case_stmt(details::e_sf39,details::sf39_op) + 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) #undef case_stmt default : return error_node(); } @@ -8913,6 +9784,17 @@ namespace exprtk case_stmt(details::e_sf32,details::sf32_op) case_stmt(details::e_sf33,details::sf33_op) case_stmt(details::e_sf34,details::sf34_op) + case_stmt(details::e_sf35,details::sf35_op) + case_stmt(details::e_sf36,details::sf36_op) + case_stmt(details::e_sf37,details::sf37_op) + case_stmt(details::e_sf38,details::sf38_op) + case_stmt(details::e_sf39,details::sf39_op) + 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) #undef case_stmt default : return error_node(); } @@ -8921,21 +9803,9 @@ namespace exprtk inline expression_node_ptr const_optimize_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4]) { expression_node_ptr temp_node = error_node(); - switch (operation) { #define case_stmt(op0,op1) case op0 : temp_node = node_allocator_->allocate > >(operation,branch); break; - case_stmt(details::e_sf35,details::sf35_op) - case_stmt(details::e_sf36,details::sf36_op) - case_stmt(details::e_sf37,details::sf37_op) - case_stmt(details::e_sf38,details::sf38_op) - case_stmt(details::e_sf39,details::sf39_op) - 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) @@ -8973,37 +9843,38 @@ namespace exprtk case_stmt(details::e_sf80,details::sf80_op) case_stmt(details::e_sf81,details::sf81_op) case_stmt(details::e_sf82,details::sf82_op) + case_stmt(details::e_sf83,details::sf83_op) + case_stmt(details::e_sf84,details::sf84_op) + case_stmt(details::e_sf85,details::sf85_op) + case_stmt(details::e_sf86,details::sf86_op) + case_stmt(details::e_sf87,details::sf87_op) + case_stmt(details::e_sf88,details::sf88_op) + case_stmt(details::e_sf89,details::sf89_op) + case_stmt(details::e_sf90,details::sf90_op) + case_stmt(details::e_sf91,details::sf91_op) + case_stmt(details::e_sf92,details::sf92_op) + case_stmt(details::e_sf93,details::sf93_op) + case_stmt(details::e_sf94,details::sf94_op) + case_stmt(details::e_sf95,details::sf95_op) + case_stmt(details::e_sf96,details::sf96_op) + case_stmt(details::e_sf97,details::sf97_op) #undef case_stmt default : return error_node(); } - T v = temp_node->value(); node_allocator_->free(temp_node); - return node_allocator_->allocate(v); } inline expression_node_ptr varnode_optimize_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4]) { - Type& v0 = dynamic_cast*>(branch[0])->ref(); - Type& v1 = dynamic_cast*>(branch[1])->ref(); - Type& v2 = dynamic_cast*>(branch[2])->ref(); - Type& v3 = dynamic_cast*>(branch[3])->ref(); - + const Type& v0 = dynamic_cast*>(branch[0])->ref(); + const Type& v1 = dynamic_cast*>(branch[1])->ref(); + const Type& v2 = dynamic_cast*>(branch[2])->ref(); + 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); - case_stmt(details::e_sf35,details::sf35_op) - case_stmt(details::e_sf36,details::sf36_op) - case_stmt(details::e_sf37,details::sf37_op) - case_stmt(details::e_sf38,details::sf38_op) - case_stmt(details::e_sf39,details::sf39_op) - 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) @@ -9041,6 +9912,21 @@ namespace exprtk case_stmt(details::e_sf80,details::sf80_op) case_stmt(details::e_sf81,details::sf81_op) case_stmt(details::e_sf82,details::sf82_op) + case_stmt(details::e_sf83,details::sf83_op) + case_stmt(details::e_sf84,details::sf84_op) + case_stmt(details::e_sf85,details::sf85_op) + case_stmt(details::e_sf86,details::sf86_op) + case_stmt(details::e_sf87,details::sf87_op) + case_stmt(details::e_sf88,details::sf88_op) + case_stmt(details::e_sf89,details::sf89_op) + case_stmt(details::e_sf90,details::sf90_op) + case_stmt(details::e_sf91,details::sf91_op) + case_stmt(details::e_sf92,details::sf92_op) + case_stmt(details::e_sf93,details::sf93_op) + case_stmt(details::e_sf94,details::sf94_op) + case_stmt(details::e_sf95,details::sf95_op) + case_stmt(details::e_sf96,details::sf96_op) + case_stmt(details::e_sf97,details::sf97_op) #undef case_stmt default : return error_node(); } @@ -9057,17 +9943,6 @@ namespace exprtk switch (operation) { #define case_stmt(op0,op1) case op0 : return node_allocator_->allocate > >(operation,branch); - case_stmt(details::e_sf35,details::sf35_op) - case_stmt(details::e_sf36,details::sf36_op) - case_stmt(details::e_sf37,details::sf37_op) - case_stmt(details::e_sf38,details::sf38_op) - case_stmt(details::e_sf39,details::sf39_op) - 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) @@ -9105,6 +9980,21 @@ namespace exprtk case_stmt(details::e_sf80,details::sf80_op) case_stmt(details::e_sf81,details::sf81_op) case_stmt(details::e_sf82,details::sf82_op) + case_stmt(details::e_sf83,details::sf83_op) + case_stmt(details::e_sf84,details::sf84_op) + case_stmt(details::e_sf85,details::sf85_op) + case_stmt(details::e_sf86,details::sf86_op) + case_stmt(details::e_sf87,details::sf87_op) + case_stmt(details::e_sf88,details::sf88_op) + case_stmt(details::e_sf89,details::sf89_op) + case_stmt(details::e_sf90,details::sf90_op) + case_stmt(details::e_sf91,details::sf91_op) + case_stmt(details::e_sf92,details::sf92_op) + case_stmt(details::e_sf93,details::sf93_op) + case_stmt(details::e_sf94,details::sf94_op) + case_stmt(details::e_sf95,details::sf95_op) + case_stmt(details::e_sf96,details::sf96_op) + case_stmt(details::e_sf97,details::sf97_op) #undef case_stmt default : return error_node(); } @@ -9114,14 +10004,12 @@ namespace exprtk inline expression_node_ptr function(ifunction_t* f, expression_node_ptr (&b)[N]) { 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 { - //has the function call been completely optimized? + // Has the function call been completely optimized? if (details::is_constant_node(result)) return result; else if (!all_nodes_valid(b)) @@ -9159,7 +10047,6 @@ namespace exprtk else if (!details::is_constant_node(b[i])) return false; } - return true; } @@ -9170,7 +10057,6 @@ namespace exprtk { if (0 == b[i]) return false; } - return true; } @@ -9187,6 +10073,18 @@ namespace exprtk return true; } + template + inline void free_all_nodes(NodeAllocator& node_allocator, expression_node_ptr (&b)[N]) const + { + for (std::size_t i = 0; i < N; ++i) + { + if (0 != b[i]) + { + node_allocator.free(b[i]); + } + } + } + inline expression_node_ptr synthesize_assignment_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2]) { if (details::is_variable_node(branch[0])) @@ -9216,29 +10114,9 @@ namespace exprtk case_stmt(details:: e_nor,details:: nor_op) \ case_stmt(details:: e_xor,details:: xor_op) \ - inline expression_node_ptr synthesize_cov_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2]) - { - T c = dynamic_cast* >(branch[0])->value(); - T& v = dynamic_cast*>(branch[1])->ref(); - - node_allocator_->free(branch[0]); - - switch (operation) - { - #define case_stmt(op0,op1) case op0 : return node_allocator_->allocate_cr > >(c,v); - basic_opr_switch_statements - #ifndef exprtk_disable_extended_operator_optimizations - extended_opr_switch_statements - #endif - #undef case_stmt - default : return error_node(); - } - } - #ifndef exprtk_disable_cardinal_pow_optimisation - template