src/UnityOncoSimul/exprtk.h
 4068375e ``` /* ****************************************************************** * C++ Mathematical Expression Toolkit Library * * * ``` a65c8e8b ``` * Author: Arash Partow (1999-2022) * * URL: https://www.partow.net/programming/exprtk/index.html * ``` 4068375e ``` * * * Copyright notice: * * Free use of the C++ Mathematical Expression Toolkit Library is * * permitted under the guidelines and in accordance with the most * * current version of the MIT License. * ``` a65c8e8b ``` * https://www.opensource.org/licenses/MIT * ``` 4068375e ``` * * * Example expressions: * * (00) (y + x / y) * (x - y / x) * * (01) (x^2 / sin(2 * pi / y)) - x / 2 * * (02) sqrt(1 - (x^2)) * * (03) 1 - sin(2 * x) + cos(pi / y) * * (04) a * exp(2 * t) + c * * (05) if(((x + 2) == 3) and ((y + 5) <= 9),1 + w, 2 / z) * * (06) (avg(x,y) <= x + y ? x - y : x * y) + 2 * pi / x * * (07) z := x + sin(2 * pi / y) * * (08) u := 2 * (pi * z) / (w := x + cos(y / pi)) * * (09) clamp(-1,sin(2 * pi * x) + cos(y / 2 * pi),+1) * * (10) inrange(-2,m,+2) == if(({-2 <= m} and [m <= +2]),1,0) * * (11) (2sin(x)cos(2y)7 + 1) == (2 * sin(x) * cos(2*y) * 7 + 1) * * (12) (x ilike 's*ri?g') and [y < (3 z^7 + w)] * * * ****************************************************************** */ #ifndef INCLUDE_EXPRTK_HPP #define INCLUDE_EXPRTK_HPP #include ``` a65c8e8b ``` #include ``` 4068375e ``` #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace exprtk { #ifdef exprtk_enable_debugging #define exprtk_debug(params) printf params #else #define exprtk_debug(params) (void)0 #endif #define exprtk_error_location \ "exprtk.hpp:" + details::to_str(__LINE__) \ #if defined(__GNUC__) && (__GNUC__ >= 7) #define exprtk_disable_fallthrough_begin \ _Pragma ("GCC diagnostic push") \ _Pragma ("GCC diagnostic ignored \"-Wimplicit-fallthrough\"") \ #define exprtk_disable_fallthrough_end \ _Pragma ("GCC diagnostic pop") \ #else #define exprtk_disable_fallthrough_begin (void)0; #define exprtk_disable_fallthrough_end (void)0; #endif ``` a65c8e8b ``` #if __cplusplus >= 201103L #define exprtk_override override #define exprtk_final final #define exprtk_delete = delete #else #define exprtk_override #define exprtk_final #define exprtk_delete #endif ``` 4068375e ``` namespace details { ``` a65c8e8b ``` typedef char char_t; typedef char_t* char_ptr; ``` 4068375e ``` typedef char_t const* char_cptr; ``` a65c8e8b ``` typedef unsigned char uchar_t; typedef uchar_t* uchar_ptr; typedef uchar_t const* uchar_cptr; ``` 4068375e ``` typedef unsigned long long int _uint64_t; ``` a65c8e8b ``` typedef long long int _int64_t; ``` 4068375e ``` inline bool is_whitespace(const char_t c) { return (' ' == c) || ('\n' == c) || ('\r' == c) || ('\t' == c) || ('\b' == c) || ('\v' == c) || ('\f' == c) ; } inline bool is_operator_char(const char_t c) { return ('+' == c) || ('-' == c) || ('*' == c) || ('/' == c) || ('^' == c) || ('<' == c) || ('>' == c) || ('=' == c) || (',' == c) || ('!' == c) || ('(' == c) || (')' == c) || ('[' == c) || (']' == c) || ('{' == c) || ('}' == c) || ('%' == c) || (':' == c) || ('?' == c) || ('&' == c) || ('|' == c) || (';' == c) ; } inline bool is_letter(const char_t c) { return (('a' <= c) && (c <= 'z')) || (('A' <= c) && (c <= 'Z')) ; } inline bool is_digit(const char_t c) { return ('0' <= c) && (c <= '9'); } inline bool is_letter_or_digit(const char_t c) { return is_letter(c) || is_digit(c); } inline bool is_left_bracket(const char_t c) { return ('(' == c) || ('[' == c) || ('{' == c); } inline bool is_right_bracket(const char_t c) { return (')' == c) || (']' == c) || ('}' == c); } inline bool is_bracket(const char_t c) { return is_left_bracket(c) || is_right_bracket(c); } inline bool is_sign(const char_t c) { return ('+' == c) || ('-' == c); } inline bool is_invalid(const char_t c) { return !is_whitespace (c) && !is_operator_char(c) && !is_letter (c) && !is_digit (c) && ('.' != c) && ('_' != c) && ('\$' != c) && ('~' != c) && ('\'' != c); } inline bool is_valid_string_char(const char_t c) { ``` a65c8e8b ``` return std::isprint(static_cast(c)) || ``` 4068375e ``` is_whitespace(c); } #ifndef exprtk_disable_caseinsensitivity inline void case_normalise(std::string& s) { for (std::size_t i = 0; i < s.size(); ++i) { s[i] = static_cast(std::tolower(s[i])); } } inline bool imatch(const char_t c1, const char_t c2) { return std::tolower(c1) == std::tolower(c2); } inline bool imatch(const std::string& s1, const std::string& s2) { if (s1.size() == s2.size()) { for (std::size_t i = 0; i < s1.size(); ++i) { if (std::tolower(s1[i]) != std::tolower(s2[i])) { return false; } } return true; } return false; } 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) { ``` a65c8e8b ``` const char_t c1 = static_cast(std::tolower(s1[i])); const char_t c2 = static_cast(std::tolower(s2[i])); ``` 4068375e ``` if (c1 > c2) return false; else if (c1 < c2) return true; } return s1.size() < s2.size(); } }; #else inline void case_normalise(std::string&) {} inline bool imatch(const char_t c1, const char_t c2) { return c1 == c2; } inline bool imatch(const std::string& s1, const std::string& s2) { return s1 == s2; } struct ilesscompare { inline bool operator() (const std::string& s1, const std::string& s2) const { return s1 < s2; } }; #endif inline bool is_valid_sf_symbol(const std::string& symbol) { // Special function: \$f12 or \$F34 return (4 == symbol.size()) && ('\$' == symbol[0]) && imatch('f',symbol[1]) && is_digit(symbol[2]) && is_digit(symbol[3]); } inline const char_t& front(const std::string& s) { return s[0]; } inline const char_t& back(const std::string& s) { return s[s.size() - 1]; } inline std::string to_str(int i) { if (0 == i) return std::string("0"); std::string result; ``` a65c8e8b ``` const int sign = (i < 0) ? -1 : 1; ``` 4068375e ``` ``` a65c8e8b ``` for ( ; i; i /= 10) { result += '0' + static_cast(sign * (i % 10)); ``` 4068375e ``` } ``` a65c8e8b ``` if (sign < 0) ``` 4068375e ``` { ``` a65c8e8b ``` result += '-'; ``` 4068375e ``` } std::reverse(result.begin(), result.end()); ``` a65c8e8b ``` ``` 4068375e ``` return result; } inline std::string to_str(std::size_t i) { return to_str(static_cast(i)); } ``` a65c8e8b ``` inline bool is_hex_digit(const uchar_t digit) ``` 4068375e ``` { return (('0' <= digit) && (digit <= '9')) || (('A' <= digit) && (digit <= 'F')) || (('a' <= digit) && (digit <= 'f')) ; } inline uchar_t hex_to_bin(uchar_t h) { if (('0' <= h) && (h <= '9')) return (h - '0'); else ``` a65c8e8b ``` return static_cast(std::toupper(h) - 'A'); ``` 4068375e ``` } template inline bool parse_hex(Iterator& itr, Iterator end, ``` a65c8e8b ``` char_t& result) ``` 4068375e ``` { if ( (end == (itr )) || (end == (itr + 1)) || (end == (itr + 2)) || (end == (itr + 3)) || ('0' != *(itr )) || ('X' != std::toupper(*(itr + 1))) || (!is_hex_digit(*(itr + 2))) || (!is_hex_digit(*(itr + 3))) ) { return false; } result = hex_to_bin(static_cast(*(itr + 2))) << 4 | hex_to_bin(static_cast(*(itr + 3))) ; return true; } inline bool cleanup_escapes(std::string& s) { typedef std::string::iterator str_itr_t; str_itr_t itr1 = s.begin(); str_itr_t itr2 = s.begin(); str_itr_t end = s.end (); std::size_t removal_count = 0; while (end != itr1) { if ('\\' == (*itr1)) { if (end == ++itr1) { return false; } else if (parse_hex(itr1, end, *itr2)) { itr1+= 4; itr2+= 1; removal_count +=4; } else if ('a' == (*itr1)) { (*itr2++) = '\a'; ++itr1; ++removal_count; } else if ('b' == (*itr1)) { (*itr2++) = '\b'; ++itr1; ++removal_count; } else if ('f' == (*itr1)) { (*itr2++) = '\f'; ++itr1; ++removal_count; } else if ('n' == (*itr1)) { (*itr2++) = '\n'; ++itr1; ++removal_count; } else if ('r' == (*itr1)) { (*itr2++) = '\r'; ++itr1; ++removal_count; } else if ('t' == (*itr1)) { (*itr2++) = '\t'; ++itr1; ++removal_count; } else if ('v' == (*itr1)) { (*itr2++) = '\v'; ++itr1; ++removal_count; } else if ('0' == (*itr1)) { (*itr2++) = '\0'; ++itr1; ++removal_count; } else { (*itr2++) = (*itr1++); ++removal_count; } continue; } else (*itr2++) = (*itr1++); } if ((removal_count > s.size()) || (0 == removal_count)) return false; s.resize(s.size() - removal_count); return true; } 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 build_string& operator << (char_cptr s) { data_ += std::string(s); return (*this); } inline operator std::string () const { return data_; } inline std::string as_string() const { return data_; } private: std::string data_; }; static const std::string reserved_words[] = { "break", "case", "continue", "default", "false", "for", "if", "else", "ilike", "in", "like", "and", "nand", "nor", "not", "null", "or", "repeat", "return", "shl", "shr", "swap", "switch", "true", "until", "var", "while", "xnor", "xor", "&", "|" }; static const std::size_t reserved_words_size = sizeof(reserved_words) / sizeof(std::string); static const std::string reserved_symbols[] = { "abs", "acos", "acosh", "and", "asin", "asinh", "atan", "atanh", "atan2", "avg", "break", "case", "ceil", "clamp", "continue", "cos", "cosh", "cot", "csc", "default", "deg2grad", "deg2rad", "equal", "erf", "erfc", "exp", "expm1", "false", "floor", "for", "frac", "grad2deg", "hypot", "iclamp", "if", "else", "ilike", "in", "inrange", "like", "log", "log10", "log2", "logn", "log1p", "mand", "max", "min", "mod", "mor", "mul", "ncdf", "nand", "nor", "not", "not_equal", "null", "or", "pow", "rad2deg", "repeat", "return", "root", "round", "roundn", "sec", "sgn", "shl", "shr", "sin", "sinc", "sinh", "sqrt", "sum", "swap", "switch", "tan", "tanh", "true", "trunc", "until", "var", "while", "xnor", "xor", "&", "|" }; static const std::size_t reserved_symbols_size = sizeof(reserved_symbols) / sizeof(std::string); static const std::string base_function_list[] = { "abs", "acos", "acosh", "asin", "asinh", "atan", "atanh", "atan2", "avg", "ceil", "clamp", "cos", "cosh", "cot", "csc", "equal", "erf", "erfc", "exp", "expm1", "floor", "frac", "hypot", "iclamp", "like", "log", "log10", "log2", "logn", "log1p", "mand", "max", "min", "mod", "mor", "mul", "ncdf", "pow", "root", "round", "roundn", "sec", "sgn", "sin", "sinc", "sinh", "sqrt", "sum", "swap", "tan", "tanh", "trunc", "not_equal", "inrange", "deg2grad", "deg2rad", "rad2deg", "grad2deg" }; static const std::size_t base_function_list_size = sizeof(base_function_list) / sizeof(std::string); static const std::string logic_ops_list[] = { "and", "nand", "nor", "not", "or", "xnor", "xor", "&", "|" }; static const std::size_t logic_ops_list_size = sizeof(logic_ops_list) / sizeof(std::string); static const std::string cntrl_struct_list[] = { "if", "switch", "for", "while", "repeat", "return" }; static const std::size_t cntrl_struct_list_size = sizeof(cntrl_struct_list) / sizeof(std::string); static const std::string arithmetic_ops_list[] = { "+", "-", "*", "/", "%", "^" }; static const std::size_t arithmetic_ops_list_size = sizeof(arithmetic_ops_list) / sizeof(std::string); static const std::string assignment_ops_list[] = { ":=", "+=", "-=", "*=", "/=", "%=" }; static const std::size_t assignment_ops_list_size = sizeof(assignment_ops_list) / sizeof(std::string); static const std::string inequality_ops_list[] = { "<", "<=", "==", "=", "!=", "<>", ">=", ">" }; static const std::size_t inequality_ops_list_size = sizeof(inequality_ops_list) / sizeof(std::string); inline bool is_reserved_word(const std::string& symbol) { for (std::size_t i = 0; i < reserved_words_size; ++i) { if (imatch(symbol, reserved_words[i])) { return true; } } return false; } inline bool is_reserved_symbol(const std::string& symbol) { for (std::size_t i = 0; i < reserved_symbols_size; ++i) { if (imatch(symbol, reserved_symbols[i])) { return true; } } return false; } inline bool is_base_function(const std::string& function_name) { for (std::size_t i = 0; i < base_function_list_size; ++i) { if (imatch(function_name, base_function_list[i])) { return true; } } return false; } inline bool is_control_struct(const std::string& cntrl_strct) { for (std::size_t i = 0; i < cntrl_struct_list_size; ++i) { if (imatch(cntrl_strct, cntrl_struct_list[i])) { return true; } } return false; } inline bool is_logic_opr(const std::string& lgc_opr) { for (std::size_t i = 0; i < logic_ops_list_size; ++i) { if (imatch(lgc_opr, logic_ops_list[i])) { return true; } } return false; } struct cs_match { static inline bool cmp(const char_t c0, const char_t c1) { return (c0 == c1); } }; struct cis_match { static inline bool cmp(const char_t c0, const char_t c1) { return (std::tolower(c0) == std::tolower(c1)); } }; template inline bool match_impl(const Iterator pattern_begin, const Iterator pattern_end , const Iterator data_begin , const Iterator data_end , const typename std::iterator_traits::value_type& zero_or_more, ``` a65c8e8b ``` const typename std::iterator_traits::value_type& exactly_one ) ``` 4068375e ``` { const Iterator null_itr(0); ``` a65c8e8b ``` Iterator p_itr = pattern_begin; Iterator d_itr = data_begin; Iterator np_itr = null_itr; Iterator nd_itr = null_itr; ``` 4068375e ``` ``` a65c8e8b ``` for ( ; ; ) ``` 4068375e ``` { ``` a65c8e8b ``` const bool pvalid = p_itr != pattern_end; const bool dvalid = d_itr != data_end; ``` 4068375e ``` ``` a65c8e8b ``` if (!pvalid && !dvalid) break; ``` 4068375e ``` ``` a65c8e8b ``` if (pvalid) { ``` 4068375e ``` const typename std::iterator_traits::value_type c = *(p_itr); ``` a65c8e8b ``` if (zero_or_more == c) { np_itr = p_itr; nd_itr = d_itr + 1; ++p_itr; continue; } else if (dvalid && ((exactly_one == c) || Compare::cmp(c,*(d_itr)))) ``` 4068375e ``` { ``` a65c8e8b ``` ++p_itr; ``` 4068375e ``` ++d_itr; ``` a65c8e8b ``` continue; ``` 4068375e ``` } } ``` a65c8e8b ``` if ((null_itr != nd_itr) && (nd_itr <= data_end)) { p_itr = np_itr; d_itr = nd_itr; ``` 4068375e ``` continue; } ``` a65c8e8b ``` return false; ``` 4068375e ``` } ``` a65c8e8b ``` return true; ``` 4068375e ``` } inline bool wc_match(const std::string& wild_card, const std::string& str) { ``` a65c8e8b ``` return match_impl( wild_card.data(), wild_card.data() + wild_card.size(), str.data(), str.data() + str.size(), '*', '?'); ``` 4068375e ``` } inline bool wc_imatch(const std::string& wild_card, const std::string& str) { ``` a65c8e8b ``` return match_impl( wild_card.data(), wild_card.data() + wild_card.size(), str.data(), str.data() + str.size(), '*', '?'); ``` 4068375e ``` } inline bool sequence_match(const std::string& pattern, const std::string& str, std::size_t& diff_index, char_t& diff_value) { if (str.empty()) { return ("Z" == pattern); } else if ('*' == pattern[0]) return false; typedef std::string::const_iterator itr_t; itr_t p_itr = pattern.begin(); itr_t s_itr = str .begin(); ``` a65c8e8b ``` const itr_t p_end = pattern.end(); const itr_t s_end = str .end(); ``` 4068375e ``` while ((s_end != s_itr) && (p_end != p_itr)) { if ('*' == (*p_itr)) { ``` a65c8e8b ``` const char_t target = static_cast(std::toupper(*(p_itr - 1))); ``` 4068375e ``` if ('*' == target) { diff_index = static_cast(std::distance(str.begin(),s_itr)); ``` a65c8e8b ``` diff_value = static_cast(std::toupper(*p_itr)); ``` 4068375e ``` return false; } else ++p_itr; while (s_itr != s_end) { if (target != std::toupper(*s_itr)) break; else ++s_itr; } continue; } else if ( ('?' != *p_itr) && std::toupper(*p_itr) != std::toupper(*s_itr) ) { diff_index = static_cast(std::distance(str.begin(),s_itr)); ``` a65c8e8b ``` diff_value = static_cast(std::toupper(*p_itr)); ``` 4068375e ``` return false; } ++p_itr; ++s_itr; } return ( (s_end == s_itr) && ( (p_end == p_itr) || ('*' == *p_itr) ) ); } static const double pow10[] = { 1.0, 1.0E+001, 1.0E+002, 1.0E+003, 1.0E+004, 1.0E+005, 1.0E+006, 1.0E+007, 1.0E+008, 1.0E+009, 1.0E+010, 1.0E+011, 1.0E+012, 1.0E+013, 1.0E+014, 1.0E+015, 1.0E+016 }; static const std::size_t pow10_size = sizeof(pow10) / sizeof(double); namespace numeric { namespace constant { static const double e = 2.71828182845904523536028747135266249775724709369996; static const double pi = 3.14159265358979323846264338327950288419716939937510; static const double pi_2 = 1.57079632679489661923132169163975144209858469968755; static const double pi_4 = 0.78539816339744830961566084581987572104929234984378; static const double pi_180 = 0.01745329251994329576923690768488612713442871888542; static const double _1_pi = 0.31830988618379067153776752674502872406891929148091; static const double _2_pi = 0.63661977236758134307553505349005744813783858296183; static const double _180_pi = 57.29577951308232087679815481410517033240547246656443; static const double log2 = 0.69314718055994530941723212145817656807550013436026; static const double sqrt2 = 1.41421356237309504880168872420969807856967187537695; } namespace details { struct unknown_type_tag { unknown_type_tag() {} }; struct real_type_tag { real_type_tag () {} }; struct complex_type_tag { complex_type_tag() {} }; struct int_type_tag { int_type_tag () {} }; template struct number_type { typedef unknown_type_tag type; number_type() {} }; #define exprtk_register_real_type_tag(T) \ ``` a65c8e8b ``` template <> struct number_type \ ``` 4068375e ``` { typedef real_type_tag type; number_type() {} }; \ #define exprtk_register_complex_type_tag(T) \ ``` a65c8e8b ``` template <> struct number_type > \ ``` 4068375e ``` { typedef complex_type_tag type; number_type() {} }; \ #define exprtk_register_int_type_tag(T) \ ``` a65c8e8b ``` template <> struct number_type \ ``` 4068375e ``` { typedef int_type_tag type; number_type() {} }; \ exprtk_register_real_type_tag(double ) exprtk_register_real_type_tag(long double) exprtk_register_real_type_tag(float ) exprtk_register_complex_type_tag(double ) exprtk_register_complex_type_tag(long double) exprtk_register_complex_type_tag(float ) exprtk_register_int_type_tag(short ) exprtk_register_int_type_tag(int ) exprtk_register_int_type_tag(_int64_t ) exprtk_register_int_type_tag(unsigned short) exprtk_register_int_type_tag(unsigned int ) exprtk_register_int_type_tag(_uint64_t ) #undef exprtk_register_real_type_tag #undef exprtk_register_int_type_tag template ``` a65c8e8b ``` struct epsilon_type {}; ``` 4068375e ``` ``` a65c8e8b ``` #define exprtk_define_epsilon_type(Type, Epsilon) \ template <> struct epsilon_type \ { \ static inline Type value() \ { \ const Type epsilon = static_cast(Epsilon); \ return epsilon; \ } \ }; \ ``` 4068375e ``` ``` a65c8e8b ``` exprtk_define_epsilon_type(float , 0.00000100000f) exprtk_define_epsilon_type(double , 0.000000000100) exprtk_define_epsilon_type(long double, 0.000000000001) #undef exprtk_define_epsilon_type ``` 4068375e ``` template inline bool is_nan_impl(const T v, real_type_tag) { return std::not_equal_to()(v,v); } template inline int to_int32_impl(const T v, real_type_tag) { return static_cast(v); } template inline _int64_t to_int64_impl(const T v, real_type_tag) { return static_cast<_int64_t>(v); } template inline bool is_true_impl(const T v) { return std::not_equal_to()(T(0),v); } template inline bool is_false_impl(const T v) { return std::equal_to()(T(0),v); } template inline T abs_impl(const T v, real_type_tag) { return ((v < T(0)) ? -v : v); } template inline T min_impl(const T v0, const T v1, real_type_tag) { return std::min(v0,v1); } template inline T max_impl(const T v0, const T v1, real_type_tag) { return std::max(v0,v1); } template inline T equal_impl(const T v0, const T v1, real_type_tag) { const T epsilon = epsilon_type::value(); return (abs_impl(v0 - v1,real_type_tag()) <= (std::max(T(1),std::max(abs_impl(v0,real_type_tag()),abs_impl(v1,real_type_tag()))) * epsilon)) ? T(1) : T(0); } inline float equal_impl(const float v0, const float v1, real_type_tag) { const float epsilon = epsilon_type::value(); return (abs_impl(v0 - v1,real_type_tag()) <= (std::max(1.0f,std::max(abs_impl(v0,real_type_tag()),abs_impl(v1,real_type_tag()))) * epsilon)) ? 1.0f : 0.0f; } template inline T equal_impl(const T v0, const T v1, int_type_tag) { return (v0 == v1) ? 1 : 0; } template inline T expm1_impl(const T v, real_type_tag) { // return std::expm1(v); if (abs_impl(v,real_type_tag()) < T(0.00001)) return v + (T(0.5) * v * v); else return std::exp(v) - T(1); } template inline T expm1_impl(const T v, int_type_tag) { return T(std::exp(v)) - T(1); } template inline T nequal_impl(const T v0, const T v1, real_type_tag) { typedef real_type_tag rtg; const T epsilon = epsilon_type::value(); return (abs_impl(v0 - v1,rtg()) > (std::max(T(1),std::max(abs_impl(v0,rtg()),abs_impl(v1,rtg()))) * epsilon)) ? T(1) : T(0); } inline float nequal_impl(const float v0, const float v1, real_type_tag) { typedef real_type_tag rtg; const float epsilon = epsilon_type::value(); return (abs_impl(v0 - v1,rtg()) > (std::max(1.0f,std::max(abs_impl(v0,rtg()),abs_impl(v1,rtg()))) * epsilon)) ? 1.0f : 0.0f; } template 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) { return std::fmod(v0,v1); } template 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) { return std::pow(v0,v1); } template 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) { return std::log(v0) / std::log(v1); } template 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 log1p_impl(const T v, real_type_tag) { if (v > T(-1)) { if (abs_impl(v,real_type_tag()) > T(0.0001)) { return std::log(T(1) + v); } else return (T(-0.5) * v + T(1)) * v; } else return std::numeric_limits::quiet_NaN(); } template inline T log1p_impl(const T v, int_type_tag) { if (v > T(-1)) { return std::log(T(1) + v); } else return std::numeric_limits::quiet_NaN(); } template inline T root_impl(const T v0, const T v1, real_type_tag) { if (v1 < T(0)) return std::numeric_limits::quiet_NaN(); const std::size_t n = static_cast(v1); if ((v0 < T(0)) && (0 == (n % 2))) return std::numeric_limits::quiet_NaN(); return std::pow(v0, T(1) / n); } template 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 round_impl(const T v, real_type_tag) { return ((v < T(0)) ? std::ceil(v - T(0.5)) : std::floor(v + T(0.5))); } template inline T roundn_impl(const T v0, const T v1, real_type_tag) { ``` a65c8e8b ``` const int index = std::max(0, std::min(pow10_size - 1, static_cast(std::floor(v1)))); ``` 4068375e ``` const T p10 = T(pow10[index]); if (v0 < T(0)) return T(std::ceil ((v0 * p10) - T(0.5)) / p10); else return T(std::floor((v0 * p10) + T(0.5)) / p10); } template inline T roundn_impl(const T v0, const T, int_type_tag) { return v0; } template inline T hypot_impl(const T v0, const T v1, real_type_tag) { return std::sqrt((v0 * v0) + (v1 * v1)); } template inline T hypot_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) { return std::atan2(v0,v1); } template 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) { 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) { return v0 >> v1; } template 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) { return v0 << v1; } template inline T sgn_impl(const T v, real_type_tag) { ``` a65c8e8b ``` if (v > T(0)) return T(+1); ``` 4068375e ``` else if (v < T(0)) return T(-1); else return T( 0); } template inline T sgn_impl(const T v, int_type_tag) { ``` a65c8e8b ``` if (v > T(0)) return T(+1); ``` 4068375e ``` else if (v < T(0)) return T(-1); else return T( 0); } template inline T and_impl(const T v0, const T v1, real_type_tag) { return (is_true_impl(v0) && is_true_impl(v1)) ? T(1) : T(0); } template inline T and_impl(const T v0, const T v1, int_type_tag) { return v0 && v1; } template inline T nand_impl(const T v0, const T v1, real_type_tag) { return (is_false_impl(v0) || is_false_impl(v1)) ? T(1) : T(0); } template inline T nand_impl(const T v0, const T v1, int_type_tag) { return !(v0 && v1); } template inline T or_impl(const T v0, const T v1, real_type_tag) { return (is_true_impl(v0) || is_true_impl(v1)) ? T(1) : T(0); } template inline T or_impl(const T v0, const T v1, int_type_tag) { return (v0 || v1); } template inline T nor_impl(const T v0, const T v1, real_type_tag) { return (is_false_impl(v0) && is_false_impl(v1)) ? T(1) : T(0); } template inline T nor_impl(const T v0, const T v1, int_type_tag) { return !(v0 || v1); } template inline T xor_impl(const T v0, const T v1, real_type_tag) { return (is_false_impl(v0) != is_false_impl(v1)) ? T(1) : T(0); } template inline T xor_impl(const T v0, const T v1, int_type_tag) { return v0 ^ v1; } template inline T xnor_impl(const T v0, const T v1, real_type_tag) { const bool v0_true = is_true_impl(v0); const bool v1_true = is_true_impl(v1); if ((v0_true && v1_true) || (!v0_true && !v1_true)) return T(1); else return T(0); } template inline T xnor_impl(const T v0, const T v1, int_type_tag) { const bool v0_true = is_true_impl(v0); const bool v1_true = is_true_impl(v1); if ((v0_true && v1_true) || (!v0_true && !v1_true)) return T(1); else return T(0); } #if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || !defined(_MSC_VER) ``` a65c8e8b ``` #define exprtk_define_erf(TT, impl) \ inline TT erf_impl(const TT v) { return impl(v); } \ ``` 4068375e ``` exprtk_define_erf( float,::erff) exprtk_define_erf( double,::erf ) exprtk_define_erf(long double,::erfl) #undef exprtk_define_erf #endif template ``` a65c8e8b ``` inline T erf_impl(const T v, real_type_tag) ``` 4068375e ``` { #if defined(_MSC_VER) && (_MSC_VER < 1900) // Credits: Abramowitz & Stegun Equations 7.1.25-28 static const T c[] = { T( 1.26551223), T(1.00002368), T( 0.37409196), T(0.09678418), T(-0.18628806), T(0.27886807), T(-1.13520398), T(1.48851587), T(-0.82215223), T(0.17087277) }; const T t = T(1) / (T(1) + T(0.5) * abs_impl(v,real_type_tag())); ``` a65c8e8b ``` const T result = T(1) - t * std::exp((-v * v) - c[0] + t * (c[1] + t * (c[2] + t * (c[3] + t * (c[4] + t * (c[5] + t * (c[6] + t * (c[7] + t * (c[8] + t * (c[9])))))))))); ``` 4068375e ``` return (v >= T(0)) ? result : -result; #else return erf_impl(v); #endif } template ``` a65c8e8b ``` inline T erf_impl(const T v, int_type_tag) ``` 4068375e ``` { return erf_impl(static_cast(v),real_type_tag()); } #if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || !defined(_MSC_VER) ``` a65c8e8b ``` #define exprtk_define_erfc(TT, impl) \ inline TT erfc_impl(const TT v) { return impl(v); } \ ``` 4068375e ``` ``` a65c8e8b ``` exprtk_define_erfc(float ,::erfcf) exprtk_define_erfc(double ,::erfc ) ``` 4068375e ``` exprtk_define_erfc(long double,::erfcl) #undef exprtk_define_erfc #endif template ``` a65c8e8b ``` inline T erfc_impl(const T v, real_type_tag) ``` 4068375e ``` { #if defined(_MSC_VER) && (_MSC_VER < 1900) return T(1) - erf_impl(v,real_type_tag()); #else return erfc_impl(v); #endif } template ``` a65c8e8b ``` inline T erfc_impl(const T v, int_type_tag) ``` 4068375e ``` { return erfc_impl(static_cast(v),real_type_tag()); } template ``` a65c8e8b ``` inline T ncdf_impl(const T v, real_type_tag) ``` 4068375e ``` { ``` a65c8e8b ``` const T cnd = T(0.5) * (T(1) + erf_impl(abs_impl(v,real_type_tag()) / T(numeric::constant::sqrt2),real_type_tag())); ``` 4068375e ``` return (v < T(0)) ? (T(1) - cnd) : cnd; } template ``` a65c8e8b ``` inline T ncdf_impl(const T v, int_type_tag) ``` 4068375e ``` { return ncdf_impl(static_cast(v),real_type_tag()); } template ``` a65c8e8b ``` inline T sinc_impl(const T v, real_type_tag) ``` 4068375e ``` { if (std::abs(v) >= std::numeric_limits::epsilon()) return(std::sin(v) / v); else return T(1); } template ``` a65c8e8b ``` inline T sinc_impl(const T v, int_type_tag) ``` 4068375e ``` { return sinc_impl(static_cast(v),real_type_tag()); } template inline T acos_impl(const T v, real_type_tag) { return std::acos (v); } template inline T acosh_impl(const T v, real_type_tag) { return std::log(v + std::sqrt((v * v) - T(1))); } template inline T asin_impl(const T v, real_type_tag) { return std::asin (v); } template inline T asinh_impl(const T v, real_type_tag) { return std::log(v + std::sqrt((v * v) + T(1))); } template inline T atan_impl(const T v, real_type_tag) { return std::atan (v); } template inline T atanh_impl(const T v, real_type_tag) { return (std::log(T(1) + v) - std::log(T(1) - v)) / T(2); } template inline T ceil_impl(const T v, real_type_tag) { return std::ceil (v); } template inline T cos_impl(const T v, real_type_tag) { return std::cos (v); } template inline T cosh_impl(const T v, real_type_tag) { return std::cosh (v); } template inline T exp_impl(const T v, real_type_tag) { return std::exp (v); } template inline T floor_impl(const T v, real_type_tag) { return std::floor(v); } template inline T log_impl(const T v, real_type_tag) { return std::log (v); } template inline T log10_impl(const T v, real_type_tag) { return std::log10(v); } template inline T log2_impl(const T v, real_type_tag) { return std::log(v)/T(numeric::constant::log2); } template inline T neg_impl(const T v, real_type_tag) { return -v; } template inline T pos_impl(const T v, real_type_tag) { return +v; } template inline T sin_impl(const T v, real_type_tag) { return std::sin (v); } template inline T sinh_impl(const T v, real_type_tag) { return std::sinh (v); } template inline T sqrt_impl(const T v, real_type_tag) { return std::sqrt (v); } template inline T tan_impl(const T v, real_type_tag) { return std::tan (v); } template inline T tanh_impl(const T v, real_type_tag) { return std::tanh (v); } template inline T cot_impl(const T v, real_type_tag) { return T(1) / std::tan(v); } template inline T sec_impl(const T v, real_type_tag) { return T(1) / std::cos(v); } template inline T csc_impl(const T v, real_type_tag) { return T(1) / std::sin(v); } template inline T r2d_impl(const T v, real_type_tag) { return (v * T(numeric::constant::_180_pi)); } template inline T d2r_impl(const T v, real_type_tag) { return (v * T(numeric::constant::pi_180)); } ``` a65c8e8b ``` template inline T d2g_impl(const T v, real_type_tag) { return (v * T(10.0/9.0)); } template inline T g2d_impl(const T v, real_type_tag) { return (v * T(9.0/10.0)); } ``` 4068375e ``` template inline T notl_impl(const T v, real_type_tag) { return (std::not_equal_to()(T(0),v) ? T(0) : T(1)); } template inline T frac_impl(const T v, real_type_tag) { return (v - static_cast(v)); } template inline T trunc_impl(const T v, real_type_tag) { return T(static_cast(v)); } ``` a65c8e8b ``` template inline T const_pi_impl(real_type_tag) { return T(numeric::constant::pi); } template inline T const_e_impl(real_type_tag) { return T(numeric::constant::e); } template inline T const_qnan_impl(real_type_tag) { return std::numeric_limits::quiet_NaN(); } ``` 4068375e ``` template inline T abs_impl(const T v, int_type_tag) { return ((v >= T(0)) ? v : -v); } template inline T exp_impl(const T v, int_type_tag) { return std::exp (v); } template inline T log_impl(const T v, int_type_tag) { return std::log (v); } template inline T log10_impl(const T v, int_type_tag) { return std::log10(v); } template inline T log2_impl(const T v, int_type_tag) { return std::log(v)/T(numeric::constant::log2); } template inline T neg_impl(const T v, int_type_tag) { return -v; } template inline T pos_impl(const T v, int_type_tag) { return +v; } template inline T ceil_impl(const T v, int_type_tag) { return v; } template inline T floor_impl(const T v, int_type_tag) { return v; } template inline T round_impl(const T v, int_type_tag) { return v; } template inline T notl_impl(const T v, int_type_tag) { return !v; } template inline T sqrt_impl(const T v, int_type_tag) { return std::sqrt (v); } template inline T 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 acosh_impl(const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } template inline T asin_impl(const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } template inline T asinh_impl(const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } template inline T atan_impl(const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } template inline T atanh_impl(const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } template inline T cos_impl(const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } template inline T cosh_impl(const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } template inline T sin_impl(const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } template inline T sinh_impl(const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } template inline T tan_impl(const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } template inline T tanh_impl(const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } template inline T cot_impl(const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } template inline T sec_impl(const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } template inline T csc_impl(const T , int_type_tag) { return std::numeric_limits::quiet_NaN(); } template inline bool is_integer_impl(const T& v, real_type_tag) { return std::equal_to()(T(0),std::fmod(v,T(1))); } template inline bool is_integer_impl(const T&, int_type_tag) { return true; } } template struct numeric_info { enum { length = 0, size = 32, bound_length = 0, min_exp = 0, max_exp = 0 }; }; ``` a65c8e8b ``` template <> struct numeric_info { enum { length = 10, size = 16, bound_length = 9 }; }; template <> struct numeric_info { enum { min_exp = -38, max_exp = +38 }; }; template <> struct numeric_info { enum { min_exp = -308, max_exp = +308 }; }; template <> struct numeric_info { enum { min_exp = -308, max_exp = +308 }; }; ``` 4068375e ``` template inline int to_int32(const T v) { const typename details::number_type::type num_type; return to_int32_impl(v, num_type); } template inline _int64_t to_int64(const T v) { const typename details::number_type::type num_type; return to_int64_impl(v, num_type); } template inline bool is_nan(const T v) { const typename details::number_type::type num_type; return is_nan_impl(v, num_type); } template inline T min(const T v0, const T v1) { const typename details::number_type::type num_type; return min_impl(v0, v1, num_type); } template inline T max(const T v0, const T v1) { const typename details::number_type::type num_type; return max_impl(v0, v1, num_type); } template inline T equal(const T v0, const T v1) { const typename details::number_type::type num_type; return equal_impl(v0, v1, num_type); } template inline T nequal(const T v0, const T v1) { const typename details::number_type::type num_type; return nequal_impl(v0, v1, num_type); } template inline T modulus(const T v0, const T v1) { const typename details::number_type::type num_type; return modulus_impl(v0, v1, num_type); } template inline T pow(const T v0, const T v1) { const typename details::number_type::type num_type; return pow_impl(v0, v1, num_type); } template inline T logn(const T v0, const T v1) { const typename details::number_type::type num_type; return logn_impl(v0, v1, num_type); } template inline T root(const T v0, const T v1) { const typename details::number_type::type num_type; return root_impl(v0, v1, num_type); } template inline T roundn(const T v0, const T v1) { const typename details::number_type::type num_type; return roundn_impl(v0, v1, num_type); } template inline T hypot(const T v0, const T v1) { const typename details::number_type::type num_type; return hypot_impl(v0, v1, num_type); } template inline T atan2(const T v0, const T v1) { const typename details::number_type::type num_type; return atan2_impl(v0, v1, num_type); } template inline T shr(const T v0, const T v1) { const typename details::number_type::type num_type; return shr_impl(v0, v1, num_type); } template inline T shl(const T v0, const T v1) { const typename details::number_type::type num_type; return shl_impl(v0, v1, num_type); } template inline T and_opr(const T v0, const T v1) { const typename details::number_type::type num_type; return and_impl(v0, v1, num_type); } template inline T nand_opr(const T v0, const T v1) { const typename details::number_type::type num_type; return nand_impl(v0, v1, num_type); } template inline T or_opr(const T v0, const T v1) { const typename details::number_type::type num_type; return or_impl(v0, v1, num_type); } template inline T nor_opr(const T v0, const T v1) { const typename details::number_type::type num_type; return nor_impl(v0, v1, num_type); } template inline T xor_opr(const T v0, const T v1) { const typename details::number_type::type num_type; return xor_impl(v0, v1, num_type); } template inline T xnor_opr(const T v0, const T v1) { const typename details::number_type::type num_type; return xnor_impl(v0, v1, num_type); } template inline bool is_integer(const T v) { const typename details::number_type::type num_type; return is_integer_impl(v, num_type); } template struct fast_exp { static inline T result(T v) { unsigned int k = N; T l = T(1); while (k) { ``` a65c8e8b ``` if (1 == (k % 2)) ``` 4068375e ``` { l *= v; --k; } v *= v; ``` a65c8e8b ``` k /= 2; ``` 4068375e ``` } return l; } }; ``` a65c8e8b ``` template struct fast_exp { static inline T result(const T v) { T v_5 = fast_exp::result(v); return v_5 * v_5; } }; template struct fast_exp { static inline T result(const T v) { return fast_exp::result(v) * v; } }; template struct fast_exp { static inline T result(const T v) { T v_4 = fast_exp::result(v); return v_4 * v_4; } }; template struct fast_exp { static inline T result(const T v) { return fast_exp::result(v) * v; } }; template struct fast_exp { static inline T result(const T v) { T v_3 = fast_exp::result(v); return v_3 * v_3; } }; template struct fast_exp { static inline T result(const T v) { return fast_exp::result(v) * v; } }; template struct fast_exp { static inline T result(const T v) { T v_2 = v * v; return v_2 * v_2; } }; template struct fast_exp { static inline T result(const T v) { return v * v * v; } }; template struct fast_exp { static inline T result(const T v) { return v * v; } }; template struct fast_exp { static inline T result(const T v) { return v; } }; template struct fast_exp { static inline T result(const T ) { return T(1); } }; ``` 4068375e ``` #define exprtk_define_unary_function(FunctionName) \ template \ inline T FunctionName (const T v) \ { \ const typename details::number_type::type num_type; \ return FunctionName##_impl(v,num_type); \ } \ exprtk_define_unary_function(abs ) exprtk_define_unary_function(acos ) exprtk_define_unary_function(acosh) exprtk_define_unary_function(asin ) exprtk_define_unary_function(asinh) exprtk_define_unary_function(atan ) exprtk_define_unary_function(atanh) exprtk_define_unary_function(ceil ) exprtk_define_unary_function(cos ) exprtk_define_unary_function(cosh ) exprtk_define_unary_function(exp ) exprtk_define_unary_function(expm1) exprtk_define_unary_function(floor) exprtk_define_unary_function(log ) exprtk_define_unary_function(log10) exprtk_define_unary_function(log2 ) exprtk_define_unary_function(log1p) exprtk_define_unary_function(neg ) exprtk_define_unary_function(pos ) exprtk_define_unary_function(round) exprtk_define_unary_function(sin ) exprtk_define_unary_function(sinc ) exprtk_define_unary_function(sinh ) exprtk_define_unary_function(sqrt ) exprtk_define_unary_function(tan ) exprtk_define_unary_function(tanh ) exprtk_define_unary_function(cot ) exprtk_define_unary_function(sec ) exprtk_define_unary_function(csc ) exprtk_define_unary_function(r2d ) exprtk_define_unary_function(d2r ) exprtk_define_unary_function(d2g ) exprtk_define_unary_function(g2d ) exprtk_define_unary_function(notl ) exprtk_define_unary_function(sgn ) exprtk_define_unary_function(erf ) exprtk_define_unary_function(erfc ) exprtk_define_unary_function(ncdf ) exprtk_define_unary_function(frac ) exprtk_define_unary_function(trunc) #undef exprtk_define_unary_function } template inline T compute_pow10(T d, const int exponent) { static const double fract10[] = { 0.0, 1.0E+001, 1.0E+002, 1.0E+003, 1.0E+004, 1.0E+005, 1.0E+006, 1.0E+007, 1.0E+008, 1.0E+009, 1.0E+010, 1.0E+011, 1.0E+012, 1.0E+013, 1.0E+014, 1.0E+015, 1.0E+016, 1.0E+017, 1.0E+018, 1.0E+019, 1.0E+020, 1.0E+021, 1.0E+022, 1.0E+023, 1.0E+024, 1.0E+025, 1.0E+026, 1.0E+027, 1.0E+028, 1.0E+029, 1.0E+030, 1.0E+031, 1.0E+032, 1.0E+033, 1.0E+034, 1.0E+035, 1.0E+036, 1.0E+037, 1.0E+038, 1.0E+039, 1.0E+040, 1.0E+041, 1.0E+042, 1.0E+043, 1.0E+044, 1.0E+045, 1.0E+046, 1.0E+047, 1.0E+048, 1.0E+049, 1.0E+050, 1.0E+051, 1.0E+052, 1.0E+053, 1.0E+054, 1.0E+055, 1.0E+056, 1.0E+057, 1.0E+058, 1.0E+059, 1.0E+060, 1.0E+061, 1.0E+062, 1.0E+063, 1.0E+064, 1.0E+065, 1.0E+066, 1.0E+067, 1.0E+068, 1.0E+069, 1.0E+070, 1.0E+071, 1.0E+072, 1.0E+073, 1.0E+074, 1.0E+075, 1.0E+076, 1.0E+077, 1.0E+078, 1.0E+079, 1.0E+080, 1.0E+081, 1.0E+082, 1.0E+083, 1.0E+084, 1.0E+085, 1.0E+086, 1.0E+087, 1.0E+088, 1.0E+089, 1.0E+090, 1.0E+091, 1.0E+092, 1.0E+093, 1.0E+094, 1.0E+095, 1.0E+096, 1.0E+097, 1.0E+098, 1.0E+099, 1.0E+100, 1.0E+101, 1.0E+102, 1.0E+103, 1.0E+104, 1.0E+105, 1.0E+106, 1.0E+107, 1.0E+108, 1.0E+109, 1.0E+110, 1.0E+111, 1.0E+112, 1.0E+113, 1.0E+114, 1.0E+115, 1.0E+116, 1.0E+117, 1.0E+118, 1.0E+119, 1.0E+120, 1.0E+121, 1.0E+122, 1.0E+123, 1.0E+124, 1.0E+125, 1.0E+126, 1.0E+127, 1.0E+128, 1.0E+129, 1.0E+130, 1.0E+131, 1.0E+132, 1.0E+133, 1.0E+134, 1.0E+135, 1.0E+136, 1.0E+137, 1.0E+138, 1.0E+139, 1.0E+140, 1.0E+141, 1.0E+142, 1.0E+143, 1.0E+144, 1.0E+145, 1.0E+146, 1.0E+147, 1.0E+148, 1.0E+149, 1.0E+150, 1.0E+151, 1.0E+152, 1.0E+153, 1.0E+154, 1.0E+155, 1.0E+156, 1.0E+157, 1.0E+158, 1.0E+159, 1.0E+160, 1.0E+161, 1.0E+162, 1.0E+163, 1.0E+164, 1.0E+165, 1.0E+166, 1.0E+167, 1.0E+168, 1.0E+169, 1.0E+170, 1.0E+171, 1.0E+172, 1.0E+173, 1.0E+174, 1.0E+175, 1.0E+176, 1.0E+177, 1.0E+178, 1.0E+179, 1.0E+180, 1.0E+181, 1.0E+182, 1.0E+183, 1.0E+184, 1.0E+185, 1.0E+186, 1.0E+187, 1.0E+188, 1.0E+189, 1.0E+190, 1.0E+191, 1.0E+192, 1.0E+193, 1.0E+194, 1.0E+195, 1.0E+196, 1.0E+197, 1.0E+198, 1.0E+199, 1.0E+200, 1.0E+201, 1.0E+202, 1.0E+203, 1.0E+204, 1.0E+205, 1.0E+206, 1.0E+207, 1.0E+208, 1.0E+209, 1.0E+210, 1.0E+211, 1.0E+212, 1.0E+213, 1.0E+214, 1.0E+215, 1.0E+216, 1.0E+217, 1.0E+218, 1.0E+219, 1.0E+220, 1.0E+221, 1.0E+222, 1.0E+223, 1.0E+224, 1.0E+225, 1.0E+226, 1.0E+227, 1.0E+228, 1.0E+229, 1.0E+230, 1.0E+231, 1.0E+232, 1.0E+233, 1.0E+234, 1.0E+235, 1.0E+236, 1.0E+237, 1.0E+238, 1.0E+239, 1.0E+240, 1.0E+241, 1.0E+242, 1.0E+243, 1.0E+244, 1.0E+245, 1.0E+246, 1.0E+247, 1.0E+248, 1.0E+249, 1.0E+250, 1.0E+251, 1.0E+252, 1.0E+253, 1.0E+254, 1.0E+255, 1.0E+256, 1.0E+257, 1.0E+258, 1.0E+259, 1.0E+260, 1.0E+261, 1.0E+262, 1.0E+263, 1.0E+264, 1.0E+265, 1.0E+266, 1.0E+267, 1.0E+268, 1.0E+269, 1.0E+270, 1.0E+271, 1.0E+272, 1.0E+273, 1.0E+274, 1.0E+275, 1.0E+276, 1.0E+277, 1.0E+278, 1.0E+279, 1.0E+280, 1.0E+281, 1.0E+282, 1.0E+283, 1.0E+284, 1.0E+285, 1.0E+286, 1.0E+287, 1.0E+288, 1.0E+289, 1.0E+290, 1.0E+291, 1.0E+292, 1.0E+293, 1.0E+294, 1.0E+295, 1.0E+296, 1.0E+297, 1.0E+298, 1.0E+299, 1.0E+300, 1.0E+301, 1.0E+302, 1.0E+303, 1.0E+304, 1.0E+305, 1.0E+306, 1.0E+307, 1.0E+308 }; static const int fract10_size = static_cast(sizeof(fract10) / sizeof(double)); const int e = std::abs(exponent); if (exponent >= std::numeric_limits::min_exponent10) { if (e < fract10_size) { if (exponent > 0) return T(d * fract10[e]); else return T(d / fract10[e]); } else return T(d * std::pow(10.0, 10.0 * exponent)); } else { d /= T(fract10[ -std::numeric_limits::min_exponent10]); return T(d / fract10[-exponent + std::numeric_limits::min_exponent10]); } } template inline bool string_to_type_converter_impl_ref(Iterator& itr, const Iterator end, T& result) { if (itr == end) return false; const bool negative = ('-' == (*itr)); if (negative || ('+' == (*itr))) { if (end == ++itr) return false; } static const uchar_t zero = static_cast('0'); while ((end != itr) && (zero == (*itr))) ++itr; bool return_result = true; unsigned int digit = 0; ``` a65c8e8b ``` const std::size_t length = static_cast(std::distance(itr,end)); ``` 4068375e ``` if (length <= 4) { exprtk_disable_fallthrough_begin switch (length) { #ifdef exprtk_use_lut #define exprtk_process_digit \ if ((digit = details::digit_table[(int)*itr++]) < 10) \ result = result * 10 + (digit); \ else \ { \ return_result = false; \ break; \ } \ #else #define exprtk_process_digit \ if ((digit = (*itr++ - zero)) < 10) \ result = result * T(10) + digit; \ else \ { \ return_result = false; \ break; \ } \ #endif ``` a65c8e8b ``` case 4 : exprtk_process_digit case 3 : exprtk_process_digit case 2 : exprtk_process_digit case 1 : if ((digit = (*itr - zero))>= 10) { digit = 0; return_result = false; } ``` 4068375e ``` #undef exprtk_process_digit } exprtk_disable_fallthrough_end } else return_result = false; if (length && return_result) { result = result * 10 + static_cast(digit); ++itr; } result = negative ? -result : result; return return_result; } template static inline bool parse_nan(Iterator& itr, const Iterator end, T& t) { 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)) ) { return false; } } else if ( (static_cast('A') != *(itr + 1)) || (static_cast('N') != *(itr + 2)) ) { return false; } t = std::numeric_limits::quiet_NaN(); return true; } template ``` a65c8e8b ``` static inline bool parse_inf(Iterator& itr, const Iterator end, T& t, const bool negative) ``` 4068375e ``` { static const char_t inf_uc[] = "INFINITY"; static const char_t inf_lc[] = "infinity"; static const std::size_t inf_length = 8; const std::size_t length = static_cast(std::distance(itr,end)); if ((3 != length) && (inf_length != length)) return false; char_cptr inf_itr = ('i' == (*itr)) ? inf_lc : inf_uc; while (end != itr) { ``` a65c8e8b ``` if (*inf_itr == static_cast(*itr)) ``` 4068375e ``` { ++itr; ++inf_itr; continue; } else return false; } if (negative) t = -std::numeric_limits::infinity(); else t = std::numeric_limits::infinity(); return true; } template inline bool valid_exponent(const int exponent, numeric::details::real_type_tag) { ``` a65c8e8b ``` using namespace details::numeric; return (numeric_info::min_exp <= exponent) && (exponent <= numeric_info::max_exp); ``` 4068375e ``` } template inline bool string_to_real(Iterator& itr_external, const Iterator end, T& t, numeric::details::real_type_tag) { if (end == itr_external) return false; Iterator itr = itr_external; T d = T(0); const bool negative = ('-' == (*itr)); if (negative || '+' == (*itr)) { if (end == ++itr) return false; } bool instate = false; static const char_t zero = static_cast('0'); #define parse_digit_1(d) \ if ((digit = (*itr - zero)) < 10) \ { d = d * T(10) + digit; } \ else \ { break; } \ if (end == ++itr) break; \ #define parse_digit_2(d) \ if ((digit = (*itr - zero)) < 10) \ { d = d * T(10) + digit; } \ ``` a65c8e8b ``` else \ { break; } \ ``` 4068375e ``` ++itr; \ if ('.' != (*itr)) { const Iterator curr = itr; while ((end != itr) && (zero == (*itr))) ++itr; while (end != itr) { unsigned int digit; parse_digit_1(d) parse_digit_1(d) parse_digit_2(d) } if (curr != itr) instate = true; } int exponent = 0; if (end != itr) { if ('.' == (*itr)) { const Iterator curr = ++itr; T tmp_d = T(0); while (end != itr) { unsigned int digit; parse_digit_1(tmp_d) parse_digit_1(tmp_d) parse_digit_2(tmp_d) } if (curr != itr) { instate = true; ``` a65c8e8b ``` const int frac_exponent = static_cast(-std::distance(curr, itr)); ``` 4068375e ``` ``` a65c8e8b ``` if (!valid_exponent(frac_exponent, numeric::details::real_type_tag())) ``` 4068375e ``` return false; ``` a65c8e8b ``` d += compute_pow10(tmp_d, frac_exponent); ``` 4068375e ``` } #undef parse_digit_1 #undef parse_digit_2 } if (end != itr) { typename std::iterator_traits::value_type c = (*itr); if (('e' == c) || ('E' == c)) { int exp = 0; if (!details::string_to_type_converter_impl_ref(++itr, end, exp)) { if (end == itr) return false; else c = (*itr); } exponent += exp; } if (end != itr) { if (('f' == c) || ('F' == c) || ('l' == c) || ('L' == c)) ++itr; else if ('#' == c) { if (end == ++itr) return false; else if (('I' <= (*itr)) && ((*itr) <= 'n')) { if (('i' == (*itr)) || ('I' == (*itr))) { return parse_inf(itr, end, t, negative); } else if (('n' == (*itr)) || ('N' == (*itr))) { return parse_nan(itr, end, t); } else return false; } else return false; } else if (('I' <= (*itr)) && ((*itr) <= 'n')) { if (('i' == (*itr)) || ('I' == (*itr))) { return parse_inf(itr, end, t, negative); } else if (('n' == (*itr)) || ('N' == (*itr))) { return parse_nan(itr, end, t); } else return false; } else return false; } } } if ((end != itr) || (!instate)) return false; else if (!valid_exponent(exponent, numeric::details::real_type_tag())) return false; else if (exponent) d = compute_pow10(d,exponent); t = static_cast((negative) ? -d : d); return true; } template inline bool string_to_real(const std::string& s, T& t) { const typename numeric::details::number_type::type num_type; char_cptr begin = s.data(); char_cptr end = s.data() + s.size(); return string_to_real(begin, end, t, num_type); } 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& RefType; 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 struct loop_runtime_check { enum loop_types { e_invalid = 0, e_for_loop = 1, e_while_loop = 2, e_repeat_until_loop = 4, e_all_loops = 7 }; enum violation_type { e_unknown = 0, e_iteration_count = 1, e_timeout = 2 }; loop_types loop_set; loop_runtime_check() ``` a65c8e8b ``` : loop_set(e_invalid) , max_loop_iterations(0) ``` 4068375e ``` {} details::_uint64_t max_loop_iterations; struct violation_context { loop_types loop; violation_type violation; details::_uint64_t iteration_count; }; virtual void handle_runtime_violation(const violation_context&) { throw std::runtime_error("ExprTk Loop run-time violation."); } virtual ~loop_runtime_check() {} }; typedef loop_runtime_check* loop_runtime_check_ptr; namespace lexer { struct token { enum token_type { e_none = 0, e_error = 1, e_err_symbol = 2, e_err_number = 3, e_err_string = 4, e_err_sfunc = 5, e_eof = 6, e_number = 7, e_symbol = 8, e_string = 9, e_assign = 10, e_addass = 11, e_subass = 12, e_mulass = 13, e_divass = 14, e_modass = 15, e_shr = 16, e_shl = 17, e_lte = 18, e_ne = 19, e_gte = 20, e_swap = 21, e_lt = '<', e_gt = '>', e_eq = '=', e_rbracket = ')', e_lbracket = '(', e_rsqrbracket = ']', e_lsqrbracket = '[', e_rcrlbracket = '}', e_lcrlbracket = '{', e_comma = ',', e_add = '+', e_sub = '-', e_div = '/', e_mul = '*', e_mod = '%', e_pow = '^', e_colon = ':', e_ternary = '?' }; token() ``` a65c8e8b ``` : type(e_none) , value("") , position(std::numeric_limits::max()) ``` 4068375e ``` {} void clear() { type = e_none; value = ""; position = std::numeric_limits::max(); } template inline token& set_operator(const token_type tt, const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0)) { type = tt; value.assign(begin,end); if (base_begin) position = static_cast(std::distance(base_begin,begin)); return (*this); } template inline token& set_symbol(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0)) { type = e_symbol; value.assign(begin,end); if (base_begin) position = static_cast(std::distance(base_begin,begin)); return (*this); } template inline token& set_numeric(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0)) { type = e_number; value.assign(begin,end); if (base_begin) position = static_cast(std::distance(base_begin,begin)); return (*this); } template inline token& set_string(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0)) { type = e_string; value.assign(begin,end); if (base_begin) position = static_cast(std::distance(base_begin,begin)); return (*this); } inline token& set_string(const std::string& s, const std::size_t p) { type = e_string; value = s; position = p; return (*this); } template inline token& set_error(const token_type et, const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0)) { if ( (e_error == et) || (e_err_symbol == et) || (e_err_number == et) || (e_err_string == et) || (e_err_sfunc == et) ) { type = et; } else type = e_error; value.assign(begin,end); if (base_begin) position = static_cast(std::distance(base_begin,begin)); return (*this); } static inline std::string to_str(token_type t) { switch (t) { case e_none : return "NONE"; case e_error : return "ERROR"; case e_err_symbol : return "ERROR_SYMBOL"; case e_err_number : return "ERROR_NUMBER"; case e_err_string : return "ERROR_STRING"; case e_eof : return "EOF"; case e_number : return "NUMBER"; case e_symbol : return "SYMBOL"; case e_string : return "STRING"; case e_assign : return ":="; case e_addass : return "+="; case e_subass : return "-="; case e_mulass : return "*="; case e_divass : return "/="; case e_modass : return "%="; case e_shr : return ">>"; case e_shl : return "<<"; case e_lte : return "<="; case e_ne : return "!="; case e_gte : return ">="; case e_lt : return "<"; case e_gt : return ">"; case e_eq : return "="; case e_rbracket : return ")"; case e_lbracket : return "("; case e_rsqrbracket : return "]"; case e_lsqrbracket : return "["; case e_rcrlbracket : return "}"; case e_lcrlbracket : return "{"; case e_comma : return ","; case e_add : return "+"; case e_sub : return "-"; case e_div : return "/"; case e_mul : return "*"; case e_mod : return "%"; case e_pow : return "^"; case e_colon : return ":"; case e_ternary : return "?"; case e_swap : return "<=>"; default : return "UNKNOWN"; } } inline bool is_error() const { return ( (e_error == type) || (e_err_symbol == type) || (e_err_number == type) || (e_err_string == type) || (e_err_sfunc == type) ); } token_type type; std::string value; std::size_t position; }; class generator { public: typedef token token_t; typedef std::vector token_list_t; typedef token_list_t::iterator token_list_itr_t; typedef details::char_t char_t; generator() ``` a65c8e8b ``` : base_itr_(0) , s_itr_ (0) , s_end_ (0) ``` 4068375e ``` { clear(); } inline void clear() { base_itr_ = 0; s_itr_ = 0; s_end_ = 0; token_list_.clear(); token_itr_ = token_list_.end(); store_token_itr_ = token_list_.end(); } inline bool process(const std::string& str) { base_itr_ = str.data(); s_itr_ = str.data(); s_end_ = str.data() + str.size(); eof_token_.set_operator(token_t::e_eof,s_end_,s_end_,base_itr_); token_list_.clear(); while (!is_end(s_itr_)) { scan_token(); if (!token_list_.empty() && token_list_.back().is_error()) return false; } return true; } inline bool empty() const { return token_list_.empty(); } inline std::size_t size() const { return token_list_.size(); } inline void begin() { token_itr_ = token_list_.begin(); store_token_itr_ = token_list_.begin(); } inline void store() { store_token_itr_ = token_itr_; } inline void restore() { token_itr_ = store_token_itr_; } inline token_t& next_token() { if (token_list_.end() != token_itr_) { return *token_itr_++; } else return eof_token_; } inline token_t& peek_next_token() { if (token_list_.end() != token_itr_) { return *token_itr_; } else return eof_token_; } inline token_t& operator[](const std::size_t& index) { if (index < token_list_.size()) return token_list_[index]; else return eof_token_; } inline token_t operator[](const std::size_t& index) const { if (index < token_list_.size()) return token_list_[index]; else return eof_token_; } inline bool finished() const { return (token_list_.end() == token_itr_); } inline void insert_front(token_t::token_type tk_type) { if ( !token_list_.empty() && (token_list_.end() != token_itr_) ) { token_t t = *token_itr_; t.type = tk_type; token_itr_ = token_list_.insert(token_itr_,t); } } ``` a65c8e8b ``` inline std::string substr(const std::size_t& begin, const std::size_t& end) const ``` 4068375e ``` { const details::char_cptr begin_itr = ((base_itr_ + begin) < s_end_) ? (base_itr_ + begin) : s_end_; ``` a65c8e8b ``` const details::char_cptr end_itr = ((base_itr_ + end ) < s_end_) ? (base_itr_ + end ) : s_end_; ``` 4068375e ``` return std::string(begin_itr,end_itr); } inline std::string remaining() const { if (finished()) return ""; else if (token_list_.begin() != token_itr_) return std::string(base_itr_ + (token_itr_ - 1)->position, s_end_); else return std::string(base_itr_ + token_itr_->position, s_end_); } private: ``` a65c8e8b ``` inline bool is_end(details::char_cptr itr) const ``` 4068375e ``` { return (s_end_ == itr); } ``` a65c8e8b ``` #ifndef exprtk_disable_comments inline bool is_comment_start(details::char_cptr itr) const ``` 4068375e ``` { const char_t c0 = *(itr + 0); const char_t c1 = *(itr + 1); if ('#' == c0) return true; else if (!is_end(itr + 1)) { if (('/' == c0) && ('/' == c1)) return true; if (('/' == c0) && ('*' == c1)) return true; } return false; } ``` a65c8e8b ``` #else inline bool is_comment_start(details::char_cptr) const { return false; } #endif ``` 4068375e ``` inline void skip_whitespace() { while (!is_end(s_itr_) && details::is_whitespace(*s_itr_)) { ++s_itr_; } } inline void skip_comments() { #ifndef exprtk_disable_comments // The following comment styles are supported: // 1. // .... \n // 2. # .... \n // 3. /* .... */ struct test { static inline bool comment_start(const char_t c0, const char_t c1, int& mode, int& incr) { mode = 0; ``` a65c8e8b ``` if ('#' == c0) { mode = 1; incr = 1; } ``` 4068375e ``` else if ('/' == c0) { ``` a65c8e8b ``` if ('/' == c1) { mode = 1; incr = 2; } ``` 4068375e ``` else if ('*' == c1) { mode = 2; incr = 2; } } return (0 != mode); } static inline bool comment_end(const char_t c0, const char_t c1, int& mode) { if ( ((1 == mode) && ('\n' == c0)) || ((2 == mode) && ( '*' == c0) && ('/' == c1)) ) { mode = 0; return true; } else return false; } }; int mode = 0; int increment = 0; if (is_end(s_itr_)) return; else if (!test::comment_start(*s_itr_, *(s_itr_ + 1), mode, increment)) return; details::char_cptr cmt_start = s_itr_; s_itr_ += increment; while (!is_end(s_itr_)) { if ((1 == mode) && test::comment_end(*s_itr_, 0, mode)) { ++s_itr_; return; } if ((2 == mode)) { if (!is_end((s_itr_ + 1)) && test::comment_end(*s_itr_, *(s_itr_ + 1), mode)) { s_itr_ += 2; return; } } ++s_itr_; } if (2 == mode) { token_t t; t.set_error(token::e_error, cmt_start, cmt_start + mode, base_itr_); token_list_.push_back(t); } #endif } inline void scan_token() { if (details::is_whitespace(*s_itr_)) { skip_whitespace(); return; } else if (is_comment_start(s_itr_)) { skip_comments(); return; } else if (details::is_operator_char(*s_itr_)) { scan_operator(); return; } else if (details::is_letter(*s_itr_)) { scan_symbol(); return; } else if (details::is_digit((*s_itr_)) || ('.' == (*s_itr_))) { scan_number(); return; } else if ('\$' == (*s_itr_)) { scan_special_function(); return; } #ifndef exprtk_disable_string_capabilities else if ('\'' == (*s_itr_)) { scan_string(); return; } #endif else if ('~' == (*s_itr_)) { token_t t; t.set_symbol(s_itr_, s_itr_ + 1, base_itr_); token_list_.push_back(t); ++s_itr_; return; } else { token_t t; t.set_error(token::e_error, s_itr_, s_itr_ + 2, base_itr_); token_list_.push_back(t); ++s_itr_; } } inline void scan_operator() { token_t t; const char_t c0 = s_itr_[0]; if (!is_end(s_itr_ + 1)) { const char_t c1 = s_itr_[1]; if (!is_end(s_itr_ + 2)) { const char_t c2 = s_itr_[2]; if ((c0 == '<') && (c1 == '=') && (c2 == '>')) { t.set_operator(token_t::e_swap, s_itr_, s_itr_ + 3, base_itr_); token_list_.push_back(t); s_itr_ += 3; return; } } token_t::token_type ttype = token_t::e_none; ``` a65c8e8b ``` if ((c0 == '<') && (c1 == '=')) ttype = token_t::e_lte; ``` 4068375e ``` else if ((c0 == '>') && (c1 == '=')) ttype = token_t::e_gte; else if ((c0 == '<') && (c1 == '>')) ttype = token_t::e_ne; else if ((c0 == '!') && (c1 == '=')) ttype = token_t::e_ne; else if ((c0 == '=') && (c1 == '=')) ttype = token_t::e_eq; else if ((c0 == ':') && (c1 == '=')) ttype = token_t::e_assign; else if ((c0 == '<') && (c1 == '<')) ttype = token_t::e_shl; else if ((c0 == '>') && (c1 == '>')) ttype = token_t::e_shr; else if ((c0 == '+') && (c1 == '=')) ttype = token_t::e_addass; else if ((c0 == '-') && (c1 == '=')) ttype = token_t::e_subass; else if ((c0 == '*') && (c1 == '=')) ttype = token_t::e_mulass; else if ((c0 == '/') && (c1 == '=')) ttype = token_t::e_divass; else if ((c0 == '%') && (c1 == '=')) ttype = token_t::e_modass; if (token_t::e_none != ttype) { t.set_operator(ttype, s_itr_, s_itr_ + 2, base_itr_); token_list_.push_back(t); s_itr_ += 2; return; } } if ('<' == c0) t.set_operator(token_t::e_lt , s_itr_, s_itr_ + 1, base_itr_); else if ('>' == c0) t.set_operator(token_t::e_gt , s_itr_, s_itr_ + 1, base_itr_); else if (';' == c0) t.set_operator(token_t::e_eof, s_itr_, s_itr_ + 1, base_itr_); else if ('&' == c0) t.set_symbol(s_itr_, s_itr_ + 1, base_itr_); else if ('|' == c0) t.set_symbol(s_itr_, s_itr_ + 1, base_itr_); else t.set_operator(token_t::token_type(c0), s_itr_, s_itr_ + 1, base_itr_); token_list_.push_back(t); ++s_itr_; } inline void scan_symbol() { details::char_cptr initial_itr = s_itr_; while (!is_end(s_itr_)) { if (!details::is_letter_or_digit(*s_itr_) && ('_' != (*s_itr_))) { if ('.' != (*s_itr_)) break; /* Permit symbols that contain a 'dot' Allowed : abc.xyz, a123.xyz, abc.123, abc_.xyz a123_.xyz abc._123 Disallowed: .abc, abc., abc., abc. */ if ( (s_itr_ != initial_itr) && !is_end(s_itr_ + 1) && !details::is_letter_or_digit(*(s_itr_ + 1)) && ('_' != (*(s_itr_ + 1))) ) break; } ++s_itr_; } token_t t; t.set_symbol(initial_itr,s_itr_,base_itr_); token_list_.push_back(t); } inline void scan_number() { /* Attempt to match a valid numeric value in one of the following formats: (01) 123456 (02) 123456. (03) 123.456 (04) 123.456e3 (05) 123.456E3 (06) 123.456e+3 (07) 123.456E+3 (08) 123.456e-3 (09) 123.456E-3 (00) .1234 (11) .1234e3 (12) .1234E+3 (13) .1234e+3 (14) .1234E-3 (15) .1234e-3 */ details::char_cptr initial_itr = s_itr_; bool dot_found = false; bool e_found = false; bool post_e_sign_found = false; bool post_e_digit_found = false; token_t t; while (!is_end(s_itr_)) { if ('.' == (*s_itr_)) { if (dot_found) { t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_); token_list_.push_back(t); return; } dot_found = true; ++s_itr_; continue; } else if ('e' == std::tolower(*s_itr_)) { const char_t& c = *(s_itr_ + 1); if (is_end(s_itr_ + 1)) { t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_); token_list_.push_back(t); return; } else if ( ('+' != c) && ('-' != c) && !details::is_digit(c) ) { t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_); token_list_.push_back(t); return; } e_found = true; ++s_itr_; continue; } else if (e_found && details::is_sign(*s_itr_) && !post_e_digit_found) { if (post_e_sign_found) { t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_); token_list_.push_back(t); return; } post_e_sign_found = true; ++s_itr_; continue; } else if (e_found && details::is_digit(*s_itr_)) { post_e_digit_found = true; ++s_itr_; continue; } else if (('.' != (*s_itr_)) && !details::is_digit(*s_itr_)) break; else ++s_itr_; } t.set_numeric(initial_itr, s_itr_, base_itr_); token_list_.push_back(t); return; } inline void scan_special_function() { details::char_cptr initial_itr = s_itr_; token_t t; // \$fdd(x,x,x) = at least 11 chars if (std::distance(s_itr_,s_end_) < 11) { ``` a65c8e8b ``` t.set_error( token::e_err_sfunc, initial_itr, std::min(initial_itr + 11, s_end_), base_itr_); ``` 4068375e ``` token_list_.push_back(t); return; } if ( !(('\$' == *s_itr_) && (details::imatch ('f',*(s_itr_ + 1))) && (details::is_digit(*(s_itr_ + 2))) && (details::is_digit(*(s_itr_ + 3)))) ) { ``` a65c8e8b ``` t.set_error( token::e_err_sfunc, initial_itr, std::min(initial_itr + 4, s_end_), base_itr_); ``` 4068375e ``` token_list_.push_back(t); return; } s_itr_ += 4; // \$fdd = 4chars t.set_symbol(initial_itr, s_itr_, base_itr_); token_list_.push_back(t); return; } #ifndef exprtk_disable_string_capabilities inline void scan_string() { details::char_cptr initial_itr = s_itr_ + 1; token_t t; if (std::distance(s_itr_,s_end_) < 2) { t.set_error(token::e_err_string, s_itr_, s_end_, base_itr_); token_list_.push_back(t); return; } ++s_itr_; bool escaped_found = false; bool escaped = false; while (!is_end(s_itr_)) { if (!details::is_valid_string_char(*s_itr_)) { t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_); token_list_.push_back(t); return; } else if (!escaped && ('\\' == *s_itr_)) { escaped_found = true; escaped = true; ++s_itr_; continue; } else if (!escaped) { if ('\'' == *s_itr_) break; } else if (escaped) { if ( !is_end(s_itr_) && ('0' == *(s_itr_)) && ((s_itr_ + 4) <= s_end_) ) { const bool x_seperator = ('X' == std::toupper(*(s_itr_ + 1))); const bool both_digits = details::is_hex_digit(*(s_itr_ + 2)) && details::is_hex_digit(*(s_itr_ + 3)) ; if (!(x_seperator && both_digits)) { t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_); token_list_.push_back(t); return; } else s_itr_ += 3; } escaped = false; } ++s_itr_; } if (is_end(s_itr_)) { t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_); token_list_.push_back(t); return; } if (!escaped_found) t.set_string(initial_itr, s_itr_, base_itr_); else { std::string parsed_string(initial_itr,s_itr_); if (!details::cleanup_escapes(parsed_string)) { t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_); token_list_.push_back(t); return; } t.set_string( parsed_string, static_cast(std::distance(base_itr_,initial_itr))); } token_list_.push_back(t); ++s_itr_; return; } #endif private: token_list_t token_list_; token_list_itr_t token_itr_; token_list_itr_t store_token_itr_; token_t eof_token_; details::char_cptr base_itr_; details::char_cptr s_itr_; details::char_cptr s_end_; friend class token_scanner; friend class token_modifier; friend class token_inserter; friend class token_joiner; ``` a65c8e8b ``` }; // class generator ``` 4068375e ``` class helper_interface { public: virtual void init() { } virtual void reset() { } virtual bool result() { return true; } virtual std::size_t process(generator&) { return 0; } virtual ~helper_interface() { } }; class token_scanner : public helper_interface { public: ``` a65c8e8b ``` virtual ~token_scanner() {} ``` 4068375e ``` explicit token_scanner(const std::size_t& stride) : stride_(stride) { if (stride > 4) { throw std::invalid_argument("token_scanner() - Invalid stride value"); } } ``` a65c8e8b ``` inline std::size_t process(generator& g) exprtk_override ``` 4068375e ``` { if (g.token_list_.size() >= stride_) { for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i) { token t; switch (stride_) { case 1 : { const token& t0 = g.token_list_[i]; if (!operator()(t0)) { return i; } } break; case 2 : { const token& t0 = g.token_list_[i ]; const token& t1 = g.token_list_[i + 1]; if (!operator()(t0, t1)) { return i; } } break; case 3 : { const token& t0 = g.token_list_[i ]; const token& t1 = g.token_list_[i + 1]; const token& t2 = g.token_list_[i + 2]; if (!operator()(t0, t1, t2)) { return i; } } break; case 4 : { const token& t0 = g.token_list_[i ]; const token& t1 = g.token_list_[i + 1]; const token& t2 = g.token_list_[i + 2]; const token& t3 = g.token_list_[i + 3]; if (!operator()(t0, t1, t2, t3)) { return i; } } break; } } } return (g.token_list_.size() - stride_ + 1); } virtual bool operator() (const token&) { return false; } virtual bool operator() (const token&, const token&) { return false; } virtual bool operator() (const token&, const token&, const token&) { return false; } virtual bool operator() (const token&, const token&, const token&, const token&) { return false; } private: const std::size_t stride_; ``` a65c8e8b ``` }; // class token_scanner ``` 4068375e ``` class token_modifier : public helper_interface { public: ``` a65c8e8b ``` inline std::size_t process(generator& g) exprtk_override ``` 4068375e ``` { std::size_t changes = 0; for (std::size_t i = 0; i < g.token_list_.size(); ++i) { if (modify(g.token_list_[i])) changes++; } return changes; } virtual bool modify(token& t) = 0; }; class token_inserter : public helper_interface { public: explicit token_inserter(const std::size_t& stride) : stride_(stride) { if (stride > 5) { throw std::invalid_argument("token_inserter() - Invalid stride value"); } } ``` a65c8e8b ``` inline std::size_t process(generator& g) exprtk_override ``` 4068375e ``` { if (g.token_list_.empty()) return 0; else if (g.token_list_.size() < stride_) return 0; std::size_t changes = 0; typedef std::pair insert_t; std::vector insert_list; insert_list.reserve(10000); for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i) { int insert_index = -1; token t; switch (stride_) { case 1 : insert_index = insert(g.token_list_[i],t); break; case 2 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], t); break; case 3 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], g.token_list_[i + 2], t); break; case 4 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], g.token_list_[i + 2], g.token_list_[i + 3], t); break; case 5 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], g.token_list_[i + 2], g.token_list_[i + 3], g.token_list_[i + 4], t); break; } if ((insert_index >= 0) && (insert_index <= (static_cast(stride_) + 1))) { insert_list.push_back(insert_t(i, t)); changes++; } } if (!insert_list.empty()) { generator::token_list_t token_list; std::size_t insert_index = 0; for (std::size_t i = 0; i < g.token_list_.size(); ++i) { token_list.push_back(g.token_list_[i]); if ( (insert_index < insert_list.size()) && (insert_list[insert_index].first == i) ) { token_list.push_back(insert_list[insert_index].second); insert_index++; } } std::swap(g.token_list_,token_list); } return changes; } #define token_inserter_empty_body \ { \ return -1; \ } \ inline virtual int insert(const token&, token&) token_inserter_empty_body inline virtual int insert(const token&, const token&, token&) token_inserter_empty_body inline virtual int insert(const token&, const token&, const token&, token&) token_inserter_empty_body inline virtual int insert(const token&, const token&, const token&, const token&, token&) token_inserter_empty_body inline virtual int insert(const token&, const token&, const token&, const token&, const token&, token&) token_inserter_empty_body #undef token_inserter_empty_body private: const std::size_t stride_; }; class token_joiner : public helper_interface { public: explicit token_joiner(const std::size_t& stride) : stride_(stride) {} ``` a65c8e8b ``` inline std::size_t process(generator& g) exprtk_override ``` 4068375e ``` { if (g.token_list_.empty()) return 0; switch (stride_) { case 2 : return process_stride_2(g); case 3 : return process_stride_3(g); default : return 0; } } virtual bool join(const token&, const token&, token&) { return false; } virtual bool join(const token&, const token&, const token&, token&) { return false; } private: inline std::size_t process_stride_2(generator& g) { if (g.token_list_.size() < 2) return 0; std::size_t changes = 0; generator::token_list_t token_list; token_list.reserve(10000); for (int i = 0; i < static_cast(g.token_list_.size() - 1); ++i) { token t; for ( ; ; ) { if (!join(g[i], g[i + 1], t)) { token_list.push_back(g[i]); break; } token_list.push_back(t); ++changes; i+=2; ``` a65c8e8b ``` if (static_cast(i) >= (g.token_list_.size() - 1)) ``` 4068375e ``` break; } } token_list.push_back(g.token_list_.back()); ``` a65c8e8b ``` assert(token_list.size() <= g.token_list_.size()); ``` 4068375e ``` std::swap(token_list, g.token_list_); return changes; } inline std::size_t process_stride_3(generator& g) { if (g.token_list_.size() < 3) return 0; std::size_t changes = 0; generator::token_list_t token_list; token_list.reserve(10000); for (int i = 0; i < static_cast(g.token_list_.size() - 2); ++i) { token t; for ( ; ; ) { if (!join(g[i], g[i + 1], g[i + 2], t)) { token_list.push_back(g[i]); break; } token_list.push_back(t); ++changes; i+=3; ``` a65c8e8b ``` if (static_cast(i) >= (g.token_list_.size() - 2)) ``` 4068375e ``` break; } } token_list.push_back(*(g.token_list_.begin() + g.token_list_.size() - 2)); token_list.push_back(*(g.token_list_.begin() + g.token_list_.size() - 1)); ``` a65c8e8b ``` assert(token_list.size() <= g.token_list_.size()); ``` 4068375e ``` std::swap(token_list, g.token_list_); return changes; } const std::size_t stride_; }; namespace helper { inline void dump(const lexer::generator& generator) { for (std::size_t i = 0; i < generator.size(); ++i) { const lexer::token& t = generator[i]; printf("Token[%02d] @ %03d %6s --> '%s'\n", static_cast(i), static_cast(t.position), t.to_str(t.type).c_str(), t.value.c_str()); } } class commutative_inserter : public lexer::token_inserter { public: using lexer::token_inserter::insert; commutative_inserter() : lexer::token_inserter(2) {} inline void ignore_symbol(const std::string& symbol) { ignore_set_.insert(symbol); } inline int insert(const lexer::token& t0, const lexer::token& t1, lexer::token& new_token) { bool match = false; new_token.type = lexer::token::e_mul; new_token.value = "*"; new_token.position = t1.position; if (t0.type == lexer::token::e_symbol) { if (ignore_set_.end() != ignore_set_.find(t0.value)) { return -1; } else if (!t0.value.empty() && ('\$' == t0.value[0])) { return -1; } } if (t1.type == lexer::token::e_symbol) { if (ignore_set_.end() != ignore_set_.find(t1.value)) { return -1; } } ``` a65c8e8b ``` if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_symbol )) match = true; ``` 4068375e ``` 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; else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lsqrbracket)) match = true; else if ((t0.type == lexer::token::e_symbol ) && (t1.type == lexer::token::e_number )) match = true; else if ((t0.type == lexer::token::e_rbracket ) && (t1.type == lexer::token::e_number )) match = true; else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_number )) match = true; else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_number )) match = true; 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; else if ((t0.type == lexer::token::e_symbol ) && (t1.type == lexer::token::e_symbol )) match = true; return (match) ? 1 : -1; } private: std::set ignore_set_; }; class operator_joiner : public token_joiner { public: explicit operator_joiner(const std::size_t& stride) : token_joiner(stride) {} inline bool join(const lexer::token& t0, const lexer::token& t1, lexer::token& t) { // ': =' --> ':=' if ((t0.type == lexer::token::e_colon) && (t1.type == lexer::token::e_eq)) { t.type = lexer::token::e_assign; t.value = ":="; t.position = t0.position; return true; } // '+ =' --> '+=' else if ((t0.type == lexer::token::e_add) && (t1.type == lexer::token::e_eq)) { t.type = lexer::token::e_addass; t.value = "+="; t.position = t0.position; return true; } // '- =' --> '-=' else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_eq)) { t.type = lexer::token::e_subass; t.value = "-="; t.position = t0.position; return true; } // '* =' --> '*=' else if ((t0.type == lexer::token::e_mul) && (t1.type == lexer::token::e_eq)) { t.type = lexer::token::e_mulass; t.value = "*="; t.position = t0.position; return true; } // '/ =' --> '/=' else if ((t0.type == lexer::token::e_div) && (t1.type == lexer::token::e_eq)) { t.type = lexer::token::e_divass; t.value = "/="; t.position = t0.position; return true; } // '% =' --> '%=' else if ((t0.type == lexer::token::e_mod) && (t1.type == lexer::token::e_eq)) { t.type = lexer::token::e_modass; t.value = "%="; t.position = t0.position; return true; } // '> =' --> '>=' else if ((t0.type == lexer::token::e_gt) && (t1.type == lexer::token::e_eq)) { t.type = lexer::token::e_gte; t.value = ">="; t.position = t0.position; return true; } // '< =' --> '<=' else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_eq)) { t.type = lexer::token::e_lte; t.value = "<="; t.position = t0.position; return true; } // '= =' --> '==' else if ((t0.type == lexer::token::e_eq) && (t1.type == lexer::token::e_eq)) { t.type = lexer::token::e_eq; t.value = "=="; t.position = t0.position; return true; } // '! =' --> '!=' ``` a65c8e8b ``` else if ((static_cast(t0.type) == '!') && (t1.type == lexer::token::e_eq)) ``` 4068375e ``` { t.type = lexer::token::e_ne; t.value = "!="; t.position = t0.position; return true; } // '< >' --> '<>' else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_gt)) { t.type = lexer::token::e_ne; t.value = "<>"; t.position = t0.position; return true; } // '<= >' --> '<=>' else if ((t0.type == lexer::token::e_lte) && (t1.type == lexer::token::e_gt)) { t.type = lexer::token::e_swap; t.value = "<=>"; t.position = t0.position; return true; } // '+ -' --> '-' else if ((t0.type == lexer::token::e_add) && (t1.type == lexer::token::e_sub)) { t.type = lexer::token::e_sub; t.value = "-"; t.position = t0.position; return true; } // '- +' --> '-' else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_add)) { t.type = lexer::token::e_sub; t.value = "-"; t.position = t0.position; return true; } // '- -' --> '+' else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_sub)) { /* Note: May need to reconsider this when wanting to implement pre/postfix decrement operator */ t.type = lexer::token::e_add; t.value = "+"; t.position = t0.position; return true; } else return false; } ``` a65c8e8b ``` inline bool join(const lexer::token& t0, const lexer::token& t1, const lexer::token& t2, lexer::token& t) ``` 4068375e ``` { // '[ * ]' --> '[*]' if ( (t0.type == lexer::token::e_lsqrbracket) && (t1.type == lexer::token::e_mul ) && (t2.type == lexer::token::e_rsqrbracket) ) { t.type = lexer::token::e_symbol; t.value = "[*]"; t.position = t0.position; return true; } else return false; } }; class bracket_checker : public lexer::token_scanner { public: using lexer::token_scanner::operator(); bracket_checker() ``` a65c8e8b ``` : token_scanner(1) , state_(true) ``` 4068375e ``` {} bool result() { if (!stack_.empty()) { lexer::token t; t.value = stack_.top().first; t.position = stack_.top().second; error_token_ = t; state_ = false; return false; } else return state_; } lexer::token error_token() { return error_token_; } void reset() { // Why? because msvc doesn't support swap properly. stack_ = std::stack >(); state_ = true; error_token_.clear(); } bool operator() (const lexer::token& t) { if ( !t.value.empty() && (lexer::token::e_string != t.type) && (lexer::token::e_symbol != t.type) && exprtk::details::is_bracket(t.value[0]) ) { details::char_t c = t.value[0]; ``` a65c8e8b ``` if (t.type == lexer::token::e_lbracket ) stack_.push(std::make_pair(')',t.position)); ``` 4068375e ``` else if (t.type == lexer::token::e_lcrlbracket) stack_.push(std::make_pair('}',t.position)); else if (t.type == lexer::token::e_lsqrbracket) stack_.push(std::make_pair(']',t.position)); else if (exprtk::details::is_right_bracket(c)) { if (stack_.empty()) { state_ = false; error_token_ = t; return false; } else if (c != stack_.top().first) { state_ = false; error_token_ = t; return false; } else stack_.pop(); } } return true; } private: bool state_; std::stack > stack_; lexer::token error_token_; }; class numeric_checker : public lexer::token_scanner { public: using lexer::token_scanner::operator(); numeric_checker() ``` a65c8e8b ``` : token_scanner (1) , current_index_(0) ``` 4068375e ``` {} bool result() { return error_list_.empty(); } void reset() { error_list_.clear(); current_index_ = 0; } bool operator() (const lexer::token& t) { if (token::e_number == t.type) { double v; if (!exprtk::details::string_to_real(t.value,v)) { error_list_.push_back(current_index_); } } ++current_index_; return true; } std::size_t error_count() const { return error_list_.size(); } std::size_t error_index(const std::size_t& i) { if (i < error_list_.size()) return error_list_[i]; else return std::numeric_limits::max(); } void clear_errors() { error_list_.clear(); } private: std::size_t current_index_; std::vector error_list_; }; class symbol_replacer : public lexer::token_modifier { private: typedef std::map,details::ilesscompare> replace_map_t; public: bool remove(const std::string& target_symbol) { const replace_map_t::iterator itr = replace_map_.find(target_symbol); if (replace_map_.end() == itr) return false; replace_map_.erase(itr); return true; } bool add_replace(const std::string& target_symbol, const std::string& replace_symbol, const lexer::token::token_type token_type = lexer::token::e_symbol) { const 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; } void clear() { replace_map_.clear(); } private: bool modify(lexer::token& t) { if (lexer::token::e_symbol == t.type) { if (replace_map_.empty()) return false; const replace_map_t::iterator itr = replace_map_.find(t.value); if (replace_map_.end() != itr) { t.value = itr->second.first; t.type = itr->second.second; return true; } } return false; } replace_map_t replace_map_; }; class sequence_validator : public lexer::token_scanner { private: typedef std::pair token_pair_t; typedef std::set set_t; public: using lexer::token_scanner::operator(); sequence_validator() : lexer::token_scanner(2) { 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_set1(lexer::token::e_assign ); add_invalid_set1(lexer::token::e_shr ); add_invalid_set1(lexer::token::e_shl ); add_invalid_set1(lexer::token::e_lte ); add_invalid_set1(lexer::token::e_ne ); add_invalid_set1(lexer::token::e_gte ); add_invalid_set1(lexer::token::e_lt ); add_invalid_set1(lexer::token::e_gt ); add_invalid_set1(lexer::token::e_eq ); add_invalid_set1(lexer::token::e_comma ); add_invalid_set1(lexer::token::e_add ); add_invalid_set1(lexer::token::e_sub ); add_invalid_set1(lexer::token::e_div ); add_invalid_set1(lexer::token::e_mul ); add_invalid_set1(lexer::token::e_mod ); add_invalid_set1(lexer::token::e_pow ); add_invalid_set1(lexer::token::e_colon ); add_invalid_set1(lexer::token::e_ternary); } bool result() { return error_list_.empty(); } bool operator() (const lexer::token& t0, const lexer::token& t1) { const set_t::value_type p = std::make_pair(t0.type,t1.type); if (invalid_bracket_check(t0.type,t1.type)) { error_list_.push_back(std::make_pair(t0,t1)); } else if (invalid_comb_.find(p) != invalid_comb_.end()) { error_list_.push_back(std::make_pair(t0,t1)); } return true; } std::size_t error_count() const { return error_list_.size(); } std::pair error(const std::size_t index) { if (index < error_list_.size()) { return error_list_[index]; } else { static const lexer::token error_token; return std::make_pair(error_token,error_token); } } void clear_errors() { error_list_.clear(); } private: ``` a65c8e8b ``` void add_invalid(const lexer::token::token_type base, const lexer::token::token_type t) ``` 4068375e ``` { invalid_comb_.insert(std::make_pair(base,t)); } ``` a65c8e8b ``` void add_invalid_set1(const lexer::token::token_type t) ``` 4068375e ``` { add_invalid(t, lexer::token::e_assign); add_invalid(t, lexer::token::e_shr ); add_invalid(t, lexer::token::e_shl ); add_invalid(t, lexer::token::e_lte ); add_invalid(t, lexer::token::e_ne ); add_invalid(t, lexer::token::e_gte ); add_invalid(t, lexer::token::e_lt ); add_invalid(t, lexer::token::e_gt ); add_invalid(t, lexer::token::e_eq ); add_invalid(t, lexer::token::e_comma ); add_invalid(t, lexer::token::e_div ); add_invalid(t, lexer::token::e_mul ); add_invalid(t, lexer::token::e_mod ); add_invalid(t, lexer::token::e_pow ); add_invalid(t, lexer::token::e_colon ); } ``` a65c8e8b ``` bool invalid_bracket_check(const lexer::token::token_type base, const lexer::token::token_type t) ``` 4068375e ``` { ``` a65c8e8b ``` if (details::is_right_bracket(static_cast(base))) ``` 4068375e ``` { switch (t) { case lexer::token::e_assign : return (']' != base); case lexer::token::e_string : return (')' != base); default : return false; } } ``` a65c8e8b ``` else if (details::is_left_bracket(static_cast(base))) ``` 4068375e ``` { ``` a65c8e8b ``` if (details::is_right_bracket(static_cast(t))) ``` 4068375e ``` return false; ``` a65c8e8b ``` else if (details::is_left_bracket(static_cast(t))) ``` 4068375e ``` return false; else { switch (t) { case lexer::token::e_number : return false; case lexer::token::e_symbol : return false; case lexer::token::e_string : return false; case lexer::token::e_add : return false; case lexer::token::e_sub : return false; case lexer::token::e_colon : return false; case lexer::token::e_ternary : return false; default : return true ; } } } ``` a65c8e8b ``` else if (details::is_right_bracket(static_cast(t))) ``` 4068375e ``` { switch (base) { case lexer::token::e_number : return false; case lexer::token::e_symbol : return false; case lexer::token::e_string : return false; case lexer::token::e_eof : return false; case lexer::token::e_colon : return false; case lexer::token::e_ternary : return false; default : return true ; } } ``` a65c8e8b ``` else if (details::is_left_bracket(static_cast(t))) ``` 4068375e ``` { switch (base) { case lexer::token::e_rbracket : return true; case lexer::token::e_rsqrbracket : return true; case lexer::token::e_rcrlbracket : return true; default : return false; } } return false; } set_t invalid_comb_; std::vector > error_list_; }; class sequence_validator_3tokens : public lexer::token_scanner { private: typedef lexer::token::token_type token_t; typedef std::pair > token_triplet_t; typedef std::set set_t; public: using lexer::token_scanner::operator(); sequence_validator_3tokens() : lexer::token_scanner(3) { ``` a65c8e8b ``` add_invalid(lexer::token::e_number , lexer::token::e_number , lexer::token::e_number); add_invalid(lexer::token::e_string , lexer::token::e_string , lexer::token::e_string); add_invalid(lexer::token::e_comma , lexer::token::e_comma , lexer::token::e_comma ); ``` 4068375e ``` ``` a65c8e8b ``` add_invalid(lexer::token::e_add , lexer::token::e_add , lexer::token::e_add ); add_invalid(lexer::token::e_sub , lexer::token::e_sub , lexer::token::e_sub ); add_invalid(lexer::token::e_div , lexer::token::e_div , lexer::token::e_div ); add_invalid(lexer::token::e_mul , lexer::token::e_mul , lexer::token::e_mul ); add_invalid(lexer::token::e_mod , lexer::token::e_mod , lexer::token::e_mod ); add_invalid(lexer::token::e_pow , lexer::token::e_pow , lexer::token::e_pow ); ``` 4068375e ``` ``` a65c8e8b ``` add_invalid(lexer::token::e_add , lexer::token::e_sub , lexer::token::e_add ); add_invalid(lexer::token::e_sub , lexer::token::e_add , lexer::token::e_sub ); add_invalid(lexer::token::e_div , lexer::token::e_mul , lexer::token::e_div ); add_invalid(lexer::token::e_mul , lexer::token::e_div , lexer::token::e_mul ); add_invalid(lexer::token::e_mod , lexer::token::e_pow , lexer::token::e_mod ); add_invalid(lexer::token::e_pow , lexer::token::e_mod , lexer::token::e_pow ); ``` 4068375e ``` } bool result() { return error_list_.empty(); } bool operator() (const lexer::token& t0, const lexer::token& t1, const lexer::token& t2) { const set_t::value_type p = std::make_pair(t0.type,std::make_pair(t1.type,t2.type)); if (invalid_comb_.find(p) != invalid_comb_.end()) { error_list_.push_back(std::make_pair(t0,t1)); } return true; } std::size_t error_count() const { return error_list_.size(); } std::pair error(const std::size_t index) { if (index < error_list_.size()) { return error_list_[index]; } else { static const lexer::token error_token; return std::make_pair(error_token,error_token); } } void clear_errors() { error_list_.clear(); } private: ``` a65c8e8b ``` void add_invalid(const token_t t0, const token_t t1, const token_t t2) ``` 4068375e ``` { invalid_comb_.insert(std::make_pair(t0,std::make_pair(t1,t2))); } set_t invalid_comb_; std::vector > error_list_; }; struct helper_assembly { inline bool register_scanner(lexer::token_scanner* scanner) { if (token_scanner_list.end() != std::find(token_scanner_list.begin(), token_scanner_list.end (), scanner)) { return false; } token_scanner_list.push_back(scanner); return true; } inline bool register_modifier(lexer::token_modifier* modifier) { if (token_modifier_list.end() != std::find(token_modifier_list.begin(), token_modifier_list.end (), modifier)) { return false; } token_modifier_list.push_back(modifier); return true; } inline bool register_joiner(lexer::token_joiner* joiner) { if (token_joiner_list.end() != std::find(token_joiner_list.begin(), token_joiner_list.end (), joiner)) { return false; } token_joiner_list.push_back(joiner); return true; } inline bool register_inserter(lexer::token_inserter* inserter) { if (token_inserter_list.end() != std::find(token_inserter_list.begin(), token_inserter_list.end (), inserter)) { return false; } token_inserter_list.push_back(inserter); return true; } inline bool run_modifiers(lexer::generator& g) { error_token_modifier = reinterpret_cast(0); 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 true; } inline bool run_joiners(lexer::generator& g) { error_token_joiner = reinterpret_cast(0); 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 true; } inline bool run_inserters(lexer::generator& g) { error_token_inserter = reinterpret_cast(0); 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 true; } inline bool run_scanners(lexer::generator& g) { error_token_scanner = reinterpret_cast(0); 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 true; } std::vector token_scanner_list; std::vector token_modifier_list; std::vector token_joiner_list; std::vector token_inserter_list; lexer::token_scanner* error_token_scanner; lexer::token_modifier* error_token_modifier; lexer::token_joiner* error_token_joiner; lexer::token_inserter* error_token_inserter; }; } class parser_helper { public: ``` a65c8e8b ``` typedef token token_t; ``` 4068375e ``` typedef generator generator_t; inline bool init(const std::string& str) { if (!lexer_.process(str)) { return false; } lexer_.begin(); next_token(); return true; } inline generator_t& lexer() { return lexer_; } inline const generator_t& lexer() const { return lexer_; } inline void store_token() { lexer_.store(); store_current_token_ = current_token_; } inline void restore_token() { lexer_.restore(); current_token_ = store_current_token_; } inline void next_token() { current_token_ = lexer_.next_token(); } inline const token_t& current_token() const { return current_token_; } enum token_advance_mode { e_hold = 0, e_advance = 1 }; inline void advance_token(const token_advance_mode mode) { if (e_advance == mode) { next_token(); } } inline bool token_is(const token_t::token_type& ttype, const token_advance_mode mode = e_advance) { if (current_token().type != ttype) { return false; } advance_token(mode); return true; } inline bool token_is(const token_t::token_type& ttype, const std::string& value, const token_advance_mode mode = e_advance) { if ( (current_token().type != ttype) || !exprtk::details::imatch(value,current_token().value) ) { return false; } advance_token(mode); return true; } inline bool peek_token_is(const token_t::token_type& ttype) { return (lexer_.peek_next_token().type == ttype); } inline bool peek_token_is(const std::string& s) { return (exprtk::details::imatch(lexer_.peek_next_token().value,s)); } private: generator_t lexer_; token_t current_token_; token_t store_current_token_; }; } template class vector_view { public: typedef T* data_ptr_t; vector_view(data_ptr_t data, const std::size_t& size) ``` a65c8e8b ``` : size_(size) , data_(data) , data_ref_(0) ``` 4068375e ``` {} vector_view(const vector_view& vv) ``` a65c8e8b ``` : size_(vv.size_) , data_(vv.data_) , data_ref_(0) ``` 4068375e ``` {} inline void rebase(data_ptr_t data) { data_ = data; if (!data_ref_.empty()) { for (std::size_t i = 0; i < data_ref_.size(); ++i) { (*data_ref_[i]) = data; } } } inline data_ptr_t data() const { return data_; } inline std::size_t size() const { return size_; } inline const T& operator[](const std::size_t index) const { return data_[index]; } inline T& operator[](const std::size_t index) { return data_[index]; } void set_ref(data_ptr_t* data_ref) { data_ref_.push_back(data_ref); } private: const std::size_t size_; data_ptr_t data_; std::vector data_ref_; }; template inline vector_view make_vector_view(T* data, const std::size_t size, const std::size_t offset = 0) { return vector_view(data + offset, size); } template inline vector_view make_vector_view(std::vector& v, const std::size_t size, const std::size_t offset = 0) { return vector_view(v.data() + offset, size); } template class results_context; template struct type_store { enum store_type { e_unknown, e_scalar , e_vector , e_string }; type_store() ``` a65c8e8b ``` : data(0) , size(0) , type(e_unknown) ``` 4068375e ``` {} union { ``` a65c8e8b ``` void* data; T* vec_data; ``` 4068375e ``` }; std::size_t size; store_type type; class parameter_list { public: ``` a65c8e8b ``` explicit parameter_list(std::vector& pl) ``` 4068375e ``` : parameter_list_(pl) {} inline bool empty() const { return parameter_list_.empty(); } inline std::size_t size() const { return parameter_list_.size(); } inline type_store& operator[](const std::size_t& index) { return parameter_list_[index]; } inline const type_store& operator[](const std::size_t& index) const { return parameter_list_[index]; } inline type_store& front() { return parameter_list_[0]; } inline const type_store& front() const { return parameter_list_[0]; } inline type_store& back() { return parameter_list_.back(); } inline const type_store& back() const { return parameter_list_.back(); } private: std::vector& parameter_list_; friend class results_context; }; template struct type_view { typedef type_store type_store_t; typedef ViewType value_t; ``` a65c8e8b ``` explicit type_view(type_store_t& ts) : ts_(ts) , data_(reinterpret_cast(ts_.data)) ``` 4068375e ``` {} ``` a65c8e8b ``` explicit type_view(const type_store_t& ts) : ts_(const_cast(ts)) , data_(reinterpret_cast(ts_.data)) ``` 4068375e ``` {} inline std::size_t size() const { return ts_.size; } inline value_t& operator[](const std::size_t& i) { return data_[i]; } inline const value_t& operator[](const std::size_t& i) const { return data_[i]; } inline const value_t* begin() const { return data_; } inline value_t* begin() { return data_; } inline const value_t* end() const { return static_cast(data_ + ts_.size); } inline value_t* end() { return static_cast(data_ + ts_.size); } type_store_t& ts_; value_t* data_; }; typedef type_view vector_view; typedef type_view string_view; struct scalar_view { typedef type_store type_store_t; typedef T value_t; ``` a65c8e8b ``` explicit scalar_view(type_store_t& ts) ``` 4068375e ``` : v_(*reinterpret_cast(ts.data)) {} ``` a65c8e8b ``` explicit scalar_view(const type_store_t& ts) ``` 4068375e ``` : v_(*reinterpret_cast(const_cast(ts).data)) {} inline value_t& operator() () { return v_; } inline const value_t& operator() () const { return v_; } template inline bool to_int(IntType& i) const { if (!exprtk::details::numeric::is_integer(v_)) return false; i = static_cast(v_); return true; } template inline bool to_uint(UIntType& u) const { if (v_ < T(0)) return false; else if (!exprtk::details::numeric::is_integer(v_)) return false; u = static_cast(v_); return true; } T& v_; }; }; template inline std::string to_str(const StringView& view) { return std::string(view.begin(),view.size()); } #ifndef exprtk_disable_return_statement namespace details { template class return_node; template class return_envelope_node; } #endif template class results_context { public: typedef type_store type_store_t; results_context() : results_available_(false) {} inline std::size_t count() const { if (results_available_) return parameter_list_.size(); else return 0; } inline type_store_t& operator[](const std::size_t& index) { return parameter_list_[index]; } inline const type_store_t& operator[](const std::size_t& index) const { return parameter_list_[index]; } private: inline void clear() { results_available_ = false; } typedef std::vector ts_list_t; typedef typename type_store_t::parameter_list parameter_list_t; inline void assign(const parameter_list_t& pl) { parameter_list_ = pl.parameter_list_; results_available_ = true; } bool results_available_; ts_list_t parameter_list_; #ifndef exprtk_disable_return_statement friend class details::return_node; friend class details::return_envelope_node; #endif }; namespace details { enum operator_type { e_default , e_null , e_add , e_sub , e_mul , e_div , e_mod , e_pow , e_atan2 , e_min , e_max , e_avg , e_sum , e_prod , e_lt , e_lte , e_eq , e_equal , e_ne , e_nequal , e_gte , e_gt , e_and , e_nand , e_or , e_nor , e_xor , e_xnor , e_mand , e_mor , e_scand , e_scor , e_shr , e_shl , e_abs , e_acos , e_acosh , e_asin , e_asinh , e_atan , e_atanh , e_ceil , e_cos , e_cosh , e_exp , e_expm1 , e_floor , e_log , e_log10 , e_log2 , e_log1p , e_logn , e_neg , e_pos , e_round , e_roundn , e_root , e_sqrt , e_sin , e_sinc , e_sinh , e_sec , e_csc , e_tan , e_tanh , e_cot , e_clamp , e_iclamp , e_inrange , e_sgn , e_r2d , e_d2r , e_d2g , e_g2d , e_hypot , e_notl , e_erf , e_erfc , e_ncdf , e_frac , e_trunc , e_assign , e_addass , e_subass , e_mulass , e_divass , e_modass , e_in , e_like , e_ilike , e_multi , e_smulti , e_swap , // Do not add new functions/operators after this point. e_sf00 = 1000, e_sf01 = 1001, e_sf02 = 1002, e_sf03 = 1003, e_sf04 = 1004, e_sf05 = 1005, e_sf06 = 1006, e_sf07 = 1007, e_sf08 = 1008, e_sf09 = 1009, e_sf10 = 1010, e_sf11 = 1011, e_sf12 = 1012, e_sf13 = 1013, e_sf14 = 1014, e_sf15 = 1015, e_sf16 = 1016, e_sf17 = 1017, e_sf18 = 1018, e_sf19 = 1019, e_sf20 = 1020, e_sf21 = 1021, e_sf22 = 1022, e_sf23 = 1023, e_sf24 = 1024, e_sf25 = 1025, e_sf26 = 1026, e_sf27 = 1027, e_sf28 = 1028, e_sf29 = 1029, e_sf30 = 1030, e_sf31 = 1031, e_sf32 = 1032, e_sf33 = 1033, e_sf34 = 1034, e_sf35 = 1035, e_sf36 = 1036, e_sf37 = 1037, e_sf38 = 1038, e_sf39 = 1039, e_sf40 = 1040, e_sf41 = 1041, e_sf42 = 1042, e_sf43 = 1043, e_sf44 = 1044, e_sf45 = 1045, e_sf46 = 1046, e_sf47 = 1047, e_sf48 = 1048, e_sf49 = 1049, e_sf50 = 1050, e_sf51 = 1051, e_sf52 = 1052, e_sf53 = 1053, e_sf54 = 1054, e_sf55 = 1055, e_sf56 = 1056, e_sf57 = 1057, e_sf58 = 1058, e_sf59 = 1059, e_sf60 = 1060, e_sf61 = 1061, e_sf62 = 1062, e_sf63 = 1063, e_sf64 = 1064, e_sf65 = 1065, e_sf66 = 1066, e_sf67 = 1067, 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_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_sf98 = 1098, e_sf99 = 1099, e_sffinal = 1100, 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, e_sf4ext40 = 2040, e_sf4ext41 = 2041, e_sf4ext42 = 2042, e_sf4ext43 = 2043, e_sf4ext44 = 2044, e_sf4ext45 = 2045, e_sf4ext46 = 2046, e_sf4ext47 = 2047, e_sf4ext48 = 2048, e_sf4ext49 = 2049, e_sf4ext50 = 2050, e_sf4ext51 = 2051, e_sf4ext52 = 2052, e_sf4ext53 = 2053, e_sf4ext54 = 2054, e_sf4ext55 = 2055, e_sf4ext56 = 2056, e_sf4ext57 = 2057, e_sf4ext58 = 2058, e_sf4ext59 = 2059, e_sf4ext60 = 2060, e_sf4ext61 = 2061 }; inline std::string to_str(const operator_type opr) { switch (opr) { case e_add : return "+" ; case e_sub : return "-" ; case e_mul : return "*" ; case e_div : return "/" ; case e_mod : return "%" ; case e_pow : return "^" ; case e_assign : return ":=" ; case e_addass : return "+=" ; case e_subass : return "-=" ; case e_mulass : return "*=" ; case e_divass : return "/=" ; case e_modass : return "%=" ; case e_lt : return "<" ; case e_lte : return "<=" ; case e_eq : return "==" ; case e_equal : return "=" ; case e_ne : return "!=" ; case e_nequal : return "<>" ; case e_gte : return ">=" ; case e_gt : return ">" ; case e_and : return "and" ; case e_or : return "or" ; case e_xor : return "xor" ; case e_nand : return "nand"; case e_nor : return "nor" ; case e_xnor : return "xnor"; default : return "N/A" ; } } struct base_operation_t { base_operation_t(const operator_type t, const unsigned int& np) ``` a65c8e8b ``` : type(t) , num_params(np) ``` 4068375e ``` {} operator_type type; unsigned int num_params; }; namespace loop_unroll { #ifndef exprtk_disable_superscalar_unroll const unsigned int global_loop_batch_size = 16; #else const unsigned int global_loop_batch_size = 4; #endif struct details { explicit details(const std::size_t& vsize, const unsigned int loop_batch_size = global_loop_batch_size) ``` a65c8e8b ``` : batch_size(loop_batch_size ) , remainder (vsize % batch_size) , upper_bound(static_cast(vsize - (remainder ? loop_batch_size : 0))) ``` 4068375e ``` {} unsigned int batch_size; ``` a65c8e8b ``` int remainder; ``` 4068375e ``` int upper_bound; }; } #ifdef exprtk_enable_debugging inline void dump_ptr(const std::string& s, const void* ptr, const std::size_t size = 0) { if (size) exprtk_debug(("%s - addr: %p\n",s.c_str(),ptr)); else exprtk_debug(("%s - addr: %p size: %d\n", s.c_str(), ptr, static_cast(size))); } #else inline void dump_ptr(const std::string&, const void*) {} inline void dump_ptr(const std::string&, const void*, const std::size_t) {} #endif template class vec_data_store { public: typedef vec_data_store type; typedef T* data_t; private: struct control_block { control_block() ``` a65c8e8b ``` : ref_count(1) , size (0) , data (0) , destruct (true) ``` 4068375e ``` {} ``` a65c8e8b ``` explicit control_block(const std::size_t& dsize) : ref_count(1 ) , size (dsize) , data (0 ) , destruct (true ) ``` 4068375e ``` { create_data(); } control_block(const std::size_t& dsize, data_t dptr, bool dstrct = false) ``` a65c8e8b ``` : ref_count(1 ) , size (dsize ) , data (dptr ) , destruct (dstrct) ``` 4068375e ``` {} ~control_block() { if (data && destruct && (0 == ref_count)) { dump_ptr("~control_block() data",data); delete[] data; data = reinterpret_cast(0); } } static inline control_block* create(const std::size_t& dsize, data_t data_ptr = data_t(0), bool dstrct = false) { if (dsize) { if (0 == data_ptr) return (new control_block(dsize)); else return (new control_block(dsize, data_ptr, dstrct)); } else return (new control_block); } static inline void destroy(control_block*& cntrl_blck) { if (cntrl_blck) { if ( (0 != cntrl_blck->ref_count) && (0 == --cntrl_blck->ref_count) ) { delete cntrl_blck; } cntrl_blck = 0; } } std::size_t ref_count; std::size_t size; data_t data; bool destruct; private: ``` a65c8e8b ``` control_block(const control_block&) exprtk_delete; control_block& operator=(const control_block&) exprtk_delete; ``` 4068375e ``` inline void create_data() { destruct = true; data = new T[size]; ``` a65c8e8b ``` std::fill_n(data, size, T(0)); dump_ptr("control_block::create_data() - data", data, size); ``` 4068375e ``` } }; public: vec_data_store() : control_block_(control_block::create(0)) {} ``` a65c8e8b ``` explicit vec_data_store(const std::size_t& size) : control_block_(control_block::create(size,reinterpret_cast(0),true)) ``` 4068375e ``` {} vec_data_store(const std::size_t& size, data_t data, bool dstrct = false) : control_block_(control_block::create(size, data, dstrct)) {} vec_data_store(const type& vds) { control_block_ = vds.control_block_; control_block_->ref_count++; } ~vec_data_store() { control_block::destroy(control_block_); } type& operator=(const type& vds) { if (this != &vds) { std::size_t final_size = min_size(control_block_, vds.control_block_); vds.control_block_->size = final_size; control_block_->size = final_size; if (control_block_->destruct || (0 == control_block_->data)) { control_block::destroy(control_block_); control_block_ = vds.control_block_; control_block_->ref_count++; } } return (*this); } inline data_t data() { return control_block_->data; } inline data_t data() const { return control_block_->data; } inline std::size_t size() const { return control_block_->size; } inline data_t& ref() { return control_block_->data; } inline void dump() const { #ifdef exprtk_enable_debugging exprtk_debug(("size: %d\taddress:%p\tdestruct:%c\n", size(), data(), (control_block_->destruct ? 'T' : 'F'))); for (std::size_t i = 0; i < size(); ++i) { if (5 == i) exprtk_debug(("\n")); exprtk_debug(("%15.10f ",data()[i])); } exprtk_debug(("\n")); #endif } static inline void match_sizes(type& vds0, type& vds1) { const std::size_t size = min_size(vds0.control_block_,vds1.control_block_); vds0.control_block_->size = size; vds1.control_block_->size = size; } private: ``` a65c8e8b ``` static inline std::size_t min_size(const control_block* cb0, const control_block* cb1) ``` 4068375e ``` { const std::size_t size0 = cb0->size; const std::size_t size1 = cb1->size; if (size0 && size1) return std::min(size0,size1); else return (size0) ? size0 : size1; } control_block* control_block_; }; namespace numeric { namespace details { template inline T process_impl(const operator_type operation, const T arg) { switch (operation) { case e_abs : return numeric::abs (arg); case e_acos : return numeric::acos (arg); case e_acosh : return numeric::acosh(arg); case e_asin : return numeric::asin (arg); case e_asinh : return numeric::asinh(arg); case e_atan : return numeric::atan (arg); case e_atanh : return numeric::atanh(arg); case e_ceil : return numeric::ceil (arg); case e_cos : return numeric::cos (arg); case e_cosh : return numeric::cosh (arg); case e_exp : return numeric::exp (arg); case e_expm1 : return numeric::expm1(arg); case e_floor : return numeric::floor(arg); case e_log : return numeric::log (arg); case e_log10 : return numeric::log10(arg); case e_log2 : return numeric::log2 (arg); case e_log1p : return numeric::log1p(arg); case e_neg : return numeric::neg (arg); case e_pos : return numeric::pos (arg); case e_round : return numeric::round(arg); case e_sin : return numeric::sin (arg); case e_sinc : return numeric::sinc (arg); case e_sinh : return numeric::sinh (arg); case e_sqrt : return numeric::sqrt (arg); case e_tan : return numeric::tan (arg); case e_tanh : return numeric::tanh (arg); case e_cot : return numeric::cot (arg); case e_sec : return numeric::sec (arg); case e_csc : return numeric::csc (arg); case e_r2d : return numeric::r2d (arg); case e_d2r : return numeric::d2r (arg); case e_d2g : return numeric::d2g (arg); case e_g2d : return numeric::g2d (arg); case e_notl : return numeric::notl (arg); case e_sgn : return numeric::sgn (arg); case e_erf : return numeric::erf (arg); case e_erfc : return numeric::erfc (arg); case e_ncdf : return numeric::ncdf (arg); case e_frac : return numeric::frac (arg); case e_trunc : return numeric::trunc(arg); default : exprtk_debug(("numeric::details::process_impl - Invalid unary operation.\n")); return std::numeric_limits::quiet_NaN(); } } template inline T process_impl(const operator_type operation, const T arg0, const T arg1) { switch (operation) { case e_add : return (arg0 + arg1); case e_sub : return (arg0 - arg1); case e_mul : return (arg0 * arg1); case e_div : return (arg0 / arg1); case e_mod : return modulus(arg0,arg1); case e_pow : return pow(arg0,arg1); case e_atan2 : return atan2(arg0,arg1); case e_min : return std::min(arg0,arg1); case e_max : return std::max(arg0,arg1); case e_logn : return logn(arg0,arg1); case e_lt : return (arg0 < arg1) ? T(1) : T(0); case e_lte : return (arg0 <= arg1) ? T(1) : T(0); case e_eq : return std::equal_to()(arg0,arg1) ? T(1) : T(0); case e_ne : return std::not_equal_to()(arg0,arg1) ? T(1) : T(0); case e_gte : return (arg0 >= arg1) ? T(1) : T(0); case e_gt : return (arg0 > arg1) ? T(1) : T(0); case e_and : return and_opr (arg0,arg1); case e_nand : return nand_opr(arg0,arg1); case e_or : return or_opr (arg0,arg1); case e_nor : return nor_opr (arg0,arg1); case e_xor : return xor_opr (arg0,arg1); case e_xnor : return xnor_opr(arg0,arg1); case e_root : return root (arg0,arg1); case e_roundn : return roundn (arg0,arg1); case e_equal : return equal (arg0,arg1); case e_nequal : return nequal (arg0,arg1); case e_hypot : return hypot (arg0,arg1); case e_shr : return shr (arg0,arg1); case e_shl : return shl (arg0,arg1); default : exprtk_debug(("numeric::details::process_impl - Invalid binary operation.\n")); return std::numeric_limits::quiet_NaN(); } } template inline T process_impl(const operator_type operation, const T arg0, const T arg1, int_type_tag) { switch (operation) { case e_add : return (arg0 + arg1); case e_sub : return (arg0 - arg1); case e_mul : return (arg0 * arg1); case e_div : return (arg0 / arg1); case e_mod : return arg0 % arg1; case e_pow : return pow(arg0,arg1); case e_min : return std::min(arg0,arg1); case e_max : return std::max(arg0,arg1); case e_logn : return logn(arg0,arg1); case e_lt : return (arg0 < arg1) ? T(1) : T(0); case e_lte : return (arg0 <= arg1) ? T(1) : T(0); case e_eq : return (arg0 == arg1) ? T(1) : T(0); case e_ne : return (arg0 != arg1) ? T(1) : T(0); case e_gte : return (arg0 >= arg1) ? T(1) : T(0); case e_gt : return (arg0 > arg1) ? T(1) : T(0); case e_and : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(1) : T(0); case e_nand : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(0) : T(1); case e_or : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(1) : T(0); case e_nor : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(0) : T(1); case e_xor : return arg0 ^ arg1; case e_xnor : return !(arg0 ^ arg1); case e_root : return root(arg0,arg1); case e_equal : return arg0 == arg1; case e_nequal : return arg0 != arg1; case e_hypot : return hypot(arg0,arg1); case e_shr : return arg0 >> arg1; case e_shl : return arg0 << arg1; default : exprtk_debug(("numeric::details::process_impl - Invalid binary operation.\n")); return std::numeric_limits::quiet_NaN(); } } } template inline T process(const operator_type operation, const T arg) { return exprtk::details::numeric::details::process_impl(operation,arg); } template inline T process(const operator_type operation, const T arg0, const T arg1) { return exprtk::details::numeric::details::process_impl(operation, arg0, arg1); } } template struct node_collector_interface { typedef Node* node_ptr_t; typedef Node** node_pp_t; typedef std::vector noderef_list_t; virtual ~node_collector_interface() {} virtual void collect_nodes(noderef_list_t&) {} }; template struct node_depth_base; template class expression_node : public node_collector_interface >, public node_depth_base > { public: enum node_type { e_none , e_null , e_constant , e_unary , e_binary , e_binary_ext , e_trinary , e_quaternary , e_vararg , e_conditional , e_while , e_repeat , e_for , e_switch , e_mswitch , e_return , e_retenv , e_variable , e_stringvar , e_stringconst , e_stringvarrng , e_cstringvarrng , e_strgenrange , e_strconcat , e_stringvarsize , e_strswap , e_stringsize , e_stringvararg , e_function , e_vafunction , e_genfunction , e_strfunction , e_strcondition , e_strccondition , e_add , e_sub , e_mul , e_div , e_mod , e_pow , e_lt , e_lte , e_gt , e_gte , e_eq , e_ne , e_and , e_nand , e_or , e_nor , e_xor , e_xnor , e_in , e_like , e_ilike , e_inranges , e_ipow , e_ipowinv , e_abs , e_acos , e_acosh , e_asin , e_asinh , e_atan , e_atanh , e_ceil , e_cos , e_cosh , e_exp , e_expm1 , e_floor , e_log , e_log10 , e_log2 , e_log1p , e_neg , e_pos , e_round , e_sin , e_sinc , e_sinh , e_sqrt , e_tan , e_tanh , e_cot , e_sec , e_csc , e_r2d , e_d2r , e_d2g , e_g2d , e_notl , e_sgn , e_erf , e_erfc , e_ncdf , e_frac , 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 , e_sf3ext , e_sf4ext , e_nulleq , e_strass , e_vector , e_vecelem , e_rbvecelem , e_rbveccelem , e_vecdefass , e_vecvalass , e_vecvecass , e_vecopvalass , e_vecopvecass , e_vecfunc , e_vecvecswap , e_vecvecineq , e_vecvalineq , e_valvecineq , e_vecvecarith , e_vecvalarith , ``` a65c8e8b ``` e_valvecarith , e_vecunaryop , e_vecondition , e_break , e_continue , e_swap ``` 4068375e ``` }; typedef T value_type; typedef expression_node* expression_ptr; typedef node_collector_interface > nci_t; typedef typename nci_t::noderef_list_t noderef_list_t; typedef node_depth_base > ndb_t; ``` a65c8e8b ``` virtual ~expression_node() {} ``` 4068375e ``` inline virtual T value() const { return std::numeric_limits::quiet_NaN(); } inline virtual expression_node* branch(const std::size_t& index = 0) const { return reinterpret_cast(index * 0); } inline virtual node_type type() const { return e_none; } ``` a65c8e8b ``` }; // class expression_node ``` 4068375e ``` template inline bool is_generally_string_node(const expression_node* node); inline bool is_true(const double v) { return std::not_equal_to()(0.0,v); } inline bool is_true(const long double v) { return std::not_equal_to()(0.0L,v); } inline bool is_true(const float v) { return std::not_equal_to()(0.0f,v); } template inline bool is_true(const std::complex& v) { return std::not_equal_to >()(std::complex(0),v); } template inline bool is_true(const expression_node* node) { return std::not_equal_to()(T(0),node->value()); } ``` a65c8e8b ``` template inline bool is_true(const std::pair*,bool>& node) { return std::not_equal_to()(T(0),node.first->value()); } ``` 4068375e ``` template inline bool is_false(const expression_node* node) { return std::equal_to()(T(0),node->value()); } ``` a65c8e8b ``` template inline bool is_false(const std::pair*,bool>& node) { return std::equal_to()(T(0),node.first->value()); } ``` 4068375e ``` template inline bool is_unary_node(const expression_node* node) { return node && (details::expression_node::e_unary == node->type()); } template inline bool is_neg_unary_node(const expression_node* node) { return node && (details::expression_node::e_neg == node->type()); } template inline bool is_binary_node(const expression_node* node) { return node && (details::expression_node::e_binary == node->type()); } template inline bool is_variable_node(const expression_node* node) { return node && (details::expression_node::e_variable == node->type()); } template inline bool is_ivariable_node(const expression_node* node) { return node && ( details::expression_node::e_variable == node->type() || details::expression_node::e_vecelem == node->type() || details::expression_node::e_rbvecelem == node->type() || details::expression_node::e_rbveccelem == node->type() ); } template inline bool is_vector_elem_node(const expression_node* node) { return node && (details::expression_node::e_vecelem == node->type()); } template inline bool is_rebasevector_elem_node(const expression_node* node) { return node && (details::expression_node::e_rbvecelem == node->type()); } template inline bool is_rebasevector_celem_node(const expression_node* node) { return node && (details::expression_node::e_rbveccelem == node->type()); } template inline bool is_vector_node(const expression_node* node) { return node && (details::expression_node::e_vector == node->type()); } template inline bool is_ivector_node(const expression_node* node) { if (node) { switch (node->type()) { case details::expression_node::e_vector : case details::expression_node::e_vecvalass : case details::expression_node::e_vecvecass : case details::expression_node::e_vecopvalass : case details::expression_node::e_vecopvecass : case details::expression_node::e_vecvecswap : case details::expression_node::e_vecvecarith : case details::expression_node::e_vecvalarith : case details::expression_node::e_valvecarith : ``` a65c8e8b ``` case details::expression_node::e_vecunaryop : case details::expression_node::e_vecondition : return true; ``` 4068375e ``` default : return false; } } else return false; } template inline bool is_constant_node(const expression_node* node) { return node && (details::expression_node::e_constant == node->type()); } template inline bool is_null_node(const expression_node* node) { return node && (details::expression_node::e_null == node->type()); } template inline bool is_break_node(const expression_node* node) { return node && (details::expression_node::e_break == node->type()); } template inline bool is_continue_node(const expression_node* node) { return node && (details::expression_node::e_continue == node->type()); } template inline bool is_swap_node(const expression_node* node) { return node && (details::expression_node::e_swap == node->type()); } template inline bool is_function(const expression_node* node) { return node && (details::expression_node::e_function == node->type()); } template inline bool is_return_node(const expression_node* node) { return node && (details::expression_node::e_return == node->type()); } template class unary_node; template inline bool is_negate_node(const expression_node* node) { if (node && is_unary_node(node)) { return (details::e_neg == static_cast*>(node)->operation()); } else return false; } template inline bool branch_deletable(expression_node* node) { return (0 != node) && !is_variable_node(node) && !is_string_node (node) ; } template inline bool all_nodes_valid(expression_node* (&b)[N]) { for (std::size_t i = 0; i < N; ++i) { if (0 == b[i]) return false; } return true; } template class Sequence> inline bool all_nodes_valid(const Sequence*,Allocator>& b) { for (std::size_t i = 0; i < b.size(); ++i) { if (0 == b[i]) return false; } return true; } template inline bool all_nodes_variables(expression_node* (&b)[N]) { for (std::size_t i = 0; i < N; ++i) { if (0 == b[i]) return false; else if (!is_variable_node(b[i])) return false; } return true; } template class Sequence> inline bool all_nodes_variables(Sequence*,Allocator>& b) { for (std::size_t i = 0; i < b.size(); ++i) { if (0 == b[i]) return false; else if (!is_variable_node(b[i])) return false; } return true; } template class node_collection_destructor { public: typedef node_collector_interface nci_t; typedef typename nci_t::node_ptr_t node_ptr_t; typedef typename nci_t::node_pp_t node_pp_t; typedef typename nci_t::noderef_list_t noderef_list_t; static void delete_nodes(node_ptr_t& root) { std::vector node_delete_list; node_delete_list.reserve(1000); collect_nodes(root, node_delete_list); for (std::size_t i = 0; i < node_delete_list.size(); ++i) { node_ptr_t& node = *node_delete_list[i]; exprtk_debug(("ncd::delete_nodes() - deleting: %p\n", static_cast(node))); delete node; node = reinterpret_cast(0); } } private: static void collect_nodes(node_ptr_t& root, noderef_list_t& node_delete_list) { std::deque node_list; node_list.push_back(root); node_delete_list.push_back(&root); noderef_list_t child_node_delete_list; child_node_delete_list.reserve(1000); while (!node_list.empty()) { node_list.front()->collect_nodes(child_node_delete_list); if (!child_node_delete_list.empty()) { for (std::size_t i = 0; i < child_node_delete_list.size(); ++i) { node_pp_t& node = child_node_delete_list[i]; if (0 == (*node)) { exprtk_debug(("ncd::collect_nodes() - null node encountered.\n")); } node_list.push_back(*node); } node_delete_list.insert( node_delete_list.end(), child_node_delete_list.begin(), child_node_delete_list.end()); child_node_delete_list.clear(); } node_list.pop_front(); } std::reverse(node_delete_list.begin(), node_delete_list.end()); } }; template inline void free_all_nodes(NodeAllocator& node_allocator, expression_node* (&b)[N]) { for (std::size_t i = 0; i < N; ++i) { free_node(node_allocator,b[i]); } } template class Sequence> inline void free_all_nodes(NodeAllocator& node_allocator, Sequence*,Allocator>& b) { for (std::size_t i = 0; i < b.size(); ++i) { free_node(node_allocator,b[i]); } b.clear(); } template inline void free_node(NodeAllocator&, expression_node*& node) { if ((0 == node) || is_variable_node(node) || is_string_node(node)) { return; } node_collection_destructor > ::delete_nodes(node); } template inline void destroy_node(expression_node*& node) { if (0 != node) { node_collection_destructor > ::delete_nodes(node); } } template struct node_depth_base { ``` a65c8e8b ``` typedef Node* node_ptr_t; typedef std::pair nb_pair_t; ``` 4068375e ``` node_depth_base() ``` a65c8e8b ``` : depth_set(false) , depth(0) ``` 4068375e ``` {} virtual ~node_depth_base() {} virtual std::size_t node_depth() const { return 1; } std::size_t compute_node_depth(const Node* const& node) const { if (!depth_set) { depth = 1 + (node ? node->node_depth() : 0); depth_set = true; } return depth; } ``` a65c8e8b ``` std::size_t compute_node_depth(const nb_pair_t& branch) const ``` 4068375e ``` { if (!depth_set) { depth = 1 + (branch.first ? branch.first->node_depth() : 0); depth_set = true; } return depth; } template ``` a65c8e8b ``` std::size_t compute_node_depth(const nb_pair_t (&branch)[N]) const ``` 4068375e ``` { if (!depth_set) { depth = 0; for (std::size_t i = 0; i < N; ++i) { if (branch[i].first) { depth = std::max(depth,branch[i].first->node_depth()); } } depth += 1; depth_set = true; } return depth; } template std::size_t compute_node_depth(const BranchType& n0, const BranchType& n1) const { if (!depth_set) { depth = 1 + std::max(compute_node_depth(n0), compute_node_depth(n1)); depth_set = true; } return depth; } template std::size_t compute_node_depth(const BranchType& n0, const BranchType& n1, const BranchType& n2) const { if (!depth_set) { depth = 1 + std::max( std::max(compute_node_depth(n0), compute_node_depth(n1)), compute_node_depth(n2)); depth_set = true; } return depth; } template std::size_t compute_node_depth(const BranchType& n0, const BranchType& n1, const BranchType& n2, const BranchType& n3) const { if (!depth_set) { depth = 1 + std::max( std::max(compute_node_depth(n0), compute_node_depth(n1)), std::max(compute_node_depth(n2), compute_node_depth(n3))); depth_set = true; } return depth; } template class Sequence> ``` a65c8e8b ``` std::size_t compute_node_depth(const Sequence& branch_list) const ``` 4068375e ``` { if (!depth_set) { for (std::size_t i = 0; i < branch_list.size(); ++i) { if (branch_list[i]) { depth = std::max(depth, compute_node_depth(branch_list[i])); } } depth_set = true; } return depth; } template class Sequence> ``` a65c8e8b ``` std::size_t compute_node_depth(const Sequence& branch_list) const ``` 4068375e ``` { if (!depth_set) { for (std::size_t i = 0; i < branch_list.size(); ++i) { if (branch_list[i].first) { depth = std::max(depth, compute_node_depth(branch_list[i].first)); } } depth_set = true; } return depth; } mutable bool depth_set; mutable std::size_t depth; template ``` a65c8e8b ``` void collect(node_ptr_t const& node, ``` 4068375e ``` const bool deletable, NodeSequence& delete_node_list) const { if ((0 != node) && deletable) { ``` a65c8e8b ``` delete_node_list.push_back(const_cast(&node)); ``` 4068375e ``` } } template ``` a65c8e8b ``` void collect(const nb_pair_t& branch, ``` 4068375e ``` NodeSequence& delete_node_list) const { collect(branch.first, branch.second, delete_node_list); } template void collect(Node*& node, NodeSequence& delete_node_list) const { collect(node, branch_deletable(node), delete_node_list); } template ``` a65c8e8b ``` void collect(const nb_pair_t(&branch)[N], ``` 4068375e ``` NodeSequence& delete_node_list) const { for (std::size_t i = 0; i < N; ++i) { collect(branch[i].first, branch[i].second, delete_node_list); } } template class Sequence, typename NodeSequence> ``` a65c8e8b ``` void collect(const Sequence& branch, ``` 4068375e ``` NodeSequence& delete_node_list) const { for (std::size_t i = 0; i < branch.size(); ++i) { collect(branch[i].first, branch[i].second, delete_node_list); } } template class Sequence, typename NodeSequence> ``` a65c8e8b ``` void collect(const Sequence& branch_list, ``` 4068375e ``` NodeSequence& delete_node_list) const { for (std::size_t i = 0; i < branch_list.size(); ++i) { collect(branch_list[i], branch_deletable(branch_list[i]), delete_node_list); } } template class Sequence, typename NodeSequence> ``` a65c8e8b ``` void collect(const Sequence& branch_list, ``` 4068375e ``` const Sequence& branch_deletable_list, NodeSequence& delete_node_list) const { for (std::size_t i = 0; i < branch_list.size(); ++i) { collect(branch_list[i], branch_deletable_list[i], delete_node_list); } } }; template class vector_holder { private: typedef Type value_type; typedef value_type* value_ptr; typedef const value_ptr const_value_ptr; class vector_holder_base { public: virtual ~vector_holder_base() {} inline value_ptr operator[](const std::size_t& index) const { return value_at(index); } inline std::size_t size() const { return vector_size(); } inline value_ptr data() const { return value_at(0); } virtual inline bool rebaseable() const { return false; } virtual void set_ref(value_ptr*) {} protected: virtual value_ptr value_at(const std::size_t&) const = 0; virtual std::size_t vector_size() const = 0; }; class array_vector_impl : public vector_holder_base { public: array_vector_impl(const Type* vec, const std::size_t& vec_size) ``` a65c8e8b ``` : vec_(vec) , size_(vec_size) ``` 4068375e ``` {} protected: value_ptr value_at(const std::size_t& index) const { if (index < size_) return const_cast(vec_ + index); else return const_value_ptr(0); } std::size_t vector_size() const { return size_; } private: ``` a65c8e8b ``` array_vector_impl(const array_vector_impl&) exprtk_delete; array_vector_impl& operator=(const array_vector_impl&) exprtk_delete; ``` 4068375e ``` const Type* vec_; const std::size_t size_; }; template class Sequence> class sequence_vector_impl : public vector_holder_base { public: typedef Sequence sequence_t; sequence_vector_impl(sequence_t& seq) : sequence_(seq) {} protected: value_ptr value_at(const std::size_t& index) const { return (index < sequence_.size()) ? (&sequence_[index]) : const_value_ptr(0); } std::size_t vector_size() const { return sequence_.size(); } private: ``` a65c8e8b ``` sequence_vector_impl(const sequence_vector_impl&) exprtk_delete; sequence_vector_impl& operator=(const sequence_vector_impl&) exprtk_delete; ``` 4068375e ``` sequence_t& sequence_; }; class vector_view_impl : public vector_holder_base { public: typedef exprtk::vector_view vector_view_t; vector_view_impl(vector_view_t& vec_view) : vec_view_(vec_view) {} void set_ref(value_ptr* ref) { vec_view_.set_ref(ref); } virtual inline bool rebaseable() const { return true; } protected: value_ptr value_at(const std::size_t& index) const { return (index < vec_view_.size()) ? (&vec_view_[index]) : const_value_ptr(0); } std::size_t vector_size() const { return vec_view_.size(); } private: ``` a65c8e8b ``` vector_view_impl(const vector_view_impl&) exprtk_delete; vector_view_impl& operator=(const vector_view_impl&) exprtk_delete; ``` 4068375e ``` vector_view_t& vec_view_; }; public: typedef typename details::vec_data_store vds_t; vector_holder(Type* vec, const std::size_t& vec_size) : vector_holder_base_(new(buffer)array_vector_impl(vec,vec_size)) {} vector_holder(const vds_t& vds) : vector_holder_base_(new(buffer)array_vector_impl(vds.data(),vds.size())) {} template vector_holder(std::vector& vec) : vector_holder_base_(new(buffer)sequence_vector_impl(vec)) {} vector_holder(exprtk::vector_view& vec) : vector_holder_base_(new(buffer)vector_view_impl(vec)) {} inline value_ptr operator[](const std::size_t& index) const { return (*vector_holder_base_)[index]; } inline std::size_t size() const { return vector_holder_base_->size(); } inline value_ptr data() const { return vector_holder_base_->data(); } void set_ref(value_ptr* ref) { vector_holder_base_->set_ref(ref); } bool rebaseable() const { return vector_holder_base_->rebaseable(); } private: mutable vector_holder_base* vector_holder_base_; uchar_t buffer[64]; }; template ``` a65c8e8b ``` class null_node exprtk_final : public expression_node ``` 4068375e ``` { public: ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { return std::numeric_limits::quiet_NaN(); } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_null; } }; template inline void construct_branch_pair(std::pair*,bool> (&branch)[N], expression_node* b, const std::size_t& index) { if (b && (index < N)) { branch[index] = std::make_pair(b,branch_deletable(b)); } } template inline void construct_branch_pair(std::pair*,bool>& branch, expression_node* b) { if (b) { branch = std::make_pair(b,branch_deletable(b)); } } template inline void init_branches(std::pair*,bool> (&branch)[N], expression_node* b0, expression_node* b1 = reinterpret_cast*>(0), expression_node* b2 = reinterpret_cast*>(0), expression_node* b3 = reinterpret_cast*>(0), expression_node* b4 = reinterpret_cast*>(0), expression_node* b5 = reinterpret_cast*>(0), expression_node* b6 = reinterpret_cast*>(0), expression_node* b7 = reinterpret_cast*>(0), expression_node* b8 = reinterpret_cast*>(0), expression_node* b9 = reinterpret_cast*>(0)) { construct_branch_pair(branch, b0, 0); construct_branch_pair(branch, b1, 1); construct_branch_pair(branch, b2, 2); construct_branch_pair(branch, b3, 3); construct_branch_pair(branch, b4, 4); construct_branch_pair(branch, b5, 5); construct_branch_pair(branch, b6, 6); construct_branch_pair(branch, b7, 7); construct_branch_pair(branch, b8, 8); construct_branch_pair(branch, b9, 9); } template ``` a65c8e8b ``` class null_eq_node exprtk_final : public expression_node ``` 4068375e ``` { public: typedef expression_node* expression_ptr; typedef std::pair branch_t; ``` a65c8e8b ``` explicit null_eq_node(expression_ptr branch, const bool equality = true) ``` 4068375e ``` : equality_(equality) { ``` a65c8e8b ``` construct_branch_pair(branch_, branch); ``` 4068375e ``` } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { ``` a65c8e8b ``` assert(branch_.first); ``` 4068375e ``` const T v = branch_.first->value(); const bool result = details::numeric::is_nan(v); if (result) return (equality_) ? T(1) : T(0); else return (equality_) ? T(0) : T(1); } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_nulleq; } ``` a65c8e8b ``` inline expression_node* branch(const std::size_t&) const exprtk_override ``` 4068375e ``` { return branch_.first; } ``` a65c8e8b ``` void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override ``` 4068375e ``` { ``` a65c8e8b ``` expression_node::ndb_t::collect(branch_, node_delete_list); ``` 4068375e ``` } ``` a65c8e8b ``` std::size_t node_depth() const exprtk_override ``` 4068375e ``` { return expression_node::ndb_t::compute_node_depth(branch_); } private: bool equality_; branch_t branch_; }; template ``` a65c8e8b ``` class literal_node exprtk_final : public expression_node ``` 4068375e ``` { public: explicit literal_node(const T& v) : value_(v) {} ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { return value_; } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_constant; } ``` a65c8e8b ``` inline expression_node* branch(const std::size_t&) const exprtk_override ``` 4068375e ``` { return reinterpret_cast*>(0); } private: ``` a65c8e8b ``` literal_node(const literal_node&) exprtk_delete; literal_node& operator=(const literal_node&) exprtk_delete; ``` 4068375e ``` const T value_; }; template struct range_pack; template struct range_data_type; template class range_interface { public: typedef range_pack range_t; ``` a65c8e8b ``` virtual ~range_interface() {} ``` 4068375e ``` virtual range_t& range_ref() = 0; virtual const range_t& range_ref() const = 0; }; #ifndef exprtk_disable_string_capabilities template class string_base_node { public: typedef range_data_type range_data_type_t; ``` a65c8e8b ``` virtual ~string_base_node() {} ``` 4068375e ``` virtual std::string str () const = 0; virtual char_cptr base() const = 0; virtual std::size_t size() const = 0; }; template ``` a65c8e8b ``` class string_literal_node exprtk_final : public expression_node , ``` 4068375e ``` public string_base_node, public range_interface { public: typedef range_pack range_t; explicit string_literal_node(const std::string& v) : value_(v) { rp_.n0_c = std::make_pair(true,0); rp_.n1_c = std::make_pair(true,v.size() - 1); rp_.cache.first = rp_.n0_c.second; rp_.cache.second = rp_.n1_c.second; } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { return std::numeric_limits::quiet_NaN(); } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_stringconst; } ``` a65c8e8b ``` inline expression_node* branch(const std::size_t&) const exprtk_override ``` 4068375e ``` { return reinterpret_cast*>(0); } ``` a65c8e8b ``` std::string str() const exprtk_override ``` 4068375e ``` { return value_; } ``` a65c8e8b ``` char_cptr base() const exprtk_override ``` 4068375e ``` { return value_.data(); } ``` a65c8e8b ``` std::size_t size() const exprtk_override ``` 4068375e ``` { return value_.size(); } ``` a65c8e8b ``` range_t& range_ref() exprtk_override ``` 4068375e ``` { return rp_; } ``` a65c8e8b ``` const range_t& range_ref() const exprtk_override ``` 4068375e ``` { return rp_; } private: ``` a65c8e8b ``` string_literal_node(const string_literal_node&) exprtk_delete; string_literal_node& operator=(const string_literal_node&) exprtk_delete; ``` 4068375e ``` const std::string value_; range_t rp_; }; #endif template class unary_node : public expression_node { public: typedef expression_node* expression_ptr; typedef std::pair branch_t; ``` a65c8e8b ``` unary_node(const operator_type& opr, expression_ptr branch) ``` 4068375e ``` : operation_(opr) { ``` a65c8e8b ``` construct_branch_pair(branch_,branch); ``` 4068375e ``` } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { ``` a65c8e8b ``` assert(branch_.first); ``` 4068375e ``` const T arg = branch_.first->value(); return numeric::process(operation_,arg); } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_unary; } ``` a65c8e8b ``` inline operator_type operation() ``` 4068375e ``` { return operation_; } ``` a65c8e8b ``` inline expression_node* branch(const std::size_t&) const exprtk_override ``` 4068375e ``` { return branch_.first; } inline void release() { branch_.second = false; } ``` a65c8e8b ``` void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override ``` 4068375e ``` { expression_node::ndb_t::collect(branch_, node_delete_list); } ``` a65c8e8b ``` std::size_t node_depth() const exprtk_override exprtk_final ``` 4068375e ``` { return expression_node::ndb_t::compute_node_depth(branch_); } protected: operator_type operation_; branch_t branch_; }; template class binary_node : public expression_node { public: typedef expression_node* expression_ptr; typedef std::pair branch_t; binary_node(const operator_type& opr, expression_ptr branch0, expression_ptr branch1) : operation_(opr) { init_branches<2>(branch_, branch0, branch1); } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { ``` a65c8e8b ``` assert(branch_[0].first); assert(branch_[1].first); ``` 4068375e ``` const T arg0 = branch_[0].first->value(); const T arg1 = branch_[1].first->value(); return numeric::process(operation_,arg0,arg1); } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_binary; } inline operator_type operation() { return operation_; } ``` a65c8e8b ``` inline expression_node* branch(const std::size_t& index = 0) const exprtk_override ``` 4068375e ``` { if (0 == index) return branch_[0].first; else if (1 == index) return branch_[1].first; else return reinterpret_cast(0); } ``` a65c8e8b ``` void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override ``` 4068375e ``` { expression_node::ndb_t::template collect(branch_, node_delete_list); } ``` a65c8e8b ``` std::size_t node_depth() const exprtk_override exprtk_final ``` 4068375e ``` { return expression_node::ndb_t::template compute_node_depth<2>(branch_); } protected: operator_type operation_; branch_t branch_[2]; }; template ``` a65c8e8b ``` class binary_ext_node exprtk_final : public expression_node ``` 4068375e ``` { 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); } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { ``` a65c8e8b ``` assert(branch_[0].first); assert(branch_[1].first); ``` 4068375e ``` const T arg0 = branch_[0].first->value(); const T arg1 = branch_[1].first->value(); return Operation::process(arg0,arg1); } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_binary_ext; } inline operator_type operation() { return Operation::operation(); } ``` a65c8e8b ``` inline expression_node* branch(const std::size_t& index = 0) const exprtk_override ``` 4068375e ``` { if (0 == index) return branch_[0].first; else if (1 == index) return branch_[1].first; else return reinterpret_cast(0); } ``` a65c8e8b ``` void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override ``` 4068375e ``` { expression_node::ndb_t::template collect(branch_, node_delete_list); } ``` a65c8e8b ``` std::size_t node_depth() const exprtk_override ``` 4068375e ``` { return expression_node::ndb_t::template compute_node_depth<2>(branch_); } protected: branch_t branch_[2]; }; template class trinary_node : public expression_node { public: typedef expression_node* expression_ptr; typedef std::pair branch_t; trinary_node(const operator_type& opr, expression_ptr branch0, expression_ptr branch1, expression_ptr branch2) : operation_(opr) { init_branches<3>(branch_, branch0, branch1, branch2); } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { ``` a65c8e8b ``` assert(branch_[0].first); assert(branch_[1].first); assert(branch_[2].first); ``` 4068375e ``` 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_inrange : return (arg1 < arg0) ? T(0) : ((arg1 > arg2) ? T(0) : T(1)); case e_clamp : return (arg1 < arg0) ? arg0 : (arg1 > arg2 ? arg2 : arg1); case e_iclamp : if ((arg1 <= arg0) || (arg1 >= arg2)) return arg1; else return ((T(2) * arg1 <= (arg2 + arg0)) ? arg0 : arg2); default : exprtk_debug(("trinary_node::value() - Error: Invalid operation\n")); return std::numeric_limits::quiet_NaN(); } } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_trinary; } ``` a65c8e8b ``` void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override ``` 4068375e ``` { expression_node::ndb_t::template collect(branch_, node_delete_list); } ``` a65c8e8b ``` std::size_t node_depth() const exprtk_override exprtk_final ``` 4068375e ``` { return expression_node::ndb_t::template compute_node_depth<3>(branch_); } protected: operator_type operation_; branch_t branch_[3]; }; template class quaternary_node : public expression_node { public: typedef expression_node* expression_ptr; typedef std::pair branch_t; quaternary_node(const operator_type& opr, expression_ptr branch0, expression_ptr branch1, expression_ptr branch2, expression_ptr branch3) : operation_(opr) { init_branches<4>(branch_, branch0, branch1, branch2, branch3); } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { return std::numeric_limits::quiet_NaN(); } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_quaternary; } ``` a65c8e8b ``` void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override ``` 4068375e ``` { expression_node::ndb_t::template collect(branch_, node_delete_list); } ``` a65c8e8b ``` std::size_t node_depth() const exprtk_override exprtk_final ``` 4068375e ``` { return expression_node::ndb_t::template compute_node_depth<4>(branch_); } protected: operator_type operation_; branch_t branch_[4]; }; template ``` a65c8e8b ``` class conditional_node exprtk_final : public expression_node ``` 4068375e ``` { public: typedef expression_node* expression_ptr; typedef std::pair branch_t; ``` a65c8e8b ``` conditional_node(expression_ptr condition, ``` 4068375e ``` expression_ptr consequent, expression_ptr alternative) { ``` a65c8e8b ``` construct_branch_pair(condition_ , condition ); ``` 4068375e ``` construct_branch_pair(consequent_ , consequent ); construct_branch_pair(alternative_, alternative); } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { ``` a65c8e8b ``` assert(condition_ .first); assert(consequent_ .first); assert(alternative_.first); if (is_true(condition_)) ``` 4068375e ``` return consequent_.first->value(); else return alternative_.first->value(); } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_conditional; } ``` a65c8e8b ``` void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override ``` 4068375e ``` { ``` a65c8e8b ``` expression_node::ndb_t::collect(condition_ , node_delete_list); expression_node::ndb_t::collect(consequent_ , node_delete_list); expression_node::ndb_t::collect(alternative_ , node_delete_list); ``` 4068375e ``` } ``` a65c8e8b ``` std::size_t node_depth() const exprtk_override ``` 4068375e ``` { ``` a65c8e8b ``` return expression_node::ndb_t::compute_node_depth (condition_, consequent_, alternative_); ``` 4068375e ``` } private: ``` a65c8e8b ``` branch_t condition_; ``` 4068375e ``` branch_t consequent_; branch_t alternative_; }; template ``` a65c8e8b ``` class cons_conditional_node exprtk_final : public expression_node ``` 4068375e ``` { public: // Consequent only conditional statement node typedef expression_node* expression_ptr; typedef std::pair branch_t; ``` a65c8e8b ``` cons_conditional_node(expression_ptr condition, ``` 4068375e ``` expression_ptr consequent) { ``` a65c8e8b ``` construct_branch_pair(condition_ , condition ); ``` 4068375e ``` construct_branch_pair(consequent_, consequent); } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { ``` a65c8e8b ``` assert(condition_ .first); assert(consequent_.first); if (is_true(condition_)) ``` 4068375e ``` return consequent_.first->value(); else return std::numeric_limits::quiet_NaN(); } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_conditional; } ``` a65c8e8b ``` void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override ``` 4068375e ``` { ``` a65c8e8b ``` expression_node::ndb_t::collect(condition_ , node_delete_list); expression_node::ndb_t::collect(consequent_ , node_delete_list); ``` 4068375e ``` } ``` a65c8e8b ``` std::size_t node_depth() const exprtk_override ``` 4068375e ``` { ``` a65c8e8b ``` return expression_node::ndb_t:: compute_node_depth(condition_, consequent_); ``` 4068375e ``` } private: ``` a65c8e8b ``` branch_t condition_; ``` 4068375e ``` branch_t consequent_; }; #ifndef exprtk_disable_break_continue template class break_exception { public: ``` a65c8e8b ``` explicit break_exception(const T& v) ``` 4068375e ``` : value(v) {} T value; }; ``` a65c8e8b ``` class continue_exception {}; ``` 4068375e ``` template ``` a65c8e8b ``` class break_node exprtk_final : public expression_node ``` 4068375e ``` { public: typedef expression_node* expression_ptr; typedef std::pair branch_t; break_node(expression_ptr ret = expression_ptr(0)) { construct_branch_pair(return_, ret); } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { ``` a65c8e8b ``` const T result = return_.first ? return_.first->value() : std::numeric_limits::quiet_NaN(); throw break_exception(result); ``` 4068375e ``` #ifndef _MSC_VER return std::numeric_limits::quiet_NaN(); #endif } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_break; } ``` a65c8e8b ``` void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override ``` 4068375e ``` { expression_node::ndb_t::collect(return_, node_delete_list); } ``` a65c8e8b ``` std::size_t node_depth() const exprtk_override ``` 4068375e ``` { return expression_node::ndb_t::compute_node_depth(return_); } private: branch_t return_; }; template ``` a65c8e8b ``` class continue_node exprtk_final : public expression_node ``` 4068375e ``` { public: ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { throw continue_exception(); #ifndef _MSC_VER return std::numeric_limits::quiet_NaN(); #endif } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_break; } }; #endif struct loop_runtime_checker { ``` a65c8e8b ``` loop_runtime_checker(loop_runtime_check_ptr loop_runtime_check, ``` 4068375e ``` loop_runtime_check::loop_types lp_typ = loop_runtime_check::e_invalid) ``` a65c8e8b ``` : iteration_count_(0) , loop_runtime_check_(loop_runtime_check) , max_loop_iterations_(loop_runtime_check_->max_loop_iterations) , loop_type_(lp_typ) { assert(loop_runtime_check_); } ``` 4068375e ``` inline void reset(const _uint64_t initial_value = 0) const { iteration_count_ = initial_value; } inline bool check() const { if ( (0 == loop_runtime_check_) || ``` a65c8e8b ``` (++iteration_count_ <= max_loop_iterations_) ``` 4068375e ``` ) { return true; } loop_runtime_check::violation_context ctxt; ``` a65c8e8b ``` ctxt.loop = loop_type_; ``` 4068375e ``` ctxt.violation = loop_runtime_check::e_iteration_count; loop_runtime_check_->handle_runtime_violation(ctxt); return false; } mutable _uint64_t iteration_count_; mutable loop_runtime_check_ptr loop_runtime_check_; ``` a65c8e8b ``` const details::_uint64_t& max_loop_iterations_; loop_runtime_check::loop_types loop_type_; ``` 4068375e ``` }; template ``` a65c8e8b ``` class while_loop_node : public expression_node ``` 4068375e ``` { public: typedef expression_node* expression_ptr; typedef std::pair branch_t; while_loop_node(expression_ptr condition, ``` a65c8e8b ``` expression_ptr loop_body) ``` 4068375e ``` { construct_branch_pair(condition_, condition); construct_branch_pair(loop_body_, loop_body); } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { ``` a65c8e8b ``` assert(condition_.first); assert(loop_body_.first); ``` 4068375e ``` ``` a65c8e8b ``` T result = T(0); ``` 4068375e ``` ``` a65c8e8b ``` while (is_true(condition_)) ``` 4068375e ``` { result = loop_body_.first->value(); } return result; } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_while; } ``` a65c8e8b ``` void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override ``` 4068375e ``` { ``` a65c8e8b ``` expression_node::ndb_t::collect(condition_ , node_delete_list); expression_node::ndb_t::collect(loop_body_ , node_delete_list); ``` 4068375e ``` } ``` a65c8e8b ``` std::size_t node_depth() const exprtk_override ``` 4068375e ``` { return expression_node::ndb_t::compute_node_depth(condition_, loop_body_); } ``` a65c8e8b ``` protected: ``` 4068375e ``` branch_t condition_; branch_t loop_body_; }; template ``` a65c8e8b ``` class while_loop_rtc_node exprtk_final : public while_loop_node , public loop_runtime_checker { public: typedef while_loop_node parent_t; typedef expression_node* expression_ptr; while_loop_rtc_node(expression_ptr condition, expression_ptr loop_body, loop_runtime_check_ptr loop_rt_chk) : parent_t(condition, loop_body) , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_while_loop) {} inline T value() const exprtk_override { assert(parent_t::condition_.first); assert(parent_t::loop_body_.first); T result = T(0); loop_runtime_checker::reset(); while (is_true(parent_t::condition_) && loop_runtime_checker::check()) { result = parent_t::loop_body_.first->value(); } return result; } }; template class repeat_until_loop_node : public expression_node ``` 4068375e ``` { public: typedef expression_node* expression_ptr; typedef std::pair branch_t; repeat_until_loop_node(expression_ptr condition, ``` a65c8e8b ``` expression_ptr loop_body) ``` 4068375e ``` { construct_branch_pair(condition_, condition); construct_branch_pair(loop_body_, loop_body); } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { ``` a65c8e8b ``` assert(condition_.first); assert(loop_body_.first); ``` 4068375e ``` ``` a65c8e8b ``` T result = T(0); ``` 4068375e ``` do { result = loop_body_.first->value(); } ``` a65c8e8b ``` while (is_false(condition_.first)); ``` 4068375e ``` return result; } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_repeat; } ``` a65c8e8b ``` void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override ``` 4068375e ``` { ``` a65c8e8b ``` expression_node::ndb_t::collect(condition_ , node_delete_list); expression_node::ndb_t::collect(loop_body_ , node_delete_list); ``` 4068375e ``` } ``` a65c8e8b ``` std::size_t node_depth() const exprtk_override ``` 4068375e ``` { return expression_node::ndb_t::compute_node_depth(condition_, loop_body_); } ``` a65c8e8b ``` protected: ``` 4068375e ``` branch_t condition_; branch_t loop_body_; }; template ``` a65c8e8b ``` class repeat_until_loop_rtc_node exprtk_final : public repeat_until_loop_node , public loop_runtime_checker { public: typedef repeat_until_loop_node parent_t; typedef expression_node* expression_ptr; repeat_until_loop_rtc_node(expression_ptr condition, expression_ptr loop_body, loop_runtime_check_ptr loop_rt_chk) : parent_t(condition, loop_body) , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_repeat_until_loop) {} inline T value() const exprtk_override { assert(parent_t::condition_.first); assert(parent_t::loop_body_.first); T result = T(0); loop_runtime_checker::reset(1); do { result = parent_t::loop_body_.first->value(); } while (is_false(parent_t::condition_.first) && loop_runtime_checker::check()); return result; } }; template class for_loop_node : public expression_node ``` 4068375e ``` { public: typedef expression_node* expression_ptr; typedef std::pair branch_t; for_loop_node(expression_ptr initialiser, expression_ptr condition, expression_ptr incrementor, ``` a65c8e8b ``` expression_ptr loop_body) ``` 4068375e ``` { construct_branch_pair(initialiser_, initialiser); construct_branch_pair(condition_ , condition ); construct_branch_pair(incrementor_, incrementor); construct_branch_pair(loop_body_ , loop_body ); } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { ``` a65c8e8b ``` assert(condition_.first); assert(loop_body_.first); ``` 4068375e ``` ``` a65c8e8b ``` T result = T(0); ``` 4068375e ``` if (initialiser_.first) initialiser_.first->value(); if (incrementor_.first) { ``` a65c8e8b ``` while (is_true(condition_)) ``` 4068375e ``` { result = loop_body_.first->value(); incrementor_.first->value(); } } else { ``` a65c8e8b ``` while (is_true(condition_)) ``` 4068375e ``` { result = loop_body_.first->value(); } } return result; } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_for; } ``` a65c8e8b ``` void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override ``` 4068375e ``` { ``` a65c8e8b ``` expression_node::ndb_t::collect(initialiser_ , node_delete_list); expression_node::ndb_t::collect(condition_ , node_delete_list); expression_node::ndb_t::collect(incrementor_ , node_delete_list); expression_node::ndb_t::collect(loop_body_ , node_delete_list); ``` 4068375e ``` } ``` a65c8e8b ``` std::size_t node_depth() const exprtk_override ``` 4068375e ``` { return expression_node::ndb_t::compute_node_depth (initialiser_, condition_, incrementor_, loop_body_); } ``` a65c8e8b ``` protected: ``` 4068375e ``` branch_t initialiser_; branch_t condition_ ; branch_t incrementor_; branch_t loop_body_ ; }; template ``` a65c8e8b ``` class for_loop_rtc_node exprtk_final : public for_loop_node , public loop_runtime_checker ``` 4068375e ``` { public: ``` a65c8e8b ``` typedef for_loop_node parent_t; ``` 4068375e ``` typedef expression_node* expression_ptr; ``` a65c8e8b ``` for_loop_rtc_node(expression_ptr initialiser, expression_ptr condition, expression_ptr incrementor, expression_ptr loop_body, loop_runtime_check_ptr loop_rt_chk) : parent_t(initialiser, condition, incrementor, loop_body) , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_for_loop) {} ``` 4068375e ``` ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { ``` a65c8e8b ``` assert(parent_t::condition_.first); assert(parent_t::loop_body_.first); ``` 4068375e ``` T result = T(0); loop_runtime_checker::reset(); ``` a65c8e8b ``` if (parent_t::initialiser_.first) parent_t::initialiser_.first->value(); if (parent_t::incrementor_.first) { while (is_true(parent_t::condition_) && loop_runtime_checker::check()) { result = parent_t::loop_body_.first->value(); parent_t::incrementor_.first->value(); } } else { while (is_true(parent_t::condition_) && loop_runtime_checker::check()) { result = parent_t::loop_body_.first->value(); } } return result; } }; #ifndef exprtk_disable_break_continue template class while_loop_bc_node : public while_loop_node { public: typedef while_loop_node parent_t; typedef expression_node* expression_ptr; while_loop_bc_node(expression_ptr condition, expression_ptr loop_body) : parent_t(condition, loop_body) {} inline T value() const exprtk_override { assert(parent_t::condition_.first); assert(parent_t::loop_body_.first); T result = T(0); while (is_true(parent_t::condition_)) ``` 4068375e ``` { try { ``` a65c8e8b ``` result = parent_t::loop_body_.first->value(); ``` 4068375e ``` } catch(const break_exception& e) { return e.value; } catch(const continue_exception&) {} } return result; } ``` a65c8e8b ``` }; ``` 4068375e ``` ``` a65c8e8b ``` template class while_loop_bc_rtc_node exprtk_final : public while_loop_bc_node , public loop_runtime_checker { public: ``` 4068375e ``` ``` a65c8e8b ``` typedef while_loop_bc_node parent_t; typedef expression_node* expression_ptr; ``` 4068375e ``` ``` a65c8e8b ``` while_loop_bc_rtc_node(expression_ptr condition, expression_ptr loop_body, loop_runtime_check_ptr loop_rt_chk) : parent_t(condition, loop_body) , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_while_loop) {} inline T value() const exprtk_override ``` 4068375e ``` { ``` a65c8e8b ``` assert(parent_t::condition_.first); assert(parent_t::loop_body_.first); ``` 4068375e ``` ``` a65c8e8b ``` T result = T(0); ``` 4068375e ``` ``` a65c8e8b ``` loop_runtime_checker::reset(); while (is_true(parent_t::condition_) && loop_runtime_checker::check()) { try { result = parent_t::loop_body_.first->value(); } catch(const break_exception& e) { return e.value; } catch(const continue_exception&) {} } return result; } ``` 4068375e ``` }; template ``` a65c8e8b ``` class repeat_until_loop_bc_node : public repeat_until_loop_node ``` 4068375e ``` { public: ``` a65c8e8b ``` typedef repeat_until_loop_node parent_t; typedef expression_node* expression_ptr; ``` 4068375e ``` repeat_until_loop_bc_node(expression_ptr condition, ``` a65c8e8b ``` expression_ptr loop_body) : parent_t(condition, loop_body) {} ``` 4068375e ``` ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { ``` a65c8e8b ``` assert(parent_t::condition_.first); assert(parent_t::loop_body_.first); ``` 4068375e ``` ``` a65c8e8b ``` T result = T(0); ``` 4068375e ``` do { try { ``` a65c8e8b ``` result = parent_t::loop_body_.first->value(); ``` 4068375e ``` } catch(const break_exception& e) { return e.value; } catch(const continue_exception&) {} } ``` a65c8e8b ``` while (is_false(parent_t::condition_.first)); ``` 4068375e ``` return result; } ``` a65c8e8b ``` }; ``` 4068375e ``` ``` a65c8e8b ``` template class repeat_until_loop_bc_rtc_node exprtk_final : public repeat_until_loop_bc_node, public loop_runtime_checker { public: ``` 4068375e ``` ``` a65c8e8b ``` typedef repeat_until_loop_bc_node parent_t; typedef expression_node* expression_ptr; ``` 4068375e ``` ``` a65c8e8b ``` repeat_until_loop_bc_rtc_node(expression_ptr condition, expression_ptr loop_body, loop_runtime_check_ptr loop_rt_chk) : parent_t(condition, loop_body) , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_repeat_until_loop) {} inline T value() const exprtk_override ``` 4068375e ``` { ``` a65c8e8b ``` assert(parent_t::condition_.first); assert(parent_t::loop_body_.first); ``` 4068375e ``` ``` a65c8e8b ``` T result = T(0); ``` 4068375e ``` ``` a65c8e8b ``` loop_runtime_checker::reset(); do { try { result = parent_t::loop_body_.first->value(); } catch(const break_exception& e) { return e.value; } catch(const continue_exception&) {} } while (is_false(parent_t::condition_.first) && loop_runtime_checker::check()); return result; } ``` 4068375e ``` }; template ``` a65c8e8b ``` class for_loop_bc_node : public for_loop_node ``` 4068375e ``` { public: ``` a65c8e8b ``` typedef for_loop_node parent_t; ``` 4068375e ``` typedef expression_node* expression_ptr; for_loop_bc_node(expression_ptr initialiser, expression_ptr condition, expression_ptr incrementor, ``` a65c8e8b ``` expression_ptr loop_body) : parent_t(initialiser, condition, incrementor, loop_body) {} ``` 4068375e ``` ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { ``` a65c8e8b ``` assert(parent_t::condition_.first); assert(parent_t::loop_body_.first); ``` 4068375e ``` T result = T(0); ``` a65c8e8b ``` if (parent_t::initialiser_.first) parent_t::initialiser_.first->value(); ``` 4068375e ``` ``` a65c8e8b ``` if (parent_t::incrementor_.first) ``` 4068375e ``` { ``` a65c8e8b ``` while (is_true(parent_t::condition_)) ``` 4068375e ``` { try { ``` a65c8e8b ``` result = parent_t::loop_body_.first->value(); ``` 4068375e ``` } catch(const break_exception& e) { return e.value; } catch(const continue_exception&) {} ``` a65c8e8b ``` parent_t::incrementor_.first->value(); ``` 4068375e ``` } } else { ``` a65c8e8b ``` while (is_true(parent_t::condition_)) ``` 4068375e ``` { try { ``` a65c8e8b ``` result = parent_t::loop_body_.first->value(); ``` 4068375e ``` } catch(const break_exception& e) { return e.value; } catch(const continue_exception&) {} } } return result; } ``` a65c8e8b ``` }; ``` 4068375e ``` ``` a65c8e8b ``` template class for_loop_bc_rtc_node exprtk_final : public for_loop_bc_node , public loop_runtime_checker { public: ``` 4068375e ``` ``` a65c8e8b ``` typedef for_loop_bc_node parent_t; typedef expression_node* expression_ptr; for_loop_bc_rtc_node(expression_ptr initialiser, expression_ptr condition, expression_ptr incrementor, expression_ptr loop_body, loop_runtime_check_ptr loop_rt_chk) : parent_t(initialiser, condition, incrementor, loop_body) , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_for_loop) {} ``` 4068375e ``` ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { ``` a65c8e8b ``` assert(parent_t::condition_.first); assert(parent_t::loop_body_.first); ``` 4068375e ``` ``` a65c8e8b ``` T result = T(0); ``` 4068375e ``` ``` a65c8e8b ``` loop_runtime_checker::reset(); if (parent_t::initialiser_.first) parent_t::initialiser_.first->value(); if (parent_t::incrementor_.first) { while (is_true(parent_t::condition_) && loop_runtime_checker::check()) { try { result = parent_t::loop_body_.first->value(); } catch(const break_exception& e) { return e.value; } catch(const continue_exception&) {} parent_t::incrementor_.first->value(); } } else { while (is_true(parent_t::condition_) && loop_runtime_checker::check()) { try { result = parent_t::loop_body_.first->value(); } catch(const break_exception& e) { return e.value; } catch(const continue_exception&) {} } } return result; } ``` 4068375e ``` }; #endif template class switch_node : public expression_node { public: typedef expression_node* expression_ptr; typedef std::pair branch_t; template class Sequence> explicit switch_node(const Sequence& arg_list) { if (1 != (arg_list.size() & 1)) return; arg_list_.resize(arg_list.size()); for (std::size_t i = 0; i < arg_list.size(); ++i) { if (arg_list[i]) { construct_branch_pair(arg_list_[i], arg_list[i]); } else { arg_list_.clear(); return; } } } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { if (!arg_list_.empty()) { const std::size_t upper_bound = (arg_list_.size() - 1); for (std::size_t i = 0; i < upper_bound; i += 2) { expression_ptr condition = arg_list_[i ].first; expression_ptr consequent = arg_list_[i + 1].first; if (is_true(condition)) { return consequent->value(); } } return arg_list_[upper_bound].first->value(); } else return std::numeric_limits::quiet_NaN(); } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override exprtk_final ``` 4068375e ``` { return expression_node::e_switch; } ``` a65c8e8b ``` void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override ``` 4068375e ``` { expression_node::ndb_t::collect(arg_list_, node_delete_list); } ``` a65c8e8b ``` std::size_t node_depth() const exprtk_override exprtk_final ``` 4068375e ``` { return expression_node::ndb_t::compute_node_depth(arg_list_); } protected: std::vector arg_list_; }; template ``` a65c8e8b ``` class switch_n_node exprtk_final : public switch_node ``` 4068375e ``` { public: typedef expression_node* expression_ptr; template class Sequence> explicit switch_n_node(const Sequence& arg_list) : switch_node(arg_list) {} ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { return Switch_N::process(switch_node::arg_list_); } }; template ``` a65c8e8b ``` class multi_switch_node exprtk_final : public expression_node ``` 4068375e ``` { public: typedef expression_node* expression_ptr; typedef std::pair branch_t; template class Sequence> explicit multi_switch_node(const Sequence& arg_list) { if (0 != (arg_list.size() & 1)) return; arg_list_.resize(arg_list.size()); for (std::size_t i = 0; i < arg_list.size(); ++i) { if (arg_list[i]) { construct_branch_pair(arg_list_[i], arg_list[i]); } else { arg_list_.clear(); return; } } } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { T result = T(0); if (arg_list_.empty()) { return std::numeric_limits::quiet_NaN(); } const std::size_t upper_bound = (arg_list_.size() - 1); for (std::size_t i = 0; i < upper_bound; i += 2) { expression_ptr condition = arg_list_[i ].first; expression_ptr consequent = arg_list_[i + 1].first; if (is_true(condition)) { result = consequent->value(); } } return result; } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_mswitch; } ``` a65c8e8b ``` void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override ``` 4068375e ``` { expression_node::ndb_t::collect(arg_list_, node_delete_list); } ``` a65c8e8b ``` std::size_t node_depth() const exprtk_override exprtk_final ``` 4068375e ``` { return expression_node::ndb_t::compute_node_depth(arg_list_); } private: std::vector arg_list_; }; template class ivariable { public: ``` a65c8e8b ``` virtual ~ivariable() {} ``` 4068375e ``` virtual T& ref() = 0; virtual const T& ref() const = 0; }; template ``` a65c8e8b ``` class variable_node exprtk_final : public expression_node, ``` 4068375e ``` public ivariable { public: static T null_value; explicit variable_node() : value_(&null_value) {} explicit variable_node(T& v) : value_(&v) {} inline bool operator <(const variable_node& v) const { return this < (&v); } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { return (*value_); } ``` a65c8e8b ``` inline T& ref() exprtk_override ``` 4068375e ``` { return (*value_); } ``` a65c8e8b ``` inline const T& ref() const exprtk_override ``` 4068375e ``` { return (*value_); } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_variable; } private: T* value_; }; template T variable_node::null_value = T(std::numeric_limits::quiet_NaN()); template struct range_pack { typedef expression_node* expression_node_ptr; typedef std::pair cached_range_t; range_pack() ``` a65c8e8b ``` : n0_e (std::make_pair(false,expression_node_ptr(0))) , n1_e (std::make_pair(false,expression_node_ptr(0))) , n0_c (std::make_pair(false,0)) , n1_c (std::make_pair(false,0)) , cache(std::make_pair(0,0)) ``` 4068375e ``` {} void clear() { n0_e = std::make_pair(false,expression_node_ptr(0)); n1_e = std::make_pair(false,expression_node_ptr(0)); n0_c = std::make_pair(false,0); n1_c = std::make_pair(false,0); cache = std::make_pair(0,0); } void free() { if (n0_e.first && n0_e.second) { n0_e.first = false; if ( !is_variable_node(n0_e.second) && !is_string_node (n0_e.second) ) { destroy_node(n0_e.second); } } if (n1_e.first && n1_e.second) { n1_e.first = false; if ( !is_variable_node(n1_e.second) && !is_string_node (n1_e.second) ) { destroy_node(n1_e.second); } } } ``` a65c8e8b ``` bool const_range() const ``` 4068375e ``` { return ( n0_c.first && n1_c.first) && (!n0_e.first && !n1_e.first); } ``` a65c8e8b ``` bool var_range() const ``` 4068375e ``` { return ( n0_e.first && n1_e.first) && (!n0_c.first && !n1_c.first); } bool operator() (std::size_t& r0, std::size_t& r1, const std::size_t& size = std::numeric_limits::max()) const { if (n0_c.first) r0 = n0_c.second; else if (n0_e.first) { ``` a65c8e8b ``` r0 = static_cast(details::numeric::to_int64(n0_e.second->value())); ``` 4068375e ``` } else return false; if (n1_c.first) r1 = n1_c.second; else if (n1_e.first) { ``` a65c8e8b ``` r1 = static_cast(details::numeric::to_int64(n1_e.second->value())); ``` 4068375e ``` } else return false; if ( (std::numeric_limits::max() != size) && (std::numeric_limits::max() == r1 ) ) { r1 = size - 1; } cache.first = r0; cache.second = r1; ``` a65c8e8b ``` #ifndef exprtk_enable_range_runtime_checks ``` 4068375e ``` return (r0 <= r1); ``` a65c8e8b ``` #else return range_runtime_check(r0, r1, size); #endif ``` 4068375e ``` } inline std::size_t const_size() const { return (n1_c.second - n0_c.second + 1); } inline std::size_t cache_size() const { return (cache.second - cache.first + 1); } std::pair n0_e; std::pair n1_e; std::pair n0_c; std::pair n1_c; mutable cached_range_t cache; ``` a65c8e8b ``` #ifdef exprtk_enable_range_runtime_checks bool range_runtime_check(const std::size_t r0, const std::size_t r1, const std::size_t size) const { if (r0 >= size) { throw std::runtime_error("range error: (r0 < 0) || (r0 >= size)"); return false; } if (r1 >= size) { throw std::runtime_error("range error: (r1 < 0) || (r1 >= size)"); return false; } return (r0 <= r1); } #endif ``` 4068375e ``` }; template class string_base_node; template struct range_data_type { typedef range_pack range_t; typedef string_base_node* strbase_ptr_t; range_data_type() ``` a65c8e8b ``` : range(0) , data (0) , size (0) , type_size(0) , str_node (0) ``` 4068375e ``` {} range_t* range; void* data; std::size_t size; std::size_t type_size; strbase_ptr_t str_node; }; template class vector_node; template class vector_interface { public: typedef vector_node* vector_node_ptr; ``` a65c8e8b ``` typedef vec_data_store vds_t; ``` 4068375e ``` ``` a65c8e8b ``` virtual ~vector_interface() {} ``` 4068375e ``` virtual std::size_t size () const = 0; virtual vector_node_ptr vec() const = 0; virtual vector_node_ptr vec() = 0; virtual vds_t& vds () = 0; virtual const vds_t& vds () const = 0; virtual bool side_effect () const { return false; } }; template ``` a65c8e8b ``` class vector_node exprtk_final : public expression_node , public vector_interface ``` 4068375e ``` { public: ``` a65c8e8b ``` typedef expression_node* expression_ptr; ``` 4068375e ``` typedef vector_holder vector_holder_t; typedef vector_node* vector_node_ptr; ``` a65c8e8b ``` typedef vec_data_store vds_t; ``` 4068375e ``` explicit vector_node(vector_holder_t* vh) ``` a65c8e8b ``` : vector_holder_(vh) , vds_((*vector_holder_).size(),(*vector_holder_)[0]) ``` 4068375e ``` { vector_holder_->set_ref(&vds_.ref()); } vector_node(const vds_t& vds, vector_holder_t* vh) ``` a65c8e8b ``` : vector_holder_(vh) , vds_(vds) ``` 4068375e ``` {} ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { return vds().data()[0]; } ``` a65c8e8b ``` vector_node_ptr vec() const exprtk_override ``` 4068375e ``` { return const_cast(this); } ``` a65c8e8b ``` vector_node_ptr vec() exprtk_override ``` 4068375e ``` { return this; } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_vector; } ``` a65c8e8b ``` std::size_t size() const exprtk_override ``` 4068375e ``` { return vds().size(); } ``` a65c8e8b ``` vds_t& vds() exprtk_override ``` 4068375e ``` { return vds_; } ``` a65c8e8b ``` const vds_t& vds() const exprtk_override ``` 4068375e ``` { return vds_; } inline vector_holder_t& vec_holder() { return (*vector_holder_); } private: vector_holder_t* vector_holder_; vds_t vds_; }; template ``` a65c8e8b ``` class vector_elem_node exprtk_final : public expression_node, ``` 4068375e ``` public ivariable { public: typedef expression_node* expression_ptr; typedef vector_holder vector_holder_t; typedef vector_holder_t* vector_holder_ptr; typedef std::pair branch_t; vector_elem_node(expression_ptr index, vector_holder_ptr vec_holder) ``` a65c8e8b ``` : vec_holder_(vec_holder) , vector_base_((*vec_holder)[0]) ``` 4068375e ``` { construct_branch_pair(index_, index); } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { return *(vector_base_ + static_cast(details::numeric::to_int64(index_.first->value()))); } ``` a65c8e8b ``` inline T& ref() exprtk_override ``` 4068375e ``` { return *(vector_base_ + static_cast(details::numeric::to_int64(index_.first->value()))); } ``` a65c8e8b ``` inline const T& ref() const exprtk_override ``` 4068375e ``` { return *(vector_base_ + static_cast(details::numeric::to_int64(index_.first->value()))); } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_vecelem; } inline vector_holder_t& vec_holder() { return (*vec_holder_); } ``` a65c8e8b ``` void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override ``` 4068375e ``` { expression_node::ndb_t::collect(index_, node_delete_list); } ``` a65c8e8b ``` std::size_t node_depth() const exprtk_override ``` 4068375e ``` { return expression_node::ndb_t::compute_node_depth(index_); } private: vector_holder_ptr vec_holder_; T* vector_base_; branch_t index_; }; template ``` a65c8e8b ``` class rebasevector_elem_node exprtk_final : public expression_node, ``` 4068375e ``` public ivariable { public: typedef expression_node* expression_ptr; typedef vector_holder vector_holder_t; typedef vector_holder_t* vector_holder_ptr; typedef vec_data_store vds_t; typedef std::pair branch_t; rebasevector_elem_node(expression_ptr index, vector_holder_ptr vec_holder) ``` a65c8e8b ``` : vector_holder_(vec_holder) , vds_((*vector_holder_).size(),(*vector_holder_)[0]) ``` 4068375e ``` { vector_holder_->set_ref(&vds_.ref()); construct_branch_pair(index_, index); } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { return *(vds_.data() + static_cast(details::numeric::to_int64(index_.first->value()))); } ``` a65c8e8b ``` inline T& ref() exprtk_override ``` 4068375e ``` { return *(vds_.data() + static_cast(details::numeric::to_int64(index_.first->value()))); } ``` a65c8e8b ``` inline const T& ref() const exprtk_override ``` 4068375e ``` { return *(vds_.data() + static_cast(details::numeric::to_int64(index_.first->value()))); } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_rbvecelem; } inline vector_holder_t& vec_holder() { return (*vector_holder_); } ``` a65c8e8b ``` void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override ``` 4068375e ``` { expression_node::ndb_t::template collect(index_, node_delete_list); } ``` a65c8e8b ``` std::size_t node_depth() const exprtk_override ``` 4068375e ``` { return expression_node::ndb_t::compute_node_depth(index_); } private: vector_holder_ptr vector_holder_; vds_t vds_; branch_t index_; }; template ``` a65c8e8b ``` class rebasevector_celem_node exprtk_final : public expression_node, ``` 4068375e ``` public ivariable { public: typedef expression_node* expression_ptr; typedef vector_holder vector_holder_t; typedef vector_holder_t* vector_holder_ptr; typedef vec_data_store vds_t; rebasevector_celem_node(const std::size_t index, vector_holder_ptr vec_holder) ``` a65c8e8b ``` : index_(index) , vector_holder_(vec_holder) , vds_((*vector_holder_).size(),(*vector_holder_)[0]) ``` 4068375e ``` { vector_holder_->set_ref(&vds_.ref()); } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { return *(vds_.data() + index_); } ``` a65c8e8b ``` inline T& ref() exprtk_override ``` 4068375e ``` { return *(vds_.data() + index_); } ``` a65c8e8b ``` inline const T& ref() const exprtk_override ``` 4068375e ``` { return *(vds_.data() + index_); } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_rbveccelem; } inline vector_holder_t& vec_holder() { return (*vector_holder_); } private: const std::size_t index_; vector_holder_ptr vector_holder_; vds_t vds_; }; template ``` a65c8e8b ``` class vector_assignment_node exprtk_final : public expression_node ``` 4068375e ``` { public: typedef expression_node* expression_ptr; vector_assignment_node(T* vector_base, const std::size_t& size, const std::vector& initialiser_list, const bool single_value_initialse) ``` a65c8e8b ``` : vector_base_(vector_base) , initialiser_list_(initialiser_list) , size_(size) , single_value_initialse_(single_value_initialse) ``` 4068375e ``` {} ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { if (single_value_initialse_) { for (std::size_t i = 0; i < size_; ++i) { *(vector_base_ + i) = initialiser_list_[0]->value(); } } else { ``` a65c8e8b ``` const std::size_t initialiser_list_size = initialiser_list_.size(); ``` 4068375e ``` ``` a65c8e8b ``` for (std::size_t i = 0; i < initialiser_list_size; ++i) ``` 4068375e ``` { *(vector_base_ + i) = initialiser_list_[i]->value(); } ``` a65c8e8b ``` if (initialiser_list_size < size_) ``` 4068375e ``` { ``` a65c8e8b ``` for (std::size_t i = initialiser_list_size; i < size_; ++i) ``` 4068375e ``` { *(vector_base_ + i) = T(0); } } } return *(vector_base_); } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_vecdefass; } ``` a65c8e8b ``` void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override ``` 4068375e ``` { expression_node::ndb_t::collect(initialiser_list_, node_delete_list); } ``` a65c8e8b ``` std::size_t node_depth() const exprtk_override ``` 4068375e ``` { return expression_node::ndb_t::compute_node_depth(initialiser_list_); } private: ``` a65c8e8b ``` vector_assignment_node(const vector_assignment_node&) exprtk_delete; vector_assignment_node& operator=(const vector_assignment_node&) exprtk_delete; ``` 4068375e ``` mutable T* vector_base_; std::vector initialiser_list_; const std::size_t size_; const bool single_value_initialse_; }; template ``` a65c8e8b ``` class swap_node exprtk_final : public expression_node ``` 4068375e ``` { public: typedef expression_node* expression_ptr; typedef variable_node* variable_node_ptr; swap_node(variable_node_ptr var0, variable_node_ptr var1) ``` a65c8e8b ``` : var0_(var0) , var1_(var1) ``` 4068375e ``` {} ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { std::swap(var0_->ref(),var1_->ref()); return var1_->ref(); } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_swap; } private: variable_node_ptr var0_; variable_node_ptr var1_; }; template ``` a65c8e8b ``` class swap_generic_node exprtk_final : public binary_node ``` 4068375e ``` { public: typedef expression_node* expression_ptr; ``` a65c8e8b ``` typedef ivariable* ivariable_ptr; ``` 4068375e ``` swap_generic_node(expression_ptr var0, expression_ptr var1) ``` a65c8e8b ``` : binary_node(details::e_swap, var0, var1) , var0_(dynamic_cast(var0)) , var1_(dynamic_cast(var1)) ``` 4068375e ``` {} ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { std::swap(var0_->ref(),var1_->ref()); return var1_->ref(); } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_swap; } private: ivariable_ptr var0_; ivariable_ptr var1_; }; template ``` a65c8e8b ``` class swap_vecvec_node exprtk_final : public binary_node , public vector_interface ``` 4068375e ``` { public: ``` a65c8e8b ``` typedef expression_node* expression_ptr; typedef vector_node * vector_node_ptr; typedef vec_data_store vds_t; ``` 4068375e ``` swap_vecvec_node(expression_ptr branch0, expression_ptr branch1) ``` a65c8e8b ``` : binary_node(details::e_swap, branch0, branch1) , vec0_node_ptr_(0) , vec1_node_ptr_(0) , vec_size_ (0) , initialised_ (false) ``` 4068375e ``` { if (is_ivector_node(binary_node::branch_[0].first)) { vector_interface* vi = reinterpret_cast*>(0); if (0 != (vi = dynamic_cast*>(binary_node::branch_[0].first))) { vec0_node_ptr_ = vi->vec(); vds() = vi->vds(); } } if (is_ivector_node(binary_node::branch_[1].first)) { vector_interface* vi = reinterpret_cast*>(0); if (0 != (vi = dynamic_cast*>(binary_node::branch_[1].first))) { vec1_node_ptr_ = vi->vec(); } } if (vec0_node_ptr_ && vec1_node_ptr_) { vec_size_ = std::min(vec0_node_ptr_->vds().size(), vec1_node_ptr_->vds().size()); initialised_ = true; } ``` a65c8e8b ``` assert(initialised_); ``` 4068375e ``` } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { if (initialised_) { ``` a65c8e8b ``` assert(binary_node::branch_[0].first); assert(binary_node::branch_[1].first); ``` 4068375e ``` binary_node::branch_[0].first->value(); binary_node::branch_[1].first->value(); T* vec0 = vec0_node_ptr_->vds().data(); T* vec1 = vec1_node_ptr_->vds().data(); for (std::size_t i = 0; i < vec_size_; ++i) { std::swap(vec0[i],vec1[i]); } return vec1_node_ptr_->value(); } else return std::numeric_limits::quiet_NaN(); } ``` a65c8e8b ``` vector_node_ptr vec() const exprtk_override ``` 4068375e ``` { return vec0_node_ptr_; } ``` a65c8e8b ``` vector_node_ptr vec() exprtk_override ``` 4068375e ``` { return vec0_node_ptr_; } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_vecvecswap; } ``` a65c8e8b ``` std::size_t size() const exprtk_override ``` 4068375e ``` { return vec_size_; } ``` a65c8e8b ``` vds_t& vds() exprtk_override ``` 4068375e ``` { return vds_; } ``` a65c8e8b ``` const vds_t& vds() const exprtk_override ``` 4068375e ``` { return vds_; } private: vector_node* vec0_node_ptr_; vector_node* vec1_node_ptr_; std::size_t vec_size_; bool initialised_; vds_t vds_; }; #ifndef exprtk_disable_string_capabilities template ``` a65c8e8b ``` class stringvar_node exprtk_final : public expression_node , ``` 4068375e ``` public string_base_node, public range_interface { public: ``` a65c8e8b ``` typedef typename range_interface::range_t range_t; ``` 4068375e ``` static std::string null_value; explicit stringvar_node() : value_(&null_value) {} explicit stringvar_node(std::string& v) : value_(&v) { rp_.n0_c = std::make_pair(true,0); rp_.n1_c = std::make_pair(true,v.size() - 1); rp_.cache.first = rp_.n0_c.second; rp_.cache.second = rp_.n1_c.second; } inline bool operator <(const stringvar_node& v) const { return this < (&v); } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { rp_.n1_c.second = (*value_).size() - 1; rp_.cache.second = rp_.n1_c.second; return std::numeric_limits::quiet_NaN(); } ``` a65c8e8b ``` std::string str() const exprtk_override ``` 4068375e ``` { return ref(); } ``` a65c8e8b ``` char_cptr base() const exprtk_override ``` 4068375e ``` { return &(*value_)[0]; } ``` a65c8e8b ``` std::size_t size() const exprtk_override ``` 4068375e ``` { return ref().size(); } std::string& ref() { return (*value_); } const std::string& ref() const { return (*value_); } ``` a65c8e8b ``` range_t& range_ref() exprtk_override ``` 4068375e ``` { return rp_; } ``` a65c8e8b ``` const range_t& range_ref() const exprtk_override ``` 4068375e ``` { return rp_; } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_stringvar; } ``` a65c8e8b ``` void rebase(std::string& s) { value_ = &s; rp_.n0_c = std::make_pair(true,0); rp_.n1_c = std::make_pair(true,value_->size() - 1); rp_.cache.first = rp_.n0_c.second; rp_.cache.second = rp_.n1_c.second; } ``` 4068375e ``` private: std::string* value_; mutable range_t rp_; }; template std::string stringvar_node::null_value = std::string(""); template ``` a65c8e8b ``` class string_range_node exprtk_final : public expression_node , ``` 4068375e ``` public string_base_node, public range_interface { public: ``` a65c8e8b ``` typedef typename range_interface::range_t range_t; ``` 4068375e ``` static std::string null_value; explicit string_range_node(std::string& v, const range_t& rp) ``` a65c8e8b ``` : value_(&v) , rp_(rp) ``` 4068375e ``` {} virtual ~string_range_node() { rp_.free(); } inline bool operator <(const string_range_node& v) const { return this < (&v); } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { return std::numeric_limits::quiet_NaN(); } ``` a65c8e8b ``` inline std::string str() const exprtk_override ``` 4068375e ``` { return (*value_); } ``` a65c8e8b ``` char_cptr base() const exprtk_override ``` 4068375e ``` { return &(*value_)[0]; } ``` a65c8e8b ``` std::size_t size() const exprtk_override ``` 4068375e ``` { return ref().size(); } inline range_t range() const { return rp_; } inline virtual std::string& ref() { return (*value_); } inline virtual const std::string& ref() const { return (*value_); } ``` a65c8e8b ``` inline range_t& range_ref() exprtk_override ``` 4068375e ``` { return rp_; } ``` a65c8e8b ``` inline const range_t& range_ref() const exprtk_override ``` 4068375e ``` { return rp_; } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_stringvarrng; } private: std::string* value_; range_t rp_; }; template std::string string_range_node::null_value = std::string(""); template ``` a65c8e8b ``` class const_string_range_node exprtk_final : public expression_node , ``` 4068375e ``` public string_base_node, public range_interface { public: ``` a65c8e8b ``` typedef typename range_interface::range_t range_t; ``` 4068375e ``` explicit const_string_range_node(const std::string& v, const range_t& rp) ``` a65c8e8b ``` : value_(v) , rp_(rp) ``` 4068375e ``` {} ~const_string_range_node() { rp_.free(); } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { return std::numeric_limits::quiet_NaN(); } ``` a65c8e8b ``` std::string str() const exprtk_override ``` 4068375e ``` { return value_; } ``` a65c8e8b ``` char_cptr base() const exprtk_override ``` 4068375e ``` { return value_.data(); } ``` a65c8e8b ``` std::size_t size() const exprtk_override ``` 4068375e ``` { return value_.size(); } range_t range() const { return rp_; } ``` a65c8e8b ``` range_t& range_ref() exprtk_override ``` 4068375e ``` { return rp_; } ``` a65c8e8b ``` const range_t& range_ref() const exprtk_override ``` 4068375e ``` { return rp_; } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_cstringvarrng; } private: ``` a65c8e8b ``` const_string_range_node(const const_string_range_node&) exprtk_delete; const_string_range_node& operator=(const const_string_range_node&) exprtk_delete; ``` 4068375e ``` const std::string value_; range_t rp_; }; template ``` a65c8e8b ``` class generic_string_range_node exprtk_final : public expression_node , ``` 4068375e ``` public string_base_node, public range_interface { public: ``` a65c8e8b ``` typedef expression_node * expression_ptr; typedef stringvar_node * strvar_node_ptr; typedef string_base_node* str_base_ptr; typedef typename range_interface::range_t range_t; typedef range_t* range_ptr; typedef range_interface irange_t; typedef irange_t* irange_ptr; ``` 4068375e ``` typedef std::pair branch_t; generic_string_range_node(expression_ptr str_branch, const range_t& brange) ``` a65c8e8b ``` : initialised_(false) , str_base_ptr_ (0) , str_range_ptr_(0) , base_range_(brange) ``` 4068375e ``` { range_.n0_c = std::make_pair(true,0); range_.n1_c = std::make_pair(true,0); range_.cache.first = range_.n0_c.second; range_.cache.second = range_.n1_c.second; construct_branch_pair(branch_, str_branch); if (is_generally_string_node(branch_.first)) { str_base_ptr_ = dynamic_cast(branch_.first); if (0 == str_base_ptr_) return; str_range_ptr_ = dynamic_cast(branch_.first); if (0 == str_range_ptr_) return; } initialised_ = (str_base_ptr_ && str_range_ptr_); ``` a65c8e8b ``` assert(initialised_); ``` 4068375e ``` } ~generic_string_range_node() { base_range_.free(); } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { if (initialised_) { ``` a65c8e8b ``` assert(branch_.first); ``` 4068375e ``` branch_.first->value(); std::size_t str_r0 = 0; std::size_t str_r1 = 0; std::size_t r0 = 0; std::size_t r1 = 0; ``` a65c8e8b ``` const range_t& range = str_range_ptr_->range_ref(); ``` 4068375e ``` const std::size_t base_str_size = str_base_ptr_->size(); if ( range (str_r0, str_r1, base_str_size) && ``` a65c8e8b ``` base_range_( r0, r1, base_str_size - str_r0) ``` 4068375e ``` ) { const std::size_t size = (r1 - r0) + 1; range_.n1_c.second = size - 1; range_.cache.second = range_.n1_c.second; value_.assign(str_base_ptr_->base() + str_r0 + r0, size); } } return std::numeric_limits::quiet_NaN(); } ``` a65c8e8b ``` std::string str() const exprtk_override ``` 4068375e ``` { return value_; } ``` a65c8e8b ``` char_cptr base() const exprtk_override ``` 4068375e ``` { return &value_[0]; } ``` a65c8e8b ``` std::size_t size() const exprtk_override ``` 4068375e ``` { return value_.size(); } ``` a65c8e8b ``` range_t& range_ref() exprtk_override ``` 4068375e ``` { return range_; } ``` a65c8e8b ``` const range_t& range_ref() const exprtk_override ``` 4068375e ``` { return range_; } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_strgenrange; } ``` a65c8e8b ``` void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override ``` 4068375e ``` { expression_node::ndb_t::collect(branch_, node_delete_list); } ``` a65c8e8b ``` std::size_t node_depth() const exprtk_override ``` 4068375e ``` { return expression_node::ndb_t::compute_node_depth(branch_); } private: bool initialised_; ``` a65c8e8b ``` branch_t branch_; str_base_ptr str_base_ptr_; irange_ptr str_range_ptr_; mutable range_t base_range_; mutable range_t range_; mutable std::string value_; ``` 4068375e ``` }; template ``` a65c8e8b ``` class string_concat_node exprtk_final : public binary_node , ``` 4068375e ``` public string_base_node, public range_interface { public: ``` a65c8e8b ``` typedef typename range_interface::range_t range_t; typedef range_interface irange_t; typedef irange_t* irange_ptr; typedef range_t* range_ptr; typedef expression_node * expression_ptr; typedef string_base_node* str_base_ptr; ``` 4068375e ``` string_concat_node(const operator_type& opr, expression_ptr branch0, expression_ptr branch1) ``` a65c8e8b ``` : binary_node(opr, branch0, branch1) , initialised_(false) , str0_base_ptr_ (0) , str1_base_ptr_ (0) , str0_range_ptr_(0) , str1_range_ptr_(0) ``` 4068375e ``` { range_.n0_c = std::make_pair(true,0); range_.n1_c = std::make_pair(true,0); range_.cache.first = range_.n0_c.second; range_.cache.second = range_.n1_c.second; if (is_generally_string_node(binary_node::branch_[0].first)) { str0_base_ptr_ = dynamic_cast(binary_node::branch_[0].first); if (0 == str0_base_ptr_) return; str0_range_ptr_ = dynamic_cast(binary_node::branch_[0].first); if (0 == str0_range_ptr_) return; } if (is_generally_string_node(binary_node::branch_[1].first)) { str1_base_ptr_ = dynamic_cast(binary_node::branch_[1].first); if (0 == str1_base_ptr_) return; str1_range_ptr_ = dynamic_cast(binary_node::branch_[1].first); if (0 == str1_range_ptr_) return; } initialised_ = str0_base_ptr_ && str1_base_ptr_ && str0_range_ptr_ && str1_range_ptr_ ; ``` a65c8e8b ``` assert(initialised_); ``` 4068375e ``` } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { if (initialised_) { ``` a65c8e8b ``` assert(binary_node::branch_[0].first); assert(binary_node::branch_[1].first); ``` 4068375e ``` binary_node::branch_[0].first->value(); binary_node::branch_[1].first->value(); std::size_t str0_r0 = 0; std::size_t str0_r1 = 0; std::size_t str1_r0 = 0; std::size_t str1_r1 = 0; ``` a65c8e8b ``` const range_t& range0 = str0_range_ptr_->range_ref(); const range_t& range1 = str1_range_ptr_->range_ref(); ``` 4068375e ``` if ( range0(str0_r0, str0_r1, str0_base_ptr_->size()) && range1(str1_r0, str1_r1, str1_base_ptr_->size()) ) { const std::size_t size0 = (str0_r1 - str0_r0) + 1; const std::size_t size1 = (str1_r1 - str1_r0) + 1; value_.assign(str0_base_ptr_->base() + str0_r0, size0); value_.append(str1_base_ptr_->base() + str1_r0, size1); range_.n1_c.second = value_.size() - 1; range_.cache.second = range_.n1_c.second; } } return std::numeric_limits::quiet_NaN(); } ``` a65c8e8b ``` std::string str() const exprtk_override ``` 4068375e ``` { return value_; } ``` a65c8e8b ``` char_cptr base() const exprtk_override ``` 4068375e ``` { return &value_[0]; } ``` a65c8e8b ``` std::size_t size() const exprtk_override ``` 4068375e ``` { return value_.size(); } ``` a65c8e8b ``` range_t& range_ref() exprtk_override ``` 4068375e ``` { return range_; } ``` a65c8e8b ``` const range_t& range_ref() const exprtk_override ``` 4068375e ``` { return range_; } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_strconcat; } private: ``` a65c8e8b ``` bool initialised_; str_base_ptr str0_base_ptr_; str_base_ptr str1_base_ptr_; irange_ptr str0_range_ptr_; irange_ptr str1_range_ptr_; ``` 4068375e ``` mutable range_t range_; mutable std::string value_; }; template ``` a65c8e8b ``` class swap_string_node exprtk_final : public binary_node , ``` 4068375e ``` public string_base_node, public range_interface { public: ``` a65c8e8b ``` typedef typename range_interface::range_t range_t; typedef range_t* range_ptr; typedef range_interface irange_t; typedef irange_t* irange_ptr; typedef expression_node * expression_ptr; ``` 4068375e ``` typedef stringvar_node * strvar_node_ptr; ``` a65c8e8b ``` typedef string_base_node* str_base_ptr; ``` 4068375e ``` swap_string_node(expression_ptr branch0, expression_ptr branch1) : binary_node(details::e_swap, branch0, branch1), initialised_(false), str0_node_ptr_(0), str1_node_ptr_(0) { if (is_string_node(binary_node::branch_[0].first)) { str0_node_ptr_ = static_cast(binary_node::branch_[0].first); } if (is_string_node(binary_node::branch_[1].first)) { str1_node_ptr_ = static_cast(binary_node::branch_[1].first); } initialised_ = (str0_node_ptr_ && str1_node_ptr_); ``` a65c8e8b ``` assert(initialised_); ``` 4068375e ``` } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { if (initialised_) { ``` a65c8e8b ``` assert(binary_node::branch_[0].first); assert(binary_node::branch_[1].first); ``` 4068375e ``` binary_node::branch_[0].first->value(); binary_node::branch_[1].first->value(); std::swap(str0_node_ptr_->ref(), str1_node_ptr_->ref()); } return std::numeric_limits::quiet_NaN(); } ``` a65c8e8b ``` std::string str() const exprtk_override ``` 4068375e ``` { return str0_node_ptr_->str(); } ``` a65c8e8b ``` char_cptr base() const exprtk_override ``` 4068375e ``` { return str0_node_ptr_->base(); } ``` a65c8e8b ``` std::size_t size() const exprtk_override ``` 4068375e ``` { return str0_node_ptr_->size(); } ``` a65c8e8b ``` range_t& range_ref() exprtk_override ``` 4068375e ``` { return str0_node_ptr_->range_ref(); } ``` a65c8e8b ``` const range_t& range_ref() const exprtk_override ``` 4068375e ``` { return str0_node_ptr_->range_ref(); } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_strswap; } private: bool initialised_; strvar_node_ptr str0_node_ptr_; strvar_node_ptr str1_node_ptr_; }; template ``` a65c8e8b ``` class swap_genstrings_node exprtk_final : public binary_node ``` 4068375e ``` { public: ``` a65c8e8b ``` typedef typename range_interface::range_t range_t; typedef range_t* range_ptr; typedef range_interface irange_t; typedef irange_t* irange_ptr; ``` 4068375e ``` typedef expression_node * expression_ptr; ``` a65c8e8b ``` typedef string_base_node* str_base_ptr; ``` 4068375e ``` swap_genstrings_node(expression_ptr branch0, expression_ptr branch1) ``` a65c8e8b ``` : binary_node(details::e_default, branch0, branch1) , str0_base_ptr_ (0) , str1_base_ptr_ (0) , str0_range_ptr_(0) , str1_range_ptr_(0) , initialised_(false) ``` 4068375e ``` { if (is_generally_string_node(binary_node::branch_[0].first)) { str0_base_ptr_ = dynamic_cast(binary_node::branch_[0].first); if (0 == str0_base_ptr_) return; irange_ptr range = dynamic_cast(binary_node::branch_[0].first); if (0 == range) return; str0_range_ptr_ = &(range->range_ref()); } if (is_generally_string_node(binary_node::branch_[1].first)) { str1_base_ptr_ = dynamic_cast(binary_node::branch_[1].first); if (0 == str1_base_ptr_) return; irange_ptr range = dynamic_cast(binary_node::branch_[1].first); if (0 == range) return; str1_range_ptr_ = &(range->range_ref()); } initialised_ = str0_base_ptr_ && str1_base_ptr_ && str0_range_ptr_ && str1_range_ptr_ ; ``` a65c8e8b ``` assert(initialised_); ``` 4068375e ``` } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { if (initialised_) { ``` a65c8e8b ``` assert(binary_node::branch_[0].first); assert(binary_node::branch_[1].first); ``` 4068375e ``` binary_node::branch_[0].first->value(); binary_node::branch_[1].first->value(); std::size_t str0_r0 = 0; std::size_t str0_r1 = 0; std::size_t str1_r0 = 0; std::size_t str1_r1 = 0; ``` a65c8e8b ``` const range_t& range0 = (*str0_range_ptr_); const range_t& range1 = (*str1_range_ptr_); ``` 4068375e ``` if ( range0(str0_r0, str0_r1, str0_base_ptr_->size()) && range1(str1_r0, str1_r1, str1_base_ptr_->size()) ) { const std::size_t size0 = range0.cache_size(); const std::size_t size1 = range1.cache_size(); const std::size_t max_size = std::min(size0,size1); char_ptr s0 = const_cast(str0_base_ptr_->base() + str0_r0); char_ptr s1 = const_cast(str1_base_ptr_->base() + str1_r0); loop_unroll::details lud(max_size); char_cptr upper_bound = s0 + lud.upper_bound; while (s0 < upper_bound) { #define exprtk_loop(N) \ std::swap(s0[N], s1[N]); \ exprtk_loop( 0) exprtk_loop( 1) exprtk_loop( 2) exprtk_loop( 3) #ifndef exprtk_disable_superscalar_unroll exprtk_loop( 4) exprtk_loop( 5) exprtk_loop( 6) exprtk_loop( 7) exprtk_loop( 8) exprtk_loop( 9) exprtk_loop(10) exprtk_loop(11) exprtk_loop(12) exprtk_loop(13) exprtk_loop(14) exprtk_loop(15) #endif s0 += lud.batch_size; s1 += lud.batch_size; } int i = 0; exprtk_disable_fallthrough_begin switch (lud.remainder) { #define case_stmt(N) \ case N : { std::swap(s0[i], s1[i]); ++i; } \ #ifndef exprtk_disable_superscalar_unroll case_stmt(15) case_stmt(14) case_stmt(13) case_stmt(12) case_stmt(11) case_stmt(10) case_stmt( 9) case_stmt( 8) case_stmt( 7) case_stmt( 6) case_stmt( 5) case_stmt( 4) #endif case_stmt( 3) case_stmt( 2) case_stmt( 1) } exprtk_disable_fallthrough_end #undef exprtk_loop #undef case_stmt } } return std::numeric_limits::quiet_NaN(); } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_strswap; } private: ``` a65c8e8b ``` swap_genstrings_node(const swap_genstrings_node&) exprtk_delete; swap_genstrings_node& operator=(const swap_genstrings_node&) exprtk_delete; ``` 4068375e ``` str_base_ptr str0_base_ptr_; str_base_ptr str1_base_ptr_; range_ptr str0_range_ptr_; range_ptr str1_range_ptr_; bool initialised_; }; template ``` a65c8e8b ``` class stringvar_size_node exprtk_final : public expression_node ``` 4068375e ``` { public: static std::string null_value; explicit stringvar_size_node() : value_(&null_value) {} explicit stringvar_size_node(std::string& v) : value_(&v) {} ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { return T((*value_).size()); } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_stringvarsize; } private: std::string* value_; }; template std::string stringvar_size_node::null_value = std::string(""); template ``` a65c8e8b ``` class string_size_node exprtk_final : public expression_node ``` 4068375e ``` { public: ``` a65c8e8b ``` typedef expression_node * expression_ptr; typedef string_base_node* str_base_ptr; ``` 4068375e ``` typedef std::pair branch_t; explicit string_size_node(expression_ptr branch) : str_base_ptr_(0) { construct_branch_pair(branch_, branch); if (is_generally_string_node(branch_.first)) { str_base_ptr_ = dynamic_cast(branch_.first); if (0 == str_base_ptr_) return; } } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { T result = std::numeric_limits::quiet_NaN(); if (str_base_ptr_) { branch_.first->value(); result = T(str_base_ptr_->size()); } return result; } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_stringsize; } ``` a65c8e8b ``` void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override ``` 4068375e ``` { expression_node::ndb_t::collect(branch_, node_delete_list); } ``` a65c8e8b ``` std::size_t node_depth() const exprtk_override ``` 4068375e ``` { return expression_node::ndb_t::compute_node_depth(branch_); } private: branch_t branch_; str_base_ptr str_base_ptr_; }; struct asn_assignment { static inline void execute(std::string& s, char_cptr data, const std::size_t size) { s.assign(data,size); } }; struct asn_addassignment { static inline void execute(std::string& s, char_cptr data, const std::size_t size) { s.append(data,size); } }; template ``` a65c8e8b ``` class assignment_string_node exprtk_final : public binary_node , ``` 4068375e ``` public string_base_node, public range_interface { public: ``` a65c8e8b ``` typedef typename range_interface::range_t range_t; typedef range_t* range_ptr; typedef range_interface irange_t; typedef irange_t* irange_ptr; typedef expression_node * expression_ptr; ``` 4068375e ``` typedef stringvar_node * strvar_node_ptr; ``` a65c8e8b ``` typedef string_base_node* str_base_ptr; ``` 4068375e ``` assignment_string_node(const operator_type& opr, expression_ptr branch0, expression_ptr branch1) ``` a65c8e8b ``` : binary_node(opr, branch0, branch1) , initialised_(false) , str0_base_ptr_ (0) , str1_base_ptr_ (0) , str0_node_ptr_ (0) , str1_range_ptr_(0) ``` 4068375e ``` { if (is_string_node(binary_node::branch_[0].first)) { str0_node_ptr_ = static_cast(binary_node::branch_[0].first); str0_base_ptr_ = dynamic_cast(binary_node::branch_[0].first); } if (is_generally_string_node(binary_node::branch_[1].first)) { str1_base_ptr_ = dynamic_cast(binary_node::branch_[1].first); if (0 == str1_base_ptr_) return; irange_ptr range = dynamic_cast(binary_node::branch_[1].first); if (0 == range) return; str1_range_ptr_ = &(range->range_ref()); } initialised_ = str0_base_ptr_ && str1_base_ptr_ && str0_node_ptr_ && str1_range_ptr_ ; ``` a65c8e8b ``` assert(initialised_); ``` 4068375e ``` } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { if (initialised_) { ``` a65c8e8b ``` assert(binary_node::branch_[0].first); assert(binary_node::branch_[1].first); ``` 4068375e ``` binary_node::branch_[1].first->value(); std::size_t r0 = 0; std::size_t r1 = 0; ``` a65c8e8b ``` const range_t& range = (*str1_range_ptr_); ``` 4068375e ``` if (range(r0, r1, str1_base_ptr_->size())) { AssignmentProcess::execute(str0_node_ptr_->ref(), str1_base_ptr_->base() + r0, (r1 - r0) + 1); binary_node::branch_[0].first->value(); } } return std::numeric_limits::quiet_NaN(); } ``` a65c8e8b ``` std::string str() const exprtk_override ``` 4068375e ``` { return str0_node_ptr_->str(); } ``` a65c8e8b ``` char_cptr base() const exprtk_override ``` 4068375e ``` { return str0_node_ptr_->base(); } ``` a65c8e8b ``` std::size_t size() const exprtk_override ``` 4068375e ``` { return str0_node_ptr_->size(); } ``` a65c8e8b ``` range_t& range_ref() exprtk_override ``` 4068375e ``` { return str0_node_ptr_->range_ref(); } ``` a65c8e8b ``` const range_t& range_ref() const exprtk_override ``` 4068375e ``` { return str0_node_ptr_->range_ref(); } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_strass; } private: bool initialised_; str_base_ptr str0_base_ptr_; str_base_ptr str1_base_ptr_; strvar_node_ptr str0_node_ptr_; range_ptr str1_range_ptr_; }; template ``` a65c8e8b ``` class assignment_string_range_node exprtk_final : public binary_node , ``` 4068375e ``` public string_base_node, public range_interface { public: ``` a65c8e8b ``` typedef typename range_interface::range_t range_t; typedef range_t* range_ptr; typedef range_interface irange_t; typedef irange_t* irange_ptr; typedef expression_node * expression_ptr; typedef stringvar_node * strvar_node_ptr; ``` 4068375e ``` typedef string_range_node* str_rng_node_ptr; ``` a65c8e8b ``` typedef string_base_node * str_base_ptr; ``` 4068375e ``` assignment_string_range_node(const operator_type& opr, expression_ptr branch0, expression_ptr branch1) ``` a65c8e8b ``` : binary_node(opr, branch0, branch1) , initialised_(false) , str0_base_ptr_ (0) , str1_base_ptr_ (0) , str0_rng_node_ptr_(0) , str0_range_ptr_ (0) , str1_range_ptr_ (0) ``` 4068375e ``` { if (is_string_range_node(binary_node::branch_[0].first)) { str0_rng_node_ptr_ = static_cast(binary_node::branch_[0].first); str0_base_ptr_ = dynamic_cast(binary_node::branch_[0].first); irange_ptr range = dynamic_cast(binary_node::branch_[0].first); if (0 == range) return; str0_range_ptr_ = &(range->range_ref()); } if (is_generally_string_node(binary_node::branch_[1].first)) { str1_base_ptr_ = dynamic_cast(binary_node::branch_[1].first); if (0 == str1_base_ptr_) return; irange_ptr range = dynamic_cast(binary_node::branch_[1].first); if (0 == range) return; str1_range_ptr_ = &(range->range_ref()); } initialised_ = str0_base_ptr_ && str1_base_ptr_ && str0_rng_node_ptr_ && str0_range_ptr_ && str1_range_ptr_ ; ``` a65c8e8b ``` assert(initialised_); ``` 4068375e ``` } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { if (initialised_) { ``` a65c8e8b ``` assert(binary_node::branch_[0].first); assert(binary_node::branch_[1].first); ``` 4068375e ``` binary_node::branch_[0].first->value(); binary_node::branch_[1].first->value(); std::size_t s0_r0 = 0; std::size_t s0_r1 = 0; std::size_t s1_r0 = 0; std::size_t s1_r1 = 0; ``` a65c8e8b ``` const range_t& range0 = (*str0_range_ptr_); const range_t& range1 = (*str1_range_ptr_); ``` 4068375e ``` if ( range0(s0_r0, s0_r1, str0_base_ptr_->size()) && range1(s1_r0, s1_r1, str1_base_ptr_->size()) ) { const std::size_t size = std::min((s0_r1 - s0_r0), (s1_r1 - s1_r0)) + 1; std::copy(str1_base_ptr_->base() + s1_r0, str1_base_ptr_->base() + s1_r0 + size, const_cast(base() + s0_r0)); } } return std::numeric_limits::quiet_NaN(); } ``` a65c8e8b ``` std::string str() const exprtk_override ``` 4068375e ``` { return str0_base_ptr_->str(); } ``` a65c8e8b ``` char_cptr base() const exprtk_override ``` 4068375e ``` { return str0_base_ptr_->base(); } ``` a65c8e8b ``` std::size_t size() const exprtk_override ``` 4068375e ``` { return str0_base_ptr_->size(); } ``` a65c8e8b ``` range_t& range_ref() exprtk_override ``` 4068375e ``` { return str0_rng_node_ptr_->range_ref(); } ``` a65c8e8b ``` const range_t& range_ref() const exprtk_override ``` 4068375e ``` { return str0_rng_node_ptr_->range_ref(); } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_strass; } private: bool initialised_; str_base_ptr str0_base_ptr_; str_base_ptr str1_base_ptr_; str_rng_node_ptr str0_rng_node_ptr_; range_ptr str0_range_ptr_; range_ptr str1_range_ptr_; }; template ``` a65c8e8b ``` class conditional_string_node exprtk_final : public trinary_node , ``` 4068375e ``` public string_base_node, public range_interface { public: ``` a65c8e8b ``` typedef typename range_interface::range_t range_t; typedef range_t* range_ptr; typedef range_interface irange_t; typedef irange_t* irange_ptr; ``` 4068375e ``` typedef expression_node * expression_ptr; ``` a65c8e8b ``` typedef string_base_node* str_base_ptr; ``` 4068375e ``` ``` a65c8e8b ``` conditional_string_node(expression_ptr condition, ``` 4068375e ``` expression_ptr consequent, expression_ptr alternative) ``` a65c8e8b ``` : trinary_node(details::e_default, consequent, alternative, condition) , initialised_(false) , str0_base_ptr_ (0) , str1_base_ptr_ (0) , str0_range_ptr_(0) , str1_range_ptr_(0) , condition_ (condition ) , consequent_ (consequent ) , alternative_(alternative) ``` 4068375e ``` { range_.n0_c = std::make_pair(true,0); range_.n1_c = std::make_pair(true,0); range_.cache.first = range_.n0_c.second; range_.cache.second = range_.n1_c.second; if (is_generally_string_node(trinary_node::branch_[0].first)) { str0_base_ptr_ = dynamic_cast(trinary_node::branch_[0].first); if (0 == str0_base_ptr_) return; str0_range_ptr_ = dynamic_cast(trinary_node::branch_[0].first); if (0 == str0_range_ptr_) return; } if (is_generally_string_node(trinary_node::branch_[1].first)) { str1_base_ptr_ = dynamic_cast(trinary_node::branch_[1].first); if (0 == str1_base_ptr_) return; str1_range_ptr_ = dynamic_cast(trinary_node::branch_[1].first); if (0 == str1_range_ptr_) return; } initialised_ = str0_base_ptr_ && str1_base_ptr_ && str0_range_ptr_ && str1_range_ptr_ ; ``` a65c8e8b ``` assert(initialised_); ``` 4068375e ``` } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { if (initialised_) { ``` a65c8e8b ``` assert(condition_ ); assert(consequent_ ); assert(alternative_); ``` 4068375e ``` std::size_t r0 = 0; std::size_t r1 = 0; ``` a65c8e8b ``` if (is_true(condition_)) ``` 4068375e ``` { consequent_->value(); ``` a65c8e8b ``` const range_t& range = str0_range_ptr_->range_ref(); ``` 4068375e ``` if (range(r0, r1, str0_base_ptr_->size())) { const std::size_t size = (r1 - r0) + 1; value_.assign(str0_base_ptr_->base() + r0, size); range_.n1_c.second = value_.size() - 1; range_.cache.second = range_.n1_c.second; return T(1); } } else { alternative_->value(); ``` a65c8e8b ``` const range_t& range = str1_range_ptr_->range_ref(); ``` 4068375e ``` if (range(r0, r1, str1_base_ptr_->size())) { const std::size_t size = (r1 - r0) + 1; value_.assign(str1_base_ptr_->base() + r0, size); range_.n1_c.second = value_.size() - 1; range_.cache.second = range_.n1_c.second; return T(0); } } } return std::numeric_limits::quiet_NaN(); } ``` a65c8e8b ``` std::string str() const exprtk_override ``` 4068375e ``` { return value_; } ``` a65c8e8b ``` char_cptr base() const exprtk_override ``` 4068375e ``` { return &value_[0]; } ``` a65c8e8b ``` std::size_t size() const exprtk_override ``` 4068375e ``` { return value_.size(); } ``` a65c8e8b ``` range_t& range_ref() exprtk_override ``` 4068375e ``` { return range_; } ``` a65c8e8b ``` const range_t& range_ref() const exprtk_override ``` 4068375e ``` { return range_; } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_strcondition; } private: bool initialised_; str_base_ptr str0_base_ptr_; str_base_ptr str1_base_ptr_; irange_ptr str0_range_ptr_; irange_ptr str1_range_ptr_; mutable range_t range_; mutable std::string value_; ``` a65c8e8b ``` expression_ptr condition_; ``` 4068375e ``` expression_ptr consequent_; expression_ptr alternative_; }; template ``` a65c8e8b ``` class cons_conditional_str_node exprtk_final : public binary_node , ``` 4068375e ``` public string_base_node, public range_interface { public: ``` a65c8e8b ``` typedef typename range_interface::range_t range_t; typedef range_t* range_ptr; typedef range_interface irange_t; typedef irange_t* irange_ptr; ``` 4068375e ``` typedef expression_node * expression_ptr; ``` a65c8e8b ``` typedef string_base_node* str_base_ptr; ``` 4068375e ``` ``` a65c8e8b ``` cons_conditional_str_node(expression_ptr condition, ``` 4068375e ``` expression_ptr consequent) ``` a65c8e8b ``` : binary_node(details::e_default, consequent, condition) , initialised_(false) , str0_base_ptr_ (0) , str0_range_ptr_(0) , condition_ (condition ) , consequent_(consequent) ``` 4068375e ``` { range_.n0_c = std::make_pair(true,0); range_.n1_c = std::make_pair(true,0); range_.cache.first = range_.n0_c.second; range_.cache.second = range_.n1_c.second; if (is_generally_string_node(binary_node::branch_[0].first)) { str0_base_ptr_ = dynamic_cast(binary_node::branch_[0].first); if (0 == str0_base_ptr_) return; str0_range_ptr_ = dynamic_cast(binary_node::branch_[0].first); if (0 == str0_range_ptr_) return; } initialised_ = str0_base_ptr_ && str0_range_ptr_ ; ``` a65c8e8b ``` assert(initialised_); ``` 4068375e ``` } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { if (initialised_) { ``` a65c8e8b ``` assert(condition_ ); assert(consequent_); if (is_true(condition_)) ``` 4068375e ``` { consequent_->value(); ``` a65c8e8b ``` const range_t& range = str0_range_ptr_->range_ref(); ``` 4068375e ``` std::size_t r0 = 0; std::size_t r1 = 0; if (range(r0, r1, str0_base_ptr_->size())) { const std::size_t size = (r1 - r0) + 1; value_.assign(str0_base_ptr_->base() + r0, size); range_.n1_c.second = value_.size() - 1; range_.cache.second = range_.n1_c.second; return T(1); } } } return std::numeric_limits::quiet_NaN(); } std::string str() const { return value_; } char_cptr base() const { return &value_[0]; } std::size_t size() const { return value_.size(); } range_t& range_ref() { return range_; } const range_t& range_ref() const { return range_; } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_strccondition; } private: bool initialised_; str_base_ptr str0_base_ptr_; irange_ptr str0_range_ptr_; mutable range_t range_; mutable std::string value_; ``` a65c8e8b ``` expression_ptr condition_; ``` 4068375e ``` expression_ptr consequent_; }; template ``` a65c8e8b ``` class str_vararg_node exprtk_final : public expression_node , public string_base_node, public range_interface ``` 4068375e ``` { public: ``` a65c8e8b ``` typedef typename range_interface::range_t range_t; typedef range_t* range_ptr; typedef range_interface irange_t; typedef irange_t* irange_ptr; typedef expression_node * expression_ptr; typedef string_base_node* str_base_ptr; ``` 4068375e ``` typedef std::pair branch_t; template class Sequence> explicit str_vararg_node(const Sequence& arg_list) ``` a65c8e8b ``` : initialised_(false) , str_base_ptr_ (0) , str_range_ptr_(0) ``` 4068375e ``` { construct_branch_pair(final_node_, const_cast(arg_list.back())); if (0 == final_node_.first) return; else if (!is_generally_string_node(final_node_.first)) return; str_base_ptr_ = dynamic_cast(final_node_.first); if (0 == str_base_ptr_) return; str_range_ptr_ = dynamic_cast(final_node_.first); if (0 == str_range_ptr_) return; initialised_ = str_base_ptr_ && str_range_ptr_; if (arg_list.size() > 1) { const std::size_t arg_list_size = arg_list.size() - 1; arg_list_.resize(arg_list_size); for (std::size_t i = 0; i < arg_list_size; ++i) { if (arg_list[i]) { construct_branch_pair(arg_list_[i], arg_list[i]); } else { arg_list_.clear(); return; } } } } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { if (!arg_list_.empty()) { VarArgFunction::process(arg_list_); } final_node_.first->value(); return std::numeric_limits::quiet_NaN(); } ``` a65c8e8b ``` std::string str() const exprtk_override ``` 4068375e ``` { return str_base_ptr_->str(); } ``` a65c8e8b ``` char_cptr base() const exprtk_override ``` 4068375e ``` { return str_base_ptr_->base(); } ``` a65c8e8b ``` std::size_t size() const exprtk_override ``` 4068375e ``` { return str_base_ptr_->size(); } ``` a65c8e8b ``` range_t& range_ref() exprtk_override ``` 4068375e ``` { return str_range_ptr_->range_ref(); } ``` a65c8e8b ``` const range_t& range_ref() const exprtk_override ``` 4068375e ``` { return str_range_ptr_->range_ref(); } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_stringvararg; } ``` a65c8e8b ``` void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override ``` 4068375e ``` { ``` a65c8e8b ``` expression_node::ndb_t::collect(final_node_ , node_delete_list); expression_node::ndb_t::collect(arg_list_ , node_delete_list); ``` 4068375e ``` } ``` a65c8e8b ``` std::size_t node_depth() const exprtk_override ``` 4068375e ``` { return std::max( expression_node::ndb_t::compute_node_depth(final_node_), expression_node::ndb_t::compute_node_depth(arg_list_ )); } private: bool initialised_; branch_t final_node_; str_base_ptr str_base_ptr_; irange_ptr str_range_ptr_; std::vector arg_list_; }; #endif template ``` a65c8e8b ``` inline T axn(const T a, const T x) ``` 4068375e ``` { // a*x^n return a * exprtk::details::numeric::fast_exp::result(x); } template ``` a65c8e8b ``` inline T axnb(const T a, const T x, const T b) ``` 4068375e ``` { // a*x^n+b return a * exprtk::details::numeric::fast_exp::result(x) + b; } 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; ``` a65c8e8b ``` 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; ``` 4068375e ``` }; ``` a65c8e8b ``` #define define_sfop3(NN, OP0, OP1) \ ``` 4068375e ``` template \ struct sf##NN##_op : public sf_base \ { \ typedef typename sf_base::Type const Type; \ static inline T process(Type x, Type y, Type z) \ { \ return (OP0); \ } \ static inline std::string id() \ { \ return (OP1); \ } \ }; \ define_sfop3(00,(x + y) / z ,"(t+t)/t") define_sfop3(01,(x + y) * z ,"(t+t)*t") define_sfop3(02,(x + y) - z ,"(t+t)-t") define_sfop3(03,(x + y) + z ,"(t+t)+t") define_sfop3(04,(x - y) + z ,"(t-t)+t") define_sfop3(05,(x - y) / z ,"(t-t)/t") define_sfop3(06,(x - y) * z ,"(t-t)*t") define_sfop3(07,(x * y) + z ,"(t*t)+t") define_sfop3(08,(x * y) - z ,"(t*t)-t") define_sfop3(09,(x * y) / z ,"(t*t)/t") define_sfop3(10,(x * y) * z ,"(t*t)*t") define_sfop3(11,(x / y) + z ,"(t/t)+t") define_sfop3(12,(x / y) - z ,"(t/t)-t") define_sfop3(13,(x / y) / z ,"(t/t)/t") define_sfop3(14,(x / y) * z ,"(t/t)*t") define_sfop3(15,x / (y + z) ,"t/(t+t)") define_sfop3(16,x / (y - z) ,"t/(t-t)") define_sfop3(17,x / (y * z) ,"t/(t*t)") define_sfop3(18,x / (y / z) ,"t/(t/t)") define_sfop3(19,x * (y + z) ,"t*(t+t)") define_sfop3(20,x * (y - z) ,"t*(t-t)") define_sfop3(21,x * (y * z) ,"t*(t*t)") define_sfop3(22,x * (y / z) ,"t*(t/t)") define_sfop3(23,x - (y + z) ,"t-(t+t)") define_sfop3(24,x - (y - z) ,"t-(t-t)") define_sfop3(25,x - (y / z) ,"t-(t/t)") define_sfop3(26,x - (y * z) ,"t-(t*t)") define_sfop3(27,x + (y * z) ,"t+(t*t)") define_sfop3(28,x + (y / z) ,"t+(t/t)") define_sfop3(29,x + (y + z) ,"t+(t+t)") define_sfop3(30,x + (y - z) ,"t+(t-t)") define_sfop3(31,(axnb(x,y,z))," ") define_sfop3(32,(axnb(x,y,z))," ") define_sfop3(33,(axnb(x,y,z))," ") define_sfop3(34,(axnb(x,y,z))," ") define_sfop3(35,(axnb(x,y,z))," ") define_sfop3(36,(axnb(x,y,z))," ") define_sfop3(37,(axnb(x,y,z))," ") define_sfop3(38,(axnb(x,y,z))," ") define_sfop3(39,x * numeric::log(y) + z,"") define_sfop3(40,x * numeric::log(y) - z,"") define_sfop3(41,x * numeric::log10(y) + z,"") define_sfop3(42,x * numeric::log10(y) - z,"") define_sfop3(43,x * numeric::sin(y) + z ,"") define_sfop3(44,x * numeric::sin(y) - z ,"") define_sfop3(45,x * numeric::cos(y) + z ,"") define_sfop3(46,x * numeric::cos(y) - z ,"") define_sfop3(47,details::is_true(x) ? y : z,"") ``` a65c8e8b ``` #define define_sfop4(NN, OP0, OP1) \ ``` 4068375e ``` template \ struct sf##NN##_op : public sf_base \ { \ typedef typename sf_base::Type const Type; \ static inline T process(Type x, Type y, Type z, Type w) \ { \ return (OP0); \ } \ static inline std::string id() \ { \ return (OP1); \ } \ }; \ define_sfop4(48,(x + ((y + z) / w)),"t+((t+t)/t)") define_sfop4(49,(x + ((y + z) * w)),"t+((t+t)*t)") define_sfop4(50,(x + ((y - z) / w)),"t+((t-t)/t)") define_sfop4(51,(x + ((y - z) * w)),"t+((t-t)*t)") define_sfop4(52,(x + ((y * z) / w)),"t+((t*t)/t)") define_sfop4(53,(x + ((y * z) * w)),"t+((t*t)*t)") define_sfop4(54,(x + ((y / z) + w)),"t+((t/t)+t)") define_sfop4(55,(x + ((y / z) / w)),"t+((t/t)/t)") define_sfop4(56,(x + ((y / z) * w)),"t+((t/t)*t)") define_sfop4(57,(x - ((y + z) / w)),"t-((t+t)/t)") define_sfop4(58,(x - ((y + z) * w)),"t-((t+t)*t)") define_sfop4(59,(x - ((y - z) / w)),"t-((t-t)/t)") define_sfop4(60,(x - ((y - z) * w)),"t-((t-t)*t)") define_sfop4(61,(x - ((y * z) / w)),"t-((t*t)/t)") define_sfop4(62,(x - ((y * z) * w)),"t-((t*t)*t)") define_sfop4(63,(x - ((y / z) / w)),"t-((t/t)/t)") define_sfop4(64,(x - ((y / z) * w)),"t-((t/t)*t)") define_sfop4(65,(((x + y) * z) - w),"((t+t)*t)-t") define_sfop4(66,(((x - y) * z) - w),"((t-t)*t)-t") define_sfop4(67,(((x * y) * z) - w),"((t*t)*t)-t") define_sfop4(68,(((x / y) * z) - w),"((t/t)*t)-t") define_sfop4(69,(((x + y) / z) - w),"((t+t)/t)-t") define_sfop4(70,(((x - y) / z) - w),"((t-t)/t)-t") define_sfop4(71,(((x * y) / z) - w),"((t*t)/t)-t") define_sfop4(72,(((x / y) / z) - w),"((t/t)/t)-t") define_sfop4(73,((x * y) + (z * w)),"(t*t)+(t*t)") define_sfop4(74,((x * y) - (z * w)),"(t*t)-(t*t)") define_sfop4(75,((x * y) + (z / w)),"(t*t)+(t/t)") define_sfop4(76,((x * y) - (z / w)),"(t*t)-(t/t)") define_sfop4(77,((x / y) + (z / w)),"(t/t)+(t/t)") define_sfop4(78,((x / y) - (z / w)),"(t/t)-(t/t)") define_sfop4(79,((x / y) - (z * w)),"(t/t)-(t*t)") define_sfop4(80,(x / (y + (z * w))),"t/(t+(t*t))") define_sfop4(81,(x / (y - (z * w))),"t/(t-(t*t))") define_sfop4(82,(x * (y + (z * w))),"t*(t+(t*t))") define_sfop4(83,(x * (y - (z * w))),"t*(t-(t*t))") define_sfop4(84,(axn(x,y) + axn(z,w)),"") define_sfop4(85,(axn(x,y) + axn(z,w)),"") define_sfop4(86,(axn(x,y) + axn(z,w)),"") define_sfop4(87,(axn(x,y) + axn(z,w)),"") define_sfop4(88,(axn(x,y) + axn(z,w)),"") define_sfop4(89,(axn(x,y) + axn(z,w)),"") define_sfop4(90,(axn(x,y) + axn(z,w)),"") define_sfop4(91,(axn(x,y) + axn(z,w)),"") define_sfop4(92,((details::is_true(x) && details::is_true(y)) ? z : w),"") define_sfop4(93,((details::is_true(x) || details::is_true(y)) ? z : w),"") define_sfop4(94,((x < y) ? z : w),"") define_sfop4(95,((x <= y) ? z : w),"") define_sfop4(96,((x > y) ? z : w),"") define_sfop4(97,((x >= y) ? z : w),"") define_sfop4(98,(details::is_true(numeric::equal(x,y)) ? z : w),"") define_sfop4(99,(x * numeric::sin(y) + z * numeric::cos(w)),"") define_sfop4(ext00,((x + y) - (z * w)),"(t+t)-(t*t)") define_sfop4(ext01,((x + y) - (z / w)),"(t+t)-(t/t)") define_sfop4(ext02,((x + y) + (z * w)),"(t+t)+(t*t)") define_sfop4(ext03,((x + y) + (z / w)),"(t+t)+(t/t)") define_sfop4(ext04,((x - y) + (z * w)),"(t-t)+(t*t)") define_sfop4(ext05,((x - y) + (z / w)),"(t-t)+(t/t)") define_sfop4(ext06,((x - y) - (z * w)),"(t-t)-(t*t)") define_sfop4(ext07,((x - y) - (z / w)),"(t-t)-(t/t)") define_sfop4(ext08,((x + y) - (z - w)),"(t+t)-(t-t)") define_sfop4(ext09,((x + y) + (z - w)),"(t+t)+(t-t)") define_sfop4(ext10,((x + y) + (z + w)),"(t+t)+(t+t)") define_sfop4(ext11,((x + y) * (z - w)),"(t+t)*(t-t)") define_sfop4(ext12,((x + y) / (z - w)),"(t+t)/(t-t)") define_sfop4(ext13,((x - y) - (z + w)),"(t-t)-(t+t)") define_sfop4(ext14,((x - y) + (z + w)),"(t-t)+(t+t)") define_sfop4(ext15,((x - y) * (z + w)),"(t-t)*(t+t)") define_sfop4(ext16,((x - y) / (z + w)),"(t-t)/(t+t)") define_sfop4(ext17,((x * y) - (z + w)),"(t*t)-(t+t)") define_sfop4(ext18,((x / y) - (z + w)),"(t/t)-(t+t)") define_sfop4(ext19,((x * y) + (z + w)),"(t*t)+(t+t)") define_sfop4(ext20,((x / y) + (z + w)),"(t/t)+(t+t)") define_sfop4(ext21,((x * y) + (z - w)),"(t*t)+(t-t)") define_sfop4(ext22,((x / y) + (z - w)),"(t/t)+(t-t)") define_sfop4(ext23,((x * y) - (z - w)),"(t*t)-(t-t)") define_sfop4(ext24,((x / y) - (z - w)),"(t/t)-(t-t)") define_sfop4(ext25,((x + y) * (z * w)),"(t+t)*(t*t)") define_sfop4(ext26,((x + y) * (z / w)),"(t+t)*(t/t)") define_sfop4(ext27,((x + y) / (z * w)),"(t+t)/(t*t)") define_sfop4(ext28,((x + y) / (z / w)),"(t+t)/(t/t)") define_sfop4(ext29,((x - y) / (z * w)),"(t-t)/(t*t)") define_sfop4(ext30,((x - y) / (z / w)),"(t-t)/(t/t)") define_sfop4(ext31,((x - y) * (z * w)),"(t-t)*(t*t)") define_sfop4(ext32,((x - y) * (z / w)),"(t-t)*(t/t)") define_sfop4(ext33,((x * y) * (z + w)),"(t*t)*(t+t)") define_sfop4(ext34,((x / y) * (z + w)),"(t/t)*(t+t)") define_sfop4(ext35,((x * y) / (z + w)),"(t*t)/(t+t)") define_sfop4(ext36,((x / y) / (z + w)),"(t/t)/(t+t)") define_sfop4(ext37,((x * y) / (z - w)),"(t*t)/(t-t)") define_sfop4(ext38,((x / y) / (z - w)),"(t/t)/(t-t)") define_sfop4(ext39,((x * y) * (z - w)),"(t*t)*(t-t)") define_sfop4(ext40,((x * y) / (z * w)),"(t*t)/(t*t)") define_sfop4(ext41,((x / y) * (z / w)),"(t/t)*(t/t)") define_sfop4(ext42,((x / y) * (z - w)),"(t/t)*(t-t)") define_sfop4(ext43,((x * y) * (z * w)),"(t*t)*(t*t)") define_sfop4(ext44,(x + (y * (z / w))),"t+(t*(t/t))") define_sfop4(ext45,(x - (y * (z / w))),"t-(t*(t/t))") define_sfop4(ext46,(x + (y / (z * w))),"t+(t/(t*t))") define_sfop4(ext47,(x - (y / (z * w))),"t-(t/(t*t))") define_sfop4(ext48,(((x - y) - z) * w),"((t-t)-t)*t") define_sfop4(ext49,(((x - y) - z) / w),"((t-t)-t)/t") define_sfop4(ext50,(((x - y) + z) * w),"((t-t)+t)*t") define_sfop4(ext51,(((x - y) + z) / w),"((t-t)+t)/t") define_sfop4(ext52,((x + (y - z)) * w),"(t+(t-t))*t") define_sfop4(ext53,((x + (y - z)) / w),"(t+(t-t))/t") define_sfop4(ext54,((x + y) / (z + w)),"(t+t)/(t+t)") define_sfop4(ext55,((x - y) / (z - w)),"(t-t)/(t-t)") define_sfop4(ext56,((x + y) * (z + w)),"(t+t)*(t+t)") define_sfop4(ext57,((x - y) * (z - w)),"(t-t)*(t-t)") define_sfop4(ext58,((x - y) + (z - w)),"(t-t)+(t-t)") define_sfop4(ext59,((x - y) - (z - w)),"(t-t)-(t-t)") define_sfop4(ext60,((x / y) + (z * w)),"(t/t)+(t*t)") define_sfop4(ext61,(((x * y) * z) / w),"((t*t)*t)/t") #undef define_sfop3 #undef define_sfop4 template ``` a65c8e8b ``` class sf3_node exprtk_final : public trinary_node ``` 4068375e ``` { public: typedef expression_node* expression_ptr; sf3_node(const operator_type& opr, expression_ptr branch0, expression_ptr branch1, expression_ptr branch2) : trinary_node(opr, branch0, branch1, branch2) {} ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { ``` a65c8e8b ``` assert(trinary_node::branch_[0].first); assert(trinary_node::branch_[1].first); assert(trinary_node::branch_[2].first); ``` 4068375e ``` 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); } }; template ``` a65c8e8b ``` class sf4_node exprtk_final : public quaternary_node ``` 4068375e ``` { public: typedef expression_node* expression_ptr; sf4_node(const operator_type& opr, expression_ptr branch0, expression_ptr branch1, expression_ptr branch2, expression_ptr branch3) : quaternary_node(opr, branch0, branch1, branch2, branch3) {} ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { ``` a65c8e8b ``` assert(quaternary_node::branch_[0].first); assert(quaternary_node::branch_[1].first); assert(quaternary_node::branch_[2].first); assert(quaternary_node::branch_[3].first); ``` 4068375e ``` const T x = quaternary_node::branch_[0].first->value(); 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); } }; template ``` a65c8e8b ``` class sf3_var_node exprtk_final : public expression_node ``` 4068375e ``` { public: typedef expression_node* expression_ptr; sf3_var_node(const T& v0, const T& v1, const T& v2) ``` a65c8e8b ``` : v0_(v0) , v1_(v1) , v2_(v2) ``` 4068375e ``` {} ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { return SpecialFunction::process(v0_, v1_, v2_); } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_trinary; } private: ``` a65c8e8b ``` sf3_var_node(const sf3_var_node&) exprtk_delete; sf3_var_node& operator=(const sf3_var_node&) exprtk_delete; ``` 4068375e ``` const T& v0_; const T& v1_; const T& v2_; }; template ``` a65c8e8b ``` class sf4_var_node exprtk_final : public expression_node ``` 4068375e ``` { public: typedef expression_node* expression_ptr; sf4_var_node(const T& v0, const T& v1, const T& v2, const T& v3) ``` a65c8e8b ``` : v0_(v0) , v1_(v1) , v2_(v2) , v3_(v3) ``` 4068375e ``` {} ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { return SpecialFunction::process(v0_, v1_, v2_, v3_); } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_trinary; } private: ``` a65c8e8b ``` sf4_var_node(const sf4_var_node&) exprtk_delete; sf4_var_node& operator=(const sf4_var_node&) exprtk_delete; ``` 4068375e ``` const T& v0_; const T& v1_; const T& v2_; const T& v3_; }; template ``` a65c8e8b ``` class vararg_node exprtk_final : public expression_node ``` 4068375e ``` { public: typedef expression_node* expression_ptr; typedef std::pair branch_t; template class Sequence> explicit vararg_node(const Sequence& arg_list) { arg_list_.resize(arg_list.size()); for (std::size_t i = 0; i < arg_list.size(); ++i) { if (arg_list[i]) { construct_branch_pair(arg_list_[i],arg_list[i]); } else { arg_list_.clear(); return; } } } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { return VarArgFunction::process(arg_list_); } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_vararg; } ``` a65c8e8b ``` void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override ``` 4068375e ``` { expression_node::ndb_t::collect(arg_list_, node_delete_list); } ``` a65c8e8b ``` std::size_t node_depth() const exprtk_override ``` 4068375e ``` { return expression_node::ndb_t::compute_node_depth(arg_list_); } private: std::vector arg_list_; }; template ``` a65c8e8b ``` class vararg_varnode exprtk_final : public expression_node ``` 4068375e ``` { public: typedef expression_node* expression_ptr; template class Sequence> explicit vararg_varnode(const Sequence& arg_list) { arg_list_.resize(arg_list.size()); for (std::size_t i = 0; i < arg_list.size(); ++i) { if (arg_list[i] && is_variable_node(arg_list[i])) { variable_node* var_node_ptr = static_cast*>(arg_list[i]); arg_list_[i] = (&var_node_ptr->ref()); } else { arg_list_.clear(); return; } } } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { if (!arg_list_.empty()) return VarArgFunction::process(arg_list_); else return std::numeric_limits::quiet_NaN(); } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_vararg; } private: std::vector arg_list_; }; template ``` a65c8e8b ``` class vectorize_node exprtk_final : public expression_node ``` 4068375e ``` { public: typedef expression_node* expression_ptr; typedef std::pair branch_t; explicit vectorize_node(const expression_ptr v) : ivec_ptr_(0) { construct_branch_pair(v_, v); if (is_ivector_node(v_.first)) { ivec_ptr_ = dynamic_cast*>(v_.first); } else ivec_ptr_ = 0; } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { if (ivec_ptr_) { ``` a65c8e8b ``` assert(v_.first); ``` 4068375e ``` v_.first->value(); ``` a65c8e8b ``` ``` 4068375e ``` return VecFunction::process(ivec_ptr_); } else return std::numeric_limits::quiet_NaN(); } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_vecfunc; } ``` a65c8e8b ``` void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override ``` 4068375e ``` { expression_node::ndb_t::collect(v_, node_delete_list); } ``` a65c8e8b ``` std::size_t node_depth() const exprtk_override ``` 4068375e ``` { return expression_node::ndb_t::compute_node_depth(v_); } private: vector_interface* ivec_ptr_; branch_t v_; }; template ``` a65c8e8b ``` class assignment_node exprtk_final : public binary_node ``` 4068375e ``` { public: typedef expression_node* expression_ptr; assignment_node(const operator_type& opr, expression_ptr branch0, expression_ptr branch1) ``` a65c8e8b ``` : binary_node(opr, branch0, branch1) , var_node_ptr_(0) ``` 4068375e ``` { if (is_variable_node(binary_node::branch_[0].first)) { var_node_ptr_ = static_cast*>(binary_node::branch_[0].first); } } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { if (var_node_ptr_) { ``` a65c8e8b ``` assert(binary_node::branch_[1].first); ``` 4068375e ``` T& result = var_node_ptr_->ref(); result = binary_node::branch_[1].first->value(); return result; } else return std::numeric_limits::quiet_NaN(); } private: variable_node* var_node_ptr_; }; template ``` a65c8e8b ``` class assignment_vec_elem_node exprtk_final : public binary_node ``` 4068375e ``` { public: typedef expression_node* expression_ptr; assignment_vec_elem_node(const operator_type& opr, expression_ptr branch0, expression_ptr branch1) ``` a65c8e8b ``` : binary_node(opr, branch0, branch1) , vec_node_ptr_(0) ``` 4068375e ``` { if (is_vector_elem_node(binary_node::branch_[0].first)) { vec_node_ptr_ = static_cast*>(binary_node::branch_[0].first); } } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { if (vec_node_ptr_) { ``` a65c8e8b ``` assert(binary_node::branch_[1].first); ``` 4068375e ``` T& result = vec_node_ptr_->ref(); result = binary_node::branch_[1].first->value(); return result; } else return std::numeric_limits::quiet_NaN(); } private: vector_elem_node* vec_node_ptr_; }; template ``` a65c8e8b ``` class assignment_rebasevec_elem_node exprtk_final : public binary_node ``` 4068375e ``` { public: typedef expression_node* expression_ptr; assignment_rebasevec_elem_node(const operator_type& opr, expression_ptr branch0, expression_ptr branch1) ``` a65c8e8b ``` : binary_node(opr, branch0, branch1) , rbvec_node_ptr_(0) ``` 4068375e ``` { if (is_rebasevector_elem_node(binary_node::branch_[0].first)) { rbvec_node_ptr_ = static_cast*>(binary_node::branch_[0].first); } } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { if (rbvec_node_ptr_) { ``` a65c8e8b ``` assert(binary_node::branch_[1].first); ``` 4068375e ``` T& result = rbvec_node_ptr_->ref(); result = binary_node::branch_[1].first->value(); return result; } else return std::numeric_limits::quiet_NaN(); } private: rebasevector_elem_node* rbvec_node_ptr_; }; template ``` a65c8e8b ``` class assignment_rebasevec_celem_node exprtk_final : public binary_node ``` 4068375e ``` { public: typedef expression_node* expression_ptr; assignment_rebasevec_celem_node(const operator_type& opr, expression_ptr branch0, expression_ptr branch1) ``` a65c8e8b ``` : binary_node(opr, branch0, branch1) , rbvec_node_ptr_(0) ``` 4068375e ``` { if (is_rebasevector_celem_node(binary_node::branch_[0].first)) { rbvec_node_ptr_ = static_cast*>(binary_node::branch_[0].first); } } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { if (rbvec_node_ptr_) { ``` a65c8e8b ``` assert(binary_node::branch_[1].first); ``` 4068375e ``` T& result = rbvec_node_ptr_->ref(); result = binary_node::branch_[1].first->value(); return result; } else return std::numeric_limits::quiet_NaN(); } private: rebasevector_celem_node* rbvec_node_ptr_; }; template ``` a65c8e8b ``` class assignment_vec_node exprtk_final : public binary_node , public vector_interface ``` 4068375e ``` { public: typedef expression_node* expression_ptr; ``` a65c8e8b ``` typedef vector_node* vector_node_ptr; typedef vec_data_store vds_t; ``` 4068375e ``` assignment_vec_node(const operator_type& opr, expression_ptr branch0, expression_ptr branch1) ``` a65c8e8b ``` : binary_node(opr, branch0, branch1) , vec_node_ptr_(0) ``` 4068375e ``` { if (is_vector_node(binary_node::branch_[0].first)) { vec_node_ptr_ = static_cast*>(binary_node::branch_[0].first); vds() = vec_node_ptr_->vds(); } } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { if (vec_node_ptr_) { ``` a65c8e8b ``` assert(binary_node::branch_[1].first); ``` 4068375e ``` const T v = binary_node::branch_[1].first->value(); T* vec = vds().data(); loop_unroll::details lud(size()); const T* upper_bound = vec + lud.upper_bound; while (vec < upper_bound) { #define exprtk_loop(N) \ vec[N] = v; \ exprtk_loop( 0) exprtk_loop( 1) exprtk_loop( 2) exprtk_loop( 3) #ifndef exprtk_disable_superscalar_unroll exprtk_loop( 4) exprtk_loop( 5) exprtk_loop( 6) exprtk_loop( 7) exprtk_loop( 8) exprtk_loop( 9) exprtk_loop(10) exprtk_loop(11) exprtk_loop(12) exprtk_loop(13) exprtk_loop(14) exprtk_loop(15) #endif vec += lud.batch_size; } exprtk_disable_fallthrough_begin switch (lud.remainder) { #define case_stmt(N) \ case N : *vec++ = v; \ #ifndef exprtk_disable_superscalar_unroll case_stmt(15) case_stmt(14) case_stmt(13) case_stmt(12) case_stmt(11) case_stmt(10) case_stmt( 9) case_stmt( 8) case_stmt( 7) case_stmt( 6) case_stmt( 5) case_stmt( 4) #endif case_stmt( 3) case_stmt( 2) case_stmt( 1) } exprtk_disable_fallthrough_end #undef exprtk_loop #undef case_stmt return vec_node_ptr_->value(); } else return std::numeric_limits::quiet_NaN(); } ``` a65c8e8b ``` vector_node_ptr vec() const exprtk_override ``` 4068375e ``` { return vec_node_ptr_; } ``` a65c8e8b ``` vector_node_ptr vec() exprtk_override ``` 4068375e ``` { return vec_node_ptr_; } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_vecvalass; } ``` a65c8e8b ``` std::size_t size() const exprtk_override ``` 4068375e ``` { return vds().size(); } ``` a65c8e8b ``` vds_t& vds() exprtk_override ``` 4068375e ``` { return vds_; } ``` a65c8e8b ``` const vds_t& vds() const exprtk_override ``` 4068375e ``` { return vds_; } private: vector_node* vec_node_ptr_; vds_t vds_; }; template ``` a65c8e8b ``` class assignment_vecvec_node exprtk_final : public binary_node , public vector_interface ``` 4068375e ``` { public: ``` a65c8e8b ``` typedef expression_node* expression_ptr; ``` 4068375e ``` typedef vector_node* vector_node_ptr; ``` a65c8e8b ``` typedef vec_data_store vds_t; ``` 4068375e ``` assignment_vecvec_node(const operator_type& opr, expression_ptr branch0, expression_ptr branch1) ``` a65c8e8b ``` : binary_node(opr, branch0, branch1) , vec0_node_ptr_(0) , vec1_node_ptr_(0) , initialised_(false) , src_is_ivec_(false) ``` 4068375e ``` { if (is_vector_node(binary_node::branch_[0].first)) { vec0_node_ptr_ = static_cast*>(binary_node::branch_[0].first); vds() = vec0_node_ptr_->vds(); } if (is_vector_node(binary_node::branch_[1].first)) { vec1_node_ptr_ = static_cast*>(binary_node::branch_[1].first); vds_t::match_sizes(vds(),vec1_node_ptr_->vds()); } else if (is_ivector_node(binary_node::branch_[1].first)) { vector_interface* vi = reinterpret_cast*>(0); if (0 != (vi = dynamic_cast*>(binary_node::branch_[1].first))) { vec1_node_ptr_ = vi->vec(); if (!vi->side_effect()) { vi->vds() = vds(); src_is_ivec_ = true; } else vds_t::match_sizes(vds(),vi->vds()); } } initialised_ = (vec0_node_ptr_ && vec1_node_ptr_); ``` a65c8e8b ``` assert(initialised_); ``` 4068375e ``` } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { if (initialised_) { ``` a65c8e8b ``` assert(binary_node::branch_[1].first); ``` 4068375e ``` binary_node::branch_[1].first->value(); if (src_is_ivec_) return vec0_node_ptr_->value(); T* vec0 = vec0_node_ptr_->vds().data(); T* vec1 = vec1_node_ptr_->vds().data(); loop_unroll::details lud(size()); const T* upper_bound = vec0 + lud.upper_bound; while (vec0 < upper_bound) { #define exprtk_loop(N) \ vec0[N] = vec1[N]; \ exprtk_loop( 0) exprtk_loop( 1) exprtk_loop( 2) exprtk_loop( 3) #ifndef exprtk_disable_superscalar_unroll exprtk_loop( 4) exprtk_loop( 5) exprtk_loop( 6) exprtk_loop( 7) exprtk_loop( 8) exprtk_loop( 9) exprtk_loop(10) exprtk_loop(11) exprtk_loop(12) exprtk_loop(13) exprtk_loop(14) exprtk_loop(15) #endif vec0 += lud.batch_size; vec1 += lud.batch_size; } exprtk_disable_fallthrough_begin switch (lud.remainder) { #define case_stmt(N) \ case N : *vec0++ = *vec1++; \ #ifndef exprtk_disable_superscalar_unroll case_stmt(15) case_stmt(14) case_stmt(13) case_stmt(12) case_stmt(11) case_stmt(10) case_stmt( 9) case_stmt( 8) case_stmt( 7) case_stmt( 6) case_stmt( 5) case_stmt( 4) #endif case_stmt( 3) case_stmt( 2) case_stmt( 1) } exprtk_disable_fallthrough_end #undef exprtk_loop #undef case_stmt return vec0_node_ptr_->value(); } else return std::numeric_limits::quiet_NaN(); } ``` a65c8e8b ``` vector_node_ptr vec() exprtk_override ``` 4068375e ``` { return vec0_node_ptr_; } ``` a65c8e8b ``` vector_node_ptr vec() const exprtk_override ``` 4068375e ``` { return vec0_node_ptr_; } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_vecvecass; } ``` a65c8e8b ``` std::size_t size() const exprtk_override ``` 4068375e ``` { return vds().size(); } ``` a65c8e8b ``` vds_t& vds() exprtk_override ``` 4068375e ``` { return vds_; } ``` a65c8e8b ``` const vds_t& vds() const exprtk_override ``` 4068375e ``` { return vds_; } private: vector_node* vec0_node_ptr_; vector_node* vec1_node_ptr_; bool initialised_; bool src_is_ivec_; vds_t vds_; }; template ``` a65c8e8b ``` class assignment_op_node exprtk_final : public binary_node ``` 4068375e ``` { public: typedef expression_node* expression_ptr; assignment_op_node(const operator_type& opr, expression_ptr branch0, expression_ptr branch1) ``` a65c8e8b ``` : binary_node(opr, branch0, branch1) , var_node_ptr_(0) ``` 4068375e ``` { if (is_variable_node(binary_node::branch_[0].first)) { var_node_ptr_ = static_cast*>(binary_node::branch_[0].first); } } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { if (var_node_ptr_) { ``` a65c8e8b ``` assert(binary_node::branch_[1].first); ``` 4068375e ``` T& v = var_node_ptr_->ref(); v = Operation::process(v,binary_node::branch_[1].first->value()); return v; } else return std::numeric_limits::quiet_NaN(); } private: variable_node* var_node_ptr_; }; template ``` a65c8e8b ``` class assignment_vec_elem_op_node exprtk_final : public binary_node ``` 4068375e ``` { public: typedef expression_node* expression_ptr; assignment_vec_elem_op_node(const operator_type& opr, expression_ptr branch0, expression_ptr branch1) ``` a65c8e8b ``` : binary_node(opr, branch0, branch1) , vec_node_ptr_(0) ``` 4068375e ``` { if (is_vector_elem_node(binary_node::branch_[0].first)) { vec_node_ptr_ = static_cast*>(binary_node::branch_[0].first); } } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { if (vec_node_ptr_) { ``` a65c8e8b ``` assert(binary_node::branch_[1].first); ``` 4068375e ``` T& v = vec_node_ptr_->ref(); v = Operation::process(v,binary_node::branch_[1].first->value()); return v; } else return std::numeric_limits::quiet_NaN(); } private: vector_elem_node* vec_node_ptr_; }; template ``` a65c8e8b ``` class assignment_rebasevec_elem_op_node exprtk_final : public binary_node ``` 4068375e ``` { public: typedef expression_node* expression_ptr; assignment_rebasevec_elem_op_node(const operator_type& opr, expression_ptr branch0, expression_ptr branch1) ``` a65c8e8b ``` : binary_node(opr, branch0, branch1) , rbvec_node_ptr_(0) ``` 4068375e ``` { if (is_rebasevector_elem_node(binary_node::branch_[0].first)) { rbvec_node_ptr_ = static_cast*>(binary_node::branch_[0].first); } } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { if (rbvec_node_ptr_) { ``` a65c8e8b ``` assert(binary_node::branch_[1].first); ``` 4068375e ``` T& v = rbvec_node_ptr_->ref(); v = Operation::process(v,binary_node::branch_[1].first->value()); return v; } else return std::numeric_limits::quiet_NaN(); } private: rebasevector_elem_node* rbvec_node_ptr_; }; template ``` a65c8e8b ``` class assignment_rebasevec_celem_op_node exprtk_final : public binary_node ``` 4068375e ``` { public: typedef expression_node* expression_ptr; assignment_rebasevec_celem_op_node(const operator_type& opr, expression_ptr branch0, expression_ptr branch1) ``` a65c8e8b ``` : binary_node(opr, branch0, branch1) , rbvec_node_ptr_(0) ``` 4068375e ``` { if (is_rebasevector_celem_node(binary_node::branch_[0].first)) { rbvec_node_ptr_ = static_cast*>(binary_node::branch_[0].first); } } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { if (rbvec_node_ptr_) { ``` a65c8e8b ``` assert(binary_node::branch_[1].first); ``` 4068375e ``` T& v = rbvec_node_ptr_->ref(); v = Operation::process(v,binary_node::branch_[1].first->value()); return v; } else return std::numeric_limits::quiet_NaN(); } private: rebasevector_celem_node* rbvec_node_ptr_; }; template ``` a65c8e8b ``` class assignment_vec_op_node exprtk_final : public binary_node , public vector_interface ``` 4068375e ``` { public: ``` a65c8e8b ``` typedef expression_node* expression_ptr; ``` 4068375e ``` typedef vector_node* vector_node_ptr; ``` a65c8e8b ``` typedef vec_data_store vds_t; ``` 4068375e ``` assignment_vec_op_node(const operator_type& opr, expression_ptr branch0, expression_ptr branch1) ``` a65c8e8b ``` : binary_node(opr, branch0, branch1) , vec_node_ptr_(0) ``` 4068375e ``` { if (is_vector_node(binary_node::branch_[0].first)) { vec_node_ptr_ = static_cast*>(binary_node::branch_[0].first); vds() = vec_node_ptr_->vds(); } } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { if (vec_node_ptr_) { ``` a65c8e8b ``` assert(binary_node::branch_[1].first); ``` 4068375e ``` const T v = binary_node::branch_[1].first->value(); T* vec = vds().data(); loop_unroll::details lud(size()); const T* upper_bound = vec + lud.upper_bound; while (vec < upper_bound) { #define exprtk_loop(N) \ Operation::assign(vec[N],v); \ exprtk_loop( 0) exprtk_loop( 1) exprtk_loop( 2) exprtk_loop( 3) #ifndef exprtk_disable_superscalar_unroll exprtk_loop( 4) exprtk_loop( 5) exprtk_loop( 6) exprtk_loop( 7) exprtk_loop( 8) exprtk_loop( 9) exprtk_loop(10) exprtk_loop(11) exprtk_loop(12) exprtk_loop(13) exprtk_loop(14) exprtk_loop(15) #endif vec += lud.batch_size; } exprtk_disable_fallthrough_begin switch (lud.remainder) { #define case_stmt(N) \ case N : Operation::assign(*vec++,v); \ #ifndef exprtk_disable_superscalar_unroll case_stmt(15) case_stmt(14) case_stmt(13) case_stmt(12) case_stmt(11) case_stmt(10) case_stmt( 9) case_stmt( 8) case_stmt( 7) case_stmt( 6) case_stmt( 5) case_stmt( 4) #endif case_stmt( 3) case_stmt( 2) case_stmt( 1) } exprtk_disable_fallthrough_end #undef exprtk_loop #undef case_stmt return vec_node_ptr_->value(); } else return std::numeric_limits::quiet_NaN(); } ``` a65c8e8b ``` vector_node_ptr vec() const exprtk_override ``` 4068375e ``` { return vec_node_ptr_; } ``` a65c8e8b ``` vector_node_ptr vec() exprtk_override ``` 4068375e ``` { return vec_node_ptr_; } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_vecopvalass; } ``` a65c8e8b ``` std::size_t size() const exprtk_override ``` 4068375e ``` { return vds().size(); } ``` a65c8e8b ``` vds_t& vds() exprtk_override ``` 4068375e ``` { return vds_; } ``` a65c8e8b ``` const vds_t& vds() const exprtk_override ``` 4068375e ``` { return vds_; } ``` a65c8e8b ``` bool side_effect() const exprtk_override ``` 4068375e ``` { return true; } private: vector_node* vec_node_ptr_; vds_t vds_; }; template ``` a65c8e8b ``` class assignment_vecvec_op_node exprtk_final : public binary_node , public vector_interface ``` 4068375e ``` { public: ``` a65c8e8b ``` typedef expression_node* expression_ptr; ``` 4068375e ``` typedef vector_node* vector_node_ptr; ``` a65c8e8b ``` typedef vec_data_store vds_t; ``` 4068375e ``` assignment_vecvec_op_node(const operator_type& opr, expression_ptr branch0, expression_ptr branch1) ``` a65c8e8b ``` : binary_node(opr, branch0, branch1) , vec0_node_ptr_(0) , vec1_node_ptr_(0) , initialised_(false) ``` 4068375e ``` { if (is_vector_node(binary_node::branch_[0].first)) { vec0_node_ptr_ = static_cast*>(binary_node::branch_[0].first); vds() = vec0_node_ptr_->vds(); } if (is_vector_node(binary_node::branch_[1].first)) { vec1_node_ptr_ = static_cast*>(binary_node::branch_[1].first); vec1_node_ptr_->vds() = vds(); } else if (is_ivector_node(binary_node::branch_[1].first)) { vector_interface* vi = reinterpret_cast*>(0); if (0 != (vi = dynamic_cast*>(binary_node::branch_[1].first))) { vec1_node_ptr_ = vi->vec(); vec1_node_ptr_->vds() = vds(); } else vds_t::match_sizes(vds(),vec1_node_ptr_->vds()); } initialised_ = (vec0_node_ptr_ && vec1_node_ptr_); ``` a65c8e8b ``` assert(initialised_); ``` 4068375e ``` } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { if (initialised_) { ``` a65c8e8b ``` assert(binary_node::branch_[0].first); assert(binary_node::branch_[1].first); ``` 4068375e ``` binary_node::branch_[0].first->value(); binary_node::branch_[1].first->value(); T* vec0 = vec0_node_ptr_->vds().data(); const T* vec1 = vec1_node_ptr_->vds().data(); loop_unroll::details lud(size()); const T* upper_bound = vec0 + lud.upper_bound; while (vec0 < upper_bound) { #define exprtk_loop(N) \ vec0[N] = Operation::process(vec0[N], vec1[N]); \ exprtk_loop( 0) exprtk_loop( 1) exprtk_loop( 2) exprtk_loop( 3) #ifndef exprtk_disable_superscalar_unroll exprtk_loop( 4) exprtk_loop( 5) exprtk_loop( 6) exprtk_loop( 7) exprtk_loop( 8) exprtk_loop( 9) exprtk_loop(10) exprtk_loop(11) exprtk_loop(12) exprtk_loop(13) exprtk_loop(14) exprtk_loop(15) #endif vec0 += lud.batch_size; vec1 += lud.batch_size; } int i = 0; exprtk_disable_fallthrough_begin switch (lud.remainder) { #define case_stmt(N) \ case N : { vec0[i] = Operation::process(vec0[i], vec1[i]); ++i; } \ #ifndef exprtk_disable_superscalar_unroll case_stmt(15) case_stmt(14) case_stmt(13) case_stmt(12) case_stmt(11) case_stmt(10) case_stmt( 9) case_stmt( 8) case_stmt( 7) case_stmt( 6) case_stmt( 5) case_stmt( 4) #endif case_stmt( 3) case_stmt( 2) case_stmt( 1) } exprtk_disable_fallthrough_end #undef exprtk_loop #undef case_stmt return vec0_node_ptr_->value(); } else return std::numeric_limits::quiet_NaN(); } ``` a65c8e8b ``` vector_node_ptr vec() const exprtk_override ``` 4068375e ``` { return vec0_node_ptr_; } ``` a65c8e8b ``` vector_node_ptr vec() exprtk_override ``` 4068375e ``` { return vec0_node_ptr_; } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_vecopvecass; } ``` a65c8e8b ``` std::size_t size() const exprtk_override ``` 4068375e ``` { return vds().size(); } ``` a65c8e8b ``` vds_t& vds() exprtk_override ``` 4068375e ``` { return vds_; } ``` a65c8e8b ``` const vds_t& vds() const exprtk_override ``` 4068375e ``` { return vds_; } ``` a65c8e8b ``` bool side_effect() const exprtk_override ``` 4068375e ``` { return true; } private: vector_node* vec0_node_ptr_; vector_node* vec1_node_ptr_; bool initialised_; vds_t vds_; }; template ``` a65c8e8b ``` class vec_binop_vecvec_node exprtk_final : public binary_node , public vector_interface ``` 4068375e ``` { public: ``` a65c8e8b ``` typedef expression_node* expression_ptr; typedef vector_node* vector_node_ptr; ``` 4068375e ``` typedef vector_holder* vector_holder_ptr; ``` a65c8e8b ``` typedef vec_data_store vds_t; ``` 4068375e ``` vec_binop_vecvec_node(const operator_type& opr, expression_ptr branch0, expression_ptr branch1) ``` a65c8e8b ``` : binary_node(opr, branch0, branch1) , vec0_node_ptr_(0) , vec1_node_ptr_(0) , temp_ (0) , temp_vec_node_(0) , initialised_(false) ``` 4068375e ``` { bool v0_is_ivec = false; bool v1_is_ivec = false; if (is_vector_node(binary_node::branch_[0].first)) { vec0_node_ptr_ = static_cast(binary_node::branch_[0].first); } else if (is_ivector_node(binary_node::branch_[0].first)) { vector_interface* vi = reinterpret_cast*>(0); if (0 != (vi = dynamic_cast*>(binary_node::branch_[0].first))) { vec0_node_ptr_ = vi->vec(); v0_is_ivec = true; } } if (is_vector_node(binary_node::branch_[1].first)) { vec1_node_ptr_ = static_cast(binary_node::branch_[1].first); } else if (is_ivector_node(binary_node::branch_[1].first)) { vector_interface* vi = reinterpret_cast*>(0); if (0 != (vi = dynamic_cast*>(binary_node::branch_[1].first))) { vec1_node_ptr_ = vi->vec(); v1_is_ivec = true; } } if (vec0_node_ptr_ && vec1_node_ptr_) { vector_holder& vec0 = vec0_node_ptr_->vec_holder(); vector_holder& vec1 = vec1_node_ptr_->vec_holder(); if (v0_is_ivec && (vec0.size() <= vec1.size())) vds_ = vds_t(vec0_node_ptr_->vds()); else if (v1_is_ivec && (vec1.size() <= vec0.size())) vds_ = vds_t(vec1_node_ptr_->vds()); else vds_ = vds_t(std::min(vec0.size(),vec1.size())); temp_ = new vector_holder(vds().data(),vds().size()); ``` a65c8e8b ``` temp_vec_node_ = new vector_node (vds(),temp_); ``` 4068375e ``` initialised_ = true; } ``` a65c8e8b ``` assert(initialised_); ``` 4068375e ``` } ~vec_binop_vecvec_node() { delete temp_; delete temp_vec_node_; } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { if (initialised_) { ``` a65c8e8b ``` assert(binary_node::branch_[0].first); assert(binary_node::branch_[1].first); ``` 4068375e ``` binary_node::branch_[0].first->value(); binary_node::branch_[1].first->value(); const T* vec0 = vec0_node_ptr_->vds().data(); const T* vec1 = vec1_node_ptr_->vds().data(); T* vec2 = vds().data(); loop_unroll::details lud(size()); const T* upper_bound = vec2 + lud.upper_bound; while (vec2 < upper_bound) { #define exprtk_loop(N) \ vec2[N] = Operation::process(vec0[N], vec1[N]); \ exprtk_loop( 0) exprtk_loop( 1) exprtk_loop( 2) exprtk_loop( 3) #ifndef exprtk_disable_superscalar_unroll exprtk_loop( 4) exprtk_loop( 5) exprtk_loop( 6) exprtk_loop( 7) exprtk_loop( 8) exprtk_loop( 9) exprtk_loop(10) exprtk_loop(11) exprtk_loop(12) exprtk_loop(13) exprtk_loop(14) exprtk_loop(15) #endif vec0 += lud.batch_size; vec1 += lud.batch_size; vec2 += lud.batch_size; } int i = 0; exprtk_disable_fallthrough_begin switch (lud.remainder) { #define case_stmt(N) \ case N : { vec2[i] = Operation::process(vec0[i], vec1[i]); ++i; } \ #ifndef exprtk_disable_superscalar_unroll case_stmt(15) case_stmt(14) case_stmt(13) case_stmt(12) case_stmt(11) case_stmt(10) case_stmt( 9) case_stmt( 8) case_stmt( 7) case_stmt( 6) case_stmt( 5) case_stmt( 4) #endif case_stmt( 3) case_stmt( 2) case_stmt( 1) } exprtk_disable_fallthrough_end #undef exprtk_loop #undef case_stmt return (vds().data())[0]; } else return std::numeric_limits::quiet_NaN(); } ``` a65c8e8b ``` vector_node_ptr vec() const exprtk_override ``` 4068375e ``` { return temp_vec_node_; } ``` a65c8e8b ``` vector_node_ptr vec() exprtk_override ``` 4068375e ``` { return temp_vec_node_; } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_vecvecarith; } ``` a65c8e8b ``` std::size_t size() const exprtk_override ``` 4068375e ``` { return vds_.size(); } ``` a65c8e8b ``` vds_t& vds() exprtk_override ``` 4068375e ``` { return vds_; } ``` a65c8e8b ``` const vds_t& vds() const exprtk_override ``` 4068375e ``` { return vds_; } private: vector_node_ptr vec0_node_ptr_; vector_node_ptr vec1_node_ptr_; vector_holder_ptr temp_; vector_node_ptr temp_vec_node_; bool initialised_; vds_t vds_; }; template ``` a65c8e8b ``` class vec_binop_vecval_node exprtk_final : public binary_node , public vector_interface ``` 4068375e ``` { public: ``` a65c8e8b ``` typedef expression_node* expression_ptr; typedef vector_node* vector_node_ptr; ``` 4068375e ``` typedef vector_holder* vector_holder_ptr; ``` a65c8e8b ``` typedef vec_data_store vds_t; ``` 4068375e ``` vec_binop_vecval_node(const operator_type& opr, expression_ptr branch0, expression_ptr branch1) ``` a65c8e8b ``` : binary_node(opr, branch0, branch1) , vec0_node_ptr_(0) , temp_ (0) , temp_vec_node_(0) ``` 4068375e ``` { bool v0_is_ivec = false; if (is_vector_node(binary_node::branch_[0].first)) { vec0_node_ptr_ = static_cast(binary_node::branch_[0].first); } else if (is_ivector_node(binary_node::branch_[0].first)) { vector_interface* vi = reinterpret_cast*>(0); if (0 != (vi = dynamic_cast*>(binary_node::branch_[0].first))) { vec0_node_ptr_ = vi->vec(); v0_is_ivec = true; } } if (vec0_node_ptr_) { if (v0_is_ivec) vds() = vec0_node_ptr_->vds(); else vds() = vds_t(vec0_node_ptr_->size()); temp_ = new vector_holder(vds()); ``` a65c8e8b ``` temp_vec_node_ = new vector_node (vds(),temp_); ``` 4068375e ``` } } ~vec_binop_vecval_node() { delete temp_; delete temp_vec_node_; } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { if (vec0_node_ptr_) { ``` a65c8e8b ``` assert(binary_node::branch_[0].first); assert(binary_node::branch_[1].first); ``` 4068375e ``` binary_node::branch_[0].first->value(); const T v = binary_node::branch_[1].first->value(); const T* vec0 = vec0_node_ptr_->vds().data(); T* vec1 = vds().data(); loop_unroll::details lud(size()); const T* upper_bound = vec0 + lud.upper_bound; while (vec0 < upper_bound) { #define exprtk_loop(N) \ vec1[N] = Operation::process(vec0[N], v); \ exprtk_loop( 0) exprtk_loop( 1) exprtk_loop( 2) exprtk_loop( 3) #ifndef exprtk_disable_superscalar_unroll exprtk_loop( 4) exprtk_loop( 5) exprtk_loop( 6) exprtk_loop( 7) exprtk_loop( 8) exprtk_loop( 9) exprtk_loop(10) exprtk_loop(11) exprtk_loop(12) exprtk_loop(13) exprtk_loop(14) exprtk_loop(15) #endif vec0 += lud.batch_size; vec1 += lud.batch_size; } int i = 0; exprtk_disable_fallthrough_begin switch (lud.remainder) { #define case_stmt(N) \ case N : { vec1[i] = Operation::process(vec0[i], v); ++i; } \ #ifndef exprtk_disable_superscalar_unroll case_stmt(15) case_stmt(14) case_stmt(13) case_stmt(12) case_stmt(11) case_stmt(10) case_stmt( 9) case_stmt( 8) case_stmt( 7) case_stmt( 6) case_stmt( 5) case_stmt( 4) #endif case_stmt( 3) case_stmt( 2) case_stmt( 1) } exprtk_disable_fallthrough_end #undef exprtk_loop #undef case_stmt return (vds().data())[0]; } else return std::numeric_limits::quiet_NaN(); } ``` a65c8e8b ``` vector_node_ptr vec() const exprtk_override ``` 4068375e ``` { return temp_vec_node_; } ``` a65c8e8b ``` vector_node_ptr vec() exprtk_override ``` 4068375e ``` { return temp_vec_node_; } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_vecvalarith; } ``` a65c8e8b ``` std::size_t size() const exprtk_override ``` 4068375e ``` { return vds().size(); } ``` a65c8e8b ``` vds_t& vds() exprtk_override ``` 4068375e ``` { return vds_; } ``` a65c8e8b ``` const vds_t& vds() const exprtk_override ``` 4068375e ``` { return vds_; } private: vector_node_ptr vec0_node_ptr_; vector_holder_ptr temp_; vector_node_ptr temp_vec_node_; vds_t vds_; }; template ``` a65c8e8b ``` class vec_binop_valvec_node exprtk_final : public binary_node , public vector_interface ``` 4068375e ``` { public: ``` a65c8e8b ``` typedef expression_node* expression_ptr; typedef vector_node* vector_node_ptr; ``` 4068375e ``` typedef vector_holder* vector_holder_ptr; ``` a65c8e8b ``` typedef vec_data_store vds_t; ``` 4068375e ``` vec_binop_valvec_node(const operator_type& opr, expression_ptr branch0, expression_ptr branch1) ``` a65c8e8b ``` : binary_node(opr, branch0, branch1) , vec1_node_ptr_(0) , temp_ (0) , temp_vec_node_(0) ``` 4068375e ``` { bool v1_is_ivec = false; if (is_vector_node(binary_node::branch_[1].first)) { vec1_node_ptr_ = static_cast(binary_node::branch_[1].first); } else if (is_ivector_node(binary_node::branch_[1].first)) { vector_interface* vi = reinterpret_cast*>(0); if (0 != (vi = dynamic_cast*>(binary_node::branch_[1].first))) { vec1_node_ptr_ = vi->vec(); v1_is_ivec = true; } } if (vec1_node_ptr_) { if (v1_is_ivec) vds() = vec1_node_ptr_->vds(); else vds() = vds_t(vec1_node_ptr_->size()); temp_ = new vector_holder(vds()); ``` a65c8e8b ``` temp_vec_node_ = new vector_node (vds(),temp_); ``` 4068375e ``` } } ~vec_binop_valvec_node() { delete temp_; delete temp_vec_node_; } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { if (vec1_node_ptr_) { ``` a65c8e8b ``` assert(binary_node::branch_[0].first); assert(binary_node::branch_[1].first); ``` 4068375e ``` const T v = binary_node::branch_[0].first->value(); binary_node::branch_[1].first->value(); T* vec0 = vds().data(); const T* vec1 = vec1_node_ptr_->vds().data(); loop_unroll::details lud(size()); const T* upper_bound = vec0 + lud.upper_bound; while (vec0 < upper_bound) { #define exprtk_loop(N) \ vec0[N] = Operation::process(v, vec1[N]); \ exprtk_loop( 0) exprtk_loop( 1) exprtk_loop( 2) exprtk_loop( 3) #ifndef exprtk_disable_superscalar_unroll exprtk_loop( 4) exprtk_loop( 5) exprtk_loop( 6) exprtk_loop( 7) exprtk_loop( 8) exprtk_loop( 9) exprtk_loop(10) exprtk_loop(11) exprtk_loop(12) exprtk_loop(13) exprtk_loop(14) exprtk_loop(15) #endif vec0 += lud.batch_size; vec1 += lud.batch_size; } int i = 0; exprtk_disable_fallthrough_begin switch (lud.remainder) { #define case_stmt(N) \ case N : { vec0[i] = Operation::process(v, vec1[i]); ++i; } \ #ifndef exprtk_disable_superscalar_unroll case_stmt(15) case_stmt(14) case_stmt(13) case_stmt(12) case_stmt(11) case_stmt(10) case_stmt( 9) case_stmt( 8) case_stmt( 7) case_stmt( 6) case_stmt( 5) case_stmt( 4) #endif case_stmt( 3) case_stmt( 2) case_stmt( 1) } exprtk_disable_fallthrough_end #undef exprtk_loop #undef case_stmt return (vds().data())[0]; } else return std::numeric_limits::quiet_NaN(); } ``` a65c8e8b ``` vector_node_ptr vec() const exprtk_override ``` 4068375e ``` { return temp_vec_node_; } ``` a65c8e8b ``` vector_node_ptr vec() exprtk_override ``` 4068375e ``` { return temp_vec_node_; } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_vecvalarith; } ``` a65c8e8b ``` std::size_t size() const exprtk_override ``` 4068375e ``` { return vds().size(); } ``` a65c8e8b ``` vds_t& vds() exprtk_override ``` 4068375e ``` { return vds_; } ``` a65c8e8b ``` const vds_t& vds() const exprtk_override ``` 4068375e ``` { return vds_; } private: vector_node_ptr vec1_node_ptr_; vector_holder_ptr temp_; vector_node_ptr temp_vec_node_; vds_t vds_; }; template ``` a65c8e8b ``` class unary_vector_node exprtk_final : public unary_node , public vector_interface ``` 4068375e ``` { public: ``` a65c8e8b ``` typedef expression_node* expression_ptr; typedef vector_node* vector_node_ptr; ``` 4068375e ``` typedef vector_holder* vector_holder_ptr; ``` a65c8e8b ``` typedef vec_data_store vds_t; ``` 4068375e ``` unary_vector_node(const operator_type& opr, expression_ptr branch0) ``` a65c8e8b ``` : unary_node(opr, branch0) , vec0_node_ptr_(0) , temp_ (0) , temp_vec_node_(0) ``` 4068375e ``` { bool vec0_is_ivec = false; if (is_vector_node(unary_node::branch_.first)) { vec0_node_ptr_ = static_cast(unary_node::branch_.first); } else if (is_ivector_node(unary_node::branch_.first)) { vector_interface* vi = reinterpret_cast*>(0); if (0 != (vi = dynamic_cast*>(unary_node::branch_.first))) { vec0_node_ptr_ = vi->vec(); vec0_is_ivec = true; } } if (vec0_node_ptr_) { if (vec0_is_ivec) vds_ = vec0_node_ptr_->vds(); else vds_ = vds_t(vec0_node_ptr_->size()); temp_ = new vector_holder(vds()); ``` a65c8e8b ``` temp_vec_node_ = new vector_node (vds(),temp_); ``` 4068375e ``` } } ~unary_vector_node() { delete temp_; delete temp_vec_node_; } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { ``` a65c8e8b ``` assert(unary_node::branch_.first); ``` 4068375e ``` unary_node::branch_.first->value(); if (vec0_node_ptr_) { const T* vec0 = vec0_node_ptr_->vds().data(); T* vec1 = vds().data(); loop_unroll::details lud(size()); const T* upper_bound = vec0 + lud.upper_bound; while (vec0 < upper_bound) { #define exprtk_loop(N) \ vec1[N] = Operation::process(vec0[N]); \ exprtk_loop( 0) exprtk_loop( 1) exprtk_loop( 2) exprtk_loop( 3) #ifndef exprtk_disable_superscalar_unroll exprtk_loop( 4) exprtk_loop( 5) exprtk_loop( 6) exprtk_loop( 7) exprtk_loop( 8) exprtk_loop( 9) exprtk_loop(10) exprtk_loop(11) exprtk_loop(12) exprtk_loop(13) exprtk_loop(14) exprtk_loop(15) #endif vec0 += lud.batch_size; vec1 += lud.batch_size; } int i = 0; exprtk_disable_fallthrough_begin switch (lud.remainder) { #define case_stmt(N) \ case N : { vec1[i] = Operation::process(vec0[i]); ++i; } \ #ifndef exprtk_disable_superscalar_unroll case_stmt(15) case_stmt(14) case_stmt(13) case_stmt(12) case_stmt(11) case_stmt(10) case_stmt( 9) case_stmt( 8) case_stmt( 7) case_stmt( 6) case_stmt( 5) case_stmt( 4) #endif case_stmt( 3) case_stmt( 2) case_stmt( 1) } exprtk_disable_fallthrough_end #undef exprtk_loop #undef case_stmt return (vds().data())[0]; } else return std::numeric_limits::quiet_NaN(); } ``` a65c8e8b ``` vector_node_ptr vec() const exprtk_override ``` 4068375e ``` { return temp_vec_node_; } ``` a65c8e8b ``` vector_node_ptr vec() exprtk_override ``` 4068375e ``` { return temp_vec_node_; } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_vecunaryop; } ``` a65c8e8b ``` std::size_t size() const exprtk_override ``` 4068375e ``` { return vds().size(); } ``` a65c8e8b ``` vds_t& vds() exprtk_override ``` 4068375e ``` { return vds_; } ``` a65c8e8b ``` const vds_t& vds() const exprtk_override ``` 4068375e ``` { return vds_; } private: vector_node_ptr vec0_node_ptr_; vector_holder_ptr temp_; vector_node_ptr temp_vec_node_; vds_t vds_; }; template ``` a65c8e8b ``` class conditional_vector_node exprtk_final : public expression_node , public vector_interface { public: typedef expression_node * expression_ptr; typedef vector_interface* vec_interface_ptr; typedef vector_node * vector_node_ptr; typedef vector_holder * vector_holder_ptr; typedef vec_data_store vds_t; typedef std::pair branch_t; conditional_vector_node(expression_ptr condition, expression_ptr consequent, expression_ptr alternative) : consequent_node_ptr_ (0) , alternative_node_ptr_(0) , temp_vec_node_ (0) , temp_ (0) , vec_size_ (0) , initialised_ (false) { construct_branch_pair(condition_ , condition ); construct_branch_pair(consequent_ , consequent ); construct_branch_pair(alternative_, alternative); if (details::is_ivector_node(consequent_.first)) { vec_interface_ptr ivec_ptr = dynamic_cast(consequent_.first); if (0 != ivec_ptr) { consequent_node_ptr_ = ivec_ptr->vec(); } } if (details::is_ivector_node(alternative_.first)) { vec_interface_ptr ivec_ptr = dynamic_cast(alternative_.first); if (0 != ivec_ptr) { alternative_node_ptr_ = ivec_ptr->vec(); } } if (consequent_node_ptr_ && alternative_node_ptr_) { vec_size_ = std::min(consequent_node_ptr_ ->vds().size(), alternative_node_ptr_->vds().size()); vds_ = vds_t(vec_size_); temp_ = new vector_holder(vds_); temp_vec_node_ = new vector_node (vds(),temp_); initialised_ = true; } assert(initialised_ && (vec_size_ > 0)); } ~conditional_vector_node() { delete temp_; delete temp_vec_node_; } inline T value() const exprtk_override { if (initialised_) { assert(condition_ .first); assert(consequent_ .first); assert(alternative_.first); T result = T(0); T* source_vector = 0; T* result_vector = vds().data(); if (is_true(condition_)) { result = consequent_.first->value(); source_vector = consequent_node_ptr_->vds().data(); } else { result = alternative_.first->value(); source_vector = alternative_node_ptr_->vds().data(); } for (std::size_t i = 0; i < vec_size_; ++i) { result_vector[i] = source_vector[i]; } return result; } return std::numeric_limits::quiet_NaN(); } vector_node_ptr vec() const exprtk_override { return temp_vec_node_; } vector_node_ptr vec() exprtk_override { return temp_vec_node_; } inline typename expression_node::node_type type() const exprtk_override { return expression_node::e_vecondition; } std::size_t size() const exprtk_override { return vec_size_; } vds_t& vds() exprtk_override { return vds_; } const vds_t& vds() const exprtk_override { return vds_; } void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override { expression_node::ndb_t::collect(condition_ , node_delete_list); expression_node::ndb_t::collect(consequent_ , node_delete_list); expression_node::ndb_t::collect(alternative_ , node_delete_list); } std::size_t node_depth() const exprtk_override { return expression_node::ndb_t::compute_node_depth (condition_, consequent_, alternative_); } private: branch_t condition_; branch_t consequent_; branch_t alternative_; vector_node_ptr consequent_node_ptr_; vector_node_ptr alternative_node_ptr_; vector_node_ptr temp_vec_node_; vector_holder_ptr temp_; vds_t vds_; std::size_t vec_size_; bool initialised_; }; template class scand_node exprtk_final : public binary_node ``` 4068375e ``` { public: typedef expression_node* expression_ptr; scand_node(const operator_type& opr, expression_ptr branch0, expression_ptr branch1) : binary_node(opr, branch0, branch1) {} ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { ``` a65c8e8b ``` assert(binary_node::branch_[0].first); assert(binary_node::branch_[1].first); ``` 4068375e ``` return ( std::not_equal_to() (T(0),binary_node::branch_[0].first->value()) && std::not_equal_to() (T(0),binary_node::branch_[1].first->value()) ) ? T(1) : T(0); } }; template ``` a65c8e8b ``` class scor_node exprtk_final : public binary_node ``` 4068375e ``` { public: typedef expression_node* expression_ptr; scor_node(const operator_type& opr, expression_ptr branch0, expression_ptr branch1) : binary_node(opr, branch0, branch1) {} ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { ``` a65c8e8b ``` assert(binary_node::branch_[0].first); assert(binary_node::branch_[1].first); ``` 4068375e ``` return ( std::not_equal_to() (T(0),binary_node::branch_[0].first->value()) || std::not_equal_to() (T(0),binary_node::branch_[1].first->value()) ) ? T(1) : T(0); } }; template ``` a65c8e8b ``` class function_N_node exprtk_final : public expression_node ``` 4068375e ``` { public: // Function of N paramters. typedef expression_node* expression_ptr; typedef std::pair branch_t; typedef IFunction ifunction; explicit function_N_node(ifunction* func) ``` a65c8e8b ``` : function_((N == func->param_count) ? func : reinterpret_cast(0)) , parameter_count_(func->param_count) ``` 4068375e ``` {} template bool init_branches(expression_ptr (&b)[NumBranches]) { // Needed for incompetent and broken msvc compiler versions #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4127) #endif if (N != NumBranches) return false; else { for (std::size_t i = 0; i < NumBranches; ++i) { if (b[i]) branch_[i] = std::make_pair(b[i],branch_deletable(b[i])); else return false; } return true; } #ifdef _MSC_VER #pragma warning(pop) #endif } inline bool operator <(const function_N_node& fn) const { return this < (&fn); } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { // Needed for incompetent and broken msvc compiler versions #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4127) #endif if ((0 == function_) || (0 == N)) return std::numeric_limits::quiet_NaN(); else { T v[N]; evaluate_branches::execute(v,branch_); return invoke::execute(*function_,v); } #ifdef _MSC_VER #pragma warning(pop) #endif } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override { return expression_node::e_function; } void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override { expression_node::ndb_t::template collect(branch_, node_delete_list); } std::size_t node_depth() const exprtk_override { return expression_node::ndb_t::template compute_node_depth(branch_); } ``` 4068375e ``` template struct evaluate_branches { static inline void execute(T_ (&v)[BranchCount], const branch_t (&b)[BranchCount]) { for (std::size_t i = 0; i < BranchCount; ++i) { v[i] = b[i].first->value(); } } }; template struct evaluate_branches { static inline void execute(T_ (&v)[5], const branch_t (&b)[5]) { v[0] = b[0].first->value(); v[1] = b[1].first->value(); v[2] = b[2].first->value(); v[3] = b[3].first->value(); v[4] = b[4].first->value(); } }; template struct evaluate_branches { static inline void execute(T_ (&v)[4], const branch_t (&b)[4]) { v[0] = b[0].first->value(); v[1] = b[1].first->value(); v[2] = b[2].first->value(); v[3] = b[3].first->value(); } }; template struct evaluate_branches { static inline void execute(T_ (&v)[3], const branch_t (&b)[3]) { v[0] = b[0].first->value(); v[1] = b[1].first->value(); v[2] = b[2].first->value(); } }; template struct evaluate_branches { static inline void execute(T_ (&v)[2], const branch_t (&b)[2]) { v[0] = b[0].first->value(); v[1] = b[1].first->value(); } }; template struct evaluate_branches { static inline void execute(T_ (&v)[1], const branch_t (&b)[1]) { v[0] = b[0].first->value(); } }; template struct invoke { static inline T execute(ifunction&, branch_t (&)[ParamCount]) { return std::numeric_limits::quiet_NaN(); } }; template struct invoke { static inline T_ execute(ifunction& f, T_ (&v)[20]) { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15],v[16],v[17],v[18],v[19]); } }; template struct invoke { static inline T_ execute(ifunction& f, T_ (&v)[19]) { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15],v[16],v[17],v[18]); } }; template struct invoke { static inline T_ execute(ifunction& f, T_ (&v)[18]) ``` a65c8e8b ``` { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9], v[10], v[11], v[12], v[13], v[14], v[15], v[16], v[17]); } ``` 4068375e ``` }; template struct invoke { static inline T_ execute(ifunction& f, T_ (&v)[17]) ``` a65c8e8b ``` { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9], v[10], v[11], v[12], v[13], v[14], v[15], v[16]); } ``` 4068375e ``` }; template struct invoke { static inline T_ execute(ifunction& f, T_ (&v)[16]) ``` a65c8e8b ``` { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9], v[10], v[11], v[12], v[13], v[14], v[15]); } ``` 4068375e ``` }; template struct invoke { static inline T_ execute(ifunction& f, T_ (&v)[15]) ``` a65c8e8b ``` { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9], v[10], v[11], v[12], v[13], v[14]); } ``` 4068375e ``` }; template struct invoke { static inline T_ execute(ifunction& f, T_ (&v)[14]) ``` a65c8e8b ``` { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9], v[10], v[11], v[12], v[13]); } ``` 4068375e ``` }; template struct invoke { static inline T_ execute(ifunction& f, T_ (&v)[13]) ``` a65c8e8b ``` { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9], v[10], v[11], v[12]); } ``` 4068375e ``` }; template struct invoke { static inline T_ execute(ifunction& f, T_ (&v)[12]) ``` a65c8e8b ``` { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9], v[10], v[11]); } ``` 4068375e ``` }; template struct invoke { static inline T_ execute(ifunction& f, T_ (&v)[11]) ``` a65c8e8b ``` { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9], v[10]); } ``` 4068375e ``` }; template struct invoke { static inline T_ execute(ifunction& f, T_ (&v)[10]) ``` a65c8e8b ``` { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9]); } ``` 4068375e ``` }; template struct invoke { static inline T_ execute(ifunction& f, T_ (&v)[9]) ``` a65c8e8b ``` { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8]); } ``` 4068375e ``` }; template struct invoke { static inline T_ execute(ifunction& f, T_ (&v)[8]) ``` a65c8e8b ``` { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]); } ``` 4068375e ``` }; template struct invoke { static inline T_ execute(ifunction& f, T_ (&v)[7]) ``` a65c8e8b ``` { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6]); } ``` 4068375e ``` }; template struct invoke { static inline T_ execute(ifunction& f, T_ (&v)[6]) ``` a65c8e8b ``` { return f(v[0], v[1], v[2], v[3], v[4], v[5]); } ``` 4068375e ``` }; template struct invoke { static inline T_ execute(ifunction& f, T_ (&v)[5]) ``` a65c8e8b ``` { return f(v[0], v[1], v[2], v[3], v[4]); } ``` 4068375e ``` }; template struct invoke { static inline T_ execute(ifunction& f, T_ (&v)[4]) ``` a65c8e8b ``` { return f(v[0], v[1], v[2], v[3]); } ``` 4068375e ``` }; template struct invoke { static inline T_ execute(ifunction& f, T_ (&v)[3]) ``` a65c8e8b ``` { return f(v[0], v[1], v[2]); } ``` 4068375e ``` }; template struct invoke { static inline T_ execute(ifunction& f, T_ (&v)[2]) ``` a65c8e8b ``` { return f(v[0], v[1]); } ``` 4068375e ``` }; template struct invoke { static inline T_ execute(ifunction& f, T_ (&v)[1]) { return f(v[0]); } }; private: ifunction* function_; std::size_t parameter_count_; branch_t branch_[N]; }; template ``` a65c8e8b ``` class function_N_node exprtk_final : public expression_node ``` 4068375e ``` { public: typedef expression_node* expression_ptr; typedef IFunction ifunction; explicit function_N_node(ifunction* func) : function_((0 == func->param_count) ? func : reinterpret_cast(0)) {} inline bool operator <(const function_N_node& fn) const { return this < (&fn); } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { if (function_) return (*function_)(); else return std::numeric_limits::quiet_NaN(); } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_function; } private: ifunction* function_; }; template ``` a65c8e8b ``` class vararg_function_node exprtk_final : public expression_node ``` 4068375e ``` { public: typedef expression_node* expression_ptr; vararg_function_node(VarArgFunction* func, const std::vector& arg_list) ``` a65c8e8b ``` : function_(func) , arg_list_(arg_list) ``` 4068375e ``` { value_list_.resize(arg_list.size(),std::numeric_limits::quiet_NaN()); } inline bool operator <(const vararg_function_node& fn) const { return this < (&fn); } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { if (function_) { populate_value_list(); return (*function_)(value_list_); } else return std::numeric_limits::quiet_NaN(); } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_vafunction; } ``` a65c8e8b ``` void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override ``` 4068375e ``` { for (std::size_t i = 0; i < arg_list_.size(); ++i) { if (arg_list_[i] && !details::is_variable_node(arg_list_[i])) { node_delete_list.push_back(&arg_list_[i]); } } } ``` a65c8e8b ``` std::size_t node_depth() const exprtk_override ``` 4068375e ``` { return expression_node::ndb_t::compute_node_depth(arg_list_); } private: inline void populate_value_list() const { for (std::size_t i = 0; i < arg_list_.size(); ++i) { value_list_[i] = arg_list_[i]->value(); } } VarArgFunction* function_; std::vector arg_list_; mutable std::vector value_list_; }; template class generic_function_node : public expression_node { public: ``` a65c8e8b ``` typedef type_store type_store_t; typedef expression_node* expression_ptr; typedef variable_node variable_node_t; typedef vector_node vector_node_t; typedef variable_node_t* variable_node_ptr_t; typedef vector_node_t* vector_node_ptr_t; typedef range_interface range_interface_t; typedef range_data_type range_data_type_t; typedef typename range_interface::range_t range_t; typedef std::pair branch_t; typedef std::pair void_t; typedef std::vector tmp_vs_t; typedef std::vector typestore_list_t; typedef std::vector range_list_t; ``` 4068375e ``` explicit generic_function_node(const std::vector& arg_list, ``` a65c8e8b ``` GenericFunction* func = reinterpret_cast(0)) : function_(func) , arg_list_(arg_list) ``` 4068375e ``` {} ``` a65c8e8b ``` virtual ~generic_function_node() {} ``` 4068375e ``` ``` a65c8e8b ``` void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override ``` 4068375e ``` { expression_node::ndb_t::collect(branch_, node_delete_list); } ``` a65c8e8b ``` std::size_t node_depth() const exprtk_override exprtk_final ``` 4068375e ``` { return expression_node::ndb_t::compute_node_depth(branch_); } virtual bool init_branches() { expr_as_vec1_store_.resize(arg_list_.size(),T(0) ); typestore_list_ .resize(arg_list_.size(),type_store_t() ); range_list_ .resize(arg_list_.size(),range_data_type_t()); ``` a65c8e8b ``` branch_ .resize(arg_list_.size(),branch_t(reinterpret_cast(0),false)); ``` 4068375e ``` for (std::size_t i = 0; i < arg_list_.size(); ++i) { type_store_t& ts = typestore_list_[i]; if (0 == arg_list_[i]) return false; else if (is_ivector_node(arg_list_[i])) { vector_interface* vi = reinterpret_cast*>(0); if (0 == (vi = dynamic_cast*>(arg_list_[i]))) return false; ts.size = vi->size(); ts.data = vi->vds().data(); ts.type = type_store_t::e_vector; vi->vec()->vec_holder().set_ref(&ts.vec_data); } #ifndef exprtk_disable_string_capabilities else if (is_generally_string_node(arg_list_[i])) { string_base_node* sbn = reinterpret_cast*>(0); if (0 == (sbn = dynamic_cast*>(arg_list_[i]))) return false; ts.size = sbn->size(); ts.data = reinterpret_cast(const_cast(sbn->base())); ts.type = type_store_t::e_string; range_list_[i].data = ts.data; range_list_[i].size = ts.size; range_list_[i].type_size = sizeof(char); range_list_[i].str_node = sbn; range_interface_t* ri = reinterpret_cast(0); if (0 == (ri = dynamic_cast(arg_list_[i]))) return false; ``` a65c8e8b ``` const range_t& rp = ri->range_ref(); ``` 4068375e ``` if ( rp.const_range() && is_const_string_range_node(arg_list_[i]) ) { ts.size = rp.const_size(); ts.data = static_cast(ts.data) + rp.n0_c.second; range_list_[i].range = reinterpret_cast(0); } else range_list_[i].range = &(ri->range_ref()); } #endif else if (is_variable_node(arg_list_[i])) { variable_node_ptr_t var = variable_node_ptr_t(0); if (0 == (var = dynamic_cast(arg_list_[i]))) return false; ts.size = 1; ts.data = &var->ref(); ts.type = type_store_t::e_scalar; } else { ts.size = 1; ts.data = reinterpret_cast(&expr_as_vec1_store_[i]); ts.type = type_store_t::e_scalar; } branch_[i] = std::make_pair(arg_list_[i],branch_deletable(arg_list_[i])); } return true; } inline bool operator <(const generic_function_node& fn) const { return this < (&fn); } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { if (function_) { if (populate_value_list()) { typedef typename GenericFunction::parameter_list_t parameter_list_t; return (*function_)(parameter_list_t(typestore_list_)); } } return std::numeric_limits::quiet_NaN(); } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_genfunction; } protected: inline virtual bool populate_value_list() const { for (std::size_t i = 0; i < branch_.size(); ++i) { expr_as_vec1_store_[i] = branch_[i].first->value(); } for (std::size_t i = 0; i < branch_.size(); ++i) { range_data_type_t& rdt = range_list_[i]; if (rdt.range) { ``` a65c8e8b ``` const range_t& rp = (*rdt.range); std::size_t r0 = 0; std::size_t r1 = 0; ``` 4068375e ``` ``` a65c8e8b ``` if (rp(r0, r1, rdt.size)) ``` 4068375e ``` { type_store_t& ts = typestore_list_[i]; ts.size = rp.cache_size(); #ifndef exprtk_disable_string_capabilities if (ts.type == type_store_t::e_string) ts.data = const_cast(rdt.str_node->base()) + rp.cache.first; else #endif ts.data = static_cast(rdt.data) + (rp.cache.first * rdt.type_size); } else return false; } } return true; } GenericFunction* function_; mutable typestore_list_t typestore_list_; private: std::vector arg_list_; std::vector branch_; mutable tmp_vs_t expr_as_vec1_store_; mutable range_list_t range_list_; }; #ifndef exprtk_disable_string_capabilities template class string_function_node : public generic_function_node, public string_base_node, public range_interface { public: typedef generic_function_node gen_function_t; ``` a65c8e8b ``` typedef typename range_interface::range_t range_t; ``` 4068375e ``` string_function_node(StringFunction* func, const std::vector& arg_list) : gen_function_t(arg_list,func) { range_.n0_c = std::make_pair(true,0); range_.n1_c = std::make_pair(true,0); range_.cache.first = range_.n0_c.second; range_.cache.second = range_.n1_c.second; } inline bool operator <(const string_function_node& fn) const { return this < (&fn); } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { if (gen_function_t::function_) { if (gen_function_t::populate_value_list()) { typedef typename StringFunction::parameter_list_t parameter_list_t; const T result = (*gen_function_t::function_) ( ret_string_, parameter_list_t(gen_function_t::typestore_list_) ); range_.n1_c.second = ret_string_.size() - 1; range_.cache.second = range_.n1_c.second; return result; } } return std::numeric_limits::quiet_NaN(); } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_strfunction; } ``` a65c8e8b ``` std::string str() const exprtk_override ``` 4068375e ``` { return ret_string_; } ``` a65c8e8b ``` char_cptr base() const exprtk_override ``` 4068375e ``` { return &ret_string_[0]; } ``` a65c8e8b ``` std::size_t size() const exprtk_override ``` 4068375e ``` { return ret_string_.size(); } ``` a65c8e8b ``` range_t& range_ref() exprtk_override ``` 4068375e ``` { return range_; } ``` a65c8e8b ``` const range_t& range_ref() const exprtk_override ``` 4068375e ``` { return range_; } protected: mutable range_t range_; mutable std::string ret_string_; }; #endif template class multimode_genfunction_node : public generic_function_node { public: typedef generic_function_node gen_function_t; ``` a65c8e8b ``` typedef typename gen_function_t::range_t range_t; ``` 4068375e ``` multimode_genfunction_node(GenericFunction* func, const std::size_t& param_seq_index, const std::vector& arg_list) ``` a65c8e8b ``` : gen_function_t(arg_list,func) , param_seq_index_(param_seq_index) ``` 4068375e ``` {} ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { if (gen_function_t::function_) { if (gen_function_t::populate_value_list()) { typedef typename GenericFunction::parameter_list_t parameter_list_t; return (*gen_function_t::function_) ( param_seq_index_, parameter_list_t(gen_function_t::typestore_list_) ); } } return std::numeric_limits::quiet_NaN(); } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override exprtk_final ``` 4068375e ``` { return expression_node::e_genfunction; } private: std::size_t param_seq_index_; }; #ifndef exprtk_disable_string_capabilities template ``` a65c8e8b ``` class multimode_strfunction_node exprtk_final : public string_function_node ``` 4068375e ``` { public: typedef string_function_node str_function_t; ``` a65c8e8b ``` typedef typename str_function_t::range_t range_t; ``` 4068375e ``` multimode_strfunction_node(StringFunction* func, const std::size_t& param_seq_index, const std::vector& arg_list) ``` a65c8e8b ``` : str_function_t(func,arg_list) , param_seq_index_(param_seq_index) ``` 4068375e ``` {} ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { if (str_function_t::function_) { if (str_function_t::populate_value_list()) { typedef typename StringFunction::parameter_list_t parameter_list_t; const T result = (*str_function_t::function_) ( param_seq_index_, str_function_t::ret_string_, parameter_list_t(str_function_t::typestore_list_) ); str_function_t::range_.n1_c.second = str_function_t::ret_string_.size() - 1; str_function_t::range_.cache.second = str_function_t::range_.n1_c.second; return result; } } return std::numeric_limits::quiet_NaN(); } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_strfunction; } private: const std::size_t param_seq_index_; }; #endif class return_exception {}; template class null_igenfunc { public: ``` a65c8e8b ``` virtual ~null_igenfunc() {} ``` 4068375e ``` typedef type_store generic_type; typedef typename generic_type::parameter_list parameter_list_t; inline virtual T operator() (parameter_list_t) { return std::numeric_limits::quiet_NaN(); } }; #ifndef exprtk_disable_return_statement template ``` a65c8e8b ``` class return_node exprtk_final : public generic_function_node > ``` 4068375e ``` { public: ``` a65c8e8b ``` typedef results_context results_context_t; typedef null_igenfunc igeneric_function_t; ``` 4068375e ``` typedef igeneric_function_t* igeneric_function_ptr; typedef generic_function_node gen_function_t; return_node(const std::vector& arg_list, results_context_t& rc) ``` a65c8e8b ``` : gen_function_t (arg_list) , results_context_(&rc) ``` 4068375e ``` {} ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { if ( (0 != results_context_) && gen_function_t::populate_value_list() ) { typedef typename type_store::parameter_list parameter_list_t; results_context_-> assign(parameter_list_t(gen_function_t::typestore_list_)); throw return_exception(); } return std::numeric_limits::quiet_NaN(); } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_return; } private: results_context_t* results_context_; }; template ``` a65c8e8b ``` class return_envelope_node exprtk_final : public expression_node ``` 4068375e ``` { public: typedef expression_node* expression_ptr; typedef results_context results_context_t; typedef std::pair branch_t; return_envelope_node(expression_ptr body, results_context_t& rc) ``` a65c8e8b ``` : results_context_(&rc ) , return_invoked_ (false) ``` 4068375e ``` { construct_branch_pair(body_, body); } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { ``` a65c8e8b ``` assert(body_.first); ``` 4068375e ``` try { return_invoked_ = false; results_context_->clear(); return body_.first->value(); } catch(const return_exception&) { return_invoked_ = true; return std::numeric_limits::quiet_NaN(); } } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_retenv; } inline bool* retinvk_ptr() { return &return_invoked_; } ``` a65c8e8b ``` void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override ``` 4068375e ``` { expression_node::ndb_t::collect(body_, node_delete_list); } ``` a65c8e8b ``` std::size_t node_depth() const exprtk_override ``` 4068375e ``` { return expression_node::ndb_t::compute_node_depth(body_); } private: results_context_t* results_context_; mutable bool return_invoked_; branch_t body_; }; #endif #define exprtk_define_unary_op(OpName) \ template \ struct OpName##_op \ { \ typedef typename functor_t::Type Type; \ typedef typename expression_node::node_type node_t; \ \ static inline T process(Type v) \ { \ return numeric:: OpName (v); \ } \ \ static inline node_t type() \ { \ return expression_node::e_##OpName; \ } \ \ static inline details::operator_type operation() \ { \ return details::e_##OpName; \ } \ }; \ exprtk_define_unary_op(abs ) exprtk_define_unary_op(acos ) exprtk_define_unary_op(acosh) exprtk_define_unary_op(asin ) exprtk_define_unary_op(asinh) exprtk_define_unary_op(atan ) exprtk_define_unary_op(atanh) exprtk_define_unary_op(ceil ) exprtk_define_unary_op(cos ) exprtk_define_unary_op(cosh ) exprtk_define_unary_op(cot ) exprtk_define_unary_op(csc ) exprtk_define_unary_op(d2g ) exprtk_define_unary_op(d2r ) exprtk_define_unary_op(erf ) exprtk_define_unary_op(erfc ) exprtk_define_unary_op(exp ) exprtk_define_unary_op(expm1) exprtk_define_unary_op(floor) exprtk_define_unary_op(frac ) exprtk_define_unary_op(g2d ) exprtk_define_unary_op(log ) exprtk_define_unary_op(log10) exprtk_define_unary_op(log2 ) exprtk_define_unary_op(log1p) exprtk_define_unary_op(ncdf ) exprtk_define_unary_op(neg ) exprtk_define_unary_op(notl ) exprtk_define_unary_op(pos ) exprtk_define_unary_op(r2d ) exprtk_define_unary_op(round) exprtk_define_unary_op(sec ) exprtk_define_unary_op(sgn ) exprtk_define_unary_op(sin ) exprtk_define_unary_op(sinc ) exprtk_define_unary_op(sinh ) exprtk_define_unary_op(sqrt ) exprtk_define_unary_op(tan ) exprtk_define_unary_op(tanh ) exprtk_define_unary_op(trunc) #undef exprtk_define_unary_op template struct opr_base { typedef typename details::functor_t::Type Type; typedef typename details::functor_t::RefType RefType; ``` a65c8e8b ``` 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; ``` 4068375e ``` }; template struct add_op : public opr_base { typedef typename opr_base::Type Type; typedef typename opr_base::RefType RefType; 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 void assign(RefType t1, Type t2) { t1 += t2; } 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 : public opr_base { typedef typename opr_base::Type Type; typedef typename opr_base::RefType RefType; 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 void assign(RefType t1, Type t2) { t1 *= t2; } 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 : public opr_base { typedef typename opr_base::Type Type; typedef typename opr_base::RefType RefType; 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 void assign(RefType t1, Type t2) { t1 -= t2; } 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 : public opr_base { typedef typename opr_base::Type Type; typedef typename opr_base::RefType RefType; 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 void assign(RefType t1, Type t2) { t1 /= t2; } 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 : public opr_base { typedef typename opr_base::Type Type; typedef typename opr_base::RefType RefType; static inline T process(Type t1, Type t2) { return numeric::modulus(t1,t2); } static inline void assign(RefType t1, Type t2) { t1 = 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 : public opr_base { typedef typename opr_base::Type Type; typedef typename opr_base::RefType RefType; static inline T process(Type t1, Type t2) { return numeric::pow(t1,t2); } static inline void assign(RefType t1, Type t2) { t1 = 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 : public opr_base { 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 : public opr_base { 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 : public opr_base { 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 : public opr_base { 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 : public opr_base { typedef typename opr_base::Type Type; static inline T process(Type t1, Type t2) { return (std::equal_to()(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 equal_op : public opr_base { typedef typename opr_base::Type Type; static inline T process(Type t1, Type t2) { return numeric::equal(t1,t2); } 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_equal; } }; template struct ne_op : public opr_base { typedef typename opr_base::Type Type; static inline T process(Type t1, Type t2) { return (std::not_equal_to()(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 : public opr_base { 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 : public opr_base { 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 : public opr_base { 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 : public opr_base { 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 : public opr_base { 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 xnor_op : public opr_base { typedef typename opr_base::Type Type; static inline T process(Type t1, Type t2) { return numeric::xnor_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_xnor; } }; template 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; } static inline details::operator_type operation() { return details::e_in; } }; template 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; } static inline details::operator_type operation() { return details::e_like; } }; template 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; } static inline details::operator_type operation() { return details::e_ilike; } }; template 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_inrange; } }; template inline T value(details::expression_node* n) { return n->value(); } template inline T value(std::pair*,bool> n) { return n.first->value(); } template inline T value(const T* t) { return (*t); } template inline T value(const T& t) { return t; } template struct vararg_add_op : public opr_base { typedef typename opr_base::Type Type; template class Sequence> static inline T process(const Sequence& arg_list) { switch (arg_list.size()) { case 0 : return T(0); case 1 : return process_1(arg_list); case 2 : return process_2(arg_list); case 3 : return process_3(arg_list); case 4 : return process_4(arg_list); case 5 : return process_5(arg_list); default : { T result = T(0); for (std::size_t i = 0; i < arg_list.size(); ++i) { result += value(arg_list[i]); } return result; } } } template static inline T process_1(const Sequence& arg_list) { return value(arg_list[0]); } template static inline T process_2(const Sequence& arg_list) { return value(arg_list[0]) + value(arg_list[1]); } template static inline T process_3(const Sequence& arg_list) { return value(arg_list[0]) + value(arg_list[1]) + value(arg_list[2]) ; } template static inline T process_4(const Sequence& arg_list) { return value(arg_list[0]) + value(arg_list[1]) + value(arg_list[2]) + value(arg_list[3]) ; } template static inline T process_5(const Sequence& arg_list) { return value(arg_list[0]) + value(arg_list[1]) + value(arg_list[2]) + value(arg_list[3]) + value(arg_list[4]) ; } }; template struct vararg_mul_op : public opr_base { typedef typename opr_base::Type Type; template class Sequence> static inline T process(const Sequence& arg_list) { switch (arg_list.size()) { case 0 : return T(0); case 1 : return process_1(arg_list); case 2 : return process_2(arg_list); case 3 : return process_3(arg_list); case 4 : return process_4(arg_list); case 5 : return process_5(arg_list); default : { T result = T(value(arg_list[0])); for (std::size_t i = 1; i < arg_list.size(); ++i) { result *= value(arg_list[i]); } return result; } } } template static inline T process_1(const Sequence& arg_list) { return value(arg_list[0]); } template static inline T process_2(const Sequence& arg_list) { return value(arg_list[0]) * value(arg_list[1]); } template static inline T process_3(const Sequence& arg_list) { return value(arg_list[0]) * value(arg_list[1]) * value(arg_list[2]) ; } template static inline T process_4(const Sequence& arg_list) { return value(arg_list[0]) * value(arg_list[1]) * value(arg_list[2]) * value(arg_list[3]) ; } template static inline T process_5(const Sequence& arg_list) { return value(arg_list[0]) * value(arg_list[1]) * value(arg_list[2]) * value(arg_list[3]) * value(arg_list[4]) ; } }; template struct vararg_avg_op : public opr_base { typedef typename opr_base::Type Type; template class Sequence> static inline T process(const Sequence& arg_list) { switch (arg_list.size()) { case 0 : return T(0); case 1 : return process_1(arg_list); case 2 : return process_2(arg_list); case 3 : return process_3(arg_list); case 4 : return process_4(arg_list); case 5 : return process_5(arg_list); default : return vararg_add_op::process(arg_list) / arg_list.size(); } } template static inline T process_1(const Sequence& arg_list) { return value(arg_list[0]); } template static inline T process_2(const Sequence& arg_list) { return (value(arg_list[0]) + value(arg_list[1])) / T(2); } template static inline T process_3(const Sequence& arg_list) { return (value(arg_list[0]) + value(arg_list[1]) + value(arg_list[2])) / T(3); } template static inline T process_4(const Sequence& arg_list) { return (value(arg_list[0]) + value(arg_list[1]) + value(arg_list[2]) + value(arg_list[3])) / T(4); } template static inline T process_5(const Sequence& arg_list) { return (value(arg_list[0]) + value(arg_list[1]) + value(arg_list[2]) + value(arg_list[3]) + value(arg_list[4])) / T(5); } }; template struct vararg_min_op : public opr_base { typedef typename opr_base::Type Type; template class Sequence> static inline T process(const Sequence& arg_list) { switch (arg_list.size()) { case 0 : return T(0); case 1 : return process_1(arg_list); case 2 : return process_2(arg_list); case 3 : return process_3(arg_list); case 4 : return process_4(arg_list); case 5 : return process_5(arg_list); default : { T result = T(value(arg_list[0])); for (std::size_t i = 1; i < arg_list.size(); ++i) { const T v = value(arg_list[i]); if (v < result) result = v; } return result; } } } template static inline T process_1(const Sequence& arg_list) { return value(arg_list[0]); } template static inline T process_2(const Sequence& arg_list) { return std::min(value(arg_list[0]),value(arg_list[1])); } template static inline T process_3(const Sequence& arg_list) { return std::min(std::min(value(arg_list[0]),value(arg_list[1])),value(arg_list[2])); } template static inline T process_4(const Sequence& arg_list) { return std::min( std::min(value(arg_list[0]), value(arg_list[1])), std::min(value(arg_list[2]), value(arg_list[3]))); } template static inline T process_5(const Sequence& arg_list) { return std::min( std::min(std::min(value(arg_list[0]), value(arg_list[1])), std::min(value(arg_list[2]), value(arg_list[3]))), value(arg_list[4])); } }; template struct vararg_max_op : public opr_base { typedef typename opr_base::Type Type; template class Sequence> static inline T process(const Sequence& arg_list) { switch (arg_list.size()) { case 0 : return T(0); case 1 : return process_1(arg_list); case 2 : return process_2(arg_list); case 3 : return process_3(arg_list); case 4 : return process_4(arg_list); case 5 : return process_5(arg_list); default : { T result = T(value(arg_list[0])); for (std::size_t i = 1; i < arg_list.size(); ++i) { const T v = value(arg_list[i]); if (v > result) result = v; } return result; } } } template static inline T process_1(const Sequence& arg_list) { return value(arg_list[0]); } template static inline T process_2(const Sequence& arg_list) { return std::max(value(arg_list[0]),value(arg_list[1])); } template static inline T process_3(const Sequence& arg_list) { return std::max(std::max(value(arg_list[0]),value(arg_list[1])),value(arg_list[2])); } template static inline T process_4(const Sequence& arg_list) { return std::max( std::max(value(arg_list[0]), value(arg_list[1])), std::max(value(arg_list[2]), value(arg_list[3]))); } template static inline T process_5(const Sequence& arg_list) { return std::max( std::max(std::max(value(arg_list[0]), value(arg_list[1])), std::max(value(arg_list[2]), value(arg_list[3]))), value(arg_list[4])); } }; template struct vararg_mand_op : public opr_base { typedef typename opr_base::Type Type; template class Sequence> static inline T process(const Sequence& arg_list) { switch (arg_list.size()) { case 1 : return process_1(arg_list); case 2 : return process_2(arg_list); case 3 : return process_3(arg_list); case 4 : return process_4(arg_list); case 5 : return process_5(arg_list); default : { for (std::size_t i = 0; i < arg_list.size(); ++i) { if (std::equal_to()(T(0), value(arg_list[i]))) return T(0); } return T(1); } } } template static inline T process_1(const Sequence& arg_list) { return std::not_equal_to() (T(0), value(arg_list[0])) ? T(1) : T(0); } template static inline T process_2(const Sequence& arg_list) { return ( std::not_equal_to()(T(0), value(arg_list[0])) && std::not_equal_to()(T(0), value(arg_list[1])) ) ? T(1) : T(0); } template static inline T process_3(const Sequence& arg_list) { return ( std::not_equal_to()(T(0), value(arg_list[0])) && std::not_equal_to()(T(0), value(arg_list[1])) && std::not_equal_to()(T(0), value(arg_list[2])) ) ? T(1) : T(0); } template static inline T process_4(const Sequence& arg_list) { return ( std::not_equal_to()(T(0), value(arg_list[0])) && std::not_equal_to()(T(0), value(arg_list[1])) && std::not_equal_to()(T(0), value(arg_list[2])) && std::not_equal_to()(T(0), value(arg_list[3])) ) ? T(1) : T(0); } template static inline T process_5(const Sequence& arg_list) { return ( std::not_equal_to()(T(0), value(arg_list[0])) && std::not_equal_to()(T(0), value(arg_list[1])) && std::not_equal_to()(T(0), value(arg_list[2])) && std::not_equal_to()(T(0), value(arg_list[3])) && std::not_equal_to()(T(0), value(arg_list[4])) ) ? T(1) : T(0); } }; template struct vararg_mor_op : public opr_base { typedef typename opr_base::Type Type; template class Sequence> static inline T process(const Sequence& arg_list) { switch (arg_list.size()) { case 1 : return process_1(arg_list); case 2 : return process_2(arg_list); case 3 : return process_3(arg_list); case 4 : return process_4(arg_list); case 5 : return process_5(arg_list); default : { for (std::size_t i = 0; i < arg_list.size(); ++i) { if (std::not_equal_to()(T(0), value(arg_list[i]))) return T(1); } return T(0); } } } template static inline T process_1(const Sequence& arg_list) { return std::not_equal_to() (T(0), value(arg_list[0])) ? T(1) : T(0); } template static inline T process_2(const Sequence& arg_list) { return ( std::not_equal_to()(T(0), value(arg_list[0])) || std::not_equal_to()(T(0), value(arg_list[1])) ) ? T(1) : T(0); } template static inline T process_3(const Sequence& arg_list) { return ( std::not_equal_to()(T(0), value(arg_list[0])) || std::not_equal_to()(T(0), value(arg_list[1])) || std::not_equal_to()(T(0), value(arg_list[2])) ) ? T(1) : T(0); } template static inline T process_4(const Sequence& arg_list) { return ( std::not_equal_to()(T(0), value(arg_list[0])) || std::not_equal_to()(T(0), value(arg_list[1])) || std::not_equal_to()(T(0), value(arg_list[2])) || std::not_equal_to()(T(0), value(arg_list[3])) ) ? T(1) : T(0); } template static inline T process_5(const Sequence& arg_list) { return ( std::not_equal_to()(T(0), value(arg_list[0])) || std::not_equal_to()(T(0), value(arg_list[1])) || std::not_equal_to()(T(0), value(arg_list[2])) || std::not_equal_to()(T(0), value(arg_list[3])) || std::not_equal_to()(T(0), value(arg_list[4])) ) ? T(1) : T(0); } }; template struct vararg_multi_op : public opr_base { typedef typename opr_base::Type Type; template class Sequence> static inline T process(const Sequence& arg_list) { switch (arg_list.size()) { case 0 : return std::numeric_limits::quiet_NaN(); case 1 : return process_1(arg_list); case 2 : return process_2(arg_list); case 3 : return process_3(arg_list); case 4 : return process_4(arg_list); case 5 : return process_5(arg_list); case 6 : return process_6(arg_list); case 7 : return process_7(arg_list); case 8 : return process_8(arg_list); default : { for (std::size_t i = 0; i < (arg_list.size() - 1); ++i) { value(arg_list[i]); } return value(arg_list.back()); } } } template static inline T process_1(const Sequence& arg_list) { return value(arg_list[0]); } template static inline T process_2(const Sequence& arg_list) { value(arg_list[0]); return value(arg_list[1]); } template static inline T process_3(const Sequence& arg_list) { value(arg_list[0]); value(arg_list[1]); return value(arg_list[2]); } template static inline T process_4(const Sequence& arg_list) { value(arg_list[0]); value(arg_list[1]); value(arg_list[2]); return value(arg_list[3]); } template static inline T process_5(const Sequence& arg_list) { value(arg_list[0]); value(arg_list[1]); value(arg_list[2]); value(arg_list[3]); return value(arg_list[4]); } template static inline T process_6(const Sequence& arg_list) { value(arg_list[0]); value(arg_list[1]); value(arg_list[2]); value(arg_list[3]); value(arg_list[4]); return value(arg_list[5]); } template static inline T process_7(const Sequence& arg_list) { value(arg_list[0]); value(arg_list[1]); value(arg_list[2]); value(arg_list[3]); value(arg_list[4]); value(arg_list[5]); return value(arg_list[6]); } template static inline T process_8(const Sequence& arg_list) { value(arg_list[0]); value(arg_list[1]); value(arg_list[2]); value(arg_list[3]); value(arg_list[4]); value(arg_list[5]); value(arg_list[6]); return value(arg_list[7]); } }; template struct vec_add_op { typedef vector_interface* ivector_ptr; static inline T process(const ivector_ptr v) { const T* vec = v->vec()->vds().data(); const std::size_t vec_size = v->vec()->vds().size(); loop_unroll::details lud(vec_size); if (vec_size <= static_cast(lud.batch_size)) { T result = T(0); int i = 0; exprtk_disable_fallthrough_begin switch (vec_size) { #define case_stmt(N) \ case N : result += vec[i++]; \ #ifndef exprtk_disable_superscalar_unroll case_stmt(16) case_stmt(15) case_stmt(14) case_stmt(13) case_stmt(12) case_stmt(11) case_stmt(10) case_stmt( 9) case_stmt( 8) case_stmt( 7) case_stmt( 6) case_stmt( 5) #endif case_stmt( 4) case_stmt( 3) case_stmt( 2) case_stmt( 1) } exprtk_disable_fallthrough_end #undef case_stmt return result; } T r[] = { T(0), T(0), T(0), T(0), T(0), T(0), T(0), T(0), T(0), T(0), T(0), T(0), T(0), T(0), T(0), T(0) }; const T* upper_bound = vec + lud.upper_bound; while (vec < upper_bound) { #define exprtk_loop(N) \ r[N] += vec[N]; \ exprtk_loop( 0) exprtk_loop( 1) exprtk_loop( 2) exprtk_loop( 3) #ifndef exprtk_disable_superscalar_unroll exprtk_loop( 4) exprtk_loop( 5) exprtk_loop( 6) exprtk_loop( 7) exprtk_loop( 8) exprtk_loop( 9) exprtk_loop(10) exprtk_loop(11) exprtk_loop(12) exprtk_loop(13) exprtk_loop(14) exprtk_loop(15) #endif vec += lud.batch_size; } int i = 0; exprtk_disable_fallthrough_begin switch (lud.remainder) { #define case_stmt(N) \ case N : r[0] += vec[i++]; \ #ifndef exprtk_disable_superscalar_unroll case_stmt(15) case_stmt(14) case_stmt(13) case_stmt(12) case_stmt(11) case_stmt(10) case_stmt( 9) case_stmt( 8) case_stmt( 7) case_stmt( 6) case_stmt( 5) case_stmt( 4) #endif case_stmt( 3) case_stmt( 2) case_stmt( 1) } exprtk_disable_fallthrough_end #undef exprtk_loop #undef case_stmt return (r[ 0] + r[ 1] + r[ 2] + r[ 3]) #ifndef exprtk_disable_superscalar_unroll + (r[ 4] + r[ 5] + r[ 6] + r[ 7]) + (r[ 8] + r[ 9] + r[10] + r[11]) + (r[12] + r[13] + r[14] + r[15]) #endif ; } }; template struct vec_mul_op { typedef vector_interface* ivector_ptr; static inline T process(const ivector_ptr v) { const T* vec = v->vec()->vds().data(); const std::size_t vec_size = v->vec()->vds().size(); loop_unroll::details lud(vec_size); if (vec_size <= static_cast(lud.batch_size)) { T result = T(1); int i = 0; exprtk_disable_fallthrough_begin switch (vec_size) { #define case_stmt(N) \ case N : result *= vec[i++]; \ #ifndef exprtk_disable_superscalar_unroll case_stmt(16) case_stmt(15) case_stmt(14) case_stmt(13) case_stmt(12) case_stmt(11) case_stmt(10) case_stmt( 9) case_stmt( 8) case_stmt( 7) case_stmt( 6) case_stmt( 5) #endif case_stmt( 4) case_stmt( 3) case_stmt( 2) case_stmt( 1) } exprtk_disable_fallthrough_end #undef case_stmt return result; } T r[] = { T(1), T(1), T(1), T(1), T(1), T(1), T(1), T(1), T(1), T(1), T(1), T(1), T(1), T(1), T(1), T(1) }; const T* upper_bound = vec + lud.upper_bound; while (vec < upper_bound) { #define exprtk_loop(N) \ r[N] *= vec[N]; \ exprtk_loop( 0) exprtk_loop( 1) exprtk_loop( 2) exprtk_loop( 3) #ifndef exprtk_disable_superscalar_unroll exprtk_loop( 4) exprtk_loop( 5) exprtk_loop( 6) exprtk_loop( 7) exprtk_loop( 8) exprtk_loop( 9) exprtk_loop(10) exprtk_loop(11) exprtk_loop(12) exprtk_loop(13) exprtk_loop(14) exprtk_loop(15) #endif vec += lud.batch_size; } int i = 0; exprtk_disable_fallthrough_begin switch (lud.remainder) { #define case_stmt(N) \ case N : r[0] *= vec[i++]; \ #ifndef exprtk_disable_superscalar_unroll case_stmt(15) case_stmt(14) case_stmt(13) case_stmt(12) case_stmt(11) case_stmt(10) case_stmt( 9) case_stmt( 8) case_stmt( 7) case_stmt( 6) case_stmt( 5) case_stmt( 4) #endif case_stmt( 3) case_stmt( 2) case_stmt( 1) } exprtk_disable_fallthrough_end #undef exprtk_loop #undef case_stmt return (r[ 0] * r[ 1] * r[ 2] * r[ 3]) #ifndef exprtk_disable_superscalar_unroll + (r[ 4] * r[ 5] * r[ 6] * r[ 7]) + (r[ 8] * r[ 9] * r[10] * r[11]) + (r[12] * r[13] * r[14] * r[15]) #endif ; } }; template struct vec_avg_op { typedef vector_interface* ivector_ptr; static inline T process(const ivector_ptr v) { const std::size_t vec_size = v->vec()->vds().size(); return vec_add_op::process(v) / vec_size; } }; template struct vec_min_op { typedef vector_interface* ivector_ptr; static inline T process(const ivector_ptr v) { const T* vec = v->vec()->vds().data(); const std::size_t vec_size = v->vec()->vds().size(); T result = vec[0]; for (std::size_t i = 1; i < vec_size; ++i) { const T v_i = vec[i]; if (v_i < result) result = v_i; } return result; } }; template struct vec_max_op { typedef vector_interface* ivector_ptr; static inline T process(const ivector_ptr v) { const T* vec = v->vec()->vds().data(); const std::size_t vec_size = v->vec()->vds().size(); T result = vec[0]; for (std::size_t i = 1; i < vec_size; ++i) { const T v_i = vec[i]; if (v_i > result) result = v_i; } return result; } }; template class vov_base_node : public expression_node { public: ``` a65c8e8b ``` virtual ~vov_base_node() {} ``` 4068375e ``` inline virtual operator_type operation() const { return details::e_default; } virtual const T& v0() const = 0; virtual const T& v1() const = 0; }; template class cov_base_node : public expression_node { public: ``` a65c8e8b ``` virtual ~cov_base_node() {} ``` 4068375e ``` inline virtual operator_type operation() const { return details::e_default; } virtual const T c() const = 0; virtual const T& v() const = 0; }; template class voc_base_node : public expression_node { public: ``` a65c8e8b ``` virtual ~voc_base_node() {} ``` 4068375e ``` inline virtual operator_type operation() const { 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: ``` a65c8e8b ``` virtual ~vob_base_node() {} ``` 4068375e ``` virtual const T& v() const = 0; }; template class bov_base_node : public expression_node { public: ``` a65c8e8b ``` virtual ~bov_base_node() {} ``` 4068375e ``` virtual const T& v() const = 0; }; template class cob_base_node : public expression_node { public: ``` a65c8e8b ``` virtual ~cob_base_node() {} ``` 4068375e ``` inline virtual operator_type operation() const { return details::e_default; } virtual const T c() const = 0; virtual void set_c(const T) = 0; virtual expression_node* move_branch(const std::size_t& index) = 0; }; template class boc_base_node : public expression_node { public: ``` a65c8e8b ``` virtual ~boc_base_node() {} ``` 4068375e ``` inline virtual operator_type operation() const { return details::e_default; } virtual const T c() const = 0; virtual void set_c(const T) = 0; virtual expression_node* move_branch(const std::size_t& index) = 0; }; template class uv_base_node : public expression_node { public: ``` a65c8e8b ``` virtual ~uv_base_node() {} ``` 4068375e ``` inline virtual operator_type operation() const { return details::e_default; } virtual const T& v() const = 0; }; template class sos_base_node : public expression_node { public: ``` a65c8e8b ``` virtual ~sos_base_node() {} ``` 4068375e ``` inline virtual operator_type operation() const { return details::e_default; } }; template class sosos_base_node : public expression_node { public: ``` a65c8e8b ``` virtual ~sosos_base_node() {} ``` 4068375e ``` inline virtual operator_type operation() const { return details::e_default; } }; template class T0oT1oT2_base_node : public expression_node { public: ``` a65c8e8b ``` virtual ~T0oT1oT2_base_node() {} ``` 4068375e ``` virtual std::string type_id() const = 0; }; template class T0oT1oT2oT3_base_node : public expression_node { public: ``` a65c8e8b ``` virtual ~T0oT1oT2oT3_base_node() {} ``` 4068375e ``` virtual std::string type_id() const = 0; }; template ``` a65c8e8b ``` class unary_variable_node exprtk_final : public uv_base_node ``` 4068375e ``` { public: typedef expression_node* expression_ptr; typedef Operation operation_t; explicit unary_variable_node(const T& var) : v_(var) {} ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { return Operation::process(v_); } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return Operation::type(); } ``` a65c8e8b ``` inline operator_type operation() const exprtk_override ``` 4068375e ``` { return Operation::operation(); } ``` a65c8e8b ``` inline const T& v() const exprtk_override ``` 4068375e ``` { return v_; } private: ``` a65c8e8b ``` unary_variable_node(const unary_variable_node&) exprtk_delete; unary_variable_node& operator=(const unary_variable_node&) exprtk_delete; ``` 4068375e ``` const T& v_; }; template ``` a65c8e8b ``` class uvouv_node exprtk_final : public expression_node ``` 4068375e ``` { public: // UOpr1(v0) Op UOpr2(v1) typedef typename details::functor_t functor_t; ``` a65c8e8b ``` typedef typename functor_t::bfunc_t bfunc_t; typedef typename functor_t::ufunc_t ufunc_t; typedef expression_node* expression_ptr; ``` 4068375e ``` explicit uvouv_node(const T& var0,const T& var1, ufunc_t uf0, ufunc_t uf1, bfunc_t bf) ``` a65c8e8b ``` : v0_(var0) , v1_(var1) , u0_(uf0 ) , u1_(uf1 ) , f_ (bf ) ``` 4068375e ``` {} ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { return f_(u0_(v0_),u1_(v1_)); } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_uvouv; } inline const T& v0() { return v0_; } inline const T& v1() { return v1_; } inline ufunc_t u0() { return u0_; } inline ufunc_t u1() { return u1_; } inline ufunc_t f() { return f_; } private: ``` a65c8e8b ``` uvouv_node(const uvouv_node&) exprtk_delete; uvouv_node& operator=(const uvouv_node&) exprtk_delete; ``` 4068375e ``` const T& v0_; const T& v1_; const ufunc_t u0_; const ufunc_t u1_; const bfunc_t f_; }; template ``` a65c8e8b ``` class unary_branch_node exprtk_final : public expression_node ``` 4068375e ``` { public: ``` a65c8e8b ``` typedef Operation operation_t; typedef expression_node* expression_ptr; ``` 4068375e ``` typedef std::pair branch_t; explicit unary_branch_node(expression_ptr branch) { construct_branch_pair(branch_, branch); } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { return Operation::process(branch_.first->value()); } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return Operation::type(); } ``` a65c8e8b ``` inline operator_type operation() ``` 4068375e ``` { return Operation::operation(); } ``` a65c8e8b ``` inline expression_node* branch(const std::size_t&) const exprtk_override ``` 4068375e ``` { return branch_.first; } inline void release() { branch_.second = false; } ``` a65c8e8b ``` void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override ``` 4068375e ``` { expression_node::ndb_t::collect(branch_, node_delete_list); } ``` a65c8e8b ``` std::size_t node_depth() const exprtk_override ``` 4068375e ``` { return expression_node::ndb_t::compute_node_depth(branch_); } private: ``` a65c8e8b ``` unary_branch_node(const unary_branch_node&) exprtk_delete; unary_branch_node& operator=(const unary_branch_node&) exprtk_delete; ``` 4068375e ``` branch_t branch_; }; 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; } }; #define exprtk_crtype(Type) \ param_to_str::result>::result() \ template struct T0oT1oT2process { typedef typename details::functor_t functor_t; ``` a65c8e8b ``` typedef typename functor_t::bfunc_t bfunc_t; ``` 4068375e ``` 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 = "(" + exprtk_crtype(T0) + "o" + exprtk_crtype(T1) + ")o(" + exprtk_crtype(T2) + ")" ; 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 = "(" + exprtk_crtype(T0) + ")o(" + exprtk_crtype(T1) + "o" + exprtk_crtype(T2) + ")" ; return result; } }; }; template struct T0oT1oT20T3process { typedef typename details::functor_t functor_t; ``` a65c8e8b ``` typedef typename functor_t::bfunc_t bfunc_t; ``` 4068375e ``` 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 = "(" + exprtk_crtype(T0) + "o" + exprtk_crtype(T1) + ")o" + "(" + exprtk_crtype(T2) + "o" + exprtk_crtype(T3) + ")" ; 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 = "(" + exprtk_crtype(T0) + ")o((" + exprtk_crtype(T1) + ")o(" + exprtk_crtype(T2) + "o" + exprtk_crtype(T3) + "))" ; 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 = "(" + exprtk_crtype(T0) + ")o((" + exprtk_crtype(T1) + "o" + exprtk_crtype(T2) + ")o(" + exprtk_crtype(T3) + "))" ; 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 = "((" + exprtk_crtype(T0) + "o" + exprtk_crtype(T1) + ")o(" + exprtk_crtype(T2) + "))o(" + exprtk_crtype(T3) + ")"; 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 = "((" + exprtk_crtype(T0) + ")o(" + exprtk_crtype(T1) + "o" + exprtk_crtype(T2) + "))o(" + exprtk_crtype(T3) + ")" ; return result; } }; }; #undef exprtk_crtype 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; ``` a65c8e8b ``` #define synthesis_node_type_define(T0_, T1_, v_) \ ``` 4068375e ``` 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_; \ synthesis_node_type_define(const T0&, const T1&, e_vov) synthesis_node_type_define(const T0&, const T1 , e_voc) synthesis_node_type_define(const T0 , const T1&, e_cov) synthesis_node_type_define( T0&, T1&, e_none) synthesis_node_type_define(const T0 , const T1 , e_none) synthesis_node_type_define( T0&, const T1 , e_none) synthesis_node_type_define(const T0 , T1&, e_none) synthesis_node_type_define(const T0&, T1&, e_none) synthesis_node_type_define( T0&, const T1&, e_none) #undef synthesis_node_type_define template struct nodetype_T0oT1oT2 { static const typename expression_node::node_type result; }; template const typename expression_node::node_type nodetype_T0oT1oT2::result = expression_node::e_none; ``` a65c8e8b ``` #define synthesis_node_type_define(T0_, T1_, T2_, v_) \ ``` 4068375e ``` 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_; \ synthesis_node_type_define(const T0&, const T1&, const T2&, e_vovov) synthesis_node_type_define(const T0&, const T1&, const T2 , e_vovoc) synthesis_node_type_define(const T0&, const T1 , const T2&, e_vocov) synthesis_node_type_define(const T0 , const T1&, const T2&, e_covov) synthesis_node_type_define(const T0 , const T1&, const T2 , e_covoc) synthesis_node_type_define(const T0 , const T1 , const T2 , e_none ) synthesis_node_type_define(const T0 , const T1 , const T2&, e_none ) synthesis_node_type_define(const T0&, const T1 , const T2 , e_none ) synthesis_node_type_define( T0&, T1&, T2&, e_none ) #undef synthesis_node_type_define template struct nodetype_T0oT1oT2oT3 { static const typename expression_node::node_type result; }; template const typename expression_node::node_type nodetype_T0oT1oT2oT3::result = expression_node::e_none; ``` a65c8e8b ``` #define synthesis_node_type_define(T0_, T1_, T2_, T3_, v_) \ ``` 4068375e ``` 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_; \ synthesis_node_type_define(const T0&, const T1&, const T2&, const T3&, e_vovovov) synthesis_node_type_define(const T0&, const T1&, const T2&, const T3 , e_vovovoc) synthesis_node_type_define(const T0&, const T1&, const T2 , const T3&, e_vovocov) synthesis_node_type_define(const T0&, const T1 , const T2&, const T3&, e_vocovov) synthesis_node_type_define(const T0 , const T1&, const T2&, const T3&, e_covovov) synthesis_node_type_define(const T0 , const T1&, const T2 , const T3&, e_covocov) synthesis_node_type_define(const T0&, const T1 , const T2&, const T3 , e_vocovoc) synthesis_node_type_define(const T0 , const T1&, const T2&, const T3 , e_covovoc) synthesis_node_type_define(const T0&, const T1 , const T2 , const T3&, e_vococov) synthesis_node_type_define(const T0 , const T1 , const T2 , const T3 , e_none ) synthesis_node_type_define(const T0 , const T1 , const T2 , const T3&, e_none ) synthesis_node_type_define(const T0 , const T1 , const T2&, const T3 , e_none ) synthesis_node_type_define(const T0 , const T1&, const T2 , const T3 , e_none ) synthesis_node_type_define(const T0&, const T1 , const T2 , const T3 , e_none ) synthesis_node_type_define(const T0 , const T1 , const T2&, const T3&, e_none ) synthesis_node_type_define(const T0&, const T1&, const T2 , const T3 , e_none ) #undef synthesis_node_type_define template ``` a65c8e8b ``` class T0oT1 exprtk_final : public expression_node ``` 4068375e ``` { public: typedef typename details::functor_t functor_t; ``` a65c8e8b ``` typedef typename functor_t::bfunc_t bfunc_t; ``` 4068375e ``` typedef T value_type; typedef T0oT1 node_type; T0oT1(T0 p0, T1 p1, const bfunc_t p2) ``` a65c8e8b ``` : t0_(p0) , t1_(p1) , f_ (p2) ``` 4068375e ``` {} ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { static const typename expression_node::node_type result = nodetype_T0oT1::result; return result; } ``` a65c8e8b ``` inline operator_type operation() const exprtk_override ``` 4068375e ``` { return e_default; } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { 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 p0, T1 p1, bfunc_t p2) { return allocator .template allocate_type (p0, p1, p2); } private: ``` a65c8e8b ``` T0oT1(const T0oT1&) exprtk_delete; T0oT1& operator=(const T0oT1&) { return (*this); } ``` 4068375e ``` T0 t0_; T1 t1_; const bfunc_t f_; }; template ``` a65c8e8b ``` class T0oT1oT2 exprtk_final : public T0oT1oT2_base_node ``` 4068375e ``` { public: typedef typename details::functor_t functor_t; ``` a65c8e8b ``` typedef typename functor_t::bfunc_t bfunc_t; ``` 4068375e ``` typedef T value_type; typedef T0oT1oT2 node_type; typedef ProcessMode process_mode_t; T0oT1oT2(T0 p0, T1 p1, T2 p2, const bfunc_t p3, const bfunc_t p4) ``` a65c8e8b ``` : t0_(p0) , t1_(p1) , t2_(p2) , f0_(p3) , f1_(p4) ``` 4068375e ``` {} ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { static const typename expression_node::node_type result = nodetype_T0oT1oT2::result; return result; } ``` a65c8e8b ``` inline operator_type operation() ``` 4068375e ``` { return e_default; } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { 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_; } ``` a65c8e8b ``` std::string type_id() const exprtk_override ``` 4068375e ``` { return id(); } static inline std::string id() { return process_mode_t::template id(); } template static inline expression_node* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, bfunc_t p3, bfunc_t p4) { return allocator .template allocate_type (p0, p1, p2, p3, p4); } private: ``` a65c8e8b ``` T0oT1oT2(const node_type&) exprtk_delete; node_type& operator=(const node_type&) { return (*this); } ``` 4068375e ``` T0 t0_; T1 t1_; T2 t2_; const bfunc_t f0_; const bfunc_t f1_; }; template ``` a65c8e8b ``` class T0oT1oT2oT3 exprtk_final : public T0oT1oT2oT3_base_node ``` 4068375e ``` { public: typedef typename details::functor_t functor_t; ``` a65c8e8b ``` typedef typename functor_t::bfunc_t bfunc_t; ``` 4068375e ``` 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 p0, T1 p1, T2 p2, T3 p3, bfunc_t p4, bfunc_t p5, bfunc_t p6) ``` a65c8e8b ``` : t0_(p0) , t1_(p1) , t2_(p2) , t3_(p3) , f0_(p4) , f1_(p5) , f2_(p6) ``` 4068375e ``` {} ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { 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_; } ``` a65c8e8b ``` inline std::string type_id() const exprtk_override ``` 4068375e ``` { return id(); } static inline std::string id() { return process_mode_t::template id(); } template static inline expression_node* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, T3 p3, bfunc_t p4, bfunc_t p5, bfunc_t p6) { return allocator .template allocate_type (p0, p1, p2, p3, p4, p5, p6); } private: ``` a65c8e8b ``` T0oT1oT2oT3(const node_type&) exprtk_delete; node_type& operator=(const node_type&) { return (*this); } ``` 4068375e ``` T0 t0_; T1 t1_; T2 t2_; T3 t3_; const bfunc_t f0_; const bfunc_t f1_; const bfunc_t f2_; }; template ``` a65c8e8b ``` class T0oT1oT2_sf3 exprtk_final : public T0oT1oT2_base_node ``` 4068375e ``` { public: typedef typename details::functor_t functor_t; ``` a65c8e8b ``` typedef typename functor_t::tfunc_t tfunc_t; ``` 4068375e ``` typedef T value_type; typedef T0oT1oT2_sf3 node_type; T0oT1oT2_sf3(T0 p0, T1 p1, T2 p2, const tfunc_t p3) ``` a65c8e8b ``` : t0_(p0) , t1_(p1) , t2_(p2) , f_ (p3) ``` 4068375e ``` {} ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { static const typename expression_node::node_type result = nodetype_T0oT1oT2::result; return result; } ``` a65c8e8b ``` inline operator_type operation() const exprtk_override ``` 4068375e ``` { return e_default; } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { 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 p0, T1 p1, T2 p2, tfunc_t p3) { return allocator .template allocate_type (p0, p1, p2, p3); } private: ``` a65c8e8b ``` T0oT1oT2_sf3(const node_type&) exprtk_delete; node_type& operator=(const node_type&) { return (*this); } ``` 4068375e ``` T0 t0_; T1 t1_; T2 t2_; const tfunc_t f_; }; template class sf3ext_type_node : public T0oT1oT2_base_node { public: ``` a65c8e8b ``` virtual ~sf3ext_type_node() {} ``` 4068375e ``` virtual T0 t0() const = 0; virtual T1 t1() const = 0; virtual T2 t2() const = 0; }; template ``` a65c8e8b ``` class T0oT1oT2_sf3ext exprtk_final : public sf3ext_type_node ``` 4068375e ``` { public: typedef typename details::functor_t functor_t; ``` a65c8e8b ``` typedef typename functor_t::tfunc_t tfunc_t; ``` 4068375e ``` typedef T value_type; ``` a65c8e8b ``` typedef T0oT1oT2_sf3ext node_type; ``` 4068375e ``` T0oT1oT2_sf3ext(T0 p0, T1 p1, T2 p2) ``` a65c8e8b ``` : t0_(p0) , t1_(p1) , t2_(p2) ``` 4068375e ``` {} ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { static const typename expression_node::node_type result = nodetype_T0oT1oT2::result; return result; } ``` a65c8e8b ``` inline operator_type operation() ``` 4068375e ``` { return e_default; } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { return SF3Operation::process(t0_, t1_, t2_); } ``` a65c8e8b ``` T0 t0() const exprtk_override ``` 4068375e ``` { return t0_; } ``` a65c8e8b ``` T1 t1() const exprtk_override ``` 4068375e ``` { return t1_; } ``` a65c8e8b ``` T2 t2() const exprtk_override ``` 4068375e ``` { return t2_; } ``` a65c8e8b ``` std::string type_id() const exprtk_override ``` 4068375e ``` { return id(); } static inline std::string id() { return SF3Operation::id(); } template static inline expression_node* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2) { return allocator .template allocate_type (p0, p1, p2); } private: ``` a65c8e8b ``` T0oT1oT2_sf3ext(const node_type&) exprtk_delete; node_type& operator=(const node_type&) { return (*this); } ``` 4068375e ``` T0 t0_; T1 t1_; T2 t2_; }; template inline bool is_sf3ext_node(const expression_node* n) { switch (n->type()) { case expression_node::e_vovov : return true; case expression_node::e_vovoc : return true; case expression_node::e_vocov : return true; case expression_node::e_covov : return true; case expression_node::e_covoc : return true; default : return false; } } template ``` a65c8e8b ``` class T0oT1oT2oT3_sf4 exprtk_final : public T0oT1oT2_base_node ``` 4068375e ``` { public: typedef typename details::functor_t functor_t; ``` a65c8e8b ``` typedef typename functor_t::qfunc_t qfunc_t; ``` 4068375e ``` typedef T value_type; ``` a65c8e8b ``` typedef T0oT1oT2oT3_sf4 node_type; ``` 4068375e ``` T0oT1oT2oT3_sf4(T0 p0, T1 p1, T2 p2, T3 p3, const qfunc_t p4) ``` a65c8e8b ``` : t0_(p0) , t1_(p1) , t2_(p2) , t3_(p3) , f_ (p4) ``` 4068375e ``` {} ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { static const typename expression_node::node_type result = nodetype_T0oT1oT2oT3::result; return result; } ``` a65c8e8b ``` inline operator_type operation() const exprtk_override ``` 4068375e ``` { return e_default; } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { 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 p0, T1 p1, T2 p2, T3 p3, qfunc_t p4) { return allocator .template allocate_type (p0, p1, p2, p3, p4); } private: ``` a65c8e8b ``` T0oT1oT2oT3_sf4(const node_type&) exprtk_delete; node_type& operator=(const node_type&) { return (*this); } ``` 4068375e ``` T0 t0_; T1 t1_; T2 t2_; T3 t3_; const qfunc_t f_; }; template ``` a65c8e8b ``` class T0oT1oT2oT3_sf4ext exprtk_final : public T0oT1oT2oT3_base_node ``` 4068375e ``` { public: typedef typename details::functor_t functor_t; ``` a65c8e8b ``` typedef typename functor_t::tfunc_t tfunc_t; ``` 4068375e ``` typedef T value_type; ``` a65c8e8b ``` typedef T0oT1oT2oT3_sf4ext node_type; ``` 4068375e ``` T0oT1oT2oT3_sf4ext(T0 p0, T1 p1, T2 p2, T3 p3) ``` a65c8e8b ``` : t0_(p0) , t1_(p1) , t2_(p2) , t3_(p3) ``` 4068375e ``` {} ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { static const typename expression_node::node_type result = nodetype_T0oT1oT2oT3::result; return result; } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { 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 t3_; } ``` a65c8e8b ``` std::string type_id() const exprtk_override ``` 4068375e ``` { return id(); } static inline std::string id() { return SF4Operation::id(); } template static inline expression_node* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, T3 p3) { return allocator .template allocate_type (p0, p1, p2, p3); } private: ``` a65c8e8b ``` T0oT1oT2oT3_sf4ext(const node_type&) exprtk_delete; node_type& operator=(const node_type&) { return (*this); } ``` 4068375e ``` T0 t0_; T1 t1_; T2 t2_; T3 t3_; }; template inline bool is_sf4ext_node(const expression_node* n) { switch (n->type()) { case expression_node::e_vovovov : return true; case expression_node::e_vovovoc : return true; case expression_node::e_vovocov : return true; case expression_node::e_vocovov : return true; case expression_node::e_covovov : return true; case expression_node::e_covocov : return true; case expression_node::e_vocovoc : return true; case expression_node::e_covovoc : return true; case expression_node::e_vococov : return true; default : return false; } } 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; typedef details::sf3ext_type_node sf3_type_node; }; 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 ``` a65c8e8b ``` class vov_node exprtk_final : public vov_base_node ``` 4068375e ``` { public: typedef expression_node* expression_ptr; typedef Operation operation_t; // variable op variable node explicit vov_node(const T& var0, const T& var1) ``` a65c8e8b ``` : v0_(var0) , v1_(var1) ``` 4068375e ``` {} ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { return Operation::process(v0_,v1_); } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return Operation::type(); } ``` a65c8e8b ``` inline operator_type operation() const exprtk_override ``` 4068375e ``` { return Operation::operation(); } ``` a65c8e8b ``` inline const T& v0() const exprtk_override ``` 4068375e ``` { return v0_; } ``` a65c8e8b ``` inline const T& v1() const exprtk_override ``` 4068375e ``` { return v1_; } protected: const T& v0_; const T& v1_; private: ``` a65c8e8b ``` vov_node(const vov_node&) exprtk_delete; vov_node& operator=(const vov_node&) exprtk_delete; ``` 4068375e ``` }; template ``` a65c8e8b ``` class cov_node exprtk_final : public cov_base_node ``` 4068375e ``` { public: typedef expression_node* expression_ptr; typedef Operation operation_t; // constant op variable node explicit cov_node(const T& const_var, const T& var) ``` a65c8e8b ``` : c_(const_var) , v_(var) ``` 4068375e ``` {} ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { return Operation::process(c_,v_); } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return Operation::type(); } ``` a65c8e8b ``` inline operator_type operation() const exprtk_override ``` 4068375e ``` { return Operation::operation(); } ``` a65c8e8b ``` inline const T c() const exprtk_override ``` 4068375e ``` { return c_; } ``` a65c8e8b ``` inline const T& v() const exprtk_override ``` 4068375e ``` { return v_; } protected: const T c_; const T& v_; private: ``` a65c8e8b ``` cov_node(const cov_node&) exprtk_delete; cov_node& operator=(const cov_node&) exprtk_delete; ``` 4068375e ``` }; template ``` a65c8e8b ``` class voc_node exprtk_final : public voc_base_node ``` 4068375e ``` { public: typedef expression_node* expression_ptr; typedef Operation operation_t; // variable op constant node explicit voc_node(const T& var, const T& const_var) ``` a65c8e8b ``` : v_(var) , c_(const_var) ``` 4068375e ``` {} ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { return Operation::process(v_,c_); } ``` a65c8e8b ``` inline operator_type operation() const exprtk_override ``` 4068375e ``` { return Operation::operation(); } ``` a65c8e8b ``` inline const T c() const exprtk_override ``` 4068375e ``` { return c_; } ``` a65c8e8b ``` inline const T& v() const exprtk_override ``` 4068375e ``` { return v_; } protected: const T& v_; const T c_; private: ``` a65c8e8b ``` voc_node(const voc_node&) exprtk_delete; voc_node& operator=(const voc_node&) exprtk_delete; ``` 4068375e ``` }; template ``` a65c8e8b ``` class vob_node exprtk_final : public vob_base_node ``` 4068375e ``` { public: typedef expression_node* expression_ptr; typedef std::pair branch_t; typedef Operation operation_t; // variable op constant node explicit vob_node(const T& var, const expression_ptr branch) : v_(var) { construct_branch_pair(branch_, branch); } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { ``` a65c8e8b ``` assert(branch_.first); ``` 4068375e ``` return Operation::process(v_,branch_.first->value()); } ``` a65c8e8b ``` inline const T& v() const exprtk_override ``` 4068375e ``` { return v_; } ``` a65c8e8b ``` inline expression_node* branch(const std::size_t&) const exprtk_override ``` 4068375e ``` { return branch_.first; } ``` a65c8e8b ``` void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override ``` 4068375e ``` { expression_node::ndb_t::template collect(branch_, node_delete_list); } ``` a65c8e8b ``` std::size_t node_depth() const exprtk_override ``` 4068375e ``` { return expression_node::ndb_t::compute_node_depth(branch_); } private: ``` a65c8e8b ``` vob_node(const vob_node&) exprtk_delete; vob_node& operator=(const vob_node&) exprtk_delete; ``` 4068375e ``` const T& v_; branch_t branch_; }; template ``` a65c8e8b ``` class bov_node exprtk_final : public bov_base_node ``` 4068375e ``` { public: typedef expression_node* expression_ptr; typedef std::pair branch_t; typedef Operation operation_t; // variable op constant node explicit bov_node(const expression_ptr branch, const T& var) : v_(var) { construct_branch_pair(branch_, branch); } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { ``` a65c8e8b ``` assert(branch_.first); ``` 4068375e ``` return Operation::process(branch_.first->value(),v_); } ``` a65c8e8b ``` inline const T& v() const exprtk_override ``` 4068375e ``` { return v_; } ``` a65c8e8b ``` inline expression_node* branch(const std::size_t&) const exprtk_override ``` 4068375e ``` { return branch_.first; } ``` a65c8e8b ``` void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override ``` 4068375e ``` { expression_node::ndb_t::template collect(branch_, node_delete_list); } ``` a65c8e8b ``` std::size_t node_depth() const exprtk_override ``` 4068375e ``` { return expression_node::ndb_t::compute_node_depth(branch_); } private: ``` a65c8e8b ``` bov_node(const bov_node&) exprtk_delete; bov_node& operator=(const bov_node&) exprtk_delete; ``` 4068375e ``` const T& v_; branch_t branch_; }; template ``` a65c8e8b ``` class cob_node exprtk_final : public cob_base_node ``` 4068375e ``` { public: typedef expression_node* expression_ptr; typedef std::pair branch_t; typedef Operation operation_t; // variable op constant node explicit cob_node(const T const_var, const expression_ptr branch) : c_(const_var) { construct_branch_pair(branch_, branch); } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { ``` a65c8e8b ``` assert(branch_.first); ``` 4068375e ``` return Operation::process(c_,branch_.first->value()); } ``` a65c8e8b ``` inline operator_type operation() const exprtk_override ``` 4068375e ``` { return Operation::operation(); } ``` a65c8e8b ``` inline const T c() const exprtk_override ``` 4068375e ``` { return c_; } ``` a65c8e8b ``` inline void set_c(const T new_c) exprtk_override ``` 4068375e ``` { (*const_cast(&c_)) = new_c; } ``` a65c8e8b ``` inline expression_node* branch(const std::size_t&) const exprtk_override ``` 4068375e ``` { return branch_.first; } ``` a65c8e8b ``` inline expression_node* move_branch(const std::size_t&) exprtk_override ``` 4068375e ``` { branch_.second = false; return branch_.first; } ``` a65c8e8b ``` void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override ``` 4068375e ``` { expression_node::ndb_t::template collect(branch_, node_delete_list); } ``` a65c8e8b ``` std::size_t node_depth() const exprtk_override ``` 4068375e ``` { return expression_node::ndb_t::compute_node_depth(branch_); } private: ``` a65c8e8b ``` cob_node(const cob_node&) exprtk_delete; cob_node& operator=(const cob_node&) exprtk_delete; ``` 4068375e ``` const T c_; branch_t branch_; }; template ``` a65c8e8b ``` class boc_node exprtk_final : public boc_base_node ``` 4068375e ``` { public: typedef expression_node* expression_ptr; typedef std::pair branch_t; typedef Operation operation_t; // variable op constant node explicit boc_node(const expression_ptr branch, const T const_var) : c_(const_var) { construct_branch_pair(branch_, branch); } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { ``` a65c8e8b ``` assert(branch_.first); ``` 4068375e ``` return Operation::process(branch_.first->value(),c_); } ``` a65c8e8b ``` inline operator_type operation() const exprtk_override ``` 4068375e ``` { return Operation::operation(); } ``` a65c8e8b ``` inline const T c() const exprtk_override ``` 4068375e ``` { return c_; } ``` a65c8e8b ``` inline void set_c(const T new_c) exprtk_override ``` 4068375e ``` { (*const_cast(&c_)) = new_c; } ``` a65c8e8b ``` inline expression_node* branch(const std::size_t&) const exprtk_override ``` 4068375e ``` { return branch_.first; } ``` a65c8e8b ``` inline expression_node* move_branch(const std::size_t&) exprtk_override ``` 4068375e ``` { branch_.second = false; return branch_.first; } ``` a65c8e8b ``` void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override ``` 4068375e ``` { expression_node::ndb_t::template collect(branch_, node_delete_list); } ``` a65c8e8b ``` std::size_t node_depth() const exprtk_override ``` 4068375e ``` { return expression_node::ndb_t::compute_node_depth(branch_); } private: ``` a65c8e8b ``` boc_node(const boc_node&) exprtk_delete; boc_node& operator=(const boc_node&) exprtk_delete; ``` 4068375e ``` const T c_; branch_t branch_; }; #ifndef exprtk_disable_string_capabilities template ``` a65c8e8b ``` class sos_node exprtk_final : public sos_base_node ``` 4068375e ``` { public: typedef expression_node* expression_ptr; typedef Operation operation_t; // string op string node explicit sos_node(SType0 p0, SType1 p1) ``` a65c8e8b ``` : s0_(p0) , s1_(p1) ``` 4068375e ``` {} ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { return Operation::process(s0_,s1_); } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return Operation::type(); } ``` a65c8e8b ``` inline operator_type operation() const exprtk_override ``` 4068375e ``` { return Operation::operation(); } inline std::string& s0() { return s0_; } inline std::string& s1() { return s1_; } protected: SType0 s0_; SType1 s1_; private: ``` a65c8e8b ``` sos_node(const sos_node&) exprtk_delete; sos_node& operator=(const sos_node&) exprtk_delete; ``` 4068375e ``` }; template ``` a65c8e8b ``` class str_xrox_node exprtk_final : public sos_base_node ``` 4068375e ``` { public: typedef expression_node* expression_ptr; typedef Operation operation_t; ``` a65c8e8b ``` typedef str_xrox_node node_type; ``` 4068375e ``` // string-range op string node explicit str_xrox_node(SType0 p0, SType1 p1, RangePack rp0) ``` a65c8e8b ``` : s0_ (p0 ) , s1_ (p1 ) , rp0_(rp0) ``` 4068375e ``` {} ~str_xrox_node() { rp0_.free(); } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { std::size_t r0 = 0; std::size_t r1 = 0; if (rp0_(r0, r1, s0_.size())) return Operation::process(s0_.substr(r0, (r1 - r0) + 1), s1_); else return T(0); } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return Operation::type(); } ``` a65c8e8b ``` inline operator_type operation() const exprtk_override ``` 4068375e ``` { return Operation::operation(); } inline std::string& s0() { return s0_; } inline std::string& s1() { return s1_; } protected: SType0 s0_; SType1 s1_; RangePack rp0_; private: ``` a65c8e8b ``` str_xrox_node(const node_type&) exprtk_delete; node_type& operator=(const node_type&) exprtk_delete; ``` 4068375e ``` }; template ``` a65c8e8b ``` class str_xoxr_node exprtk_final : public sos_base_node ``` 4068375e ``` { public: typedef expression_node* expression_ptr; typedef Operation operation_t; ``` a65c8e8b ``` typedef str_xoxr_node node_type; ``` 4068375e ``` // string op string range node explicit str_xoxr_node(SType0 p0, SType1 p1, RangePack rp1) ``` a65c8e8b ``` : s0_ (p0 ) , s1_ (p1 ) , rp1_(rp1) ``` 4068375e ``` {} ~str_xoxr_node() { rp1_.free(); } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { std::size_t r0 = 0; std::size_t r1 = 0; if (rp1_(r0, r1, s1_.size())) return Operation::process(s0_, s1_.substr(r0, (r1 - r0) + 1)); else return T(0); } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return Operation::type(); } ``` a65c8e8b ``` inline operator_type operation() const exprtk_override ``` 4068375e ``` { return Operation::operation(); } inline std::string& s0() { return s0_; } inline std::string& s1() { return s1_; } protected: SType0 s0_; SType1 s1_; RangePack rp1_; private: ``` a65c8e8b ``` str_xoxr_node(const node_type&) exprtk_delete; node_type& operator=(const node_type&) exprtk_delete; ``` 4068375e ``` }; template ``` a65c8e8b ``` class str_xroxr_node exprtk_final : public sos_base_node ``` 4068375e ``` { public: typedef expression_node* expression_ptr; typedef Operation operation_t; ``` a65c8e8b ``` typedef str_xroxr_node node_type; ``` 4068375e ``` // string-range op string-range node explicit str_xroxr_node(SType0 p0, SType1 p1, RangePack rp0, RangePack rp1) ``` a65c8e8b ``` : s0_ (p0 ) , s1_ (p1 ) , rp0_(rp0) , rp1_(rp1) ``` 4068375e ``` {} ~str_xroxr_node() { rp0_.free(); rp1_.free(); } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { std::size_t r0_0 = 0; std::size_t r0_1 = 0; std::size_t r1_0 = 0; std::size_t r1_1 = 0; if ( rp0_(r0_0, r1_0, s0_.size()) && rp1_(r0_1, r1_1, s1_.size()) ) { return Operation::process( s0_.substr(r0_0, (r1_0 - r0_0) + 1), s1_.substr(r0_1, (r1_1 - r0_1) + 1) ); } else return T(0); } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return Operation::type(); } ``` a65c8e8b ``` inline operator_type operation() const exprtk_override ``` 4068375e ``` { return Operation::operation(); } inline std::string& s0() { return s0_; } inline std::string& s1() { return s1_; } protected: SType0 s0_; SType1 s1_; RangePack rp0_; RangePack rp1_; private: ``` a65c8e8b ``` str_xroxr_node(const node_type&) exprtk_delete; node_type& operator=(const node_type&) exprtk_delete; ``` 4068375e ``` }; template ``` a65c8e8b ``` class str_sogens_node exprtk_final : public binary_node ``` 4068375e ``` { public: typedef expression_node * expression_ptr; ``` a65c8e8b ``` typedef string_base_node* str_base_ptr; typedef range_pack range_t; typedef range_t* range_ptr; typedef range_interface irange_t; typedef irange_t* irange_ptr; ``` 4068375e ``` str_sogens_node(const operator_type& opr, expression_ptr branch0, expression_ptr branch1) ``` a65c8e8b ``` : binary_node(opr, branch0, branch1) , str0_base_ptr_ (0) , str1_base_ptr_ (0) , str0_range_ptr_(0) , str1_range_ptr_(0) ``` 4068375e ``` { if (is_generally_string_node(binary_node::branch_[0].first)) { str0_base_ptr_ = dynamic_cast(binary_node::branch_[0].first); if (0 == str0_base_ptr_) return; irange_ptr range = dynamic_cast(binary_node::branch_[0].first); if (0 == range) return; str0_range_ptr_ = &(range->range_ref()); } if (is_generally_string_node(binary_node::branch_[1].first)) { str1_base_ptr_ = dynamic_cast(binary_node::branch_[1].first); if (0 == str1_base_ptr_) return; irange_ptr range = dynamic_cast(binary_node::branch_[1].first); if (0 == range) return; str1_range_ptr_ = &(range->range_ref()); } } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { if ( str0_base_ptr_ && str1_base_ptr_ && str0_range_ptr_ && str1_range_ptr_ ) { binary_node::branch_[0].first->value(); binary_node::branch_[1].first->value(); std::size_t str0_r0 = 0; std::size_t str0_r1 = 0; std::size_t str1_r0 = 0; std::size_t str1_r1 = 0; ``` a65c8e8b ``` const range_t& range0 = (*str0_range_ptr_); const range_t& range1 = (*str1_range_ptr_); ``` 4068375e ``` if ( range0(str0_r0, str0_r1, str0_base_ptr_->size()) && range1(str1_r0, str1_r1, str1_base_ptr_->size()) ) { return Operation::process( str0_base_ptr_->str().substr(str0_r0,(str0_r1 - str0_r0) + 1), str1_base_ptr_->str().substr(str1_r0,(str1_r1 - str1_r0) + 1) ); } } return std::numeric_limits::quiet_NaN(); } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return Operation::type(); } private: ``` a65c8e8b ``` str_sogens_node(const str_sogens_node&) exprtk_delete; str_sogens_node& operator=(const str_sogens_node&) exprtk_delete; ``` 4068375e ``` str_base_ptr str0_base_ptr_; str_base_ptr str1_base_ptr_; range_ptr str0_range_ptr_; range_ptr str1_range_ptr_; }; template ``` a65c8e8b ``` class sosos_node exprtk_final : public sosos_base_node ``` 4068375e ``` { public: typedef expression_node* expression_ptr; typedef Operation operation_t; ``` a65c8e8b ``` typedef sosos_node node_type; ``` 4068375e ``` // variable op variable node explicit sosos_node(SType0 p0, SType1 p1, SType2 p2) ``` a65c8e8b ``` : s0_(p0) , s1_(p1) , s2_(p2) ``` 4068375e ``` {} ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { ``` a65c8e8b ``` return Operation::process(s0_, s1_, s2_); ``` 4068375e ``` } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return Operation::type(); } ``` a65c8e8b ``` inline operator_type operation() const exprtk_override ``` 4068375e ``` { return Operation::operation(); } inline std::string& s0() { return s0_; } inline std::string& s1() { return s1_; } inline std::string& s2() { return s2_; } protected: SType0 s0_; SType1 s1_; SType2 s2_; private: ``` a65c8e8b ``` sosos_node(const node_type&) exprtk_delete; node_type& operator=(const node_type&) exprtk_delete; ``` 4068375e ``` }; #endif template ``` a65c8e8b ``` class ipow_node exprtk_final: public expression_node ``` 4068375e ``` { public: typedef expression_node* expression_ptr; typedef PowOp operation_t; explicit ipow_node(const T& v) : v_(v) {} ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { return PowOp::result(v_); } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_ipow; } private: ``` a65c8e8b ``` ipow_node(const ipow_node&) exprtk_delete; ipow_node& operator=(const ipow_node&) exprtk_delete; ``` 4068375e ``` const T& v_; }; template ``` a65c8e8b ``` class bipow_node exprtk_final : public expression_node ``` 4068375e ``` { public: typedef expression_node* expression_ptr; typedef std::pair branch_t; typedef PowOp operation_t; explicit bipow_node(expression_ptr branch) { construct_branch_pair(branch_, branch); } ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { ``` a65c8e8b ``` assert(branch_.first); ``` 4068375e ``` return PowOp::result(branch_.first->value()); } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_ipow; } ``` a65c8e8b ``` void collect_nodes(typename expression_node::noderef_list_t& node_delete_list) exprtk_override ``` 4068375e ``` { expression_node::ndb_t::collect(branch_, node_delete_list); } ``` a65c8e8b ``` std::size_t node_depth() const exprtk_override ``` 4068375e ``` { return expression_node::ndb_t::compute_node_depth(branch_); } private: ``` a65c8e8b ``` bipow_node(const bipow_node&) exprtk_delete; bipow_node& operator=(const bipow_node&) exprtk_delete; ``` 4068375e ``` branch_t branch_; }; template ``` a65c8e8b ``` class ipowinv_node exprtk_final : public expression_node ``` 4068375e ``` { public: typedef expression_node* expression_ptr; typedef PowOp operation_t; explicit ipowinv_node(const T& v) : v_(v) {} ``` a65c8e8b ``` inline T value() const exprtk_override ``` 4068375e ``` { return (T(1) / PowOp::result(v_)); } ``` a65c8e8b ``` inline typename expression_node::node_type type() const exprtk_override ``` 4068375e ``` { return expression_node::e_ipowinv; } private: ``` a65c8e8b ``` ipowinv_node(const ipowinv_node&) exprtk_delete; ipowinv_node& operator=(const ipowinv_node&) exprtk_delete; ``` 4068375e ``` const T& v_; }; template ``` a65c8e8b ``` class bipowninv_node exprtk_final : public expression_node ``` 4068375e ``` { public: typedef expression_node* expression_ptr; typedef std::pair branch_t; typedef PowOp operation_t; explicit bipowninv_node(expression_ptr branch) { construct_branch_pair(branch_, branch); } ```