00000 | /* 00001 | ****************************************************************** 00002 | * C++ Mathematical Expression Toolkit Library * 00003 | * * 00004 | * Author: Arash Partow (1999-2025) * 00005 | * URL: https://www.partow.net/programming/exprtk/index.html * 00006 | * * 00007 | * Copyright notice: * 00008 | * Free use of the C++ Mathematical Expression Toolkit Library is * 00009 | * permitted under the guidelines and in accordance with the most * 00010 | * current version of the MIT License. * 00011 | * https://www.opensource.org/licenses/MIT * 00012 | * SPDX-License-Identifier: MIT * 00013 | * * 00014 | * Example expressions: * 00015 | * (00) (y + x / y) * (x - y / x) * 00016 | * (01) (x^2 / sin(2 * pi / y)) - x / 2 * 00017 | * (02) sqrt(1 - (x^2)) * 00018 | * (03) 1 - sin(2 * x) + cos(pi / y) * 00019 | * (04) a * exp(2 * t) + c * 00020 | * (05) if(((x + 2) == 3) and ((y + 5) <= 9), 1 + w, 2 / z) * 00021 | * (06) (avg(x,y) <= x + y ? x - y : x * y) + 2 * pi / x * 00022 | * (07) z := x + sin(2 * pi / y) * 00023 | * (08) u := 2 * (pi * z) / (w := x + cos(y / pi)) * 00024 | * (09) clamp(-1, sin(2 * pi * x) + cos(y / 2 * pi), +1) * 00025 | * (10) inrange(-2, m, +2) == if(({-2 <= m} and [m <= +2]), 1, 0) * 00026 | * (11) (2sin(x)cos(2y)7 + 1) == (2 * sin(x) * cos(2*y) * 7 + 1) * 00027 | * (12) (x ilike 's*ri?g') and [y < (3 z^7 + w)] * 00028 | * * 00029 | ****************************************************************** 00030 | */ 00031 | 00032 | 00033 | #ifndef INCLUDE_EXPRTK_HPP 00034 | #define INCLUDE_EXPRTK_HPP 00035 | 00036 | 00037 | #include00038 | #include 00039 | #include 00040 | #include 00041 | #include 00042 | #include 00043 | #include 00044 | #include 00045 | #include 00046 | #include 00047 | #include 00048 | #include 00049 | #include 00050 | #include
00051 | #include 00052 | #include 00053 | #include 00054 | #include 00055 | #include 00056 | 00057 | 00058 | namespace exprtk 00059 | { 00060 | #ifdef exprtk_enable_debugging 00061 | #define exprtk_debug(params) printf params 00062 | #else 00063 | #define exprtk_debug(params) (void)0 00064 | #endif 00065 | 00066 | #define exprtk_error_location \ 00067 | "exprtk.hpp:" + details::to_str(__LINE__) \ 00068 | 00069 | #if __cplusplus >= 201103L 00070 | #define exprtk_override override 00071 | #define exprtk_final final 00072 | #define exprtk_delete = delete 00073 | #else 00074 | #define exprtk_override 00075 | #define exprtk_final 00076 | #define exprtk_delete 00077 | #endif 00078 | 00079 | #if __cplusplus >= 201603L 00080 | #define exprtk_fallthrough [[fallthrough]]; 00081 | #elif (__cplusplus >= 201103L) && (defined(__GNUC__) && !defined(__clang__)) 00082 | #define exprtk_fallthrough [[gnu::fallthrough]]; 00083 | #else 00084 | #ifndef _MSC_VER 00085 | #define exprtk_fallthrough __attribute__ ((fallthrough)); 00086 | #else 00087 | #define exprtk_fallthrough 00088 | #endif 00089 | #endif 00090 | 00091 | namespace details 00092 | { 00093 | typedef char char_t; 00094 | typedef char_t* char_ptr; 00095 | typedef char_t const* char_cptr; 00096 | typedef unsigned char uchar_t; 00097 | typedef uchar_t* uchar_ptr; 00098 | typedef uchar_t const* uchar_cptr; 00099 | typedef unsigned long long int _uint64_t; 00100 | typedef long long int _int64_t; 00101 | 00102 | inline bool is_whitespace(const char_t c) 00103 | { 00104 | return (' ' == c) || ('\n' == c) || 00105 | ('\r' == c) || ('\t' == c) || 00106 | ('\b' == c) || ('\v' == c) || 00107 | ('\f' == c) ; 00108 | } 00109 | 00110 | inline bool is_operator_char(const char_t c) 00111 | { 00112 | return ('+' == c) || ('-' == c) || 00113 | ('*' == c) || ('/' == c) || 00114 | ('^' == c) || ('<' == c) || 00115 | ('>' == c) || ('=' == c) || 00116 | (',' == c) || ('!' == c) || 00117 | ('(' == c) || (')' == c) || 00118 | ('[' == c) || (']' == c) || 00119 | ('{' == c) || ('}' == c) || 00120 | ('%' == c) || (':' == c) || 00121 | ('?' == c) || ('&' == c) || 00122 | ('|' == c) || (';' == c) ; 00123 | } 00124 | 00125 | inline bool is_letter(const char_t c) 00126 | { 00127 | return (('a' <= c) && (c <= 'z')) || 00128 | (('A' <= c) && (c <= 'Z')) ; 00129 | } 00130 | 00131 | inline bool is_digit(const char_t c) 00132 | { 00133 | return ('0' <= c) && (c <= '9'); 00134 | } 00135 | 00136 | inline bool is_letter_or_digit(const char_t c) 00137 | { 00138 | return is_letter(c) || is_digit(c); 00139 | } 00140 | 00141 | inline bool is_left_bracket(const char_t c) 00142 | { 00143 | return ('(' == c) || ('[' == c) || ('{' == c); 00144 | } 00145 | 00146 | inline bool is_right_bracket(const char_t c) 00147 | { 00148 | return (')' == c) || (']' == c) || ('}' == c); 00149 | } 00150 | 00151 | inline bool is_bracket(const char_t c) 00152 | { 00153 | return is_left_bracket(c) || is_right_bracket(c); 00154 | } 00155 | 00156 | inline bool is_sign(const char_t c) 00157 | { 00158 | return ('+' == c) || ('-' == c); 00159 | } 00160 | 00161 | inline bool is_invalid(const char_t c) 00162 | { 00163 | return !is_whitespace (c) && 00164 | !is_operator_char(c) && 00165 | !is_letter (c) && 00166 | !is_digit (c) && 00167 | ('.' != c) && 00168 | ('_' != c) && 00169 | ('$' != c) && 00170 | ('~' != c) && 00171 | ('\'' != c); 00172 | } 00173 | 00174 | inline bool is_valid_string_char(const char_t c) 00175 | { 00176 | return std::isprint(static_cast<uchar_t>(c)) || 00177 | is_whitespace(c); 00178 | } 00179 | 00180 | #ifndef exprtk_disable_caseinsensitivity 00181 | inline void case_normalise(std::string& s) 00182 | { 00183 | for (std::size_t i = 0; i < s.size(); ++i) 00184 | { 00185 | s[i] = static_cast<std::string::value_type>(std::tolower(s[i])); 00186 | } 00187 | } 00188 | 00189 | inline bool imatch(const char_t c1, const char_t c2) 00190 | { 00191 | return std::tolower(c1) == std::tolower(c2); 00192 | } 00193 | 00194 | inline bool imatch(const std::string& s1, const std::string& s2) 00195 | { 00196 | if (s1.size() == s2.size()) 00197 | { 00198 | for (std::size_t i = 0; i < s1.size(); ++i) 00199 | { 00200 | if (std::tolower(s1[i]) != std::tolower(s2[i])) 00201 | { 00202 | return false; 00203 | } 00204 | } 00205 | 00206 | return true; 00207 | } 00208 | 00209 | return false; 00210 | } 00211 | 00212 | struct ilesscompare 00213 | { 00214 | inline bool operator() (const std::string& s1, const std::string& s2) const 00215 | { 00216 | const std::size_t length = std::min(s1.size(),s2.size()); 00217 | 00218 | for (std::size_t i = 0; i < length; ++i) 00219 | { 00220 | const char_t c1 = static_cast<char_t>(std::tolower(s1[i])); 00221 | const char_t c2 = static_cast<char_t>(std::tolower(s2[i])); 00222 | 00223 | if (c1 < c2) 00224 | return true; 00225 | else if (c2 < c1) 00226 | return false; 00227 | } 00228 | 00229 | return s1.size() < s2.size(); 00230 | } 00231 | }; 00232 | 00233 | #else 00234 | inline void case_normalise(std::string&) 00235 | {} 00236 | 00237 | inline bool imatch(const char_t c1, const char_t c2) 00238 | { 00239 | return c1 == c2; 00240 | } 00241 | 00242 | inline bool imatch(const std::string& s1, const std::string& s2) 00243 | { 00244 | return s1 == s2; 00245 | } 00246 | 00247 | struct ilesscompare 00248 | { 00249 | inline bool operator() (const std::string& s1, const std::string& s2) const 00250 | { 00251 | return s1 < s2; 00252 | } 00253 | }; 00254 | #endif 00255 | 00256 | inline bool is_valid_sf_symbol(const std::string& symbol) 00257 | { 00258 | // Special function: $f12 or $F34 00259 | return (4 == symbol.size()) && 00260 | ('$' == symbol[0]) && 00261 | imatch('f',symbol[1]) && 00262 | is_digit(symbol[2]) && 00263 | is_digit(symbol[3]); 00264 | } 00265 | 00266 | inline const char_t& front(const std::string& s) 00267 | { 00268 | return s[0]; 00269 | } 00270 | 00271 | inline const char_t& back(const std::string& s) 00272 | { 00273 | return s[s.size() - 1]; 00274 | } 00275 | 00276 | template <typename SignedType> 00277 | inline std::string to_str_impl(SignedType i) 00278 | { 00279 | if (0 == i) 00280 | return std::string("0"); 00281 | 00282 | std::string result; 00283 | 00284 | const int sign = (i < 0) ? -1 : 1; 00285 | 00286 | for ( ; i; i /= 10) 00287 | { 00288 | result += '0' + static_cast<char_t>(sign * (i % 10)); 00289 | } 00290 | 00291 | if (sign < 0) 00292 | { 00293 | result += '-'; 00294 | } 00295 | 00296 | std::reverse(result.begin(), result.end()); 00297 | 00298 | return result; 00299 | } 00300 | 00301 | inline std::string to_str(int i) 00302 | { 00303 | return to_str_impl(i); 00304 | } 00305 | 00306 | inline std::string to_str(std::size_t i) 00307 | { 00308 | return to_str_impl(static_cast<long long int>(i)); 00309 | } 00310 | 00311 | inline bool is_hex_digit(const uchar_t digit) 00312 | { 00313 | return (('0' <= digit) && (digit <= '9')) || 00314 | (('A' <= digit) && (digit <= 'F')) || 00315 | (('a' <= digit) && (digit <= 'f')) ; 00316 | } 00317 | 00318 | inline uchar_t hex_to_bin(uchar_t h) 00319 | { 00320 | if (('0' <= h) && (h <= '9')) 00321 | return (h - '0'); 00322 | else 00323 | return static_cast<uchar_t>(std::toupper(h) - 'A' + 10); 00324 | } 00325 | 00326 | template <typename Iterator> 00327 | inline bool parse_hex(Iterator& itr, Iterator end, 00328 | char_t& result) 00329 | { 00330 | if ( 00331 | (end == (itr )) || 00332 | (end == (itr + 1)) || 00333 | (end == (itr + 2)) || 00334 | (end == (itr + 3)) || 00335 | ('0' != *(itr )) || 00336 | ('X' != std::toupper(*(itr + 1))) || 00337 | (!is_hex_digit(*(itr + 2))) || 00338 | (!is_hex_digit(*(itr + 3))) 00339 | ) 00340 | { 00341 | return false; 00342 | } 00343 | 00344 | result = static_cast<char_t>( 00345 | hex_to_bin(static_cast<uchar_t>(*(itr + 2))) << 4 | 00346 | hex_to_bin(static_cast<uchar_t>(*(itr + 3)))) ; 00347 | 00348 | return true; 00349 | } 00350 | 00351 | inline bool cleanup_escapes(std::string& s) 00352 | { 00353 | typedef std::string::iterator str_itr_t; 00354 | 00355 | str_itr_t itr1 = s.begin(); 00356 | str_itr_t itr2 = s.begin(); 00357 | str_itr_t end = s.end (); 00358 | 00359 | std::size_t removal_count = 0; 00360 | 00361 | while (end != itr1) 00362 | { 00363 | if ('\\' == (*itr1)) 00364 | { 00365 | if (end == ++itr1) 00366 | { 00367 | return false; 00368 | } 00369 | else if (parse_hex(itr1, end, *itr2)) 00370 | { 00371 | itr1 += 4; 00372 | itr2 += 1; 00373 | removal_count += 4; 00374 | } 00375 | else if ('a' == (*itr1)) { (*itr2++) = '\a'; ++itr1; ++removal_count; } 00376 | else if ('b' == (*itr1)) { (*itr2++) = '\b'; ++itr1; ++removal_count; } 00377 | else if ('f' == (*itr1)) { (*itr2++) = '\f'; ++itr1; ++removal_count; } 00378 | else if ('n' == (*itr1)) { (*itr2++) = '\n'; ++itr1; ++removal_count; } 00379 | else if ('r' == (*itr1)) { (*itr2++) = '\r'; ++itr1; ++removal_count; } 00380 | else if ('t' == (*itr1)) { (*itr2++) = '\t'; ++itr1; ++removal_count; } 00381 | else if ('v' == (*itr1)) { (*itr2++) = '\v'; ++itr1; ++removal_count; } 00382 | else if ('0' == (*itr1)) { (*itr2++) = '\0'; ++itr1; ++removal_count; } 00383 | else 00384 | { 00385 | (*itr2++) = (*itr1++); 00386 | ++removal_count; 00387 | } 00388 | 00389 | continue; 00390 | } 00391 | else 00392 | (*itr2++) = (*itr1++); 00393 | } 00394 | 00395 | if ((removal_count > s.size()) || (0 == removal_count)) 00396 | return false; 00397 | 00398 | s.resize(s.size() - removal_count); 00399 | 00400 | return true; 00401 | } 00402 | 00403 | class build_string 00404 | { 00405 | public: 00406 | 00407 | explicit build_string(const std::size_t& initial_size = 64) 00408 | { 00409 | data_.reserve(initial_size); 00410 | } 00411 | 00412 | inline build_string& operator << (const std::string& s) 00413 | { 00414 | data_ += s; 00415 | return (*this); 00416 | } 00417 | 00418 | inline build_string& operator << (char_cptr s) 00419 | { 00420 | data_ += std::string(s); 00421 | return (*this); 00422 | } 00423 | 00424 | inline operator std::string () const 00425 | { 00426 | return data_; 00427 | } 00428 | 00429 | inline std::string as_string() const 00430 | { 00431 | return data_; 00432 | } 00433 | 00434 | private: 00435 | 00436 | std::string data_; 00437 | }; 00438 | 00439 | static const std::string reserved_words[] = 00440 | { 00441 | "assert", "break", "case", "continue", "const", "default", 00442 | "false", "for", "if", "else", "ilike", "in", "like", "and", 00443 | "nand", "nor", "not", "null", "or", "repeat", "return", 00444 | "shl", "shr", "swap", "switch", "true", "until", "var", 00445 | "while", "xnor", "xor", "&", "|" 00446 | }; 00447 | 00448 | static const std::size_t reserved_words_size = sizeof(reserved_words) / sizeof(std::string); 00449 | 00450 | static const std::string reserved_symbols[] = 00451 | { 00452 | "abs", "acos", "acosh", "and", "asin", "asinh", "assert", 00453 | "atan", "atanh", "atan2", "avg", "break", "case", "ceil", 00454 | "clamp", "continue", "const", "cos", "cosh", "cot", "csc", 00455 | "default", "deg2grad", "deg2rad", "equal", "erf", "erfc", 00456 | "exp", "expm1", "false", "floor", "for", "frac", "grad2deg", 00457 | "hypot", "iclamp", "if", "else", "ilike", "in", "inrange", 00458 | "like", "log", "log10", "log2", "logn", "log1p", "mand", 00459 | "max", "min", "mod", "mor", "mul", "ncdf", "nand", "nor", 00460 | "not", "not_equal", "null", "or", "pow", "rad2deg", 00461 | "repeat", "return", "root", "round", "roundn", "sec", "sgn", 00462 | "shl", "shr", "sin", "sinc", "sinh", "sqrt", "sum", "swap", 00463 | "switch", "tan", "tanh", "true", "trunc", "until", "var", 00464 | "while", "xnor", "xor", "&", "|" 00465 | }; 00466 | 00467 | static const std::size_t reserved_symbols_size = sizeof(reserved_symbols) / sizeof(std::string); 00468 | 00469 | static const std::string base_function_list[] = 00470 | { 00471 | "abs", "acos", "acosh", "asin", "asinh", "atan", "atanh", 00472 | "atan2", "avg", "ceil", "clamp", "cos", "cosh", "cot", 00473 | "csc", "equal", "erf", "erfc", "exp", "expm1", "floor", 00474 | "frac", "hypot", "iclamp", "like", "log", "log10", "log2", 00475 | "logn", "log1p", "mand", "max", "min", "mod", "mor", "mul", 00476 | "ncdf", "pow", "root", "round", "roundn", "sec", "sgn", 00477 | "sin", "sinc", "sinh", "sqrt", "sum", "swap", "tan", "tanh", 00478 | "trunc", "not_equal", "inrange", "deg2grad", "deg2rad", 00479 | "rad2deg", "grad2deg" 00480 | }; 00481 | 00482 | static const std::size_t base_function_list_size = sizeof(base_function_list) / sizeof(std::string); 00483 | 00484 | static const std::string logic_ops_list[] = 00485 | { 00486 | "and", "nand", "nor", "not", "or", "xnor", "xor", "&", "|" 00487 | }; 00488 | 00489 | static const std::size_t logic_ops_list_size = sizeof(logic_ops_list) / sizeof(std::string); 00490 | 00491 | static const std::string cntrl_struct_list[] = 00492 | { 00493 | "if", "switch", "for", "while", "repeat", "return" 00494 | }; 00495 | 00496 | static const std::size_t cntrl_struct_list_size = sizeof(cntrl_struct_list) / sizeof(std::string); 00497 | 00498 | static const std::string arithmetic_ops_list[] = 00499 | { 00500 | "+", "-", "*", "/", "%", "^" 00501 | }; 00502 | 00503 | static const std::size_t arithmetic_ops_list_size = sizeof(arithmetic_ops_list) / sizeof(std::string); 00504 | 00505 | static const std::string assignment_ops_list[] = 00506 | { 00507 | ":=", "+=", "-=", 00508 | "*=", "/=", "%=" 00509 | }; 00510 | 00511 | static const std::size_t assignment_ops_list_size = sizeof(assignment_ops_list) / sizeof(std::string); 00512 | 00513 | static const std::string inequality_ops_list[] = 00514 | { 00515 | "<", "<=", "==", 00516 | "=", "!=", "<>", 00517 | ">=", ">" 00518 | }; 00519 | 00520 | static const std::size_t inequality_ops_list_size = sizeof(inequality_ops_list) / sizeof(std::string); 00521 | 00522 | inline bool is_reserved_word(const std::string& symbol) 00523 | { 00524 | for (std::size_t i = 0; i < reserved_words_size; ++i) 00525 | { 00526 | if (imatch(symbol, reserved_words[i])) 00527 | { 00528 | return true; 00529 | } 00530 | } 00531 | 00532 | return false; 00533 | } 00534 | 00535 | inline bool is_reserved_symbol(const std::string& symbol) 00536 | { 00537 | for (std::size_t i = 0; i < reserved_symbols_size; ++i) 00538 | { 00539 | if (imatch(symbol, reserved_symbols[i])) 00540 | { 00541 | return true; 00542 | } 00543 | } 00544 | 00545 | return false; 00546 | } 00547 | 00548 | inline bool is_base_function(const std::string& function_name) 00549 | { 00550 | for (std::size_t i = 0; i < base_function_list_size; ++i) 00551 | { 00552 | if (imatch(function_name, base_function_list[i])) 00553 | { 00554 | return true; 00555 | } 00556 | } 00557 | 00558 | return false; 00559 | } 00560 | 00561 | inline bool is_control_struct(const std::string& cntrl_strct) 00562 | { 00563 | for (std::size_t i = 0; i < cntrl_struct_list_size; ++i) 00564 | { 00565 | if (imatch(cntrl_strct, cntrl_struct_list[i])) 00566 | { 00567 | return true; 00568 | } 00569 | } 00570 | 00571 | return false; 00572 | } 00573 | 00574 | inline bool is_logic_opr(const std::string& lgc_opr) 00575 | { 00576 | for (std::size_t i = 0; i < logic_ops_list_size; ++i) 00577 | { 00578 | if (imatch(lgc_opr, logic_ops_list[i])) 00579 | { 00580 | return true; 00581 | } 00582 | } 00583 | 00584 | return false; 00585 | } 00586 | 00587 | struct cs_match 00588 | { 00589 | static inline bool cmp(const char_t c0, const char_t c1) 00590 | { 00591 | return (c0 == c1); 00592 | } 00593 | }; 00594 | 00595 | struct cis_match 00596 | { 00597 | static inline bool cmp(const char_t c0, const char_t c1) 00598 | { 00599 | return (std::tolower(c0) == std::tolower(c1)); 00600 | } 00601 | }; 00602 | 00603 | template <typename Iterator, typename Compare> 00604 | inline bool match_impl(const Iterator pattern_begin, 00605 | const Iterator pattern_end , 00606 | const Iterator data_begin , 00607 | const Iterator data_end , 00608 | const typename std::iterator_traits<Iterator>::value_type& zero_or_more, 00609 | const typename std::iterator_traits<Iterator>::value_type& exactly_one ) 00610 | { 00611 | typedef typename std::iterator_traits<Iterator>::value_type type; 00612 | 00613 | const Iterator null_itr(0); 00614 | 00615 | Iterator p_itr = pattern_begin; 00616 | Iterator d_itr = data_begin; 00617 | Iterator np_itr = null_itr; 00618 | Iterator nd_itr = null_itr; 00619 | 00620 | for ( ; ; ) 00621 | { 00622 | if (p_itr != pattern_end) 00623 | { 00624 | const type c = *(p_itr); 00625 | 00626 | if ((data_end != d_itr) && (Compare::cmp(c,*(d_itr)) || (exactly_one == c))) 00627 | { 00628 | ++d_itr; 00629 | ++p_itr; 00630 | continue; 00631 | } 00632 | else if (zero_or_more == c) 00633 | { 00634 | while ((pattern_end != p_itr) && (zero_or_more == *(p_itr))) 00635 | { 00636 | ++p_itr; 00637 | } 00638 | 00639 | const type d = *(p_itr); 00640 | 00641 | while ((data_end != d_itr) && !(Compare::cmp(d,*(d_itr)) || (exactly_one == d))) 00642 | { 00643 | ++d_itr; 00644 | } 00645 | 00646 | // set backtrack iterators 00647 | np_itr = p_itr - 1; 00648 | nd_itr = d_itr + 1; 00649 | 00650 | continue; 00651 | } 00652 | } 00653 | else if (data_end == d_itr) 00654 | break; 00655 | 00656 | if ((data_end == d_itr) || (null_itr == nd_itr)) 00657 | return false; 00658 | 00659 | p_itr = np_itr; 00660 | d_itr = nd_itr; 00661 | } 00662 | 00663 | return true; 00664 | } 00665 | 00666 | inline bool wc_match(const std::string& wild_card, 00667 | const std::string& str) 00668 | { 00669 | return match_impl<char_cptr,cs_match> 00670 | ( 00671 | wild_card.data(), 00672 | wild_card.data() + wild_card.size(), 00673 | str.data(), 00674 | str.data() + str.size(), 00675 | '*', '?' 00676 | ); 00677 | } 00678 | 00679 | inline bool wc_imatch(const std::string& wild_card, 00680 | const std::string& str) 00681 | { 00682 | return match_impl<char_cptr,cis_match> 00683 | ( 00684 | wild_card.data(), 00685 | wild_card.data() + wild_card.size(), 00686 | str.data(), 00687 | str.data() + str.size(), 00688 | '*', '?' 00689 | ); 00690 | } 00691 | 00692 | inline bool sequence_match(const std::string& pattern, 00693 | const std::string& str, 00694 | std::size_t& diff_index, 00695 | char_t& diff_value) 00696 | { 00697 | if (str.empty()) 00698 | { 00699 | return ("Z" == pattern); 00700 | } 00701 | else if ('*' == pattern[0]) 00702 | return false; 00703 | 00704 | typedef std::string::const_iterator itr_t; 00705 | 00706 | itr_t p_itr = pattern.begin(); 00707 | itr_t s_itr = str .begin(); 00708 | 00709 | const itr_t p_end = pattern.end(); 00710 | const itr_t s_end = str .end(); 00711 | 00712 | while ((s_end != s_itr) && (p_end != p_itr)) 00713 | { 00714 | if ('*' == (*p_itr)) 00715 | { 00716 | const char_t target = static_cast<char_t>(std::toupper(*(p_itr - 1))); 00717 | 00718 | if ('*' == target) 00719 | { 00720 | diff_index = static_cast<std::size_t>(std::distance(str.begin(),s_itr)); 00721 | diff_value = static_cast<char_t>(std::toupper(*p_itr)); 00722 | 00723 | return false; 00724 | } 00725 | else 00726 | ++p_itr; 00727 | 00728 | while (s_itr != s_end) 00729 | { 00730 | if (target != std::toupper(*s_itr)) 00731 | break; 00732 | else 00733 | ++s_itr; 00734 | } 00735 | 00736 | continue; 00737 | } 00738 | else if ( 00739 | ('?' != *p_itr) && 00740 | std::toupper(*p_itr) != std::toupper(*s_itr) 00741 | ) 00742 | { 00743 | diff_index = static_cast<std::size_t>(std::distance(str.begin(),s_itr)); 00744 | diff_value = static_cast<char_t>(std::toupper(*p_itr)); 00745 | 00746 | return false; 00747 | } 00748 | 00749 | ++p_itr; 00750 | ++s_itr; 00751 | } 00752 | 00753 | return ( 00754 | (s_end == s_itr) && 00755 | ( 00756 | (p_end == p_itr) || 00757 | ('*' == *p_itr) 00758 | ) 00759 | ); 00760 | } 00761 | 00762 | template<typename T> 00763 | struct set_zero_value_impl 00764 | { 00765 | static inline void process(T* base_ptr, const std::size_t size) 00766 | { 00767 | const T zero = T(0); 00768 | for (std::size_t i = 0; i < size; ++i) 00769 | { 00770 | base_ptr[i] = zero; 00771 | } 00772 | } 00773 | }; 00774 | 00775 | #define pod_set_zero_value(T) \ 00776 | template <> \ 00777 | struct set_zero_value_impl<T> \ 00778 | { \ 00779 | static inline void process(T* base_ptr, const std::size_t size) \ 00780 | { std::memset(base_ptr, 0x00, size * sizeof(T)); } \ 00781 | }; \ 00782 | 00783 | pod_set_zero_value(float ) 00784 | pod_set_zero_value(double ) 00785 | pod_set_zero_value(long double) 00786 | 00787 | #ifdef pod_set_zero_value 00788 | #undef pod_set_zero_value 00789 | #endif 00790 | 00791 | template<typename T> 00792 | inline void set_zero_value(T* data, const std::size_t size) 00793 | { 00794 | set_zero_value_impl<T>::process(data,size); 00795 | } 00796 | 00797 | template<typename T> 00798 | inline void set_zero_value(std::vector<T>& v) 00799 | { 00800 | set_zero_value(v.data(),v.size()); 00801 | } 00802 | 00803 | static const double pow10[] = 00804 | { 00805 | 1.0, 00806 | 1.0E+001, 1.0E+002, 1.0E+003, 1.0E+004, 00807 | 1.0E+005, 1.0E+006, 1.0E+007, 1.0E+008, 00808 | 1.0E+009, 1.0E+010, 1.0E+011, 1.0E+012, 00809 | 1.0E+013, 1.0E+014, 1.0E+015, 1.0E+016 00810 | }; 00811 | 00812 | static const std::size_t pow10_size = sizeof(pow10) / sizeof(double); 00813 | 00814 | namespace numeric 00815 | { 00816 | namespace constant 00817 | { 00818 | static const double e = 2.71828182845904523536028747135266249775724709369996; 00819 | static const double pi = 3.14159265358979323846264338327950288419716939937510; 00820 | static const double pi_2 = 1.57079632679489661923132169163975144209858469968755; 00821 | static const double pi_4 = 0.78539816339744830961566084581987572104929234984378; 00822 | static const double pi_180 = 0.01745329251994329576923690768488612713442871888542; 00823 | static const double _1_pi = 0.31830988618379067153776752674502872406891929148091; 00824 | static const double _2_pi = 0.63661977236758134307553505349005744813783858296183; 00825 | static const double _180_pi = 57.29577951308232087679815481410517033240547246656443; 00826 | static const double log2 = 0.69314718055994530941723212145817656807550013436026; 00827 | static const double sqrt2 = 1.41421356237309504880168872420969807856967187537695; 00828 | } 00829 | 00830 | namespace details 00831 | { 00832 | struct unknown_type_tag { unknown_type_tag() {} }; 00833 | struct real_type_tag { real_type_tag () {} }; 00834 | struct int_type_tag { int_type_tag () {} }; 00835 | 00836 | template <typename T> 00837 | struct number_type 00838 | { 00839 | typedef unknown_type_tag type; 00840 | number_type() {} 00841 | }; 00842 | 00843 | #define exprtk_register_real_type_tag(T) \ 00844 | template <> struct number_type<T> \ 00845 | { typedef real_type_tag type; number_type() {} }; \ 00846 | 00847 | #define exprtk_register_int_type_tag(T) \ 00848 | template <> struct number_type<T> \ 00849 | { typedef int_type_tag type; number_type() {} }; \ 00850 | 00851 | exprtk_register_real_type_tag(float ) 00852 | exprtk_register_real_type_tag(double ) 00853 | exprtk_register_real_type_tag(long double) 00854 | 00855 | exprtk_register_int_type_tag(short ) 00856 | exprtk_register_int_type_tag(int ) 00857 | exprtk_register_int_type_tag(_int64_t ) 00858 | exprtk_register_int_type_tag(unsigned short) 00859 | exprtk_register_int_type_tag(unsigned int ) 00860 | exprtk_register_int_type_tag(_uint64_t ) 00861 | 00862 | #undef exprtk_register_real_type_tag 00863 | #undef exprtk_register_int_type_tag 00864 | 00865 | template <typename T> 00866 | struct epsilon_type {}; 00867 | 00868 | #define exprtk_define_epsilon_type(Type, Epsilon) \ 00869 | template <> struct epsilon_type<Type> \ 00870 | { \ 00871 | static inline Type value() \ 00872 | { \ 00873 | const Type epsilon = static_cast<Type>(Epsilon); \ 00874 | return epsilon; \ 00875 | } \ 00876 | }; \ 00877 | 00878 | exprtk_define_epsilon_type(float , 0.00000100000f) 00879 | exprtk_define_epsilon_type(double , 0.000000000100) 00880 | exprtk_define_epsilon_type(long double, 0.000000000001) 00881 | 00882 | #undef exprtk_define_epsilon_type 00883 | 00884 | template <typename T> 00885 | inline bool is_nan_impl(const T v, real_type_tag) 00886 | { 00887 | return std::not_equal_to<T>()(v,v); 00888 | } 00889 | 00890 | template <typename T> 00891 | inline int to_int32_impl(const T v, real_type_tag) 00892 | { 00893 | return static_cast<int>(v); 00894 | } 00895 | 00896 | template <typename T> 00897 | inline _int64_t to_int64_impl(const T v, real_type_tag) 00898 | { 00899 | return static_cast<_int64_t>(v); 00900 | } 00901 | 00902 | template <typename T> 00903 | inline _uint64_t to_uint64_impl(const T v, real_type_tag) 00904 | { 00905 | return static_cast<_uint64_t>(v); 00906 | } 00907 | 00908 | template <typename T> 00909 | inline bool is_true_impl(const T v) 00910 | { 00911 | return std::not_equal_to<T>()(T(0),v); 00912 | } 00913 | 00914 | template <typename T> 00915 | inline bool is_false_impl(const T v) 00916 | { 00917 | return std::equal_to<T>()(T(0),v); 00918 | } 00919 | 00920 | template <typename T> 00921 | inline T abs_impl(const T v, real_type_tag) 00922 | { 00923 | return ((v < T(0)) ? -v : v); 00924 | } 00925 | 00926 | template <typename T> 00927 | inline T min_impl(const T v0, const T v1, real_type_tag) 00928 | { 00929 | return std::min<T>(v0,v1); 00930 | } 00931 | 00932 | template <typename T> 00933 | inline T max_impl(const T v0, const T v1, real_type_tag) 00934 | { 00935 | return std::max<T>(v0,v1); 00936 | } 00937 | 00938 | template <typename T> 00939 | inline T equal_impl(const T v0, const T v1, real_type_tag) 00940 | { 00941 | const T epsilon = epsilon_type<T>::value(); 00942 | 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); 00943 | } 00944 | 00945 | inline float equal_impl(const float v0, const float v1, real_type_tag) 00946 | { 00947 | const float epsilon = epsilon_type<float>::value(); 00948 | 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; 00949 | } 00950 | 00951 | template <typename T> 00952 | inline T equal_impl(const T v0, const T v1, int_type_tag) 00953 | { 00954 | return (v0 == v1) ? 1 : 0; 00955 | } 00956 | 00957 | template <typename T> 00958 | inline T nequal_impl(const T v0, const T v1, real_type_tag) 00959 | { 00960 | typedef real_type_tag rtg; 00961 | const T epsilon = epsilon_type<T>::value(); 00962 | 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); 00963 | } 00964 | 00965 | inline float nequal_impl(const float v0, const float v1, real_type_tag) 00966 | { 00967 | typedef real_type_tag rtg; 00968 | const float epsilon = epsilon_type<float>::value(); 00969 | 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; 00970 | } 00971 | 00972 | template <typename T> 00973 | inline T nequal_impl(const T v0, const T v1, int_type_tag) 00974 | { 00975 | return (v0 != v1) ? 1 : 0; 00976 | } 00977 | 00978 | template <typename T> 00979 | inline T modulus_impl(const T v0, const T v1, real_type_tag) 00980 | { 00981 | return std::fmod(v0,v1); 00982 | } 00983 | 00984 | template <typename T> 00985 | inline T modulus_impl(const T v0, const T v1, int_type_tag) 00986 | { 00987 | return v0 % v1; 00988 | } 00989 | 00990 | template <typename T> 00991 | inline T pow_impl(const T v0, const T v1, real_type_tag) 00992 | { 00993 | return std::pow(v0,v1); 00994 | } 00995 | 00996 | template <typename T> 00997 | inline T pow_impl(const T v0, const T v1, int_type_tag) 00998 | { 00999 | return std::pow(static_cast<double>(v0),static_cast<double>(v1)); 01000 | } 01001 | 01002 | template <typename T> 01003 | inline T logn_impl(const T v0, const T v1, real_type_tag) 01004 | { 01005 | return std::log(v0) / std::log(v1); 01006 | } 01007 | 01008 | template <typename T> 01009 | inline T logn_impl(const T v0, const T v1, int_type_tag) 01010 | { 01011 | return static_cast<T>(logn_impl<double>(static_cast<double>(v0),static_cast<double>(v1),real_type_tag())); 01012 | } 01013 | 01014 | template <typename T> 01015 | inline T root_impl(const T v0, const T v1, real_type_tag) 01016 | { 01017 | if (v0 < T(0)) 01018 | { 01019 | return (v1 == trunc_impl(v1, real_type_tag())) && 01020 | (modulus_impl(v1, T(2), real_type_tag()) != T(0)) ? 01021 | -std::pow(abs_impl(v0, real_type_tag()), T(1) / v1) : 01022 | std::numeric_limits<T>::quiet_NaN(); 01023 | } 01024 | 01025 | return std::pow(v0, T(1) / v1); 01026 | } 01027 | 01028 | template <typename T> 01029 | inline T root_impl(const T v0, const T v1, int_type_tag) 01030 | { 01031 | return root_impl<double>(static_cast<double>(v0),static_cast<double>(v1),real_type_tag()); 01032 | } 01033 | 01034 | template <typename T> 01035 | inline T round_impl(const T v, real_type_tag) 01036 | { 01037 | return ((v < T(0)) ? std::ceil(v - T(0.5)) : std::floor(v + T(0.5))); 01038 | } 01039 | 01040 | template <typename T> 01041 | inline T roundn_impl(const T v0, const T v1, real_type_tag) 01042 | { 01043 | const int index = std::max<int>(0, std::min<int>(pow10_size - 1, static_cast<int>(std::floor(v1)))); 01044 | const T p10 = T(pow10[index]); 01045 | 01046 | if (v0 < T(0)) 01047 | return T(std::ceil ((v0 * p10) - T(0.5)) / p10); 01048 | else 01049 | return T(std::floor((v0 * p10) + T(0.5)) / p10); 01050 | } 01051 | 01052 | template <typename T> 01053 | inline T roundn_impl(const T v0, const T, int_type_tag) 01054 | { 01055 | return v0; 01056 | } 01057 | 01058 | template <typename T> 01059 | inline T hypot_impl(const T v0, const T v1, real_type_tag) 01060 | { 01061 | return std::sqrt((v0 * v0) + (v1 * v1)); 01062 | } 01063 | 01064 | template <typename T> 01065 | inline T hypot_impl(const T v0, const T v1, int_type_tag) 01066 | { 01067 | return static_cast<T>(std::sqrt(static_cast<double>((v0 * v0) + (v1 * v1)))); 01068 | } 01069 | 01070 | template <typename T> 01071 | inline T atan2_impl(const T v0, const T v1, real_type_tag) 01072 | { 01073 | return std::atan2(v0,v1); 01074 | } 01075 | 01076 | template <typename T> 01077 | inline T atan2_impl(const T, const T, int_type_tag) 01078 | { 01079 | return 0; 01080 | } 01081 | 01082 | template <typename T> 01083 | inline T shr_impl(const T v0, const T v1, real_type_tag) 01084 | { 01085 | return v0 * (T(1) / std::pow(T(2),static_cast<T>(static_cast<int>(v1)))); 01086 | } 01087 | 01088 | template <typename T> 01089 | inline T shr_impl(const T v0, const T v1, int_type_tag) 01090 | { 01091 | return v0 >> v1; 01092 | } 01093 | 01094 | template <typename T> 01095 | inline T shl_impl(const T v0, const T v1, real_type_tag) 01096 | { 01097 | return v0 * std::pow(T(2),static_cast<T>(static_cast<int>(v1))); 01098 | } 01099 | 01100 | template <typename T> 01101 | inline T shl_impl(const T v0, const T v1, int_type_tag) 01102 | { 01103 | return v0 << v1; 01104 | } 01105 | 01106 | template <typename T> 01107 | inline T sgn_impl(const T v, real_type_tag) 01108 | { 01109 | if (v > T(0)) return T(+1); 01110 | else if (v < T(0)) return T(-1); 01111 | else return T( 0); 01112 | } 01113 | 01114 | template <typename T> 01115 | inline T sgn_impl(const T v, int_type_tag) 01116 | { 01117 | if (v > T(0)) return T(+1); 01118 | else if (v < T(0)) return T(-1); 01119 | else return T( 0); 01120 | } 01121 | 01122 | template <typename T> 01123 | inline T and_impl(const T v0, const T v1, real_type_tag) 01124 | { 01125 | return (is_true_impl(v0) && is_true_impl(v1)) ? T(1) : T(0); 01126 | } 01127 | 01128 | template <typename T> 01129 | inline T and_impl(const T v0, const T v1, int_type_tag) 01130 | { 01131 | return v0 && v1; 01132 | } 01133 | 01134 | template <typename T> 01135 | inline T nand_impl(const T v0, const T v1, real_type_tag) 01136 | { 01137 | return (is_false_impl(v0) || is_false_impl(v1)) ? T(1) : T(0); 01138 | } 01139 | 01140 | template <typename T> 01141 | inline T nand_impl(const T v0, const T v1, int_type_tag) 01142 | { 01143 | return !(v0 && v1); 01144 | } 01145 | 01146 | template <typename T> 01147 | inline T or_impl(const T v0, const T v1, real_type_tag) 01148 | { 01149 | return (is_true_impl(v0) || is_true_impl(v1)) ? T(1) : T(0); 01150 | } 01151 | 01152 | template <typename T> 01153 | inline T or_impl(const T v0, const T v1, int_type_tag) 01154 | { 01155 | return (v0 || v1); 01156 | } 01157 | 01158 | template <typename T> 01159 | inline T nor_impl(const T v0, const T v1, real_type_tag) 01160 | { 01161 | return (is_false_impl(v0) && is_false_impl(v1)) ? T(1) : T(0); 01162 | } 01163 | 01164 | template <typename T> 01165 | inline T nor_impl(const T v0, const T v1, int_type_tag) 01166 | { 01167 | return !(v0 || v1); 01168 | } 01169 | 01170 | template <typename T> 01171 | inline T xor_impl(const T v0, const T v1, real_type_tag) 01172 | { 01173 | return (is_false_impl(v0) != is_false_impl(v1)) ? T(1) : T(0); 01174 | } 01175 | 01176 | template <typename T> 01177 | inline T xor_impl(const T v0, const T v1, int_type_tag) 01178 | { 01179 | return v0 ^ v1; 01180 | } 01181 | 01182 | template <typename T> 01183 | inline T xnor_impl(const T v0, const T v1, real_type_tag) 01184 | { 01185 | const bool v0_true = is_true_impl(v0); 01186 | const bool v1_true = is_true_impl(v1); 01187 | 01188 | if ((v0_true && v1_true) || (!v0_true && !v1_true)) 01189 | return T(1); 01190 | else 01191 | return T(0); 01192 | } 01193 | 01194 | template <typename T> 01195 | inline T xnor_impl(const T v0, const T v1, int_type_tag) 01196 | { 01197 | const bool v0_true = is_true_impl(v0); 01198 | const bool v1_true = is_true_impl(v1); 01199 | 01200 | if ((v0_true && v1_true) || (!v0_true && !v1_true)) 01201 | return T(1); 01202 | else 01203 | return T(0); 01204 | } 01205 | 01206 | #if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || !defined(_MSC_VER) 01207 | #define exprtk_define_erf(TT, impl) \ 01208 | inline TT erf_impl(const TT v) { return impl(v); } \ 01209 | 01210 | exprtk_define_erf(float , ::erff) 01211 | exprtk_define_erf(double , ::erf ) 01212 | exprtk_define_erf(long double, ::erfl) 01213 | #undef exprtk_define_erf 01214 | #endif 01215 | 01216 | template <typename T> 01217 | inline T erf_impl(const T v, real_type_tag) 01218 | { 01219 | #if defined(_MSC_VER) && (_MSC_VER < 1900) 01220 | // Credits: Abramowitz & Stegun Equations 7.1.25-28 01221 | static const T c[] = 01222 | { 01223 | T( 1.26551223), T(1.00002368), 01224 | T( 0.37409196), T(0.09678418), 01225 | T(-0.18628806), T(0.27886807), 01226 | T(-1.13520398), T(1.48851587), 01227 | T(-0.82215223), T(0.17087277) 01228 | }; 01229 | 01230 | const T t = T(1) / (T(1) + T(0.5) * abs_impl(v,real_type_tag())); 01231 | 01232 | const T result = T(1) - t * std::exp((-v * v) - 01233 | c[0] + t * (c[1] + t * 01234 | (c[2] + t * (c[3] + t * 01235 | (c[4] + t * (c[5] + t * 01236 | (c[6] + t * (c[7] + t * 01237 | (c[8] + t * (c[9])))))))))); 01238 | 01239 | return (v >= T(0)) ? result : -result; 01240 | #else 01241 | return erf_impl(v); 01242 | #endif 01243 | } 01244 | 01245 | template <typename T> 01246 | inline T erf_impl(const T v, int_type_tag) 01247 | { 01248 | return erf_impl(static_cast<double>(v),real_type_tag()); 01249 | } 01250 | 01251 | #if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || !defined(_MSC_VER) 01252 | #define exprtk_define_erfc(TT, impl) \ 01253 | inline TT erfc_impl(const TT v) { return impl(v); } \ 01254 | 01255 | exprtk_define_erfc(float ,::erfcf) 01256 | exprtk_define_erfc(double ,::erfc ) 01257 | exprtk_define_erfc(long double,::erfcl) 01258 | #undef exprtk_define_erfc 01259 | #endif 01260 | 01261 | template <typename T> 01262 | inline T erfc_impl(const T v, real_type_tag) 01263 | { 01264 | #if defined(_MSC_VER) && (_MSC_VER < 1900) 01265 | return T(1) - erf_impl(v,real_type_tag()); 01266 | #else 01267 | return erfc_impl(v); 01268 | #endif 01269 | } 01270 | 01271 | template <typename T> 01272 | inline T erfc_impl(const T v, int_type_tag) 01273 | { 01274 | return erfc_impl(static_cast<double>(v),real_type_tag()); 01275 | } 01276 | 01277 | template <typename T> 01278 | inline T ncdf_impl(const T v, real_type_tag) 01279 | { 01280 | return T(0.5) * erfc_impl(-(v / T(numeric::constant::sqrt2)),real_type_tag()); 01281 | } 01282 | 01283 | template <typename T> 01284 | inline T ncdf_impl(const T v, int_type_tag) 01285 | { 01286 | return ncdf_impl(static_cast<double>(v),real_type_tag()); 01287 | } 01288 | 01289 | template <typename T> 01290 | inline T sinc_impl(const T v, real_type_tag) 01291 | { 01292 | if (std::abs(v) >= std::numeric_limits<T>::epsilon()) 01293 | return(std::sin(v) / v); 01294 | else 01295 | return T(1); 01296 | } 01297 | 01298 | template <typename T> 01299 | inline T sinc_impl(const T v, int_type_tag) 01300 | { 01301 | return sinc_impl(static_cast<double>(v),real_type_tag()); 01302 | } 01303 | 01304 | #if __cplusplus >= 201103L 01305 | template <typename T> 01306 | inline T acosh_impl(const T v, real_type_tag) 01307 | { 01308 | return std::acosh(v); 01309 | } 01310 | 01311 | template <typename T> 01312 | inline T asinh_impl(const T v, real_type_tag) 01313 | { 01314 | return std::asinh(v); 01315 | } 01316 | 01317 | template <typename T> 01318 | inline T atanh_impl(const T v, real_type_tag) 01319 | { 01320 | return std::atanh(v); 01321 | } 01322 | 01323 | template <typename T> 01324 | inline T trunc_impl(const T v, real_type_tag) 01325 | { 01326 | return std::trunc(v); 01327 | } 01328 | 01329 | template <typename T> 01330 | inline T expm1_impl(const T v, real_type_tag) 01331 | { 01332 | return std::expm1(v); 01333 | } 01334 | 01335 | template <typename T> 01336 | inline T expm1_impl(const T v, int_type_tag) 01337 | { 01338 | return std::expm1(v); 01339 | } 01340 | 01341 | template <typename T> 01342 | inline T log1p_impl(const T v, real_type_tag) 01343 | { 01344 | return std::log1p(v); 01345 | } 01346 | 01347 | template <typename T> 01348 | inline T log1p_impl(const T v, int_type_tag) 01349 | { 01350 | return std::log1p(v); 01351 | } 01352 | #else 01353 | template <typename T> 01354 | inline T acosh_impl(const T v, real_type_tag) 01355 | { 01356 | return std::log(v + std::sqrt((v * v) - T(1))); 01357 | } 01358 | 01359 | template <typename T> 01360 | inline T asinh_impl(const T v, real_type_tag) 01361 | { 01362 | return std::log(v + std::sqrt((v * v) + T(1))); 01363 | } 01364 | 01365 | template <typename T> 01366 | inline T atanh_impl(const T v, real_type_tag) 01367 | { 01368 | return (std::log(T(1) + v) - std::log(T(1) - v)) / T(2); 01369 | } 01370 | 01371 | template <typename T> 01372 | inline T trunc_impl(const T v, real_type_tag) 01373 | { 01374 | return T(static_cast<long long>(v)); 01375 | } 01376 | 01377 | template <typename T> 01378 | inline T expm1_impl(const T v, real_type_tag) 01379 | { 01380 | if (abs_impl(v,real_type_tag()) < T(0.00001)) 01381 | return v + (T(0.5) * v * v); 01382 | else 01383 | return std::exp(v) - T(1); 01384 | } 01385 | 01386 | template <typename T> 01387 | inline T expm1_impl(const T v, int_type_tag) 01388 | { 01389 | return T(std::exp<double>(v)) - T(1); 01390 | } 01391 | 01392 | template <typename T> 01393 | inline T log1p_impl(const T v, real_type_tag) 01394 | { 01395 | if (v > T(-1)) 01396 | { 01397 | if (abs_impl(v,real_type_tag()) > T(0.0001)) 01398 | { 01399 | return std::log(T(1) + v); 01400 | } 01401 | else 01402 | return (T(-0.5) * v + T(1)) * v; 01403 | } 01404 | 01405 | return std::numeric_limits<T>::quiet_NaN(); 01406 | } 01407 | 01408 | template <typename T> 01409 | inline T log1p_impl(const T v, int_type_tag) 01410 | { 01411 | if (v > T(-1)) 01412 | { 01413 | return std::log(T(1) + v); 01414 | } 01415 | 01416 | return std::numeric_limits<T>::quiet_NaN(); 01417 | } 01418 | #endif 01419 | 01420 | template <typename T> inline T acos_impl(const T v, real_type_tag) { return std::acos (v); } 01421 | template <typename T> inline T asin_impl(const T v, real_type_tag) { return std::asin (v); } 01422 | template <typename T> inline T atan_impl(const T v, real_type_tag) { return std::atan (v); } 01423 | template <typename T> inline T ceil_impl(const T v, real_type_tag) { return std::ceil (v); } 01424 | template <typename T> inline T cos_impl(const T v, real_type_tag) { return std::cos (v); } 01425 | template <typename T> inline T cosh_impl(const T v, real_type_tag) { return std::cosh (v); } 01426 | template <typename T> inline T exp_impl(const T v, real_type_tag) { return std::exp (v); } 01427 | template <typename T> inline T floor_impl(const T v, real_type_tag) { return std::floor(v); } 01428 | template <typename T> inline T log_impl(const T v, real_type_tag) { return std::log (v); } 01429 | template <typename T> inline T log10_impl(const T v, real_type_tag) { return std::log10(v); } 01430 | template <typename T> inline T log2_impl(const T v, real_type_tag) { return std::log(v)/T(numeric::constant::log2); } 01431 | template <typename T> inline T neg_impl(const T v, real_type_tag) { return -v; } 01432 | template <typename T> inline T pos_impl(const T v, real_type_tag) { return +v; } 01433 | template <typename T> inline T sin_impl(const T v, real_type_tag) { return std::sin (v); } 01434 | template <typename T> inline T sinh_impl(const T v, real_type_tag) { return std::sinh (v); } 01435 | template <typename T> inline T sqrt_impl(const T v, real_type_tag) { return std::sqrt (v); } 01436 | template <typename T> inline T tan_impl(const T v, real_type_tag) { return std::tan (v); } 01437 | template <typename T> inline T tanh_impl(const T v, real_type_tag) { return std::tanh (v); } 01438 | template <typename T> inline T cot_impl(const T v, real_type_tag) { return T(1) / std::tan(v); } 01439 | template <typename T> inline T sec_impl(const T v, real_type_tag) { return T(1) / std::cos(v); } 01440 | template <typename T> inline T csc_impl(const T v, real_type_tag) { return T(1) / std::sin(v); } 01441 | template <typename T> inline T r2d_impl(const T v, real_type_tag) { return (v * T(numeric::constant::_180_pi)); } 01442 | template <typename T> inline T d2r_impl(const T v, real_type_tag) { return (v * T(numeric::constant::pi_180)); } 01443 | template <typename T> inline T d2g_impl(const T v, real_type_tag) { return (v * T(10.0/9.0)); } 01444 | template <typename T> inline T g2d_impl(const T v, real_type_tag) { return (v * T(9.0/10.0)); } 01445 | template <typename T> inline T notl_impl(const T v, real_type_tag) { return (std::not_equal_to<T>()(T(0),v) ? T(0) : T(1)); } 01446 | template <typename T> inline T frac_impl(const T v, real_type_tag) { return (v - trunc_impl(v,real_type_tag())); } 01447 | 01448 | template <typename T> inline T const_pi_impl(real_type_tag) { return T(numeric::constant::pi); } 01449 | template <typename T> inline T const_e_impl(real_type_tag) { return T(numeric::constant::e); } 01450 | template <typename T> inline T const_qnan_impl(real_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01451 | 01452 | template <typename T> inline T abs_impl(const T v, int_type_tag) { return ((v >= T(0)) ? v : -v); } 01453 | template <typename T> inline T exp_impl(const T v, int_type_tag) { return std::exp (v); } 01454 | template <typename T> inline T log_impl(const T v, int_type_tag) { return std::log (v); } 01455 | template <typename T> inline T log10_impl(const T v, int_type_tag) { return std::log10(v); } 01456 | template <typename T> inline T log2_impl(const T v, int_type_tag) { return std::log(v)/T(numeric::constant::log2); } 01457 | template <typename T> inline T neg_impl(const T v, int_type_tag) { return -v; } 01458 | template <typename T> inline T pos_impl(const T v, int_type_tag) { return +v; } 01459 | template <typename T> inline T ceil_impl(const T v, int_type_tag) { return v; } 01460 | template <typename T> inline T floor_impl(const T v, int_type_tag) { return v; } 01461 | template <typename T> inline T round_impl(const T v, int_type_tag) { return v; } 01462 | template <typename T> inline T notl_impl(const T v, int_type_tag) { return !v; } 01463 | template <typename T> inline T sqrt_impl(const T v, int_type_tag) { return std::sqrt (v); } 01464 | template <typename T> inline T frac_impl(const T , int_type_tag) { return T(0); } 01465 | template <typename T> inline T trunc_impl(const T v, int_type_tag) { return v; } 01466 | template <typename T> inline T acos_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01467 | template <typename T> inline T acosh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01468 | template <typename T> inline T asin_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01469 | template <typename T> inline T asinh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01470 | template <typename T> inline T atan_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01471 | template <typename T> inline T atanh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01472 | template <typename T> inline T cos_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01473 | template <typename T> inline T cosh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01474 | template <typename T> inline T sin_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01475 | template <typename T> inline T sinh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01476 | template <typename T> inline T tan_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01477 | template <typename T> inline T tanh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01478 | template <typename T> inline T cot_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01479 | template <typename T> inline T sec_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01480 | template <typename T> inline T csc_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01481 | 01482 | template <typename T> 01483 | inline bool is_integer_impl(const T& v, real_type_tag) 01484 | { 01485 | return std::equal_to<T>()(T(0),std::fmod(v,T(1))); 01486 | } 01487 | 01488 | template <typename T> 01489 | inline bool is_integer_impl(const T&, int_type_tag) 01490 | { 01491 | return true; 01492 | } 01493 | } 01494 | 01495 | template <typename Type> 01496 | struct numeric_info { enum { length = 0, size = 32, bound_length = 0, min_exp = 0, max_exp = 0 }; }; 01497 | 01498 | template <> struct numeric_info<int > { enum { length = 10, size = 16, bound_length = 9 }; }; 01499 | template <> struct numeric_info<float > { enum { min_exp = -38, max_exp = +38 }; }; 01500 | template <> struct numeric_info<double > { enum { min_exp = -308, max_exp = +308 }; }; 01501 | template <> struct numeric_info<long double> { enum { min_exp = -308, max_exp = +308 }; }; 01502 | 01503 | template <typename T> 01504 | inline int to_int32(const T v) 01505 | { 01506 | const typename details::number_type<T>::type num_type; 01507 | return to_int32_impl(v, num_type); 01508 | } 01509 | 01510 | template <typename T> 01511 | inline _int64_t to_int64(const T v) 01512 | { 01513 | const typename details::number_type<T>::type num_type; 01514 | return to_int64_impl(v, num_type); 01515 | } 01516 | 01517 | template <typename T> 01518 | inline _uint64_t to_uint64(const T v) 01519 | { 01520 | const typename details::number_type<T>::type num_type; 01521 | return to_uint64_impl(v, num_type); 01522 | } 01523 | 01524 | template <typename T> 01525 | inline bool is_nan(const T v) 01526 | { 01527 | const typename details::number_type<T>::type num_type; 01528 | return is_nan_impl(v, num_type); 01529 | } 01530 | 01531 | template <typename T> 01532 | inline T min(const T v0, const T v1) 01533 | { 01534 | const typename details::number_type<T>::type num_type; 01535 | return min_impl(v0, v1, num_type); 01536 | } 01537 | 01538 | template <typename T> 01539 | inline T max(const T v0, const T v1) 01540 | { 01541 | const typename details::number_type<T>::type num_type; 01542 | return max_impl(v0, v1, num_type); 01543 | } 01544 | 01545 | template <typename T> 01546 | inline T equal(const T v0, const T v1) 01547 | { 01548 | const typename details::number_type<T>::type num_type; 01549 | return equal_impl(v0, v1, num_type); 01550 | } 01551 | 01552 | template <typename T> 01553 | inline T nequal(const T v0, const T v1) 01554 | { 01555 | const typename details::number_type<T>::type num_type; 01556 | return nequal_impl(v0, v1, num_type); 01557 | } 01558 | 01559 | template <typename T> 01560 | inline T modulus(const T v0, const T v1) 01561 | { 01562 | const typename details::number_type<T>::type num_type; 01563 | return modulus_impl(v0, v1, num_type); 01564 | } 01565 | 01566 | template <typename T> 01567 | inline T pow(const T v0, const T v1) 01568 | { 01569 | const typename details::number_type<T>::type num_type; 01570 | return pow_impl(v0, v1, num_type); 01571 | } 01572 | 01573 | template <typename T> 01574 | inline T logn(const T v0, const T v1) 01575 | { 01576 | const typename details::number_type<T>::type num_type; 01577 | return logn_impl(v0, v1, num_type); 01578 | } 01579 | 01580 | template <typename T> 01581 | inline T root(const T v0, const T v1) 01582 | { 01583 | const typename details::number_type<T>::type num_type; 01584 | return root_impl(v0, v1, num_type); 01585 | } 01586 | 01587 | template <typename T> 01588 | inline T roundn(const T v0, const T v1) 01589 | { 01590 | const typename details::number_type<T>::type num_type; 01591 | return roundn_impl(v0, v1, num_type); 01592 | } 01593 | 01594 | template <typename T> 01595 | inline T hypot(const T v0, const T v1) 01596 | { 01597 | const typename details::number_type<T>::type num_type; 01598 | return hypot_impl(v0, v1, num_type); 01599 | } 01600 | 01601 | template <typename T> 01602 | inline T atan2(const T v0, const T v1) 01603 | { 01604 | const typename details::number_type<T>::type num_type; 01605 | return atan2_impl(v0, v1, num_type); 01606 | } 01607 | 01608 | template <typename T> 01609 | inline T shr(const T v0, const T v1) 01610 | { 01611 | const typename details::number_type<T>::type num_type; 01612 | return shr_impl(v0, v1, num_type); 01613 | } 01614 | 01615 | template <typename T> 01616 | inline T shl(const T v0, const T v1) 01617 | { 01618 | const typename details::number_type<T>::type num_type; 01619 | return shl_impl(v0, v1, num_type); 01620 | } 01621 | 01622 | template <typename T> 01623 | inline T and_opr(const T v0, const T v1) 01624 | { 01625 | const typename details::number_type<T>::type num_type; 01626 | return and_impl(v0, v1, num_type); 01627 | } 01628 | 01629 | template <typename T> 01630 | inline T nand_opr(const T v0, const T v1) 01631 | { 01632 | const typename details::number_type<T>::type num_type; 01633 | return nand_impl(v0, v1, num_type); 01634 | } 01635 | 01636 | template <typename T> 01637 | inline T or_opr(const T v0, const T v1) 01638 | { 01639 | const typename details::number_type<T>::type num_type; 01640 | return or_impl(v0, v1, num_type); 01641 | } 01642 | 01643 | template <typename T> 01644 | inline T nor_opr(const T v0, const T v1) 01645 | { 01646 | const typename details::number_type<T>::type num_type; 01647 | return nor_impl(v0, v1, num_type); 01648 | } 01649 | 01650 | template <typename T> 01651 | inline T xor_opr(const T v0, const T v1) 01652 | { 01653 | const typename details::number_type<T>::type num_type; 01654 | return xor_impl(v0, v1, num_type); 01655 | } 01656 | 01657 | template <typename T> 01658 | inline T xnor_opr(const T v0, const T v1) 01659 | { 01660 | const typename details::number_type<T>::type num_type; 01661 | return xnor_impl(v0, v1, num_type); 01662 | } 01663 | 01664 | template <typename T> 01665 | inline bool is_integer(const T v) 01666 | { 01667 | const typename details::number_type<T>::type num_type; 01668 | return is_integer_impl(v, num_type); 01669 | } 01670 | 01671 | template <typename T, unsigned int N> 01672 | struct fast_exp 01673 | { 01674 | static inline T result(T v) 01675 | { 01676 | unsigned int k = N; 01677 | T l = T(1); 01678 | 01679 | while (k) 01680 | { 01681 | if (1 == (k % 2)) 01682 | { 01683 | l *= v; 01684 | --k; 01685 | } 01686 | 01687 | v *= v; 01688 | k /= 2; 01689 | } 01690 | 01691 | return l; 01692 | } 01693 | }; 01694 | 01695 | template <typename T> struct fast_exp<T,10> { static inline T result(const T v) { T v_5 = fast_exp<T,5>::result(v); return v_5 * v_5; } }; 01696 | template <typename T> struct fast_exp<T, 9> { static inline T result(const T v) { return fast_exp<T,8>::result(v) * v; } }; 01697 | template <typename T> struct fast_exp<T, 8> { static inline T result(const T v) { T v_4 = fast_exp<T,4>::result(v); return v_4 * v_4; } }; 01698 | template <typename T> struct fast_exp<T, 7> { static inline T result(const T v) { return fast_exp<T,6>::result(v) * v; } }; 01699 | template <typename T> struct fast_exp<T, 6> { static inline T result(const T v) { T v_3 = fast_exp<T,3>::result(v); return v_3 * v_3; } }; 01700 | template <typename T> struct fast_exp<T, 5> { static inline T result(const T v) { return fast_exp<T,4>::result(v) * v; } }; 01701 | template <typename T> struct fast_exp<T, 4> { static inline T result(const T v) { T v_2 = v * v; return v_2 * v_2; } }; 01702 | template <typename T> struct fast_exp<T, 3> { static inline T result(const T v) { return v * v * v; } }; 01703 | template <typename T> struct fast_exp<T, 2> { static inline T result(const T v) { return v * v; } }; 01704 | template <typename T> struct fast_exp<T, 1> { static inline T result(const T v) { return v; } }; 01705 | template <typename T> struct fast_exp<T, 0> { static inline T result(const T ) { return T(1); } }; 01706 | 01707 | #define exprtk_define_unary_function(FunctionName) \ 01708 | template <typename T> \ 01709 | inline T FunctionName (const T v) \ 01710 | { \ 01711 | const typename details::number_type<T>::type num_type; \ 01712 | return FunctionName##_impl(v,num_type); \ 01713 | } \ 01714 | 01715 | exprtk_define_unary_function(abs ) 01716 | exprtk_define_unary_function(acos ) 01717 | exprtk_define_unary_function(acosh) 01718 | exprtk_define_unary_function(asin ) 01719 | exprtk_define_unary_function(asinh) 01720 | exprtk_define_unary_function(atan ) 01721 | exprtk_define_unary_function(atanh) 01722 | exprtk_define_unary_function(ceil ) 01723 | exprtk_define_unary_function(cos ) 01724 | exprtk_define_unary_function(cosh ) 01725 | exprtk_define_unary_function(exp ) 01726 | exprtk_define_unary_function(expm1) 01727 | exprtk_define_unary_function(floor) 01728 | exprtk_define_unary_function(log ) 01729 | exprtk_define_unary_function(log10) 01730 | exprtk_define_unary_function(log2 ) 01731 | exprtk_define_unary_function(log1p) 01732 | exprtk_define_unary_function(neg ) 01733 | exprtk_define_unary_function(pos ) 01734 | exprtk_define_unary_function(round) 01735 | exprtk_define_unary_function(sin ) 01736 | exprtk_define_unary_function(sinc ) 01737 | exprtk_define_unary_function(sinh ) 01738 | exprtk_define_unary_function(sqrt ) 01739 | exprtk_define_unary_function(tan ) 01740 | exprtk_define_unary_function(tanh ) 01741 | exprtk_define_unary_function(cot ) 01742 | exprtk_define_unary_function(sec ) 01743 | exprtk_define_unary_function(csc ) 01744 | exprtk_define_unary_function(r2d ) 01745 | exprtk_define_unary_function(d2r ) 01746 | exprtk_define_unary_function(d2g ) 01747 | exprtk_define_unary_function(g2d ) 01748 | exprtk_define_unary_function(notl ) 01749 | exprtk_define_unary_function(sgn ) 01750 | exprtk_define_unary_function(erf ) 01751 | exprtk_define_unary_function(erfc ) 01752 | exprtk_define_unary_function(ncdf ) 01753 | exprtk_define_unary_function(frac ) 01754 | exprtk_define_unary_function(trunc) 01755 | #undef exprtk_define_unary_function 01756 | } 01757 | 01758 | template <typename T> 01759 | inline T compute_pow10(T d, const int exponent) 01760 | { 01761 | static const double fract10[] = 01762 | { 01763 | 0.0, 01764 | 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, 01765 | 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, 01766 | 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, 01767 | 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, 01768 | 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, 01769 | 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, 01770 | 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, 01771 | 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, 01772 | 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, 01773 | 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, 01774 | 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, 01775 | 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, 01776 | 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, 01777 | 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, 01778 | 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, 01779 | 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, 01780 | 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, 01781 | 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, 01782 | 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, 01783 | 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, 01784 | 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, 01785 | 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, 01786 | 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, 01787 | 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, 01788 | 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, 01789 | 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, 01790 | 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, 01791 | 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, 01792 | 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, 01793 | 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, 01794 | 1.0E+301, 1.0E+302, 1.0E+303, 1.0E+304, 1.0E+305, 1.0E+306, 1.0E+307, 1.0E+308 01795 | }; 01796 | 01797 | static const int fract10_size = static_cast<int>(sizeof(fract10) / sizeof(double)); 01798 | 01799 | const int e = std::abs(exponent); 01800 | 01801 | if (exponent >= std::numeric_limits<T>::min_exponent10) 01802 | { 01803 | if (e < fract10_size) 01804 | { 01805 | if (exponent > 0) 01806 | return T(d * fract10[e]); 01807 | else 01808 | return T(d / fract10[e]); 01809 | } 01810 | else 01811 | return T(d * std::pow(10.0, 10.0 * exponent)); 01812 | } 01813 | else 01814 | { 01815 | d /= T(fract10[ -std::numeric_limits<T>::min_exponent10]); 01816 | return T(d / fract10[-exponent + std::numeric_limits<T>::min_exponent10]); 01817 | } 01818 | } 01819 | 01820 | template <typename Iterator, typename T> 01821 | inline bool string_to_type_converter_impl_ref(Iterator& itr, const Iterator end, T& result) 01822 | { 01823 | if (itr == end) 01824 | return false; 01825 | 01826 | const bool negative = ('-' == (*itr)); 01827 | 01828 | if (negative || ('+' == (*itr))) 01829 | { 01830 | if (end == ++itr) 01831 | return false; 01832 | } 01833 | 01834 | static const uchar_t zero = static_cast<uchar_t>('0'); 01835 | 01836 | while ((end != itr) && (zero == (*itr))) ++itr; 01837 | 01838 | bool return_result = true; 01839 | unsigned int digit = 0; 01840 | const std::size_t length = static_cast<std::size_t>(std::distance(itr,end)); 01841 | 01842 | if (length <= 4) 01843 | { 01844 | switch (length) 01845 | { 01846 | #ifdef exprtk_use_lut 01847 | 01848 | #define exprtk_process_digit \ 01849 | if ((digit = details::digit_table[(int)*itr++]) < 10) \ 01850 | result = result * 10 + (digit); \ 01851 | else \ 01852 | { \ 01853 | return_result = false; \ 01854 | break; \ 01855 | } \ 01856 | exprtk_fallthrough \ 01857 | 01858 | #else 01859 | 01860 | #define exprtk_process_digit \ 01861 | if ((digit = (*itr++ - zero)) < 10) \ 01862 | result = result * T(10) + digit; \ 01863 | else \ 01864 | { \ 01865 | return_result = false; \ 01866 | break; \ 01867 | } \ 01868 | exprtk_fallthrough \ 01869 | 01870 | #endif 01871 | 01872 | case 4 : exprtk_process_digit 01873 | case 3 : exprtk_process_digit 01874 | case 2 : exprtk_process_digit 01875 | case 1 : if ((digit = (*itr - zero)) >= 10) 01876 | { 01877 | digit = 0; 01878 | return_result = false; 01879 | } 01880 | 01881 | #undef exprtk_process_digit 01882 | } 01883 | } 01884 | else 01885 | return_result = false; 01886 | 01887 | if (length && return_result) 01888 | { 01889 | result = result * 10 + static_cast<T>(digit); 01890 | ++itr; 01891 | } 01892 | 01893 | result = negative ? -result : result; 01894 | return return_result; 01895 | } 01896 | 01897 | template <typename Iterator, typename T> 01898 | static inline bool parse_nan(Iterator& itr, const Iterator end, T& t) 01899 | { 01900 | typedef typename std::iterator_traits<Iterator>::value_type type; 01901 | 01902 | static const std::size_t nan_length = 3; 01903 | 01904 | if (std::distance(itr,end) != static_cast<int>(nan_length)) 01905 | return false; 01906 | 01907 | if (static_cast<type>('n') == (*itr)) 01908 | { 01909 | if ( 01910 | (static_cast<type>('a') != *(itr + 1)) || 01911 | (static_cast<type>('n') != *(itr + 2)) 01912 | ) 01913 | { 01914 | return false; 01915 | } 01916 | } 01917 | else if ( 01918 | (static_cast<type>('A') != *(itr + 1)) || 01919 | (static_cast<type>('N') != *(itr + 2)) 01920 | ) 01921 | { 01922 | return false; 01923 | } 01924 | 01925 | t = std::numeric_limits<T>::quiet_NaN(); 01926 | 01927 | return true; 01928 | } 01929 | 01930 | template <typename Iterator, typename T> 01931 | static inline bool parse_inf(Iterator& itr, const Iterator end, T& t, const bool negative) 01932 | { 01933 | static const char_t inf_uc[] = "INFINITY" 01934 | static const char_t inf_lc[] = "infinity" 01935 | static const std::size_t inf_length = 8; 01936 | 01937 | const std::size_t length = static_cast<std::size_t>(std::distance(itr,end)); 01938 | 01939 | if ((3 != length) && (inf_length != length)) 01940 | return false; 01941 | 01942 | char_cptr inf_itr = ('i' == (*itr)) ? inf_lc : inf_uc; 01943 | 01944 | while (end != itr) 01945 | { 01946 | if (*inf_itr == static_cast<char_t>(*itr)) 01947 | { 01948 | ++itr; 01949 | ++inf_itr; 01950 | continue; 01951 | } 01952 | else 01953 | return false; 01954 | } 01955 | 01956 | if (negative) 01957 | t = -std::numeric_limits<T>::infinity(); 01958 | else 01959 | t = std::numeric_limits<T>::infinity(); 01960 | 01961 | return true; 01962 | } 01963 | 01964 | template <typename T> 01965 | inline bool valid_exponent(const int exponent, numeric::details::real_type_tag) 01966 | { 01967 | using namespace details::numeric; 01968 | return (numeric_info<T>::min_exp <= exponent) && (exponent <= numeric_info<T>::max_exp); 01969 | } 01970 | 01971 | template <typename Iterator, typename T> 01972 | inline bool string_to_real(Iterator& itr_external, const Iterator end, T& t, numeric::details::real_type_tag) 01973 | { 01974 | if (end == itr_external) return false; 01975 | 01976 | Iterator itr = itr_external; 01977 | 01978 | T d = T(0); 01979 | 01980 | const bool negative = ('-' == (*itr)); 01981 | 01982 | if (negative || '+' == (*itr)) 01983 | { 01984 | if (end == ++itr) 01985 | return false; 01986 | } 01987 | 01988 | bool instate = false; 01989 | 01990 | static const char_t zero = static_cast<uchar_t>('0'); 01991 | 01992 | #define parse_digit_1(d) \ 01993 | if ((digit = (*itr - zero)) < 10) \ 01994 | { d = d * T(10) + digit; } \ 01995 | else \ 01996 | { break; } \ 01997 | if (end == ++itr) break; \ 01998 | 01999 | #define parse_digit_2(d) \ 02000 | if ((digit = (*itr - zero)) < 10) \ 02001 | { d = d * T(10) + digit; } \ 02002 | else \ 02003 | { break; } \ 02004 | ++itr; \ 02005 | 02006 | if ('.' != (*itr)) 02007 | { 02008 | const Iterator curr = itr; 02009 | 02010 | while ((end != itr) && (zero == (*itr))) ++itr; 02011 | 02012 | while (end != itr) 02013 | { 02014 | unsigned int digit; 02015 | parse_digit_1(d) 02016 | parse_digit_1(d) 02017 | parse_digit_2(d) 02018 | } 02019 | 02020 | if (curr != itr) instate = true; 02021 | } 02022 | 02023 | int exponent = 0; 02024 | 02025 | if (end != itr) 02026 | { 02027 | if ('.' == (*itr)) 02028 | { 02029 | const Iterator curr = ++itr; 02030 | T tmp_d = T(0); 02031 | 02032 | while (end != itr) 02033 | { 02034 | unsigned int digit; 02035 | parse_digit_1(tmp_d) 02036 | parse_digit_1(tmp_d) 02037 | parse_digit_2(tmp_d) 02038 | } 02039 | 02040 | if (curr != itr) 02041 | { 02042 | instate = true; 02043 | 02044 | const int frac_exponent = static_cast<int>(-std::distance(curr, itr)); 02045 | 02046 | if (!valid_exponent<T>(frac_exponent, numeric::details::real_type_tag())) 02047 | return false; 02048 | 02049 | d += compute_pow10(tmp_d, frac_exponent); 02050 | } 02051 | 02052 | #undef parse_digit_1 02053 | #undef parse_digit_2 02054 | } 02055 | 02056 | if (end != itr) 02057 | { 02058 | typename std::iterator_traits<Iterator>::value_type c = (*itr); 02059 | 02060 | if (('e' == c) || ('E' == c)) 02061 | { 02062 | int exp = 0; 02063 | 02064 | if (!details::string_to_type_converter_impl_ref(++itr, end, exp)) 02065 | { 02066 | if (end == itr) 02067 | return false; 02068 | else 02069 | c = (*itr); 02070 | } 02071 | 02072 | exponent += exp; 02073 | } 02074 | 02075 | if (end != itr) 02076 | { 02077 | if (('f' == c) || ('F' == c) || ('l' == c) || ('L' == c)) 02078 | ++itr; 02079 | else if ('#' == c) 02080 | { 02081 | if (end == ++itr) 02082 | return false; 02083 | 02084 | if (('I' <= (*itr)) && ((*itr) <= 'n')) 02085 | { 02086 | if (('i' == (*itr)) || ('I' == (*itr))) 02087 | { 02088 | return parse_inf(itr, end, t, negative); 02089 | } 02090 | else if (('n' == (*itr)) || ('N' == (*itr))) 02091 | { 02092 | return parse_nan(itr, end, t); 02093 | } 02094 | else 02095 | return false; 02096 | } 02097 | else 02098 | return false; 02099 | } 02100 | else if (('I' <= (*itr)) && ((*itr) <= 'n')) 02101 | { 02102 | if (('i' == (*itr)) || ('I' == (*itr))) 02103 | { 02104 | return parse_inf(itr, end, t, negative); 02105 | } 02106 | else if (('n' == (*itr)) || ('N' == (*itr))) 02107 | { 02108 | return parse_nan(itr, end, t); 02109 | } 02110 | else 02111 | return false; 02112 | } 02113 | else 02114 | return false; 02115 | } 02116 | } 02117 | } 02118 | 02119 | if ((end != itr) || (!instate)) 02120 | return false; 02121 | else if (!valid_exponent<T>(exponent, numeric::details::real_type_tag())) 02122 | return false; 02123 | else if (exponent) 02124 | d = compute_pow10(d,exponent); 02125 | 02126 | t = static_cast<T>((negative) ? -d : d); 02127 | return true; 02128 | } 02129 | 02130 | template <typename T> 02131 | inline bool string_to_real(const std::string& s, T& t) 02132 | { 02133 | const typename numeric::details::number_type<T>::type num_type; 02134 | 02135 | char_cptr begin = s.data(); 02136 | char_cptr end = s.data() + s.size(); 02137 | 02138 | return string_to_real(begin, end, t, num_type); 02139 | } 02140 | 02141 | template <typename T> 02142 | struct functor_t 02143 | { 02144 | /* 02145 | Note: The following definitions for Type, may require tweaking 02146 | based on the compiler and target architecture. The benchmark 02147 | should provide enough information to make the right choice. 02148 | */ 02149 | //typedef T Type; 02150 | //typedef const T Type; 02151 | typedef const T& Type; 02152 | typedef T& RefType; 02153 | typedef T (*qfunc_t)(Type t0, Type t1, Type t2, Type t3); 02154 | typedef T (*tfunc_t)(Type t0, Type t1, Type t2); 02155 | typedef T (*bfunc_t)(Type t0, Type t1); 02156 | typedef T (*ufunc_t)(Type t0); 02157 | }; 02158 | 02159 | } // namespace details 02160 | 02161 | struct loop_runtime_check 02162 | { 02163 | enum loop_types 02164 | { 02165 | e_invalid = 0, 02166 | e_for_loop = 1, 02167 | e_while_loop = 2, 02168 | e_repeat_until_loop = 4, 02169 | e_all_loops = 7 02170 | }; 02171 | 02172 | enum violation_type 02173 | { 02174 | e_unknown = 0, 02175 | e_iteration_count = 1, 02176 | e_timeout = 2 02177 | }; 02178 | 02179 | loop_types loop_set; 02180 | 02181 | loop_runtime_check() 02182 | : loop_set(e_invalid) 02183 | , max_loop_iterations(0) 02184 | {} 02185 | 02186 | details::_uint64_t max_loop_iterations; 02187 | 02188 | struct violation_context 02189 | { 02190 | loop_types loop; 02191 | violation_type violation; 02192 | details::_uint64_t iteration_count; 02193 | }; 02194 | 02195 | virtual bool check() 02196 | { 02197 | return true; 02198 | } 02199 | 02200 | virtual void handle_runtime_violation(const violation_context&) 02201 | { 02202 | throw std::runtime_error("ExprTk Loop runtime violation."); 02203 | } 02204 | 02205 | virtual ~loop_runtime_check() 02206 | {} 02207 | }; 02208 | 02209 | typedef loop_runtime_check* loop_runtime_check_ptr; 02210 | 02211 | struct vector_access_runtime_check 02212 | { 02213 | struct violation_context 02214 | { 02215 | void* base_ptr; 02216 | void* end_ptr; 02217 | void* access_ptr; 02218 | std::size_t type_size; 02219 | }; 02220 | 02221 | virtual ~vector_access_runtime_check() 02222 | {} 02223 | 02224 | virtual bool handle_runtime_violation(violation_context& /*context*/) 02225 | { 02226 | throw std::runtime_error("ExprTk runtime vector access violation."); 02227 | #if !defined(_MSC_VER) && !defined(__NVCOMPILER) 02228 | return false; 02229 | #endif 02230 | } 02231 | }; 02232 | 02233 | typedef vector_access_runtime_check* vector_access_runtime_check_ptr; 02234 | 02235 | struct assert_check 02236 | { 02237 | struct assert_context 02238 | { 02239 | std::string condition; 02240 | std::string message; 02241 | std::string id; 02242 | std::size_t offet; 02243 | }; 02244 | 02245 | virtual ~assert_check() 02246 | {} 02247 | 02248 | virtual void handle_assert(const assert_context& /*context*/) 02249 | {} 02250 | }; 02251 | 02252 | typedef assert_check* assert_check_ptr; 02253 | 02254 | struct compilation_check 02255 | { 02256 | struct compilation_context 02257 | { 02258 | std::string error_message; 02259 | }; 02260 | 02261 | virtual bool continue_compilation(compilation_context& /*context*/) = 0; 02262 | 02263 | virtual ~compilation_check() 02264 | {} 02265 | }; 02266 | 02267 | typedef compilation_check* compilation_check_ptr; 02268 | 02269 | namespace lexer 02270 | { 02271 | struct token 02272 | { 02273 | enum token_type 02274 | { 02275 | e_none = 0, e_error = 1, e_err_symbol = 2, 02276 | e_err_number = 3, e_err_string = 4, e_err_sfunc = 5, 02277 | e_eof = 6, e_number = 7, e_symbol = 8, 02278 | e_string = 9, e_assign = 10, e_addass = 11, 02279 | e_subass = 12, e_mulass = 13, e_divass = 14, 02280 | e_modass = 15, e_shr = 16, e_shl = 17, 02281 | e_lte = 18, e_ne = 19, e_gte = 20, 02282 | e_swap = 21, e_lt = '<', e_gt = '>', 02283 | e_eq = '=', e_rbracket = ')', e_lbracket = '(', 02284 | e_rsqrbracket = ']', e_lsqrbracket = '[', e_rcrlbracket = '}', 02285 | e_lcrlbracket = '{', e_comma = ',', e_add = '+', 02286 | e_sub = '-', e_div = '/', e_mul = '*', 02287 | e_mod = '%', e_pow = '^', e_colon = ':', 02288 | e_ternary = '?' 02289 | }; 02290 | 02291 | token() 02292 | : type(e_none) 02293 | , value("") 02294 | , position(std::numeric_limits<std::size_t>::max()) 02295 | {} 02296 | 02297 | void clear() 02298 | { 02299 | type = e_none; 02300 | value = "" 02301 | position = std::numeric_limits<std::size_t>::max(); 02302 | } 02303 | 02304 | template <typename Iterator> 02305 | inline token& set_operator(const token_type tt, 02306 | const Iterator begin, const Iterator end, 02307 | const Iterator base_begin = Iterator(0)) 02308 | { 02309 | type = tt; 02310 | value.assign(begin,end); 02311 | if (base_begin) 02312 | position = static_cast<std::size_t>(std::distance(base_begin,begin)); 02313 | return (*this); 02314 | } 02315 | 02316 | template <typename Iterator> 02317 | inline token& set_symbol(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0)) 02318 | { 02319 | type = e_symbol; 02320 | value.assign(begin,end); 02321 | if (base_begin) 02322 | position = static_cast<std::size_t>(std::distance(base_begin,begin)); 02323 | return (*this); 02324 | } 02325 | 02326 | template <typename Iterator> 02327 | inline token& set_numeric(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0)) 02328 | { 02329 | type = e_number; 02330 | value.assign(begin,end); 02331 | if (base_begin) 02332 | position = static_cast<std::size_t>(std::distance(base_begin,begin)); 02333 | return (*this); 02334 | } 02335 | 02336 | template <typename Iterator> 02337 | inline token& set_string(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0)) 02338 | { 02339 | type = e_string; 02340 | value.assign(begin,end); 02341 | if (base_begin) 02342 | position = static_cast<std::size_t>(std::distance(base_begin,begin)); 02343 | return (*this); 02344 | } 02345 | 02346 | inline token& set_string(const std::string& s, const std::size_t p) 02347 | { 02348 | type = e_string; 02349 | value = s; 02350 | position = p; 02351 | return (*this); 02352 | } 02353 | 02354 | template <typename Iterator> 02355 | inline token& set_error(const token_type et, 02356 | const Iterator begin, const Iterator end, 02357 | const Iterator base_begin = Iterator(0)) 02358 | { 02359 | if ( 02360 | (e_error == et) || 02361 | (e_err_symbol == et) || 02362 | (e_err_number == et) || 02363 | (e_err_string == et) || 02364 | (e_err_sfunc == et) 02365 | ) 02366 | { 02367 | type = et; 02368 | } 02369 | else 02370 | type = e_error; 02371 | 02372 | value.assign(begin,end); 02373 | 02374 | if (base_begin) 02375 | position = static_cast<std::size_t>(std::distance(base_begin,begin)); 02376 | 02377 | return (*this); 02378 | } 02379 | 02380 | static inline std::string to_str(const token_type t) 02381 | { 02382 | switch (t) 02383 | { 02384 | case e_none : return "NONE" 02385 | case e_error : return "ERROR" 02386 | case e_err_symbol : return "ERROR_SYMBOL" 02387 | case e_err_number : return "ERROR_NUMBER" 02388 | case e_err_string : return "ERROR_STRING" 02389 | case e_eof : return "EOF" 02390 | case e_number : return "NUMBER" 02391 | case e_symbol : return "SYMBOL" 02392 | case e_string : return "STRING" 02393 | case e_assign : return ":=" 02394 | case e_addass : return "+=" 02395 | case e_subass : return "-=" 02396 | case e_mulass : return "*=" 02397 | case e_divass : return "/=" 02398 | case e_modass : return "%=" 02399 | case e_shr : return ">>" 02400 | case e_shl : return "<<" 02401 | case e_lte : return "<=" 02402 | case e_ne : return "!=" 02403 | case e_gte : return ">=" 02404 | case e_lt : return "<" 02405 | case e_gt : return ">" 02406 | case e_eq : return "=" 02407 | case e_rbracket : return ")" 02408 | case e_lbracket : return "(" 02409 | case e_rsqrbracket : return "]" 02410 | case e_lsqrbracket : return "[" 02411 | case e_rcrlbracket : return "}" 02412 | case e_lcrlbracket : return "{" 02413 | case e_comma : return "," 02414 | case e_add : return "+" 02415 | case e_sub : return "-" 02416 | case e_div : return "/" 02417 | case e_mul : return "*" 02418 | case e_mod : return "%" 02419 | case e_pow : return "^" 02420 | case e_colon : return ":" 02421 | case e_ternary : return "?" 02422 | case e_swap : return "<=>" 02423 | default : return "UNKNOWN" 02424 | } 02425 | } 02426 | 02427 | static inline std::string seperator_to_str(const token_type t) 02428 | { 02429 | switch (t) 02430 | { 02431 | case e_comma : return "," 02432 | case e_colon : return ":" 02433 | case e_eof : return "" 02434 | default : return "UNKNOWN" 02435 | } 02436 | 02437 | #if !defined(_MSC_VER) && !defined(__NVCOMPILER) 02438 | return "UNKNOWN" 02439 | #endif 02440 | } 02441 | 02442 | inline bool is_error() const 02443 | { 02444 | return (e_error == type) || 02445 | (e_err_symbol == type) || 02446 | (e_err_number == type) || 02447 | (e_err_string == type) || 02448 | (e_err_sfunc == type) ; 02449 | } 02450 | 02451 | token_type type; 02452 | std::string value; 02453 | std::size_t position; 02454 | }; 02455 | 02456 | class generator 02457 | { 02458 | public: 02459 | 02460 | typedef token token_t; 02461 | typedef std::vector<token_t> token_list_t; 02462 | typedef token_list_t::iterator token_list_itr_t; 02463 | typedef details::char_t char_t; 02464 | 02465 | generator() 02466 | : base_itr_(0) 02467 | , s_itr_ (0) 02468 | , s_end_ (0) 02469 | { 02470 | clear(); 02471 | } 02472 | 02473 | inline void clear() 02474 | { 02475 | base_itr_ = 0; 02476 | s_itr_ = 0; 02477 | s_end_ = 0; 02478 | token_list_.clear(); 02479 | token_itr_ = token_list_.end(); 02480 | store_token_itr_ = token_list_.end(); 02481 | } 02482 | 02483 | inline bool process(const std::string& str) 02484 | { 02485 | base_itr_ = str.data(); 02486 | s_itr_ = str.data(); 02487 | s_end_ = str.data() + str.size(); 02488 | 02489 | eof_token_.set_operator(token_t::e_eof, s_end_, s_end_, base_itr_); 02490 | token_list_.clear(); 02491 | 02492 | while (!is_end(s_itr_)) 02493 | { 02494 | scan_token(); 02495 | 02496 | if (!token_list_.empty() && token_list_.back().is_error()) 02497 | return false; 02498 | } 02499 | 02500 | return true; 02501 | } 02502 | 02503 | inline bool empty() const 02504 | { 02505 | return token_list_.empty(); 02506 | } 02507 | 02508 | inline std::size_t size() const 02509 | { 02510 | return token_list_.size(); 02511 | } 02512 | 02513 | inline void begin() 02514 | { 02515 | token_itr_ = token_list_.begin(); 02516 | store_token_itr_ = token_list_.begin(); 02517 | } 02518 | 02519 | inline void store() 02520 | { 02521 | store_token_itr_ = token_itr_; 02522 | } 02523 | 02524 | inline void restore() 02525 | { 02526 | token_itr_ = store_token_itr_; 02527 | } 02528 | 02529 | inline token_t& next_token() 02530 | { 02531 | if (token_list_.end() != token_itr_) 02532 | { 02533 | return *token_itr_++; 02534 | } 02535 | else 02536 | return eof_token_; 02537 | } 02538 | 02539 | inline token_t& peek_next_token() 02540 | { 02541 | if (token_list_.end() != token_itr_) 02542 | { 02543 | return *token_itr_; 02544 | } 02545 | else 02546 | return eof_token_; 02547 | } 02548 | 02549 | inline token_t& operator[](const std::size_t& index) 02550 | { 02551 | if (index < token_list_.size()) 02552 | { 02553 | return token_list_[index]; 02554 | } 02555 | else 02556 | return eof_token_; 02557 | } 02558 | 02559 | inline token_t operator[](const std::size_t& index) const 02560 | { 02561 | if (index < token_list_.size()) 02562 | { 02563 | return token_list_[index]; 02564 | } 02565 | else 02566 | return eof_token_; 02567 | } 02568 | 02569 | inline bool finished() const 02570 | { 02571 | return (token_list_.end() == token_itr_); 02572 | } 02573 | 02574 | inline void insert_front(token_t::token_type tk_type) 02575 | { 02576 | if ( 02577 | !token_list_.empty() && 02578 | (token_list_.end() != token_itr_) 02579 | ) 02580 | { 02581 | token_t t = *token_itr_; 02582 | 02583 | t.type = tk_type; 02584 | token_itr_ = token_list_.insert(token_itr_,t); 02585 | } 02586 | } 02587 | 02588 | inline std::string substr(const std::size_t& begin, const std::size_t& end) const 02589 | { 02590 | const details::char_cptr begin_itr = ((base_itr_ + begin) < s_end_) ? (base_itr_ + begin) : s_end_; 02591 | const details::char_cptr end_itr = ((base_itr_ + end ) < s_end_) ? (base_itr_ + end ) : s_end_; 02592 | 02593 | return std::string(begin_itr,end_itr); 02594 | } 02595 | 02596 | inline std::string remaining() const 02597 | { 02598 | if (finished()) 02599 | return "" 02600 | else if (token_list_.begin() != token_itr_) 02601 | return std::string(base_itr_ + (token_itr_ - 1)->position, s_end_); 02602 | else 02603 | return std::string(base_itr_ + token_itr_->position, s_end_); 02604 | } 02605 | 02606 | private: 02607 | 02608 | inline bool is_end(details::char_cptr itr) const 02609 | { 02610 | return (s_end_ == itr); 02611 | } 02612 | 02613 | #ifndef exprtk_disable_comments 02614 | inline bool is_comment_start(details::char_cptr itr) const 02615 | { 02616 | const char_t c0 = *(itr + 0); 02617 | const char_t c1 = *(itr + 1); 02618 | 02619 | if ('#' == c0) 02620 | return true; 02621 | else if (!is_end(itr + 1)) 02622 | { 02623 | if (('/' == c0) && ('/' == c1)) return true; 02624 | if (('/' == c0) && ('*' == c1)) return true; 02625 | } 02626 | return false; 02627 | } 02628 | #else 02629 | inline bool is_comment_start(details::char_cptr) const 02630 | { 02631 | return false; 02632 | } 02633 | #endif 02634 | 02635 | inline void skip_whitespace() 02636 | { 02637 | while (!is_end(s_itr_) && details::is_whitespace(*s_itr_)) 02638 | { 02639 | ++s_itr_; 02640 | } 02641 | } 02642 | 02643 | inline void skip_comments() 02644 | { 02645 | #ifndef exprtk_disable_comments 02646 | // The following comment styles are supported: 02647 | // 1. // .... \n 02648 | // 2. # .... \n 02649 | // 3. /* .... */ 02650 | struct test 02651 | { 02652 | static inline bool comment_start(const char_t c0, const char_t c1, int& mode, int& incr) 02653 | { 02654 | mode = 0; 02655 | if ('#' == c0) { mode = 1; incr = 1; } 02656 | else if ('/' == c0) 02657 | { 02658 | if ('/' == c1) { mode = 1; incr = 2; } 02659 | else if ('*' == c1) { mode = 2; incr = 2; } 02660 | } 02661 | return (0 != mode); 02662 | } 02663 | 02664 | static inline bool comment_end(const char_t c0, const char_t c1, int& mode) 02665 | { 02666 | if ( 02667 | ((1 == mode) && ('\n' == c0)) || 02668 | ((2 == mode) && ( '*' == c0) && ('/' == c1)) 02669 | ) 02670 | { 02671 | mode = 0; 02672 | return true; 02673 | } 02674 | else 02675 | return false; 02676 | } 02677 | }; 02678 | 02679 | int mode = 0; 02680 | int increment = 0; 02681 | 02682 | if (is_end(s_itr_)) 02683 | return; 02684 | else if (!test::comment_start(*s_itr_, *(s_itr_ + 1), mode, increment)) 02685 | return; 02686 | 02687 | details::char_cptr cmt_start = s_itr_; 02688 | 02689 | s_itr_ += increment; 02690 | 02691 | while (!is_end(s_itr_)) 02692 | { 02693 | if (details::is_invalid(*s_itr_)) 02694 | { 02695 | token_t t; 02696 | t.set_error(token::e_error, s_itr_, s_itr_ + 1, base_itr_); 02697 | token_list_.push_back(t); 02698 | return; 02699 | } 02700 | 02701 | if ((1 == mode) && test::comment_end(*s_itr_, 0, mode)) 02702 | { 02703 | ++s_itr_; 02704 | return; 02705 | } 02706 | 02707 | if ((2 == mode)) 02708 | { 02709 | if (!is_end((s_itr_ + 1)) && test::comment_end(*s_itr_, *(s_itr_ + 1), mode)) 02710 | { 02711 | s_itr_ += 2; 02712 | return; 02713 | } 02714 | } 02715 | 02716 | ++s_itr_; 02717 | } 02718 | 02719 | if (2 == mode) 02720 | { 02721 | token_t t; 02722 | t.set_error(token::e_error, cmt_start, cmt_start + mode, base_itr_); 02723 | token_list_.push_back(t); 02724 | } 02725 | #endif 02726 | } 02727 | 02728 | inline bool next_is_digit(const details::char_cptr itr) const 02729 | { 02730 | return ((itr + 1) != s_end_) && 02731 | details::is_digit(*(itr + 1)); 02732 | } 02733 | 02734 | inline void scan_token() 02735 | { 02736 | const char_t c = *s_itr_; 02737 | 02738 | if (details::is_whitespace(c)) 02739 | { 02740 | skip_whitespace(); 02741 | return; 02742 | } 02743 | else if (is_comment_start(s_itr_)) 02744 | { 02745 | skip_comments(); 02746 | return; 02747 | } 02748 | else if (details::is_operator_char(c)) 02749 | { 02750 | scan_operator(); 02751 | return; 02752 | } 02753 | else if (details::is_letter(c)) 02754 | { 02755 | scan_symbol(); 02756 | return; 02757 | } 02758 | else if (('.' == c) && !next_is_digit(s_itr_)) 02759 | { 02760 | scan_operator(); 02761 | return; 02762 | } 02763 | else if (details::is_digit(c) || ('.' == c)) 02764 | { 02765 | scan_number(); 02766 | return; 02767 | } 02768 | else if ('$' == c) 02769 | { 02770 | scan_special_function(); 02771 | return; 02772 | } 02773 | #ifndef exprtk_disable_string_capabilities 02774 | else if ('\'' == c) 02775 | { 02776 | scan_string(); 02777 | return; 02778 | } 02779 | #endif 02780 | else if ('~' == c) 02781 | { 02782 | token_t t; 02783 | t.set_symbol(s_itr_, s_itr_ + 1, base_itr_); 02784 | token_list_.push_back(t); 02785 | ++s_itr_; 02786 | return; 02787 | } 02788 | else 02789 | { 02790 | token_t t; 02791 | t.set_error(token::e_error, s_itr_, s_itr_ + 2, base_itr_); 02792 | token_list_.push_back(t); 02793 | ++s_itr_; 02794 | } 02795 | } 02796 | 02797 | inline void scan_operator() 02798 | { 02799 | token_t t; 02800 | 02801 | const char_t c0 = s_itr_[0]; 02802 | 02803 | if (!is_end(s_itr_ + 1)) 02804 | { 02805 | const char_t c1 = s_itr_[1]; 02806 | 02807 | if (!is_end(s_itr_ + 2)) 02808 | { 02809 | const char_t c2 = s_itr_[2]; 02810 | 02811 | if ((c0 == '<') && (c1 == '=') && (c2 == '>')) 02812 | { 02813 | t.set_operator(token_t::e_swap, s_itr_, s_itr_ + 3, base_itr_); 02814 | token_list_.push_back(t); 02815 | s_itr_ += 3; 02816 | return; 02817 | } 02818 | } 02819 | 02820 | token_t::token_type ttype = token_t::e_none; 02821 | 02822 | if ((c0 == '<') && (c1 == '=')) ttype = token_t::e_lte; 02823 | else if ((c0 == '>') && (c1 == '=')) ttype = token_t::e_gte; 02824 | else if ((c0 == '<') && (c1 == '>')) ttype = token_t::e_ne; 02825 | else if ((c0 == '!') && (c1 == '=')) ttype = token_t::e_ne; 02826 | else if ((c0 == '=') && (c1 == '=')) ttype = token_t::e_eq; 02827 | else if ((c0 == ':') && (c1 == '=')) ttype = token_t::e_assign; 02828 | else if ((c0 == '<') && (c1 == '<')) ttype = token_t::e_shl; 02829 | else if ((c0 == '>') && (c1 == '>')) ttype = token_t::e_shr; 02830 | else if ((c0 == '+') && (c1 == '=')) ttype = token_t::e_addass; 02831 | else if ((c0 == '-') && (c1 == '=')) ttype = token_t::e_subass; 02832 | else if ((c0 == '*') && (c1 == '=')) ttype = token_t::e_mulass; 02833 | else if ((c0 == '/') && (c1 == '=')) ttype = token_t::e_divass; 02834 | else if ((c0 == '%') && (c1 == '=')) ttype = token_t::e_modass; 02835 | 02836 | if (token_t::e_none != ttype) 02837 | { 02838 | t.set_operator(ttype, s_itr_, s_itr_ + 2, base_itr_); 02839 | token_list_.push_back(t); 02840 | s_itr_ += 2; 02841 | return; 02842 | } 02843 | } 02844 | 02845 | if ('<' == c0) 02846 | t.set_operator(token_t::e_lt , s_itr_, s_itr_ + 1, base_itr_); 02847 | else if ('>' == c0) 02848 | t.set_operator(token_t::e_gt , s_itr_, s_itr_ + 1, base_itr_); 02849 | else if (';' == c0) 02850 | t.set_operator(token_t::e_eof, s_itr_, s_itr_ + 1, base_itr_); 02851 | else if ('&' == c0) 02852 | t.set_symbol(s_itr_, s_itr_ + 1, base_itr_); 02853 | else if ('|' == c0) 02854 | t.set_symbol(s_itr_, s_itr_ + 1, base_itr_); 02855 | else 02856 | t.set_operator(token_t::token_type(c0), s_itr_, s_itr_ + 1, base_itr_); 02857 | 02858 | token_list_.push_back(t); 02859 | ++s_itr_; 02860 | } 02861 | 02862 | inline void scan_symbol() 02863 | { 02864 | details::char_cptr initial_itr = s_itr_; 02865 | 02866 | while (!is_end(s_itr_)) 02867 | { 02868 | if (!details::is_letter_or_digit(*s_itr_) && ('_' != (*s_itr_))) 02869 | { 02870 | if ('.' != (*s_itr_)) 02871 | break; 02872 | /* 02873 | Permit symbols that contain a 'dot' 02874 | Allowed : abc.xyz, a123.xyz, abc.123, abc_.xyz a123_.xyz abc._123 02875 | Disallowed: .abc, abc.<white-space>, abc.<eof>, abc.<operator +,-,*,/...> 02876 | */ 02877 | if ( 02878 | (s_itr_ != initial_itr) && 02879 | !is_end(s_itr_ + 1) && 02880 | !details::is_letter_or_digit(*(s_itr_ + 1)) && 02881 | ('_' != (*(s_itr_ + 1))) 02882 | ) 02883 | break; 02884 | } 02885 | 02886 | ++s_itr_; 02887 | } 02888 | 02889 | token_t t; 02890 | t.set_symbol(initial_itr, s_itr_, base_itr_); 02891 | token_list_.push_back(t); 02892 | } 02893 | 02894 | inline void scan_number() 02895 | { 02896 | /* 02897 | Attempt to match a valid numeric value in one of the following formats: 02898 | (01) 123456 02899 | (02) 123456. 02900 | (03) 123.456 02901 | (04) 123.456e3 02902 | (05) 123.456E3 02903 | (06) 123.456e+3 02904 | (07) 123.456E+3 02905 | (08) 123.456e-3 02906 | (09) 123.456E-3 02907 | (00) .1234 02908 | (11) .1234e3 02909 | (12) .1234E+3 02910 | (13) .1234e+3 02911 | (14) .1234E-3 02912 | (15) .1234e-3 02913 | */ 02914 | 02915 | details::char_cptr initial_itr = s_itr_; 02916 | bool dot_found = false; 02917 | bool e_found = false; 02918 | bool post_e_sign_found = false; 02919 | bool post_e_digit_found = false; 02920 | token_t t; 02921 | 02922 | while (!is_end(s_itr_)) 02923 | { 02924 | if ('.' == (*s_itr_)) 02925 | { 02926 | if (dot_found) 02927 | { 02928 | t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_); 02929 | token_list_.push_back(t); 02930 | 02931 | return; 02932 | } 02933 | 02934 | dot_found = true; 02935 | ++s_itr_; 02936 | 02937 | continue; 02938 | } 02939 | else if ('e' == std::tolower(*s_itr_)) 02940 | { 02941 | const char_t& c = *(s_itr_ + 1); 02942 | 02943 | if (is_end(s_itr_ + 1)) 02944 | { 02945 | t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_); 02946 | token_list_.push_back(t); 02947 | 02948 | return; 02949 | } 02950 | else if ( 02951 | ('+' != c) && 02952 | ('-' != c) && 02953 | !details::is_digit(c) 02954 | ) 02955 | { 02956 | t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_); 02957 | token_list_.push_back(t); 02958 | 02959 | return; 02960 | } 02961 | 02962 | e_found = true; 02963 | ++s_itr_; 02964 | 02965 | continue; 02966 | } 02967 | else if (e_found && details::is_sign(*s_itr_) && !post_e_digit_found) 02968 | { 02969 | if (post_e_sign_found) 02970 | { 02971 | t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_); 02972 | token_list_.push_back(t); 02973 | 02974 | return; 02975 | } 02976 | 02977 | post_e_sign_found = true; 02978 | ++s_itr_; 02979 | 02980 | continue; 02981 | } 02982 | else if (e_found && details::is_digit(*s_itr_)) 02983 | { 02984 | post_e_digit_found = true; 02985 | ++s_itr_; 02986 | 02987 | continue; 02988 | } 02989 | else if (('.' != (*s_itr_)) && !details::is_digit(*s_itr_)) 02990 | break; 02991 | else 02992 | ++s_itr_; 02993 | } 02994 | 02995 | t.set_numeric(initial_itr, s_itr_, base_itr_); 02996 | token_list_.push_back(t); 02997 | 02998 | return; 02999 | } 03000 | 03001 | inline void scan_special_function() 03002 | { 03003 | details::char_cptr initial_itr = s_itr_; 03004 | token_t t; 03005 | 03006 | // $fdd(x,x,x) = at least 11 chars 03007 | if (std::distance(s_itr_,s_end_) < 11) 03008 | { 03009 | t.set_error( 03010 | token::e_err_sfunc, 03011 | initial_itr, std::min(initial_itr + 11, s_end_), 03012 | base_itr_); 03013 | token_list_.push_back(t); 03014 | 03015 | return; 03016 | } 03017 | 03018 | if ( 03019 | !(('$' == *s_itr_) && 03020 | (details::imatch ('f',*(s_itr_ + 1))) && 03021 | (details::is_digit(*(s_itr_ + 2))) && 03022 | (details::is_digit(*(s_itr_ + 3)))) 03023 | ) 03024 | { 03025 | t.set_error( 03026 | token::e_err_sfunc, 03027 | initial_itr, std::min(initial_itr + 4, s_end_), 03028 | base_itr_); 03029 | token_list_.push_back(t); 03030 | 03031 | return; 03032 | } 03033 | 03034 | s_itr_ += 4; // $fdd = 4chars 03035 | 03036 | t.set_symbol(initial_itr, s_itr_, base_itr_); 03037 | token_list_.push_back(t); 03038 | 03039 | return; 03040 | } 03041 | 03042 | #ifndef exprtk_disable_string_capabilities 03043 | inline void scan_string() 03044 | { 03045 | details::char_cptr initial_itr = s_itr_ + 1; 03046 | token_t t; 03047 | 03048 | if (std::distance(s_itr_,s_end_) < 2) 03049 | { 03050 | t.set_error(token::e_err_string, s_itr_, s_end_, base_itr_); 03051 | token_list_.push_back(t); 03052 | 03053 | return; 03054 | } 03055 | 03056 | ++s_itr_; 03057 | 03058 | bool escaped_found = false; 03059 | bool escaped = false; 03060 | 03061 | while (!is_end(s_itr_)) 03062 | { 03063 | if (!details::is_valid_string_char(*s_itr_)) 03064 | { 03065 | t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_); 03066 | token_list_.push_back(t); 03067 | 03068 | return; 03069 | } 03070 | else if (!escaped && ('\\' == *s_itr_)) 03071 | { 03072 | escaped_found = true; 03073 | escaped = true; 03074 | ++s_itr_; 03075 | 03076 | continue; 03077 | } 03078 | else if (!escaped) 03079 | { 03080 | if ('\'' == *s_itr_) 03081 | break; 03082 | } 03083 | else if (escaped) 03084 | { 03085 | if ( 03086 | !is_end(s_itr_) && ('0' == *(s_itr_)) && 03087 | ((s_itr_ + 4) <= s_end_) 03088 | ) 03089 | { 03090 | const bool x_separator = ('X' == std::toupper(*(s_itr_ + 1))); 03091 | 03092 | const bool both_digits = details::is_hex_digit(*(s_itr_ + 2)) && 03093 | details::is_hex_digit(*(s_itr_ + 3)) ; 03094 | 03095 | if (!(x_separator && both_digits)) 03096 | { 03097 | t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_); 03098 | token_list_.push_back(t); 03099 | 03100 | return; 03101 | } 03102 | else 03103 | s_itr_ += 3; 03104 | } 03105 | 03106 | escaped = false; 03107 | } 03108 | 03109 | ++s_itr_; 03110 | } 03111 | 03112 | if (is_end(s_itr_)) 03113 | { 03114 | t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_); 03115 | token_list_.push_back(t); 03116 | 03117 | return; 03118 | } 03119 | 03120 | if (!escaped_found) 03121 | t.set_string(initial_itr, s_itr_, base_itr_); 03122 | else 03123 | { 03124 | std::string parsed_string(initial_itr,s_itr_); 03125 | 03126 | if (!details::cleanup_escapes(parsed_string)) 03127 | { 03128 | t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_); 03129 | token_list_.push_back(t); 03130 | 03131 | return; 03132 | } 03133 | 03134 | t.set_string( 03135 | parsed_string, 03136 | static_cast<std::size_t>(std::distance(base_itr_,initial_itr))); 03137 | } 03138 | 03139 | token_list_.push_back(t); 03140 | ++s_itr_; 03141 | 03142 | return; 03143 | } 03144 | #endif 03145 | 03146 | private: 03147 | 03148 | token_list_t token_list_; 03149 | token_list_itr_t token_itr_; 03150 | token_list_itr_t store_token_itr_; 03151 | token_t eof_token_; 03152 | details::char_cptr base_itr_; 03153 | details::char_cptr s_itr_; 03154 | details::char_cptr s_end_; 03155 | 03156 | friend class token_scanner; 03157 | friend class token_modifier; 03158 | friend class token_inserter; 03159 | friend class token_joiner; 03160 | }; // class generator 03161 | 03162 | class helper_interface 03163 | { 03164 | public: 03165 | 03166 | virtual void init() { } 03167 | virtual void reset() { } 03168 | virtual bool result() { return true; } 03169 | virtual std::size_t process(generator&) { return 0; } 03170 | virtual ~helper_interface() { } 03171 | }; 03172 | 03173 | class token_scanner : public helper_interface 03174 | { 03175 | public: 03176 | 03177 | virtual ~token_scanner() exprtk_override 03178 | {} 03179 | 03180 | explicit token_scanner(const std::size_t& stride) 03181 | : stride_(stride) 03182 | { 03183 | if (stride > 4) 03184 | { 03185 | throw std::invalid_argument("token_scanner() - Invalid stride value"); 03186 | } 03187 | } 03188 | 03189 | inline std::size_t process(generator& g) exprtk_override 03190 | { 03191 | if (g.token_list_.size() >= stride_) 03192 | { 03193 | for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i) 03194 | { 03195 | token t; 03196 | 03197 | switch (stride_) 03198 | { 03199 | case 1 : 03200 | { 03201 | const token& t0 = g.token_list_[i]; 03202 | 03203 | if (!operator()(t0)) 03204 | { 03205 | return 0; 03206 | } 03207 | } 03208 | break; 03209 | 03210 | case 2 : 03211 | { 03212 | const token& t0 = g.token_list_[i ]; 03213 | const token& t1 = g.token_list_[i + 1]; 03214 | 03215 | if (!operator()(t0, t1)) 03216 | { 03217 | return 0; 03218 | } 03219 | } 03220 | break; 03221 | 03222 | case 3 : 03223 | { 03224 | const token& t0 = g.token_list_[i ]; 03225 | const token& t1 = g.token_list_[i + 1]; 03226 | const token& t2 = g.token_list_[i + 2]; 03227 | 03228 | if (!operator()(t0, t1, t2)) 03229 | { 03230 | return 0; 03231 | } 03232 | } 03233 | break; 03234 | 03235 | case 4 : 03236 | { 03237 | const token& t0 = g.token_list_[i ]; 03238 | const token& t1 = g.token_list_[i + 1]; 03239 | const token& t2 = g.token_list_[i + 2]; 03240 | const token& t3 = g.token_list_[i + 3]; 03241 | 03242 | if (!operator()(t0, t1, t2, t3)) 03243 | { 03244 | return 0; 03245 | } 03246 | } 03247 | break; 03248 | 03249 | default: continue; 03250 | } 03251 | } 03252 | } 03253 | 03254 | return 0; 03255 | } 03256 | 03257 | virtual bool operator() (const token&) 03258 | { 03259 | return false; 03260 | } 03261 | 03262 | virtual bool operator() (const token&, const token&) 03263 | { 03264 | return false; 03265 | } 03266 | 03267 | virtual bool operator() (const token&, const token&, const token&) 03268 | { 03269 | return false; 03270 | } 03271 | 03272 | virtual bool operator() (const token&, const token&, const token&, const token&) 03273 | { 03274 | return false; 03275 | } 03276 | 03277 | private: 03278 | 03279 | const std::size_t stride_; 03280 | }; // class token_scanner 03281 | 03282 | class token_modifier : public helper_interface 03283 | { 03284 | public: 03285 | 03286 | inline std::size_t process(generator& g) exprtk_override 03287 | { 03288 | std::size_t changes = 0; 03289 | 03290 | for (std::size_t i = 0; i < g.token_list_.size(); ++i) 03291 | { 03292 | if (modify(g.token_list_[i])) changes++; 03293 | } 03294 | 03295 | return changes; 03296 | } 03297 | 03298 | virtual bool modify(token& t) = 0; 03299 | }; 03300 | 03301 | class token_inserter : public helper_interface 03302 | { 03303 | public: 03304 | 03305 | explicit token_inserter(const std::size_t& stride) 03306 | : stride_(stride) 03307 | { 03308 | if (stride > 5) 03309 | { 03310 | throw std::invalid_argument("token_inserter() - Invalid stride value"); 03311 | } 03312 | } 03313 | 03314 | inline std::size_t process(generator& g) exprtk_override 03315 | { 03316 | if (g.token_list_.empty()) 03317 | return 0; 03318 | else if (g.token_list_.size() < stride_) 03319 | return 0; 03320 | 03321 | std::size_t changes = 0; 03322 | 03323 | typedef std::pair<std::size_t, token> insert_t; 03324 | std::vector<insert_t> insert_list; 03325 | insert_list.reserve(10000); 03326 | 03327 | for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i) 03328 | { 03329 | int insert_index = -1; 03330 | token t; 03331 | 03332 | switch (stride_) 03333 | { 03334 | case 1 : insert_index = insert(g.token_list_[i],t); 03335 | break; 03336 | 03337 | case 2 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], t); 03338 | break; 03339 | 03340 | case 3 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], g.token_list_[i + 2], t); 03341 | break; 03342 | 03343 | 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); 03344 | break; 03345 | 03346 | 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); 03347 | break; 03348 | } 03349 | 03350 | if ((insert_index >= 0) && (insert_index <= (static_cast<int>(stride_) + 1))) 03351 | { 03352 | insert_list.push_back(insert_t(i, t)); 03353 | changes++; 03354 | } 03355 | } 03356 | 03357 | if (!insert_list.empty()) 03358 | { 03359 | generator::token_list_t token_list; 03360 | 03361 | std::size_t insert_index = 0; 03362 | 03363 | for (std::size_t i = 0; i < g.token_list_.size(); ++i) 03364 | { 03365 | token_list.push_back(g.token_list_[i]); 03366 | 03367 | if ( 03368 | (insert_index < insert_list.size()) && 03369 | (insert_list[insert_index].first == i) 03370 | ) 03371 | { 03372 | token_list.push_back(insert_list[insert_index].second); 03373 | insert_index++; 03374 | } 03375 | } 03376 | 03377 | std::swap(g.token_list_,token_list); 03378 | } 03379 | 03380 | return changes; 03381 | } 03382 | 03383 | #define token_inserter_empty_body \ 03384 | { \ 03385 | return -1; \ 03386 | } \ 03387 | 03388 | inline virtual int insert(const token&, token&) 03389 | token_inserter_empty_body 03390 | 03391 | inline virtual int insert(const token&, const token&, token&) 03392 | token_inserter_empty_body 03393 | 03394 | inline virtual int insert(const token&, const token&, const token&, token&) 03395 | token_inserter_empty_body 03396 | 03397 | inline virtual int insert(const token&, const token&, const token&, const token&, token&) 03398 | token_inserter_empty_body 03399 | 03400 | inline virtual int insert(const token&, const token&, const token&, const token&, const token&, token&) 03401 | token_inserter_empty_body 03402 | 03403 | #undef token_inserter_empty_body 03404 | 03405 | private: 03406 | 03407 | const std::size_t stride_; 03408 | }; 03409 | 03410 | class token_joiner : public helper_interface 03411 | { 03412 | public: 03413 | 03414 | explicit token_joiner(const std::size_t& stride) 03415 | : stride_(stride) 03416 | {} 03417 | 03418 | inline std::size_t process(generator& g) exprtk_override 03419 | { 03420 | if (g.token_list_.empty()) 03421 | return 0; 03422 | 03423 | switch (stride_) 03424 | { 03425 | case 2 : return process_stride_2(g); 03426 | case 3 : return process_stride_3(g); 03427 | default : return 0; 03428 | } 03429 | } 03430 | 03431 | virtual bool join(const token&, const token&, token&) { return false; } 03432 | virtual bool join(const token&, const token&, const token&, token&) { return false; } 03433 | 03434 | private: 03435 | 03436 | inline std::size_t process_stride_2(generator& g) 03437 | { 03438 | if (g.token_list_.size() < 2) 03439 | return 0; 03440 | 03441 | std::size_t changes = 0; 03442 | 03443 | generator::token_list_t token_list; 03444 | token_list.reserve(10000); 03445 | 03446 | for (int i = 0; i < static_cast<int>(g.token_list_.size() - 1); ++i) 03447 | { 03448 | token t; 03449 | 03450 | for ( ; ; ) 03451 | { 03452 | if (!join(g[i], g[i + 1], t)) 03453 | { 03454 | token_list.push_back(g[i]); 03455 | break; 03456 | } 03457 | 03458 | token_list.push_back(t); 03459 | 03460 | ++changes; 03461 | 03462 | i += 2; 03463 | 03464 | if (static_cast<std::size_t>(i) >= (g.token_list_.size() - 1)) 03465 | break; 03466 | } 03467 | } 03468 | 03469 | token_list.push_back(g.token_list_.back()); 03470 | 03471 | assert(token_list.size() <= g.token_list_.size()); 03472 | 03473 | std::swap(token_list, g.token_list_); 03474 | 03475 | return changes; 03476 | } 03477 | 03478 | inline std::size_t process_stride_3(generator& g) 03479 | { 03480 | if (g.token_list_.size() < 3) 03481 | return 0; 03482 | 03483 | std::size_t changes = 0; 03484 | 03485 | generator::token_list_t token_list; 03486 | token_list.reserve(10000); 03487 | 03488 | for (int i = 0; i < static_cast<int>(g.token_list_.size() - 2); ++i) 03489 | { 03490 | token t; 03491 | 03492 | for ( ; ; ) 03493 | { 03494 | if (!join(g[i], g[i + 1], g[i + 2], t)) 03495 | { 03496 | token_list.push_back(g[i]); 03497 | break; 03498 | } 03499 | 03500 | token_list.push_back(t); 03501 | 03502 | ++changes; 03503 | 03504 | i += 3; 03505 | 03506 | if (static_cast<std::size_t>(i) >= (g.token_list_.size() - 2)) 03507 | break; 03508 | } 03509 | } 03510 | 03511 | token_list.push_back(*(g.token_list_.begin() + g.token_list_.size() - 2)); 03512 | token_list.push_back(*(g.token_list_.begin() + g.token_list_.size() - 1)); 03513 | 03514 | assert(token_list.size() <= g.token_list_.size()); 03515 | 03516 | std::swap(token_list, g.token_list_); 03517 | 03518 | return changes; 03519 | } 03520 | 03521 | const std::size_t stride_; 03522 | }; 03523 | 03524 | namespace helper 03525 | { 03526 | 03527 | inline void dump(const lexer::generator& generator) 03528 | { 03529 | for (std::size_t i = 0; i < generator.size(); ++i) 03530 | { 03531 | const lexer::token& t = generator[i]; 03532 | printf("Token[%02d] @ %03d %6s --> '%s'\n", 03533 | static_cast<int>(i), 03534 | static_cast<int>(t.position), 03535 | t.to_str(t.type).c_str(), 03536 | t.value.c_str()); 03537 | } 03538 | } 03539 | 03540 | class commutative_inserter : public lexer::token_inserter 03541 | { 03542 | public: 03543 | 03544 | using lexer::token_inserter::insert; 03545 | 03546 | commutative_inserter() 03547 | : lexer::token_inserter(2) 03548 | {} 03549 | 03550 | inline void ignore_symbol(const std::string& symbol) 03551 | { 03552 | ignore_set_.insert(symbol); 03553 | } 03554 | 03555 | inline int insert(const lexer::token& t0, const lexer::token& t1, lexer::token& new_token) exprtk_override 03556 | { 03557 | bool match = false; 03558 | new_token.type = lexer::token::e_mul; 03559 | new_token.value = "*" 03560 | new_token.position = t1.position; 03561 | 03562 | if (t0.type == lexer::token::e_symbol) 03563 | { 03564 | if (ignore_set_.end() != ignore_set_.find(t0.value)) 03565 | { 03566 | return -1; 03567 | } 03568 | else if (!t0.value.empty() && ('$' == t0.value[0])) 03569 | { 03570 | return -1; 03571 | } 03572 | } 03573 | 03574 | if (t1.type == lexer::token::e_symbol) 03575 | { 03576 | if (ignore_set_.end() != ignore_set_.find(t1.value)) 03577 | { 03578 | return -1; 03579 | } 03580 | } 03581 | if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_symbol )) match = true; 03582 | else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lbracket )) match = true; 03583 | else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lcrlbracket)) match = true; 03584 | else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lsqrbracket)) match = true; 03585 | else if ((t0.type == lexer::token::e_symbol ) && (t1.type == lexer::token::e_number )) match = true; 03586 | else if ((t0.type == lexer::token::e_rbracket ) && (t1.type == lexer::token::e_number )) match = true; 03587 | else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_number )) match = true; 03588 | else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_number )) match = true; 03589 | else if ((t0.type == lexer::token::e_rbracket ) && (t1.type == lexer::token::e_symbol )) match = true; 03590 | else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_symbol )) match = true; 03591 | else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_symbol )) match = true; 03592 | else if ((t0.type == lexer::token::e_symbol ) && (t1.type == lexer::token::e_symbol )) match = true; 03593 | 03594 | return (match) ? 1 : -1; 03595 | } 03596 | 03597 | private: 03598 | 03599 | std::set<std::string,details::ilesscompare> ignore_set_; 03600 | }; 03601 | 03602 | class operator_joiner exprtk_final : public token_joiner 03603 | { 03604 | public: 03605 | 03606 | explicit operator_joiner(const std::size_t& stride) 03607 | : token_joiner(stride) 03608 | {} 03609 | 03610 | inline bool join(const lexer::token& t0, const lexer::token& t1, lexer::token& t) exprtk_override 03611 | { 03612 | // ': =' --> ':=' 03613 | if ((t0.type == lexer::token::e_colon) && (t1.type == lexer::token::e_eq)) 03614 | { 03615 | t.type = lexer::token::e_assign; 03616 | t.value = ":=" 03617 | t.position = t0.position; 03618 | 03619 | return true; 03620 | } 03621 | // '+ =' --> '+=' 03622 | else if ((t0.type == lexer::token::e_add) && (t1.type == lexer::token::e_eq)) 03623 | { 03624 | t.type = lexer::token::e_addass; 03625 | t.value = "+=" 03626 | t.position = t0.position; 03627 | 03628 | return true; 03629 | } 03630 | // '- =' --> '-=' 03631 | else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_eq)) 03632 | { 03633 | t.type = lexer::token::e_subass; 03634 | t.value = "-=" 03635 | t.position = t0.position; 03636 | 03637 | return true; 03638 | } 03639 | // '* =' --> '*=' 03640 | else if ((t0.type == lexer::token::e_mul) && (t1.type == lexer::token::e_eq)) 03641 | { 03642 | t.type = lexer::token::e_mulass; 03643 | t.value = "*=" 03644 | t.position = t0.position; 03645 | 03646 | return true; 03647 | } 03648 | // '/ =' --> '/=' 03649 | else if ((t0.type == lexer::token::e_div) && (t1.type == lexer::token::e_eq)) 03650 | { 03651 | t.type = lexer::token::e_divass; 03652 | t.value = "/=" 03653 | t.position = t0.position; 03654 | 03655 | return true; 03656 | } 03657 | // '% =' --> '%=' 03658 | else if ((t0.type == lexer::token::e_mod) && (t1.type == lexer::token::e_eq)) 03659 | { 03660 | t.type = lexer::token::e_modass; 03661 | t.value = "%=" 03662 | t.position = t0.position; 03663 | 03664 | return true; 03665 | } 03666 | // '> =' --> '>=' 03667 | else if ((t0.type == lexer::token::e_gt) && (t1.type == lexer::token::e_eq)) 03668 | { 03669 | t.type = lexer::token::e_gte; 03670 | t.value = ">=" 03671 | t.position = t0.position; 03672 | 03673 | return true; 03674 | } 03675 | // '< =' --> '<=' 03676 | else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_eq)) 03677 | { 03678 | t.type = lexer::token::e_lte; 03679 | t.value = "<=" 03680 | t.position = t0.position; 03681 | 03682 | return true; 03683 | } 03684 | // '= =' --> '==' 03685 | else if ((t0.type == lexer::token::e_eq) && (t1.type == lexer::token::e_eq)) 03686 | { 03687 | t.type = lexer::token::e_eq; 03688 | t.value = "==" 03689 | t.position = t0.position; 03690 | 03691 | return true; 03692 | } 03693 | // '! =' --> '!=' 03694 | else if ((static_cast<details::char_t>(t0.type) == '!') && (t1.type == lexer::token::e_eq)) 03695 | { 03696 | t.type = lexer::token::e_ne; 03697 | t.value = "!=" 03698 | t.position = t0.position; 03699 | 03700 | return true; 03701 | } 03702 | // '< >' --> '<>' 03703 | else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_gt)) 03704 | { 03705 | t.type = lexer::token::e_ne; 03706 | t.value = "<>" 03707 | t.position = t0.position; 03708 | 03709 | return true; 03710 | } 03711 | // '<= >' --> '<=>' 03712 | else if ((t0.type == lexer::token::e_lte) && (t1.type == lexer::token::e_gt)) 03713 | { 03714 | t.type = lexer::token::e_swap; 03715 | t.value = "<=>" 03716 | t.position = t0.position; 03717 | 03718 | return true; 03719 | } 03720 | // '+ -' --> '-' 03721 | else if ((t0.type == lexer::token::e_add) && (t1.type == lexer::token::e_sub)) 03722 | { 03723 | t.type = lexer::token::e_sub; 03724 | t.value = "-" 03725 | t.position = t0.position; 03726 | 03727 | return true; 03728 | } 03729 | // '- +' --> '-' 03730 | else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_add)) 03731 | { 03732 | t.type = lexer::token::e_sub; 03733 | t.value = "-" 03734 | t.position = t0.position; 03735 | 03736 | return true; 03737 | } 03738 | // '- -' --> '+' 03739 | else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_sub)) 03740 | { 03741 | /* 03742 | Note: May need to reconsider this when wanting to implement 03743 | pre/postfix decrement operator 03744 | */ 03745 | t.type = lexer::token::e_add; 03746 | t.value = "+" 03747 | t.position = t0.position; 03748 | 03749 | return true; 03750 | } 03751 | else 03752 | return false; 03753 | } 03754 | 03755 | inline bool join(const lexer::token& t0, 03756 | const lexer::token& t1, 03757 | const lexer::token& t2, 03758 | lexer::token& t) exprtk_override 03759 | { 03760 | // '[ * ]' --> '[*]' 03761 | if ( 03762 | (t0.type == lexer::token::e_lsqrbracket) && 03763 | (t1.type == lexer::token::e_mul ) && 03764 | (t2.type == lexer::token::e_rsqrbracket) 03765 | ) 03766 | { 03767 | t.type = lexer::token::e_symbol; 03768 | t.value = "[*]" 03769 | t.position = t0.position; 03770 | 03771 | return true; 03772 | } 03773 | else 03774 | return false; 03775 | } 03776 | }; 03777 | 03778 | class bracket_checker exprtk_final : public lexer::token_scanner 03779 | { 03780 | public: 03781 | 03782 | using lexer::token_scanner::operator(); 03783 | 03784 | bracket_checker() 03785 | : token_scanner(1) 03786 | , state_(true) 03787 | {} 03788 | 03789 | bool result() exprtk_override 03790 | { 03791 | if (!stack_.empty()) 03792 | { 03793 | lexer::token t; 03794 | t.value = stack_.top().first; 03795 | t.position = stack_.top().second; 03796 | error_token_ = t; 03797 | state_ = false; 03798 | 03799 | return false; 03800 | } 03801 | else 03802 | return state_; 03803 | } 03804 | 03805 | lexer::token error_token() const 03806 | { 03807 | return error_token_; 03808 | } 03809 | 03810 | void reset() exprtk_override 03811 | { 03812 | // Why? because msvc doesn't support swap properly. 03813 | stack_ = std::stack<std::pair<char,std::size_t> >(); 03814 | state_ = true; 03815 | error_token_.clear(); 03816 | } 03817 | 03818 | bool operator() (const lexer::token& t) exprtk_override 03819 | { 03820 | if ( 03821 | !t.value.empty() && 03822 | (lexer::token::e_string != t.type) && 03823 | (lexer::token::e_symbol != t.type) && 03824 | exprtk::details::is_bracket(t.value[0]) 03825 | ) 03826 | { 03827 | details::char_t c = t.value[0]; 03828 | 03829 | if (t.type == lexer::token::e_lbracket ) stack_.push(std::make_pair(')',t.position)); 03830 | else if (t.type == lexer::token::e_lcrlbracket) stack_.push(std::make_pair('}',t.position)); 03831 | else if (t.type == lexer::token::e_lsqrbracket) stack_.push(std::make_pair(']',t.position)); 03832 | else if (exprtk::details::is_right_bracket(c)) 03833 | { 03834 | if (stack_.empty()) 03835 | { 03836 | state_ = false; 03837 | error_token_ = t; 03838 | 03839 | return false; 03840 | } 03841 | else if (c != stack_.top().first) 03842 | { 03843 | state_ = false; 03844 | error_token_ = t; 03845 | 03846 | return false; 03847 | } 03848 | else 03849 | stack_.pop(); 03850 | } 03851 | } 03852 | 03853 | return true; 03854 | } 03855 | 03856 | private: 03857 | 03858 | bool state_; 03859 | std::stack<std::pair<char,std::size_t> > stack_; 03860 | lexer::token error_token_; 03861 | }; 03862 | 03863 | template <typename T> 03864 | class numeric_checker exprtk_final : public lexer::token_scanner 03865 | { 03866 | public: 03867 | 03868 | using lexer::token_scanner::operator(); 03869 | 03870 | numeric_checker() 03871 | : token_scanner (1) 03872 | , current_index_(0) 03873 | {} 03874 | 03875 | bool result() exprtk_override 03876 | { 03877 | return error_list_.empty(); 03878 | } 03879 | 03880 | void reset() exprtk_override 03881 | { 03882 | error_list_.clear(); 03883 | current_index_ = 0; 03884 | } 03885 | 03886 | bool operator() (const lexer::token& t) exprtk_override 03887 | { 03888 | if (token::e_number == t.type) 03889 | { 03890 | T v; 03891 | 03892 | if (!exprtk::details::string_to_real(t.value,v)) 03893 | { 03894 | error_list_.push_back(current_index_); 03895 | } 03896 | } 03897 | 03898 | ++current_index_; 03899 | 03900 | return true; 03901 | } 03902 | 03903 | std::size_t error_count() const 03904 | { 03905 | return error_list_.size(); 03906 | } 03907 | 03908 | std::size_t error_index(const std::size_t& i) const 03909 | { 03910 | if (i < error_list_.size()) 03911 | return error_list_[i]; 03912 | else 03913 | return std::numeric_limits<std::size_t>::max(); 03914 | } 03915 | 03916 | void clear_errors() 03917 | { 03918 | error_list_.clear(); 03919 | } 03920 | 03921 | private: 03922 | 03923 | std::size_t current_index_; 03924 | std::vector<std::size_t> error_list_; 03925 | }; 03926 | 03927 | class symbol_replacer exprtk_final : public lexer::token_modifier 03928 | { 03929 | private: 03930 | 03931 | typedef std::map<std::string,std::pair<std::string,token::token_type>,details::ilesscompare> replace_map_t; 03932 | 03933 | public: 03934 | 03935 | bool remove(const std::string& target_symbol) 03936 | { 03937 | const replace_map_t::iterator itr = replace_map_.find(target_symbol); 03938 | 03939 | if (replace_map_.end() == itr) 03940 | return false; 03941 | 03942 | replace_map_.erase(itr); 03943 | 03944 | return true; 03945 | } 03946 | 03947 | bool add_replace(const std::string& target_symbol, 03948 | const std::string& replace_symbol, 03949 | const lexer::token::token_type token_type = lexer::token::e_symbol) 03950 | { 03951 | const replace_map_t::iterator itr = replace_map_.find(target_symbol); 03952 | 03953 | if (replace_map_.end() != itr) 03954 | { 03955 | return false; 03956 | } 03957 | 03958 | replace_map_[target_symbol] = std::make_pair(replace_symbol,token_type); 03959 | 03960 | return true; 03961 | } 03962 | 03963 | void clear() 03964 | { 03965 | replace_map_.clear(); 03966 | } 03967 | 03968 | private: 03969 | 03970 | bool modify(lexer::token& t) exprtk_override 03971 | { 03972 | if (lexer::token::e_symbol == t.type) 03973 | { 03974 | if (replace_map_.empty()) 03975 | return false; 03976 | 03977 | const replace_map_t::iterator itr = replace_map_.find(t.value); 03978 | 03979 | if (replace_map_.end() != itr) 03980 | { 03981 | t.value = itr->second.first; 03982 | t.type = itr->second.second; 03983 | 03984 | return true; 03985 | } 03986 | } 03987 | 03988 | return false; 03989 | } 03990 | 03991 | replace_map_t replace_map_; 03992 | }; 03993 | 03994 | class sequence_validator exprtk_final : public lexer::token_scanner 03995 | { 03996 | private: 03997 | 03998 | typedef std::pair<lexer::token::token_type,lexer::token::token_type> token_pair_t; 03999 | typedef std::set<token_pair_t> set_t; 04000 | 04001 | public: 04002 | 04003 | using lexer::token_scanner::operator(); 04004 | 04005 | sequence_validator() 04006 | : lexer::token_scanner(2) 04007 | { 04008 | add_invalid(lexer::token::e_number, lexer::token::e_number); 04009 | add_invalid(lexer::token::e_string, lexer::token::e_string); 04010 | add_invalid(lexer::token::e_number, lexer::token::e_string); 04011 | add_invalid(lexer::token::e_string, lexer::token::e_number); 04012 | 04013 | add_invalid_set1(lexer::token::e_assign ); 04014 | add_invalid_set1(lexer::token::e_shr ); 04015 | add_invalid_set1(lexer::token::e_shl ); 04016 | add_invalid_set1(lexer::token::e_lte ); 04017 | add_invalid_set1(lexer::token::e_ne ); 04018 | add_invalid_set1(lexer::token::e_gte ); 04019 | add_invalid_set1(lexer::token::e_lt ); 04020 | add_invalid_set1(lexer::token::e_gt ); 04021 | add_invalid_set1(lexer::token::e_eq ); 04022 | add_invalid_set1(lexer::token::e_comma ); 04023 | add_invalid_set1(lexer::token::e_add ); 04024 | add_invalid_set1(lexer::token::e_sub ); 04025 | add_invalid_set1(lexer::token::e_div ); 04026 | add_invalid_set1(lexer::token::e_mul ); 04027 | add_invalid_set1(lexer::token::e_mod ); 04028 | add_invalid_set1(lexer::token::e_pow ); 04029 | add_invalid_set1(lexer::token::e_colon ); 04030 | add_invalid_set1(lexer::token::e_ternary); 04031 | } 04032 | 04033 | bool result() exprtk_override 04034 | { 04035 | return error_list_.empty(); 04036 | } 04037 | 04038 | bool operator() (const lexer::token& t0, const lexer::token& t1) exprtk_override 04039 | { 04040 | const set_t::value_type p = std::make_pair(t0.type,t1.type); 04041 | 04042 | if (invalid_bracket_check(t0.type,t1.type)) 04043 | { 04044 | error_list_.push_back(std::make_pair(t0,t1)); 04045 | } 04046 | else if (invalid_comb_.find(p) != invalid_comb_.end()) 04047 | { 04048 | error_list_.push_back(std::make_pair(t0,t1)); 04049 | } 04050 | 04051 | return true; 04052 | } 04053 | 04054 | std::size_t error_count() const 04055 | { 04056 | return error_list_.size(); 04057 | } 04058 | 04059 | std::pair<lexer::token,lexer::token> error(const std::size_t index) 04060 | { 04061 | if (index < error_list_.size()) 04062 | { 04063 | return error_list_[index]; 04064 | } 04065 | else 04066 | { 04067 | static const lexer::token error_token; 04068 | return std::make_pair(error_token,error_token); 04069 | } 04070 | } 04071 | 04072 | void clear_errors() 04073 | { 04074 | error_list_.clear(); 04075 | } 04076 | 04077 | private: 04078 | 04079 | void add_invalid(const lexer::token::token_type base, const lexer::token::token_type t) 04080 | { 04081 | invalid_comb_.insert(std::make_pair(base,t)); 04082 | } 04083 | 04084 | void add_invalid_set1(const lexer::token::token_type t) 04085 | { 04086 | add_invalid(t, lexer::token::e_assign); 04087 | add_invalid(t, lexer::token::e_shr ); 04088 | add_invalid(t, lexer::token::e_shl ); 04089 | add_invalid(t, lexer::token::e_lte ); 04090 | add_invalid(t, lexer::token::e_ne ); 04091 | add_invalid(t, lexer::token::e_gte ); 04092 | add_invalid(t, lexer::token::e_lt ); 04093 | add_invalid(t, lexer::token::e_gt ); 04094 | add_invalid(t, lexer::token::e_eq ); 04095 | add_invalid(t, lexer::token::e_comma ); 04096 | add_invalid(t, lexer::token::e_div ); 04097 | add_invalid(t, lexer::token::e_mul ); 04098 | add_invalid(t, lexer::token::e_mod ); 04099 | add_invalid(t, lexer::token::e_pow ); 04100 | add_invalid(t, lexer::token::e_colon ); 04101 | } 04102 | 04103 | bool invalid_bracket_check(const lexer::token::token_type base, const lexer::token::token_type t) 04104 | { 04105 | if (details::is_right_bracket(static_cast<details::char_t>(base))) 04106 | { 04107 | switch (t) 04108 | { 04109 | case lexer::token::e_assign : return (']' != base); 04110 | case lexer::token::e_string : return (')' != base); 04111 | default : return false; 04112 | } 04113 | } 04114 | else if (details::is_left_bracket(static_cast<details::char_t>(base))) 04115 | { 04116 | if (details::is_right_bracket(static_cast<details::char_t>(t))) 04117 | return false; 04118 | else if (details::is_left_bracket(static_cast<details::char_t>(t))) 04119 | return false; 04120 | else 04121 | { 04122 | switch (t) 04123 | { 04124 | case lexer::token::e_number : return false; 04125 | case lexer::token::e_symbol : return false; 04126 | case lexer::token::e_string : return false; 04127 | case lexer::token::e_add : return false; 04128 | case lexer::token::e_sub : return false; 04129 | case lexer::token::e_colon : return false; 04130 | case lexer::token::e_ternary : return false; 04131 | default : return true ; 04132 | } 04133 | } 04134 | } 04135 | else if (details::is_right_bracket(static_cast<details::char_t>(t))) 04136 | { 04137 | switch (base) 04138 | { 04139 | case lexer::token::e_number : return false; 04140 | case lexer::token::e_symbol : return false; 04141 | case lexer::token::e_string : return false; 04142 | case lexer::token::e_eof : return false; 04143 | case lexer::token::e_colon : return false; 04144 | case lexer::token::e_ternary : return false; 04145 | default : return true ; 04146 | } 04147 | } 04148 | else if (details::is_left_bracket(static_cast<details::char_t>(t))) 04149 | { 04150 | switch (base) 04151 | { 04152 | case lexer::token::e_rbracket : return true; 04153 | case lexer::token::e_rsqrbracket : return true; 04154 | case lexer::token::e_rcrlbracket : return true; 04155 | default : return false; 04156 | } 04157 | } 04158 | 04159 | return false; 04160 | } 04161 | 04162 | set_t invalid_comb_; 04163 | std::vector<std::pair<lexer::token,lexer::token> > error_list_; 04164 | }; 04165 | 04166 | class sequence_validator_3tokens exprtk_final : public lexer::token_scanner 04167 | { 04168 | private: 04169 | 04170 | typedef lexer::token::token_type token_t; 04171 | typedef std::pair<token_t,std::pair<token_t,token_t> > token_triplet_t; 04172 | typedef std::set<token_triplet_t> set_t; 04173 | 04174 | public: 04175 | 04176 | using lexer::token_scanner::operator(); 04177 | 04178 | sequence_validator_3tokens() 04179 | : lexer::token_scanner(3) 04180 | { 04181 | add_invalid(lexer::token::e_number , lexer::token::e_number , lexer::token::e_number); 04182 | add_invalid(lexer::token::e_string , lexer::token::e_string , lexer::token::e_string); 04183 | add_invalid(lexer::token::e_comma , lexer::token::e_comma , lexer::token::e_comma ); 04184 | 04185 | add_invalid(lexer::token::e_add , lexer::token::e_add , lexer::token::e_add ); 04186 | add_invalid(lexer::token::e_sub , lexer::token::e_sub , lexer::token::e_sub ); 04187 | add_invalid(lexer::token::e_div , lexer::token::e_div , lexer::token::e_div ); 04188 | add_invalid(lexer::token::e_mul , lexer::token::e_mul , lexer::token::e_mul ); 04189 | add_invalid(lexer::token::e_mod , lexer::token::e_mod , lexer::token::e_mod ); 04190 | add_invalid(lexer::token::e_pow , lexer::token::e_pow , lexer::token::e_pow ); 04191 | 04192 | add_invalid(lexer::token::e_add , lexer::token::e_sub , lexer::token::e_add ); 04193 | add_invalid(lexer::token::e_sub , lexer::token::e_add , lexer::token::e_sub ); 04194 | add_invalid(lexer::token::e_div , lexer::token::e_mul , lexer::token::e_div ); 04195 | add_invalid(lexer::token::e_mul , lexer::token::e_div , lexer::token::e_mul ); 04196 | add_invalid(lexer::token::e_mod , lexer::token::e_pow , lexer::token::e_mod ); 04197 | add_invalid(lexer::token::e_pow , lexer::token::e_mod , lexer::token::e_pow ); 04198 | } 04199 | 04200 | bool result() exprtk_override 04201 | { 04202 | return error_list_.empty(); 04203 | } 04204 | 04205 | bool operator() (const lexer::token& t0, const lexer::token& t1, const lexer::token& t2) exprtk_override 04206 | { 04207 | const set_t::value_type p = std::make_pair(t0.type,std::make_pair(t1.type,t2.type)); 04208 | 04209 | if (invalid_comb_.find(p) != invalid_comb_.end()) 04210 | { 04211 | error_list_.push_back(std::make_pair(t0,t1)); 04212 | } 04213 | 04214 | return true; 04215 | } 04216 | 04217 | std::size_t error_count() const 04218 | { 04219 | return error_list_.size(); 04220 | } 04221 | 04222 | std::pair<lexer::token,lexer::token> error(const std::size_t index) 04223 | { 04224 | if (index < error_list_.size()) 04225 | { 04226 | return error_list_[index]; 04227 | } 04228 | else 04229 | { 04230 | static const lexer::token error_token; 04231 | return std::make_pair(error_token,error_token); 04232 | } 04233 | } 04234 | 04235 | void clear_errors() 04236 | { 04237 | error_list_.clear(); 04238 | } 04239 | 04240 | private: 04241 | 04242 | void add_invalid(const token_t t0, const token_t t1, const token_t t2) 04243 | { 04244 | invalid_comb_.insert(std::make_pair(t0,std::make_pair(t1,t2))); 04245 | } 04246 | 04247 | set_t invalid_comb_; 04248 | std::vector<std::pair<lexer::token,lexer::token> > error_list_; 04249 | }; 04250 | 04251 | struct helper_assembly 04252 | { 04253 | inline bool register_scanner(lexer::token_scanner* scanner) 04254 | { 04255 | if (token_scanner_list.end() != std::find(token_scanner_list.begin(), 04256 | token_scanner_list.end (), 04257 | scanner)) 04258 | { 04259 | return false; 04260 | } 04261 | 04262 | token_scanner_list.push_back(scanner); 04263 | 04264 | return true; 04265 | } 04266 | 04267 | inline bool register_modifier(lexer::token_modifier* modifier) 04268 | { 04269 | if (token_modifier_list.end() != std::find(token_modifier_list.begin(), 04270 | token_modifier_list.end (), 04271 | modifier)) 04272 | { 04273 | return false; 04274 | } 04275 | 04276 | token_modifier_list.push_back(modifier); 04277 | 04278 | return true; 04279 | } 04280 | 04281 | inline bool register_joiner(lexer::token_joiner* joiner) 04282 | { 04283 | if (token_joiner_list.end() != std::find(token_joiner_list.begin(), 04284 | token_joiner_list.end (), 04285 | joiner)) 04286 | { 04287 | return false; 04288 | } 04289 | 04290 | token_joiner_list.push_back(joiner); 04291 | 04292 | return true; 04293 | } 04294 | 04295 | inline bool register_inserter(lexer::token_inserter* inserter) 04296 | { 04297 | if (token_inserter_list.end() != std::find(token_inserter_list.begin(), 04298 | token_inserter_list.end (), 04299 | inserter)) 04300 | { 04301 | return false; 04302 | } 04303 | 04304 | token_inserter_list.push_back(inserter); 04305 | 04306 | return true; 04307 | } 04308 | 04309 | inline bool run_modifiers(lexer::generator& g) 04310 | { 04311 | error_token_modifier = reinterpret_cast<lexer::token_modifier*>(0); 04312 | 04313 | for (std::size_t i = 0; i < token_modifier_list.size(); ++i) 04314 | { 04315 | lexer::token_modifier& modifier = (*token_modifier_list[i]); 04316 | 04317 | modifier.reset(); 04318 | modifier.process(g); 04319 | 04320 | if (!modifier.result()) 04321 | { 04322 | error_token_modifier = token_modifier_list[i]; 04323 | 04324 | return false; 04325 | } 04326 | } 04327 | 04328 | return true; 04329 | } 04330 | 04331 | inline bool run_joiners(lexer::generator& g) 04332 | { 04333 | error_token_joiner = reinterpret_cast<lexer::token_joiner*>(0); 04334 | 04335 | for (std::size_t i = 0; i < token_joiner_list.size(); ++i) 04336 | { 04337 | lexer::token_joiner& joiner = (*token_joiner_list[i]); 04338 | 04339 | joiner.reset(); 04340 | joiner.process(g); 04341 | 04342 | if (!joiner.result()) 04343 | { 04344 | error_token_joiner = token_joiner_list[i]; 04345 | 04346 | return false; 04347 | } 04348 | } 04349 | 04350 | return true; 04351 | } 04352 | 04353 | inline bool run_inserters(lexer::generator& g) 04354 | { 04355 | error_token_inserter = reinterpret_cast<lexer::token_inserter*>(0); 04356 | 04357 | for (std::size_t i = 0; i < token_inserter_list.size(); ++i) 04358 | { 04359 | lexer::token_inserter& inserter = (*token_inserter_list[i]); 04360 | 04361 | inserter.reset(); 04362 | inserter.process(g); 04363 | 04364 | if (!inserter.result()) 04365 | { 04366 | error_token_inserter = token_inserter_list[i]; 04367 | 04368 | return false; 04369 | } 04370 | } 04371 | 04372 | return true; 04373 | } 04374 | 04375 | inline bool run_scanners(lexer::generator& g) 04376 | { 04377 | error_token_scanner = reinterpret_cast<lexer::token_scanner*>(0); 04378 | 04379 | for (std::size_t i = 0; i < token_scanner_list.size(); ++i) 04380 | { 04381 | lexer::token_scanner& scanner = (*token_scanner_list[i]); 04382 | 04383 | scanner.reset(); 04384 | scanner.process(g); 04385 | 04386 | if (!scanner.result()) 04387 | { 04388 | error_token_scanner = token_scanner_list[i]; 04389 | 04390 | return false; 04391 | } 04392 | } 04393 | 04394 | return true; 04395 | } 04396 | 04397 | std::vector<lexer::token_scanner*> token_scanner_list; 04398 | std::vector<lexer::token_modifier*> token_modifier_list; 04399 | std::vector<lexer::token_joiner*> token_joiner_list; 04400 | std::vector<lexer::token_inserter*> token_inserter_list; 04401 | 04402 | lexer::token_scanner* error_token_scanner; 04403 | lexer::token_modifier* error_token_modifier; 04404 | lexer::token_joiner* error_token_joiner; 04405 | lexer::token_inserter* error_token_inserter; 04406 | }; 04407 | } 04408 | 04409 | class parser_helper 04410 | { 04411 | public: 04412 | 04413 | typedef token token_t; 04414 | typedef generator generator_t; 04415 | 04416 | inline bool init(const std::string& str) 04417 | { 04418 | if (!lexer_.process(str)) 04419 | { 04420 | return false; 04421 | } 04422 | 04423 | lexer_.begin(); 04424 | 04425 | next_token(); 04426 | 04427 | return true; 04428 | } 04429 | 04430 | inline generator_t& lexer() 04431 | { 04432 | return lexer_; 04433 | } 04434 | 04435 | inline const generator_t& lexer() const 04436 | { 04437 | return lexer_; 04438 | } 04439 | 04440 | inline void store_token() 04441 | { 04442 | lexer_.store(); 04443 | store_current_token_ = current_token_; 04444 | } 04445 | 04446 | inline void restore_token() 04447 | { 04448 | lexer_.restore(); 04449 | current_token_ = store_current_token_; 04450 | } 04451 | 04452 | inline void next_token() 04453 | { 04454 | current_token_ = lexer_.next_token(); 04455 | } 04456 | 04457 | inline const token_t& current_token() const 04458 | { 04459 | return current_token_; 04460 | } 04461 | 04462 | inline const token_t& peek_next_token() 04463 | { 04464 | return lexer_.peek_next_token(); 04465 | } 04466 | 04467 | enum token_advance_mode 04468 | { 04469 | e_hold = 0, 04470 | e_advance = 1 04471 | }; 04472 | 04473 | inline void advance_token(const token_advance_mode mode) 04474 | { 04475 | if (e_advance == mode) 04476 | { 04477 | next_token(); 04478 | } 04479 | } 04480 | 04481 | inline bool token_is(const token_t::token_type& ttype, const token_advance_mode mode = e_advance) 04482 | { 04483 | if (current_token().type != ttype) 04484 | { 04485 | return false; 04486 | } 04487 | 04488 | advance_token(mode); 04489 | 04490 | return true; 04491 | } 04492 | 04493 | inline bool token_is(const token_t::token_type& ttype, 04494 | const std::string& value, 04495 | const token_advance_mode mode = e_advance) 04496 | { 04497 | if ( 04498 | (current_token().type != ttype) || 04499 | !exprtk::details::imatch(value,current_token().value) 04500 | ) 04501 | { 04502 | return false; 04503 | } 04504 | 04505 | advance_token(mode); 04506 | 04507 | return true; 04508 | } 04509 | 04510 | inline bool token_is(const std::string& value, 04511 | const token_advance_mode mode = e_advance) 04512 | { 04513 | if (!exprtk::details::imatch(value,current_token().value)) 04514 | { 04515 | return false; 04516 | } 04517 | 04518 | advance_token(mode); 04519 | 04520 | return true; 04521 | } 04522 | 04523 | inline bool token_is_arithmetic_opr(const token_advance_mode mode = e_advance) 04524 | { 04525 | switch (current_token().type) 04526 | { 04527 | case token_t::e_add : 04528 | case token_t::e_sub : 04529 | case token_t::e_div : 04530 | case token_t::e_mul : 04531 | case token_t::e_mod : 04532 | case token_t::e_pow : break; 04533 | default : return false; 04534 | } 04535 | 04536 | advance_token(mode); 04537 | 04538 | return true; 04539 | } 04540 | 04541 | inline bool token_is_ineq_opr(const token_advance_mode mode = e_advance) 04542 | { 04543 | switch (current_token().type) 04544 | { 04545 | case token_t::e_eq : 04546 | case token_t::e_lte : 04547 | case token_t::e_ne : 04548 | case token_t::e_gte : 04549 | case token_t::e_lt : 04550 | case token_t::e_gt : break; 04551 | default : return false; 04552 | } 04553 | 04554 | advance_token(mode); 04555 | 04556 | return true; 04557 | } 04558 | 04559 | inline bool token_is_left_bracket(const token_advance_mode mode = e_advance) 04560 | { 04561 | switch (current_token().type) 04562 | { 04563 | case token_t::e_lbracket : 04564 | case token_t::e_lcrlbracket : 04565 | case token_t::e_lsqrbracket : break; 04566 | default : return false; 04567 | } 04568 | 04569 | advance_token(mode); 04570 | 04571 | return true; 04572 | } 04573 | 04574 | inline bool token_is_right_bracket(const token_advance_mode mode = e_advance) 04575 | { 04576 | switch (current_token().type) 04577 | { 04578 | case token_t::e_rbracket : 04579 | case token_t::e_rcrlbracket : 04580 | case token_t::e_rsqrbracket : break; 04581 | default : return false; 04582 | } 04583 | 04584 | advance_token(mode); 04585 | 04586 | return true; 04587 | } 04588 | 04589 | inline bool token_is_bracket(const token_advance_mode mode = e_advance) 04590 | { 04591 | switch (current_token().type) 04592 | { 04593 | case token_t::e_rbracket : 04594 | case token_t::e_rcrlbracket : 04595 | case token_t::e_rsqrbracket : 04596 | case token_t::e_lbracket : 04597 | case token_t::e_lcrlbracket : 04598 | case token_t::e_lsqrbracket : break; 04599 | default : return false; 04600 | } 04601 | 04602 | advance_token(mode); 04603 | 04604 | return true; 04605 | } 04606 | 04607 | inline bool token_is_loop(const token_advance_mode mode = e_advance) 04608 | { 04609 | return token_is("for" , mode) || 04610 | token_is("while" , mode) || 04611 | token_is("repeat", mode) ; 04612 | } 04613 | 04614 | inline bool peek_token_is(const token_t::token_type& ttype) 04615 | { 04616 | return (lexer_.peek_next_token().type == ttype); 04617 | } 04618 | 04619 | inline bool peek_token_is(const std::string& s) 04620 | { 04621 | return (exprtk::details::imatch(lexer_.peek_next_token().value,s)); 04622 | } 04623 | 04624 | private: 04625 | 04626 | generator_t lexer_; 04627 | token_t current_token_; 04628 | token_t store_current_token_; 04629 | }; 04630 | } 04631 | 04632 | template <typename T> 04633 | class vector_view 04634 | { 04635 | public: 04636 | 04637 | typedef T* data_ptr_t; 04638 | 04639 | vector_view(data_ptr_t data, const std::size_t& size) 04640 | : base_size_(size) 04641 | , size_(size) 04642 | , data_(data) 04643 | , data_ref_(0) 04644 | { 04645 | assert(size_ > 0); 04646 | } 04647 | 04648 | vector_view(const vector_view<T>& vv) 04649 | : base_size_(vv.base_size_) 04650 | , size_(vv.size_) 04651 | , data_(vv.data_) 04652 | , data_ref_(0) 04653 | { 04654 | assert(size_ > 0); 04655 | } 04656 | 04657 | inline void rebase(data_ptr_t data) 04658 | { 04659 | data_ = data; 04660 | 04661 | if (!data_ref_.empty()) 04662 | { 04663 | for (std::size_t i = 0; i < data_ref_.size(); ++i) 04664 | { 04665 | (*data_ref_[i]) = data; 04666 | } 04667 | } 04668 | } 04669 | 04670 | inline data_ptr_t data() const 04671 | { 04672 | return data_; 04673 | } 04674 | 04675 | inline std::size_t base_size() const 04676 | { 04677 | return base_size_; 04678 | } 04679 | 04680 | inline std::size_t size() const 04681 | { 04682 | return size_; 04683 | } 04684 | 04685 | inline const T& operator[](const std::size_t index) const 04686 | { 04687 | assert(index < size_); 04688 | return data_[index]; 04689 | } 04690 | 04691 | inline T& operator[](const std::size_t index) 04692 | { 04693 | assert(index < size_); 04694 | return data_[index]; 04695 | } 04696 | 04697 | void set_ref(data_ptr_t* data_ref) 04698 | { 04699 | data_ref_.push_back(data_ref); 04700 | exprtk_debug(("vector_view::set_ref() - data_ref: %p data_ref_.size(): %d\n", 04701 | reinterpret_cast<void*>(data_ref), 04702 | static_cast<int>(data_ref_.size()))); 04703 | } 04704 | 04705 | void set_size_ref(std::size_t* size_ref) 04706 | { 04707 | size_ref_.push_back(size_ref); 04708 | exprtk_debug(("vector_view::set_size_ref() - size_ref: %p size_ref_.size(): %d\n", 04709 | reinterpret_cast<void*>(size_ref), 04710 | static_cast<int>(size_ref_.size()))); 04711 | } 04712 | 04713 | void remove_ref(data_ptr_t* data_ref) 04714 | { 04715 | data_ref_.erase( 04716 | std::remove(data_ref_.begin(), data_ref_.end(), data_ref), 04717 | data_ref_.end()); 04718 | exprtk_debug(("vector_view::remove_ref() - data_ref: %p data_ref_.size(): %d\n", 04719 | reinterpret_cast<void*>(data_ref), 04720 | static_cast<int>(data_ref_.size()))); 04721 | } 04722 | 04723 | void remove_size_ref(std::size_t* size_ref) 04724 | { 04725 | size_ref_.erase( 04726 | std::remove(size_ref_.begin(), size_ref_.end(), size_ref), 04727 | size_ref_.end()); 04728 | exprtk_debug(("vector_view::remove_size_ref() - size_ref: %p size_ref_.size(): %d\n", 04729 | reinterpret_cast<void*>(size_ref), 04730 | static_cast<int>(size_ref_.size()))); 04731 | } 04732 | 04733 | bool set_size(const std::size_t new_size) 04734 | { 04735 | if ((new_size > 0) && (new_size <= base_size_)) 04736 | { 04737 | size_ = new_size; 04738 | exprtk_debug(("vector_view::set_size() - data_: %p size: %lu\n", 04739 | reinterpret_cast<void*>(data_), 04740 | size_)); 04741 | 04742 | if (!size_ref_.empty()) 04743 | { 04744 | for (std::size_t i = 0; i < size_ref_.size(); ++i) 04745 | { 04746 | (*size_ref_[i]) = new_size; 04747 | } 04748 | } 04749 | 04750 | return true; 04751 | } 04752 | 04753 | exprtk_debug(("vector_view::set_size() - error invalid new_size: %lu base_size: %lu\n", 04754 | new_size, 04755 | base_size_)); 04756 | return false; 04757 | } 04758 | 04759 | private: 04760 | 04761 | const std::size_t base_size_; 04762 | std::size_t size_; 04763 | data_ptr_t data_; 04764 | std::vector<data_ptr_t*> data_ref_; 04765 | std::vector<std::size_t*> size_ref_; 04766 | }; 04767 | 04768 | template <typename T> 04769 | inline vector_view<T> make_vector_view(T* data, 04770 | const std::size_t size, const std::size_t offset = 0) 04771 | { 04772 | return vector_view<T>(data + offset, size); 04773 | } 04774 | 04775 | template <typename T> 04776 | inline vector_view<T> make_vector_view(std::vector<T>& v, 04777 | const std::size_t size, const std::size_t offset = 0) 04778 | { 04779 | return vector_view<T>(v.data() + offset, size); 04780 | } 04781 | 04782 | template <typename T> class results_context; 04783 | namespace details { template <typename T> class vector_interface; } 04784 | 04785 | template <typename T> 04786 | struct type_store 04787 | { 04788 | enum store_type 04789 | { 04790 | e_unknown, 04791 | e_scalar , 04792 | e_vector , 04793 | e_string 04794 | }; 04795 | 04796 | type_store() 04797 | : data(0) 04798 | , size(0) 04799 | , type(e_unknown) 04800 | , ivec(0) 04801 | {} 04802 | 04803 | union 04804 | { 04805 | void* data; 04806 | T* vec_data; 04807 | }; 04808 | 04809 | typedef details::vector_interface<T>* ivec_t; 04810 | 04811 | std::size_t size; 04812 | store_type type; 04813 | ivec_t ivec; 04814 | 04815 | class parameter_list 04816 | { 04817 | public: 04818 | 04819 | explicit parameter_list(std::vector<type_store>& pl) 04820 | : parameter_list_(pl) 04821 | {} 04822 | 04823 | inline bool empty() const 04824 | { 04825 | return parameter_list_.empty(); 04826 | } 04827 | 04828 | inline std::size_t size() const 04829 | { 04830 | return parameter_list_.size(); 04831 | } 04832 | 04833 | inline type_store& operator[](const std::size_t& index) 04834 | { 04835 | return parameter_list_[index]; 04836 | } 04837 | 04838 | inline const type_store& operator[](const std::size_t& index) const 04839 | { 04840 | return parameter_list_[index]; 04841 | } 04842 | 04843 | inline type_store& front() 04844 | { 04845 | return parameter_list_[0]; 04846 | } 04847 | 04848 | inline const type_store& front() const 04849 | { 04850 | return parameter_list_[0]; 04851 | } 04852 | 04853 | inline type_store& back() 04854 | { 04855 | return parameter_list_.back(); 04856 | } 04857 | 04858 | inline const type_store& back() const 04859 | { 04860 | return parameter_list_.back(); 04861 | } 04862 | 04863 | inline typename std::vector<type_store>::const_iterator begin() const 04864 | { 04865 | return parameter_list_.begin(); 04866 | } 04867 | 04868 | inline typename std::vector<type_store>::const_iterator end() const 04869 | { 04870 | return parameter_list_.end(); 04871 | } 04872 | 04873 | inline typename std::vector<type_store>::iterator begin() 04874 | { 04875 | return parameter_list_.begin(); 04876 | } 04877 | 04878 | inline typename std::vector<type_store>::iterator end() 04879 | { 04880 | return parameter_list_.end(); 04881 | } 04882 | 04883 | private: 04884 | 04885 | std::vector<type_store>& parameter_list_; 04886 | 04887 | friend class results_context<T>; 04888 | }; 04889 | 04890 | template <typename ViewType> 04891 | struct type_view 04892 | { 04893 | typedef type_store<T> type_store_t; 04894 | typedef ViewType value_t; 04895 | 04896 | explicit type_view(type_store_t& ts) 04897 | : ts_(ts) 04898 | , data_(reinterpret_cast<value_t*>(ts_.data)) 04899 | {} 04900 | 04901 | explicit type_view(const type_store_t& ts) 04902 | : ts_(const_cast<type_store_t&>(ts)) 04903 | , data_(reinterpret_cast<value_t*>(ts_.data)) 04904 | {} 04905 | 04906 | inline std::size_t size() const 04907 | { 04908 | return ts_.size; 04909 | } 04910 | 04911 | inline value_t& operator[](const std::size_t& i) 04912 | { 04913 | return data_[i]; 04914 | } 04915 | 04916 | inline const value_t& operator[](const std::size_t& i) const 04917 | { 04918 | return data_[i]; 04919 | } 04920 | 04921 | inline const value_t* begin() const { return data_; } 04922 | inline value_t* begin() { return data_; } 04923 | 04924 | inline const value_t* end() const 04925 | { 04926 | return static_cast<value_t*>(data_ + ts_.size); 04927 | } 04928 | 04929 | inline value_t* end() 04930 | { 04931 | return static_cast<value_t*>(data_ + ts_.size); 04932 | } 04933 | 04934 | type_store_t& ts_; 04935 | value_t* data_; 04936 | }; 04937 | 04938 | typedef type_view<T> vector_view; 04939 | typedef type_view<char> string_view; 04940 | 04941 | struct scalar_view 04942 | { 04943 | typedef type_store<T> type_store_t; 04944 | typedef T value_t; 04945 | 04946 | explicit scalar_view(type_store_t& ts) 04947 | : v_(*reinterpret_cast<value_t*>(ts.data)) 04948 | {} 04949 | 04950 | explicit scalar_view(const type_store_t& ts) 04951 | : v_(*reinterpret_cast<value_t*>(const_cast<type_store_t&>(ts).data)) 04952 | {} 04953 | 04954 | inline value_t& operator() () 04955 | { 04956 | return v_; 04957 | } 04958 | 04959 | inline const value_t& operator() () const 04960 | { 04961 | return v_; 04962 | } 04963 | 04964 | inline operator value_t() const 04965 | { 04966 | return v_; 04967 | } 04968 | 04969 | inline operator value_t() 04970 | { 04971 | return v_; 04972 | } 04973 | 04974 | template <typename IntType> 04975 | inline bool to_int(IntType& i) const 04976 | { 04977 | if (!exprtk::details::numeric::is_integer(v_)) 04978 | return false; 04979 | 04980 | i = static_cast<IntType>(v_); 04981 | 04982 | return true; 04983 | } 04984 | 04985 | template <typename UIntType> 04986 | inline bool to_uint(UIntType& u) const 04987 | { 04988 | if (v_ < T(0)) 04989 | return false; 04990 | else if (!exprtk::details::numeric::is_integer(v_)) 04991 | return false; 04992 | 04993 | u = static_cast<UIntType>(v_); 04994 | 04995 | return true; 04996 | } 04997 | 04998 | T& v_; 04999 | }; 05000 | }; 05001 | 05002 | template <typename StringView> 05003 | inline std::string to_str(const StringView& view) 05004 | { 05005 | return std::string(view.begin(),view.size()); 05006 | } 05007 | 05008 | #ifndef exprtk_disable_return_statement 05009 | namespace details 05010 | { 05011 | template <typename T> class return_node; 05012 | template <typename T> class return_envelope_node; 05013 | } 05014 | #endif 05015 | 05016 | template <typename T> 05017 | class results_context 05018 | { 05019 | public: 05020 | 05021 | typedef type_store<T> type_store_t; 05022 | typedef typename type_store_t::scalar_view scalar_t; 05023 | typedef typename type_store_t::vector_view vector_t; 05024 | typedef typename type_store_t::string_view string_t; 05025 | 05026 | results_context() 05027 | : results_available_(false) 05028 | {} 05029 | 05030 | inline std::size_t count() const 05031 | { 05032 | if (results_available_) 05033 | return parameter_list_.size(); 05034 | else 05035 | return 0; 05036 | } 05037 | 05038 | inline type_store_t& operator[](const std::size_t& index) 05039 | { 05040 | return parameter_list_[index]; 05041 | } 05042 | 05043 | inline const type_store_t& operator[](const std::size_t& index) const 05044 | { 05045 | return parameter_list_[index]; 05046 | } 05047 | 05048 | inline bool get_scalar(const std::size_t& index, T& out) const 05049 | { 05050 | if ( 05051 | (index < parameter_list_.size()) && 05052 | (parameter_list_[index].type == type_store_t::e_scalar) 05053 | ) 05054 | { 05055 | const scalar_t scalar(parameter_list_[index]); 05056 | out = scalar(); 05057 | return true; 05058 | } 05059 | 05060 | return false; 05061 | } 05062 | 05063 | template <typename OutputIterator> 05064 | inline bool get_vector(const std::size_t& index, OutputIterator out_itr) const 05065 | { 05066 | if ( 05067 | (index < parameter_list_.size()) && 05068 | (parameter_list_[index].type == type_store_t::e_vector) 05069 | ) 05070 | { 05071 | const vector_t vector(parameter_list_[index]); 05072 | for (std::size_t i = 0; i < vector.size(); ++i) 05073 | { 05074 | *(out_itr++) = vector[i]; 05075 | } 05076 | 05077 | return true; 05078 | } 05079 | 05080 | return false; 05081 | } 05082 | 05083 | inline bool get_vector(const std::size_t& index, std::vector<T>& out) const 05084 | { 05085 | return get_vector(index,std::back_inserter(out)); 05086 | } 05087 | 05088 | inline bool get_string(const std::size_t& index, std::string& out) const 05089 | { 05090 | if ( 05091 | (index < parameter_list_.size()) && 05092 | (parameter_list_[index].type == type_store_t::e_string) 05093 | ) 05094 | { 05095 | const string_t str(parameter_list_[index]); 05096 | out.assign(str.begin(),str.size()); 05097 | return true; 05098 | } 05099 | 05100 | return false; 05101 | } 05102 | 05103 | private: 05104 | 05105 | inline void clear() 05106 | { 05107 | results_available_ = false; 05108 | } 05109 | 05110 | typedef std::vector<type_store_t> ts_list_t; 05111 | typedef typename type_store_t::parameter_list parameter_list_t; 05112 | 05113 | inline void assign(const parameter_list_t& pl) 05114 | { 05115 | parameter_list_ = pl.parameter_list_; 05116 | results_available_ = true; 05117 | } 05118 | 05119 | bool results_available_; 05120 | ts_list_t parameter_list_; 05121 | 05122 | #ifndef exprtk_disable_return_statement 05123 | friend class details::return_node<T>; 05124 | friend class details::return_envelope_node<T>; 05125 | #endif 05126 | }; 05127 | 05128 | namespace details 05129 | { 05130 | enum operator_type 05131 | { 05132 | e_default , e_null , e_add , e_sub , 05133 | e_mul , e_div , e_mod , e_pow , 05134 | e_atan2 , e_min , e_max , e_avg , 05135 | e_sum , e_prod , e_lt , e_lte , 05136 | e_eq , e_equal , e_ne , e_nequal , 05137 | e_gte , e_gt , e_and , e_nand , 05138 | e_or , e_nor , e_xor , e_xnor , 05139 | e_mand , e_mor , e_scand , e_scor , 05140 | e_shr , e_shl , e_abs , e_acos , 05141 | e_acosh , e_asin , e_asinh , e_atan , 05142 | e_atanh , e_ceil , e_cos , e_cosh , 05143 | e_exp , e_expm1 , e_floor , e_log , 05144 | e_log10 , e_log2 , e_log1p , e_logn , 05145 | e_neg , e_pos , e_round , e_roundn , 05146 | e_root , e_sqrt , e_sin , e_sinc , 05147 | e_sinh , e_sec , e_csc , e_tan , 05148 | e_tanh , e_cot , e_clamp , e_iclamp , 05149 | e_inrange , e_sgn , e_r2d , e_d2r , 05150 | e_d2g , e_g2d , e_hypot , e_notl , 05151 | e_erf , e_erfc , e_ncdf , e_frac , 05152 | e_trunc , e_assign , e_addass , e_subass , 05153 | e_mulass , e_divass , e_modass , e_in , 05154 | e_like , e_ilike , e_multi , e_smulti , 05155 | e_swap , 05156 | 05157 | // Do not add new functions/operators after this point. 05158 | e_sf00 = 1000, e_sf01 = 1001, e_sf02 = 1002, e_sf03 = 1003, 05159 | e_sf04 = 1004, e_sf05 = 1005, e_sf06 = 1006, e_sf07 = 1007, 05160 | e_sf08 = 1008, e_sf09 = 1009, e_sf10 = 1010, e_sf11 = 1011, 05161 | e_sf12 = 1012, e_sf13 = 1013, e_sf14 = 1014, e_sf15 = 1015, 05162 | e_sf16 = 1016, e_sf17 = 1017, e_sf18 = 1018, e_sf19 = 1019, 05163 | e_sf20 = 1020, e_sf21 = 1021, e_sf22 = 1022, e_sf23 = 1023, 05164 | e_sf24 = 1024, e_sf25 = 1025, e_sf26 = 1026, e_sf27 = 1027, 05165 | e_sf28 = 1028, e_sf29 = 1029, e_sf30 = 1030, e_sf31 = 1031, 05166 | e_sf32 = 1032, e_sf33 = 1033, e_sf34 = 1034, e_sf35 = 1035, 05167 | e_sf36 = 1036, e_sf37 = 1037, e_sf38 = 1038, e_sf39 = 1039, 05168 | e_sf40 = 1040, e_sf41 = 1041, e_sf42 = 1042, e_sf43 = 1043, 05169 | e_sf44 = 1044, e_sf45 = 1045, e_sf46 = 1046, e_sf47 = 1047, 05170 | e_sf48 = 1048, e_sf49 = 1049, e_sf50 = 1050, e_sf51 = 1051, 05171 | e_sf52 = 1052, e_sf53 = 1053, e_sf54 = 1054, e_sf55 = 1055, 05172 | e_sf56 = 1056, e_sf57 = 1057, e_sf58 = 1058, e_sf59 = 1059, 05173 | e_sf60 = 1060, e_sf61 = 1061, e_sf62 = 1062, e_sf63 = 1063, 05174 | e_sf64 = 1064, e_sf65 = 1065, e_sf66 = 1066, e_sf67 = 1067, 05175 | e_sf68 = 1068, e_sf69 = 1069, e_sf70 = 1070, e_sf71 = 1071, 05176 | e_sf72 = 1072, e_sf73 = 1073, e_sf74 = 1074, e_sf75 = 1075, 05177 | e_sf76 = 1076, e_sf77 = 1077, e_sf78 = 1078, e_sf79 = 1079, 05178 | e_sf80 = 1080, e_sf81 = 1081, e_sf82 = 1082, e_sf83 = 1083, 05179 | e_sf84 = 1084, e_sf85 = 1085, e_sf86 = 1086, e_sf87 = 1087, 05180 | e_sf88 = 1088, e_sf89 = 1089, e_sf90 = 1090, e_sf91 = 1091, 05181 | e_sf92 = 1092, e_sf93 = 1093, e_sf94 = 1094, e_sf95 = 1095, 05182 | e_sf96 = 1096, e_sf97 = 1097, e_sf98 = 1098, e_sf99 = 1099, 05183 | e_sffinal = 1100, 05184 | e_sf4ext00 = 2000, e_sf4ext01 = 2001, e_sf4ext02 = 2002, e_sf4ext03 = 2003, 05185 | e_sf4ext04 = 2004, e_sf4ext05 = 2005, e_sf4ext06 = 2006, e_sf4ext07 = 2007, 05186 | e_sf4ext08 = 2008, e_sf4ext09 = 2009, e_sf4ext10 = 2010, e_sf4ext11 = 2011, 05187 | e_sf4ext12 = 2012, e_sf4ext13 = 2013, e_sf4ext14 = 2014, e_sf4ext15 = 2015, 05188 | e_sf4ext16 = 2016, e_sf4ext17 = 2017, e_sf4ext18 = 2018, e_sf4ext19 = 2019, 05189 | e_sf4ext20 = 2020, e_sf4ext21 = 2021, e_sf4ext22 = 2022, e_sf4ext23 = 2023, 05190 | e_sf4ext24 = 2024, e_sf4ext25 = 2025, e_sf4ext26 = 2026, e_sf4ext27 = 2027, 05191 | e_sf4ext28 = 2028, e_sf4ext29 = 2029, e_sf4ext30 = 2030, e_sf4ext31 = 2031, 05192 | e_sf4ext32 = 2032, e_sf4ext33 = 2033, e_sf4ext34 = 2034, e_sf4ext35 = 2035, 05193 | e_sf4ext36 = 2036, e_sf4ext37 = 2037, e_sf4ext38 = 2038, e_sf4ext39 = 2039, 05194 | e_sf4ext40 = 2040, e_sf4ext41 = 2041, e_sf4ext42 = 2042, e_sf4ext43 = 2043, 05195 | e_sf4ext44 = 2044, e_sf4ext45 = 2045, e_sf4ext46 = 2046, e_sf4ext47 = 2047, 05196 | e_sf4ext48 = 2048, e_sf4ext49 = 2049, e_sf4ext50 = 2050, e_sf4ext51 = 2051, 05197 | e_sf4ext52 = 2052, e_sf4ext53 = 2053, e_sf4ext54 = 2054, e_sf4ext55 = 2055, 05198 | e_sf4ext56 = 2056, e_sf4ext57 = 2057, e_sf4ext58 = 2058, e_sf4ext59 = 2059, 05199 | e_sf4ext60 = 2060, e_sf4ext61 = 2061 05200 | }; 05201 | 05202 | inline std::string to_str(const operator_type opr) 05203 | { 05204 | switch (opr) 05205 | { 05206 | case e_add : return "+" ; 05207 | case e_sub : return "-" ; 05208 | case e_mul : return "*" ; 05209 | case e_div : return "/" ; 05210 | case e_mod : return "%" ; 05211 | case e_pow : return "^" ; 05212 | case e_assign : return ":=" ; 05213 | case e_addass : return "+=" ; 05214 | case e_subass : return "-=" ; 05215 | case e_mulass : return "*=" ; 05216 | case e_divass : return "/=" ; 05217 | case e_modass : return "%=" ; 05218 | case e_lt : return "<" ; 05219 | case e_lte : return "<=" ; 05220 | case e_eq : return "==" ; 05221 | case e_equal : return "=" ; 05222 | case e_ne : return "!=" ; 05223 | case e_nequal : return "<>" ; 05224 | case e_gte : return ">=" ; 05225 | case e_gt : return ">" ; 05226 | case e_and : return "and" ; 05227 | case e_or : return "or" ; 05228 | case e_xor : return "xor" ; 05229 | case e_nand : return "nand" 05230 | case e_nor : return "nor" ; 05231 | case e_xnor : return "xnor" 05232 | default : return "N/A" ; 05233 | } 05234 | } 05235 | 05236 | struct base_operation_t 05237 | { 05238 | base_operation_t(const operator_type t, const unsigned int& np) 05239 | : type(t) 05240 | , num_params(np) 05241 | {} 05242 | 05243 | operator_type type; 05244 | unsigned int num_params; 05245 | }; 05246 | 05247 | namespace loop_unroll 05248 | { 05249 | const unsigned int global_loop_batch_size = 05250 | #ifndef exprtk_disable_superscalar_unroll 05251 | 16; 05252 | #else 05253 | 4; 05254 | #endif 05255 | 05256 | struct details 05257 | { 05258 | explicit details(const std::size_t& vsize, 05259 | const unsigned int loop_batch_size = global_loop_batch_size) 05260 | : batch_size(loop_batch_size ) 05261 | , remainder (vsize % batch_size) 05262 | , upper_bound(static_cast<int>(vsize - (remainder ? loop_batch_size : 0))) 05263 | {} 05264 | 05265 | unsigned int batch_size; 05266 | int remainder; 05267 | int upper_bound; 05268 | }; 05269 | } 05270 | 05271 | #ifdef exprtk_enable_debugging 05272 | inline void dump_ptr(const std::string& s, const void* ptr, const std::size_t size = 0) 05273 | { 05274 | if (size) 05275 | exprtk_debug(("%s - addr: %p size: %d\n", 05276 | s.c_str(), 05277 | ptr, 05278 | static_cast<unsigned int>(size))); 05279 | else 05280 | exprtk_debug(("%s - addr: %p\n", s.c_str(), ptr)); 05281 | } 05282 | 05283 | template <typename T> 05284 | inline void dump_vector(const std::string& vec_name, const T* data, const std::size_t size) 05285 | { 05286 | printf("----- %s (%p) -----\n", 05287 | vec_name.c_str(), 05288 | static_cast<const void*>(data)); 05289 | printf("[ "); 05290 | for (std::size_t i = 0; i < size; ++i) 05291 | { 05292 | printf("%8.3f\t", data[i]); 05293 | } 05294 | printf(" ]\n"); 05295 | printf("---------------------\n"); 05296 | } 05297 | #else 05298 | inline void dump_ptr(const std::string&, const void*) {} 05299 | inline void dump_ptr(const std::string&, const void*, const std::size_t) {} 05300 | template <typename T> 05301 | inline void dump_vector(const std::string&, const T*, const std::size_t) {} 05302 | #endif 05303 | 05304 | template <typename T> 05305 | class vec_data_store 05306 | { 05307 | public: 05308 | 05309 | typedef vec_data_store<T> type; 05310 | typedef T* data_t; 05311 | 05312 | private: 05313 | 05314 | struct control_block 05315 | { 05316 | control_block() 05317 | : ref_count(1) 05318 | , size (0) 05319 | , data (0) 05320 | , destruct (true) 05321 | {} 05322 | 05323 | explicit control_block(const std::size_t& dsize) 05324 | : ref_count(1 ) 05325 | , size (dsize) 05326 | , data (0 ) 05327 | , destruct (true ) 05328 | { create_data(); } 05329 | 05330 | control_block(const std::size_t& dsize, data_t dptr, bool dstrct = false) 05331 | : ref_count(1 ) 05332 | , size (dsize ) 05333 | , data (dptr ) 05334 | , destruct (dstrct) 05335 | {} 05336 | 05337 | ~control_block() 05338 | { 05339 | if (data && destruct && (0 == ref_count)) 05340 | { 05341 | dump_ptr("~vec_data_store::control_block() data",data); 05342 | delete[] data; 05343 | data = reinterpret_cast<data_t>(0); 05344 | } 05345 | } 05346 | 05347 | static inline control_block* create(const std::size_t& dsize, data_t data_ptr = data_t(0), bool dstrct = false) 05348 | { 05349 | if (dsize) 05350 | { 05351 | if (0 == data_ptr) 05352 | return (new control_block(dsize)); 05353 | else 05354 | return (new control_block(dsize, data_ptr, dstrct)); 05355 | } 05356 | else 05357 | return (new control_block); 05358 | } 05359 | 05360 | static inline void destroy(control_block*& cntrl_blck) 05361 | { 05362 | if (cntrl_blck) 05363 | { 05364 | if ( 05365 | (0 != cntrl_blck->ref_count) && 05366 | (0 == --cntrl_blck->ref_count) 05367 | ) 05368 | { 05369 | delete cntrl_blck; 05370 | } 05371 | 05372 | cntrl_blck = 0; 05373 | } 05374 | } 05375 | 05376 | std::size_t ref_count; 05377 | std::size_t size; 05378 | data_t data; 05379 | bool destruct; 05380 | 05381 | private: 05382 | 05383 | control_block(const control_block&) exprtk_delete; 05384 | control_block& operator=(const control_block&) exprtk_delete; 05385 | 05386 | inline void create_data() 05387 | { 05388 | destruct = true; 05389 | data = new T[size]; 05390 | std::fill_n(data, size, T(0)); 05391 | dump_ptr("control_block::create_data() - data", data, size); 05392 | } 05393 | }; 05394 | 05395 | public: 05396 | 05397 | vec_data_store() 05398 | : control_block_(control_block::create(0)) 05399 | {} 05400 | 05401 | explicit vec_data_store(const std::size_t& size) 05402 | : control_block_(control_block::create(size,reinterpret_cast<data_t>(0),true)) 05403 | {} 05404 | 05405 | vec_data_store(const std::size_t& size, data_t data, bool dstrct = false) 05406 | : control_block_(control_block::create(size, data, dstrct)) 05407 | {} 05408 | 05409 | vec_data_store(const type& vds) 05410 | { 05411 | control_block_ = vds.control_block_; 05412 | control_block_->ref_count++; 05413 | } 05414 | 05415 | ~vec_data_store() 05416 | { 05417 | control_block::destroy(control_block_); 05418 | } 05419 | 05420 | type& operator=(const type& vds) 05421 | { 05422 | if (this != &vds) 05423 | { 05424 | const std::size_t final_size = min_size(control_block_, vds.control_block_); 05425 | 05426 | vds.control_block_->size = final_size; 05427 | control_block_->size = final_size; 05428 | 05429 | if (control_block_->destruct || (0 == control_block_->data)) 05430 | { 05431 | control_block::destroy(control_block_); 05432 | 05433 | control_block_ = vds.control_block_; 05434 | control_block_->ref_count++; 05435 | } 05436 | } 05437 | 05438 | return (*this); 05439 | } 05440 | 05441 | inline data_t data() 05442 | { 05443 | return control_block_->data; 05444 | } 05445 | 05446 | inline data_t data() const 05447 | { 05448 | return control_block_->data; 05449 | } 05450 | 05451 | inline std::size_t size() const 05452 | { 05453 | return control_block_->size; 05454 | } 05455 | 05456 | inline data_t& ref() 05457 | { 05458 | return control_block_->data; 05459 | } 05460 | 05461 | inline void dump() const 05462 | { 05463 | #ifdef exprtk_enable_debugging 05464 | exprtk_debug(("size: %d\taddress:%p\tdestruct:%c\n", 05465 | size(), 05466 | data(), 05467 | (control_block_->destruct ? 'T' : 'F'))); 05468 | 05469 | for (std::size_t i = 0; i < size(); ++i) 05470 | { 05471 | if (5 == i) 05472 | exprtk_debug(("\n")); 05473 | 05474 | exprtk_debug(("%15.10f ", data()[i])); 05475 | } 05476 | exprtk_debug(("\n")); 05477 | #endif 05478 | } 05479 | 05480 | static inline void match_sizes(type& vds0, type& vds1) 05481 | { 05482 | const std::size_t size = min_size(vds0.control_block_,vds1.control_block_); 05483 | vds0.control_block_->size = size; 05484 | vds1.control_block_->size = size; 05485 | } 05486 | 05487 | private: 05488 | 05489 | static inline std::size_t min_size(const control_block* cb0, const control_block* cb1) 05490 | { 05491 | const std::size_t size0 = cb0->size; 05492 | const std::size_t size1 = cb1->size; 05493 | 05494 | if (size0 && size1) 05495 | return std::min(size0,size1); 05496 | else 05497 | return (size0) ? size0 : size1; 05498 | } 05499 | 05500 | control_block* control_block_; 05501 | }; 05502 | 05503 | namespace numeric 05504 | { 05505 | namespace details 05506 | { 05507 | template <typename T> 05508 | inline T process_impl(const operator_type operation, const T arg) 05509 | { 05510 | switch (operation) 05511 | { 05512 | case e_abs : return numeric::abs (arg); 05513 | case e_acos : return numeric::acos (arg); 05514 | case e_acosh : return numeric::acosh(arg); 05515 | case e_asin : return numeric::asin (arg); 05516 | case e_asinh : return numeric::asinh(arg); 05517 | case e_atan : return numeric::atan (arg); 05518 | case e_atanh : return numeric::atanh(arg); 05519 | case e_ceil : return numeric::ceil (arg); 05520 | case e_cos : return numeric::cos (arg); 05521 | case e_cosh : return numeric::cosh (arg); 05522 | case e_exp : return numeric::exp (arg); 05523 | case e_expm1 : return numeric::expm1(arg); 05524 | case e_floor : return numeric::floor(arg); 05525 | case e_log : return numeric::log (arg); 05526 | case e_log10 : return numeric::log10(arg); 05527 | case e_log2 : return numeric::log2 (arg); 05528 | case e_log1p : return numeric::log1p(arg); 05529 | case e_neg : return numeric::neg (arg); 05530 | case e_pos : return numeric::pos (arg); 05531 | case e_round : return numeric::round(arg); 05532 | case e_sin : return numeric::sin (arg); 05533 | case e_sinc : return numeric::sinc (arg); 05534 | case e_sinh : return numeric::sinh (arg); 05535 | case e_sqrt : return numeric::sqrt (arg); 05536 | case e_tan : return numeric::tan (arg); 05537 | case e_tanh : return numeric::tanh (arg); 05538 | case e_cot : return numeric::cot (arg); 05539 | case e_sec : return numeric::sec (arg); 05540 | case e_csc : return numeric::csc (arg); 05541 | case e_r2d : return numeric::r2d (arg); 05542 | case e_d2r : return numeric::d2r (arg); 05543 | case e_d2g : return numeric::d2g (arg); 05544 | case e_g2d : return numeric::g2d (arg); 05545 | case e_notl : return numeric::notl (arg); 05546 | case e_sgn : return numeric::sgn (arg); 05547 | case e_erf : return numeric::erf (arg); 05548 | case e_erfc : return numeric::erfc (arg); 05549 | case e_ncdf : return numeric::ncdf (arg); 05550 | case e_frac : return numeric::frac (arg); 05551 | case e_trunc : return numeric::trunc(arg); 05552 | 05553 | default : exprtk_debug(("numeric::details::process_impl<T> - Invalid unary operation.\n")); 05554 | return std::numeric_limits<T>::quiet_NaN(); 05555 | } 05556 | } 05557 | 05558 | template <typename T> 05559 | inline T process_impl(const operator_type operation, const T arg0, const T arg1) 05560 | { 05561 | switch (operation) 05562 | { 05563 | case e_add : return (arg0 + arg1); 05564 | case e_sub : return (arg0 - arg1); 05565 | case e_mul : return (arg0 * arg1); 05566 | case e_div : return (arg0 / arg1); 05567 | case e_mod : return modulus<T>(arg0,arg1); 05568 | case e_pow : return pow<T>(arg0,arg1); 05569 | case e_atan2 : return atan2<T>(arg0,arg1); 05570 | case e_min : return std::min<T>(arg0,arg1); 05571 | case e_max : return std::max<T>(arg0,arg1); 05572 | case e_logn : return logn<T>(arg0,arg1); 05573 | case e_lt : return (arg0 < arg1) ? T(1) : T(0); 05574 | case e_lte : return (arg0 <= arg1) ? T(1) : T(0); 05575 | case e_eq : return std::equal_to<T>()(arg0,arg1) ? T(1) : T(0); 05576 | case e_ne : return std::not_equal_to<T>()(arg0,arg1) ? T(1) : T(0); 05577 | case e_gte : return (arg0 >= arg1) ? T(1) : T(0); 05578 | case e_gt : return (arg0 > arg1) ? T(1) : T(0); 05579 | case e_and : return and_opr <T>(arg0,arg1); 05580 | case e_nand : return nand_opr<T>(arg0,arg1); 05581 | case e_or : return or_opr <T>(arg0,arg1); 05582 | case e_nor : return nor_opr <T>(arg0,arg1); 05583 | case e_xor : return xor_opr <T>(arg0,arg1); 05584 | case e_xnor : return xnor_opr<T>(arg0,arg1); 05585 | case e_root : return root <T>(arg0,arg1); 05586 | case e_roundn : return roundn <T>(arg0,arg1); 05587 | case e_equal : return equal <T>(arg0,arg1); 05588 | case e_nequal : return nequal <T>(arg0,arg1); 05589 | case e_hypot : return hypot <T>(arg0,arg1); 05590 | case e_shr : return shr <T>(arg0,arg1); 05591 | case e_shl : return shl <T>(arg0,arg1); 05592 | 05593 | default : exprtk_debug(("numeric::details::process_impl<T> - Invalid binary operation.\n")); 05594 | return std::numeric_limits<T>::quiet_NaN(); 05595 | } 05596 | } 05597 | 05598 | template <typename T> 05599 | inline T process_impl(const operator_type operation, const T arg0, const T arg1, int_type_tag) 05600 | { 05601 | switch (operation) 05602 | { 05603 | case e_add : return (arg0 + arg1); 05604 | case e_sub : return (arg0 - arg1); 05605 | case e_mul : return (arg0 * arg1); 05606 | case e_div : return (arg0 / arg1); 05607 | case e_mod : return arg0 % arg1; 05608 | case e_pow : return pow<T>(arg0,arg1); 05609 | case e_min : return std::min<T>(arg0,arg1); 05610 | case e_max : return std::max<T>(arg0,arg1); 05611 | case e_logn : return logn<T>(arg0,arg1); 05612 | case e_lt : return (arg0 < arg1) ? T(1) : T(0); 05613 | case e_lte : return (arg0 <= arg1) ? T(1) : T(0); 05614 | case e_eq : return (arg0 == arg1) ? T(1) : T(0); 05615 | case e_ne : return (arg0 != arg1) ? T(1) : T(0); 05616 | case e_gte : return (arg0 >= arg1) ? T(1) : T(0); 05617 | case e_gt : return (arg0 > arg1) ? T(1) : T(0); 05618 | case e_and : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(1) : T(0); 05619 | case e_nand : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(0) : T(1); 05620 | case e_or : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(1) : T(0); 05621 | case e_nor : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(0) : T(1); 05622 | case e_xor : return arg0 ^ arg1; 05623 | case e_xnor : return !(arg0 ^ arg1); 05624 | case e_root : return root<T>(arg0,arg1); 05625 | case e_equal : return arg0 == arg1; 05626 | case e_nequal : return arg0 != arg1; 05627 | case e_hypot : return hypot<T>(arg0,arg1); 05628 | case e_shr : return arg0 >> arg1; 05629 | case e_shl : return arg0 << arg1; 05630 | 05631 | default : exprtk_debug(("numeric::details::process_impl<IntType> - Invalid binary operation.\n")); 05632 | return std::numeric_limits<T>::quiet_NaN(); 05633 | } 05634 | } 05635 | } 05636 | 05637 | template <typename T> 05638 | inline T process(const operator_type operation, const T arg) 05639 | { 05640 | return exprtk::details::numeric::details::process_impl(operation,arg); 05641 | } 05642 | 05643 | template <typename T> 05644 | inline T process(const operator_type operation, const T arg0, const T arg1) 05645 | { 05646 | return exprtk::details::numeric::details::process_impl(operation, arg0, arg1); 05647 | } 05648 | } 05649 | 05650 | template <typename Node> 05651 | struct node_collector_interface 05652 | { 05653 | typedef Node* node_ptr_t; 05654 | typedef Node** node_pp_t; 05655 | typedef std::vector<node_pp_t> noderef_list_t; 05656 | 05657 | virtual ~node_collector_interface() 05658 | {} 05659 | 05660 | virtual void collect_nodes(noderef_list_t&) 05661 | {} 05662 | }; 05663 | 05664 | template <typename Node> 05665 | struct node_depth_base; 05666 | 05667 | template <typename T> 05668 | class expression_node : public node_collector_interface<expression_node<T> > 05669 | , public node_depth_base<expression_node<T> > 05670 | { 05671 | public: 05672 | 05673 | enum node_type 05674 | { 05675 | e_none , e_null , e_constant , e_unary , 05676 | e_binary , e_binary_ext , e_trinary , e_quaternary , 05677 | e_vararg , e_conditional , e_while , e_repeat , 05678 | e_for , e_switch , e_mswitch , e_return , 05679 | e_retenv , e_variable , e_stringvar , e_stringconst , 05680 | e_stringvarrng , e_cstringvarrng , e_strgenrange , e_strconcat , 05681 | e_stringvarsize , e_strswap , e_stringsize , e_stringvararg , 05682 | e_function , e_vafunction , e_genfunction , e_strfunction , 05683 | e_strcondition , e_strccondition , e_add , e_sub , 05684 | e_mul , e_div , e_mod , e_pow , 05685 | e_lt , e_lte , e_gt , e_gte , 05686 | e_eq , e_ne , e_and , e_nand , 05687 | e_or , e_nor , e_xor , e_xnor , 05688 | e_in , e_like , e_ilike , e_inranges , 05689 | e_ipow , e_ipowinv , e_abs , e_acos , 05690 | e_acosh , e_asin , e_asinh , e_atan , 05691 | e_atanh , e_ceil , e_cos , e_cosh , 05692 | e_exp , e_expm1 , e_floor , e_log , 05693 | e_log10 , e_log2 , e_log1p , e_neg , 05694 | e_pos , e_round , e_sin , e_sinc , 05695 | e_sinh , e_sqrt , e_tan , e_tanh , 05696 | e_cot , e_sec , e_csc , e_r2d , 05697 | e_d2r , e_d2g , e_g2d , e_notl , 05698 | e_sgn , e_erf , e_erfc , e_ncdf , 05699 | e_frac , e_trunc , e_uvouv , e_vov , 05700 | e_cov , e_voc , e_vob , e_bov , 05701 | e_cob , e_boc , e_vovov , e_vovoc , 05702 | e_vocov , e_covov , e_covoc , e_vovovov , 05703 | e_vovovoc , e_vovocov , e_vocovov , e_covovov , 05704 | e_covocov , e_vocovoc , e_covovoc , e_vococov , 05705 | e_sf3ext , e_sf4ext , e_nulleq , e_strass , 05706 | e_vector , e_vecsize , e_vecelem , e_veccelem , 05707 | e_vecelemrtc , e_veccelemrtc , e_rbvecelem , e_rbvecelemrtc , 05708 | e_rbveccelem , e_rbveccelemrtc , e_vecinit , e_vecvalass , 05709 | e_vecvecass , e_vecopvalass , e_vecopvecass , e_vecfunc , 05710 | e_vecvecswap , e_vecvecineq , e_vecvalineq , e_valvecineq , 05711 | e_vecvecarith , e_vecvalarith , e_valvecarith , e_vecunaryop , 05712 | e_vecondition , e_break , e_continue , e_swap , 05713 | e_assert 05714 | }; 05715 | 05716 | typedef T value_type; 05717 | typedef expression_node<T>* expression_ptr; 05718 | typedef node_collector_interface<expression_node<T> > nci_t; 05719 | typedef typename nci_t::noderef_list_t noderef_list_t; 05720 | typedef node_depth_base<expression_node<T> > ndb_t; 05721 | 05722 | virtual ~expression_node() 05723 | {} 05724 | 05725 | inline virtual T value() const 05726 | { 05727 | return std::numeric_limits<T>::quiet_NaN(); 05728 | } 05729 | 05730 | inline virtual expression_node<T>* branch(const std::size_t& index = 0) const 05731 | { 05732 | return reinterpret_cast<expression_ptr>(index * 0); 05733 | } 05734 | 05735 | inline virtual node_type type() const 05736 | { 05737 | return e_none; 05738 | } 05739 | 05740 | inline virtual bool valid() const 05741 | { 05742 | return true; 05743 | } 05744 | }; // class expression_node 05745 | 05746 | template <typename T> 05747 | inline bool is_generally_string_node(const expression_node<T>* node); 05748 | 05749 | inline bool is_true(const double v) 05750 | { 05751 | return std::not_equal_to<double>()(0.0,v); 05752 | } 05753 | 05754 | inline bool is_true(const long double v) 05755 | { 05756 | return std::not_equal_to<long double>()(0.0L,v); 05757 | } 05758 | 05759 | inline bool is_true(const float v) 05760 | { 05761 | return std::not_equal_to<float>()(0.0f,v); 05762 | } 05763 | 05764 | template <typename T> 05765 | inline bool is_true(const expression_node<T>* node) 05766 | { 05767 | return std::not_equal_to<T>()(T(0),node->value()); 05768 | } 05769 | 05770 | template <typename T> 05771 | inline bool is_true(const std::pair<expression_node<T>*,bool>& node) 05772 | { 05773 | return std::not_equal_to<T>()(T(0),node.first->value()); 05774 | } 05775 | 05776 | template <typename T> 05777 | inline bool is_false(const expression_node<T>* node) 05778 | { 05779 | return std::equal_to<T>()(T(0),node->value()); 05780 | } 05781 | 05782 | template <typename T> 05783 | inline bool is_false(const std::pair<expression_node<T>*,bool>& node) 05784 | { 05785 | return std::equal_to<T>()(T(0),node.first->value()); 05786 | } 05787 | 05788 | template <typename T> 05789 | inline bool is_literal_node(const expression_node<T>* node) 05790 | { 05791 | return node && (details::expression_node<T>::e_constant == node->type()); 05792 | } 05793 | 05794 | template <typename T> 05795 | inline bool is_unary_node(const expression_node<T>* node) 05796 | { 05797 | return node && (details::expression_node<T>::e_unary == node->type()); 05798 | } 05799 | 05800 | template <typename T> 05801 | inline bool is_neg_unary_node(const expression_node<T>* node) 05802 | { 05803 | return node && (details::expression_node<T>::e_neg == node->type()); 05804 | } 05805 | 05806 | template <typename T> 05807 | inline bool is_binary_node(const expression_node<T>* node) 05808 | { 05809 | return node && (details::expression_node<T>::e_binary == node->type()); 05810 | } 05811 | 05812 | template <typename T> 05813 | inline bool is_variable_node(const expression_node<T>* node) 05814 | { 05815 | return node && (details::expression_node<T>::e_variable == node->type()); 05816 | } 05817 | 05818 | template <typename T> 05819 | inline bool is_ivariable_node(const expression_node<T>* node) 05820 | { 05821 | return node && 05822 | ( 05823 | details::expression_node<T>::e_variable == node->type() || 05824 | details::expression_node<T>::e_vecelem == node->type() || 05825 | details::expression_node<T>::e_veccelem == node->type() || 05826 | details::expression_node<T>::e_vecelemrtc == node->type() || 05827 | details::expression_node<T>::e_veccelemrtc == node->type() || 05828 | details::expression_node<T>::e_rbvecelem == node->type() || 05829 | details::expression_node<T>::e_rbveccelem == node->type() || 05830 | details::expression_node<T>::e_rbvecelemrtc == node->type() || 05831 | details::expression_node<T>::e_rbveccelemrtc == node->type() 05832 | ); 05833 | } 05834 | 05835 | template <typename T> 05836 | inline bool is_vector_elem_node(const expression_node<T>* node) 05837 | { 05838 | return node && (details::expression_node<T>::e_vecelem == node->type()); 05839 | } 05840 | 05841 | template <typename T> 05842 | inline bool is_vector_celem_node(const expression_node<T>* node) 05843 | { 05844 | return node && (details::expression_node<T>::e_veccelem == node->type()); 05845 | } 05846 | 05847 | template <typename T> 05848 | inline bool is_vector_elem_rtc_node(const expression_node<T>* node) 05849 | { 05850 | return node && (details::expression_node<T>::e_vecelemrtc == node->type()); 05851 | } 05852 | 05853 | template <typename T> 05854 | inline bool is_vector_celem_rtc_node(const expression_node<T>* node) 05855 | { 05856 | return node && (details::expression_node<T>::e_veccelemrtc == node->type()); 05857 | } 05858 | 05859 | template <typename T> 05860 | inline bool is_rebasevector_elem_node(const expression_node<T>* node) 05861 | { 05862 | return node && (details::expression_node<T>::e_rbvecelem == node->type()); 05863 | } 05864 | 05865 | template <typename T> 05866 | inline bool is_rebasevector_elem_rtc_node(const expression_node<T>* node) 05867 | { 05868 | return node && (details::expression_node<T>::e_rbvecelemrtc == node->type()); 05869 | } 05870 | 05871 | template <typename T> 05872 | inline bool is_rebasevector_celem_rtc_node(const expression_node<T>* node) 05873 | { 05874 | return node && (details::expression_node<T>::e_rbveccelemrtc == node->type()); 05875 | } 05876 | 05877 | template <typename T> 05878 | inline bool is_rebasevector_celem_node(const expression_node<T>* node) 05879 | { 05880 | return node && (details::expression_node<T>::e_rbveccelem == node->type()); 05881 | } 05882 | 05883 | template <typename T> 05884 | inline bool is_vector_node(const expression_node<T>* node) 05885 | { 05886 | return node && (details::expression_node<T>::e_vector == node->type()); 05887 | } 05888 | 05889 | template <typename T> 05890 | inline bool is_ivector_node(const expression_node<T>* node) 05891 | { 05892 | if (node) 05893 | { 05894 | switch (node->type()) 05895 | { 05896 | case details::expression_node<T>::e_vector : 05897 | case details::expression_node<T>::e_vecvalass : 05898 | case details::expression_node<T>::e_vecvecass : 05899 | case details::expression_node<T>::e_vecopvalass : 05900 | case details::expression_node<T>::e_vecopvecass : 05901 | case details::expression_node<T>::e_vecvecswap : 05902 | case details::expression_node<T>::e_vecvecarith : 05903 | case details::expression_node<T>::e_vecvalarith : 05904 | case details::expression_node<T>::e_valvecarith : 05905 | case details::expression_node<T>::e_vecunaryop : 05906 | case details::expression_node<T>::e_vecondition : return true; 05907 | default : return false; 05908 | } 05909 | } 05910 | else 05911 | return false; 05912 | } 05913 | 05914 | template <typename T> 05915 | inline bool amalgamated_vecop(const expression_node<T>* node) 05916 | { 05917 | if (node) 05918 | { 05919 | switch (node->type()) 05920 | { 05921 | case details::expression_node<T>::e_vecvecarith : 05922 | case details::expression_node<T>::e_vecvalarith : 05923 | case details::expression_node<T>::e_valvecarith : 05924 | case details::expression_node<T>::e_vecunaryop : return true; 05925 | default : return false; 05926 | } 05927 | } 05928 | else 05929 | return false; 05930 | } 05931 | 05932 | template <typename T> 05933 | inline bool is_constant_node(const expression_node<T>* node) 05934 | { 05935 | return node && 05936 | ( 05937 | details::expression_node<T>::e_constant == node->type() || 05938 | details::expression_node<T>::e_stringconst == node->type() 05939 | ); 05940 | } 05941 | 05942 | template <typename T> 05943 | inline bool is_null_node(const expression_node<T>* node) 05944 | { 05945 | return node && (details::expression_node<T>::e_null == node->type()); 05946 | } 05947 | 05948 | template <typename T> 05949 | inline bool is_break_node(const expression_node<T>* node) 05950 | { 05951 | return node && (details::expression_node<T>::e_break == node->type()); 05952 | } 05953 | 05954 | template <typename T> 05955 | inline bool is_continue_node(const expression_node<T>* node) 05956 | { 05957 | return node && (details::expression_node<T>::e_continue == node->type()); 05958 | } 05959 | 05960 | template <typename T> 05961 | inline bool is_swap_node(const expression_node<T>* node) 05962 | { 05963 | return node && (details::expression_node<T>::e_swap == node->type()); 05964 | } 05965 | 05966 | template <typename T> 05967 | inline bool is_function(const expression_node<T>* node) 05968 | { 05969 | return node && (details::expression_node<T>::e_function == node->type()); 05970 | } 05971 | 05972 | template <typename T> 05973 | inline bool is_vararg_node(const expression_node<T>* node) 05974 | { 05975 | return node && (details::expression_node<T>::e_vararg == node->type()); 05976 | } 05977 | 05978 | template <typename T> 05979 | inline bool is_return_node(const expression_node<T>* node) 05980 | { 05981 | return node && (details::expression_node<T>::e_return == node->type()); 05982 | } 05983 | 05984 | template <typename T> class unary_node; 05985 | 05986 | template <typename T> 05987 | inline bool is_negate_node(const expression_node<T>* node) 05988 | { 05989 | if (node && is_unary_node(node)) 05990 | { 05991 | return (details::e_neg == static_cast<const unary_node<T>*>(node)->operation()); 05992 | } 05993 | else 05994 | return false; 05995 | } 05996 | 05997 | template <typename T> 05998 | inline bool is_assert_node(const expression_node<T>* node) 05999 | { 06000 | return node && (details::expression_node<T>::e_assert == node->type()); 06001 | } 06002 | 06003 | template <typename T> 06004 | inline bool branch_deletable(const expression_node<T>* node) 06005 | { 06006 | return (0 != node) && 06007 | !is_variable_node(node) && 06008 | !is_string_node (node) ; 06009 | } 06010 | 06011 | template <std::size_t N, typename T> 06012 | inline bool all_nodes_valid(expression_node<T>* const (&b)[N]) 06013 | { 06014 | for (std::size_t i = 0; i < N; ++i) 06015 | { 06016 | if (0 == b[i]) return false; 06017 | } 06018 | 06019 | return true; 06020 | } 06021 | 06022 | template <typename T, 06023 | typename Allocator, 06024 | template <typename, typename> class Sequence> 06025 | inline bool all_nodes_valid(const Sequence<expression_node<T>*,Allocator>& b) 06026 | { 06027 | for (std::size_t i = 0; i < b.size(); ++i) 06028 | { 06029 | if (0 == b[i]) return false; 06030 | } 06031 | 06032 | return true; 06033 | } 06034 | 06035 | template <std::size_t N, typename T> 06036 | inline bool all_nodes_variables(expression_node<T>* const (&b)[N]) 06037 | { 06038 | for (std::size_t i = 0; i < N; ++i) 06039 | { 06040 | if (0 == b[i]) 06041 | return false; 06042 | else if (!is_variable_node(b[i])) 06043 | return false; 06044 | } 06045 | 06046 | return true; 06047 | } 06048 | 06049 | template <typename T, 06050 | typename Allocator, 06051 | template <typename, typename> class Sequence> 06052 | inline bool all_nodes_variables(const Sequence<expression_node<T>*,Allocator>& b) 06053 | { 06054 | for (std::size_t i = 0; i < b.size(); ++i) 06055 | { 06056 | if (0 == b[i]) 06057 | return false; 06058 | else if (!is_variable_node(b[i])) 06059 | return false; 06060 | } 06061 | 06062 | return true; 06063 | } 06064 | 06065 | template <typename Node> 06066 | class node_collection_destructor 06067 | { 06068 | public: 06069 | 06070 | typedef node_collector_interface<Node> nci_t; 06071 | 06072 | typedef typename nci_t::node_ptr_t node_ptr_t; 06073 | typedef typename nci_t::node_pp_t node_pp_t; 06074 | typedef typename nci_t::noderef_list_t noderef_list_t; 06075 | 06076 | static void delete_nodes(node_ptr_t& root) 06077 | { 06078 | std::vector<node_pp_t> node_delete_list; 06079 | node_delete_list.reserve(1000); 06080 | 06081 | collect_nodes(root, node_delete_list); 06082 | 06083 | for (std::size_t i = 0; i < node_delete_list.size(); ++i) 06084 | { 06085 | node_ptr_t& node = *node_delete_list[i]; 06086 | exprtk_debug(("ncd::delete_nodes() - deleting: %p\n", reinterpret_cast<void*>(node))); 06087 | delete node; 06088 | node = reinterpret_cast<node_ptr_t>(0); 06089 | } 06090 | } 06091 | 06092 | private: 06093 | 06094 | static void collect_nodes(node_ptr_t& root, noderef_list_t& node_delete_list) 06095 | { 06096 | std::deque<node_ptr_t> node_list; 06097 | node_list.push_back(root); 06098 | node_delete_list.push_back(&root); 06099 | 06100 | noderef_list_t child_node_delete_list; 06101 | child_node_delete_list.reserve(1000); 06102 | 06103 | while (!node_list.empty()) 06104 | { 06105 | node_list.front()->collect_nodes(child_node_delete_list); 06106 | 06107 | if (!child_node_delete_list.empty()) 06108 | { 06109 | for (std::size_t i = 0; i < child_node_delete_list.size(); ++i) 06110 | { 06111 | node_pp_t& node = child_node_delete_list[i]; 06112 | 06113 | if (0 == (*node)) 06114 | { 06115 | exprtk_debug(("ncd::collect_nodes() - null node encountered.\n")); 06116 | } 06117 | 06118 | node_list.push_back(*node); 06119 | } 06120 | 06121 | node_delete_list.insert( 06122 | node_delete_list.end(), 06123 | child_node_delete_list.begin(), child_node_delete_list.end()); 06124 | 06125 | child_node_delete_list.clear(); 06126 | } 06127 | 06128 | node_list.pop_front(); 06129 | } 06130 | 06131 | std::reverse(node_delete_list.begin(), node_delete_list.end()); 06132 | } 06133 | }; 06134 | 06135 | template <typename NodeAllocator, typename T, std::size_t N> 06136 | inline void free_all_nodes(NodeAllocator& node_allocator, expression_node<T>* (&b)[N]) 06137 | { 06138 | for (std::size_t i = 0; i < N; ++i) 06139 | { 06140 | free_node(node_allocator,b[i]); 06141 | } 06142 | } 06143 | 06144 | template <typename NodeAllocator, 06145 | typename T, 06146 | typename Allocator, 06147 | template <typename, typename> class Sequence> 06148 | inline void free_all_nodes(NodeAllocator& node_allocator, Sequence<expression_node<T>*,Allocator>& b) 06149 | { 06150 | for (std::size_t i = 0; i < b.size(); ++i) 06151 | { 06152 | free_node(node_allocator,b[i]); 06153 | } 06154 | 06155 | b.clear(); 06156 | } 06157 | 06158 | template <typename NodeAllocator, typename T> 06159 | inline void free_node(NodeAllocator&, expression_node<T>*& node) 06160 | { 06161 | if ((0 == node) || is_variable_node(node) || is_string_node(node)) 06162 | { 06163 | return; 06164 | } 06165 | 06166 | node_collection_destructor<expression_node<T> > 06167 | ::delete_nodes(node); 06168 | } 06169 | 06170 | template <typename T> 06171 | inline void destroy_node(expression_node<T>*& node) 06172 | { 06173 | if (0 != node) 06174 | { 06175 | node_collection_destructor<expression_node<T> > 06176 | ::delete_nodes(node); 06177 | } 06178 | } 06179 | 06180 | template <typename Node> 06181 | struct node_depth_base 06182 | { 06183 | typedef Node* node_ptr_t; 06184 | typedef std::pair<node_ptr_t,bool> nb_pair_t; 06185 | 06186 | node_depth_base() 06187 | : depth_set(false) 06188 | , depth(0) 06189 | {} 06190 | 06191 | virtual ~node_depth_base() 06192 | {} 06193 | 06194 | virtual std::size_t node_depth() const { return 1; } 06195 | 06196 | std::size_t compute_node_depth(const Node* const& node) const 06197 | { 06198 | if (!depth_set) 06199 | { 06200 | depth = 1 + (node ? node->node_depth() : 0); 06201 | depth_set = true; 06202 | } 06203 | 06204 | return depth; 06205 | } 06206 | 06207 | std::size_t compute_node_depth(const nb_pair_t& branch) const 06208 | { 06209 | if (!depth_set) 06210 | { 06211 | depth = 1 + (branch.first ? branch.first->node_depth() : 0); 06212 | depth_set = true; 06213 | } 06214 | 06215 | return depth; 06216 | } 06217 | 06218 | template <std::size_t N> 06219 | std::size_t compute_node_depth(const nb_pair_t (&branch)[N]) const 06220 | { 06221 | if (!depth_set) 06222 | { 06223 | depth = 0; 06224 | 06225 | for (std::size_t i = 0; i < N; ++i) 06226 | { 06227 | if (branch[i].first) 06228 | { 06229 | depth = std::max(depth,branch[i].first->node_depth()); 06230 | } 06231 | } 06232 | 06233 | depth += 1; 06234 | depth_set = true; 06235 | } 06236 | 06237 | return depth; 06238 | } 06239 | 06240 | template <typename BranchType> 06241 | std::size_t max_node_depth(const BranchType& n0, const BranchType& n1) const 06242 | { 06243 | return std::max(compute_node_depth(n0), compute_node_depth(n1)); 06244 | } 06245 | 06246 | template <typename BranchType> 06247 | std::size_t max_node_depth(const BranchType& n0, const BranchType& n1, const BranchType& n2) const 06248 | { 06249 | return std::max(compute_node_depth(n0), 06250 | std::max(compute_node_depth(n1), compute_node_depth(n2))); 06251 | } 06252 | 06253 | template <typename BranchType> 06254 | std::size_t max_node_depth(const BranchType& n0, const BranchType& n1, 06255 | const BranchType& n2, const BranchType& n3) const 06256 | { 06257 | return std::max( 06258 | std::max(compute_node_depth(n0), compute_node_depth(n1)), 06259 | std::max(compute_node_depth(n2), compute_node_depth(n3))); 06260 | } 06261 | 06262 | template <typename BranchType> 06263 | std::size_t compute_node_depth(const BranchType& n0, const BranchType& n1) const 06264 | { 06265 | if (!depth_set) 06266 | { 06267 | depth = 1 + max_node_depth(n0, n1); 06268 | depth_set = true; 06269 | } 06270 | 06271 | return depth; 06272 | } 06273 | 06274 | template <typename BranchType> 06275 | std::size_t compute_node_depth(const BranchType& n0, const BranchType& n1, 06276 | const BranchType& n2) const 06277 | { 06278 | if (!depth_set) 06279 | { 06280 | depth = 1 + max_node_depth(n0, n1, n2); 06281 | depth_set = true; 06282 | } 06283 | 06284 | return depth; 06285 | } 06286 | 06287 | template <typename BranchType> 06288 | std::size_t compute_node_depth(const BranchType& n0, const BranchType& n1, 06289 | const BranchType& n2, const BranchType& n3) const 06290 | { 06291 | if (!depth_set) 06292 | { 06293 | depth = 1 + max_node_depth(n0, n1, n2, n3); 06294 | depth_set = true; 06295 | } 06296 | 06297 | return depth; 06298 | } 06299 | 06300 | template <typename Allocator, 06301 | template <typename, typename> class Sequence> 06302 | std::size_t compute_node_depth(const Sequence<node_ptr_t, Allocator>& branch_list) const 06303 | { 06304 | if (!depth_set) 06305 | { 06306 | for (std::size_t i = 0; i < branch_list.size(); ++i) 06307 | { 06308 | if (branch_list[i]) 06309 | { 06310 | depth = std::max(depth, compute_node_depth(branch_list[i])); 06311 | } 06312 | } 06313 | 06314 | depth_set = true; 06315 | } 06316 | 06317 | return depth; 06318 | } 06319 | 06320 | template <typename Allocator, 06321 | template <typename, typename> class Sequence> 06322 | std::size_t compute_node_depth(const Sequence<nb_pair_t,Allocator>& branch_list) const 06323 | { 06324 | if (!depth_set) 06325 | { 06326 | for (std::size_t i = 0; i < branch_list.size(); ++i) 06327 | { 06328 | if (branch_list[i].first) 06329 | { 06330 | depth = std::max(depth, compute_node_depth(branch_list[i].first)); 06331 | } 06332 | } 06333 | 06334 | depth_set = true; 06335 | } 06336 | 06337 | return depth; 06338 | } 06339 | 06340 | mutable bool depth_set; 06341 | mutable std::size_t depth; 06342 | 06343 | template <typename NodeSequence> 06344 | void collect(node_ptr_t const& node, 06345 | const bool deletable, 06346 | NodeSequence& delete_node_list) const 06347 | { 06348 | if ((0 != node) && deletable) 06349 | { 06350 | delete_node_list.push_back(const_cast<node_ptr_t*>(&node)); 06351 | } 06352 | } 06353 | 06354 | template <typename NodeSequence> 06355 | void collect(const nb_pair_t& branch, 06356 | NodeSequence& delete_node_list) const 06357 | { 06358 | collect(branch.first, branch.second, delete_node_list); 06359 | } 06360 | 06361 | template <typename NodeSequence> 06362 | void collect(Node*& node, 06363 | NodeSequence& delete_node_list) const 06364 | { 06365 | collect(node, branch_deletable(node), delete_node_list); 06366 | } 06367 | 06368 | template <std::size_t N, typename NodeSequence> 06369 | void collect(const nb_pair_t(&branch)[N], 06370 | NodeSequence& delete_node_list) const 06371 | { 06372 | for (std::size_t i = 0; i < N; ++i) 06373 | { 06374 | collect(branch[i].first, branch[i].second, delete_node_list); 06375 | } 06376 | } 06377 | 06378 | template <typename Allocator, 06379 | template <typename, typename> class Sequence, 06380 | typename NodeSequence> 06381 | void collect(const Sequence<nb_pair_t, Allocator>& branch, 06382 | NodeSequence& delete_node_list) const 06383 | { 06384 | for (std::size_t i = 0; i < branch.size(); ++i) 06385 | { 06386 | collect(branch[i].first, branch[i].second, delete_node_list); 06387 | } 06388 | } 06389 | 06390 | template <typename Allocator, 06391 | template <typename, typename> class Sequence, 06392 | typename NodeSequence> 06393 | void collect(const Sequence<node_ptr_t, Allocator>& branch_list, 06394 | NodeSequence& delete_node_list) const 06395 | { 06396 | for (std::size_t i = 0; i < branch_list.size(); ++i) 06397 | { 06398 | collect(branch_list[i], branch_deletable(branch_list[i]), delete_node_list); 06399 | } 06400 | } 06401 | 06402 | template <typename Boolean, 06403 | typename AllocatorT, 06404 | typename AllocatorB, 06405 | template <typename, typename> class Sequence, 06406 | typename NodeSequence> 06407 | void collect(const Sequence<node_ptr_t, AllocatorT>& branch_list, 06408 | const Sequence<Boolean, AllocatorB>& branch_deletable_list, 06409 | NodeSequence& delete_node_list) const 06410 | { 06411 | for (std::size_t i = 0; i < branch_list.size(); ++i) 06412 | { 06413 | collect(branch_list[i], branch_deletable_list[i], delete_node_list); 06414 | } 06415 | } 06416 | }; 06417 | 06418 | template <typename Type> 06419 | class vector_holder 06420 | { 06421 | private: 06422 | 06423 | typedef Type value_type; 06424 | typedef value_type* value_ptr; 06425 | typedef const value_ptr const_value_ptr; 06426 | typedef vector_holder<Type> vector_holder_t; 06427 | 06428 | class vector_holder_base 06429 | { 06430 | public: 06431 | 06432 | virtual ~vector_holder_base() 06433 | {} 06434 | 06435 | inline value_ptr operator[](const std::size_t& index) const 06436 | { 06437 | return value_at(index); 06438 | } 06439 | 06440 | inline std::size_t size() const 06441 | { 06442 | return vector_size(); 06443 | } 06444 | 06445 | inline std::size_t base_size() const 06446 | { 06447 | return vector_base_size(); 06448 | } 06449 | 06450 | inline value_ptr data() const 06451 | { 06452 | return value_at(0); 06453 | } 06454 | 06455 | virtual inline bool rebaseable() const 06456 | { 06457 | return false; 06458 | } 06459 | 06460 | virtual void set_ref(value_ptr*) 06461 | {} 06462 | 06463 | virtual void remove_ref(value_ptr*) 06464 | {} 06465 | 06466 | virtual void set_size_ref(std::size_t*) 06467 | {} 06468 | 06469 | virtual void remove_size_ref(std::size_t*) 06470 | {} 06471 | 06472 | virtual vector_view<Type>* rebaseable_instance() 06473 | { 06474 | return reinterpret_cast<vector_view<Type>*>(0); 06475 | } 06476 | 06477 | protected: 06478 | 06479 | virtual value_ptr value_at(const std::size_t&) const = 0; 06480 | virtual std::size_t vector_size() const = 0; 06481 | virtual std::size_t vector_base_size() const = 0; 06482 | }; 06483 | 06484 | class array_vector_impl exprtk_final : public vector_holder_base 06485 | { 06486 | public: 06487 | 06488 | array_vector_impl(const Type* vec, const std::size_t& vec_size) 06489 | : vec_(vec) 06490 | , size_(vec_size) 06491 | {} 06492 | 06493 | protected: 06494 | 06495 | value_ptr value_at(const std::size_t& index) const exprtk_override 06496 | { 06497 | assert(index < size_); 06498 | return const_cast<const_value_ptr>(vec_ + index); 06499 | } 06500 | 06501 | std::size_t vector_size() const exprtk_override 06502 | { 06503 | return size_; 06504 | } 06505 | 06506 | std::size_t vector_base_size() const exprtk_override 06507 | { 06508 | return vector_size(); 06509 | } 06510 | 06511 | private: 06512 | 06513 | array_vector_impl(const array_vector_impl&) exprtk_delete; 06514 | array_vector_impl& operator=(const array_vector_impl&) exprtk_delete; 06515 | 06516 | const Type* vec_; 06517 | const std::size_t size_; 06518 | }; 06519 | 06520 | template <typename Allocator, 06521 | template <typename, typename> class Sequence> 06522 | class sequence_vector_impl exprtk_final : public vector_holder_base 06523 | { 06524 | public: 06525 | 06526 | typedef Sequence<Type,Allocator> sequence_t; 06527 | 06528 | explicit sequence_vector_impl(sequence_t& seq) 06529 | : sequence_(seq) 06530 | {} 06531 | 06532 | protected: 06533 | 06534 | value_ptr value_at(const std::size_t& index) const exprtk_override 06535 | { 06536 | assert(index < sequence_.size()); 06537 | return (&sequence_[index]); 06538 | } 06539 | 06540 | std::size_t vector_size() const exprtk_override 06541 | { 06542 | return sequence_.size(); 06543 | } 06544 | 06545 | std::size_t vector_base_size() const exprtk_override 06546 | { 06547 | return vector_size(); 06548 | } 06549 | 06550 | private: 06551 | 06552 | sequence_vector_impl(const sequence_vector_impl&) exprtk_delete; 06553 | sequence_vector_impl& operator=(const sequence_vector_impl&) exprtk_delete; 06554 | 06555 | sequence_t& sequence_; 06556 | }; 06557 | 06558 | class vector_view_impl exprtk_final : public vector_holder_base 06559 | { 06560 | public: 06561 | 06562 | typedef exprtk::vector_view<Type> vector_view_t; 06563 | 06564 | explicit vector_view_impl(vector_view_t& vec_view) 06565 | : vec_view_(vec_view) 06566 | { 06567 | assert(vec_view_.size() > 0); 06568 | } 06569 | 06570 | void set_ref(value_ptr* ref) exprtk_override 06571 | { 06572 | vec_view_.set_ref(ref); 06573 | } 06574 | 06575 | void remove_ref(value_ptr* ref) exprtk_override 06576 | { 06577 | vec_view_.remove_ref(ref); 06578 | } 06579 | 06580 | bool rebaseable() const exprtk_override 06581 | { 06582 | return true; 06583 | } 06584 | 06585 | vector_view<Type>* rebaseable_instance() exprtk_override 06586 | { 06587 | return &vec_view_; 06588 | } 06589 | 06590 | protected: 06591 | 06592 | value_ptr value_at(const std::size_t& index) const exprtk_override 06593 | { 06594 | assert(index < vec_view_.size()); 06595 | return (&vec_view_[index]); 06596 | } 06597 | 06598 | std::size_t vector_size() const exprtk_override 06599 | { 06600 | return vec_view_.size(); 06601 | } 06602 | 06603 | std::size_t vector_base_size() const exprtk_override 06604 | { 06605 | return vec_view_.base_size(); 06606 | } 06607 | 06608 | private: 06609 | 06610 | vector_view_impl(const vector_view_impl&) exprtk_delete; 06611 | vector_view_impl& operator=(const vector_view_impl&) exprtk_delete; 06612 | 06613 | vector_view_t& vec_view_; 06614 | }; 06615 | 06616 | class resizable_vector_impl exprtk_final : public vector_holder_base 06617 | { 06618 | public: 06619 | 06620 | resizable_vector_impl(vector_holder& vec_view_holder, 06621 | const Type* vec, 06622 | const std::size_t& vec_size) 06623 | : vec_(vec) 06624 | , size_(vec_size) 06625 | , vec_view_holder_(*vec_view_holder.rebaseable_instance()) 06626 | { 06627 | assert(vec_view_holder.rebaseable_instance()); 06628 | assert(size_ <= vector_base_size()); 06629 | } 06630 | 06631 | virtual ~resizable_vector_impl() exprtk_override 06632 | {} 06633 | 06634 | protected: 06635 | 06636 | value_ptr value_at(const std::size_t& index) const exprtk_override 06637 | { 06638 | assert(index < vector_size()); 06639 | return const_cast<const_value_ptr>(vec_ + index); 06640 | } 06641 | 06642 | std::size_t vector_size() const exprtk_override 06643 | { 06644 | return vec_view_holder_.size(); 06645 | } 06646 | 06647 | std::size_t vector_base_size() const exprtk_override 06648 | { 06649 | return vec_view_holder_.base_size(); 06650 | } 06651 | 06652 | bool rebaseable() const exprtk_override 06653 | { 06654 | return true; 06655 | } 06656 | 06657 | virtual vector_view<Type>* rebaseable_instance() exprtk_override 06658 | { 06659 | return &vec_view_holder_; 06660 | } 06661 | 06662 | private: 06663 | 06664 | resizable_vector_impl(const resizable_vector_impl&) exprtk_delete; 06665 | resizable_vector_impl& operator=(const resizable_vector_impl&) exprtk_delete; 06666 | 06667 | const Type* vec_; 06668 | const std::size_t size_; 06669 | vector_view<Type>& vec_view_holder_; 06670 | }; 06671 | 06672 | public: 06673 | 06674 | typedef typename details::vec_data_store<Type> vds_t; 06675 | 06676 | vector_holder(Type* vec, const std::size_t& vec_size) 06677 | : vector_holder_base_(new(buffer)array_vector_impl(vec,vec_size)) 06678 | {} 06679 | 06680 | explicit vector_holder(const vds_t& vds) 06681 | : vector_holder_base_(new(buffer)array_vector_impl(vds.data(),vds.size())) 06682 | {} 06683 | 06684 | template <typename Allocator> 06685 | explicit vector_holder(std::vector<Type,Allocator>& vec) 06686 | : vector_holder_base_(new(buffer)sequence_vector_impl<Allocator,std::vector>(vec)) 06687 | {} 06688 | 06689 | explicit vector_holder(exprtk::vector_view<Type>& vec) 06690 | : vector_holder_base_(new(buffer)vector_view_impl(vec)) 06691 | {} 06692 | 06693 | explicit vector_holder(vector_holder_t& vec_holder, const vds_t& vds) 06694 | : vector_holder_base_(new(buffer)resizable_vector_impl(vec_holder, vds.data(), vds.size())) 06695 | {} 06696 | 06697 | inline value_ptr operator[](const std::size_t& index) const 06698 | { 06699 | return (*vector_holder_base_)[index]; 06700 | } 06701 | 06702 | inline std::size_t size() const 06703 | { 06704 | return vector_holder_base_->size(); 06705 | } 06706 | 06707 | inline std::size_t base_size() const 06708 | { 06709 | return vector_holder_base_->base_size(); 06710 | } 06711 | 06712 | inline value_ptr data() const 06713 | { 06714 | return vector_holder_base_->data(); 06715 | } 06716 | 06717 | void set_ref(value_ptr* ref) 06718 | { 06719 | if (rebaseable()) 06720 | { 06721 | vector_holder_base_->set_ref(ref); 06722 | } 06723 | } 06724 | 06725 | void set_size_ref(std::size_t* ref) 06726 | { 06727 | if (rebaseable()) 06728 | { 06729 | vector_holder_base_->set_size_ref(ref); 06730 | } 06731 | } 06732 | 06733 | void remove_ref(value_ptr* ref) 06734 | { 06735 | if (rebaseable()) 06736 | { 06737 | vector_holder_base_->remove_ref(ref); 06738 | } 06739 | } 06740 | 06741 | void remove_size_ref(std::size_t* ref) 06742 | { 06743 | if (rebaseable()) 06744 | { 06745 | vector_holder_base_->remove_size_ref(ref); 06746 | } 06747 | } 06748 | 06749 | bool rebaseable() const 06750 | { 06751 | return vector_holder_base_->rebaseable(); 06752 | } 06753 | 06754 | vector_view<Type>* rebaseable_instance() 06755 | { 06756 | return vector_holder_base_->rebaseable_instance(); 06757 | } 06758 | 06759 | private: 06760 | 06761 | vector_holder(const vector_holder<Type>&) exprtk_delete; 06762 | vector_holder<Type>& operator=(const vector_holder<Type>&) exprtk_delete; 06763 | 06764 | mutable vector_holder_base* vector_holder_base_; 06765 | uchar_t buffer[64]; 06766 | }; 06767 | 06768 | template <typename T> 06769 | class null_node exprtk_final : public expression_node<T> 06770 | { 06771 | public: 06772 | 06773 | inline T value() const exprtk_override 06774 | { 06775 | return std::numeric_limits<T>::quiet_NaN(); 06776 | } 06777 | 06778 | inline typename expression_node<T>::node_type type() const exprtk_override 06779 | { 06780 | return expression_node<T>::e_null; 06781 | } 06782 | }; 06783 | 06784 | template <typename T, std::size_t N> 06785 | inline void construct_branch_pair(std::pair<expression_node<T>*,bool> (&branch)[N], 06786 | expression_node<T>* b, 06787 | const std::size_t& index) 06788 | { 06789 | if (b && (index < N)) 06790 | { 06791 | branch[index] = std::make_pair(b,branch_deletable(b)); 06792 | } 06793 | } 06794 | 06795 | template <typename T> 06796 | inline void construct_branch_pair(std::pair<expression_node<T>*,bool>& branch, expression_node<T>* b) 06797 | { 06798 | if (b) 06799 | { 06800 | branch = std::make_pair(b,branch_deletable(b)); 06801 | } 06802 | } 06803 | 06804 | template <std::size_t N, typename T> 06805 | inline void init_branches(std::pair<expression_node<T>*,bool> (&branch)[N], 06806 | expression_node<T>* b0, 06807 | expression_node<T>* b1 = reinterpret_cast<expression_node<T>*>(0), 06808 | expression_node<T>* b2 = reinterpret_cast<expression_node<T>*>(0), 06809 | expression_node<T>* b3 = reinterpret_cast<expression_node<T>*>(0), 06810 | expression_node<T>* b4 = reinterpret_cast<expression_node<T>*>(0), 06811 | expression_node<T>* b5 = reinterpret_cast<expression_node<T>*>(0), 06812 | expression_node<T>* b6 = reinterpret_cast<expression_node<T>*>(0), 06813 | expression_node<T>* b7 = reinterpret_cast<expression_node<T>*>(0), 06814 | expression_node<T>* b8 = reinterpret_cast<expression_node<T>*>(0), 06815 | expression_node<T>* b9 = reinterpret_cast<expression_node<T>*>(0)) 06816 | { 06817 | construct_branch_pair(branch, b0, 0); 06818 | construct_branch_pair(branch, b1, 1); 06819 | construct_branch_pair(branch, b2, 2); 06820 | construct_branch_pair(branch, b3, 3); 06821 | construct_branch_pair(branch, b4, 4); 06822 | construct_branch_pair(branch, b5, 5); 06823 | construct_branch_pair(branch, b6, 6); 06824 | construct_branch_pair(branch, b7, 7); 06825 | construct_branch_pair(branch, b8, 8); 06826 | construct_branch_pair(branch, b9, 9); 06827 | } 06828 | 06829 | template <typename T> 06830 | class null_eq_node exprtk_final : public expression_node<T> 06831 | { 06832 | public: 06833 | 06834 | typedef expression_node<T>* expression_ptr; 06835 | typedef std::pair<expression_ptr,bool> branch_t; 06836 | 06837 | explicit null_eq_node(expression_ptr branch, const bool equality = true) 06838 | : equality_(equality) 06839 | { 06840 | construct_branch_pair(branch_, branch); 06841 | assert(valid()); 06842 | } 06843 | 06844 | inline T value() const exprtk_override 06845 | { 06846 | const T v = branch_.first->value(); 06847 | const bool result = details::numeric::is_nan(v); 06848 | 06849 | if (result) 06850 | return equality_ ? T(1) : T(0); 06851 | else 06852 | return equality_ ? T(0) : T(1); 06853 | } 06854 | 06855 | inline typename expression_node<T>::node_type type() const exprtk_override 06856 | { 06857 | return expression_node<T>::e_nulleq; 06858 | } 06859 | 06860 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 06861 | { 06862 | return branch_.first; 06863 | } 06864 | 06865 | inline bool valid() const exprtk_override 06866 | { 06867 | return branch_.first; 06868 | } 06869 | 06870 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 06871 | { 06872 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 06873 | } 06874 | 06875 | std::size_t node_depth() const exprtk_override 06876 | { 06877 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 06878 | } 06879 | 06880 | private: 06881 | 06882 | bool equality_; 06883 | branch_t branch_; 06884 | }; 06885 | 06886 | template <typename T> 06887 | class literal_node exprtk_final : public expression_node<T> 06888 | { 06889 | public: 06890 | 06891 | explicit literal_node(const T& v) 06892 | : value_(v) 06893 | {} 06894 | 06895 | inline T value() const exprtk_override 06896 | { 06897 | return value_; 06898 | } 06899 | 06900 | inline typename expression_node<T>::node_type type() const exprtk_override 06901 | { 06902 | return expression_node<T>::e_constant; 06903 | } 06904 | 06905 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 06906 | { 06907 | return reinterpret_cast<expression_node<T>*>(0); 06908 | } 06909 | 06910 | private: 06911 | 06912 | literal_node(const literal_node<T>&) exprtk_delete; 06913 | literal_node<T>& operator=(const literal_node<T>&) exprtk_delete; 06914 | 06915 | const T value_; 06916 | }; 06917 | 06918 | template <typename T> 06919 | struct range_pack; 06920 | 06921 | template <typename T> 06922 | struct range_data_type; 06923 | 06924 | template <typename T> 06925 | class range_interface 06926 | { 06927 | public: 06928 | 06929 | typedef range_pack<T> range_t; 06930 | 06931 | virtual ~range_interface() 06932 | {} 06933 | 06934 | virtual range_t& range_ref() = 0; 06935 | 06936 | virtual const range_t& range_ref() const = 0; 06937 | }; 06938 | 06939 | #ifndef exprtk_disable_string_capabilities 06940 | template <typename T> 06941 | class string_base_node 06942 | { 06943 | public: 06944 | 06945 | typedef range_data_type<T> range_data_type_t; 06946 | 06947 | virtual ~string_base_node() 06948 | {} 06949 | 06950 | virtual std::string str () const = 0; 06951 | 06952 | virtual char_cptr base() const = 0; 06953 | 06954 | virtual std::size_t size() const = 0; 06955 | }; 06956 | 06957 | template <typename T> 06958 | class string_literal_node exprtk_final 06959 | : public expression_node <T> 06960 | , public string_base_node<T> 06961 | , public range_interface <T> 06962 | { 06963 | public: 06964 | 06965 | typedef range_pack<T> range_t; 06966 | 06967 | explicit string_literal_node(const std::string& v) 06968 | : value_(v) 06969 | { 06970 | rp_.n0_c = std::make_pair<bool,std::size_t>(true, 0); 06971 | rp_.n1_c = std::make_pair<bool,std::size_t>(true, v.size()); 06972 | rp_.cache.first = rp_.n0_c.second; 06973 | rp_.cache.second = rp_.n1_c.second; 06974 | } 06975 | 06976 | inline T value() const exprtk_override 06977 | { 06978 | return std::numeric_limits<T>::quiet_NaN(); 06979 | } 06980 | 06981 | inline typename expression_node<T>::node_type type() const exprtk_override 06982 | { 06983 | return expression_node<T>::e_stringconst; 06984 | } 06985 | 06986 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 06987 | { 06988 | return reinterpret_cast<expression_node<T>*>(0); 06989 | } 06990 | 06991 | std::string str() const exprtk_override 06992 | { 06993 | return value_; 06994 | } 06995 | 06996 | char_cptr base() const exprtk_override 06997 | { 06998 | return value_.data(); 06999 | } 07000 | 07001 | std::size_t size() const exprtk_override 07002 | { 07003 | return value_.size(); 07004 | } 07005 | 07006 | range_t& range_ref() exprtk_override 07007 | { 07008 | return rp_; 07009 | } 07010 | 07011 | const range_t& range_ref() const exprtk_override 07012 | { 07013 | return rp_; 07014 | } 07015 | 07016 | private: 07017 | 07018 | string_literal_node(const string_literal_node<T>&) exprtk_delete; 07019 | string_literal_node<T>& operator=(const string_literal_node<T>&) exprtk_delete; 07020 | 07021 | const std::string value_; 07022 | range_t rp_; 07023 | }; 07024 | #endif 07025 | 07026 | template <typename T> 07027 | class unary_node : public expression_node<T> 07028 | { 07029 | public: 07030 | 07031 | typedef expression_node<T>* expression_ptr; 07032 | typedef std::pair<expression_ptr,bool> branch_t; 07033 | 07034 | unary_node(const operator_type& opr, expression_ptr branch) 07035 | : operation_(opr) 07036 | { 07037 | construct_branch_pair(branch_,branch); 07038 | assert(valid()); 07039 | } 07040 | 07041 | inline T value() const exprtk_override 07042 | { 07043 | return numeric::process<T> 07044 | (operation_,branch_.first->value()); 07045 | } 07046 | 07047 | inline typename expression_node<T>::node_type type() const exprtk_override 07048 | { 07049 | return expression_node<T>::e_unary; 07050 | } 07051 | 07052 | inline operator_type operation() 07053 | { 07054 | return operation_; 07055 | } 07056 | 07057 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 07058 | { 07059 | return branch_.first; 07060 | } 07061 | 07062 | inline bool valid() const exprtk_override 07063 | { 07064 | return branch_.first && branch_.first->valid(); 07065 | } 07066 | 07067 | inline void release() 07068 | { 07069 | branch_.second = false; 07070 | } 07071 | 07072 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07073 | { 07074 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 07075 | } 07076 | 07077 | std::size_t node_depth() const exprtk_final 07078 | { 07079 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 07080 | } 07081 | 07082 | private: 07083 | 07084 | operator_type operation_; 07085 | branch_t branch_; 07086 | }; 07087 | 07088 | template <typename T> 07089 | class binary_node : public expression_node<T> 07090 | { 07091 | public: 07092 | 07093 | typedef expression_node<T>* expression_ptr; 07094 | typedef std::pair<expression_ptr,bool> branch_t; 07095 | 07096 | binary_node(const operator_type& opr, 07097 | expression_ptr branch0, 07098 | expression_ptr branch1) 07099 | : operation_(opr) 07100 | { 07101 | init_branches<2>(branch_, branch0, branch1); 07102 | assert(valid()); 07103 | } 07104 | 07105 | inline T value() const exprtk_override 07106 | { 07107 | return numeric::process<T> 07108 | ( 07109 | operation_, 07110 | branch_[0].first->value(), 07111 | branch_[1].first->value() 07112 | ); 07113 | } 07114 | 07115 | inline typename expression_node<T>::node_type type() const exprtk_override 07116 | { 07117 | return expression_node<T>::e_binary; 07118 | } 07119 | 07120 | inline operator_type operation() 07121 | { 07122 | return operation_; 07123 | } 07124 | 07125 | inline expression_node<T>* branch(const std::size_t& index = 0) const exprtk_override 07126 | { 07127 | assert(index < 2); 07128 | return branch_[index].first; 07129 | } 07130 | 07131 | inline bool valid() const exprtk_override 07132 | { 07133 | return 07134 | branch_[0].first && branch_[0].first->valid() && 07135 | branch_[1].first && branch_[1].first->valid() ; 07136 | } 07137 | 07138 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07139 | { 07140 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 07141 | } 07142 | 07143 | std::size_t node_depth() const exprtk_final 07144 | { 07145 | return expression_node<T>::ndb_t::template compute_node_depth<2>(branch_); 07146 | } 07147 | 07148 | private: 07149 | 07150 | operator_type operation_; 07151 | branch_t branch_[2]; 07152 | }; 07153 | 07154 | template <typename T, typename Operation> 07155 | class binary_ext_node exprtk_final : public expression_node<T> 07156 | { 07157 | public: 07158 | 07159 | typedef expression_node<T>* expression_ptr; 07160 | typedef std::pair<expression_ptr,bool> branch_t; 07161 | 07162 | binary_ext_node(expression_ptr branch0, expression_ptr branch1) 07163 | { 07164 | init_branches<2>(branch_, branch0, branch1); 07165 | assert(valid()); 07166 | } 07167 | 07168 | inline T value() const exprtk_override 07169 | { 07170 | const T arg0 = branch_[0].first->value(); 07171 | const T arg1 = branch_[1].first->value(); 07172 | return Operation::process(arg0,arg1); 07173 | } 07174 | 07175 | inline typename expression_node<T>::node_type type() const exprtk_override 07176 | { 07177 | return expression_node<T>::e_binary_ext; 07178 | } 07179 | 07180 | inline operator_type operation() 07181 | { 07182 | return Operation::operation(); 07183 | } 07184 | 07185 | inline expression_node<T>* branch(const std::size_t& index = 0) const exprtk_override 07186 | { 07187 | assert(index < 2); 07188 | return branch_[index].first; 07189 | } 07190 | 07191 | inline bool valid() const exprtk_override 07192 | { 07193 | return 07194 | branch_[0].first && branch_[0].first->valid() && 07195 | branch_[1].first && branch_[1].first->valid() ; 07196 | } 07197 | 07198 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07199 | { 07200 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 07201 | } 07202 | 07203 | std::size_t node_depth() const exprtk_override 07204 | { 07205 | return expression_node<T>::ndb_t::template compute_node_depth<2>(branch_); 07206 | } 07207 | 07208 | protected: 07209 | 07210 | branch_t branch_[2]; 07211 | }; 07212 | 07213 | template <typename T> 07214 | class trinary_node : public expression_node<T> 07215 | { 07216 | public: 07217 | 07218 | typedef expression_node<T>* expression_ptr; 07219 | typedef std::pair<expression_ptr,bool> branch_t; 07220 | 07221 | trinary_node(const operator_type& opr, 07222 | expression_ptr branch0, 07223 | expression_ptr branch1, 07224 | expression_ptr branch2) 07225 | : operation_(opr) 07226 | { 07227 | init_branches<3>(branch_, branch0, branch1, branch2); 07228 | assert(valid()); 07229 | } 07230 | 07231 | inline T value() const exprtk_override 07232 | { 07233 | const T arg0 = branch_[0].first->value(); 07234 | const T arg1 = branch_[1].first->value(); 07235 | const T arg2 = branch_[2].first->value(); 07236 | 07237 | switch (operation_) 07238 | { 07239 | case e_inrange : return (arg1 < arg0) ? T(0) : ((arg1 > arg2) ? T(0) : T(1)); 07240 | 07241 | case e_clamp : return (arg1 < arg0) ? arg0 : (arg1 > arg2 ? arg2 : arg1); 07242 | 07243 | case e_iclamp : if ((arg1 <= arg0) || (arg1 >= arg2)) 07244 | return arg1; 07245 | else 07246 | return ((T(2) * arg1 <= (arg2 + arg0)) ? arg0 : arg2); 07247 | 07248 | default : exprtk_debug(("trinary_node::value() - Error: Invalid operation\n")); 07249 | return std::numeric_limits<T>::quiet_NaN(); 07250 | } 07251 | } 07252 | 07253 | inline typename expression_node<T>::node_type type() const exprtk_override 07254 | { 07255 | return expression_node<T>::e_trinary; 07256 | } 07257 | 07258 | inline bool valid() const exprtk_override 07259 | { 07260 | return 07261 | branch_[0].first && branch_[0].first->valid() && 07262 | branch_[1].first && branch_[1].first->valid() && 07263 | branch_[2].first && branch_[2].first->valid() ; 07264 | } 07265 | 07266 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07267 | { 07268 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 07269 | } 07270 | 07271 | std::size_t node_depth() const exprtk_override exprtk_final 07272 | { 07273 | return expression_node<T>::ndb_t::template compute_node_depth<3>(branch_); 07274 | } 07275 | 07276 | protected: 07277 | 07278 | operator_type operation_; 07279 | branch_t branch_[3]; 07280 | }; 07281 | 07282 | template <typename T> 07283 | class quaternary_node : public expression_node<T> 07284 | { 07285 | public: 07286 | 07287 | typedef expression_node<T>* expression_ptr; 07288 | typedef std::pair<expression_ptr,bool> branch_t; 07289 | 07290 | quaternary_node(const operator_type& opr, 07291 | expression_ptr branch0, 07292 | expression_ptr branch1, 07293 | expression_ptr branch2, 07294 | expression_ptr branch3) 07295 | : operation_(opr) 07296 | { 07297 | init_branches<4>(branch_, branch0, branch1, branch2, branch3); 07298 | } 07299 | 07300 | inline T value() const exprtk_override 07301 | { 07302 | return std::numeric_limits<T>::quiet_NaN(); 07303 | } 07304 | 07305 | inline typename expression_node<T>::node_type type() const exprtk_override 07306 | { 07307 | return expression_node<T>::e_quaternary; 07308 | } 07309 | 07310 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07311 | { 07312 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 07313 | } 07314 | 07315 | std::size_t node_depth() const exprtk_override exprtk_final 07316 | { 07317 | return expression_node<T>::ndb_t::template compute_node_depth<4>(branch_); 07318 | } 07319 | 07320 | inline bool valid() const exprtk_override 07321 | { 07322 | return 07323 | branch_[0].first && branch_[0].first->valid() && 07324 | branch_[1].first && branch_[1].first->valid() && 07325 | branch_[2].first && branch_[2].first->valid() && 07326 | branch_[3].first && branch_[3].first->valid() ; 07327 | } 07328 | 07329 | protected: 07330 | 07331 | operator_type operation_; 07332 | branch_t branch_[4]; 07333 | }; 07334 | 07335 | template <typename T> 07336 | class conditional_node exprtk_final : public expression_node<T> 07337 | { 07338 | public: 07339 | 07340 | typedef expression_node<T>* expression_ptr; 07341 | typedef std::pair<expression_ptr,bool> branch_t; 07342 | 07343 | conditional_node(expression_ptr condition, 07344 | expression_ptr consequent, 07345 | expression_ptr alternative) 07346 | { 07347 | construct_branch_pair(condition_ , condition ); 07348 | construct_branch_pair(consequent_ , consequent ); 07349 | construct_branch_pair(alternative_, alternative); 07350 | assert(valid()); 07351 | } 07352 | 07353 | inline T value() const exprtk_override 07354 | { 07355 | if (is_true(condition_)) 07356 | return consequent_.first->value(); 07357 | else 07358 | return alternative_.first->value(); 07359 | } 07360 | 07361 | inline typename expression_node<T>::node_type type() const exprtk_override 07362 | { 07363 | return expression_node<T>::e_conditional; 07364 | } 07365 | 07366 | inline bool valid() const exprtk_override 07367 | { 07368 | return 07369 | condition_ .first && condition_ .first->valid() && 07370 | consequent_ .first && consequent_ .first->valid() && 07371 | alternative_.first && alternative_.first->valid() ; 07372 | } 07373 | 07374 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07375 | { 07376 | expression_node<T>::ndb_t::collect(condition_ , node_delete_list); 07377 | expression_node<T>::ndb_t::collect(consequent_ , node_delete_list); 07378 | expression_node<T>::ndb_t::collect(alternative_ , node_delete_list); 07379 | } 07380 | 07381 | std::size_t node_depth() const exprtk_override 07382 | { 07383 | return expression_node<T>::ndb_t::compute_node_depth 07384 | (condition_, consequent_, alternative_); 07385 | } 07386 | 07387 | private: 07388 | 07389 | branch_t condition_; 07390 | branch_t consequent_; 07391 | branch_t alternative_; 07392 | }; 07393 | 07394 | template <typename T> 07395 | class cons_conditional_node exprtk_final : public expression_node<T> 07396 | { 07397 | public: 07398 | 07399 | // Consequent only conditional statement node 07400 | typedef expression_node<T>* expression_ptr; 07401 | typedef std::pair<expression_ptr,bool> branch_t; 07402 | 07403 | cons_conditional_node(expression_ptr condition, 07404 | expression_ptr consequent) 07405 | { 07406 | construct_branch_pair(condition_ , condition ); 07407 | construct_branch_pair(consequent_, consequent); 07408 | assert(valid()); 07409 | } 07410 | 07411 | inline T value() const exprtk_override 07412 | { 07413 | if (is_true(condition_)) 07414 | return consequent_.first->value(); 07415 | else 07416 | return std::numeric_limits<T>::quiet_NaN(); 07417 | } 07418 | 07419 | inline typename expression_node<T>::node_type type() const exprtk_override 07420 | { 07421 | return expression_node<T>::e_conditional; 07422 | } 07423 | 07424 | inline bool valid() const exprtk_override 07425 | { 07426 | return 07427 | condition_ .first && condition_ .first->valid() && 07428 | consequent_.first && consequent_.first->valid() ; 07429 | } 07430 | 07431 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07432 | { 07433 | expression_node<T>::ndb_t::collect(condition_ , node_delete_list); 07434 | expression_node<T>::ndb_t::collect(consequent_ , node_delete_list); 07435 | } 07436 | 07437 | std::size_t node_depth() const exprtk_override 07438 | { 07439 | return expression_node<T>::ndb_t:: 07440 | compute_node_depth(condition_, consequent_); 07441 | } 07442 | 07443 | private: 07444 | 07445 | branch_t condition_; 07446 | branch_t consequent_; 07447 | }; 07448 | 07449 | #ifndef exprtk_disable_break_continue 07450 | template <typename T> 07451 | class break_exception 07452 | { 07453 | public: 07454 | 07455 | explicit break_exception(const T& v) 07456 | : value(v) 07457 | {} 07458 | 07459 | T value; 07460 | }; 07461 | 07462 | class continue_exception {}; 07463 | 07464 | template <typename T> 07465 | class break_node exprtk_final : public expression_node<T> 07466 | { 07467 | public: 07468 | 07469 | typedef expression_node<T>* expression_ptr; 07470 | typedef std::pair<expression_ptr,bool> branch_t; 07471 | 07472 | explicit break_node(expression_ptr ret = expression_ptr(0)) 07473 | { 07474 | construct_branch_pair(return_, ret); 07475 | } 07476 | 07477 | inline T value() const exprtk_override 07478 | { 07479 | const T result = return_.first ? 07480 | return_.first->value() : 07481 | std::numeric_limits<T>::quiet_NaN(); 07482 | 07483 | throw break_exception<T>(result); 07484 | 07485 | #if !defined(_MSC_VER) && !defined(__NVCOMPILER) 07486 | return std::numeric_limits<T>::quiet_NaN(); 07487 | #endif 07488 | } 07489 | 07490 | inline typename expression_node<T>::node_type type() const exprtk_override 07491 | { 07492 | return expression_node<T>::e_break; 07493 | } 07494 | 07495 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07496 | { 07497 | expression_node<T>::ndb_t::collect(return_, node_delete_list); 07498 | } 07499 | 07500 | std::size_t node_depth() const exprtk_override 07501 | { 07502 | return expression_node<T>::ndb_t::compute_node_depth(return_); 07503 | } 07504 | 07505 | private: 07506 | 07507 | branch_t return_; 07508 | }; 07509 | 07510 | template <typename T> 07511 | class continue_node exprtk_final : public expression_node<T> 07512 | { 07513 | public: 07514 | 07515 | inline T value() const exprtk_override 07516 | { 07517 | throw continue_exception(); 07518 | #if !defined(_MSC_VER) && !defined(__NVCOMPILER) 07519 | return std::numeric_limits<T>::quiet_NaN(); 07520 | #endif 07521 | } 07522 | 07523 | inline typename expression_node<T>::node_type type() const exprtk_override 07524 | { 07525 | return expression_node<T>::e_break; 07526 | } 07527 | }; 07528 | #endif 07529 | 07530 | struct loop_runtime_checker 07531 | { 07532 | loop_runtime_checker(loop_runtime_check_ptr loop_runtime_check, 07533 | loop_runtime_check::loop_types lp_typ = loop_runtime_check::e_invalid) 07534 | : iteration_count_(0) 07535 | , loop_runtime_check_(loop_runtime_check) 07536 | , max_loop_iterations_(loop_runtime_check_->max_loop_iterations) 07537 | , loop_type_(lp_typ) 07538 | { 07539 | assert(loop_runtime_check_); 07540 | } 07541 | 07542 | inline void reset(const _uint64_t initial_value = 0) const 07543 | { 07544 | iteration_count_ = initial_value; 07545 | } 07546 | 07547 | inline bool check() const 07548 | { 07549 | assert(loop_runtime_check_); 07550 | 07551 | if ( 07552 | (++iteration_count_ <= max_loop_iterations_) && 07553 | loop_runtime_check_->check() 07554 | ) 07555 | { 07556 | return true; 07557 | } 07558 | 07559 | loop_runtime_check::violation_context ctxt; 07560 | ctxt.loop = loop_type_; 07561 | ctxt.violation = loop_runtime_check::e_iteration_count; 07562 | 07563 | loop_runtime_check_->handle_runtime_violation(ctxt); 07564 | 07565 | return false; 07566 | } 07567 | 07568 | bool valid() const 07569 | { 07570 | return 0 != loop_runtime_check_; 07571 | } 07572 | 07573 | mutable _uint64_t iteration_count_; 07574 | mutable loop_runtime_check_ptr loop_runtime_check_; 07575 | const details::_uint64_t& max_loop_iterations_; 07576 | loop_runtime_check::loop_types loop_type_; 07577 | }; 07578 | 07579 | template <typename T> 07580 | class while_loop_node : public expression_node<T> 07581 | { 07582 | public: 07583 | 07584 | typedef expression_node<T>* expression_ptr; 07585 | typedef std::pair<expression_ptr,bool> branch_t; 07586 | 07587 | while_loop_node(expression_ptr condition, 07588 | expression_ptr loop_body) 07589 | { 07590 | construct_branch_pair(condition_, condition); 07591 | construct_branch_pair(loop_body_, loop_body); 07592 | assert(valid()); 07593 | } 07594 | 07595 | inline T value() const exprtk_override 07596 | { 07597 | T result = T(0); 07598 | 07599 | while (is_true(condition_)) 07600 | { 07601 | result = loop_body_.first->value(); 07602 | } 07603 | 07604 | return result; 07605 | } 07606 | 07607 | inline typename expression_node<T>::node_type type() const exprtk_override 07608 | { 07609 | return expression_node<T>::e_while; 07610 | } 07611 | 07612 | inline bool valid() const exprtk_override 07613 | { 07614 | return 07615 | condition_.first && condition_.first->valid() && 07616 | loop_body_.first && loop_body_.first->valid() ; 07617 | } 07618 | 07619 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07620 | { 07621 | expression_node<T>::ndb_t::collect(condition_ , node_delete_list); 07622 | expression_node<T>::ndb_t::collect(loop_body_ , node_delete_list); 07623 | } 07624 | 07625 | std::size_t node_depth() const exprtk_override 07626 | { 07627 | return expression_node<T>::ndb_t::compute_node_depth(condition_, loop_body_); 07628 | } 07629 | 07630 | protected: 07631 | 07632 | branch_t condition_; 07633 | branch_t loop_body_; 07634 | }; 07635 | 07636 | template <typename T> 07637 | class while_loop_rtc_node exprtk_final 07638 | : public while_loop_node<T> 07639 | , public loop_runtime_checker 07640 | { 07641 | public: 07642 | 07643 | typedef while_loop_node<T> parent_t; 07644 | typedef expression_node<T>* expression_ptr; 07645 | 07646 | while_loop_rtc_node(expression_ptr condition, 07647 | expression_ptr loop_body, 07648 | loop_runtime_check_ptr loop_rt_chk) 07649 | : parent_t(condition, loop_body) 07650 | , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_while_loop) 07651 | { 07652 | assert(valid()); 07653 | } 07654 | 07655 | inline T value() const exprtk_override 07656 | { 07657 | 07658 | T result = T(0); 07659 | 07660 | loop_runtime_checker::reset(); 07661 | 07662 | while (is_true(parent_t::condition_) && loop_runtime_checker::check()) 07663 | { 07664 | result = parent_t::loop_body_.first->value(); 07665 | } 07666 | 07667 | return result; 07668 | } 07669 | 07670 | using parent_t::valid; 07671 | 07672 | bool valid() const exprtk_override exprtk_final 07673 | { 07674 | return parent_t::valid() && 07675 | loop_runtime_checker::valid(); 07676 | } 07677 | }; 07678 | 07679 | template <typename T> 07680 | class repeat_until_loop_node : public expression_node<T> 07681 | { 07682 | public: 07683 | 07684 | typedef expression_node<T>* expression_ptr; 07685 | typedef std::pair<expression_ptr,bool> branch_t; 07686 | 07687 | repeat_until_loop_node(expression_ptr condition, 07688 | expression_ptr loop_body) 07689 | { 07690 | construct_branch_pair(condition_, condition); 07691 | construct_branch_pair(loop_body_, loop_body); 07692 | assert(valid()); 07693 | } 07694 | 07695 | inline T value() const exprtk_override 07696 | { 07697 | T result = T(0); 07698 | 07699 | do 07700 | { 07701 | result = loop_body_.first->value(); 07702 | } 07703 | while (is_false(condition_.first)); 07704 | 07705 | return result; 07706 | } 07707 | 07708 | inline typename expression_node<T>::node_type type() const exprtk_override 07709 | { 07710 | return expression_node<T>::e_repeat; 07711 | } 07712 | 07713 | inline bool valid() const exprtk_override 07714 | { 07715 | return 07716 | condition_.first && condition_.first->valid() && 07717 | loop_body_.first && loop_body_.first->valid() ; 07718 | } 07719 | 07720 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07721 | { 07722 | expression_node<T>::ndb_t::collect(condition_ , node_delete_list); 07723 | expression_node<T>::ndb_t::collect(loop_body_ , node_delete_list); 07724 | } 07725 | 07726 | std::size_t node_depth() const exprtk_override 07727 | { 07728 | return expression_node<T>::ndb_t::compute_node_depth(condition_, loop_body_); 07729 | } 07730 | 07731 | protected: 07732 | 07733 | branch_t condition_; 07734 | branch_t loop_body_; 07735 | }; 07736 | 07737 | template <typename T> 07738 | class repeat_until_loop_rtc_node exprtk_final 07739 | : public repeat_until_loop_node<T> 07740 | , public loop_runtime_checker 07741 | { 07742 | public: 07743 | 07744 | typedef repeat_until_loop_node<T> parent_t; 07745 | typedef expression_node<T>* expression_ptr; 07746 | 07747 | repeat_until_loop_rtc_node(expression_ptr condition, 07748 | expression_ptr loop_body, 07749 | loop_runtime_check_ptr loop_rt_chk) 07750 | : parent_t(condition, loop_body) 07751 | , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_repeat_until_loop) 07752 | { 07753 | assert(valid()); 07754 | } 07755 | 07756 | inline T value() const exprtk_override 07757 | { 07758 | T result = T(0); 07759 | 07760 | loop_runtime_checker::reset(1); 07761 | 07762 | do 07763 | { 07764 | result = parent_t::loop_body_.first->value(); 07765 | } 07766 | while (is_false(parent_t::condition_.first) && loop_runtime_checker::check()); 07767 | 07768 | return result; 07769 | } 07770 | 07771 | using parent_t::valid; 07772 | 07773 | inline bool valid() const exprtk_override exprtk_final 07774 | { 07775 | return parent_t::valid() && 07776 | loop_runtime_checker::valid(); 07777 | } 07778 | }; 07779 | 07780 | template <typename T> 07781 | class for_loop_node : public expression_node<T> 07782 | { 07783 | public: 07784 | 07785 | typedef expression_node<T>* expression_ptr; 07786 | typedef std::pair<expression_ptr,bool> branch_t; 07787 | 07788 | for_loop_node(expression_ptr initialiser, 07789 | expression_ptr condition, 07790 | expression_ptr incrementor, 07791 | expression_ptr loop_body) 07792 | { 07793 | construct_branch_pair(initialiser_, initialiser); 07794 | construct_branch_pair(condition_ , condition ); 07795 | construct_branch_pair(incrementor_, incrementor); 07796 | construct_branch_pair(loop_body_ , loop_body ); 07797 | assert(valid()); 07798 | } 07799 | 07800 | inline T value() const exprtk_override 07801 | { 07802 | T result = T(0); 07803 | 07804 | if (initialiser_.first) 07805 | initialiser_.first->value(); 07806 | 07807 | if (incrementor_.first) 07808 | { 07809 | while (is_true(condition_)) 07810 | { 07811 | result = loop_body_.first->value(); 07812 | incrementor_.first->value(); 07813 | } 07814 | } 07815 | else 07816 | { 07817 | while (is_true(condition_)) 07818 | { 07819 | result = loop_body_.first->value(); 07820 | } 07821 | } 07822 | 07823 | return result; 07824 | } 07825 | 07826 | inline typename expression_node<T>::node_type type() const exprtk_override 07827 | { 07828 | return expression_node<T>::e_for; 07829 | } 07830 | 07831 | inline bool valid() const exprtk_override 07832 | { 07833 | return condition_.first && loop_body_.first; 07834 | } 07835 | 07836 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07837 | { 07838 | expression_node<T>::ndb_t::collect(initialiser_ , node_delete_list); 07839 | expression_node<T>::ndb_t::collect(condition_ , node_delete_list); 07840 | expression_node<T>::ndb_t::collect(incrementor_ , node_delete_list); 07841 | expression_node<T>::ndb_t::collect(loop_body_ , node_delete_list); 07842 | } 07843 | 07844 | std::size_t node_depth() const exprtk_override 07845 | { 07846 | return expression_node<T>::ndb_t::compute_node_depth 07847 | (initialiser_, condition_, incrementor_, loop_body_); 07848 | } 07849 | 07850 | protected: 07851 | 07852 | branch_t initialiser_; 07853 | branch_t condition_ ; 07854 | branch_t incrementor_; 07855 | branch_t loop_body_ ; 07856 | }; 07857 | 07858 | template <typename T> 07859 | class for_loop_rtc_node exprtk_final 07860 | : public for_loop_node<T> 07861 | , public loop_runtime_checker 07862 | { 07863 | public: 07864 | 07865 | typedef for_loop_node<T> parent_t; 07866 | typedef expression_node<T>* expression_ptr; 07867 | 07868 | for_loop_rtc_node(expression_ptr initialiser, 07869 | expression_ptr condition, 07870 | expression_ptr incrementor, 07871 | expression_ptr loop_body, 07872 | loop_runtime_check_ptr loop_rt_chk) 07873 | : parent_t(initialiser, condition, incrementor, loop_body) 07874 | , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_for_loop) 07875 | { 07876 | assert(valid()); 07877 | } 07878 | 07879 | inline T value() const exprtk_override 07880 | { 07881 | T result = T(0); 07882 | 07883 | loop_runtime_checker::reset(); 07884 | 07885 | if (parent_t::initialiser_.first) 07886 | parent_t::initialiser_.first->value(); 07887 | 07888 | if (parent_t::incrementor_.first) 07889 | { 07890 | while (is_true(parent_t::condition_) && loop_runtime_checker::check()) 07891 | { 07892 | result = parent_t::loop_body_.first->value(); 07893 | parent_t::incrementor_.first->value(); 07894 | } 07895 | } 07896 | else 07897 | { 07898 | while (is_true(parent_t::condition_) && loop_runtime_checker::check()) 07899 | { 07900 | result = parent_t::loop_body_.first->value(); 07901 | } 07902 | } 07903 | 07904 | return result; 07905 | } 07906 | 07907 | using parent_t::valid; 07908 | 07909 | inline bool valid() const exprtk_override exprtk_final 07910 | { 07911 | return parent_t::valid() && 07912 | loop_runtime_checker::valid(); 07913 | } 07914 | }; 07915 | 07916 | #ifndef exprtk_disable_break_continue 07917 | template <typename T> 07918 | class while_loop_bc_node : public while_loop_node<T> 07919 | { 07920 | public: 07921 | 07922 | typedef while_loop_node<T> parent_t; 07923 | typedef expression_node<T>* expression_ptr; 07924 | 07925 | while_loop_bc_node(expression_ptr condition, 07926 | expression_ptr loop_body) 07927 | : parent_t(condition, loop_body) 07928 | { 07929 | assert(parent_t::valid()); 07930 | } 07931 | 07932 | inline T value() const exprtk_override 07933 | { 07934 | T result = T(0); 07935 | 07936 | while (is_true(parent_t::condition_)) 07937 | { 07938 | try 07939 | { 07940 | result = parent_t::loop_body_.first->value(); 07941 | } 07942 | catch(const break_exception<T>& e) 07943 | { 07944 | return e.value; 07945 | } 07946 | catch(const continue_exception&) 07947 | {} 07948 | } 07949 | 07950 | return result; 07951 | } 07952 | }; 07953 | 07954 | template <typename T> 07955 | class while_loop_bc_rtc_node exprtk_final 07956 | : public while_loop_bc_node<T> 07957 | , public loop_runtime_checker 07958 | { 07959 | public: 07960 | 07961 | typedef while_loop_bc_node<T> parent_t; 07962 | typedef expression_node<T>* expression_ptr; 07963 | 07964 | while_loop_bc_rtc_node(expression_ptr condition, 07965 | expression_ptr loop_body, 07966 | loop_runtime_check_ptr loop_rt_chk) 07967 | : parent_t(condition, loop_body) 07968 | , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_while_loop) 07969 | { 07970 | assert(valid()); 07971 | } 07972 | 07973 | inline T value() const exprtk_override 07974 | { 07975 | T result = T(0); 07976 | 07977 | loop_runtime_checker::reset(); 07978 | 07979 | while (is_true(parent_t::condition_) && loop_runtime_checker::check()) 07980 | { 07981 | try 07982 | { 07983 | result = parent_t::loop_body_.first->value(); 07984 | } 07985 | catch(const break_exception<T>& e) 07986 | { 07987 | return e.value; 07988 | } 07989 | catch(const continue_exception&) 07990 | {} 07991 | } 07992 | 07993 | return result; 07994 | } 07995 | 07996 | using parent_t::valid; 07997 | 07998 | inline bool valid() const exprtk_override exprtk_final 07999 | { 08000 | return parent_t::valid() && 08001 | loop_runtime_checker::valid(); 08002 | } 08003 | }; 08004 | 08005 | template <typename T> 08006 | class repeat_until_loop_bc_node : public repeat_until_loop_node<T> 08007 | { 08008 | public: 08009 | 08010 | typedef repeat_until_loop_node<T> parent_t; 08011 | typedef expression_node<T>* expression_ptr; 08012 | 08013 | repeat_until_loop_bc_node(expression_ptr condition, 08014 | expression_ptr loop_body) 08015 | : parent_t(condition, loop_body) 08016 | { 08017 | assert(parent_t::valid()); 08018 | } 08019 | 08020 | inline T value() const exprtk_override 08021 | { 08022 | T result = T(0); 08023 | 08024 | do 08025 | { 08026 | try 08027 | { 08028 | result = parent_t::loop_body_.first->value(); 08029 | } 08030 | catch(const break_exception<T>& e) 08031 | { 08032 | return e.value; 08033 | } 08034 | catch(const continue_exception&) 08035 | {} 08036 | } 08037 | while (is_false(parent_t::condition_.first)); 08038 | 08039 | return result; 08040 | } 08041 | }; 08042 | 08043 | template <typename T> 08044 | class repeat_until_loop_bc_rtc_node exprtk_final 08045 | : public repeat_until_loop_bc_node<T> 08046 | , public loop_runtime_checker 08047 | { 08048 | public: 08049 | 08050 | typedef repeat_until_loop_bc_node<T> parent_t; 08051 | typedef expression_node<T>* expression_ptr; 08052 | 08053 | repeat_until_loop_bc_rtc_node(expression_ptr condition, 08054 | expression_ptr loop_body, 08055 | loop_runtime_check_ptr loop_rt_chk) 08056 | : parent_t(condition, loop_body) 08057 | , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_repeat_until_loop) 08058 | { 08059 | assert(valid()); 08060 | } 08061 | 08062 | inline T value() const exprtk_override 08063 | { 08064 | T result = T(0); 08065 | 08066 | loop_runtime_checker::reset(); 08067 | 08068 | do 08069 | { 08070 | try 08071 | { 08072 | result = parent_t::loop_body_.first->value(); 08073 | } 08074 | catch(const break_exception<T>& e) 08075 | { 08076 | return e.value; 08077 | } 08078 | catch(const continue_exception&) 08079 | {} 08080 | } 08081 | while (is_false(parent_t::condition_.first) && loop_runtime_checker::check()); 08082 | 08083 | return result; 08084 | } 08085 | 08086 | using parent_t::valid; 08087 | 08088 | inline bool valid() const exprtk_override exprtk_final 08089 | { 08090 | return parent_t::valid() && 08091 | loop_runtime_checker::valid(); 08092 | } 08093 | }; 08094 | 08095 | template <typename T> 08096 | class for_loop_bc_node : public for_loop_node<T> 08097 | { 08098 | public: 08099 | 08100 | typedef for_loop_node<T> parent_t; 08101 | typedef expression_node<T>* expression_ptr; 08102 | 08103 | for_loop_bc_node(expression_ptr initialiser, 08104 | expression_ptr condition, 08105 | expression_ptr incrementor, 08106 | expression_ptr loop_body) 08107 | : parent_t(initialiser, condition, incrementor, loop_body) 08108 | { 08109 | assert(parent_t::valid()); 08110 | } 08111 | 08112 | inline T value() const exprtk_override 08113 | { 08114 | T result = T(0); 08115 | 08116 | if (parent_t::initialiser_.first) 08117 | parent_t::initialiser_.first->value(); 08118 | 08119 | if (parent_t::incrementor_.first) 08120 | { 08121 | while (is_true(parent_t::condition_)) 08122 | { 08123 | try 08124 | { 08125 | result = parent_t::loop_body_.first->value(); 08126 | } 08127 | catch(const break_exception<T>& e) 08128 | { 08129 | return e.value; 08130 | } 08131 | catch(const continue_exception&) 08132 | {} 08133 | 08134 | parent_t::incrementor_.first->value(); 08135 | } 08136 | } 08137 | else 08138 | { 08139 | while (is_true(parent_t::condition_)) 08140 | { 08141 | try 08142 | { 08143 | result = parent_t::loop_body_.first->value(); 08144 | } 08145 | catch(const break_exception<T>& e) 08146 | { 08147 | return e.value; 08148 | } 08149 | catch(const continue_exception&) 08150 | {} 08151 | } 08152 | } 08153 | 08154 | return result; 08155 | } 08156 | }; 08157 | 08158 | template <typename T> 08159 | class for_loop_bc_rtc_node exprtk_final 08160 | : public for_loop_bc_node<T> 08161 | , public loop_runtime_checker 08162 | { 08163 | public: 08164 | 08165 | typedef for_loop_bc_node<T> parent_t; 08166 | typedef expression_node<T>* expression_ptr; 08167 | 08168 | for_loop_bc_rtc_node(expression_ptr initialiser, 08169 | expression_ptr condition, 08170 | expression_ptr incrementor, 08171 | expression_ptr loop_body, 08172 | loop_runtime_check_ptr loop_rt_chk) 08173 | : parent_t(initialiser, condition, incrementor, loop_body) 08174 | , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_for_loop) 08175 | { 08176 | assert(valid()); 08177 | } 08178 | 08179 | inline T value() const exprtk_override 08180 | { 08181 | T result = T(0); 08182 | 08183 | loop_runtime_checker::reset(); 08184 | 08185 | if (parent_t::initialiser_.first) 08186 | parent_t::initialiser_.first->value(); 08187 | 08188 | if (parent_t::incrementor_.first) 08189 | { 08190 | while (is_true(parent_t::condition_) && loop_runtime_checker::check()) 08191 | { 08192 | try 08193 | { 08194 | result = parent_t::loop_body_.first->value(); 08195 | } 08196 | catch(const break_exception<T>& e) 08197 | { 08198 | return e.value; 08199 | } 08200 | catch(const continue_exception&) 08201 | {} 08202 | 08203 | parent_t::incrementor_.first->value(); 08204 | } 08205 | } 08206 | else 08207 | { 08208 | while (is_true(parent_t::condition_) && loop_runtime_checker::check()) 08209 | { 08210 | try 08211 | { 08212 | result = parent_t::loop_body_.first->value(); 08213 | } 08214 | catch(const break_exception<T>& e) 08215 | { 08216 | return e.value; 08217 | } 08218 | catch(const continue_exception&) 08219 | {} 08220 | } 08221 | } 08222 | 08223 | return result; 08224 | } 08225 | 08226 | using parent_t::valid; 08227 | 08228 | inline bool valid() const exprtk_override exprtk_final 08229 | { 08230 | return parent_t::valid() && 08231 | loop_runtime_checker::valid(); 08232 | } 08233 | }; 08234 | #endif 08235 | 08236 | template <typename T> 08237 | class switch_node : public expression_node<T> 08238 | { 08239 | public: 08240 | 08241 | typedef expression_node<T>* expression_ptr; 08242 | typedef std::pair<expression_ptr,bool> branch_t; 08243 | 08244 | template <typename Allocator, 08245 | template <typename, typename> class Sequence> 08246 | explicit switch_node(const Sequence<expression_ptr,Allocator>& arg_list) 08247 | { 08248 | if (1 != (arg_list.size() & 1)) 08249 | return; 08250 | 08251 | arg_list_.resize(arg_list.size()); 08252 | 08253 | for (std::size_t i = 0; i < arg_list.size(); ++i) 08254 | { 08255 | if (arg_list[i] && arg_list[i]->valid()) 08256 | { 08257 | construct_branch_pair(arg_list_[i], arg_list[i]); 08258 | } 08259 | else 08260 | { 08261 | arg_list_.clear(); 08262 | return; 08263 | } 08264 | } 08265 | 08266 | assert(valid()); 08267 | } 08268 | 08269 | inline T value() const exprtk_override 08270 | { 08271 | const std::size_t upper_bound = (arg_list_.size() - 1); 08272 | 08273 | for (std::size_t i = 0; i < upper_bound; i += 2) 08274 | { 08275 | expression_ptr condition = arg_list_[i ].first; 08276 | expression_ptr consequent = arg_list_[i + 1].first; 08277 | 08278 | if (is_true(condition)) 08279 | { 08280 | return consequent->value(); 08281 | } 08282 | } 08283 | 08284 | return arg_list_[upper_bound].first->value(); 08285 | } 08286 | 08287 | inline typename expression_node<T>::node_type type() const exprtk_override exprtk_final 08288 | { 08289 | return expression_node<T>::e_switch; 08290 | } 08291 | 08292 | inline bool valid() const exprtk_override 08293 | { 08294 | return !arg_list_.empty(); 08295 | } 08296 | 08297 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 08298 | { 08299 | expression_node<T>::ndb_t::collect(arg_list_, node_delete_list); 08300 | } 08301 | 08302 | std::size_t node_depth() const exprtk_override exprtk_final 08303 | { 08304 | return expression_node<T>::ndb_t::compute_node_depth(arg_list_); 08305 | } 08306 | 08307 | protected: 08308 | 08309 | std::vector<branch_t> arg_list_; 08310 | }; 08311 | 08312 | template <typename T, typename Switch_N> 08313 | class switch_n_node exprtk_final : public switch_node<T> 08314 | { 08315 | public: 08316 | 08317 | typedef expression_node<T>* expression_ptr; 08318 | 08319 | template <typename Allocator, 08320 | template <typename, typename> class Sequence> 08321 | explicit switch_n_node(const Sequence<expression_ptr,Allocator>& arg_list) 08322 | : switch_node<T>(arg_list) 08323 | {} 08324 | 08325 | inline T value() const exprtk_override 08326 | { 08327 | return Switch_N::process(switch_node<T>::arg_list_); 08328 | } 08329 | }; 08330 | 08331 | template <typename T> 08332 | class multi_switch_node exprtk_final : public expression_node<T> 08333 | { 08334 | public: 08335 | 08336 | typedef expression_node<T>* expression_ptr; 08337 | typedef std::pair<expression_ptr,bool> branch_t; 08338 | 08339 | template <typename Allocator, 08340 | template <typename, typename> class Sequence> 08341 | explicit multi_switch_node(const Sequence<expression_ptr,Allocator>& arg_list) 08342 | { 08343 | if (0 != (arg_list.size() & 1)) 08344 | return; 08345 | 08346 | arg_list_.resize(arg_list.size()); 08347 | 08348 | for (std::size_t i = 0; i < arg_list.size(); ++i) 08349 | { 08350 | if (arg_list[i] && arg_list[i]->valid()) 08351 | { 08352 | construct_branch_pair(arg_list_[i], arg_list[i]); 08353 | } 08354 | else 08355 | { 08356 | arg_list_.clear(); 08357 | return; 08358 | } 08359 | } 08360 | 08361 | assert(valid()); 08362 | } 08363 | 08364 | inline T value() const exprtk_override 08365 | { 08366 | const std::size_t upper_bound = (arg_list_.size() - 1); 08367 | 08368 | T result = T(0); 08369 | 08370 | for (std::size_t i = 0; i < upper_bound; i += 2) 08371 | { 08372 | expression_ptr condition = arg_list_[i ].first; 08373 | expression_ptr consequent = arg_list_[i + 1].first; 08374 | 08375 | if (is_true(condition)) 08376 | { 08377 | result = consequent->value(); 08378 | } 08379 | } 08380 | 08381 | return result; 08382 | } 08383 | 08384 | inline typename expression_node<T>::node_type type() const exprtk_override 08385 | { 08386 | return expression_node<T>::e_mswitch; 08387 | } 08388 | 08389 | inline bool valid() const exprtk_override 08390 | { 08391 | return !arg_list_.empty() && (0 == (arg_list_.size() % 2)); 08392 | } 08393 | 08394 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 08395 | { 08396 | expression_node<T>::ndb_t::collect(arg_list_, node_delete_list); 08397 | } 08398 | 08399 | std::size_t node_depth() const exprtk_override exprtk_final 08400 | { 08401 | return expression_node<T>::ndb_t::compute_node_depth(arg_list_); 08402 | } 08403 | 08404 | private: 08405 | 08406 | std::vector<branch_t> arg_list_; 08407 | }; 08408 | 08409 | template <typename T> 08410 | class ivariable 08411 | { 08412 | public: 08413 | 08414 | virtual ~ivariable() 08415 | {} 08416 | 08417 | virtual T& ref() = 0; 08418 | virtual const T& ref() const = 0; 08419 | }; 08420 | 08421 | template <typename T> 08422 | class variable_node exprtk_final 08423 | : public expression_node<T> 08424 | , public ivariable <T> 08425 | { 08426 | public: 08427 | 08428 | static T null_value; 08429 | 08430 | explicit variable_node() 08431 | : value_(&null_value) 08432 | {} 08433 | 08434 | explicit variable_node(T& v) 08435 | : value_(&v) 08436 | {} 08437 | 08438 | inline bool operator <(const variable_node<T>& v) const 08439 | { 08440 | return this < (&v); 08441 | } 08442 | 08443 | inline T value() const exprtk_override 08444 | { 08445 | return (*value_); 08446 | } 08447 | 08448 | inline T& ref() exprtk_override 08449 | { 08450 | return (*value_); 08451 | } 08452 | 08453 | inline const T& ref() const exprtk_override 08454 | { 08455 | return (*value_); 08456 | } 08457 | 08458 | inline typename expression_node<T>::node_type type() const exprtk_override 08459 | { 08460 | return expression_node<T>::e_variable; 08461 | } 08462 | 08463 | private: 08464 | 08465 | T* value_; 08466 | }; 08467 | 08468 | template <typename T> 08469 | T variable_node<T>::null_value = T(std::numeric_limits<T>::quiet_NaN()); 08470 | 08471 | template <typename T> 08472 | struct range_pack 08473 | { 08474 | typedef expression_node<T>* expression_node_ptr; 08475 | typedef std::pair<std::size_t,std::size_t> cached_range_t; 08476 | 08477 | range_pack() 08478 | : n0_e (std::make_pair(false,expression_node_ptr(0))) 08479 | , n1_e (std::make_pair(false,expression_node_ptr(0))) 08480 | , n0_c (std::make_pair(false,0)) 08481 | , n1_c (std::make_pair(false,0)) 08482 | , cache(std::make_pair(0,0)) 08483 | {} 08484 | 08485 | void clear() 08486 | { 08487 | n0_e = std::make_pair(false,expression_node_ptr(0)); 08488 | n1_e = std::make_pair(false,expression_node_ptr(0)); 08489 | n0_c = std::make_pair(false,0); 08490 | n1_c = std::make_pair(false,0); 08491 | cache = std::make_pair(0,0); 08492 | } 08493 | 08494 | void free() 08495 | { 08496 | if (n0_e.first && n0_e.second) 08497 | { 08498 | n0_e.first = false; 08499 | 08500 | if ( 08501 | !is_variable_node(n0_e.second) && 08502 | !is_string_node (n0_e.second) 08503 | ) 08504 | { 08505 | destroy_node(n0_e.second); 08506 | } 08507 | } 08508 | 08509 | if (n1_e.first && n1_e.second) 08510 | { 08511 | n1_e.first = false; 08512 | 08513 | if ( 08514 | !is_variable_node(n1_e.second) && 08515 | !is_string_node (n1_e.second) 08516 | ) 08517 | { 08518 | destroy_node(n1_e.second); 08519 | } 08520 | } 08521 | } 08522 | 08523 | bool const_range() const 08524 | { 08525 | return ( n0_c.first && n1_c.first) && 08526 | (!n0_e.first && !n1_e.first); 08527 | } 08528 | 08529 | bool var_range() const 08530 | { 08531 | return ( n0_e.first && n1_e.first) && 08532 | (!n0_c.first && !n1_c.first); 08533 | } 08534 | 08535 | bool operator() (std::size_t& r0, std::size_t& r1, 08536 | const std::size_t& size = std::numeric_limits<std::size_t>::max()) const 08537 | { 08538 | if (n0_c.first) 08539 | r0 = n0_c.second; 08540 | else if (n0_e.first) 08541 | { 08542 | r0 = static_cast<std::size_t>(details::numeric::to_int64(n0_e.second->value())); 08543 | } 08544 | else 08545 | return false; 08546 | 08547 | if (n1_c.first) 08548 | r1 = n1_c.second; 08549 | else if (n1_e.first) 08550 | { 08551 | r1 = static_cast<std::size_t>(details::numeric::to_int64(n1_e.second->value())); 08552 | } 08553 | else 08554 | return false; 08555 | 08556 | if ( 08557 | (std::numeric_limits<std::size_t>::max() != size) && 08558 | (std::numeric_limits<std::size_t>::max() == r1 ) 08559 | ) 08560 | { 08561 | r1 = size; 08562 | } 08563 | 08564 | cache.first = r0; 08565 | cache.second = r1; 08566 | 08567 | #ifndef exprtk_enable_range_runtime_checks 08568 | return (r0 <= r1); 08569 | #else 08570 | return range_runtime_check(r0, r1, size); 08571 | #endif 08572 | } 08573 | 08574 | inline std::size_t const_size() const 08575 | { 08576 | return (n1_c.second - n0_c.second); 08577 | } 08578 | 08579 | inline std::size_t cache_size() const 08580 | { 08581 | return (cache.second - cache.first); 08582 | } 08583 | 08584 | std::pair<bool,expression_node_ptr> n0_e; 08585 | std::pair<bool,expression_node_ptr> n1_e; 08586 | std::pair<bool,std::size_t > n0_c; 08587 | std::pair<bool,std::size_t > n1_c; 08588 | mutable cached_range_t cache; 08589 | 08590 | #ifdef exprtk_enable_range_runtime_checks 08591 | bool range_runtime_check(const std::size_t r0, 08592 | const std::size_t r1, 08593 | const std::size_t size) const 08594 | { 08595 | if (r0 > size) 08596 | { 08597 | throw std::runtime_error("range error: (r0 < 0) || (r0 > size)"); 08598 | #if !defined(_MSC_VER) && !defined(__NVCOMPILER) 08599 | return false; 08600 | #endif 08601 | } 08602 | 08603 | if (r1 > size) 08604 | { 08605 | throw std::runtime_error("range error: (r1 < 0) || (r1 > size)"); 08606 | #if !defined(_MSC_VER) && !defined(__NVCOMPILER) 08607 | return false; 08608 | #endif 08609 | } 08610 | 08611 | return (r0 <= r1); 08612 | } 08613 | #endif 08614 | }; 08615 | 08616 | template <typename T> 08617 | class string_base_node; 08618 | 08619 | template <typename T> 08620 | struct range_data_type 08621 | { 08622 | typedef range_pack<T> range_t; 08623 | typedef string_base_node<T>* strbase_ptr_t; 08624 | 08625 | range_data_type() 08626 | : range(0) 08627 | , data (0) 08628 | , size (0) 08629 | , type_size(0) 08630 | , str_node (0) 08631 | {} 08632 | 08633 | range_t* range; 08634 | void* data; 08635 | std::size_t size; 08636 | std::size_t type_size; 08637 | strbase_ptr_t str_node; 08638 | }; 08639 | 08640 | template <typename T> class vector_node; 08641 | 08642 | template <typename T> 08643 | class vector_interface 08644 | { 08645 | public: 08646 | 08647 | typedef vector_node<T>* vector_node_ptr; 08648 | typedef vec_data_store<T> vds_t; 08649 | 08650 | virtual ~vector_interface() 08651 | {} 08652 | 08653 | virtual std::size_t size () const = 0; 08654 | 08655 | virtual std::size_t base_size() const = 0; 08656 | 08657 | virtual vector_node_ptr vec () const = 0; 08658 | 08659 | virtual vector_node_ptr vec () = 0; 08660 | 08661 | virtual vds_t& vds () = 0; 08662 | 08663 | virtual const vds_t& vds () const = 0; 08664 | 08665 | virtual bool side_effect () const { return false; } 08666 | }; 08667 | 08668 | template <typename T> 08669 | class vector_node exprtk_final 08670 | : public expression_node <T> 08671 | , public vector_interface<T> 08672 | { 08673 | public: 08674 | 08675 | typedef expression_node<T>* expression_ptr; 08676 | typedef vector_holder<T> vector_holder_t; 08677 | typedef vector_node<T>* vector_node_ptr; 08678 | typedef vec_data_store<T> vds_t; 08679 | 08680 | explicit vector_node(vector_holder_t* vh) 08681 | : vector_holder_(vh) 08682 | , vds_((*vector_holder_).size(),(*vector_holder_)[0]) 08683 | { 08684 | vector_holder_->set_ref(&vds_.ref()); 08685 | } 08686 | 08687 | vector_node(const vds_t& vds, vector_holder_t* vh) 08688 | : vector_holder_(vh) 08689 | , vds_(vds) 08690 | {} 08691 | 08692 | ~vector_node() exprtk_override 08693 | { 08694 | assert(valid()); 08695 | vector_holder_->remove_ref(&vds_.ref()); 08696 | } 08697 | 08698 | inline T value() const exprtk_override 08699 | { 08700 | return vds().data()[0]; 08701 | } 08702 | 08703 | vector_node_ptr vec() const exprtk_override 08704 | { 08705 | return const_cast<vector_node_ptr>(this); 08706 | } 08707 | 08708 | vector_node_ptr vec() exprtk_override 08709 | { 08710 | return this; 08711 | } 08712 | 08713 | inline typename expression_node<T>::node_type type() const exprtk_override 08714 | { 08715 | return expression_node<T>::e_vector; 08716 | } 08717 | 08718 | inline bool valid() const exprtk_override 08719 | { 08720 | return vector_holder_; 08721 | } 08722 | 08723 | std::size_t size() const exprtk_override 08724 | { 08725 | return vec_holder().size(); 08726 | } 08727 | 08728 | std::size_t base_size() const exprtk_override 08729 | { 08730 | return vec_holder().base_size(); 08731 | } 08732 | 08733 | vds_t& vds() exprtk_override 08734 | { 08735 | return vds_; 08736 | } 08737 | 08738 | const vds_t& vds() const exprtk_override 08739 | { 08740 | return vds_; 08741 | } 08742 | 08743 | inline vector_holder_t& vec_holder() 08744 | { 08745 | return (*vector_holder_); 08746 | } 08747 | 08748 | inline vector_holder_t& vec_holder() const 08749 | { 08750 | return (*vector_holder_); 08751 | } 08752 | 08753 | private: 08754 | 08755 | vector_holder_t* vector_holder_; 08756 | vds_t vds_; 08757 | }; 08758 | 08759 | template <typename T> 08760 | class vector_size_node exprtk_final 08761 | : public expression_node <T> 08762 | { 08763 | public: 08764 | 08765 | typedef expression_node<T>* expression_ptr; 08766 | typedef vector_holder<T> vector_holder_t; 08767 | 08768 | explicit vector_size_node(vector_holder_t* vh) 08769 | : vector_holder_(vh) 08770 | {} 08771 | 08772 | ~vector_size_node() exprtk_override 08773 | { 08774 | assert(valid()); 08775 | } 08776 | 08777 | inline T value() const exprtk_override 08778 | { 08779 | assert(vector_holder_); 08780 | return static_cast<T>(vector_holder_->size()); 08781 | } 08782 | 08783 | inline typename expression_node<T>::node_type type() const exprtk_override 08784 | { 08785 | return expression_node<T>::e_vecsize; 08786 | } 08787 | 08788 | inline bool valid() const exprtk_override 08789 | { 08790 | return vector_holder_ && vector_holder_->size(); 08791 | } 08792 | 08793 | inline vector_holder_t* vec_holder() 08794 | { 08795 | return vector_holder_; 08796 | } 08797 | 08798 | private: 08799 | 08800 | vector_holder_t* vector_holder_; 08801 | }; 08802 | 08803 | template <typename T> 08804 | class vector_elem_node exprtk_final 08805 | : public expression_node<T> 08806 | , public ivariable <T> 08807 | { 08808 | public: 08809 | 08810 | typedef expression_node<T>* expression_ptr; 08811 | typedef vector_holder<T> vector_holder_t; 08812 | typedef vector_holder_t* vector_holder_ptr; 08813 | typedef std::pair<expression_ptr,bool> branch_t; 08814 | 08815 | vector_elem_node(expression_ptr vec_node, 08816 | expression_ptr index, 08817 | vector_holder_ptr vec_holder) 08818 | : vector_holder_(vec_holder) 08819 | , vector_base_((*vec_holder)[0]) 08820 | { 08821 | construct_branch_pair(vector_node_, vec_node); 08822 | construct_branch_pair(index_ , index ); 08823 | assert(valid()); 08824 | } 08825 | 08826 | inline T value() const exprtk_override 08827 | { 08828 | return *access_vector(); 08829 | } 08830 | 08831 | inline T& ref() exprtk_override 08832 | { 08833 | return *access_vector(); 08834 | } 08835 | 08836 | inline const T& ref() const exprtk_override 08837 | { 08838 | return *access_vector(); 08839 | } 08840 | 08841 | inline typename expression_node<T>::node_type type() const exprtk_override 08842 | { 08843 | return expression_node<T>::e_vecelem; 08844 | } 08845 | 08846 | inline bool valid() const exprtk_override 08847 | { 08848 | return 08849 | vector_holder_ && 08850 | index_.first && 08851 | vector_node_.first && 08852 | index_.first->valid() && 08853 | vector_node_.first->valid(); 08854 | } 08855 | 08856 | inline vector_holder_t& vec_holder() 08857 | { 08858 | return (*vector_holder_); 08859 | } 08860 | 08861 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 08862 | { 08863 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 08864 | expression_node<T>::ndb_t::collect(index_ , node_delete_list); 08865 | } 08866 | 08867 | std::size_t node_depth() const exprtk_override 08868 | { 08869 | return expression_node<T>::ndb_t::compute_node_depth 08870 | (vector_node_, index_); 08871 | } 08872 | 08873 | private: 08874 | 08875 | inline T* access_vector() const 08876 | { 08877 | vector_node_.first->value(); 08878 | return (vector_base_ + details::numeric::to_uint64(index_.first->value())); 08879 | } 08880 | 08881 | vector_holder_ptr vector_holder_; 08882 | T* vector_base_; 08883 | branch_t vector_node_; 08884 | branch_t index_; 08885 | }; 08886 | 08887 | template <typename T> 08888 | class vector_celem_node exprtk_final 08889 | : public expression_node<T> 08890 | , public ivariable <T> 08891 | { 08892 | public: 08893 | 08894 | typedef expression_node<T>* expression_ptr; 08895 | typedef vector_holder<T> vector_holder_t; 08896 | typedef vector_holder_t* vector_holder_ptr; 08897 | typedef std::pair<expression_ptr,bool> branch_t; 08898 | 08899 | vector_celem_node(expression_ptr vec_node, 08900 | const std::size_t index, 08901 | vector_holder_ptr vec_holder) 08902 | : index_(index) 08903 | , vector_holder_(vec_holder) 08904 | , vector_base_((*vec_holder)[0]) 08905 | { 08906 | construct_branch_pair(vector_node_, vec_node); 08907 | assert(valid()); 08908 | } 08909 | 08910 | inline T value() const exprtk_override 08911 | { 08912 | return *access_vector(); 08913 | } 08914 | 08915 | inline T& ref() exprtk_override 08916 | { 08917 | return *access_vector(); 08918 | } 08919 | 08920 | inline const T& ref() const exprtk_override 08921 | { 08922 | return *access_vector(); 08923 | } 08924 | 08925 | inline typename expression_node<T>::node_type type() const exprtk_override 08926 | { 08927 | return expression_node<T>::e_veccelem; 08928 | } 08929 | 08930 | inline bool valid() const exprtk_override 08931 | { 08932 | return 08933 | vector_holder_ && 08934 | vector_node_.first && 08935 | vector_node_.first->valid(); 08936 | } 08937 | 08938 | inline vector_holder_t& vec_holder() 08939 | { 08940 | return (*vector_holder_); 08941 | } 08942 | 08943 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 08944 | { 08945 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 08946 | } 08947 | 08948 | std::size_t node_depth() const exprtk_override 08949 | { 08950 | return expression_node<T>::ndb_t::compute_node_depth(vector_node_); 08951 | } 08952 | 08953 | private: 08954 | 08955 | inline T* access_vector() const 08956 | { 08957 | vector_node_.first->value(); 08958 | return (vector_base_ + index_); 08959 | } 08960 | 08961 | const std::size_t index_; 08962 | vector_holder_ptr vector_holder_; 08963 | T* vector_base_; 08964 | branch_t vector_node_; 08965 | }; 08966 | 08967 | template <typename T> 08968 | class vector_elem_rtc_node exprtk_final 08969 | : public expression_node<T> 08970 | , public ivariable <T> 08971 | { 08972 | public: 08973 | 08974 | typedef expression_node<T>* expression_ptr; 08975 | typedef vector_holder<T> vector_holder_t; 08976 | typedef vector_holder_t* vector_holder_ptr; 08977 | typedef std::pair<expression_ptr,bool> branch_t; 08978 | 08979 | vector_elem_rtc_node(expression_ptr vec_node, 08980 | expression_ptr index, 08981 | vector_holder_ptr vec_holder, 08982 | vector_access_runtime_check_ptr vec_rt_chk) 08983 | : vector_holder_(vec_holder) 08984 | , vector_base_((*vec_holder)[0]) 08985 | , vec_rt_chk_(vec_rt_chk) 08986 | , max_vector_index_(vector_holder_->size() - 1) 08987 | { 08988 | construct_branch_pair(vector_node_, vec_node); 08989 | construct_branch_pair(index_ , index ); 08990 | assert(valid()); 08991 | } 08992 | 08993 | inline T value() const exprtk_override 08994 | { 08995 | return *access_vector(); 08996 | } 08997 | 08998 | inline T& ref() exprtk_override 08999 | { 09000 | return *access_vector(); 09001 | } 09002 | 09003 | inline const T& ref() const exprtk_override 09004 | { 09005 | return *access_vector(); 09006 | } 09007 | 09008 | inline typename expression_node<T>::node_type type() const exprtk_override 09009 | { 09010 | return expression_node<T>::e_vecelemrtc; 09011 | } 09012 | 09013 | inline bool valid() const exprtk_override 09014 | { 09015 | return 09016 | vector_holder_ && 09017 | index_.first && 09018 | vector_node_.first && 09019 | index_.first->valid() && 09020 | vector_node_.first->valid(); 09021 | } 09022 | 09023 | inline vector_holder_t& vec_holder() 09024 | { 09025 | return (*vector_holder_); 09026 | } 09027 | 09028 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09029 | { 09030 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 09031 | expression_node<T>::ndb_t::collect(index_, node_delete_list); 09032 | } 09033 | 09034 | std::size_t node_depth() const exprtk_override 09035 | { 09036 | return expression_node<T>::ndb_t::compute_node_depth 09037 | (vector_node_, index_); 09038 | } 09039 | 09040 | private: 09041 | 09042 | inline T* access_vector() const 09043 | { 09044 | const _uint64_t index = details::numeric::to_uint64(index_.first->value()); 09045 | vector_node_.first->value(); 09046 | 09047 | if (index <= max_vector_index_) 09048 | { 09049 | return (vector_holder_->data() + index); 09050 | } 09051 | 09052 | assert(vec_rt_chk_); 09053 | 09054 | vector_access_runtime_check::violation_context context; 09055 | context.base_ptr = reinterpret_cast<void*>(vector_base_); 09056 | context.end_ptr = reinterpret_cast<void*>(vector_base_ + vector_holder_->size()); 09057 | context.access_ptr = reinterpret_cast<void*>(vector_base_ + index); 09058 | context.type_size = sizeof(T); 09059 | 09060 | return vec_rt_chk_->handle_runtime_violation(context) ? 09061 | reinterpret_cast<T*>(context.access_ptr) : 09062 | vector_base_ ; 09063 | } 09064 | 09065 | vector_holder_ptr vector_holder_; 09066 | T* vector_base_; 09067 | branch_t vector_node_; 09068 | branch_t index_; 09069 | vector_access_runtime_check_ptr vec_rt_chk_; 09070 | const std::size_t max_vector_index_; 09071 | }; 09072 | 09073 | template <typename T> 09074 | class vector_celem_rtc_node exprtk_final 09075 | : public expression_node<T> 09076 | , public ivariable <T> 09077 | { 09078 | public: 09079 | 09080 | typedef expression_node<T>* expression_ptr; 09081 | typedef vector_holder<T> vector_holder_t; 09082 | typedef vector_holder_t* vector_holder_ptr; 09083 | typedef std::pair<expression_ptr,bool> branch_t; 09084 | 09085 | vector_celem_rtc_node(expression_ptr vec_node, 09086 | const std::size_t index, 09087 | vector_holder_ptr vec_holder, 09088 | vector_access_runtime_check_ptr vec_rt_chk) 09089 | : index_(index) 09090 | , max_vector_index_(vec_holder->size() - 1) 09091 | , vector_holder_(vec_holder) 09092 | , vector_base_((*vec_holder)[0]) 09093 | , vec_rt_chk_(vec_rt_chk) 09094 | { 09095 | construct_branch_pair(vector_node_, vec_node); 09096 | assert(valid()); 09097 | } 09098 | 09099 | inline T value() const exprtk_override 09100 | { 09101 | return *access_vector(); 09102 | } 09103 | 09104 | inline T& ref() exprtk_override 09105 | { 09106 | return *access_vector(); 09107 | } 09108 | 09109 | inline const T& ref() const exprtk_override 09110 | { 09111 | return *access_vector(); 09112 | } 09113 | 09114 | inline typename expression_node<T>::node_type type() const exprtk_override 09115 | { 09116 | return expression_node<T>::e_veccelemrtc; 09117 | } 09118 | 09119 | inline bool valid() const exprtk_override 09120 | { 09121 | return 09122 | vector_holder_ && 09123 | vector_node_.first && 09124 | vector_node_.first->valid(); 09125 | } 09126 | 09127 | inline vector_holder_t& vec_holder() 09128 | { 09129 | return (*vector_holder_); 09130 | } 09131 | 09132 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09133 | { 09134 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 09135 | } 09136 | 09137 | std::size_t node_depth() const exprtk_override 09138 | { 09139 | return expression_node<T>::ndb_t::compute_node_depth(vector_node_); 09140 | } 09141 | 09142 | private: 09143 | 09144 | inline T* access_vector() const 09145 | { 09146 | vector_node_.first->value(); 09147 | 09148 | if (index_ <= max_vector_index_) 09149 | { 09150 | return (vector_holder_->data() + index_); 09151 | } 09152 | 09153 | assert(vec_rt_chk_); 09154 | 09155 | vector_access_runtime_check::violation_context context; 09156 | context.base_ptr = reinterpret_cast<void*>(vector_base_); 09157 | context.end_ptr = reinterpret_cast<void*>(vector_base_ + vector_holder_->size()); 09158 | context.access_ptr = reinterpret_cast<void*>(vector_base_ + index_); 09159 | context.type_size = sizeof(T); 09160 | 09161 | return vec_rt_chk_->handle_runtime_violation(context) ? 09162 | reinterpret_cast<T*>(context.access_ptr) : 09163 | vector_base_ ; 09164 | } 09165 | 09166 | const std::size_t index_; 09167 | const std::size_t max_vector_index_; 09168 | vector_holder_ptr vector_holder_; 09169 | T* vector_base_; 09170 | branch_t vector_node_; 09171 | vector_access_runtime_check_ptr vec_rt_chk_; 09172 | }; 09173 | 09174 | template <typename T> 09175 | class rebasevector_elem_node exprtk_final 09176 | : public expression_node<T> 09177 | , public ivariable <T> 09178 | { 09179 | public: 09180 | 09181 | typedef expression_node<T>* expression_ptr; 09182 | typedef vector_holder<T> vector_holder_t; 09183 | typedef vector_holder_t* vector_holder_ptr; 09184 | typedef vec_data_store<T> vds_t; 09185 | typedef std::pair<expression_ptr,bool> branch_t; 09186 | 09187 | rebasevector_elem_node(expression_ptr vec_node, 09188 | expression_ptr index, 09189 | vector_holder_ptr vec_holder) 09190 | : vector_holder_(vec_holder) 09191 | { 09192 | construct_branch_pair(vector_node_, vec_node); 09193 | construct_branch_pair(index_ , index ); 09194 | assert(valid()); 09195 | } 09196 | 09197 | inline T value() const exprtk_override 09198 | { 09199 | return *access_vector(); 09200 | } 09201 | 09202 | inline T& ref() exprtk_override 09203 | { 09204 | return *access_vector(); 09205 | } 09206 | 09207 | inline const T& ref() const exprtk_override 09208 | { 09209 | return *access_vector(); 09210 | } 09211 | 09212 | inline typename expression_node<T>::node_type type() const exprtk_override 09213 | { 09214 | return expression_node<T>::e_rbvecelem; 09215 | } 09216 | 09217 | inline bool valid() const exprtk_override 09218 | { 09219 | return 09220 | vector_holder_ && 09221 | index_.first && 09222 | vector_node_.first && 09223 | index_.first->valid() && 09224 | vector_node_.first->valid(); 09225 | } 09226 | 09227 | inline vector_holder_t& vec_holder() 09228 | { 09229 | return (*vector_holder_); 09230 | } 09231 | 09232 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09233 | { 09234 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 09235 | expression_node<T>::ndb_t::collect(index_, node_delete_list); 09236 | } 09237 | 09238 | std::size_t node_depth() const exprtk_override 09239 | { 09240 | return expression_node<T>::ndb_t::compute_node_depth 09241 | (vector_node_, index_); 09242 | } 09243 | 09244 | private: 09245 | 09246 | inline T* access_vector() const 09247 | { 09248 | vector_node_.first->value(); 09249 | return (vector_holder_->data() + details::numeric::to_uint64(index_.first->value())); 09250 | } 09251 | 09252 | vector_holder_ptr vector_holder_; 09253 | branch_t vector_node_; 09254 | branch_t index_; 09255 | }; 09256 | 09257 | template <typename T> 09258 | class rebasevector_celem_node exprtk_final 09259 | : public expression_node<T> 09260 | , public ivariable <T> 09261 | { 09262 | public: 09263 | 09264 | typedef expression_node<T>* expression_ptr; 09265 | typedef vector_holder<T> vector_holder_t; 09266 | typedef vector_holder_t* vector_holder_ptr; 09267 | typedef std::pair<expression_ptr,bool> branch_t; 09268 | 09269 | rebasevector_celem_node(expression_ptr vec_node, 09270 | const std::size_t index, 09271 | vector_holder_ptr vec_holder) 09272 | : index_(index) 09273 | , vector_holder_(vec_holder) 09274 | { 09275 | construct_branch_pair(vector_node_, vec_node); 09276 | assert(valid()); 09277 | } 09278 | 09279 | inline T value() const exprtk_override 09280 | { 09281 | vector_node_.first->value(); 09282 | return ref(); 09283 | } 09284 | 09285 | inline T& ref() exprtk_override 09286 | { 09287 | return *(vector_holder_->data() + index_); 09288 | } 09289 | 09290 | inline const T& ref() const exprtk_override 09291 | { 09292 | return *(vector_holder_->data() + index_); 09293 | } 09294 | 09295 | inline typename expression_node<T>::node_type type() const exprtk_override 09296 | { 09297 | return expression_node<T>::e_rbveccelem; 09298 | } 09299 | 09300 | inline bool valid() const exprtk_override 09301 | { 09302 | return 09303 | vector_holder_ && 09304 | vector_node_.first && 09305 | vector_node_.first->valid(); 09306 | } 09307 | 09308 | inline vector_holder_t& vec_holder() 09309 | { 09310 | return (*vector_holder_); 09311 | } 09312 | 09313 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09314 | { 09315 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 09316 | } 09317 | 09318 | std::size_t node_depth() const exprtk_override 09319 | { 09320 | return expression_node<T>::ndb_t::compute_node_depth(vector_node_); 09321 | } 09322 | 09323 | private: 09324 | 09325 | const std::size_t index_; 09326 | vector_holder_ptr vector_holder_; 09327 | branch_t vector_node_; 09328 | }; 09329 | 09330 | template <typename T> 09331 | class rebasevector_elem_rtc_node exprtk_final 09332 | : public expression_node<T> 09333 | , public ivariable <T> 09334 | { 09335 | public: 09336 | 09337 | typedef expression_node<T>* expression_ptr; 09338 | typedef vector_holder<T> vector_holder_t; 09339 | typedef vector_holder_t* vector_holder_ptr; 09340 | typedef std::pair<expression_ptr,bool> branch_t; 09341 | 09342 | rebasevector_elem_rtc_node(expression_ptr vec_node, 09343 | expression_ptr index, 09344 | vector_holder_ptr vec_holder, 09345 | vector_access_runtime_check_ptr vec_rt_chk) 09346 | : vector_holder_(vec_holder) 09347 | , vec_rt_chk_(vec_rt_chk) 09348 | { 09349 | construct_branch_pair(vector_node_, vec_node); 09350 | construct_branch_pair(index_ , index ); 09351 | assert(valid()); 09352 | } 09353 | 09354 | inline T value() const exprtk_override 09355 | { 09356 | return *access_vector(); 09357 | } 09358 | 09359 | inline T& ref() exprtk_override 09360 | { 09361 | return *access_vector(); 09362 | } 09363 | 09364 | inline const T& ref() const exprtk_override 09365 | { 09366 | return *access_vector(); 09367 | } 09368 | 09369 | inline typename expression_node<T>::node_type type() const exprtk_override 09370 | { 09371 | return expression_node<T>::e_rbvecelemrtc; 09372 | } 09373 | 09374 | inline bool valid() const exprtk_override 09375 | { 09376 | return 09377 | vector_holder_ && 09378 | index_.first && 09379 | vector_node_.first && 09380 | index_.first->valid() && 09381 | vector_node_.first->valid(); 09382 | } 09383 | 09384 | inline vector_holder_t& vec_holder() 09385 | { 09386 | return (*vector_holder_); 09387 | } 09388 | 09389 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09390 | { 09391 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 09392 | expression_node<T>::ndb_t::collect(index_ , node_delete_list); 09393 | } 09394 | 09395 | std::size_t node_depth() const exprtk_override 09396 | { 09397 | return expression_node<T>::ndb_t::compute_node_depth 09398 | (vector_node_, index_); 09399 | } 09400 | 09401 | private: 09402 | 09403 | inline T* access_vector() const 09404 | { 09405 | vector_node_.first->value(); 09406 | const _uint64_t index = details::numeric::to_uint64(index_.first->value()); 09407 | 09408 | if (index <= (vector_holder_->size() - 1)) 09409 | { 09410 | return (vector_holder_->data() + index); 09411 | } 09412 | 09413 | assert(vec_rt_chk_); 09414 | 09415 | vector_access_runtime_check::violation_context context; 09416 | context.base_ptr = reinterpret_cast<void*>(vector_holder_->data()); 09417 | context.end_ptr = reinterpret_cast<void*>(vector_holder_->data() + vector_holder_->size()); 09418 | context.access_ptr = reinterpret_cast<void*>(vector_holder_->data() + index); 09419 | context.type_size = sizeof(T); 09420 | 09421 | return vec_rt_chk_->handle_runtime_violation(context) ? 09422 | reinterpret_cast<T*>(context.access_ptr) : 09423 | vector_holder_->data() ; 09424 | } 09425 | 09426 | vector_holder_ptr vector_holder_; 09427 | branch_t vector_node_; 09428 | branch_t index_; 09429 | vector_access_runtime_check_ptr vec_rt_chk_; 09430 | }; 09431 | 09432 | template <typename T> 09433 | class rebasevector_celem_rtc_node exprtk_final 09434 | : public expression_node<T> 09435 | , public ivariable <T> 09436 | { 09437 | public: 09438 | 09439 | typedef expression_node<T>* expression_ptr; 09440 | typedef vector_holder<T> vector_holder_t; 09441 | typedef vector_holder_t* vector_holder_ptr; 09442 | typedef std::pair<expression_ptr,bool> branch_t; 09443 | 09444 | rebasevector_celem_rtc_node(expression_ptr vec_node, 09445 | const std::size_t index, 09446 | vector_holder_ptr vec_holder, 09447 | vector_access_runtime_check_ptr vec_rt_chk) 09448 | : index_(index) 09449 | , vector_holder_(vec_holder) 09450 | , vector_base_((*vec_holder)[0]) 09451 | , vec_rt_chk_(vec_rt_chk) 09452 | { 09453 | construct_branch_pair(vector_node_, vec_node); 09454 | assert(valid()); 09455 | } 09456 | 09457 | inline T value() const exprtk_override 09458 | { 09459 | return *access_vector(); 09460 | } 09461 | 09462 | inline T& ref() exprtk_override 09463 | { 09464 | return *access_vector(); 09465 | } 09466 | 09467 | inline const T& ref() const exprtk_override 09468 | { 09469 | return *access_vector(); 09470 | } 09471 | 09472 | inline typename expression_node<T>::node_type type() const exprtk_override 09473 | { 09474 | return expression_node<T>::e_rbveccelemrtc; 09475 | } 09476 | 09477 | inline bool valid() const exprtk_override 09478 | { 09479 | return 09480 | vector_holder_ && 09481 | vector_node_.first && 09482 | vector_node_.first->valid(); 09483 | } 09484 | 09485 | inline vector_holder_t& vec_holder() 09486 | { 09487 | return (*vector_holder_); 09488 | } 09489 | 09490 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09491 | { 09492 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 09493 | } 09494 | 09495 | std::size_t node_depth() const exprtk_override 09496 | { 09497 | return expression_node<T>::ndb_t::compute_node_depth(vector_node_); 09498 | } 09499 | 09500 | private: 09501 | 09502 | inline T* access_vector() const 09503 | { 09504 | vector_node_.first->value(); 09505 | 09506 | if (index_ <= vector_holder_->size() - 1) 09507 | { 09508 | return (vector_holder_->data() + index_); 09509 | } 09510 | 09511 | assert(vec_rt_chk_); 09512 | 09513 | vector_access_runtime_check::violation_context context; 09514 | context.base_ptr = reinterpret_cast<void*>(vector_base_); 09515 | context.end_ptr = reinterpret_cast<void*>(vector_base_ + vector_holder_->size()); 09516 | context.access_ptr = reinterpret_cast<void*>(vector_base_ + index_); 09517 | context.type_size = sizeof(T); 09518 | 09519 | return vec_rt_chk_->handle_runtime_violation(context) ? 09520 | reinterpret_cast<T*>(context.access_ptr) : 09521 | vector_base_ ; 09522 | } 09523 | 09524 | const std::size_t index_; 09525 | vector_holder_ptr vector_holder_; 09526 | T* vector_base_; 09527 | branch_t vector_node_; 09528 | vector_access_runtime_check_ptr vec_rt_chk_; 09529 | }; 09530 | 09531 | template <typename T> 09532 | class vector_initialisation_node exprtk_final : public expression_node<T> 09533 | { 09534 | public: 09535 | 09536 | typedef expression_node<T>* expression_ptr; 09537 | 09538 | vector_initialisation_node(T* vector_base, 09539 | const std::size_t& size, 09540 | const std::vector<expression_ptr>& initialiser_list, 09541 | const bool single_value_initialse) 09542 | : vector_base_(vector_base) 09543 | , initialiser_list_(initialiser_list) 09544 | , size_(size) 09545 | , single_value_initialse_(single_value_initialse) 09546 | , zero_value_initialse_(false) 09547 | , const_nonzero_literal_value_initialse_(false) 09548 | , single_initialiser_value_(T(0)) 09549 | { 09550 | if (single_value_initialse_) 09551 | { 09552 | if (initialiser_list_.empty()) 09553 | zero_value_initialse_ = true; 09554 | else if ( 09555 | (initialiser_list_.size() == 1) && 09556 | details::is_constant_node(initialiser_list_[0]) && 09557 | (T(0) == initialiser_list_[0]->value()) 09558 | ) 09559 | { 09560 | zero_value_initialse_ = true; 09561 | } 09562 | else 09563 | { 09564 | assert(initialiser_list_.size() == 1); 09565 | 09566 | if (details::is_constant_node(initialiser_list_[0])) 09567 | { 09568 | const_nonzero_literal_value_initialse_ = true; 09569 | single_initialiser_value_ = initialiser_list_[0]->value(); 09570 | assert(T(0) != single_initialiser_value_); 09571 | } 09572 | } 09573 | } 09574 | } 09575 | 09576 | inline T value() const exprtk_override 09577 | { 09578 | if (single_value_initialse_) 09579 | { 09580 | if (zero_value_initialse_) 09581 | { 09582 | details::set_zero_value(vector_base_, size_); 09583 | } 09584 | else if (const_nonzero_literal_value_initialse_) 09585 | { 09586 | for (std::size_t i = 0; i < size_; ++i) 09587 | { 09588 | *(vector_base_ + i) = single_initialiser_value_; 09589 | } 09590 | } 09591 | else 09592 | { 09593 | for (std::size_t i = 0; i < size_; ++i) 09594 | { 09595 | *(vector_base_ + i) = initialiser_list_[0]->value(); 09596 | } 09597 | } 09598 | } 09599 | else 09600 | { 09601 | const std::size_t initialiser_list_size = initialiser_list_.size(); 09602 | 09603 | for (std::size_t i = 0; i < initialiser_list_size; ++i) 09604 | { 09605 | *(vector_base_ + i) = initialiser_list_[i]->value(); 09606 | } 09607 | 09608 | if (initialiser_list_size < size_) 09609 | { 09610 | details::set_zero_value( 09611 | vector_base_ + initialiser_list_size, 09612 | (size_ - initialiser_list_size)); 09613 | } 09614 | } 09615 | 09616 | return *(vector_base_); 09617 | } 09618 | 09619 | inline typename expression_node<T>::node_type type() const exprtk_override 09620 | { 09621 | return expression_node<T>::e_vecinit; 09622 | } 09623 | 09624 | inline bool valid() const exprtk_override 09625 | { 09626 | return vector_base_; 09627 | } 09628 | 09629 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09630 | { 09631 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09632 | } 09633 | 09634 | std::size_t node_depth() const exprtk_override 09635 | { 09636 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09637 | } 09638 | 09639 | private: 09640 | 09641 | vector_initialisation_node(const vector_initialisation_node<T>&) exprtk_delete; 09642 | vector_initialisation_node<T>& operator=(const vector_initialisation_node<T>&) exprtk_delete; 09643 | 09644 | mutable T* vector_base_; 09645 | std::vector<expression_ptr> initialiser_list_; 09646 | const std::size_t size_; 09647 | const bool single_value_initialse_; 09648 | bool zero_value_initialse_; 09649 | bool const_nonzero_literal_value_initialse_; 09650 | T single_initialiser_value_; 09651 | }; 09652 | 09653 | template <typename T> 09654 | class vector_init_zero_value_node exprtk_final : public expression_node<T> 09655 | { 09656 | public: 09657 | 09658 | typedef expression_node<T>* expression_ptr; 09659 | 09660 | vector_init_zero_value_node(T* vector_base, 09661 | const std::size_t& size, 09662 | const std::vector<expression_ptr>& initialiser_list) 09663 | : vector_base_(vector_base) 09664 | , size_(size) 09665 | , initialiser_list_(initialiser_list) 09666 | {} 09667 | 09668 | inline T value() const exprtk_override 09669 | { 09670 | details::set_zero_value(vector_base_, size_); 09671 | return *(vector_base_); 09672 | } 09673 | 09674 | inline typename expression_node<T>::node_type type() const exprtk_override 09675 | { 09676 | return expression_node<T>::e_vecinit; 09677 | } 09678 | 09679 | inline bool valid() const exprtk_override 09680 | { 09681 | return vector_base_; 09682 | } 09683 | 09684 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09685 | { 09686 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09687 | } 09688 | 09689 | std::size_t node_depth() const exprtk_override 09690 | { 09691 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09692 | } 09693 | 09694 | private: 09695 | 09696 | vector_init_zero_value_node(const vector_init_zero_value_node<T>&) exprtk_delete; 09697 | vector_init_zero_value_node<T>& operator=(const vector_init_zero_value_node<T>&) exprtk_delete; 09698 | 09699 | mutable T* vector_base_; 09700 | const std::size_t size_; 09701 | std::vector<expression_ptr> initialiser_list_; 09702 | }; 09703 | 09704 | template <typename T> 09705 | class vector_init_single_constvalue_node exprtk_final : public expression_node<T> 09706 | { 09707 | public: 09708 | 09709 | typedef expression_node<T>* expression_ptr; 09710 | 09711 | vector_init_single_constvalue_node(T* vector_base, 09712 | const std::size_t& size, 09713 | const std::vector<expression_ptr>& initialiser_list) 09714 | : vector_base_(vector_base) 09715 | , size_(size) 09716 | , initialiser_list_(initialiser_list) 09717 | { 09718 | single_initialiser_value_ = initialiser_list_[0]->value(); 09719 | assert(valid()); 09720 | } 09721 | 09722 | inline T value() const exprtk_override 09723 | { 09724 | for (std::size_t i = 0; i < size_; ++i) 09725 | { 09726 | *(vector_base_ + i) = single_initialiser_value_; 09727 | } 09728 | 09729 | return *(vector_base_); 09730 | } 09731 | 09732 | inline typename expression_node<T>::node_type type() const exprtk_override 09733 | { 09734 | return expression_node<T>::e_vecinit; 09735 | } 09736 | 09737 | inline bool valid() const exprtk_override 09738 | { 09739 | return vector_base_ && 09740 | (initialiser_list_.size() == 1) && 09741 | (details::is_constant_node(initialiser_list_[0])) && 09742 | (single_initialiser_value_ != T(0)); 09743 | } 09744 | 09745 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09746 | { 09747 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09748 | } 09749 | 09750 | std::size_t node_depth() const exprtk_override 09751 | { 09752 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09753 | } 09754 | 09755 | private: 09756 | 09757 | vector_init_single_constvalue_node(const vector_init_single_constvalue_node<T>&) exprtk_delete; 09758 | vector_init_single_constvalue_node<T>& operator=(const vector_init_single_constvalue_node<T>&) exprtk_delete; 09759 | 09760 | mutable T* vector_base_; 09761 | const std::size_t size_; 09762 | std::vector<expression_ptr> initialiser_list_; 09763 | T single_initialiser_value_; 09764 | }; 09765 | 09766 | template <typename T> 09767 | class vector_init_single_value_node exprtk_final : public expression_node<T> 09768 | { 09769 | public: 09770 | 09771 | typedef expression_node<T>* expression_ptr; 09772 | 09773 | vector_init_single_value_node(T* vector_base, 09774 | const std::size_t& size, 09775 | const std::vector<expression_ptr>& initialiser_list) 09776 | : vector_base_(vector_base) 09777 | , size_(size) 09778 | , initialiser_list_(initialiser_list) 09779 | { 09780 | assert(valid()); 09781 | } 09782 | 09783 | inline T value() const exprtk_override 09784 | { 09785 | expression_node<T>& node = *initialiser_list_[0]; 09786 | 09787 | for (std::size_t i = 0; i < size_; ++i) 09788 | { 09789 | *(vector_base_ + i) = node.value(); 09790 | } 09791 | 09792 | return *(vector_base_); 09793 | } 09794 | 09795 | inline typename expression_node<T>::node_type type() const exprtk_override 09796 | { 09797 | return expression_node<T>::e_vecinit; 09798 | } 09799 | 09800 | inline bool valid() const exprtk_override 09801 | { 09802 | return vector_base_ && 09803 | (initialiser_list_.size() == 1) && 09804 | !details::is_constant_node(initialiser_list_[0]); 09805 | } 09806 | 09807 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09808 | { 09809 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09810 | } 09811 | 09812 | std::size_t node_depth() const exprtk_override 09813 | { 09814 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09815 | } 09816 | 09817 | private: 09818 | 09819 | vector_init_single_value_node(const vector_init_single_value_node<T>&) exprtk_delete; 09820 | vector_init_single_value_node<T>& operator=(const vector_init_single_value_node<T>&) exprtk_delete; 09821 | 09822 | mutable T* vector_base_; 09823 | const std::size_t size_; 09824 | std::vector<expression_ptr> initialiser_list_; 09825 | }; 09826 | 09827 | template <typename T> 09828 | class vector_init_iota_constconst_node exprtk_final : public expression_node<T> 09829 | { 09830 | public: 09831 | 09832 | typedef expression_node<T>* expression_ptr; 09833 | 09834 | vector_init_iota_constconst_node(T* vector_base, 09835 | const std::size_t& size, 09836 | const std::vector<expression_ptr>& initialiser_list) 09837 | : vector_base_(vector_base) 09838 | , size_(size) 09839 | , initialiser_list_(initialiser_list) 09840 | { 09841 | base_value_ = initialiser_list_[0]->value(); 09842 | increment_value_ = initialiser_list_[1]->value(); 09843 | 09844 | assert(valid()); 09845 | } 09846 | 09847 | inline T value() const exprtk_override 09848 | { 09849 | T value = base_value_; 09850 | 09851 | for (std::size_t i = 0; i < size_; ++i, value += increment_value_) 09852 | { 09853 | *(vector_base_ + i) = value; 09854 | } 09855 | 09856 | return *(vector_base_); 09857 | } 09858 | 09859 | inline typename expression_node<T>::node_type type() const exprtk_override 09860 | { 09861 | return expression_node<T>::e_vecinit; 09862 | } 09863 | 09864 | inline bool valid() const exprtk_override 09865 | { 09866 | return vector_base_ && 09867 | (initialiser_list_.size() == 2) && 09868 | (details::is_constant_node(initialiser_list_[0])) && 09869 | (details::is_constant_node(initialiser_list_[1])) ; 09870 | } 09871 | 09872 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09873 | { 09874 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09875 | } 09876 | 09877 | std::size_t node_depth() const exprtk_override 09878 | { 09879 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09880 | } 09881 | 09882 | private: 09883 | 09884 | vector_init_iota_constconst_node(const vector_init_iota_constconst_node<T>&) exprtk_delete; 09885 | vector_init_iota_constconst_node<T>& operator=(const vector_init_iota_constconst_node<T>&) exprtk_delete; 09886 | 09887 | mutable T* vector_base_; 09888 | const std::size_t size_; 09889 | std::vector<expression_ptr> initialiser_list_; 09890 | T base_value_; 09891 | T increment_value_; 09892 | }; 09893 | 09894 | template <typename T> 09895 | class vector_init_iota_constnconst_node exprtk_final : public expression_node<T> 09896 | { 09897 | public: 09898 | 09899 | typedef expression_node<T>* expression_ptr; 09900 | 09901 | vector_init_iota_constnconst_node(T* vector_base, 09902 | const std::size_t& size, 09903 | const std::vector<expression_ptr>& initialiser_list) 09904 | : vector_base_(vector_base) 09905 | , size_(size) 09906 | , initialiser_list_(initialiser_list) 09907 | { 09908 | assert(valid()); 09909 | base_value_ = initialiser_list_[0]->value(); 09910 | } 09911 | 09912 | inline T value() const exprtk_override 09913 | { 09914 | T value = base_value_; 09915 | expression_node<T>& increment = *initialiser_list_[1]; 09916 | 09917 | for (std::size_t i = 0; i < size_; ++i, value += increment.value()) 09918 | { 09919 | *(vector_base_ + i) = value; 09920 | } 09921 | 09922 | return *(vector_base_); 09923 | } 09924 | 09925 | inline typename expression_node<T>::node_type type() const exprtk_override 09926 | { 09927 | return expression_node<T>::e_vecinit; 09928 | } 09929 | 09930 | inline bool valid() const exprtk_override 09931 | { 09932 | return vector_base_ && 09933 | (initialiser_list_.size() == 2) && 09934 | ( details::is_constant_node(initialiser_list_[0])) && 09935 | (!details::is_constant_node(initialiser_list_[1])); 09936 | } 09937 | 09938 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09939 | { 09940 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09941 | } 09942 | 09943 | std::size_t node_depth() const exprtk_override 09944 | { 09945 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09946 | } 09947 | 09948 | private: 09949 | 09950 | vector_init_iota_constnconst_node(const vector_init_iota_constnconst_node<T>&) exprtk_delete; 09951 | vector_init_iota_constnconst_node<T>& operator=(const vector_init_iota_constnconst_node<T>&) exprtk_delete; 09952 | 09953 | mutable T* vector_base_; 09954 | const std::size_t size_; 09955 | std::vector<expression_ptr> initialiser_list_; 09956 | T base_value_; 09957 | }; 09958 | 09959 | template <typename T> 09960 | class vector_init_iota_nconstconst_node exprtk_final : public expression_node<T> 09961 | { 09962 | public: 09963 | 09964 | typedef expression_node<T>* expression_ptr; 09965 | 09966 | vector_init_iota_nconstconst_node(T* vector_base, 09967 | const std::size_t& size, 09968 | const std::vector<expression_ptr>& initialiser_list) 09969 | : vector_base_(vector_base) 09970 | , size_(size) 09971 | , initialiser_list_(initialiser_list) 09972 | { 09973 | assert(valid()); 09974 | } 09975 | 09976 | inline T value() const exprtk_override 09977 | { 09978 | T value = initialiser_list_[0]->value(); 09979 | const T increment = initialiser_list_[1]->value(); 09980 | 09981 | for (std::size_t i = 0; i < size_; ++i, value += increment) 09982 | { 09983 | *(vector_base_ + i) = value; 09984 | } 09985 | 09986 | return *(vector_base_); 09987 | } 09988 | 09989 | inline typename expression_node<T>::node_type type() const exprtk_override 09990 | { 09991 | return expression_node<T>::e_vecinit; 09992 | } 09993 | 09994 | inline bool valid() const exprtk_override 09995 | { 09996 | return vector_base_ && 09997 | (initialiser_list_.size() == 2) && 09998 | (!details::is_constant_node(initialiser_list_[0])) && 09999 | (details::is_constant_node(initialiser_list_[1])); 10000 | } 10001 | 10002 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 10003 | { 10004 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 10005 | } 10006 | 10007 | std::size_t node_depth() const exprtk_override 10008 | { 10009 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 10010 | } 10011 | 10012 | private: 10013 | 10014 | vector_init_iota_nconstconst_node(const vector_init_iota_nconstconst_node<T>&) exprtk_delete; 10015 | vector_init_iota_nconstconst_node<T>& operator=(const vector_init_iota_nconstconst_node<T>&) exprtk_delete; 10016 | 10017 | mutable T* vector_base_; 10018 | const std::size_t size_; 10019 | std::vector<expression_ptr> initialiser_list_; 10020 | }; 10021 | 10022 | template <typename T> 10023 | class vector_init_iota_nconstnconst_node exprtk_final : public expression_node<T> 10024 | { 10025 | public: 10026 | 10027 | typedef expression_node<T>* expression_ptr; 10028 | 10029 | vector_init_iota_nconstnconst_node(T* vector_base, 10030 | const std::size_t& size, 10031 | const std::vector<expression_ptr>& initialiser_list) 10032 | : vector_base_(vector_base) 10033 | , size_(size) 10034 | , initialiser_list_(initialiser_list) 10035 | { 10036 | assert(valid()); 10037 | } 10038 | 10039 | inline T value() const exprtk_override 10040 | { 10041 | T value = initialiser_list_[0]->value(); 10042 | expression_node<T>& increment = *initialiser_list_[1]; 10043 | 10044 | for (std::size_t i = 0; i < size_; ++i, value += increment.value()) 10045 | { 10046 | *(vector_base_ + i) = value; 10047 | } 10048 | 10049 | return *(vector_base_); 10050 | } 10051 | 10052 | inline typename expression_node<T>::node_type type() const exprtk_override 10053 | { 10054 | return expression_node<T>::e_vecinit; 10055 | } 10056 | 10057 | inline bool valid() const exprtk_override 10058 | { 10059 | return vector_base_ && 10060 | (initialiser_list_.size() == 2) && 10061 | (!details::is_constant_node(initialiser_list_[0])) && 10062 | (!details::is_constant_node(initialiser_list_[1])); 10063 | } 10064 | 10065 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 10066 | { 10067 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 10068 | } 10069 | 10070 | std::size_t node_depth() const exprtk_override 10071 | { 10072 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 10073 | } 10074 | 10075 | private: 10076 | 10077 | vector_init_iota_nconstnconst_node(const vector_init_iota_nconstnconst_node<T>&) exprtk_delete; 10078 | vector_init_iota_nconstnconst_node<T>& operator=(const vector_init_iota_nconstnconst_node<T>&) exprtk_delete; 10079 | 10080 | mutable T* vector_base_; 10081 | const std::size_t size_; 10082 | std::vector<expression_ptr> initialiser_list_; 10083 | }; 10084 | 10085 | template <typename T> 10086 | class swap_node exprtk_final : public expression_node<T> 10087 | { 10088 | public: 10089 | 10090 | typedef expression_node<T>* expression_ptr; 10091 | typedef variable_node<T>* variable_node_ptr; 10092 | 10093 | swap_node(variable_node_ptr var0, variable_node_ptr var1) 10094 | : var0_(var0) 10095 | , var1_(var1) 10096 | {} 10097 | 10098 | inline T value() const exprtk_override 10099 | { 10100 | std::swap(var0_->ref(),var1_->ref()); 10101 | return var1_->ref(); 10102 | } 10103 | 10104 | inline typename expression_node<T>::node_type type() const exprtk_override 10105 | { 10106 | return expression_node<T>::e_swap; 10107 | } 10108 | 10109 | private: 10110 | 10111 | variable_node_ptr var0_; 10112 | variable_node_ptr var1_; 10113 | }; 10114 | 10115 | template <typename T> 10116 | class swap_generic_node exprtk_final : public binary_node<T> 10117 | { 10118 | public: 10119 | 10120 | typedef expression_node<T>* expression_ptr; 10121 | typedef ivariable<T>* ivariable_ptr; 10122 | 10123 | swap_generic_node(expression_ptr var0, expression_ptr var1) 10124 | : binary_node<T>(details::e_swap, var0, var1) 10125 | , var0_(dynamic_cast<ivariable_ptr>(var0)) 10126 | , var1_(dynamic_cast<ivariable_ptr>(var1)) 10127 | {} 10128 | 10129 | inline T value() const exprtk_override 10130 | { 10131 | std::swap(var0_->ref(),var1_->ref()); 10132 | return var1_->ref(); 10133 | } 10134 | 10135 | inline typename expression_node<T>::node_type type() const exprtk_override 10136 | { 10137 | return expression_node<T>::e_swap; 10138 | } 10139 | 10140 | private: 10141 | 10142 | ivariable_ptr var0_; 10143 | ivariable_ptr var1_; 10144 | }; 10145 | 10146 | template <typename T> 10147 | class swap_vecvec_node exprtk_final 10148 | : public binary_node <T> 10149 | , public vector_interface<T> 10150 | { 10151 | public: 10152 | 10153 | typedef expression_node<T>* expression_ptr; 10154 | typedef vector_node <T>* vector_node_ptr; 10155 | typedef vec_data_store <T> vds_t; 10156 | 10157 | using binary_node<T>::branch; 10158 | 10159 | swap_vecvec_node(expression_ptr branch0, 10160 | expression_ptr branch1) 10161 | : binary_node<T>(details::e_swap, branch0, branch1) 10162 | , vec0_node_ptr_(0) 10163 | , vec1_node_ptr_(0) 10164 | , initialised_ (false) 10165 | { 10166 | if (is_ivector_node(branch(0))) 10167 | { 10168 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 10169 | 10170 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(0)))) 10171 | { 10172 | vec0_node_ptr_ = vi->vec(); 10173 | vds() = vi->vds(); 10174 | } 10175 | } 10176 | 10177 | if (is_ivector_node(branch(1))) 10178 | { 10179 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 10180 | 10181 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1)))) 10182 | { 10183 | vec1_node_ptr_ = vi->vec(); 10184 | } 10185 | } 10186 | 10187 | if (vec0_node_ptr_ && vec1_node_ptr_) 10188 | { 10189 | initialised_ = size() <= base_size(); 10190 | } 10191 | 10192 | assert(valid()); 10193 | } 10194 | 10195 | inline T value() const exprtk_override 10196 | { 10197 | binary_node<T>::branch(0)->value(); 10198 | binary_node<T>::branch(1)->value(); 10199 | 10200 | T* vec0 = vec0_node_ptr_->vds().data(); 10201 | T* vec1 = vec1_node_ptr_->vds().data(); 10202 | 10203 | assert(size() <= base_size()); 10204 | const std::size_t n = size(); 10205 | 10206 | for (std::size_t i = 0; i < n; ++i) 10207 | { 10208 | std::swap(vec0[i],vec1[i]); 10209 | } 10210 | 10211 | return vec1_node_ptr_->value(); 10212 | } 10213 | 10214 | vector_node_ptr vec() const exprtk_override 10215 | { 10216 | return vec0_node_ptr_; 10217 | } 10218 | 10219 | vector_node_ptr vec() exprtk_override 10220 | { 10221 | return vec0_node_ptr_; 10222 | } 10223 | 10224 | inline typename expression_node<T>::node_type type() const exprtk_override 10225 | { 10226 | return expression_node<T>::e_vecvecswap; 10227 | } 10228 | 10229 | inline bool valid() const exprtk_override 10230 | { 10231 | return initialised_ && binary_node<T>::valid(); 10232 | } 10233 | 10234 | std::size_t size() const exprtk_override 10235 | { 10236 | return std::min( 10237 | vec0_node_ptr_->vec_holder().size(), 10238 | vec1_node_ptr_->vec_holder().size()); 10239 | } 10240 | 10241 | std::size_t base_size() const exprtk_override 10242 | { 10243 | return std::min( 10244 | vec0_node_ptr_->vec_holder().base_size(), 10245 | vec1_node_ptr_->vec_holder().base_size()); 10246 | } 10247 | 10248 | vds_t& vds() exprtk_override 10249 | { 10250 | return vds_; 10251 | } 10252 | 10253 | const vds_t& vds() const exprtk_override 10254 | { 10255 | return vds_; 10256 | } 10257 | 10258 | private: 10259 | 10260 | vector_node<T>* vec0_node_ptr_; 10261 | vector_node<T>* vec1_node_ptr_; 10262 | bool initialised_; 10263 | vds_t vds_; 10264 | }; 10265 | 10266 | #ifndef exprtk_disable_string_capabilities 10267 | template <typename T> 10268 | class stringvar_node exprtk_final 10269 | : public expression_node <T> 10270 | , public string_base_node<T> 10271 | , public range_interface <T> 10272 | { 10273 | public: 10274 | 10275 | typedef typename range_interface<T>::range_t range_t; 10276 | 10277 | static std::string null_value; 10278 | 10279 | explicit stringvar_node() 10280 | : value_(&null_value) 10281 | {} 10282 | 10283 | explicit stringvar_node(std::string& v) 10284 | : value_(&v) 10285 | { 10286 | rp_.n0_c = std::make_pair<bool,std::size_t>(true,0); 10287 | rp_.n1_c = std::make_pair<bool,std::size_t>(true,v.size()); 10288 | rp_.cache.first = rp_.n0_c.second; 10289 | rp_.cache.second = rp_.n1_c.second; 10290 | } 10291 | 10292 | inline bool operator <(const stringvar_node<T>& v) const 10293 | { 10294 | return this < (&v); 10295 | } 10296 | 10297 | inline T value() const exprtk_override 10298 | { 10299 | rp_.n1_c.second = (*value_).size(); 10300 | rp_.cache.second = rp_.n1_c.second; 10301 | 10302 | return std::numeric_limits<T>::quiet_NaN(); 10303 | } 10304 | 10305 | std::string str() const exprtk_override 10306 | { 10307 | return ref(); 10308 | } 10309 | 10310 | char_cptr base() const exprtk_override 10311 | { 10312 | return &(*value_)[0]; 10313 | } 10314 | 10315 | std::size_t size() const exprtk_override 10316 | { 10317 | return ref().size(); 10318 | } 10319 | 10320 | std::string& ref() 10321 | { 10322 | return (*value_); 10323 | } 10324 | 10325 | const std::string& ref() const 10326 | { 10327 | return (*value_); 10328 | } 10329 | 10330 | range_t& range_ref() exprtk_override 10331 | { 10332 | return rp_; 10333 | } 10334 | 10335 | const range_t& range_ref() const exprtk_override 10336 | { 10337 | return rp_; 10338 | } 10339 | 10340 | inline typename expression_node<T>::node_type type() const exprtk_override 10341 | { 10342 | return expression_node<T>::e_stringvar; 10343 | } 10344 | 10345 | void rebase(std::string& s) 10346 | { 10347 | value_ = &s; 10348 | rp_.n0_c = std::make_pair<bool,std::size_t>(true,0); 10349 | rp_.n1_c = std::make_pair<bool,std::size_t>(true,value_->size() - 1); 10350 | rp_.cache.first = rp_.n0_c.second; 10351 | rp_.cache.second = rp_.n1_c.second; 10352 | } 10353 | 10354 | private: 10355 | 10356 | std::string* value_; 10357 | mutable range_t rp_; 10358 | }; 10359 | 10360 | template <typename T> 10361 | std::string stringvar_node<T>::null_value = std::string(""); 10362 | 10363 | template <typename T> 10364 | class string_range_node exprtk_final 10365 | : public expression_node <T> 10366 | , public string_base_node<T> 10367 | , public range_interface <T> 10368 | { 10369 | public: 10370 | 10371 | typedef typename range_interface<T>::range_t range_t; 10372 | 10373 | static std::string null_value; 10374 | 10375 | explicit string_range_node(std::string& v, const range_t& rp) 10376 | : value_(&v) 10377 | , rp_(rp) 10378 | {} 10379 | 10380 | virtual ~string_range_node() 10381 | { 10382 | rp_.free(); 10383 | } 10384 | 10385 | inline bool operator <(const string_range_node<T>& v) const 10386 | { 10387 | return this < (&v); 10388 | } 10389 | 10390 | inline T value() const exprtk_override 10391 | { 10392 | return std::numeric_limits<T>::quiet_NaN(); 10393 | } 10394 | 10395 | inline std::string str() const exprtk_override 10396 | { 10397 | return (*value_); 10398 | } 10399 | 10400 | char_cptr base() const exprtk_override 10401 | { 10402 | return &(*value_)[0]; 10403 | } 10404 | 10405 | std::size_t size() const exprtk_override 10406 | { 10407 | return ref().size(); 10408 | } 10409 | 10410 | inline range_t range() const 10411 | { 10412 | return rp_; 10413 | } 10414 | 10415 | inline std::string& ref() 10416 | { 10417 | return (*value_); 10418 | } 10419 | 10420 | inline const std::string& ref() const 10421 | { 10422 | return (*value_); 10423 | } 10424 | 10425 | inline range_t& range_ref() exprtk_override 10426 | { 10427 | return rp_; 10428 | } 10429 | 10430 | inline const range_t& range_ref() const exprtk_override 10431 | { 10432 | return rp_; 10433 | } 10434 | 10435 | inline typename expression_node<T>::node_type type() const exprtk_override 10436 | { 10437 | return expression_node<T>::e_stringvarrng; 10438 | } 10439 | 10440 | private: 10441 | 10442 | std::string* value_; 10443 | range_t rp_; 10444 | }; 10445 | 10446 | template <typename T> 10447 | std::string string_range_node<T>::null_value = std::string(""); 10448 | 10449 | template <typename T> 10450 | class const_string_range_node exprtk_final 10451 | : public expression_node <T> 10452 | , public string_base_node<T> 10453 | , public range_interface <T> 10454 | { 10455 | public: 10456 | 10457 | typedef typename range_interface<T>::range_t range_t; 10458 | 10459 | explicit const_string_range_node(const std::string& v, const range_t& rp) 10460 | : value_(v) 10461 | , rp_(rp) 10462 | {} 10463 | 10464 | ~const_string_range_node() exprtk_override 10465 | { 10466 | rp_.free(); 10467 | } 10468 | 10469 | inline T value() const exprtk_override 10470 | { 10471 | return std::numeric_limits<T>::quiet_NaN(); 10472 | } 10473 | 10474 | std::string str() const exprtk_override 10475 | { 10476 | return value_; 10477 | } 10478 | 10479 | char_cptr base() const exprtk_override 10480 | { 10481 | return value_.data(); 10482 | } 10483 | 10484 | std::size_t size() const exprtk_override 10485 | { 10486 | return value_.size(); 10487 | } 10488 | 10489 | range_t range() const 10490 | { 10491 | return rp_; 10492 | } 10493 | 10494 | range_t& range_ref() exprtk_override 10495 | { 10496 | return rp_; 10497 | } 10498 | 10499 | const range_t& range_ref() const exprtk_override 10500 | { 10501 | return rp_; 10502 | } 10503 | 10504 | inline typename expression_node<T>::node_type type() const exprtk_override 10505 | { 10506 | return expression_node<T>::e_cstringvarrng; 10507 | } 10508 | 10509 | private: 10510 | 10511 | const_string_range_node(const const_string_range_node<T>&) exprtk_delete; 10512 | const_string_range_node<T>& operator=(const const_string_range_node<T>&) exprtk_delete; 10513 | 10514 | const std::string value_; 10515 | range_t rp_; 10516 | }; 10517 | 10518 | template <typename T> 10519 | class generic_string_range_node exprtk_final 10520 | : public expression_node <T> 10521 | , public string_base_node<T> 10522 | , public range_interface <T> 10523 | { 10524 | public: 10525 | 10526 | typedef expression_node <T>* expression_ptr; 10527 | typedef stringvar_node <T>* strvar_node_ptr; 10528 | typedef string_base_node<T>* str_base_ptr; 10529 | typedef typename range_interface<T>::range_t range_t; 10530 | typedef range_t* range_ptr; 10531 | typedef range_interface<T> irange_t; 10532 | typedef irange_t* irange_ptr; 10533 | typedef std::pair<expression_ptr,bool> branch_t; 10534 | 10535 | generic_string_range_node(expression_ptr str_branch, const range_t& brange) 10536 | : initialised_(false) 10537 | , str_base_ptr_ (0) 10538 | , str_range_ptr_(0) 10539 | , base_range_(brange) 10540 | { 10541 | range_.n0_c = std::make_pair<bool,std::size_t>(true,0); 10542 | range_.n1_c = std::make_pair<bool,std::size_t>(true,0); 10543 | range_.cache.first = range_.n0_c.second; 10544 | range_.cache.second = range_.n1_c.second; 10545 | 10546 | construct_branch_pair(branch_, str_branch); 10547 | 10548 | if (is_generally_string_node(branch_.first)) 10549 | { 10550 | str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_.first); 10551 | 10552 | if (0 == str_base_ptr_) 10553 | return; 10554 | 10555 | str_range_ptr_ = dynamic_cast<irange_ptr>(branch_.first); 10556 | 10557 | if (0 == str_range_ptr_) 10558 | return; 10559 | } 10560 | 10561 | initialised_ = (str_base_ptr_ && str_range_ptr_); 10562 | assert(valid()); 10563 | } 10564 | 10565 | ~generic_string_range_node() exprtk_override 10566 | { 10567 | base_range_.free(); 10568 | } 10569 | 10570 | inline T value() const exprtk_override 10571 | { 10572 | branch_.first->value(); 10573 | 10574 | std::size_t str_r0 = 0; 10575 | std::size_t str_r1 = 0; 10576 | 10577 | std::size_t r0 = 0; 10578 | std::size_t r1 = 0; 10579 | 10580 | const range_t& range = str_range_ptr_->range_ref(); 10581 | 10582 | const std::size_t base_str_size = str_base_ptr_->size(); 10583 | 10584 | if ( 10585 | range (str_r0, str_r1, base_str_size ) && 10586 | base_range_(r0 , r1 , base_str_size - str_r0) 10587 | ) 10588 | { 10589 | const std::size_t size = r1 - r0; 10590 | 10591 | range_.n1_c.second = size; 10592 | range_.cache.second = range_.n1_c.second; 10593 | 10594 | value_.assign(str_base_ptr_->base() + str_r0 + r0, size); 10595 | } 10596 | 10597 | return std::numeric_limits<T>::quiet_NaN(); 10598 | } 10599 | 10600 | std::string str() const exprtk_override 10601 | { 10602 | return value_; 10603 | } 10604 | 10605 | char_cptr base() const exprtk_override 10606 | { 10607 | return &value_[0]; 10608 | } 10609 | 10610 | std::size_t size() const exprtk_override 10611 | { 10612 | return value_.size(); 10613 | } 10614 | 10615 | range_t& range_ref() exprtk_override 10616 | { 10617 | return range_; 10618 | } 10619 | 10620 | const range_t& range_ref() const exprtk_override 10621 | { 10622 | return range_; 10623 | } 10624 | 10625 | inline typename expression_node<T>::node_type type() const exprtk_override 10626 | { 10627 | return expression_node<T>::e_strgenrange; 10628 | } 10629 | 10630 | inline bool valid() const exprtk_override 10631 | { 10632 | return initialised_ && branch_.first; 10633 | } 10634 | 10635 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 10636 | { 10637 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 10638 | } 10639 | 10640 | std::size_t node_depth() const exprtk_override 10641 | { 10642 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 10643 | } 10644 | 10645 | private: 10646 | 10647 | bool initialised_; 10648 | branch_t branch_; 10649 | str_base_ptr str_base_ptr_; 10650 | irange_ptr str_range_ptr_; 10651 | mutable range_t base_range_; 10652 | mutable range_t range_; 10653 | mutable std::string value_; 10654 | }; 10655 | 10656 | template <typename T> 10657 | class string_concat_node exprtk_final 10658 | : public binary_node <T> 10659 | , public string_base_node<T> 10660 | , public range_interface <T> 10661 | { 10662 | public: 10663 | 10664 | typedef typename range_interface<T>::range_t range_t; 10665 | typedef range_interface<T> irange_t; 10666 | typedef irange_t* irange_ptr; 10667 | typedef range_t* range_ptr; 10668 | typedef expression_node <T>* expression_ptr; 10669 | typedef string_base_node<T>* str_base_ptr; 10670 | 10671 | using binary_node<T>::branch; 10672 | 10673 | string_concat_node(const operator_type& opr, 10674 | expression_ptr branch0, 10675 | expression_ptr branch1) 10676 | : binary_node<T>(opr, branch0, branch1) 10677 | , initialised_(false) 10678 | , str0_base_ptr_ (0) 10679 | , str1_base_ptr_ (0) 10680 | , str0_range_ptr_(0) 10681 | , str1_range_ptr_(0) 10682 | { 10683 | range_.n0_c = std::make_pair<bool,std::size_t>(true,0); 10684 | range_.n1_c = std::make_pair<bool,std::size_t>(true,0); 10685 | 10686 | range_.cache.first = range_.n0_c.second; 10687 | range_.cache.second = range_.n1_c.second; 10688 | 10689 | if (is_generally_string_node(branch(0))) 10690 | { 10691 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0)); 10692 | 10693 | if (0 == str0_base_ptr_) 10694 | return; 10695 | 10696 | str0_range_ptr_ = dynamic_cast<irange_ptr>(branch(0)); 10697 | 10698 | if (0 == str0_range_ptr_) 10699 | return; 10700 | } 10701 | 10702 | if (is_generally_string_node(branch(1))) 10703 | { 10704 | str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1)); 10705 | 10706 | if (0 == str1_base_ptr_) 10707 | return; 10708 | 10709 | str1_range_ptr_ = dynamic_cast<irange_ptr>(branch(1)); 10710 | 10711 | if (0 == str1_range_ptr_) 10712 | return; 10713 | } 10714 | 10715 | initialised_ = str0_base_ptr_ && 10716 | str1_base_ptr_ && 10717 | str0_range_ptr_ && 10718 | str1_range_ptr_ ; 10719 | 10720 | assert(valid()); 10721 | } 10722 | 10723 | inline T value() const exprtk_override 10724 | { 10725 | branch(0)->value(); 10726 | branch(1)->value(); 10727 | 10728 | std::size_t str0_r0 = 0; 10729 | std::size_t str0_r1 = 0; 10730 | 10731 | std::size_t str1_r0 = 0; 10732 | std::size_t str1_r1 = 0; 10733 | 10734 | const range_t& range0 = str0_range_ptr_->range_ref(); 10735 | const range_t& range1 = str1_range_ptr_->range_ref(); 10736 | 10737 | if ( 10738 | range0(str0_r0, str0_r1, str0_base_ptr_->size()) && 10739 | range1(str1_r0, str1_r1, str1_base_ptr_->size()) 10740 | ) 10741 | { 10742 | const std::size_t size0 = (str0_r1 - str0_r0); 10743 | const std::size_t size1 = (str1_r1 - str1_r0); 10744 | 10745 | value_.assign(str0_base_ptr_->base() + str0_r0, size0); 10746 | value_.append(str1_base_ptr_->base() + str1_r0, size1); 10747 | 10748 | range_.n1_c.second = value_.size(); 10749 | range_.cache.second = range_.n1_c.second; 10750 | } 10751 | 10752 | return std::numeric_limits<T>::quiet_NaN(); 10753 | } 10754 | 10755 | std::string str() const exprtk_override 10756 | { 10757 | return value_; 10758 | } 10759 | 10760 | char_cptr base() const exprtk_override 10761 | { 10762 | return &value_[0]; 10763 | } 10764 | 10765 | std::size_t size() const exprtk_override 10766 | { 10767 | return value_.size(); 10768 | } 10769 | 10770 | range_t& range_ref() exprtk_override 10771 | { 10772 | return range_; 10773 | } 10774 | 10775 | const range_t& range_ref() const exprtk_override 10776 | { 10777 | return range_; 10778 | } 10779 | 10780 | inline typename expression_node<T>::node_type type() const exprtk_override 10781 | { 10782 | return expression_node<T>::e_strconcat; 10783 | } 10784 | 10785 | inline bool valid() const exprtk_override 10786 | { 10787 | return initialised_ && binary_node<T>::valid(); 10788 | } 10789 | 10790 | private: 10791 | 10792 | bool initialised_; 10793 | str_base_ptr str0_base_ptr_; 10794 | str_base_ptr str1_base_ptr_; 10795 | irange_ptr str0_range_ptr_; 10796 | irange_ptr str1_range_ptr_; 10797 | mutable range_t range_; 10798 | mutable std::string value_; 10799 | }; 10800 | 10801 | template <typename T> 10802 | class swap_string_node exprtk_final 10803 | : public binary_node <T> 10804 | , public string_base_node<T> 10805 | , public range_interface <T> 10806 | { 10807 | public: 10808 | 10809 | typedef typename range_interface<T>::range_t range_t; 10810 | typedef range_t* range_ptr; 10811 | typedef range_interface<T> irange_t; 10812 | typedef irange_t* irange_ptr; 10813 | typedef expression_node <T>* expression_ptr; 10814 | typedef stringvar_node <T>* strvar_node_ptr; 10815 | typedef string_base_node<T>* str_base_ptr; 10816 | 10817 | using binary_node<T>::branch; 10818 | 10819 | swap_string_node(expression_ptr branch0, expression_ptr branch1) 10820 | : binary_node<T>(details::e_swap, branch0, branch1) 10821 | , initialised_(false) 10822 | , str0_node_ptr_(0) 10823 | , str1_node_ptr_(0) 10824 | { 10825 | if (is_string_node(branch(0))) 10826 | { 10827 | str0_node_ptr_ = static_cast<strvar_node_ptr>(branch(0)); 10828 | } 10829 | 10830 | if (is_string_node(branch(1))) 10831 | { 10832 | str1_node_ptr_ = static_cast<strvar_node_ptr>(branch(1)); 10833 | } 10834 | 10835 | initialised_ = (str0_node_ptr_ && str1_node_ptr_); 10836 | assert(valid()); 10837 | } 10838 | 10839 | inline T value() const exprtk_override 10840 | { 10841 | branch(0)->value(); 10842 | branch(1)->value(); 10843 | 10844 | std::swap(str0_node_ptr_->ref(), str1_node_ptr_->ref()); 10845 | 10846 | return std::numeric_limits<T>::quiet_NaN(); 10847 | } 10848 | 10849 | std::string str() const exprtk_override 10850 | { 10851 | return str0_node_ptr_->str(); 10852 | } 10853 | 10854 | char_cptr base() const exprtk_override 10855 | { 10856 | return str0_node_ptr_->base(); 10857 | } 10858 | 10859 | std::size_t size() const exprtk_override 10860 | { 10861 | return str0_node_ptr_->size(); 10862 | } 10863 | 10864 | range_t& range_ref() exprtk_override 10865 | { 10866 | return str0_node_ptr_->range_ref(); 10867 | } 10868 | 10869 | const range_t& range_ref() const exprtk_override 10870 | { 10871 | return str0_node_ptr_->range_ref(); 10872 | } 10873 | 10874 | inline typename expression_node<T>::node_type type() const exprtk_override 10875 | { 10876 | return expression_node<T>::e_strswap; 10877 | } 10878 | 10879 | inline bool valid() const exprtk_override 10880 | { 10881 | return initialised_ && binary_node<T>::valid(); 10882 | } 10883 | 10884 | private: 10885 | 10886 | bool initialised_; 10887 | strvar_node_ptr str0_node_ptr_; 10888 | strvar_node_ptr str1_node_ptr_; 10889 | }; 10890 | 10891 | template <typename T> 10892 | class swap_genstrings_node exprtk_final : public binary_node<T> 10893 | { 10894 | public: 10895 | 10896 | typedef typename range_interface<T>::range_t range_t; 10897 | typedef range_t* range_ptr; 10898 | typedef range_interface<T> irange_t; 10899 | typedef irange_t* irange_ptr; 10900 | typedef expression_node <T>* expression_ptr; 10901 | typedef string_base_node<T>* str_base_ptr; 10902 | 10903 | using binary_node<T>::branch; 10904 | 10905 | swap_genstrings_node(expression_ptr branch0, 10906 | expression_ptr branch1) 10907 | : binary_node<T>(details::e_default, branch0, branch1) 10908 | , str0_base_ptr_ (0) 10909 | , str1_base_ptr_ (0) 10910 | , str0_range_ptr_(0) 10911 | , str1_range_ptr_(0) 10912 | , initialised_(false) 10913 | { 10914 | if (is_generally_string_node(branch(0))) 10915 | { 10916 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0)); 10917 | 10918 | if (0 == str0_base_ptr_) 10919 | return; 10920 | 10921 | irange_ptr range = dynamic_cast<irange_ptr>(branch(0)); 10922 | 10923 | if (0 == range) 10924 | return; 10925 | 10926 | str0_range_ptr_ = &(range->range_ref()); 10927 | } 10928 | 10929 | if (is_generally_string_node(branch(1))) 10930 | { 10931 | str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1)); 10932 | 10933 | if (0 == str1_base_ptr_) 10934 | return; 10935 | 10936 | irange_ptr range = dynamic_cast<irange_ptr>(branch(1)); 10937 | 10938 | if (0 == range) 10939 | return; 10940 | 10941 | str1_range_ptr_ = &(range->range_ref()); 10942 | } 10943 | 10944 | initialised_ = str0_base_ptr_ && 10945 | str1_base_ptr_ && 10946 | str0_range_ptr_ && 10947 | str1_range_ptr_ ; 10948 | 10949 | assert(valid()); 10950 | } 10951 | 10952 | inline T value() const exprtk_override 10953 | { 10954 | branch(0)->value(); 10955 | branch(1)->value(); 10956 | 10957 | std::size_t str0_r0 = 0; 10958 | std::size_t str0_r1 = 0; 10959 | 10960 | std::size_t str1_r0 = 0; 10961 | std::size_t str1_r1 = 0; 10962 | 10963 | const range_t& range0 = (*str0_range_ptr_); 10964 | const range_t& range1 = (*str1_range_ptr_); 10965 | 10966 | if ( 10967 | range0(str0_r0, str0_r1, str0_base_ptr_->size()) && 10968 | range1(str1_r0, str1_r1, str1_base_ptr_->size()) 10969 | ) 10970 | { 10971 | const std::size_t size0 = range0.cache_size(); 10972 | const std::size_t size1 = range1.cache_size(); 10973 | const std::size_t max_size = std::min(size0,size1); 10974 | 10975 | char_ptr s0 = const_cast<char_ptr>(str0_base_ptr_->base() + str0_r0); 10976 | char_ptr s1 = const_cast<char_ptr>(str1_base_ptr_->base() + str1_r0); 10977 | 10978 | loop_unroll::details lud(max_size); 10979 | char_cptr upper_bound = s0 + lud.upper_bound; 10980 | 10981 | while (s0 < upper_bound) 10982 | { 10983 | #define exprtk_loop(N) \ 10984 | std::swap(s0[N], s1[N]); \ 10985 | 10986 | exprtk_loop( 0) exprtk_loop( 1) 10987 | exprtk_loop( 2) exprtk_loop( 3) 10988 | #ifndef exprtk_disable_superscalar_unroll 10989 | exprtk_loop( 4) exprtk_loop( 5) 10990 | exprtk_loop( 6) exprtk_loop( 7) 10991 | exprtk_loop( 8) exprtk_loop( 9) 10992 | exprtk_loop(10) exprtk_loop(11) 10993 | exprtk_loop(12) exprtk_loop(13) 10994 | exprtk_loop(14) exprtk_loop(15) 10995 | #endif 10996 | 10997 | s0 += lud.batch_size; 10998 | s1 += lud.batch_size; 10999 | } 11000 | 11001 | int i = 0; 11002 | 11003 | switch (lud.remainder) 11004 | { 11005 | #define case_stmt(N) \ 11006 | case N : { std::swap(s0[i], s1[i]); ++i; } \ 11007 | exprtk_fallthrough \ 11008 | 11009 | #ifndef exprtk_disable_superscalar_unroll 11010 | case_stmt(15) case_stmt(14) 11011 | case_stmt(13) case_stmt(12) 11012 | case_stmt(11) case_stmt(10) 11013 | case_stmt( 9) case_stmt( 8) 11014 | case_stmt( 7) case_stmt( 6) 11015 | case_stmt( 5) case_stmt( 4) 11016 | #endif 11017 | case_stmt( 3) case_stmt( 2) 11018 | case_stmt( 1) 11019 | default: break; 11020 | } 11021 | 11022 | #undef exprtk_loop 11023 | #undef case_stmt 11024 | } 11025 | 11026 | return std::numeric_limits<T>::quiet_NaN(); 11027 | } 11028 | 11029 | inline typename expression_node<T>::node_type type() const exprtk_override 11030 | { 11031 | return expression_node<T>::e_strswap; 11032 | } 11033 | 11034 | inline bool valid() const exprtk_override 11035 | { 11036 | return initialised_ && binary_node<T>::valid(); 11037 | } 11038 | 11039 | private: 11040 | 11041 | swap_genstrings_node(const swap_genstrings_node<T>&) exprtk_delete; 11042 | swap_genstrings_node<T>& operator=(const swap_genstrings_node<T>&) exprtk_delete; 11043 | 11044 | str_base_ptr str0_base_ptr_; 11045 | str_base_ptr str1_base_ptr_; 11046 | range_ptr str0_range_ptr_; 11047 | range_ptr str1_range_ptr_; 11048 | bool initialised_; 11049 | }; 11050 | 11051 | template <typename T> 11052 | class stringvar_size_node exprtk_final : public expression_node<T> 11053 | { 11054 | public: 11055 | 11056 | static const std::string null_value; 11057 | 11058 | explicit stringvar_size_node() 11059 | : value_(&null_value) 11060 | {} 11061 | 11062 | explicit stringvar_size_node(std::string& v) 11063 | : value_(&v) 11064 | {} 11065 | 11066 | inline T value() const exprtk_override 11067 | { 11068 | return T((*value_).size()); 11069 | } 11070 | 11071 | inline typename expression_node<T>::node_type type() const exprtk_override 11072 | { 11073 | return expression_node<T>::e_stringvarsize; 11074 | } 11075 | 11076 | private: 11077 | 11078 | const std::string* value_; 11079 | }; 11080 | 11081 | template <typename T> 11082 | const std::string stringvar_size_node<T>::null_value = std::string(""); 11083 | 11084 | template <typename T> 11085 | class string_size_node exprtk_final : public expression_node<T> 11086 | { 11087 | public: 11088 | 11089 | typedef expression_node <T>* expression_ptr; 11090 | typedef string_base_node<T>* str_base_ptr; 11091 | typedef std::pair<expression_ptr,bool> branch_t; 11092 | 11093 | explicit string_size_node(expression_ptr branch) 11094 | : str_base_ptr_(0) 11095 | { 11096 | construct_branch_pair(branch_, branch); 11097 | 11098 | if (is_generally_string_node(branch_.first)) 11099 | { 11100 | str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_.first); 11101 | } 11102 | 11103 | assert(valid()); 11104 | } 11105 | 11106 | inline T value() const exprtk_override 11107 | { 11108 | branch_.first->value(); 11109 | return T(str_base_ptr_->size()); 11110 | } 11111 | 11112 | inline typename expression_node<T>::node_type type() const exprtk_override 11113 | { 11114 | return expression_node<T>::e_stringsize; 11115 | } 11116 | 11117 | inline bool valid() const exprtk_override 11118 | { 11119 | return str_base_ptr_; 11120 | } 11121 | 11122 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 11123 | { 11124 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 11125 | } 11126 | 11127 | std::size_t node_depth() const exprtk_override 11128 | { 11129 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 11130 | } 11131 | 11132 | private: 11133 | 11134 | branch_t branch_; 11135 | str_base_ptr str_base_ptr_; 11136 | }; 11137 | 11138 | struct asn_assignment 11139 | { 11140 | static inline void execute(std::string& s, char_cptr data, const std::size_t size) 11141 | { s.assign(data,size); } 11142 | }; 11143 | 11144 | struct asn_addassignment 11145 | { 11146 | static inline void execute(std::string& s, char_cptr data, const std::size_t size) 11147 | { s.append(data,size); } 11148 | }; 11149 | 11150 | template <typename T, typename AssignmentProcess = asn_assignment> 11151 | class assignment_string_node exprtk_final 11152 | : public binary_node <T> 11153 | , public string_base_node<T> 11154 | , public range_interface <T> 11155 | { 11156 | public: 11157 | 11158 | typedef typename range_interface<T>::range_t range_t; 11159 | typedef range_t* range_ptr; 11160 | typedef range_interface <T> irange_t; 11161 | typedef irange_t* irange_ptr; 11162 | typedef expression_node <T>* expression_ptr; 11163 | typedef stringvar_node <T>* strvar_node_ptr; 11164 | typedef string_base_node<T>* str_base_ptr; 11165 | 11166 | using binary_node<T>::branch; 11167 | 11168 | assignment_string_node(const operator_type& opr, 11169 | expression_ptr branch0, 11170 | expression_ptr branch1) 11171 | : binary_node<T>(opr, branch0, branch1) 11172 | , initialised_(false) 11173 | , str0_base_ptr_ (0) 11174 | , str1_base_ptr_ (0) 11175 | , str0_node_ptr_ (0) 11176 | , str1_range_ptr_(0) 11177 | { 11178 | if (is_string_node(branch(0))) 11179 | { 11180 | str0_node_ptr_ = static_cast<strvar_node_ptr>(branch(0)); 11181 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0)); 11182 | } 11183 | 11184 | if (is_generally_string_node(branch(1))) 11185 | { 11186 | str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1)); 11187 | 11188 | if (0 == str1_base_ptr_) 11189 | return; 11190 | 11191 | irange_ptr range = dynamic_cast<irange_ptr>(branch(1)); 11192 | 11193 | if (0 == range) 11194 | return; 11195 | 11196 | str1_range_ptr_ = &(range->range_ref()); 11197 | } 11198 | 11199 | initialised_ = str0_base_ptr_ && 11200 | str1_base_ptr_ && 11201 | str0_node_ptr_ && 11202 | str1_range_ptr_ ; 11203 | 11204 | assert(valid()); 11205 | } 11206 | 11207 | inline T value() const exprtk_override 11208 | { 11209 | branch(1)->value(); 11210 | 11211 | std::size_t r0 = 0; 11212 | std::size_t r1 = 0; 11213 | 11214 | const range_t& range = (*str1_range_ptr_); 11215 | 11216 | if (range(r0, r1, str1_base_ptr_->size())) 11217 | { 11218 | AssignmentProcess::execute( 11219 | str0_node_ptr_->ref(), 11220 | str1_base_ptr_->base() + r0, (r1 - r0)); 11221 | 11222 | branch(0)->value(); 11223 | } 11224 | 11225 | return std::numeric_limits<T>::quiet_NaN(); 11226 | } 11227 | 11228 | std::string str() const exprtk_override 11229 | { 11230 | return str0_node_ptr_->str(); 11231 | } 11232 | 11233 | char_cptr base() const exprtk_override 11234 | { 11235 | return str0_node_ptr_->base(); 11236 | } 11237 | 11238 | std::size_t size() const exprtk_override 11239 | { 11240 | return str0_node_ptr_->size(); 11241 | } 11242 | 11243 | range_t& range_ref() exprtk_override 11244 | { 11245 | return str0_node_ptr_->range_ref(); 11246 | } 11247 | 11248 | const range_t& range_ref() const exprtk_override 11249 | { 11250 | return str0_node_ptr_->range_ref(); 11251 | } 11252 | 11253 | inline typename expression_node<T>::node_type type() const exprtk_override 11254 | { 11255 | return expression_node<T>::e_strass; 11256 | } 11257 | 11258 | inline bool valid() const exprtk_override 11259 | { 11260 | return initialised_ && binary_node<T>::valid(); 11261 | } 11262 | 11263 | private: 11264 | 11265 | bool initialised_; 11266 | str_base_ptr str0_base_ptr_; 11267 | str_base_ptr str1_base_ptr_; 11268 | strvar_node_ptr str0_node_ptr_; 11269 | range_ptr str1_range_ptr_; 11270 | }; 11271 | 11272 | template <typename T, typename AssignmentProcess = asn_assignment> 11273 | class assignment_string_range_node exprtk_final 11274 | : public binary_node <T> 11275 | , public string_base_node<T> 11276 | , public range_interface <T> 11277 | { 11278 | public: 11279 | 11280 | typedef typename range_interface<T>::range_t range_t; 11281 | typedef range_t* range_ptr; 11282 | typedef range_interface <T> irange_t; 11283 | typedef irange_t* irange_ptr; 11284 | typedef expression_node <T>* expression_ptr; 11285 | typedef stringvar_node <T>* strvar_node_ptr; 11286 | typedef string_range_node<T>* str_rng_node_ptr; 11287 | typedef string_base_node <T>* str_base_ptr; 11288 | 11289 | using binary_node<T>::branch; 11290 | 11291 | assignment_string_range_node(const operator_type& opr, 11292 | expression_ptr branch0, 11293 | expression_ptr branch1) 11294 | : binary_node<T>(opr, branch0, branch1) 11295 | , initialised_(false) 11296 | , str0_base_ptr_ (0) 11297 | , str1_base_ptr_ (0) 11298 | , str0_rng_node_ptr_(0) 11299 | , str0_range_ptr_ (0) 11300 | , str1_range_ptr_ (0) 11301 | { 11302 | if (is_string_range_node(branch(0))) 11303 | { 11304 | str0_rng_node_ptr_ = static_cast<str_rng_node_ptr>(branch(0)); 11305 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0)); 11306 | irange_ptr range = dynamic_cast<irange_ptr>(branch(0)); 11307 | 11308 | if (0 == range) 11309 | return; 11310 | 11311 | str0_range_ptr_ = &(range->range_ref()); 11312 | } 11313 | 11314 | if (is_generally_string_node(branch(1))) 11315 | { 11316 | str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1)); 11317 | 11318 | if (0 == str1_base_ptr_) 11319 | return; 11320 | 11321 | irange_ptr range = dynamic_cast<irange_ptr>(branch(1)); 11322 | 11323 | if (0 == range) 11324 | return; 11325 | 11326 | str1_range_ptr_ = &(range->range_ref()); 11327 | } 11328 | 11329 | initialised_ = str0_base_ptr_ && 11330 | str1_base_ptr_ && 11331 | str0_rng_node_ptr_ && 11332 | str0_range_ptr_ && 11333 | str1_range_ptr_ ; 11334 | 11335 | assert(valid()); 11336 | } 11337 | 11338 | inline T value() const exprtk_override 11339 | { 11340 | branch(0)->value(); 11341 | branch(1)->value(); 11342 | 11343 | std::size_t s0_r0 = 0; 11344 | std::size_t s0_r1 = 0; 11345 | 11346 | std::size_t s1_r0 = 0; 11347 | std::size_t s1_r1 = 0; 11348 | 11349 | const range_t& range0 = (*str0_range_ptr_); 11350 | const range_t& range1 = (*str1_range_ptr_); 11351 | 11352 | if ( 11353 | range0(s0_r0, s0_r1, str0_base_ptr_->size()) && 11354 | range1(s1_r0, s1_r1, str1_base_ptr_->size()) 11355 | ) 11356 | { 11357 | const std::size_t size = std::min((s0_r1 - s0_r0), (s1_r1 - s1_r0)); 11358 | 11359 | std::copy( 11360 | str1_base_ptr_->base() + s1_r0, 11361 | str1_base_ptr_->base() + s1_r0 + size, 11362 | const_cast<char_ptr>(base() + s0_r0)); 11363 | } 11364 | 11365 | return std::numeric_limits<T>::quiet_NaN(); 11366 | } 11367 | 11368 | std::string str() const exprtk_override 11369 | { 11370 | return str0_base_ptr_->str(); 11371 | } 11372 | 11373 | char_cptr base() const exprtk_override 11374 | { 11375 | return str0_base_ptr_->base(); 11376 | } 11377 | 11378 | std::size_t size() const exprtk_override 11379 | { 11380 | return str0_base_ptr_->size(); 11381 | } 11382 | 11383 | range_t& range_ref() exprtk_override 11384 | { 11385 | return str0_rng_node_ptr_->range_ref(); 11386 | } 11387 | 11388 | const range_t& range_ref() const exprtk_override 11389 | { 11390 | return str0_rng_node_ptr_->range_ref(); 11391 | } 11392 | 11393 | inline typename expression_node<T>::node_type type() const exprtk_override 11394 | { 11395 | return expression_node<T>::e_strass; 11396 | } 11397 | 11398 | inline bool valid() const exprtk_override 11399 | { 11400 | return initialised_ && binary_node<T>::valid(); 11401 | } 11402 | 11403 | private: 11404 | 11405 | bool initialised_; 11406 | str_base_ptr str0_base_ptr_; 11407 | str_base_ptr str1_base_ptr_; 11408 | str_rng_node_ptr str0_rng_node_ptr_; 11409 | range_ptr str0_range_ptr_; 11410 | range_ptr str1_range_ptr_; 11411 | }; 11412 | 11413 | template <typename T> 11414 | class conditional_string_node exprtk_final 11415 | : public trinary_node <T> 11416 | , public string_base_node<T> 11417 | , public range_interface <T> 11418 | { 11419 | public: 11420 | 11421 | typedef typename range_interface<T>::range_t range_t; 11422 | typedef range_t* range_ptr; 11423 | typedef range_interface <T> irange_t; 11424 | typedef irange_t* irange_ptr; 11425 | typedef expression_node <T>* expression_ptr; 11426 | typedef string_base_node<T>* str_base_ptr; 11427 | 11428 | conditional_string_node(expression_ptr condition, 11429 | expression_ptr consequent, 11430 | expression_ptr alternative) 11431 | : trinary_node<T>(details::e_default, consequent, alternative, condition) 11432 | , initialised_(false) 11433 | , str0_base_ptr_ (0) 11434 | , str1_base_ptr_ (0) 11435 | , str0_range_ptr_(0) 11436 | , str1_range_ptr_(0) 11437 | , condition_ (condition ) 11438 | , consequent_ (consequent ) 11439 | , alternative_(alternative) 11440 | { 11441 | range_.n0_c = std::make_pair<bool,std::size_t>(true,0); 11442 | range_.n1_c = std::make_pair<bool,std::size_t>(true,0); 11443 | 11444 | range_.cache.first = range_.n0_c.second; 11445 | range_.cache.second = range_.n1_c.second; 11446 | 11447 | if (is_generally_string_node(trinary_node<T>::branch_[0].first)) 11448 | { 11449 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(trinary_node<T>::branch_[0].first); 11450 | 11451 | if (0 == str0_base_ptr_) 11452 | return; 11453 | 11454 | str0_range_ptr_ = dynamic_cast<irange_ptr>(trinary_node<T>::branch_[0].first); 11455 | 11456 | if (0 == str0_range_ptr_) 11457 | return; 11458 | } 11459 | 11460 | if (is_generally_string_node(trinary_node<T>::branch_[1].first)) 11461 | { 11462 | str1_base_ptr_ = dynamic_cast<str_base_ptr>(trinary_node<T>::branch_[1].first); 11463 | 11464 | if (0 == str1_base_ptr_) 11465 | return; 11466 | 11467 | str1_range_ptr_ = dynamic_cast<irange_ptr>(trinary_node<T>::branch_[1].first); 11468 | 11469 | if (0 == str1_range_ptr_) 11470 | return; 11471 | } 11472 | 11473 | initialised_ = str0_base_ptr_ && 11474 | str1_base_ptr_ && 11475 | str0_range_ptr_ && 11476 | str1_range_ptr_ ; 11477 | 11478 | assert(valid()); 11479 | } 11480 | 11481 | inline T value() const exprtk_override 11482 | { 11483 | std::size_t r0 = 0; 11484 | std::size_t r1 = 0; 11485 | 11486 | if (is_true(condition_)) 11487 | { 11488 | consequent_->value(); 11489 | 11490 | const range_t& range = str0_range_ptr_->range_ref(); 11491 | 11492 | if (range(r0, r1, str0_base_ptr_->size())) 11493 | { 11494 | const std::size_t size = (r1 - r0); 11495 | 11496 | value_.assign(str0_base_ptr_->base() + r0, size); 11497 | 11498 | range_.n1_c.second = value_.size(); 11499 | range_.cache.second = range_.n1_c.second; 11500 | 11501 | return T(1); 11502 | } 11503 | } 11504 | else 11505 | { 11506 | alternative_->value(); 11507 | 11508 | const range_t& range = str1_range_ptr_->range_ref(); 11509 | 11510 | if (range(r0, r1, str1_base_ptr_->size())) 11511 | { 11512 | const std::size_t size = (r1 - r0); 11513 | 11514 | value_.assign(str1_base_ptr_->base() + r0, size); 11515 | 11516 | range_.n1_c.second = value_.size(); 11517 | range_.cache.second = range_.n1_c.second; 11518 | 11519 | return T(0); 11520 | } 11521 | } 11522 | 11523 | return std::numeric_limits<T>::quiet_NaN(); 11524 | } 11525 | 11526 | std::string str() const exprtk_override 11527 | { 11528 | return value_; 11529 | } 11530 | 11531 | char_cptr base() const exprtk_override 11532 | { 11533 | return &value_[0]; 11534 | } 11535 | 11536 | std::size_t size() const exprtk_override 11537 | { 11538 | return value_.size(); 11539 | } 11540 | 11541 | range_t& range_ref() exprtk_override 11542 | { 11543 | return range_; 11544 | } 11545 | 11546 | const range_t& range_ref() const exprtk_override 11547 | { 11548 | return range_; 11549 | } 11550 | 11551 | inline typename expression_node<T>::node_type type() const exprtk_override 11552 | { 11553 | return expression_node<T>::e_strcondition; 11554 | } 11555 | 11556 | inline bool valid() const exprtk_override 11557 | { 11558 | return 11559 | initialised_ && 11560 | condition_ && condition_ ->valid() && 11561 | consequent_ && consequent_ ->valid() && 11562 | alternative_&& alternative_->valid() ; 11563 | } 11564 | 11565 | private: 11566 | 11567 | bool initialised_; 11568 | str_base_ptr str0_base_ptr_; 11569 | str_base_ptr str1_base_ptr_; 11570 | irange_ptr str0_range_ptr_; 11571 | irange_ptr str1_range_ptr_; 11572 | mutable range_t range_; 11573 | mutable std::string value_; 11574 | 11575 | expression_ptr condition_; 11576 | expression_ptr consequent_; 11577 | expression_ptr alternative_; 11578 | }; 11579 | 11580 | template <typename T> 11581 | class cons_conditional_str_node exprtk_final 11582 | : public binary_node <T> 11583 | , public string_base_node<T> 11584 | , public range_interface <T> 11585 | { 11586 | public: 11587 | 11588 | typedef typename range_interface<T>::range_t range_t; 11589 | typedef range_t* range_ptr; 11590 | typedef range_interface <T> irange_t; 11591 | typedef irange_t* irange_ptr; 11592 | typedef expression_node <T>* expression_ptr; 11593 | typedef string_base_node<T>* str_base_ptr; 11594 | 11595 | using binary_node<T>::branch; 11596 | 11597 | cons_conditional_str_node(expression_ptr condition, 11598 | expression_ptr consequent) 11599 | : binary_node<T>(details::e_default, consequent, condition) 11600 | , initialised_(false) 11601 | , str0_base_ptr_ (0) 11602 | , str0_range_ptr_(0) 11603 | , condition_ (condition ) 11604 | , consequent_(consequent) 11605 | { 11606 | range_.n0_c = std::make_pair<bool,std::size_t>(true,0); 11607 | range_.n1_c = std::make_pair<bool,std::size_t>(true,0); 11608 | 11609 | range_.cache.first = range_.n0_c.second; 11610 | range_.cache.second = range_.n1_c.second; 11611 | 11612 | if (is_generally_string_node(branch(0))) 11613 | { 11614 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0)); 11615 | 11616 | if (0 == str0_base_ptr_) 11617 | return; 11618 | 11619 | str0_range_ptr_ = dynamic_cast<irange_ptr>(branch(0)); 11620 | 11621 | if (0 == str0_range_ptr_) 11622 | return; 11623 | } 11624 | 11625 | initialised_ = str0_base_ptr_ && str0_range_ptr_ ; 11626 | assert(valid()); 11627 | } 11628 | 11629 | inline T value() const exprtk_override 11630 | { 11631 | if (is_true(condition_)) 11632 | { 11633 | consequent_->value(); 11634 | 11635 | const range_t& range = str0_range_ptr_->range_ref(); 11636 | 11637 | std::size_t r0 = 0; 11638 | std::size_t r1 = 0; 11639 | 11640 | if (range(r0, r1, str0_base_ptr_->size())) 11641 | { 11642 | const std::size_t size = (r1 - r0); 11643 | 11644 | value_.assign(str0_base_ptr_->base() + r0, size); 11645 | 11646 | range_.n1_c.second = value_.size(); 11647 | range_.cache.second = range_.n1_c.second; 11648 | 11649 | return T(1); 11650 | } 11651 | } 11652 | 11653 | return std::numeric_limits<T>::quiet_NaN(); 11654 | } 11655 | 11656 | std::string str() const 11657 | { 11658 | return value_; 11659 | } 11660 | 11661 | char_cptr base() const 11662 | { 11663 | return &value_[0]; 11664 | } 11665 | 11666 | std::size_t size() const 11667 | { 11668 | return value_.size(); 11669 | } 11670 | 11671 | range_t& range_ref() 11672 | { 11673 | return range_; 11674 | } 11675 | 11676 | const range_t& range_ref() const 11677 | { 11678 | return range_; 11679 | } 11680 | 11681 | inline typename expression_node<T>::node_type type() const exprtk_override 11682 | { 11683 | return expression_node<T>::e_strccondition; 11684 | } 11685 | 11686 | inline bool valid() const exprtk_override 11687 | { 11688 | return 11689 | initialised_ && 11690 | condition_ && condition_ ->valid() && 11691 | consequent_ && consequent_ ->valid() ; 11692 | } 11693 | 11694 | private: 11695 | 11696 | bool initialised_; 11697 | str_base_ptr str0_base_ptr_; 11698 | irange_ptr str0_range_ptr_; 11699 | mutable range_t range_; 11700 | mutable std::string value_; 11701 | 11702 | expression_ptr condition_; 11703 | expression_ptr consequent_; 11704 | }; 11705 | 11706 | template <typename T, typename VarArgFunction> 11707 | class str_vararg_node exprtk_final 11708 | : public expression_node <T> 11709 | , public string_base_node<T> 11710 | , public range_interface <T> 11711 | { 11712 | public: 11713 | 11714 | typedef typename range_interface<T>::range_t range_t; 11715 | typedef range_t* range_ptr; 11716 | typedef range_interface <T> irange_t; 11717 | typedef irange_t* irange_ptr; 11718 | typedef expression_node <T>* expression_ptr; 11719 | typedef string_base_node<T>* str_base_ptr; 11720 | typedef std::pair<expression_ptr,bool> branch_t; 11721 | 11722 | template <typename Allocator, 11723 | template <typename, typename> class Sequence> 11724 | explicit str_vararg_node(const Sequence<expression_ptr,Allocator>& arg_list) 11725 | : initialised_(false) 11726 | , str_base_ptr_ (0) 11727 | , str_range_ptr_(0) 11728 | { 11729 | construct_branch_pair(final_node_, const_cast<expression_ptr>(arg_list.back())); 11730 | 11731 | if (0 == final_node_.first) 11732 | return; 11733 | else if (!is_generally_string_node(final_node_.first)) 11734 | return; 11735 | 11736 | str_base_ptr_ = dynamic_cast<str_base_ptr>(final_node_.first); 11737 | 11738 | if (0 == str_base_ptr_) 11739 | return; 11740 | 11741 | str_range_ptr_ = dynamic_cast<irange_ptr>(final_node_.first); 11742 | 11743 | if (0 == str_range_ptr_) 11744 | return; 11745 | 11746 | if (arg_list.size() > 1) 11747 | { 11748 | const std::size_t arg_list_size = arg_list.size() - 1; 11749 | 11750 | arg_list_.resize(arg_list_size); 11751 | 11752 | for (std::size_t i = 0; i < arg_list_size; ++i) 11753 | { 11754 | if (arg_list[i] && arg_list[i]->valid()) 11755 | { 11756 | construct_branch_pair(arg_list_[i], arg_list[i]); 11757 | } 11758 | else 11759 | { 11760 | arg_list_.clear(); 11761 | return; 11762 | } 11763 | } 11764 | 11765 | initialised_ = true; 11766 | } 11767 | 11768 | initialised_ &= str_base_ptr_ && str_range_ptr_; 11769 | assert(valid()); 11770 | } 11771 | 11772 | inline T value() const exprtk_override 11773 | { 11774 | if (!arg_list_.empty()) 11775 | { 11776 | VarArgFunction::process(arg_list_); 11777 | } 11778 | 11779 | final_node_.first->value(); 11780 | 11781 | return std::numeric_limits<T>::quiet_NaN(); 11782 | } 11783 | 11784 | std::string str() const exprtk_override 11785 | { 11786 | return str_base_ptr_->str(); 11787 | } 11788 | 11789 | char_cptr base() const exprtk_override 11790 | { 11791 | return str_base_ptr_->base(); 11792 | } 11793 | 11794 | std::size_t size() const exprtk_override 11795 | { 11796 | return str_base_ptr_->size(); 11797 | } 11798 | 11799 | range_t& range_ref() exprtk_override 11800 | { 11801 | return str_range_ptr_->range_ref(); 11802 | } 11803 | 11804 | const range_t& range_ref() const exprtk_override 11805 | { 11806 | return str_range_ptr_->range_ref(); 11807 | } 11808 | 11809 | inline typename expression_node<T>::node_type type() const exprtk_override 11810 | { 11811 | return expression_node<T>::e_stringvararg; 11812 | } 11813 | 11814 | inline bool valid() const exprtk_override 11815 | { 11816 | return 11817 | initialised_ && 11818 | final_node_.first && final_node_.first->valid(); 11819 | } 11820 | 11821 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 11822 | { 11823 | expression_node<T>::ndb_t::collect(final_node_ , node_delete_list); 11824 | expression_node<T>::ndb_t::collect(arg_list_ , node_delete_list); 11825 | } 11826 | 11827 | std::size_t node_depth() const exprtk_override 11828 | { 11829 | return std::max( 11830 | expression_node<T>::ndb_t::compute_node_depth(final_node_), 11831 | expression_node<T>::ndb_t::compute_node_depth(arg_list_ )); 11832 | } 11833 | 11834 | private: 11835 | 11836 | bool initialised_; 11837 | branch_t final_node_; 11838 | str_base_ptr str_base_ptr_; 11839 | irange_ptr str_range_ptr_; 11840 | std::vector<branch_t> arg_list_; 11841 | }; 11842 | #endif 11843 | 11844 | template <typename T> 11845 | class assert_node exprtk_final : public expression_node<T> 11846 | { 11847 | public: 11848 | 11849 | typedef expression_node<T>* expression_ptr; 11850 | typedef std::pair<expression_ptr,bool> branch_t; 11851 | typedef string_base_node<T>* str_base_ptr; 11852 | typedef assert_check::assert_context assert_context_t; 11853 | 11854 | assert_node(expression_ptr assert_condition_node, 11855 | expression_ptr assert_message_node, 11856 | assert_check_ptr assert_check, 11857 | const assert_context_t& context) 11858 | : assert_message_str_base_(0) 11859 | , assert_check_(assert_check) 11860 | , context_(context) 11861 | { 11862 | construct_branch_pair(assert_condition_node_, assert_condition_node); 11863 | construct_branch_pair(assert_message_node_ , assert_message_node ); 11864 | 11865 | #ifndef exprtk_disable_string_capabilities 11866 | if ( 11867 | assert_message_node_.first && 11868 | details::is_generally_string_node(assert_message_node_.first) 11869 | ) 11870 | { 11871 | assert_message_str_base_ = dynamic_cast<str_base_ptr>(assert_message_node_.first); 11872 | } 11873 | #endif 11874 | 11875 | assert(valid()); 11876 | } 11877 | 11878 | inline T value() const exprtk_override 11879 | { 11880 | if (details::is_true(assert_condition_node_.first->value())) 11881 | { 11882 | return T(1); 11883 | } 11884 | 11885 | #ifndef exprtk_disable_string_capabilities 11886 | if (assert_message_node_.first) 11887 | { 11888 | assert_message_node_.first->value(); 11889 | assert(assert_message_str_base_); 11890 | context_.message = assert_message_str_base_->str(); 11891 | } 11892 | #endif 11893 | 11894 | assert_check_->handle_assert(context_); 11895 | return T(0); 11896 | } 11897 | 11898 | inline typename expression_node<T>::node_type type() const exprtk_override 11899 | { 11900 | return expression_node<T>::e_assert; 11901 | } 11902 | 11903 | inline bool valid() const exprtk_override 11904 | { 11905 | return ( 11906 | assert_check_ && 11907 | assert_condition_node_.first && 11908 | assert_condition_node_.first->valid() 11909 | ) && 11910 | ( 11911 | (0 == assert_message_node_.first) || 11912 | ( 11913 | assert_message_node_.first && 11914 | assert_message_str_base_ && 11915 | assert_message_node_.first->valid() && 11916 | details::is_generally_string_node(assert_message_node_.first) 11917 | ) 11918 | ); 11919 | } 11920 | 11921 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 11922 | { 11923 | expression_node<T>::ndb_t::collect(assert_condition_node_, node_delete_list); 11924 | expression_node<T>::ndb_t::collect(assert_message_node_ , node_delete_list); 11925 | } 11926 | 11927 | std::size_t node_depth() const exprtk_override 11928 | { 11929 | return expression_node<T>::ndb_t::compute_node_depth 11930 | (assert_condition_node_, assert_message_node_); 11931 | } 11932 | 11933 | private: 11934 | 11935 | branch_t assert_condition_node_; 11936 | branch_t assert_message_node_; 11937 | str_base_ptr assert_message_str_base_; 11938 | assert_check_ptr assert_check_; 11939 | mutable assert_context_t context_; 11940 | }; 11941 | 11942 | template <typename T, std::size_t N> 11943 | inline T axn(const T a, const T x) 11944 | { 11945 | // a*x^n 11946 | return a * exprtk::details::numeric::fast_exp<T,N>::result(x); 11947 | } 11948 | 11949 | template <typename T, std::size_t N> 11950 | inline T axnb(const T a, const T x, const T b) 11951 | { 11952 | // a*x^n+b 11953 | return a * exprtk::details::numeric::fast_exp<T,N>::result(x) + b; 11954 | } 11955 | 11956 | template <typename T> 11957 | struct sf_base 11958 | { 11959 | typedef typename details::functor_t<T>::Type Type; 11960 | typedef typename details::functor_t<T> functor_t; 11961 | typedef typename functor_t::qfunc_t quaternary_functor_t; 11962 | typedef typename functor_t::tfunc_t trinary_functor_t; 11963 | typedef typename functor_t::bfunc_t binary_functor_t; 11964 | typedef typename functor_t::ufunc_t unary_functor_t; 11965 | }; 11966 | 11967 | #define define_sfop3(NN, OP0, OP1) \ 11968 | template <typename T> \ 11969 | struct sf##NN##_op : public sf_base<T> \ 11970 | { \ 11971 | typedef typename sf_base<T>::Type const Type; \ 11972 | static inline T process(Type x, Type y, Type z) \ 11973 | { \ 11974 | return (OP0); \ 11975 | } \ 11976 | static inline std::string id() \ 11977 | { \ 11978 | return (OP1); \ 11979 | } \ 11980 | }; \ 11981 | 11982 | define_sfop3(00,(x + y) / z ,"(t+t)/t") 11983 | define_sfop3(01,(x + y) * z ,"(t+t)*t") 11984 | define_sfop3(02,(x + y) - z ,"(t+t)-t") 11985 | define_sfop3(03,(x + y) + z ,"(t+t)+t") 11986 | define_sfop3(04,(x - y) + z ,"(t-t)+t") 11987 | define_sfop3(05,(x - y) / z ,"(t-t)/t") 11988 | define_sfop3(06,(x - y) * z ,"(t-t)*t") 11989 | define_sfop3(07,(x * y) + z ,"(t*t)+t") 11990 | define_sfop3(08,(x * y) - z ,"(t*t)-t") 11991 | define_sfop3(09,(x * y) / z ,"(t*t)/t") 11992 | define_sfop3(10,(x * y) * z ,"(t*t)*t") 11993 | define_sfop3(11,(x / y) + z ,"(t/t)+t") 11994 | define_sfop3(12,(x / y) - z ,"(t/t)-t") 11995 | define_sfop3(13,(x / y) / z ,"(t/t)/t") 11996 | define_sfop3(14,(x / y) * z ,"(t/t)*t") 11997 | define_sfop3(15,x / (y + z) ,"t/(t+t)") 11998 | define_sfop3(16,x / (y - z) ,"t/(t-t)") 11999 | define_sfop3(17,x / (y * z) ,"t/(t*t)") 12000 | define_sfop3(18,x / (y / z) ,"t/(t/t)") 12001 | define_sfop3(19,x * (y + z) ,"t*(t+t)") 12002 | define_sfop3(20,x * (y - z) ,"t*(t-t)") 12003 | define_sfop3(21,x * (y * z) ,"t*(t*t)") 12004 | define_sfop3(22,x * (y / z) ,"t*(t/t)") 12005 | define_sfop3(23,x - (y + z) ,"t-(t+t)") 12006 | define_sfop3(24,x - (y - z) ,"t-(t-t)") 12007 | define_sfop3(25,x - (y / z) ,"t-(t/t)") 12008 | define_sfop3(26,x - (y * z) ,"t-(t*t)") 12009 | define_sfop3(27,x + (y * z) ,"t+(t*t)") 12010 | define_sfop3(28,x + (y / z) ,"t+(t/t)") 12011 | define_sfop3(29,x + (y + z) ,"t+(t+t)") 12012 | define_sfop3(30,x + (y - z) ,"t+(t-t)") 12013 | define_sfop3(31,(axnb<T,2>(x,y,z))," ") 12014 | define_sfop3(32,(axnb<T,3>(x,y,z))," ") 12015 | define_sfop3(33,(axnb<T,4>(x,y,z))," ") 12016 | define_sfop3(34,(axnb<T,5>(x,y,z))," ") 12017 | define_sfop3(35,(axnb<T,6>(x,y,z))," ") 12018 | define_sfop3(36,(axnb<T,7>(x,y,z))," ") 12019 | define_sfop3(37,(axnb<T,8>(x,y,z))," ") 12020 | define_sfop3(38,(axnb<T,9>(x,y,z))," ") 12021 | define_sfop3(39,x * numeric::log(y) + z,"") 12022 | define_sfop3(40,x * numeric::log(y) - z,"") 12023 | define_sfop3(41,x * numeric::log10(y) + z,"") 12024 | define_sfop3(42,x * numeric::log10(y) - z,"") 12025 | define_sfop3(43,x * numeric::sin(y) + z ,"") 12026 | define_sfop3(44,x * numeric::sin(y) - z ,"") 12027 | define_sfop3(45,x * numeric::cos(y) + z ,"") 12028 | define_sfop3(46,x * numeric::cos(y) - z ,"") 12029 | define_sfop3(47,details::is_true(x) ? y : z,"") 12030 | 12031 | #define define_sfop4(NN, OP0, OP1) \ 12032 | template <typename T> \ 12033 | struct sf##NN##_op : public sf_base<T> \ 12034 | { \ 12035 | typedef typename sf_base<T>::Type const Type; \ 12036 | static inline T process(Type x, Type y, Type z, Type w) \ 12037 | { \ 12038 | return (OP0); \ 12039 | } \ 12040 | static inline std::string id() \ 12041 | { \ 12042 | return (OP1); \ 12043 | } \ 12044 | }; \ 12045 | 12046 | define_sfop4(48,(x + ((y + z) / w)),"t+((t+t)/t)") 12047 | define_sfop4(49,(x + ((y + z) * w)),"t+((t+t)*t)") 12048 | define_sfop4(50,(x + ((y - z) / w)),"t+((t-t)/t)") 12049 | define_sfop4(51,(x + ((y - z) * w)),"t+((t-t)*t)") 12050 | define_sfop4(52,(x + ((y * z) / w)),"t+((t*t)/t)") 12051 | define_sfop4(53,(x + ((y * z) * w)),"t+((t*t)*t)") 12052 | define_sfop4(54,(x + ((y / z) + w)),"t+((t/t)+t)") 12053 | define_sfop4(55,(x + ((y / z) / w)),"t+((t/t)/t)") 12054 | define_sfop4(56,(x + ((y / z) * w)),"t+((t/t)*t)") 12055 | define_sfop4(57,(x - ((y + z) / w)),"t-((t+t)/t)") 12056 | define_sfop4(58,(x - ((y + z) * w)),"t-((t+t)*t)") 12057 | define_sfop4(59,(x - ((y - z) / w)),"t-((t-t)/t)") 12058 | define_sfop4(60,(x - ((y - z) * w)),"t-((t-t)*t)") 12059 | define_sfop4(61,(x - ((y * z) / w)),"t-((t*t)/t)") 12060 | define_sfop4(62,(x - ((y * z) * w)),"t-((t*t)*t)") 12061 | define_sfop4(63,(x - ((y / z) / w)),"t-((t/t)/t)") 12062 | define_sfop4(64,(x - ((y / z) * w)),"t-((t/t)*t)") 12063 | define_sfop4(65,(((x + y) * z) - w),"((t+t)*t)-t") 12064 | define_sfop4(66,(((x - y) * z) - w),"((t-t)*t)-t") 12065 | define_sfop4(67,(((x * y) * z) - w),"((t*t)*t)-t") 12066 | define_sfop4(68,(((x / y) * z) - w),"((t/t)*t)-t") 12067 | define_sfop4(69,(((x + y) / z) - w),"((t+t)/t)-t") 12068 | define_sfop4(70,(((x - y) / z) - w),"((t-t)/t)-t") 12069 | define_sfop4(71,(((x * y) / z) - w),"((t*t)/t)-t") 12070 | define_sfop4(72,(((x / y) / z) - w),"((t/t)/t)-t") 12071 | define_sfop4(73,((x * y) + (z * w)),"(t*t)+(t*t)") 12072 | define_sfop4(74,((x * y) - (z * w)),"(t*t)-(t*t)") 12073 | define_sfop4(75,((x * y) + (z / w)),"(t*t)+(t/t)") 12074 | define_sfop4(76,((x * y) - (z / w)),"(t*t)-(t/t)") 12075 | define_sfop4(77,((x / y) + (z / w)),"(t/t)+(t/t)") 12076 | define_sfop4(78,((x / y) - (z / w)),"(t/t)-(t/t)") 12077 | define_sfop4(79,((x / y) - (z * w)),"(t/t)-(t*t)") 12078 | define_sfop4(80,(x / (y + (z * w))),"t/(t+(t*t))") 12079 | define_sfop4(81,(x / (y - (z * w))),"t/(t-(t*t))") 12080 | define_sfop4(82,(x * (y + (z * w))),"t*(t+(t*t))") 12081 | define_sfop4(83,(x * (y - (z * w))),"t*(t-(t*t))") 12082 | 12083 | define_sfop4(84,(axn<T,2>(x,y) + axn<T,2>(z,w)),"") 12084 | define_sfop4(85,(axn<T,3>(x,y) + axn<T,3>(z,w)),"") 12085 | define_sfop4(86,(axn<T,4>(x,y) + axn<T,4>(z,w)),"") 12086 | define_sfop4(87,(axn<T,5>(x,y) + axn<T,5>(z,w)),"") 12087 | define_sfop4(88,(axn<T,6>(x,y) + axn<T,6>(z,w)),"") 12088 | define_sfop4(89,(axn<T,7>(x,y) + axn<T,7>(z,w)),"") 12089 | define_sfop4(90,(axn<T,8>(x,y) + axn<T,8>(z,w)),"") 12090 | define_sfop4(91,(axn<T,9>(x,y) + axn<T,9>(z,w)),"") 12091 | define_sfop4(92,((details::is_true(x) && details::is_true(y)) ? z : w),"") 12092 | define_sfop4(93,((details::is_true(x) || details::is_true(y)) ? z : w),"") 12093 | define_sfop4(94,((x < y) ? z : w),"") 12094 | define_sfop4(95,((x <= y) ? z : w),"") 12095 | define_sfop4(96,((x > y) ? z : w),"") 12096 | define_sfop4(97,((x >= y) ? z : w),"") 12097 | define_sfop4(98,(details::is_true(numeric::equal(x,y)) ? z : w),"") 12098 | define_sfop4(99,(x * numeric::sin(y) + z * numeric::cos(w)),"") 12099 | 12100 | define_sfop4(ext00,((x + y) - (z * w)),"(t+t)-(t*t)") 12101 | define_sfop4(ext01,((x + y) - (z / w)),"(t+t)-(t/t)") 12102 | define_sfop4(ext02,((x + y) + (z * w)),"(t+t)+(t*t)") 12103 | define_sfop4(ext03,((x + y) + (z / w)),"(t+t)+(t/t)") 12104 | define_sfop4(ext04,((x - y) + (z * w)),"(t-t)+(t*t)") 12105 | define_sfop4(ext05,((x - y) + (z / w)),"(t-t)+(t/t)") 12106 | define_sfop4(ext06,((x - y) - (z * w)),"(t-t)-(t*t)") 12107 | define_sfop4(ext07,((x - y) - (z / w)),"(t-t)-(t/t)") 12108 | define_sfop4(ext08,((x + y) - (z - w)),"(t+t)-(t-t)") 12109 | define_sfop4(ext09,((x + y) + (z - w)),"(t+t)+(t-t)") 12110 | define_sfop4(ext10,((x + y) + (z + w)),"(t+t)+(t+t)") 12111 | define_sfop4(ext11,((x + y) * (z - w)),"(t+t)*(t-t)") 12112 | define_sfop4(ext12,((x + y) / (z - w)),"(t+t)/(t-t)") 12113 | define_sfop4(ext13,((x - y) - (z + w)),"(t-t)-(t+t)") 12114 | define_sfop4(ext14,((x - y) + (z + w)),"(t-t)+(t+t)") 12115 | define_sfop4(ext15,((x - y) * (z + w)),"(t-t)*(t+t)") 12116 | define_sfop4(ext16,((x - y) / (z + w)),"(t-t)/(t+t)") 12117 | define_sfop4(ext17,((x * y) - (z + w)),"(t*t)-(t+t)") 12118 | define_sfop4(ext18,((x / y) - (z + w)),"(t/t)-(t+t)") 12119 | define_sfop4(ext19,((x * y) + (z + w)),"(t*t)+(t+t)") 12120 | define_sfop4(ext20,((x / y) + (z + w)),"(t/t)+(t+t)") 12121 | define_sfop4(ext21,((x * y) + (z - w)),"(t*t)+(t-t)") 12122 | define_sfop4(ext22,((x / y) + (z - w)),"(t/t)+(t-t)") 12123 | define_sfop4(ext23,((x * y) - (z - w)),"(t*t)-(t-t)") 12124 | define_sfop4(ext24,((x / y) - (z - w)),"(t/t)-(t-t)") 12125 | define_sfop4(ext25,((x + y) * (z * w)),"(t+t)*(t*t)") 12126 | define_sfop4(ext26,((x + y) * (z / w)),"(t+t)*(t/t)") 12127 | define_sfop4(ext27,((x + y) / (z * w)),"(t+t)/(t*t)") 12128 | define_sfop4(ext28,((x + y) / (z / w)),"(t+t)/(t/t)") 12129 | define_sfop4(ext29,((x - y) / (z * w)),"(t-t)/(t*t)") 12130 | define_sfop4(ext30,((x - y) / (z / w)),"(t-t)/(t/t)") 12131 | define_sfop4(ext31,((x - y) * (z * w)),"(t-t)*(t*t)") 12132 | define_sfop4(ext32,((x - y) * (z / w)),"(t-t)*(t/t)") 12133 | define_sfop4(ext33,((x * y) * (z + w)),"(t*t)*(t+t)") 12134 | define_sfop4(ext34,((x / y) * (z + w)),"(t/t)*(t+t)") 12135 | define_sfop4(ext35,((x * y) / (z + w)),"(t*t)/(t+t)") 12136 | define_sfop4(ext36,((x / y) / (z + w)),"(t/t)/(t+t)") 12137 | define_sfop4(ext37,((x * y) / (z - w)),"(t*t)/(t-t)") 12138 | define_sfop4(ext38,((x / y) / (z - w)),"(t/t)/(t-t)") 12139 | define_sfop4(ext39,((x * y) * (z - w)),"(t*t)*(t-t)") 12140 | define_sfop4(ext40,((x * y) / (z * w)),"(t*t)/(t*t)") 12141 | define_sfop4(ext41,((x / y) * (z / w)),"(t/t)*(t/t)") 12142 | define_sfop4(ext42,((x / y) * (z - w)),"(t/t)*(t-t)") 12143 | define_sfop4(ext43,((x * y) * (z * w)),"(t*t)*(t*t)") 12144 | define_sfop4(ext44,(x + (y * (z / w))),"t+(t*(t/t))") 12145 | define_sfop4(ext45,(x - (y * (z / w))),"t-(t*(t/t))") 12146 | define_sfop4(ext46,(x + (y / (z * w))),"t+(t/(t*t))") 12147 | define_sfop4(ext47,(x - (y / (z * w))),"t-(t/(t*t))") 12148 | define_sfop4(ext48,(((x - y) - z) * w),"((t-t)-t)*t") 12149 | define_sfop4(ext49,(((x - y) - z) / w),"((t-t)-t)/t") 12150 | define_sfop4(ext50,(((x - y) + z) * w),"((t-t)+t)*t") 12151 | define_sfop4(ext51,(((x - y) + z) / w),"((t-t)+t)/t") 12152 | define_sfop4(ext52,((x + (y - z)) * w),"(t+(t-t))*t") 12153 | define_sfop4(ext53,((x + (y - z)) / w),"(t+(t-t))/t") 12154 | define_sfop4(ext54,((x + y) / (z + w)),"(t+t)/(t+t)") 12155 | define_sfop4(ext55,((x - y) / (z - w)),"(t-t)/(t-t)") 12156 | define_sfop4(ext56,((x + y) * (z + w)),"(t+t)*(t+t)") 12157 | define_sfop4(ext57,((x - y) * (z - w)),"(t-t)*(t-t)") 12158 | define_sfop4(ext58,((x - y) + (z - w)),"(t-t)+(t-t)") 12159 | define_sfop4(ext59,((x - y) - (z - w)),"(t-t)-(t-t)") 12160 | define_sfop4(ext60,((x / y) + (z * w)),"(t/t)+(t*t)") 12161 | define_sfop4(ext61,(((x * y) * z) / w),"((t*t)*t)/t") 12162 | 12163 | #undef define_sfop3 12164 | #undef define_sfop4 12165 | 12166 | template <typename T, typename SpecialFunction> 12167 | class sf3_node exprtk_final : public trinary_node<T> 12168 | { 12169 | public: 12170 | 12171 | typedef expression_node<T>* expression_ptr; 12172 | 12173 | sf3_node(const operator_type& opr, 12174 | expression_ptr branch0, 12175 | expression_ptr branch1, 12176 | expression_ptr branch2) 12177 | : trinary_node<T>(opr, branch0, branch1, branch2) 12178 | {} 12179 | 12180 | inline T value() const exprtk_override 12181 | { 12182 | const T x = trinary_node<T>::branch_[0].first->value(); 12183 | const T y = trinary_node<T>::branch_[1].first->value(); 12184 | const T z = trinary_node<T>::branch_[2].first->value(); 12185 | 12186 | return SpecialFunction::process(x, y, z); 12187 | } 12188 | }; 12189 | 12190 | template <typename T, typename SpecialFunction> 12191 | class sf4_node exprtk_final : public quaternary_node<T> 12192 | { 12193 | public: 12194 | 12195 | typedef expression_node<T>* expression_ptr; 12196 | 12197 | sf4_node(const operator_type& opr, 12198 | expression_ptr branch0, 12199 | expression_ptr branch1, 12200 | expression_ptr branch2, 12201 | expression_ptr branch3) 12202 | : quaternary_node<T>(opr, branch0, branch1, branch2, branch3) 12203 | {} 12204 | 12205 | inline T value() const exprtk_override 12206 | { 12207 | const T x = quaternary_node<T>::branch_[0].first->value(); 12208 | const T y = quaternary_node<T>::branch_[1].first->value(); 12209 | const T z = quaternary_node<T>::branch_[2].first->value(); 12210 | const T w = quaternary_node<T>::branch_[3].first->value(); 12211 | 12212 | return SpecialFunction::process(x, y, z, w); 12213 | } 12214 | }; 12215 | 12216 | template <typename T, typename SpecialFunction> 12217 | class sf3_var_node exprtk_final : public expression_node<T> 12218 | { 12219 | public: 12220 | 12221 | typedef expression_node<T>* expression_ptr; 12222 | 12223 | sf3_var_node(const T& v0, const T& v1, const T& v2) 12224 | : v0_(v0) 12225 | , v1_(v1) 12226 | , v2_(v2) 12227 | {} 12228 | 12229 | inline T value() const exprtk_override 12230 | { 12231 | return SpecialFunction::process(v0_, v1_, v2_); 12232 | } 12233 | 12234 | inline typename expression_node<T>::node_type type() const exprtk_override 12235 | { 12236 | return expression_node<T>::e_trinary; 12237 | } 12238 | 12239 | private: 12240 | 12241 | sf3_var_node(const sf3_var_node<T,SpecialFunction>&) exprtk_delete; 12242 | sf3_var_node<T,SpecialFunction>& operator=(const sf3_var_node<T,SpecialFunction>&) exprtk_delete; 12243 | 12244 | const T& v0_; 12245 | const T& v1_; 12246 | const T& v2_; 12247 | }; 12248 | 12249 | template <typename T, typename SpecialFunction> 12250 | class sf4_var_node exprtk_final : public expression_node<T> 12251 | { 12252 | public: 12253 | 12254 | typedef expression_node<T>* expression_ptr; 12255 | 12256 | sf4_var_node(const T& v0, const T& v1, const T& v2, const T& v3) 12257 | : v0_(v0) 12258 | , v1_(v1) 12259 | , v2_(v2) 12260 | , v3_(v3) 12261 | {} 12262 | 12263 | inline T value() const exprtk_override 12264 | { 12265 | return SpecialFunction::process(v0_, v1_, v2_, v3_); 12266 | } 12267 | 12268 | inline typename expression_node<T>::node_type type() const exprtk_override 12269 | { 12270 | return expression_node<T>::e_trinary; 12271 | } 12272 | 12273 | private: 12274 | 12275 | sf4_var_node(const sf4_var_node<T,SpecialFunction>&) exprtk_delete; 12276 | sf4_var_node<T,SpecialFunction>& operator=(const sf4_var_node<T,SpecialFunction>&) exprtk_delete; 12277 | 12278 | const T& v0_; 12279 | const T& v1_; 12280 | const T& v2_; 12281 | const T& v3_; 12282 | }; 12283 | 12284 | template <typename T, typename VarArgFunction> 12285 | class vararg_node exprtk_final : public expression_node<T> 12286 | { 12287 | public: 12288 | 12289 | typedef expression_node<T>* expression_ptr; 12290 | typedef std::pair<expression_ptr,bool> branch_t; 12291 | 12292 | template <typename Allocator, 12293 | template <typename, typename> class Sequence> 12294 | explicit vararg_node(const Sequence<expression_ptr,Allocator>& arg_list) 12295 | : initialised_(false) 12296 | { 12297 | arg_list_.resize(arg_list.size()); 12298 | 12299 | for (std::size_t i = 0; i < arg_list.size(); ++i) 12300 | { 12301 | if (arg_list[i] && arg_list[i]->valid()) 12302 | { 12303 | construct_branch_pair(arg_list_[i],arg_list[i]); 12304 | } 12305 | else 12306 | { 12307 | arg_list_.clear(); 12308 | return; 12309 | } 12310 | } 12311 | 12312 | initialised_ = (arg_list_.size() == arg_list.size()); 12313 | assert(valid()); 12314 | } 12315 | 12316 | inline T value() const exprtk_override 12317 | { 12318 | return VarArgFunction::process(arg_list_); 12319 | } 12320 | 12321 | inline typename expression_node<T>::node_type type() const exprtk_override 12322 | { 12323 | return expression_node<T>::e_vararg; 12324 | } 12325 | 12326 | inline bool valid() const exprtk_override 12327 | { 12328 | return initialised_; 12329 | } 12330 | 12331 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 12332 | { 12333 | expression_node<T>::ndb_t::collect(arg_list_, node_delete_list); 12334 | } 12335 | 12336 | std::size_t node_depth() const exprtk_override 12337 | { 12338 | return expression_node<T>::ndb_t::compute_node_depth(arg_list_); 12339 | } 12340 | 12341 | std::size_t size() const 12342 | { 12343 | return arg_list_.size(); 12344 | } 12345 | 12346 | expression_ptr operator[](const std::size_t& index) const 12347 | { 12348 | return arg_list_[index].first; 12349 | } 12350 | 12351 | private: 12352 | 12353 | std::vector<branch_t> arg_list_; 12354 | bool initialised_; 12355 | }; 12356 | 12357 | template <typename T, typename VarArgFunction> 12358 | class vararg_varnode exprtk_final : public expression_node<T> 12359 | { 12360 | public: 12361 | 12362 | typedef expression_node<T>* expression_ptr; 12363 | 12364 | template <typename Allocator, 12365 | template <typename, typename> class Sequence> 12366 | explicit vararg_varnode(const Sequence<expression_ptr,Allocator>& arg_list) 12367 | : initialised_(false) 12368 | { 12369 | arg_list_.resize(arg_list.size()); 12370 | 12371 | for (std::size_t i = 0; i < arg_list.size(); ++i) 12372 | { 12373 | if (arg_list[i] && arg_list[i]->valid() && is_variable_node(arg_list[i])) 12374 | { 12375 | variable_node<T>* var_node_ptr = static_cast<variable_node<T>*>(arg_list[i]); 12376 | arg_list_[i] = (&var_node_ptr->ref()); 12377 | } 12378 | else 12379 | { 12380 | arg_list_.clear(); 12381 | return; 12382 | } 12383 | } 12384 | 12385 | initialised_ = (arg_list.size() == arg_list_.size()); 12386 | assert(valid()); 12387 | } 12388 | 12389 | inline T value() const exprtk_override 12390 | { 12391 | return VarArgFunction::process(arg_list_); 12392 | } 12393 | 12394 | inline typename expression_node<T>::node_type type() const exprtk_override 12395 | { 12396 | return expression_node<T>::e_vararg; 12397 | } 12398 | 12399 | inline bool valid() const exprtk_override 12400 | { 12401 | return initialised_; 12402 | } 12403 | 12404 | private: 12405 | 12406 | std::vector<const T*> arg_list_; 12407 | bool initialised_; 12408 | }; 12409 | 12410 | template <typename T, typename VecFunction> 12411 | class vectorize_node exprtk_final : public expression_node<T> 12412 | { 12413 | public: 12414 | 12415 | typedef expression_node<T>* expression_ptr; 12416 | typedef std::pair<expression_ptr,bool> branch_t; 12417 | 12418 | explicit vectorize_node(const expression_ptr v) 12419 | : ivec_ptr_(0) 12420 | { 12421 | construct_branch_pair(v_, v); 12422 | 12423 | if (is_ivector_node(v_.first)) 12424 | { 12425 | ivec_ptr_ = dynamic_cast<vector_interface<T>*>(v_.first); 12426 | } 12427 | } 12428 | 12429 | inline T value() const exprtk_override 12430 | { 12431 | v_.first->value(); 12432 | return VecFunction::process(ivec_ptr_); 12433 | } 12434 | 12435 | inline typename expression_node<T>::node_type type() const exprtk_override 12436 | { 12437 | return expression_node<T>::e_vecfunc; 12438 | } 12439 | 12440 | inline bool valid() const exprtk_override 12441 | { 12442 | return ivec_ptr_ && v_.first && v_.first->valid(); 12443 | } 12444 | 12445 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 12446 | { 12447 | expression_node<T>::ndb_t::collect(v_, node_delete_list); 12448 | } 12449 | 12450 | std::size_t node_depth() const exprtk_override 12451 | { 12452 | return expression_node<T>::ndb_t::compute_node_depth(v_); 12453 | } 12454 | 12455 | private: 12456 | 12457 | vector_interface<T>* ivec_ptr_; 12458 | branch_t v_; 12459 | }; 12460 | 12461 | template <typename T> 12462 | class assignment_node exprtk_final : public binary_node<T> 12463 | { 12464 | public: 12465 | 12466 | typedef expression_node<T>* expression_ptr; 12467 | using binary_node<T>::branch; 12468 | 12469 | assignment_node(const operator_type& opr, 12470 | expression_ptr branch0, 12471 | expression_ptr branch1) 12472 | : binary_node<T>(opr, branch0, branch1) 12473 | , var_node_ptr_(0) 12474 | { 12475 | if (is_variable_node(branch(0))) 12476 | { 12477 | var_node_ptr_ = static_cast<variable_node<T>*>(branch(0)); 12478 | } 12479 | } 12480 | 12481 | inline T value() const exprtk_override 12482 | { 12483 | T& result = var_node_ptr_->ref(); 12484 | result = branch(1)->value(); 12485 | 12486 | return result; 12487 | } 12488 | 12489 | inline bool valid() const exprtk_override 12490 | { 12491 | return var_node_ptr_ && binary_node<T>::valid(); 12492 | } 12493 | 12494 | private: 12495 | 12496 | variable_node<T>* var_node_ptr_; 12497 | }; 12498 | 12499 | template <typename T> 12500 | class assignment_vec_elem_node exprtk_final : public binary_node<T> 12501 | { 12502 | public: 12503 | 12504 | typedef expression_node<T>* expression_ptr; 12505 | using binary_node<T>::branch; 12506 | 12507 | assignment_vec_elem_node(const operator_type& opr, 12508 | expression_ptr branch0, 12509 | expression_ptr branch1) 12510 | : binary_node<T>(opr, branch0, branch1) 12511 | , vec_node_ptr_(0) 12512 | { 12513 | if (is_vector_elem_node(branch(0))) 12514 | { 12515 | vec_node_ptr_ = static_cast<vector_elem_node<T>*>(branch(0)); 12516 | } 12517 | 12518 | assert(valid()); 12519 | } 12520 | 12521 | inline T value() const exprtk_override 12522 | { 12523 | T& result = vec_node_ptr_->ref(); 12524 | result = branch(1)->value(); 12525 | 12526 | return result; 12527 | } 12528 | 12529 | inline bool valid() const exprtk_override 12530 | { 12531 | return vec_node_ptr_ && binary_node<T>::valid(); 12532 | } 12533 | 12534 | private: 12535 | 12536 | vector_elem_node<T>* vec_node_ptr_; 12537 | }; 12538 | 12539 | template <typename T> 12540 | class assignment_vec_elem_rtc_node exprtk_final : public binary_node<T> 12541 | { 12542 | public: 12543 | 12544 | typedef expression_node<T>* expression_ptr; 12545 | using binary_node<T>::branch; 12546 | 12547 | assignment_vec_elem_rtc_node(const operator_type& opr, 12548 | expression_ptr branch0, 12549 | expression_ptr branch1) 12550 | : binary_node<T>(opr, branch0, branch1) 12551 | , vec_node_ptr_(0) 12552 | { 12553 | if (is_vector_elem_rtc_node(branch(0))) 12554 | { 12555 | vec_node_ptr_ = static_cast<vector_elem_rtc_node<T>*>(branch(0)); 12556 | } 12557 | 12558 | assert(valid()); 12559 | } 12560 | 12561 | inline T value() const exprtk_override 12562 | { 12563 | T& result = vec_node_ptr_->ref(); 12564 | result = branch(1)->value(); 12565 | 12566 | return result; 12567 | } 12568 | 12569 | inline bool valid() const exprtk_override 12570 | { 12571 | return vec_node_ptr_ && binary_node<T>::valid(); 12572 | } 12573 | 12574 | private: 12575 | 12576 | vector_elem_rtc_node<T>* vec_node_ptr_; 12577 | }; 12578 | 12579 | template <typename T> 12580 | class assignment_rebasevec_elem_node exprtk_final : public binary_node<T> 12581 | { 12582 | public: 12583 | 12584 | typedef expression_node<T>* expression_ptr; 12585 | using expression_node<T>::branch; 12586 | 12587 | assignment_rebasevec_elem_node(const operator_type& opr, 12588 | expression_ptr branch0, 12589 | expression_ptr branch1) 12590 | : binary_node<T>(opr, branch0, branch1) 12591 | , rbvec_node_ptr_(0) 12592 | { 12593 | if (is_rebasevector_elem_node(branch(0))) 12594 | { 12595 | rbvec_node_ptr_ = static_cast<rebasevector_elem_node<T>*>(branch(0)); 12596 | } 12597 | 12598 | assert(valid()); 12599 | } 12600 | 12601 | inline T value() const exprtk_override 12602 | { 12603 | T& result = rbvec_node_ptr_->ref(); 12604 | result = branch(1)->value(); 12605 | 12606 | return result; 12607 | } 12608 | 12609 | inline bool valid() const exprtk_override 12610 | { 12611 | return rbvec_node_ptr_ && binary_node<T>::valid(); 12612 | } 12613 | 12614 | private: 12615 | 12616 | rebasevector_elem_node<T>* rbvec_node_ptr_; 12617 | }; 12618 | 12619 | template <typename T> 12620 | class assignment_rebasevec_elem_rtc_node exprtk_final : public binary_node<T> 12621 | { 12622 | public: 12623 | 12624 | typedef expression_node<T>* expression_ptr; 12625 | using expression_node<T>::branch; 12626 | 12627 | assignment_rebasevec_elem_rtc_node(const operator_type& opr, 12628 | expression_ptr branch0, 12629 | expression_ptr branch1) 12630 | : binary_node<T>(opr, branch0, branch1) 12631 | , rbvec_node_ptr_(0) 12632 | { 12633 | if (is_rebasevector_elem_rtc_node(branch(0))) 12634 | { 12635 | rbvec_node_ptr_ = static_cast<rebasevector_elem_rtc_node<T>*>(branch(0)); 12636 | } 12637 | 12638 | assert(valid()); 12639 | } 12640 | 12641 | inline T value() const exprtk_override 12642 | { 12643 | T& result = rbvec_node_ptr_->ref(); 12644 | result = branch(1)->value(); 12645 | 12646 | return result; 12647 | } 12648 | 12649 | inline bool valid() const exprtk_override 12650 | { 12651 | return rbvec_node_ptr_ && binary_node<T>::valid(); 12652 | } 12653 | 12654 | private: 12655 | 12656 | rebasevector_elem_rtc_node<T>* rbvec_node_ptr_; 12657 | }; 12658 | 12659 | template <typename T> 12660 | class assignment_rebasevec_celem_node exprtk_final : public binary_node<T> 12661 | { 12662 | public: 12663 | 12664 | typedef expression_node<T>* expression_ptr; 12665 | using binary_node<T>::branch; 12666 | 12667 | assignment_rebasevec_celem_node(const operator_type& opr, 12668 | expression_ptr branch0, 12669 | expression_ptr branch1) 12670 | : binary_node<T>(opr, branch0, branch1) 12671 | , rbvec_node_ptr_(0) 12672 | { 12673 | if (is_rebasevector_celem_node(branch(0))) 12674 | { 12675 | rbvec_node_ptr_ = static_cast<rebasevector_celem_node<T>*>(branch(0)); 12676 | } 12677 | 12678 | assert(valid()); 12679 | } 12680 | 12681 | inline T value() const exprtk_override 12682 | { 12683 | T& result = rbvec_node_ptr_->ref(); 12684 | result = branch(1)->value(); 12685 | 12686 | return result; 12687 | } 12688 | 12689 | inline bool valid() const exprtk_override 12690 | { 12691 | return rbvec_node_ptr_ && binary_node<T>::valid(); 12692 | } 12693 | 12694 | private: 12695 | 12696 | rebasevector_celem_node<T>* rbvec_node_ptr_; 12697 | }; 12698 | 12699 | template <typename T> 12700 | class assignment_vec_node exprtk_final 12701 | : public binary_node <T> 12702 | , public vector_interface<T> 12703 | { 12704 | public: 12705 | 12706 | typedef expression_node<T>* expression_ptr; 12707 | typedef vector_node<T>* vector_node_ptr; 12708 | typedef vec_data_store<T> vds_t; 12709 | 12710 | using binary_node<T>::branch; 12711 | 12712 | assignment_vec_node(const operator_type& opr, 12713 | expression_ptr branch0, 12714 | expression_ptr branch1) 12715 | : binary_node<T>(opr, branch0, branch1) 12716 | , vec_node_ptr_(0) 12717 | { 12718 | if (is_vector_node(branch(0))) 12719 | { 12720 | vec_node_ptr_ = static_cast<vector_node<T>*>(branch(0)); 12721 | vds() = vec_node_ptr_->vds(); 12722 | } 12723 | 12724 | assert(valid()); 12725 | } 12726 | 12727 | inline T value() const exprtk_override 12728 | { 12729 | const T v = branch(1)->value(); 12730 | 12731 | T* vec = vds().data(); 12732 | 12733 | loop_unroll::details lud(size()); 12734 | const T* upper_bound = vec + lud.upper_bound; 12735 | 12736 | while (vec < upper_bound) 12737 | { 12738 | #define exprtk_loop(N) \ 12739 | vec[N] = v; \ 12740 | 12741 | exprtk_loop( 0) exprtk_loop( 1) 12742 | exprtk_loop( 2) exprtk_loop( 3) 12743 | #ifndef exprtk_disable_superscalar_unroll 12744 | exprtk_loop( 4) exprtk_loop( 5) 12745 | exprtk_loop( 6) exprtk_loop( 7) 12746 | exprtk_loop( 8) exprtk_loop( 9) 12747 | exprtk_loop(10) exprtk_loop(11) 12748 | exprtk_loop(12) exprtk_loop(13) 12749 | exprtk_loop(14) exprtk_loop(15) 12750 | #endif 12751 | 12752 | vec += lud.batch_size; 12753 | } 12754 | 12755 | switch (lud.remainder) 12756 | { 12757 | #define case_stmt(N) \ 12758 | case N : *vec++ = v; \ 12759 | exprtk_fallthrough \ 12760 | 12761 | #ifndef exprtk_disable_superscalar_unroll 12762 | case_stmt(15) case_stmt(14) 12763 | case_stmt(13) case_stmt(12) 12764 | case_stmt(11) case_stmt(10) 12765 | case_stmt( 9) case_stmt( 8) 12766 | case_stmt( 7) case_stmt( 6) 12767 | case_stmt( 5) case_stmt( 4) 12768 | #endif 12769 | case_stmt( 3) case_stmt( 2) 12770 | case 1 : *vec++ = v; 12771 | } 12772 | 12773 | #undef exprtk_loop 12774 | #undef case_stmt 12775 | 12776 | return vec_node_ptr_->value(); 12777 | } 12778 | 12779 | vector_node_ptr vec() const exprtk_override 12780 | { 12781 | return vec_node_ptr_; 12782 | } 12783 | 12784 | vector_node_ptr vec() exprtk_override 12785 | { 12786 | return vec_node_ptr_; 12787 | } 12788 | 12789 | inline typename expression_node<T>::node_type type() const exprtk_override 12790 | { 12791 | return expression_node<T>::e_vecvalass; 12792 | } 12793 | 12794 | inline bool valid() const exprtk_override 12795 | { 12796 | return 12797 | vec_node_ptr_ && 12798 | (vds().size() <= vec_node_ptr_->vec_holder().base_size()) && 12799 | binary_node<T>::valid(); 12800 | } 12801 | 12802 | std::size_t size() const exprtk_override 12803 | { 12804 | return vec_node_ptr_->vec_holder().size(); 12805 | } 12806 | 12807 | std::size_t base_size() const exprtk_override 12808 | { 12809 | return vec_node_ptr_->vec_holder().base_size(); 12810 | } 12811 | 12812 | vds_t& vds() exprtk_override 12813 | { 12814 | return vds_; 12815 | } 12816 | 12817 | const vds_t& vds() const exprtk_override 12818 | { 12819 | return vds_; 12820 | } 12821 | 12822 | private: 12823 | 12824 | vector_node<T>* vec_node_ptr_; 12825 | vds_t vds_; 12826 | }; 12827 | 12828 | template <typename T> 12829 | class assignment_vecvec_node exprtk_final 12830 | : public binary_node <T> 12831 | , public vector_interface<T> 12832 | { 12833 | public: 12834 | 12835 | typedef expression_node<T>* expression_ptr; 12836 | typedef vector_node<T>* vector_node_ptr; 12837 | typedef vec_data_store<T> vds_t; 12838 | 12839 | using binary_node<T>::branch; 12840 | 12841 | assignment_vecvec_node(const operator_type& opr, 12842 | expression_ptr branch0, 12843 | expression_ptr branch1) 12844 | : binary_node<T>(opr, branch0, branch1) 12845 | , vec0_node_ptr_(0) 12846 | , vec1_node_ptr_(0) 12847 | , initialised_(false) 12848 | , src_is_ivec_(false) 12849 | { 12850 | if (is_vector_node(branch(0))) 12851 | { 12852 | vec0_node_ptr_ = static_cast<vector_node<T>*>(branch(0)); 12853 | vds() = vec0_node_ptr_->vds(); 12854 | } 12855 | 12856 | if (is_vector_node(branch(1))) 12857 | { 12858 | vec1_node_ptr_ = static_cast<vector_node<T>*>(branch(1)); 12859 | vds_t::match_sizes(vds(),vec1_node_ptr_->vds()); 12860 | } 12861 | else if (is_ivector_node(branch(1))) 12862 | { 12863 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 12864 | 12865 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1)))) 12866 | { 12867 | vec1_node_ptr_ = vi->vec(); 12868 | 12869 | if (!vi->side_effect()) 12870 | { 12871 | vi->vds() = vds(); 12872 | src_is_ivec_ = true; 12873 | } 12874 | else 12875 | vds_t::match_sizes(vds(),vi->vds()); 12876 | } 12877 | } 12878 | 12879 | initialised_ = 12880 | vec0_node_ptr_ && 12881 | vec1_node_ptr_ && 12882 | (size() <= base_size()) && 12883 | (vds_.size() <= base_size()) && 12884 | binary_node<T>::valid(); 12885 | 12886 | assert(valid()); 12887 | } 12888 | 12889 | inline T value() const exprtk_override 12890 | { 12891 | branch(1)->value(); 12892 | 12893 | if (src_is_ivec_) 12894 | return vec0_node_ptr_->value(); 12895 | 12896 | T* vec0 = vec0_node_ptr_->vds().data(); 12897 | T* vec1 = vec1_node_ptr_->vds().data(); 12898 | 12899 | loop_unroll::details lud(size()); 12900 | const T* upper_bound = vec0 + lud.upper_bound; 12901 | 12902 | while (vec0 < upper_bound) 12903 | { 12904 | #define exprtk_loop(N) \ 12905 | vec0[N] = vec1[N]; \ 12906 | 12907 | exprtk_loop( 0) exprtk_loop( 1) 12908 | exprtk_loop( 2) exprtk_loop( 3) 12909 | #ifndef exprtk_disable_superscalar_unroll 12910 | exprtk_loop( 4) exprtk_loop( 5) 12911 | exprtk_loop( 6) exprtk_loop( 7) 12912 | exprtk_loop( 8) exprtk_loop( 9) 12913 | exprtk_loop(10) exprtk_loop(11) 12914 | exprtk_loop(12) exprtk_loop(13) 12915 | exprtk_loop(14) exprtk_loop(15) 12916 | #endif 12917 | 12918 | vec0 += lud.batch_size; 12919 | vec1 += lud.batch_size; 12920 | } 12921 | 12922 | switch (lud.remainder) 12923 | { 12924 | #define case_stmt(N,fall_through) \ 12925 | case N : *vec0++ = *vec1++; \ 12926 | fall_through \ 12927 | 12928 | #ifndef exprtk_disable_superscalar_unroll 12929 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 12930 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 12931 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 12932 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 12933 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 12934 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 12935 | #endif 12936 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 12937 | case_stmt( 1, (void)0;) 12938 | } 12939 | 12940 | #undef exprtk_loop 12941 | #undef case_stmt 12942 | 12943 | return vec0_node_ptr_->value(); 12944 | } 12945 | 12946 | vector_node_ptr vec() exprtk_override 12947 | { 12948 | return vec0_node_ptr_; 12949 | } 12950 | 12951 | vector_node_ptr vec() const exprtk_override 12952 | { 12953 | return vec0_node_ptr_; 12954 | } 12955 | 12956 | inline typename expression_node<T>::node_type type() const exprtk_override 12957 | { 12958 | return expression_node<T>::e_vecvecass; 12959 | } 12960 | 12961 | inline bool valid() const exprtk_override 12962 | { 12963 | return initialised_; 12964 | } 12965 | 12966 | std::size_t size() const exprtk_override 12967 | { 12968 | return std::min( 12969 | vec0_node_ptr_->vec_holder().size(), 12970 | vec1_node_ptr_->vec_holder().size()); 12971 | } 12972 | 12973 | std::size_t base_size() const exprtk_override 12974 | { 12975 | return std::min( 12976 | vec0_node_ptr_->vec_holder().base_size(), 12977 | vec1_node_ptr_->vec_holder().base_size()); 12978 | } 12979 | 12980 | vds_t& vds() exprtk_override 12981 | { 12982 | return vds_; 12983 | } 12984 | 12985 | const vds_t& vds() const exprtk_override 12986 | { 12987 | return vds_; 12988 | } 12989 | 12990 | private: 12991 | 12992 | vector_node<T>* vec0_node_ptr_; 12993 | vector_node<T>* vec1_node_ptr_; 12994 | bool initialised_; 12995 | bool src_is_ivec_; 12996 | vds_t vds_; 12997 | }; 12998 | 12999 | template <typename T, typename Operation> 13000 | class assignment_op_node exprtk_final : public binary_node<T> 13001 | { 13002 | public: 13003 | 13004 | typedef expression_node<T>* expression_ptr; 13005 | using binary_node<T>::branch; 13006 | 13007 | assignment_op_node(const operator_type& opr, 13008 | expression_ptr branch0, 13009 | expression_ptr branch1) 13010 | : binary_node<T>(opr, branch0, branch1) 13011 | , var_node_ptr_(0) 13012 | { 13013 | if (is_variable_node(branch(0))) 13014 | { 13015 | var_node_ptr_ = static_cast<variable_node<T>*>(branch(0)); 13016 | } 13017 | 13018 | assert(valid()); 13019 | } 13020 | 13021 | inline T value() const exprtk_override 13022 | { 13023 | T& v = var_node_ptr_->ref(); 13024 | v = Operation::process(v,branch(1)->value()); 13025 | 13026 | return v; 13027 | } 13028 | 13029 | inline bool valid() const exprtk_override 13030 | { 13031 | return var_node_ptr_ && binary_node<T>::valid(); 13032 | } 13033 | 13034 | private: 13035 | 13036 | variable_node<T>* var_node_ptr_; 13037 | }; 13038 | 13039 | template <typename T, typename Operation> 13040 | class assignment_vec_elem_op_node exprtk_final : public binary_node<T> 13041 | { 13042 | public: 13043 | 13044 | typedef expression_node<T>* expression_ptr; 13045 | using binary_node<T>::branch; 13046 | 13047 | assignment_vec_elem_op_node(const operator_type& opr, 13048 | expression_ptr branch0, 13049 | expression_ptr branch1) 13050 | : binary_node<T>(opr, branch0, branch1) 13051 | , vec_node_ptr_(0) 13052 | { 13053 | if (is_vector_elem_node(branch(0))) 13054 | { 13055 | vec_node_ptr_ = static_cast<vector_elem_node<T>*>(branch(0)); 13056 | } 13057 | 13058 | assert(valid()); 13059 | } 13060 | 13061 | inline T value() const exprtk_override 13062 | { 13063 | T& v = vec_node_ptr_->ref(); 13064 | v = Operation::process(v,branch(1)->value()); 13065 | 13066 | return v; 13067 | } 13068 | 13069 | inline bool valid() const exprtk_override 13070 | { 13071 | return vec_node_ptr_ && binary_node<T>::valid(); 13072 | } 13073 | 13074 | private: 13075 | 13076 | vector_elem_node<T>* vec_node_ptr_; 13077 | }; 13078 | 13079 | template <typename T, typename Operation> 13080 | class assignment_vec_elem_op_rtc_node exprtk_final : public binary_node<T> 13081 | { 13082 | public: 13083 | 13084 | typedef expression_node<T>* expression_ptr; 13085 | using binary_node<T>::branch; 13086 | 13087 | assignment_vec_elem_op_rtc_node(const operator_type& opr, 13088 | expression_ptr branch0, 13089 | expression_ptr branch1) 13090 | : binary_node<T>(opr, branch0, branch1) 13091 | , vec_node_ptr_(0) 13092 | { 13093 | if (is_vector_elem_rtc_node(branch(0))) 13094 | { 13095 | vec_node_ptr_ = static_cast<vector_elem_rtc_node<T>*>(branch(0)); 13096 | } 13097 | 13098 | assert(valid()); 13099 | } 13100 | 13101 | inline T value() const exprtk_override 13102 | { 13103 | T& v = vec_node_ptr_->ref(); 13104 | v = Operation::process(v,branch(1)->value()); 13105 | 13106 | return v; 13107 | } 13108 | 13109 | inline bool valid() const exprtk_override 13110 | { 13111 | return vec_node_ptr_ && binary_node<T>::valid(); 13112 | } 13113 | 13114 | private: 13115 | 13116 | vector_elem_rtc_node<T>* vec_node_ptr_; 13117 | }; 13118 | 13119 | template <typename T, typename Operation> 13120 | class assignment_vec_celem_op_rtc_node exprtk_final : public binary_node<T> 13121 | { 13122 | public: 13123 | 13124 | typedef expression_node<T>* expression_ptr; 13125 | using binary_node<T>::branch; 13126 | 13127 | assignment_vec_celem_op_rtc_node(const operator_type& opr, 13128 | expression_ptr branch0, 13129 | expression_ptr branch1) 13130 | : binary_node<T>(opr, branch0, branch1) 13131 | , vec_node_ptr_(0) 13132 | { 13133 | if (is_vector_celem_rtc_node(branch(0))) 13134 | { 13135 | vec_node_ptr_ = static_cast<vector_celem_rtc_node<T>*>(branch(0)); 13136 | } 13137 | 13138 | assert(valid()); 13139 | } 13140 | 13141 | inline T value() const exprtk_override 13142 | { 13143 | T& v = vec_node_ptr_->ref(); 13144 | v = Operation::process(v,branch(1)->value()); 13145 | 13146 | return v; 13147 | } 13148 | 13149 | inline bool valid() const exprtk_override 13150 | { 13151 | return vec_node_ptr_ && binary_node<T>::valid(); 13152 | } 13153 | 13154 | private: 13155 | 13156 | vector_celem_rtc_node<T>* vec_node_ptr_; 13157 | }; 13158 | 13159 | template <typename T, typename Operation> 13160 | class assignment_rebasevec_elem_op_node exprtk_final : public binary_node<T> 13161 | { 13162 | public: 13163 | 13164 | typedef expression_node<T>* expression_ptr; 13165 | using binary_node<T>::branch; 13166 | 13167 | assignment_rebasevec_elem_op_node(const operator_type& opr, 13168 | expression_ptr branch0, 13169 | expression_ptr branch1) 13170 | : binary_node<T>(opr, branch0, branch1) 13171 | , rbvec_node_ptr_(0) 13172 | { 13173 | if (is_rebasevector_elem_node(branch(0))) 13174 | { 13175 | rbvec_node_ptr_ = static_cast<rebasevector_elem_node<T>*>(branch(0)); 13176 | } 13177 | 13178 | assert(valid()); 13179 | } 13180 | 13181 | inline T value() const exprtk_override 13182 | { 13183 | T& v = rbvec_node_ptr_->ref(); 13184 | v = Operation::process(v,branch(1)->value()); 13185 | 13186 | return v; 13187 | } 13188 | 13189 | inline bool valid() const exprtk_override 13190 | { 13191 | return rbvec_node_ptr_ && binary_node<T>::valid(); 13192 | } 13193 | 13194 | private: 13195 | 13196 | rebasevector_elem_node<T>* rbvec_node_ptr_; 13197 | }; 13198 | 13199 | template <typename T, typename Operation> 13200 | class assignment_rebasevec_celem_op_node exprtk_final : public binary_node<T> 13201 | { 13202 | public: 13203 | 13204 | typedef expression_node<T>* expression_ptr; 13205 | using binary_node<T>::branch; 13206 | 13207 | assignment_rebasevec_celem_op_node(const operator_type& opr, 13208 | expression_ptr branch0, 13209 | expression_ptr branch1) 13210 | : binary_node<T>(opr, branch0, branch1) 13211 | , rbvec_node_ptr_(0) 13212 | { 13213 | if (is_rebasevector_celem_node(branch(0))) 13214 | { 13215 | rbvec_node_ptr_ = static_cast<rebasevector_celem_node<T>*>(branch(0)); 13216 | } 13217 | 13218 | assert(valid()); 13219 | } 13220 | 13221 | inline T value() const exprtk_override 13222 | { 13223 | T& v = rbvec_node_ptr_->ref(); 13224 | v = Operation::process(v,branch(1)->value()); 13225 | 13226 | return v; 13227 | } 13228 | 13229 | inline bool valid() const exprtk_override 13230 | { 13231 | return rbvec_node_ptr_ && binary_node<T>::valid(); 13232 | } 13233 | 13234 | private: 13235 | 13236 | rebasevector_celem_node<T>* rbvec_node_ptr_; 13237 | }; 13238 | 13239 | template <typename T, typename Operation> 13240 | class assignment_rebasevec_elem_op_rtc_node exprtk_final : public binary_node<T> 13241 | { 13242 | public: 13243 | 13244 | typedef expression_node<T>* expression_ptr; 13245 | using binary_node<T>::branch; 13246 | 13247 | assignment_rebasevec_elem_op_rtc_node(const operator_type& opr, 13248 | expression_ptr branch0, 13249 | expression_ptr branch1) 13250 | : binary_node<T>(opr, branch0, branch1) 13251 | , rbvec_node_ptr_(0) 13252 | { 13253 | if (is_rebasevector_elem_rtc_node(branch(0))) 13254 | { 13255 | rbvec_node_ptr_ = static_cast<rebasevector_elem_rtc_node<T>*>(branch(0)); 13256 | } 13257 | 13258 | assert(valid()); 13259 | } 13260 | 13261 | inline T value() const exprtk_override 13262 | { 13263 | T& v = rbvec_node_ptr_->ref(); 13264 | v = Operation::process(v,branch(1)->value()); 13265 | 13266 | return v; 13267 | } 13268 | 13269 | inline bool valid() const exprtk_override 13270 | { 13271 | return rbvec_node_ptr_ && binary_node<T>::valid(); 13272 | } 13273 | 13274 | private: 13275 | 13276 | rebasevector_elem_rtc_node<T>* rbvec_node_ptr_; 13277 | }; 13278 | 13279 | template <typename T, typename Operation> 13280 | class assignment_rebasevec_celem_op_rtc_node exprtk_final : public binary_node<T> 13281 | { 13282 | public: 13283 | 13284 | typedef expression_node<T>* expression_ptr; 13285 | using binary_node<T>::branch; 13286 | 13287 | assignment_rebasevec_celem_op_rtc_node(const operator_type& opr, 13288 | expression_ptr branch0, 13289 | expression_ptr branch1) 13290 | : binary_node<T>(opr, branch0, branch1) 13291 | , rbvec_node_ptr_(0) 13292 | { 13293 | if (is_rebasevector_celem_rtc_node(branch(0))) 13294 | { 13295 | rbvec_node_ptr_ = static_cast<rebasevector_celem_rtc_node<T>*>(branch(0)); 13296 | } 13297 | 13298 | assert(valid()); 13299 | } 13300 | 13301 | inline T value() const exprtk_override 13302 | { 13303 | T& v = rbvec_node_ptr_->ref(); 13304 | v = Operation::process(v,branch(1)->value()); 13305 | 13306 | return v; 13307 | } 13308 | 13309 | inline bool valid() const exprtk_override 13310 | { 13311 | return rbvec_node_ptr_ && binary_node<T>::valid(); 13312 | } 13313 | 13314 | private: 13315 | 13316 | rebasevector_celem_rtc_node<T>* rbvec_node_ptr_; 13317 | }; 13318 | 13319 | template <typename T, typename Operation> 13320 | class assignment_vec_op_node exprtk_final 13321 | : public binary_node <T> 13322 | , public vector_interface<T> 13323 | { 13324 | public: 13325 | 13326 | typedef expression_node<T>* expression_ptr; 13327 | typedef vector_node<T>* vector_node_ptr; 13328 | typedef vec_data_store<T> vds_t; 13329 | 13330 | using binary_node<T>::branch; 13331 | 13332 | assignment_vec_op_node(const operator_type& opr, 13333 | expression_ptr branch0, 13334 | expression_ptr branch1) 13335 | : binary_node<T>(opr, branch0, branch1) 13336 | , vec_node_ptr_(0) 13337 | { 13338 | if (is_vector_node(branch(0))) 13339 | { 13340 | vec_node_ptr_ = static_cast<vector_node<T>*>(branch(0)); 13341 | vds() = vec_node_ptr_->vds(); 13342 | } 13343 | 13344 | assert(valid()); 13345 | } 13346 | 13347 | inline T value() const exprtk_override 13348 | { 13349 | const T v = branch(1)->value(); 13350 | 13351 | T* vec = vds().data(); 13352 | 13353 | loop_unroll::details lud(size()); 13354 | const T* upper_bound = vec + lud.upper_bound; 13355 | 13356 | while (vec < upper_bound) 13357 | { 13358 | #define exprtk_loop(N) \ 13359 | Operation::assign(vec[N],v); \ 13360 | 13361 | exprtk_loop( 0) exprtk_loop( 1) 13362 | exprtk_loop( 2) exprtk_loop( 3) 13363 | #ifndef exprtk_disable_superscalar_unroll 13364 | exprtk_loop( 4) exprtk_loop( 5) 13365 | exprtk_loop( 6) exprtk_loop( 7) 13366 | exprtk_loop( 8) exprtk_loop( 9) 13367 | exprtk_loop(10) exprtk_loop(11) 13368 | exprtk_loop(12) exprtk_loop(13) 13369 | exprtk_loop(14) exprtk_loop(15) 13370 | #endif 13371 | 13372 | vec += lud.batch_size; 13373 | } 13374 | 13375 | switch (lud.remainder) 13376 | { 13377 | #define case_stmt(N,fall_through) \ 13378 | case N : Operation::assign(*vec++,v); \ 13379 | fall_through \ 13380 | 13381 | #ifndef exprtk_disable_superscalar_unroll 13382 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 13383 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 13384 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 13385 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 13386 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 13387 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 13388 | #endif 13389 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 13390 | case_stmt( 1, (void)0;) 13391 | } 13392 | 13393 | #undef exprtk_loop 13394 | #undef case_stmt 13395 | 13396 | return vec_node_ptr_->value(); 13397 | } 13398 | 13399 | vector_node_ptr vec() const exprtk_override 13400 | { 13401 | return vec_node_ptr_; 13402 | } 13403 | 13404 | vector_node_ptr vec() exprtk_override 13405 | { 13406 | return vec_node_ptr_; 13407 | } 13408 | 13409 | inline typename expression_node<T>::node_type type() const exprtk_override 13410 | { 13411 | return expression_node<T>::e_vecopvalass; 13412 | } 13413 | 13414 | inline bool valid() const exprtk_override 13415 | { 13416 | return 13417 | vec_node_ptr_ && 13418 | (size() <= base_size()) && 13419 | binary_node<T>::valid() ; 13420 | } 13421 | 13422 | std::size_t size() const exprtk_override 13423 | { 13424 | return vec_node_ptr_->vec_holder().size(); 13425 | } 13426 | 13427 | std::size_t base_size() const exprtk_override 13428 | { 13429 | return vec_node_ptr_->vec_holder().base_size(); 13430 | } 13431 | 13432 | vds_t& vds() exprtk_override 13433 | { 13434 | return vds_; 13435 | } 13436 | 13437 | const vds_t& vds() const exprtk_override 13438 | { 13439 | return vds_; 13440 | } 13441 | 13442 | bool side_effect() const exprtk_override 13443 | { 13444 | return true; 13445 | } 13446 | 13447 | private: 13448 | 13449 | vector_node<T>* vec_node_ptr_; 13450 | vds_t vds_; 13451 | }; 13452 | 13453 | template <typename T, typename Operation> 13454 | class assignment_vecvec_op_node exprtk_final 13455 | : public binary_node <T> 13456 | , public vector_interface<T> 13457 | { 13458 | public: 13459 | 13460 | typedef expression_node<T>* expression_ptr; 13461 | typedef vector_node<T>* vector_node_ptr; 13462 | typedef vec_data_store<T> vds_t; 13463 | 13464 | using binary_node<T>::branch; 13465 | 13466 | assignment_vecvec_op_node(const operator_type& opr, 13467 | expression_ptr branch0, 13468 | expression_ptr branch1) 13469 | : binary_node<T>(opr, branch0, branch1) 13470 | , vec0_node_ptr_(0) 13471 | , vec1_node_ptr_(0) 13472 | , initialised_(false) 13473 | { 13474 | if (is_vector_node(branch(0))) 13475 | { 13476 | vec0_node_ptr_ = static_cast<vector_node<T>*>(branch(0)); 13477 | vds() = vec0_node_ptr_->vds(); 13478 | } 13479 | 13480 | if (is_vector_node(branch(1))) 13481 | { 13482 | vec1_node_ptr_ = static_cast<vector_node<T>*>(branch(1)); 13483 | vec1_node_ptr_->vds() = vds(); 13484 | } 13485 | else if (is_ivector_node(branch(1))) 13486 | { 13487 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 13488 | 13489 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1)))) 13490 | { 13491 | vec1_node_ptr_ = vi->vec(); 13492 | vec1_node_ptr_->vds() = vi->vds(); 13493 | } 13494 | else 13495 | vds_t::match_sizes(vds(),vec1_node_ptr_->vds()); 13496 | } 13497 | 13498 | initialised_ = 13499 | vec0_node_ptr_ && 13500 | vec1_node_ptr_ && 13501 | (size() <= base_size()) && 13502 | binary_node<T>::valid(); 13503 | 13504 | assert(valid()); 13505 | } 13506 | 13507 | inline T value() const exprtk_override 13508 | { 13509 | branch(0)->value(); 13510 | branch(1)->value(); 13511 | 13512 | T* vec0 = vec0_node_ptr_->vds().data(); 13513 | const T* vec1 = vec1_node_ptr_->vds().data(); 13514 | 13515 | loop_unroll::details lud(size()); 13516 | const T* upper_bound = vec0 + lud.upper_bound; 13517 | 13518 | while (vec0 < upper_bound) 13519 | { 13520 | #define exprtk_loop(N) \ 13521 | vec0[N] = Operation::process(vec0[N], vec1[N]); \ 13522 | 13523 | exprtk_loop( 0) exprtk_loop( 1) 13524 | exprtk_loop( 2) exprtk_loop( 3) 13525 | #ifndef exprtk_disable_superscalar_unroll 13526 | exprtk_loop( 4) exprtk_loop( 5) 13527 | exprtk_loop( 6) exprtk_loop( 7) 13528 | exprtk_loop( 8) exprtk_loop( 9) 13529 | exprtk_loop(10) exprtk_loop(11) 13530 | exprtk_loop(12) exprtk_loop(13) 13531 | exprtk_loop(14) exprtk_loop(15) 13532 | #endif 13533 | 13534 | vec0 += lud.batch_size; 13535 | vec1 += lud.batch_size; 13536 | } 13537 | 13538 | int i = 0; 13539 | 13540 | switch (lud.remainder) 13541 | { 13542 | #define case_stmt(N,fall_through) \ 13543 | case N : { vec0[i] = Operation::process(vec0[i], vec1[i]); ++i; } \ 13544 | fall_through \ 13545 | 13546 | #ifndef exprtk_disable_superscalar_unroll 13547 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 13548 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 13549 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 13550 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 13551 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 13552 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 13553 | #endif 13554 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 13555 | case_stmt( 1, (void)0;) 13556 | } 13557 | 13558 | #undef exprtk_loop 13559 | #undef case_stmt 13560 | 13561 | return vec0_node_ptr_->value(); 13562 | } 13563 | 13564 | vector_node_ptr vec() const exprtk_override 13565 | { 13566 | return vec0_node_ptr_; 13567 | } 13568 | 13569 | vector_node_ptr vec() exprtk_override 13570 | { 13571 | return vec0_node_ptr_; 13572 | } 13573 | 13574 | inline typename expression_node<T>::node_type type() const exprtk_override 13575 | { 13576 | return expression_node<T>::e_vecopvecass; 13577 | } 13578 | 13579 | inline bool valid() const exprtk_override 13580 | { 13581 | return initialised_; 13582 | } 13583 | 13584 | std::size_t size() const exprtk_override 13585 | { 13586 | return std::min( 13587 | vec0_node_ptr_->vec_holder().size(), 13588 | vec1_node_ptr_->vec_holder().size()); 13589 | } 13590 | 13591 | std::size_t base_size() const exprtk_override 13592 | { 13593 | return std::min( 13594 | vec0_node_ptr_->vec_holder().base_size(), 13595 | vec1_node_ptr_->vec_holder().base_size()); 13596 | } 13597 | 13598 | vds_t& vds() exprtk_override 13599 | { 13600 | return vds_; 13601 | } 13602 | 13603 | const vds_t& vds() const exprtk_override 13604 | { 13605 | return vds_; 13606 | } 13607 | 13608 | bool side_effect() const exprtk_override 13609 | { 13610 | return true; 13611 | } 13612 | 13613 | private: 13614 | 13615 | vector_node<T>* vec0_node_ptr_; 13616 | vector_node<T>* vec1_node_ptr_; 13617 | bool initialised_; 13618 | vds_t vds_; 13619 | }; 13620 | 13621 | template <typename T> 13622 | struct memory_context_t 13623 | { 13624 | typedef vector_node<T>* vector_node_ptr; 13625 | typedef vector_holder<T> vector_holder_t; 13626 | typedef vector_holder_t* vector_holder_ptr; 13627 | 13628 | memory_context_t() 13629 | : temp_(0) 13630 | , temp_vec_node_(0) 13631 | {} 13632 | 13633 | void clear() 13634 | { 13635 | delete temp_vec_node_; 13636 | delete temp_; 13637 | } 13638 | 13639 | vector_holder_ptr temp_; 13640 | vector_node_ptr temp_vec_node_; 13641 | }; 13642 | 13643 | template <typename T> 13644 | inline memory_context_t<T> make_memory_context(vector_holder<T>& vec_holder, 13645 | vec_data_store<T>& vds) 13646 | { 13647 | memory_context_t<T> result_ctxt; 13648 | 13649 | result_ctxt.temp_ = (vec_holder.rebaseable()) ? 13650 | new vector_holder<T>(vec_holder,vds) : 13651 | new vector_holder<T>(vds) ; 13652 | 13653 | result_ctxt.temp_vec_node_ = new vector_node<T>(vds,result_ctxt.temp_); 13654 | 13655 | return result_ctxt; 13656 | } 13657 | 13658 | template <typename T> 13659 | inline memory_context_t<T> make_memory_context(vector_holder<T>& vec_holder0, 13660 | vector_holder<T>& vec_holder1, 13661 | vec_data_store<T>& vds) 13662 | { 13663 | memory_context_t<T> result_ctxt; 13664 | 13665 | if (!vec_holder0.rebaseable() && !vec_holder1.rebaseable()) 13666 | result_ctxt.temp_ = new vector_holder<T>(vds); 13667 | else if (vec_holder0.rebaseable() && !vec_holder1.rebaseable()) 13668 | result_ctxt.temp_ = new vector_holder<T>(vec_holder0,vds); 13669 | else if (!vec_holder0.rebaseable() && vec_holder1.rebaseable()) 13670 | result_ctxt.temp_ = new vector_holder<T>(vec_holder1,vds); 13671 | else 13672 | { 13673 | result_ctxt.temp_ = (vec_holder0.base_size() >= vec_holder1.base_size()) ? 13674 | new vector_holder<T>(vec_holder0, vds) : 13675 | new vector_holder<T>(vec_holder1, vds) ; 13676 | } 13677 | 13678 | result_ctxt.temp_vec_node_ = new vector_node<T>(vds,result_ctxt.temp_); 13679 | 13680 | return result_ctxt; 13681 | } 13682 | 13683 | template <typename T, typename Operation> 13684 | class vec_binop_vecvec_node exprtk_final 13685 | : public binary_node <T> 13686 | , public vector_interface<T> 13687 | { 13688 | public: 13689 | 13690 | typedef expression_node<T>* expression_ptr; 13691 | typedef vector_node<T>* vector_node_ptr; 13692 | typedef vector_holder<T> vector_holder_t; 13693 | typedef vector_holder_t* vector_holder_ptr; 13694 | typedef vec_data_store<T> vds_t; 13695 | typedef memory_context_t<T> memory_context; 13696 | 13697 | using binary_node<T>::branch; 13698 | 13699 | vec_binop_vecvec_node(const operator_type& opr, 13700 | expression_ptr branch0, 13701 | expression_ptr branch1) 13702 | : binary_node<T>(opr, branch0, branch1) 13703 | , vec0_node_ptr_(0) 13704 | , vec1_node_ptr_(0) 13705 | , initialised_(false) 13706 | { 13707 | bool v0_is_ivec = false; 13708 | bool v1_is_ivec = false; 13709 | 13710 | if (is_vector_node(branch(0))) 13711 | { 13712 | vec0_node_ptr_ = static_cast<vector_node_ptr>(branch(0)); 13713 | } 13714 | else if (is_ivector_node(branch(0))) 13715 | { 13716 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 13717 | 13718 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(0)))) 13719 | { 13720 | vec0_node_ptr_ = vi->vec(); 13721 | v0_is_ivec = true; 13722 | } 13723 | } 13724 | 13725 | if (is_vector_node(branch(1))) 13726 | { 13727 | vec1_node_ptr_ = static_cast<vector_node_ptr>(branch(1)); 13728 | } 13729 | else if (is_ivector_node(branch(1))) 13730 | { 13731 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 13732 | 13733 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1)))) 13734 | { 13735 | vec1_node_ptr_ = vi->vec(); 13736 | v1_is_ivec = true; 13737 | } 13738 | } 13739 | 13740 | if (vec0_node_ptr_ && vec1_node_ptr_) 13741 | { 13742 | vector_holder<T>& vec0 = vec0_node_ptr_->vec_holder(); 13743 | vector_holder<T>& vec1 = vec1_node_ptr_->vec_holder(); 13744 | 13745 | if (v0_is_ivec && (vec0.base_size() <= vec1.base_size())) 13746 | { 13747 | vds_ = vds_t(vec0_node_ptr_->vds()); 13748 | } 13749 | else if (v1_is_ivec && (vec1.base_size() <= vec0.base_size())) 13750 | { 13751 | vds_ = vds_t(vec1_node_ptr_->vds()); 13752 | } 13753 | else 13754 | { 13755 | vds_ = vds_t(std::min(vec0.base_size(),vec1.base_size())); 13756 | } 13757 | 13758 | memory_context_ = make_memory_context(vec0, vec1, vds()); 13759 | 13760 | initialised_ = 13761 | (size() <= base_size()) && 13762 | binary_node<T>::valid(); 13763 | } 13764 | 13765 | assert(valid()); 13766 | } 13767 | 13768 | ~vec_binop_vecvec_node() 13769 | { 13770 | memory_context_.clear(); 13771 | } 13772 | 13773 | inline T value() const exprtk_override 13774 | { 13775 | branch(0)->value(); 13776 | branch(1)->value(); 13777 | 13778 | const T* vec0 = vec0_node_ptr_->vds().data(); 13779 | const T* vec1 = vec1_node_ptr_->vds().data(); 13780 | T* vec2 = vds().data(); 13781 | 13782 | loop_unroll::details lud(size()); 13783 | const T* upper_bound = vec2 + lud.upper_bound; 13784 | 13785 | while (vec2 < upper_bound) 13786 | { 13787 | #define exprtk_loop(N) \ 13788 | vec2[N] = Operation::process(vec0[N], vec1[N]); \ 13789 | 13790 | exprtk_loop( 0) exprtk_loop( 1) 13791 | exprtk_loop( 2) exprtk_loop( 3) 13792 | #ifndef exprtk_disable_superscalar_unroll 13793 | exprtk_loop( 4) exprtk_loop( 5) 13794 | exprtk_loop( 6) exprtk_loop( 7) 13795 | exprtk_loop( 8) exprtk_loop( 9) 13796 | exprtk_loop(10) exprtk_loop(11) 13797 | exprtk_loop(12) exprtk_loop(13) 13798 | exprtk_loop(14) exprtk_loop(15) 13799 | #endif 13800 | 13801 | vec0 += lud.batch_size; 13802 | vec1 += lud.batch_size; 13803 | vec2 += lud.batch_size; 13804 | } 13805 | 13806 | int i = 0; 13807 | 13808 | switch (lud.remainder) 13809 | { 13810 | #define case_stmt(N) \ 13811 | case N : { vec2[i] = Operation::process(vec0[i], vec1[i]); ++i; } \ 13812 | exprtk_fallthrough \ 13813 | 13814 | #ifndef exprtk_disable_superscalar_unroll 13815 | case_stmt(15) case_stmt(14) 13816 | case_stmt(13) case_stmt(12) 13817 | case_stmt(11) case_stmt(10) 13818 | case_stmt( 9) case_stmt( 8) 13819 | case_stmt( 7) case_stmt( 6) 13820 | case_stmt( 5) case_stmt( 4) 13821 | #endif 13822 | case_stmt( 3) case_stmt( 2) 13823 | case_stmt( 1) 13824 | default: break; 13825 | } 13826 | 13827 | #undef exprtk_loop 13828 | #undef case_stmt 13829 | 13830 | return (vds().data())[0]; 13831 | } 13832 | 13833 | vector_node_ptr vec() const exprtk_override 13834 | { 13835 | return memory_context_.temp_vec_node_; 13836 | } 13837 | 13838 | vector_node_ptr vec() exprtk_override 13839 | { 13840 | return memory_context_.temp_vec_node_; 13841 | } 13842 | 13843 | inline typename expression_node<T>::node_type type() const exprtk_override 13844 | { 13845 | return expression_node<T>::e_vecvecarith; 13846 | } 13847 | 13848 | inline bool valid() const exprtk_override 13849 | { 13850 | return initialised_; 13851 | } 13852 | 13853 | std::size_t size() const exprtk_override 13854 | { 13855 | return std::min( 13856 | vec0_node_ptr_->vec_holder().size(), 13857 | vec1_node_ptr_->vec_holder().size()); 13858 | } 13859 | 13860 | std::size_t base_size() const exprtk_override 13861 | { 13862 | return std::min( 13863 | vec0_node_ptr_->vec_holder().base_size(), 13864 | vec1_node_ptr_->vec_holder().base_size()); 13865 | } 13866 | 13867 | vds_t& vds() exprtk_override 13868 | { 13869 | return vds_; 13870 | } 13871 | 13872 | const vds_t& vds() const exprtk_override 13873 | { 13874 | return vds_; 13875 | } 13876 | 13877 | private: 13878 | 13879 | vector_node_ptr vec0_node_ptr_; 13880 | vector_node_ptr vec1_node_ptr_; 13881 | bool initialised_; 13882 | vds_t vds_; 13883 | memory_context memory_context_; 13884 | }; 13885 | 13886 | template <typename T, typename Operation> 13887 | class vec_binop_vecval_node exprtk_final 13888 | : public binary_node <T> 13889 | , public vector_interface<T> 13890 | { 13891 | public: 13892 | 13893 | typedef expression_node<T>* expression_ptr; 13894 | typedef vector_node<T>* vector_node_ptr; 13895 | typedef vector_holder<T> vector_holder_t; 13896 | typedef vector_holder_t* vector_holder_ptr; 13897 | typedef vec_data_store<T> vds_t; 13898 | typedef memory_context_t<T> memory_context; 13899 | 13900 | using binary_node<T>::branch; 13901 | 13902 | vec_binop_vecval_node(const operator_type& opr, 13903 | expression_ptr branch0, 13904 | expression_ptr branch1) 13905 | : binary_node<T>(opr, branch0, branch1) 13906 | , vec0_node_ptr_(0) 13907 | { 13908 | bool v0_is_ivec = false; 13909 | 13910 | if (is_vector_node(branch(0))) 13911 | { 13912 | vec0_node_ptr_ = static_cast<vector_node_ptr>(branch(0)); 13913 | } 13914 | else if (is_ivector_node(branch(0))) 13915 | { 13916 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 13917 | 13918 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(0)))) 13919 | { 13920 | vec0_node_ptr_ = vi->vec(); 13921 | v0_is_ivec = true; 13922 | } 13923 | } 13924 | 13925 | if (vec0_node_ptr_) 13926 | { 13927 | if (v0_is_ivec) 13928 | vds() = vec0_node_ptr_->vds(); 13929 | else 13930 | vds() = vds_t(vec0_node_ptr_->base_size()); 13931 | 13932 | memory_context_ = make_memory_context(vec0_node_ptr_->vec_holder(), vds()); 13933 | } 13934 | 13935 | assert(valid()); 13936 | } 13937 | 13938 | ~vec_binop_vecval_node() 13939 | { 13940 | memory_context_.clear(); 13941 | } 13942 | 13943 | inline T value() const exprtk_override 13944 | { 13945 | branch(0)->value(); 13946 | const T v = branch(1)->value(); 13947 | 13948 | const T* vec0 = vec0_node_ptr_->vds().data(); 13949 | T* vec1 = vds().data(); 13950 | 13951 | loop_unroll::details lud(size()); 13952 | const T* upper_bound = vec0 + lud.upper_bound; 13953 | 13954 | while (vec0 < upper_bound) 13955 | { 13956 | #define exprtk_loop(N) \ 13957 | vec1[N] = Operation::process(vec0[N], v); \ 13958 | 13959 | exprtk_loop( 0) exprtk_loop( 1) 13960 | exprtk_loop( 2) exprtk_loop( 3) 13961 | #ifndef exprtk_disable_superscalar_unroll 13962 | exprtk_loop( 4) exprtk_loop( 5) 13963 | exprtk_loop( 6) exprtk_loop( 7) 13964 | exprtk_loop( 8) exprtk_loop( 9) 13965 | exprtk_loop(10) exprtk_loop(11) 13966 | exprtk_loop(12) exprtk_loop(13) 13967 | exprtk_loop(14) exprtk_loop(15) 13968 | #endif 13969 | 13970 | vec0 += lud.batch_size; 13971 | vec1 += lud.batch_size; 13972 | } 13973 | 13974 | int i = 0; 13975 | 13976 | switch (lud.remainder) 13977 | { 13978 | #define case_stmt(N,fall_through) \ 13979 | case N : { vec1[i] = Operation::process(vec0[i], v); ++i; } \ 13980 | fall_through \ 13981 | 13982 | #ifndef exprtk_disable_superscalar_unroll 13983 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 13984 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 13985 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 13986 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 13987 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 13988 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 13989 | #endif 13990 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 13991 | case_stmt( 1, (void)0;) 13992 | } 13993 | 13994 | #undef exprtk_loop 13995 | #undef case_stmt 13996 | 13997 | return (vds().data())[0]; 13998 | } 13999 | 14000 | vector_node_ptr vec() const exprtk_override 14001 | { 14002 | return memory_context_.temp_vec_node_; 14003 | } 14004 | 14005 | vector_node_ptr vec() exprtk_override 14006 | { 14007 | return memory_context_.temp_vec_node_; 14008 | } 14009 | 14010 | inline typename expression_node<T>::node_type type() const exprtk_override 14011 | { 14012 | return expression_node<T>::e_vecvalarith; 14013 | } 14014 | 14015 | inline bool valid() const exprtk_override 14016 | { 14017 | return 14018 | vec0_node_ptr_ && 14019 | (size() <= base_size()) && 14020 | binary_node<T>::valid(); 14021 | } 14022 | 14023 | std::size_t size() const exprtk_override 14024 | { 14025 | return vec0_node_ptr_->size(); 14026 | } 14027 | 14028 | std::size_t base_size() const exprtk_override 14029 | { 14030 | return vec0_node_ptr_->vec_holder().base_size(); 14031 | } 14032 | 14033 | vds_t& vds() exprtk_override 14034 | { 14035 | return vds_; 14036 | } 14037 | 14038 | const vds_t& vds() const exprtk_override 14039 | { 14040 | return vds_; 14041 | } 14042 | 14043 | private: 14044 | 14045 | vector_node_ptr vec0_node_ptr_; 14046 | vds_t vds_; 14047 | memory_context memory_context_; 14048 | }; 14049 | 14050 | template <typename T, typename Operation> 14051 | class vec_binop_valvec_node exprtk_final 14052 | : public binary_node <T> 14053 | , public vector_interface<T> 14054 | { 14055 | public: 14056 | 14057 | typedef expression_node<T>* expression_ptr; 14058 | typedef vector_node<T>* vector_node_ptr; 14059 | typedef vector_holder<T> vector_holder_t; 14060 | typedef vector_holder_t* vector_holder_ptr; 14061 | typedef vec_data_store<T> vds_t; 14062 | typedef memory_context_t<T> memory_context; 14063 | 14064 | using binary_node<T>::branch; 14065 | 14066 | vec_binop_valvec_node(const operator_type& opr, 14067 | expression_ptr branch0, 14068 | expression_ptr branch1) 14069 | : binary_node<T>(opr, branch0, branch1) 14070 | , vec1_node_ptr_(0) 14071 | { 14072 | bool v1_is_ivec = false; 14073 | 14074 | if (is_vector_node(branch(1))) 14075 | { 14076 | vec1_node_ptr_ = static_cast<vector_node_ptr>(branch(1)); 14077 | } 14078 | else if (is_ivector_node(branch(1))) 14079 | { 14080 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 14081 | 14082 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1)))) 14083 | { 14084 | vec1_node_ptr_ = vi->vec(); 14085 | v1_is_ivec = true; 14086 | } 14087 | } 14088 | 14089 | if (vec1_node_ptr_) 14090 | { 14091 | if (v1_is_ivec) 14092 | vds() = vec1_node_ptr_->vds(); 14093 | else 14094 | vds() = vds_t(vec1_node_ptr_->base_size()); 14095 | 14096 | memory_context_ = make_memory_context(vec1_node_ptr_->vec_holder(), vds()); 14097 | } 14098 | 14099 | assert(valid()); 14100 | } 14101 | 14102 | ~vec_binop_valvec_node() 14103 | { 14104 | memory_context_.clear(); 14105 | } 14106 | 14107 | inline T value() const exprtk_override 14108 | { 14109 | const T v = branch(0)->value(); 14110 | branch(1)->value(); 14111 | 14112 | T* vec0 = vds().data(); 14113 | const T* vec1 = vec1_node_ptr_->vds().data(); 14114 | 14115 | loop_unroll::details lud(size()); 14116 | const T* upper_bound = vec0 + lud.upper_bound; 14117 | 14118 | while (vec0 < upper_bound) 14119 | { 14120 | #define exprtk_loop(N) \ 14121 | vec0[N] = Operation::process(v, vec1[N]); \ 14122 | 14123 | exprtk_loop( 0) exprtk_loop( 1) 14124 | exprtk_loop( 2) exprtk_loop( 3) 14125 | #ifndef exprtk_disable_superscalar_unroll 14126 | exprtk_loop( 4) exprtk_loop( 5) 14127 | exprtk_loop( 6) exprtk_loop( 7) 14128 | exprtk_loop( 8) exprtk_loop( 9) 14129 | exprtk_loop(10) exprtk_loop(11) 14130 | exprtk_loop(12) exprtk_loop(13) 14131 | exprtk_loop(14) exprtk_loop(15) 14132 | #endif 14133 | 14134 | vec0 += lud.batch_size; 14135 | vec1 += lud.batch_size; 14136 | } 14137 | 14138 | int i = 0; 14139 | 14140 | switch (lud.remainder) 14141 | { 14142 | #define case_stmt(N,fall_through) \ 14143 | case N : { vec0[i] = Operation::process(v, vec1[i]); ++i; } \ 14144 | fall_through \ 14145 | 14146 | #ifndef exprtk_disable_superscalar_unroll 14147 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 14148 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 14149 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 14150 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 14151 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 14152 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 14153 | #endif 14154 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 14155 | case_stmt( 1, (void)0;) 14156 | } 14157 | 14158 | #undef exprtk_loop 14159 | #undef case_stmt 14160 | 14161 | return (vds().data())[0]; 14162 | } 14163 | 14164 | vector_node_ptr vec() const exprtk_override 14165 | { 14166 | return memory_context_.temp_vec_node_; 14167 | } 14168 | 14169 | vector_node_ptr vec() exprtk_override 14170 | { 14171 | return memory_context_.temp_vec_node_; 14172 | } 14173 | 14174 | inline typename expression_node<T>::node_type type() const exprtk_override 14175 | { 14176 | return expression_node<T>::e_vecvalarith; 14177 | } 14178 | 14179 | inline bool valid() const exprtk_override 14180 | { 14181 | return 14182 | vec1_node_ptr_ && 14183 | (size() <= base_size()) && 14184 | (vds_.size() <= base_size()) && 14185 | binary_node<T>::valid(); 14186 | } 14187 | 14188 | std::size_t size() const exprtk_override 14189 | { 14190 | return vec1_node_ptr_->vec_holder().size(); 14191 | } 14192 | 14193 | std::size_t base_size() const exprtk_override 14194 | { 14195 | return vec1_node_ptr_->vec_holder().base_size(); 14196 | } 14197 | 14198 | vds_t& vds() exprtk_override 14199 | { 14200 | return vds_; 14201 | } 14202 | 14203 | const vds_t& vds() const exprtk_override 14204 | { 14205 | return vds_; 14206 | } 14207 | 14208 | private: 14209 | 14210 | vector_node_ptr vec1_node_ptr_; 14211 | vds_t vds_; 14212 | memory_context memory_context_; 14213 | }; 14214 | 14215 | template <typename T, typename Operation> 14216 | class unary_vector_node exprtk_final 14217 | : public unary_node <T> 14218 | , public vector_interface<T> 14219 | { 14220 | public: 14221 | 14222 | typedef expression_node<T>* expression_ptr; 14223 | typedef vector_node<T>* vector_node_ptr; 14224 | typedef vector_holder<T> vector_holder_t; 14225 | typedef vector_holder_t* vector_holder_ptr; 14226 | typedef vec_data_store<T> vds_t; 14227 | typedef memory_context_t<T> memory_context; 14228 | 14229 | using expression_node<T>::branch; 14230 | 14231 | unary_vector_node(const operator_type& opr, expression_ptr branch0) 14232 | : unary_node<T>(opr, branch0) 14233 | , vec0_node_ptr_(0) 14234 | { 14235 | bool vec0_is_ivec = false; 14236 | 14237 | if (is_vector_node(branch(0))) 14238 | { 14239 | vec0_node_ptr_ = static_cast<vector_node_ptr>(branch(0)); 14240 | } 14241 | else if (is_ivector_node(branch(0))) 14242 | { 14243 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 14244 | 14245 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(0)))) 14246 | { 14247 | vec0_node_ptr_ = vi->vec(); 14248 | vec0_is_ivec = true; 14249 | } 14250 | } 14251 | 14252 | if (vec0_node_ptr_) 14253 | { 14254 | if (vec0_is_ivec) 14255 | vds_ = vec0_node_ptr_->vds(); 14256 | else 14257 | vds_ = vds_t(vec0_node_ptr_->base_size()); 14258 | 14259 | memory_context_ = make_memory_context(vec0_node_ptr_->vec_holder(), vds()); 14260 | } 14261 | 14262 | assert(valid()); 14263 | } 14264 | 14265 | ~unary_vector_node() 14266 | { 14267 | memory_context_.clear(); 14268 | } 14269 | 14270 | inline T value() const exprtk_override 14271 | { 14272 | branch()->value(); 14273 | 14274 | const T* vec0 = vec0_node_ptr_->vds().data(); 14275 | T* vec1 = vds().data(); 14276 | 14277 | loop_unroll::details lud(size()); 14278 | const T* upper_bound = vec0 + lud.upper_bound; 14279 | 14280 | while (vec0 < upper_bound) 14281 | { 14282 | #define exprtk_loop(N) \ 14283 | vec1[N] = Operation::process(vec0[N]); \ 14284 | 14285 | exprtk_loop( 0) exprtk_loop( 1) 14286 | exprtk_loop( 2) exprtk_loop( 3) 14287 | #ifndef exprtk_disable_superscalar_unroll 14288 | exprtk_loop( 4) exprtk_loop( 5) 14289 | exprtk_loop( 6) exprtk_loop( 7) 14290 | exprtk_loop( 8) exprtk_loop( 9) 14291 | exprtk_loop(10) exprtk_loop(11) 14292 | exprtk_loop(12) exprtk_loop(13) 14293 | exprtk_loop(14) exprtk_loop(15) 14294 | #endif 14295 | 14296 | vec0 += lud.batch_size; 14297 | vec1 += lud.batch_size; 14298 | } 14299 | 14300 | int i = 0; 14301 | 14302 | switch (lud.remainder) 14303 | { 14304 | #define case_stmt(N) \ 14305 | case N : { vec1[i] = Operation::process(vec0[i]); ++i; } \ 14306 | exprtk_fallthrough \ 14307 | 14308 | #ifndef exprtk_disable_superscalar_unroll 14309 | case_stmt(15) case_stmt(14) 14310 | case_stmt(13) case_stmt(12) 14311 | case_stmt(11) case_stmt(10) 14312 | case_stmt( 9) case_stmt( 8) 14313 | case_stmt( 7) case_stmt( 6) 14314 | case_stmt( 5) case_stmt( 4) 14315 | #endif 14316 | case_stmt( 3) case_stmt( 2) 14317 | case_stmt( 1) 14318 | default: break; 14319 | } 14320 | 14321 | #undef exprtk_loop 14322 | #undef case_stmt 14323 | 14324 | return (vds().data())[0]; 14325 | } 14326 | 14327 | vector_node_ptr vec() const exprtk_override 14328 | { 14329 | return memory_context_.temp_vec_node_; 14330 | } 14331 | 14332 | vector_node_ptr vec() exprtk_override 14333 | { 14334 | return memory_context_.temp_vec_node_; 14335 | } 14336 | 14337 | inline typename expression_node<T>::node_type type() const exprtk_override 14338 | { 14339 | return expression_node<T>::e_vecunaryop; 14340 | } 14341 | 14342 | inline bool valid() const exprtk_override 14343 | { 14344 | return vec0_node_ptr_ && unary_node<T>::valid(); 14345 | } 14346 | 14347 | std::size_t size() const exprtk_override 14348 | { 14349 | return vec0_node_ptr_->vec_holder().size(); 14350 | } 14351 | 14352 | std::size_t base_size() const exprtk_override 14353 | { 14354 | return vec0_node_ptr_->vec_holder().base_size(); 14355 | } 14356 | 14357 | vds_t& vds() exprtk_override 14358 | { 14359 | return vds_; 14360 | } 14361 | 14362 | const vds_t& vds() const exprtk_override 14363 | { 14364 | return vds_; 14365 | } 14366 | 14367 | private: 14368 | 14369 | vector_node_ptr vec0_node_ptr_; 14370 | vds_t vds_; 14371 | memory_context memory_context_; 14372 | }; 14373 | 14374 | template <typename T> 14375 | class conditional_vector_node exprtk_final 14376 | : public expression_node <T> 14377 | , public vector_interface<T> 14378 | { 14379 | public: 14380 | 14381 | typedef expression_node <T>* expression_ptr; 14382 | typedef vector_interface<T>* vec_interface_ptr; 14383 | typedef vector_node <T>* vector_node_ptr; 14384 | typedef vector_holder <T> vector_holder_t; 14385 | typedef vector_holder_t* vector_holder_ptr; 14386 | typedef vec_data_store <T> vds_t; 14387 | typedef memory_context_t<T> memory_context; 14388 | typedef std::pair<expression_ptr,bool> branch_t; 14389 | 14390 | conditional_vector_node(expression_ptr condition, 14391 | expression_ptr consequent, 14392 | expression_ptr alternative) 14393 | : consequent_node_ptr_ (0) 14394 | , alternative_node_ptr_(0) 14395 | , temp_vec_node_ (0) 14396 | , temp_ (0) 14397 | , result_vec_size_ (0) 14398 | , initialised_ (false) 14399 | { 14400 | construct_branch_pair(condition_ , condition ); 14401 | construct_branch_pair(consequent_ , consequent ); 14402 | construct_branch_pair(alternative_, alternative); 14403 | 14404 | if (details::is_ivector_node(consequent_.first)) 14405 | { 14406 | vec_interface_ptr ivec_ptr = dynamic_cast<vec_interface_ptr>(consequent_.first); 14407 | 14408 | if (0 != ivec_ptr) 14409 | { 14410 | consequent_node_ptr_ = ivec_ptr->vec(); 14411 | } 14412 | } 14413 | 14414 | if (details::is_ivector_node(alternative_.first)) 14415 | { 14416 | vec_interface_ptr ivec_ptr = dynamic_cast<vec_interface_ptr>(alternative_.first); 14417 | 14418 | if (0 != ivec_ptr) 14419 | { 14420 | alternative_node_ptr_ = ivec_ptr->vec(); 14421 | } 14422 | } 14423 | 14424 | if (consequent_node_ptr_ && alternative_node_ptr_) 14425 | { 14426 | const std::size_t vec_size = 14427 | std::max(consequent_node_ptr_ ->vec_holder().base_size(), 14428 | alternative_node_ptr_->vec_holder().base_size()); 14429 | 14430 | vds_ = vds_t(vec_size); 14431 | memory_context_ = make_memory_context( 14432 | consequent_node_ptr_ ->vec_holder(), 14433 | alternative_node_ptr_->vec_holder(), 14434 | vds()); 14435 | 14436 | initialised_ = (vec_size > 0); 14437 | } 14438 | 14439 | assert(initialised_); 14440 | } 14441 | 14442 | ~conditional_vector_node() 14443 | { 14444 | memory_context_.clear(); 14445 | } 14446 | 14447 | inline T value() const exprtk_override 14448 | { 14449 | T result = T(0); 14450 | T* source_vector = 0; 14451 | T* result_vector = vds().data(); 14452 | 14453 | if (is_true(condition_)) 14454 | { 14455 | result = consequent_.first->value(); 14456 | source_vector = consequent_node_ptr_->vds().data(); 14457 | result_vec_size_ = consequent_node_ptr_->size(); 14458 | } 14459 | else 14460 | { 14461 | result = alternative_.first->value(); 14462 | source_vector = alternative_node_ptr_->vds().data(); 14463 | result_vec_size_ = alternative_node_ptr_->size(); 14464 | } 14465 | 14466 | for (std::size_t i = 0; i < result_vec_size_; ++i) 14467 | { 14468 | result_vector[i] = source_vector[i]; 14469 | } 14470 | 14471 | return result; 14472 | } 14473 | 14474 | vector_node_ptr vec() const exprtk_override 14475 | { 14476 | return memory_context_.temp_vec_node_; 14477 | } 14478 | 14479 | vector_node_ptr vec() exprtk_override 14480 | { 14481 | return memory_context_.temp_vec_node_; 14482 | } 14483 | 14484 | inline typename expression_node<T>::node_type type() const exprtk_override 14485 | { 14486 | return expression_node<T>::e_vecondition; 14487 | } 14488 | 14489 | inline bool valid() const exprtk_override 14490 | { 14491 | return 14492 | initialised_ && 14493 | condition_ .first && condition_ .first->valid() && 14494 | consequent_ .first && consequent_ .first->valid() && 14495 | alternative_.first && alternative_.first->valid() && 14496 | size() <= base_size(); 14497 | } 14498 | 14499 | std::size_t size() const exprtk_override 14500 | { 14501 | return result_vec_size_; 14502 | } 14503 | 14504 | std::size_t base_size() const exprtk_override 14505 | { 14506 | return std::min( 14507 | consequent_node_ptr_ ->vec_holder().base_size(), 14508 | alternative_node_ptr_->vec_holder().base_size()); 14509 | } 14510 | 14511 | vds_t& vds() exprtk_override 14512 | { 14513 | return vds_; 14514 | } 14515 | 14516 | const vds_t& vds() const exprtk_override 14517 | { 14518 | return vds_; 14519 | } 14520 | 14521 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 14522 | { 14523 | expression_node<T>::ndb_t::collect(condition_ , node_delete_list); 14524 | expression_node<T>::ndb_t::collect(consequent_ , node_delete_list); 14525 | expression_node<T>::ndb_t::collect(alternative_ , node_delete_list); 14526 | } 14527 | 14528 | std::size_t node_depth() const exprtk_override 14529 | { 14530 | return expression_node<T>::ndb_t::compute_node_depth 14531 | (condition_, consequent_, alternative_); 14532 | } 14533 | 14534 | private: 14535 | 14536 | branch_t condition_; 14537 | branch_t consequent_; 14538 | branch_t alternative_; 14539 | vector_node_ptr consequent_node_ptr_; 14540 | vector_node_ptr alternative_node_ptr_; 14541 | vector_node_ptr temp_vec_node_; 14542 | vector_holder_ptr temp_; 14543 | vds_t vds_; 14544 | mutable std::size_t result_vec_size_; 14545 | bool initialised_; 14546 | memory_context memory_context_; 14547 | }; 14548 | 14549 | template <typename T> 14550 | class scand_node exprtk_final : public binary_node<T> 14551 | { 14552 | public: 14553 | 14554 | typedef expression_node<T>* expression_ptr; 14555 | using binary_node<T>::branch; 14556 | 14557 | scand_node(const operator_type& opr, 14558 | expression_ptr branch0, 14559 | expression_ptr branch1) 14560 | : binary_node<T>(opr, branch0, branch1) 14561 | { 14562 | assert(binary_node<T>::valid()); 14563 | } 14564 | 14565 | inline T value() const exprtk_override 14566 | { 14567 | return ( 14568 | std::not_equal_to<T>() 14569 | (T(0),branch(0)->value()) && 14570 | std::not_equal_to<T>() 14571 | (T(0),branch(1)->value()) 14572 | ) ? T(1) : T(0); 14573 | } 14574 | }; 14575 | 14576 | template <typename T> 14577 | class scor_node exprtk_final : public binary_node<T> 14578 | { 14579 | public: 14580 | 14581 | typedef expression_node<T>* expression_ptr; 14582 | using binary_node<T>::branch; 14583 | 14584 | scor_node(const operator_type& opr, 14585 | expression_ptr branch0, 14586 | expression_ptr branch1) 14587 | : binary_node<T>(opr, branch0, branch1) 14588 | { 14589 | assert(binary_node<T>::valid()); 14590 | } 14591 | 14592 | inline T value() const exprtk_override 14593 | { 14594 | return ( 14595 | std::not_equal_to<T>() 14596 | (T(0),branch(0)->value()) || 14597 | std::not_equal_to<T>() 14598 | (T(0),branch(1)->value()) 14599 | ) ? T(1) : T(0); 14600 | } 14601 | }; 14602 | 14603 | template <typename T, typename IFunction, std::size_t N> 14604 | class function_N_node exprtk_final : public expression_node<T> 14605 | { 14606 | public: 14607 | 14608 | // Function of N parameters. 14609 | typedef expression_node<T>* expression_ptr; 14610 | typedef std::pair<expression_ptr,bool> branch_t; 14611 | typedef IFunction ifunction; 14612 | 14613 | explicit function_N_node(ifunction* func) 14614 | : function_((N == func->param_count) ? func : reinterpret_cast<ifunction*>(0)) 14615 | , parameter_count_(func->param_count) 14616 | , initialised_(false) 14617 | {} 14618 | 14619 | template <std::size_t NumBranches> 14620 | bool init_branches(expression_ptr (&b)[NumBranches]) 14621 | { 14622 | // Needed for incompetent and broken msvc compiler versions 14623 | #ifdef _MSC_VER 14624 | #pragma warning(push) 14625 | #pragma warning(disable: 4127) 14626 | #endif 14627 | 14628 | if (N != NumBranches) 14629 | { 14630 | return false; 14631 | } 14632 | 14633 | for (std::size_t i = 0; i < NumBranches; ++i) 14634 | { 14635 | if (b[i] && b[i]->valid()) 14636 | branch_[i] = std::make_pair(b[i],branch_deletable(b[i])); 14637 | else 14638 | return false; 14639 | } 14640 | 14641 | initialised_ = function_; 14642 | assert(valid()); 14643 | return initialised_; 14644 | 14645 | #ifdef _MSC_VER 14646 | #pragma warning(pop) 14647 | #endif 14648 | } 14649 | 14650 | inline bool operator <(const function_N_node<T,IFunction,N>& fn) const 14651 | { 14652 | return this < (&fn); 14653 | } 14654 | 14655 | inline T value() const exprtk_override 14656 | { 14657 | // Needed for incompetent and broken msvc compiler versions 14658 | #ifdef _MSC_VER 14659 | #pragma warning(push) 14660 | #pragma warning(disable: 4127) 14661 | #endif 14662 | 14663 | T v[N]; 14664 | evaluate_branches<T,N>::execute(v,branch_); 14665 | return invoke<T,N>::execute(*function_,v); 14666 | 14667 | #ifdef _MSC_VER 14668 | #pragma warning(pop) 14669 | #endif 14670 | } 14671 | 14672 | inline typename expression_node<T>::node_type type() const exprtk_override 14673 | { 14674 | return expression_node<T>::e_function; 14675 | } 14676 | 14677 | inline bool valid() const exprtk_override 14678 | { 14679 | return initialised_; 14680 | } 14681 | 14682 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 14683 | { 14684 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 14685 | } 14686 | 14687 | std::size_t node_depth() const exprtk_override 14688 | { 14689 | return expression_node<T>::ndb_t::template compute_node_depth<N>(branch_); 14690 | } 14691 | 14692 | template <typename T_, std::size_t BranchCount> 14693 | struct evaluate_branches 14694 | { 14695 | static inline void execute(T_ (&v)[BranchCount], const branch_t (&b)[BranchCount]) 14696 | { 14697 | for (std::size_t i = 0; i < BranchCount; ++i) 14698 | { 14699 | v[i] = b[i].first->value(); 14700 | } 14701 | } 14702 | }; 14703 | 14704 | template <typename T_> 14705 | struct evaluate_branches <T_,6> 14706 | { 14707 | static inline void execute(T_ (&v)[6], const branch_t (&b)[6]) 14708 | { 14709 | v[0] = b[0].first->value(); 14710 | v[1] = b[1].first->value(); 14711 | v[2] = b[2].first->value(); 14712 | v[3] = b[3].first->value(); 14713 | v[4] = b[4].first->value(); 14714 | v[5] = b[5].first->value(); 14715 | } 14716 | }; 14717 | 14718 | template <typename T_> 14719 | struct evaluate_branches <T_,5> 14720 | { 14721 | static inline void execute(T_ (&v)[5], const branch_t (&b)[5]) 14722 | { 14723 | v[0] = b[0].first->value(); 14724 | v[1] = b[1].first->value(); 14725 | v[2] = b[2].first->value(); 14726 | v[3] = b[3].first->value(); 14727 | v[4] = b[4].first->value(); 14728 | } 14729 | }; 14730 | 14731 | template <typename T_> 14732 | struct evaluate_branches <T_,4> 14733 | { 14734 | static inline void execute(T_ (&v)[4], const branch_t (&b)[4]) 14735 | { 14736 | v[0] = b[0].first->value(); 14737 | v[1] = b[1].first->value(); 14738 | v[2] = b[2].first->value(); 14739 | v[3] = b[3].first->value(); 14740 | } 14741 | }; 14742 | 14743 | template <typename T_> 14744 | struct evaluate_branches <T_,3> 14745 | { 14746 | static inline void execute(T_ (&v)[3], const branch_t (&b)[3]) 14747 | { 14748 | v[0] = b[0].first->value(); 14749 | v[1] = b[1].first->value(); 14750 | v[2] = b[2].first->value(); 14751 | } 14752 | }; 14753 | 14754 | template <typename T_> 14755 | struct evaluate_branches <T_,2> 14756 | { 14757 | static inline void execute(T_ (&v)[2], const branch_t (&b)[2]) 14758 | { 14759 | v[0] = b[0].first->value(); 14760 | v[1] = b[1].first->value(); 14761 | } 14762 | }; 14763 | 14764 | template <typename T_> 14765 | struct evaluate_branches <T_,1> 14766 | { 14767 | static inline void execute(T_ (&v)[1], const branch_t (&b)[1]) 14768 | { 14769 | v[0] = b[0].first->value(); 14770 | } 14771 | }; 14772 | 14773 | template <typename T_, std::size_t ParamCount> 14774 | struct invoke { static inline T execute(ifunction&, branch_t (&)[ParamCount]) { return std::numeric_limits<T_>::quiet_NaN(); } }; 14775 | 14776 | template <typename T_> 14777 | struct invoke<T_,20> 14778 | { 14779 | static inline T_ execute(ifunction& f, T_ (&v)[20]) 14780 | { 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]); } 14781 | }; 14782 | 14783 | template <typename T_> 14784 | struct invoke<T_,19> 14785 | { 14786 | static inline T_ execute(ifunction& f, T_ (&v)[19]) 14787 | { 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]); } 14788 | }; 14789 | 14790 | template <typename T_> 14791 | struct invoke<T_,18> 14792 | { 14793 | static inline T_ execute(ifunction& f, T_ (&v)[18]) 14794 | { 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]); } 14795 | }; 14796 | 14797 | template <typename T_> 14798 | struct invoke<T_,17> 14799 | { 14800 | static inline T_ execute(ifunction& f, T_ (&v)[17]) 14801 | { 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]); } 14802 | }; 14803 | 14804 | template <typename T_> 14805 | struct invoke<T_,16> 14806 | { 14807 | static inline T_ execute(ifunction& f, T_ (&v)[16]) 14808 | { 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]); } 14809 | }; 14810 | 14811 | template <typename T_> 14812 | struct invoke<T_,15> 14813 | { 14814 | static inline T_ execute(ifunction& f, T_ (&v)[15]) 14815 | { 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]); } 14816 | }; 14817 | 14818 | template <typename T_> 14819 | struct invoke<T_,14> 14820 | { 14821 | static inline T_ execute(ifunction& f, T_ (&v)[14]) 14822 | { 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]); } 14823 | }; 14824 | 14825 | template <typename T_> 14826 | struct invoke<T_,13> 14827 | { 14828 | static inline T_ execute(ifunction& f, T_ (&v)[13]) 14829 | { 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]); } 14830 | }; 14831 | 14832 | template <typename T_> 14833 | struct invoke<T_,12> 14834 | { 14835 | static inline T_ execute(ifunction& f, T_ (&v)[12]) 14836 | { 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]); } 14837 | }; 14838 | 14839 | template <typename T_> 14840 | struct invoke<T_,11> 14841 | { 14842 | static inline T_ execute(ifunction& f, T_ (&v)[11]) 14843 | { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9], v[10]); } 14844 | }; 14845 | 14846 | template <typename T_> 14847 | struct invoke<T_,10> 14848 | { 14849 | static inline T_ execute(ifunction& f, T_ (&v)[10]) 14850 | { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9]); } 14851 | }; 14852 | 14853 | template <typename T_> 14854 | struct invoke<T_,9> 14855 | { 14856 | static inline T_ execute(ifunction& f, T_ (&v)[9]) 14857 | { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8]); } 14858 | }; 14859 | 14860 | template <typename T_> 14861 | struct invoke<T_,8> 14862 | { 14863 | static inline T_ execute(ifunction& f, T_ (&v)[8]) 14864 | { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]); } 14865 | }; 14866 | 14867 | template <typename T_> 14868 | struct invoke<T_,7> 14869 | { 14870 | static inline T_ execute(ifunction& f, T_ (&v)[7]) 14871 | { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6]); } 14872 | }; 14873 | 14874 | template <typename T_> 14875 | struct invoke<T_,6> 14876 | { 14877 | static inline T_ execute(ifunction& f, T_ (&v)[6]) 14878 | { return f(v[0], v[1], v[2], v[3], v[4], v[5]); } 14879 | }; 14880 | 14881 | template <typename T_> 14882 | struct invoke<T_,5> 14883 | { 14884 | static inline T_ execute(ifunction& f, T_ (&v)[5]) 14885 | { return f(v[0], v[1], v[2], v[3], v[4]); } 14886 | }; 14887 | 14888 | template <typename T_> 14889 | struct invoke<T_,4> 14890 | { 14891 | static inline T_ execute(ifunction& f, T_ (&v)[4]) 14892 | { return f(v[0], v[1], v[2], v[3]); } 14893 | }; 14894 | 14895 | template <typename T_> 14896 | struct invoke<T_,3> 14897 | { 14898 | static inline T_ execute(ifunction& f, T_ (&v)[3]) 14899 | { return f(v[0], v[1], v[2]); } 14900 | }; 14901 | 14902 | template <typename T_> 14903 | struct invoke<T_,2> 14904 | { 14905 | static inline T_ execute(ifunction& f, T_ (&v)[2]) 14906 | { return f(v[0], v[1]); } 14907 | }; 14908 | 14909 | template <typename T_> 14910 | struct invoke<T_,1> 14911 | { 14912 | static inline T_ execute(ifunction& f, T_ (&v)[1]) 14913 | { return f(v[0]); } 14914 | }; 14915 | 14916 | private: 14917 | 14918 | ifunction* function_; 14919 | std::size_t parameter_count_; 14920 | branch_t branch_[N]; 14921 | bool initialised_; 14922 | }; 14923 | 14924 | template <typename T, typename IFunction> 14925 | class function_N_node<T,IFunction,0> exprtk_final : public expression_node<T> 14926 | { 14927 | public: 14928 | 14929 | typedef expression_node<T>* expression_ptr; 14930 | typedef IFunction ifunction; 14931 | 14932 | explicit function_N_node(ifunction* func) 14933 | : function_((0 == func->param_count) ? func : reinterpret_cast<ifunction*>(0)) 14934 | { 14935 | assert(valid()); 14936 | } 14937 | 14938 | inline bool operator <(const function_N_node<T,IFunction,0>& fn) const 14939 | { 14940 | return this < (&fn); 14941 | } 14942 | 14943 | inline T value() const exprtk_override 14944 | { 14945 | return (*function_)(); 14946 | } 14947 | 14948 | inline typename expression_node<T>::node_type type() const exprtk_override 14949 | { 14950 | return expression_node<T>::e_function; 14951 | } 14952 | 14953 | inline bool valid() const exprtk_override 14954 | { 14955 | return function_; 14956 | } 14957 | 14958 | private: 14959 | 14960 | ifunction* function_; 14961 | }; 14962 | 14963 | template <typename T, typename VarArgFunction> 14964 | class vararg_function_node exprtk_final : public expression_node<T> 14965 | { 14966 | public: 14967 | 14968 | typedef expression_node<T>* expression_ptr; 14969 | 14970 | vararg_function_node(VarArgFunction* func, 14971 | const std::vector<expression_ptr>& arg_list) 14972 | : function_(func) 14973 | , arg_list_(arg_list) 14974 | { 14975 | value_list_.resize(arg_list.size(),std::numeric_limits<T>::quiet_NaN()); 14976 | assert(valid()); 14977 | } 14978 | 14979 | inline bool operator <(const vararg_function_node<T,VarArgFunction>& fn) const 14980 | { 14981 | return this < (&fn); 14982 | } 14983 | 14984 | inline T value() const exprtk_override 14985 | { 14986 | populate_value_list(); 14987 | return (*function_)(value_list_); 14988 | } 14989 | 14990 | inline typename expression_node<T>::node_type type() const exprtk_override 14991 | { 14992 | return expression_node<T>::e_vafunction; 14993 | } 14994 | 14995 | inline bool valid() const exprtk_override 14996 | { 14997 | return function_; 14998 | } 14999 | 15000 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 15001 | { 15002 | for (std::size_t i = 0; i < arg_list_.size(); ++i) 15003 | { 15004 | if (arg_list_[i] && !details::is_variable_node(arg_list_[i])) 15005 | { 15006 | node_delete_list.push_back(&arg_list_[i]); 15007 | } 15008 | } 15009 | } 15010 | 15011 | std::size_t node_depth() const exprtk_override 15012 | { 15013 | return expression_node<T>::ndb_t::compute_node_depth(arg_list_); 15014 | } 15015 | 15016 | private: 15017 | 15018 | inline void populate_value_list() const 15019 | { 15020 | for (std::size_t i = 0; i < arg_list_.size(); ++i) 15021 | { 15022 | value_list_[i] = arg_list_[i]->value(); 15023 | } 15024 | } 15025 | 15026 | VarArgFunction* function_; 15027 | std::vector<expression_ptr> arg_list_; 15028 | mutable std::vector<T> value_list_; 15029 | }; 15030 | 15031 | template <typename T, typename GenericFunction> 15032 | class generic_function_node : public expression_node<T> 15033 | { 15034 | public: 15035 | 15036 | typedef type_store<T> type_store_t; 15037 | typedef expression_node<T>* expression_ptr; 15038 | typedef variable_node<T> variable_node_t; 15039 | typedef vector_node<T> vector_node_t; 15040 | typedef variable_node_t* variable_node_ptr_t; 15041 | typedef vector_node_t* vector_node_ptr_t; 15042 | typedef range_interface<T> range_interface_t; 15043 | typedef range_data_type<T> range_data_type_t; 15044 | typedef typename range_interface<T>::range_t range_t; 15045 | 15046 | typedef std::pair<expression_ptr,bool> branch_t; 15047 | typedef vector_holder<T>* vh_t; 15048 | typedef vector_view<T>* vecview_t; 15049 | 15050 | typedef std::vector<T> tmp_vs_t; 15051 | typedef std::vector<type_store_t> typestore_list_t; 15052 | typedef std::vector<range_data_type_t> range_list_t; 15053 | 15054 | explicit generic_function_node(const std::vector<expression_ptr>& arg_list, 15055 | GenericFunction* func = reinterpret_cast<GenericFunction*>(0)) 15056 | : function_(func) 15057 | , arg_list_(arg_list) 15058 | {} 15059 | 15060 | virtual ~generic_function_node() 15061 | { 15062 | for (std::size_t i = 0; i < vv_list_.size(); ++i) 15063 | { 15064 | vecview_t& vv = vv_list_[i]; 15065 | if (vv) 15066 | { 15067 | if (typestore_list_[i].vec_data) 15068 | { 15069 | vv->remove_ref(&typestore_list_[i].vec_data); 15070 | } 15071 | 15072 | vv->remove_size_ref(&typestore_list_[i].size); 15073 | typestore_list_[i].vec_data = 0; 15074 | } 15075 | } 15076 | } 15077 | 15078 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 15079 | { 15080 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 15081 | } 15082 | 15083 | std::size_t node_depth() const exprtk_override exprtk_final 15084 | { 15085 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 15086 | } 15087 | 15088 | virtual bool init_branches() 15089 | { 15090 | expr_as_vec1_store_.resize(arg_list_.size(), T(0) ); 15091 | typestore_list_ .resize(arg_list_.size(), type_store_t() ); 15092 | range_list_ .resize(arg_list_.size(), range_data_type_t()); 15093 | branch_ .resize(arg_list_.size(), branch_t(reinterpret_cast<expression_ptr>(0),false)); 15094 | vv_list_ .resize(arg_list_.size(), vecview_t(0)); 15095 | 15096 | for (std::size_t i = 0; i < arg_list_.size(); ++i) 15097 | { 15098 | type_store_t& ts = typestore_list_[i]; 15099 | 15100 | if (0 == arg_list_[i]) 15101 | return false; 15102 | else if (is_ivector_node(arg_list_[i])) 15103 | { 15104 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 15105 | 15106 | if (0 == (vi = dynamic_cast<vector_interface<T>*>(arg_list_[i]))) 15107 | return false; 15108 | 15109 | ts.size = vi->size(); 15110 | ts.data = vi->vds().data(); 15111 | ts.type = type_store_t::e_vector; 15112 | ts.ivec = vi; 15113 | 15114 | if ( 15115 | vi->vec()->vec_holder().rebaseable() && 15116 | vi->vec()->vec_holder().rebaseable_instance() 15117 | ) 15118 | { 15119 | vv_list_[i] = vi->vec()->vec_holder().rebaseable_instance(); 15120 | vv_list_[i]->set_size_ref(&ts.size); 15121 | 15122 | if (!amalgamated_vecop(arg_list_[i])) 15123 | { 15124 | vv_list_[i]->set_ref(&ts.vec_data); 15125 | } 15126 | } 15127 | } 15128 | #ifndef exprtk_disable_string_capabilities 15129 | else if (is_generally_string_node(arg_list_[i])) 15130 | { 15131 | string_base_node<T>* sbn = reinterpret_cast<string_base_node<T>*>(0); 15132 | 15133 | if (0 == (sbn = dynamic_cast<string_base_node<T>*>(arg_list_[i]))) 15134 | return false; 15135 | 15136 | ts.size = sbn->size(); 15137 | ts.data = reinterpret_cast<void*>(const_cast<char_ptr>(sbn->base())); 15138 | ts.type = type_store_t::e_string; 15139 | 15140 | range_list_[i].data = ts.data; 15141 | range_list_[i].size = ts.size; 15142 | range_list_[i].type_size = sizeof(char); 15143 | range_list_[i].str_node = sbn; 15144 | 15145 | range_interface_t* ri = reinterpret_cast<range_interface_t*>(0); 15146 | 15147 | if (0 == (ri = dynamic_cast<range_interface_t*>(arg_list_[i]))) 15148 | return false; 15149 | 15150 | const range_t& rp = ri->range_ref(); 15151 | 15152 | if ( 15153 | rp.const_range() && 15154 | is_const_string_range_node(arg_list_[i]) 15155 | ) 15156 | { 15157 | ts.size = rp.const_size(); 15158 | ts.data = static_cast<char_ptr>(ts.data) + rp.n0_c.second; 15159 | range_list_[i].range = reinterpret_cast<range_t*>(0); 15160 | } 15161 | else 15162 | { 15163 | range_list_[i].range = &(ri->range_ref()); 15164 | range_param_list_.push_back(i); 15165 | } 15166 | } 15167 | #endif 15168 | else if (is_variable_node(arg_list_[i])) 15169 | { 15170 | variable_node_ptr_t var = variable_node_ptr_t(0); 15171 | 15172 | if (0 == (var = dynamic_cast<variable_node_ptr_t>(arg_list_[i]))) 15173 | return false; 15174 | 15175 | ts.size = 1; 15176 | ts.data = &var->ref(); 15177 | ts.type = type_store_t::e_scalar; 15178 | } 15179 | else 15180 | { 15181 | ts.size = 1; 15182 | ts.data = reinterpret_cast<void*>(&expr_as_vec1_store_[i]); 15183 | ts.type = type_store_t::e_scalar; 15184 | } 15185 | 15186 | branch_[i] = std::make_pair(arg_list_[i],branch_deletable(arg_list_[i])); 15187 | } 15188 | 15189 | return true; 15190 | } 15191 | 15192 | inline bool operator <(const generic_function_node<T,GenericFunction>& fn) const 15193 | { 15194 | return this < (&fn); 15195 | } 15196 | 15197 | inline T value() const exprtk_override 15198 | { 15199 | if (populate_value_list()) 15200 | { 15201 | typedef typename GenericFunction::parameter_list_t parameter_list_t; 15202 | 15203 | return (*function_)(parameter_list_t(typestore_list_)); 15204 | } 15205 | 15206 | return std::numeric_limits<T>::quiet_NaN(); 15207 | } 15208 | 15209 | inline typename expression_node<T>::node_type type() const exprtk_override 15210 | { 15211 | return expression_node<T>::e_genfunction; 15212 | } 15213 | 15214 | inline bool valid() const exprtk_override 15215 | { 15216 | return function_; 15217 | } 15218 | 15219 | protected: 15220 | 15221 | inline virtual bool populate_value_list() const 15222 | { 15223 | assert(branch_.size() == typestore_list_.size()); 15224 | 15225 | for (std::size_t i = 0; i < branch_.size(); ++i) 15226 | { 15227 | expr_as_vec1_store_[i] = branch_[i].first->value(); 15228 | } 15229 | 15230 | if (!range_param_list_.empty()) 15231 | { 15232 | assert(range_param_list_.size() <= branch_.size()); 15233 | 15234 | for (std::size_t i = 0; i < range_param_list_.size(); ++i) 15235 | { 15236 | const std::size_t index = range_param_list_[i]; 15237 | range_data_type_t& rdt = range_list_[index]; 15238 | 15239 | const range_t& rp = (*rdt.range); 15240 | std::size_t r0 = 0; 15241 | std::size_t r1 = 0; 15242 | 15243 | const std::size_t data_size = 15244 | #ifndef exprtk_disable_string_capabilities 15245 | rdt.str_node ? rdt.str_node->size() : rdt.size; 15246 | #else 15247 | rdt.size; 15248 | #endif 15249 | 15250 | if (!rp(r0, r1, data_size)) 15251 | { 15252 | return false; 15253 | } 15254 | 15255 | type_store_t& ts = typestore_list_[index]; 15256 | 15257 | ts.size = rp.cache_size(); 15258 | #ifndef exprtk_disable_string_capabilities 15259 | if (ts.type == type_store_t::e_string) 15260 | ts.data = const_cast<char_ptr>(rdt.str_node->base()) + rp.cache.first; 15261 | else 15262 | #endif 15263 | ts.data = static_cast<char_ptr>(rdt.data) + (rp.cache.first * rdt.type_size); 15264 | } 15265 | } 15266 | 15267 | return true; 15268 | } 15269 | 15270 | GenericFunction* function_; 15271 | mutable typestore_list_t typestore_list_; 15272 | 15273 | private: 15274 | 15275 | std::vector<expression_ptr> arg_list_; 15276 | std::vector<branch_t> branch_; 15277 | std::vector<vecview_t> vv_list_; 15278 | mutable tmp_vs_t expr_as_vec1_store_; 15279 | mutable range_list_t range_list_; 15280 | std::vector<std::size_t> range_param_list_; 15281 | }; 15282 | 15283 | #ifndef exprtk_disable_string_capabilities 15284 | template <typename T, typename StringFunction> 15285 | class string_function_node : public generic_function_node<T,StringFunction> 15286 | , public string_base_node<T> 15287 | , public range_interface <T> 15288 | { 15289 | public: 15290 | 15291 | typedef generic_function_node<T,StringFunction> gen_function_t; 15292 | typedef typename range_interface<T>::range_t range_t; 15293 | 15294 | string_function_node(StringFunction* func, 15295 | const std::vector<typename gen_function_t::expression_ptr>& arg_list) 15296 | : gen_function_t(arg_list,func) 15297 | { 15298 | range_.n0_c = std::make_pair<bool,std::size_t>(true,0); 15299 | range_.n1_c = std::make_pair<bool,std::size_t>(true,0); 15300 | range_.cache.first = range_.n0_c.second; 15301 | range_.cache.second = range_.n1_c.second; 15302 | assert(valid()); 15303 | } 15304 | 15305 | inline bool operator <(const string_function_node<T,StringFunction>& fn) const 15306 | { 15307 | return this < (&fn); 15308 | } 15309 | 15310 | inline T value() const exprtk_override 15311 | { 15312 | if (gen_function_t::populate_value_list()) 15313 | { 15314 | typedef typename StringFunction::parameter_list_t parameter_list_t; 15315 | 15316 | const T result = 15317 | (*gen_function_t::function_) 15318 | ( 15319 | ret_string_, 15320 | parameter_list_t(gen_function_t::typestore_list_) 15321 | ); 15322 | 15323 | range_.n1_c.second = ret_string_.size(); 15324 | range_.cache.second = range_.n1_c.second; 15325 | 15326 | return result; 15327 | } 15328 | 15329 | return std::numeric_limits<T>::quiet_NaN(); 15330 | } 15331 | 15332 | inline typename expression_node<T>::node_type type() const exprtk_override 15333 | { 15334 | return expression_node<T>::e_strfunction; 15335 | } 15336 | 15337 | inline bool valid() const exprtk_override 15338 | { 15339 | return gen_function_t::function_; 15340 | } 15341 | 15342 | std::string str() const exprtk_override 15343 | { 15344 | return ret_string_; 15345 | } 15346 | 15347 | char_cptr base() const exprtk_override 15348 | { 15349 | return &ret_string_[0]; 15350 | } 15351 | 15352 | std::size_t size() const exprtk_override 15353 | { 15354 | return ret_string_.size(); 15355 | } 15356 | 15357 | range_t& range_ref() exprtk_override 15358 | { 15359 | return range_; 15360 | } 15361 | 15362 | const range_t& range_ref() const exprtk_override 15363 | { 15364 | return range_; 15365 | } 15366 | 15367 | protected: 15368 | 15369 | mutable range_t range_; 15370 | mutable std::string ret_string_; 15371 | }; 15372 | #endif 15373 | 15374 | template <typename T, typename GenericFunction> 15375 | class multimode_genfunction_node : public generic_function_node<T,GenericFunction> 15376 | { 15377 | public: 15378 | 15379 | typedef generic_function_node<T,GenericFunction> gen_function_t; 15380 | typedef typename gen_function_t::range_t range_t; 15381 | 15382 | multimode_genfunction_node(GenericFunction* func, 15383 | const std::size_t& param_seq_index, 15384 | const std::vector<typename gen_function_t::expression_ptr>& arg_list) 15385 | : gen_function_t(arg_list,func) 15386 | , param_seq_index_(param_seq_index) 15387 | {} 15388 | 15389 | inline T value() const exprtk_override 15390 | { 15391 | assert(gen_function_t::valid()); 15392 | 15393 | if (gen_function_t::populate_value_list()) 15394 | { 15395 | typedef typename GenericFunction::parameter_list_t parameter_list_t; 15396 | 15397 | return 15398 | (*gen_function_t::function_) 15399 | ( 15400 | param_seq_index_, 15401 | parameter_list_t(gen_function_t::typestore_list_) 15402 | ); 15403 | } 15404 | 15405 | return std::numeric_limits<T>::quiet_NaN(); 15406 | } 15407 | 15408 | inline typename expression_node<T>::node_type type() const exprtk_override exprtk_final 15409 | { 15410 | return expression_node<T>::e_genfunction; 15411 | } 15412 | 15413 | private: 15414 | 15415 | std::size_t param_seq_index_; 15416 | }; 15417 | 15418 | #ifndef exprtk_disable_string_capabilities 15419 | template <typename T, typename StringFunction> 15420 | class multimode_strfunction_node exprtk_final : public string_function_node<T,StringFunction> 15421 | { 15422 | public: 15423 | 15424 | typedef string_function_node<T,StringFunction> str_function_t; 15425 | typedef typename str_function_t::range_t range_t; 15426 | 15427 | multimode_strfunction_node(StringFunction* func, 15428 | const std::size_t& param_seq_index, 15429 | const std::vector<typename str_function_t::expression_ptr>& arg_list) 15430 | : str_function_t(func,arg_list) 15431 | , param_seq_index_(param_seq_index) 15432 | {} 15433 | 15434 | inline T value() const exprtk_override 15435 | { 15436 | if (str_function_t::populate_value_list()) 15437 | { 15438 | typedef typename StringFunction::parameter_list_t parameter_list_t; 15439 | 15440 | const T result = 15441 | (*str_function_t::function_) 15442 | ( 15443 | param_seq_index_, 15444 | str_function_t::ret_string_, 15445 | parameter_list_t(str_function_t::typestore_list_) 15446 | ); 15447 | 15448 | str_function_t::range_.n1_c.second = str_function_t::ret_string_.size(); 15449 | str_function_t::range_.cache.second = str_function_t::range_.n1_c.second; 15450 | 15451 | return result; 15452 | } 15453 | 15454 | return std::numeric_limits<T>::quiet_NaN(); 15455 | } 15456 | 15457 | inline typename expression_node<T>::node_type type() const exprtk_override 15458 | { 15459 | return expression_node<T>::e_strfunction; 15460 | } 15461 | 15462 | private: 15463 | 15464 | const std::size_t param_seq_index_; 15465 | }; 15466 | #endif 15467 | 15468 | class return_exception {}; 15469 | 15470 | template <typename T> 15471 | class null_igenfunc 15472 | { 15473 | public: 15474 | 15475 | virtual ~null_igenfunc() 15476 | {} 15477 | 15478 | typedef type_store<T> generic_type; 15479 | typedef typename generic_type::parameter_list parameter_list_t; 15480 | 15481 | inline virtual T operator() (parameter_list_t) 15482 | { 15483 | return std::numeric_limits<T>::quiet_NaN(); 15484 | } 15485 | }; 15486 | 15487 | #ifndef exprtk_disable_return_statement 15488 | template <typename T> 15489 | class return_node exprtk_final : public generic_function_node<T,null_igenfunc<T> > 15490 | { 15491 | public: 15492 | 15493 | typedef results_context<T> results_context_t; 15494 | typedef null_igenfunc<T> igeneric_function_t; 15495 | typedef igeneric_function_t* igeneric_function_ptr; 15496 | typedef generic_function_node<T,igeneric_function_t> gen_function_t; 15497 | 15498 | return_node(const std::vector<typename gen_function_t::expression_ptr>& arg_list, 15499 | results_context_t& rc) 15500 | : gen_function_t (arg_list) 15501 | , results_context_(&rc) 15502 | { 15503 | assert(valid()); 15504 | } 15505 | 15506 | inline T value() const exprtk_override 15507 | { 15508 | if (gen_function_t::populate_value_list()) 15509 | { 15510 | prepare_typestore_list(); 15511 | 15512 | typedef typename type_store<T>::parameter_list parameter_list_t; 15513 | 15514 | results_context_-> 15515 | assign(parameter_list_t(gen_function_t::typestore_list_)); 15516 | 15517 | throw return_exception(); 15518 | } 15519 | 15520 | return std::numeric_limits<T>::quiet_NaN(); 15521 | } 15522 | 15523 | inline typename expression_node<T>::node_type type() const exprtk_override 15524 | { 15525 | return expression_node<T>::e_return; 15526 | } 15527 | 15528 | inline bool valid() const exprtk_override 15529 | { 15530 | return results_context_; 15531 | } 15532 | 15533 | private: 15534 | 15535 | void prepare_typestore_list() const 15536 | { 15537 | for (std::size_t i = 0; i < gen_function_t::typestore_list_.size(); ++i) 15538 | { 15539 | typename gen_function_t::type_store_t& ts = gen_function_t::typestore_list_[i]; 15540 | 15541 | if (ts.ivec) 15542 | { 15543 | ts.size = ts.ivec->size(); 15544 | } 15545 | } 15546 | } 15547 | 15548 | results_context_t* results_context_; 15549 | }; 15550 | 15551 | template <typename T> 15552 | class return_envelope_node exprtk_final : public expression_node<T> 15553 | { 15554 | public: 15555 | 15556 | typedef expression_node<T>* expression_ptr; 15557 | typedef results_context<T> results_context_t; 15558 | typedef std::pair<expression_ptr,bool> branch_t; 15559 | 15560 | return_envelope_node(expression_ptr body, results_context_t& rc) 15561 | : results_context_(&rc ) 15562 | , return_invoked_ (false) 15563 | { 15564 | construct_branch_pair(body_, body); 15565 | assert(valid()); 15566 | } 15567 | 15568 | inline T value() const exprtk_override 15569 | { 15570 | try 15571 | { 15572 | return_invoked_ = false; 15573 | results_context_->clear(); 15574 | 15575 | return body_.first->value(); 15576 | } 15577 | catch(const return_exception&) 15578 | { 15579 | return_invoked_ = true; 15580 | 15581 | return std::numeric_limits<T>::quiet_NaN(); 15582 | } 15583 | } 15584 | 15585 | inline typename expression_node<T>::node_type type() const exprtk_override 15586 | { 15587 | return expression_node<T>::e_retenv; 15588 | } 15589 | 15590 | inline bool valid() const exprtk_override 15591 | { 15592 | return results_context_ && body_.first; 15593 | } 15594 | 15595 | inline bool* retinvk_ptr() 15596 | { 15597 | return &return_invoked_; 15598 | } 15599 | 15600 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 15601 | { 15602 | expression_node<T>::ndb_t::collect(body_, node_delete_list); 15603 | } 15604 | 15605 | std::size_t node_depth() const exprtk_override 15606 | { 15607 | return expression_node<T>::ndb_t::compute_node_depth(body_); 15608 | } 15609 | 15610 | private: 15611 | 15612 | results_context_t* results_context_; 15613 | mutable bool return_invoked_; 15614 | branch_t body_; 15615 | }; 15616 | #endif 15617 | 15618 | #define exprtk_define_unary_op(OpName) \ 15619 | template <typename T> \ 15620 | struct OpName##_op \ 15621 | { \ 15622 | typedef typename functor_t<T>::Type Type; \ 15623 | typedef typename expression_node<T>::node_type node_t; \ 15624 | \ 15625 | static inline T process(Type v) \ 15626 | { \ 15627 | return numeric:: OpName (v); \ 15628 | } \ 15629 | \ 15630 | static inline node_t type() \ 15631 | { \ 15632 | return expression_node<T>::e_##OpName; \ 15633 | } \ 15634 | \ 15635 | static inline details::operator_type operation() \ 15636 | { \ 15637 | return details::e_##OpName; \ 15638 | } \ 15639 | }; \ 15640 | 15641 | exprtk_define_unary_op(abs ) 15642 | exprtk_define_unary_op(acos ) 15643 | exprtk_define_unary_op(acosh) 15644 | exprtk_define_unary_op(asin ) 15645 | exprtk_define_unary_op(asinh) 15646 | exprtk_define_unary_op(atan ) 15647 | exprtk_define_unary_op(atanh) 15648 | exprtk_define_unary_op(ceil ) 15649 | exprtk_define_unary_op(cos ) 15650 | exprtk_define_unary_op(cosh ) 15651 | exprtk_define_unary_op(cot ) 15652 | exprtk_define_unary_op(csc ) 15653 | exprtk_define_unary_op(d2g ) 15654 | exprtk_define_unary_op(d2r ) 15655 | exprtk_define_unary_op(erf ) 15656 | exprtk_define_unary_op(erfc ) 15657 | exprtk_define_unary_op(exp ) 15658 | exprtk_define_unary_op(expm1) 15659 | exprtk_define_unary_op(floor) 15660 | exprtk_define_unary_op(frac ) 15661 | exprtk_define_unary_op(g2d ) 15662 | exprtk_define_unary_op(log ) 15663 | exprtk_define_unary_op(log10) 15664 | exprtk_define_unary_op(log2 ) 15665 | exprtk_define_unary_op(log1p) 15666 | exprtk_define_unary_op(ncdf ) 15667 | exprtk_define_unary_op(neg ) 15668 | exprtk_define_unary_op(notl ) 15669 | exprtk_define_unary_op(pos ) 15670 | exprtk_define_unary_op(r2d ) 15671 | exprtk_define_unary_op(round) 15672 | exprtk_define_unary_op(sec ) 15673 | exprtk_define_unary_op(sgn ) 15674 | exprtk_define_unary_op(sin ) 15675 | exprtk_define_unary_op(sinc ) 15676 | exprtk_define_unary_op(sinh ) 15677 | exprtk_define_unary_op(sqrt ) 15678 | exprtk_define_unary_op(tan ) 15679 | exprtk_define_unary_op(tanh ) 15680 | exprtk_define_unary_op(trunc) 15681 | #undef exprtk_define_unary_op 15682 | 15683 | template <typename T> 15684 | struct opr_base 15685 | { 15686 | typedef typename details::functor_t<T>::Type Type; 15687 | typedef typename details::functor_t<T>::RefType RefType; 15688 | typedef typename details::functor_t<T> functor_t; 15689 | typedef typename functor_t::qfunc_t quaternary_functor_t; 15690 | typedef typename functor_t::tfunc_t trinary_functor_t; 15691 | typedef typename functor_t::bfunc_t binary_functor_t; 15692 | typedef typename functor_t::ufunc_t unary_functor_t; 15693 | }; 15694 | 15695 | template <typename T> 15696 | struct add_op : public opr_base<T> 15697 | { 15698 | typedef typename opr_base<T>::Type Type; 15699 | typedef typename opr_base<T>::RefType RefType; 15700 | 15701 | static inline T process(Type t1, Type t2) { return t1 + t2; } 15702 | static inline T process(Type t1, Type t2, Type t3) { return t1 + t2 + t3; } 15703 | static inline void assign(RefType t1, Type t2) { t1 += t2; } 15704 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_add; } 15705 | static inline details::operator_type operation() { return details::e_add; } 15706 | }; 15707 | 15708 | template <typename T> 15709 | struct mul_op : public opr_base<T> 15710 | { 15711 | typedef typename opr_base<T>::Type Type; 15712 | typedef typename opr_base<T>::RefType RefType; 15713 | 15714 | static inline T process(Type t1, Type t2) { return t1 * t2; } 15715 | static inline T process(Type t1, Type t2, Type t3) { return t1 * t2 * t3; } 15716 | static inline void assign(RefType t1, Type t2) { t1 *= t2; } 15717 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_mul; } 15718 | static inline details::operator_type operation() { return details::e_mul; } 15719 | }; 15720 | 15721 | template <typename T> 15722 | struct sub_op : public opr_base<T> 15723 | { 15724 | typedef typename opr_base<T>::Type Type; 15725 | typedef typename opr_base<T>::RefType RefType; 15726 | 15727 | static inline T process(Type t1, Type t2) { return t1 - t2; } 15728 | static inline T process(Type t1, Type t2, Type t3) { return t1 - t2 - t3; } 15729 | static inline void assign(RefType t1, Type t2) { t1 -= t2; } 15730 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_sub; } 15731 | static inline details::operator_type operation() { return details::e_sub; } 15732 | }; 15733 | 15734 | template <typename T> 15735 | struct div_op : public opr_base<T> 15736 | { 15737 | typedef typename opr_base<T>::Type Type; 15738 | typedef typename opr_base<T>::RefType RefType; 15739 | 15740 | static inline T process(Type t1, Type t2) { return t1 / t2; } 15741 | static inline T process(Type t1, Type t2, Type t3) { return t1 / t2 / t3; } 15742 | static inline void assign(RefType t1, Type t2) { t1 /= t2; } 15743 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_div; } 15744 | static inline details::operator_type operation() { return details::e_div; } 15745 | }; 15746 | 15747 | template <typename T> 15748 | struct mod_op : public opr_base<T> 15749 | { 15750 | typedef typename opr_base<T>::Type Type; 15751 | typedef typename opr_base<T>::RefType RefType; 15752 | 15753 | static inline T process(Type t1, Type t2) { return numeric::modulus<T>(t1,t2); } 15754 | static inline void assign(RefType t1, Type t2) { t1 = numeric::modulus<T>(t1,t2); } 15755 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_mod; } 15756 | static inline details::operator_type operation() { return details::e_mod; } 15757 | }; 15758 | 15759 | template <typename T> 15760 | struct pow_op : public opr_base<T> 15761 | { 15762 | typedef typename opr_base<T>::Type Type; 15763 | typedef typename opr_base<T>::RefType RefType; 15764 | 15765 | static inline T process(Type t1, Type t2) { return numeric::pow<T>(t1,t2); } 15766 | static inline void assign(RefType t1, Type t2) { t1 = numeric::pow<T>(t1,t2); } 15767 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_pow; } 15768 | static inline details::operator_type operation() { return details::e_pow; } 15769 | }; 15770 | 15771 | template <typename T> 15772 | struct lt_op : public opr_base<T> 15773 | { 15774 | typedef typename opr_base<T>::Type Type; 15775 | 15776 | static inline T process(Type t1, Type t2) { return ((t1 < t2) ? T(1) : T(0)); } 15777 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 < t2) ? T(1) : T(0)); } 15778 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_lt; } 15779 | static inline details::operator_type operation() { return details::e_lt; } 15780 | }; 15781 | 15782 | template <typename T> 15783 | struct lte_op : public opr_base<T> 15784 | { 15785 | typedef typename opr_base<T>::Type Type; 15786 | 15787 | static inline T process(Type t1, Type t2) { return ((t1 <= t2) ? T(1) : T(0)); } 15788 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 <= t2) ? T(1) : T(0)); } 15789 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_lte; } 15790 | static inline details::operator_type operation() { return details::e_lte; } 15791 | }; 15792 | 15793 | template <typename T> 15794 | struct gt_op : public opr_base<T> 15795 | { 15796 | typedef typename opr_base<T>::Type Type; 15797 | 15798 | static inline T process(Type t1, Type t2) { return ((t1 > t2) ? T(1) : T(0)); } 15799 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 > t2) ? T(1) : T(0)); } 15800 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_gt; } 15801 | static inline details::operator_type operation() { return details::e_gt; } 15802 | }; 15803 | 15804 | template <typename T> 15805 | struct gte_op : public opr_base<T> 15806 | { 15807 | typedef typename opr_base<T>::Type Type; 15808 | 15809 | static inline T process(Type t1, Type t2) { return ((t1 >= t2) ? T(1) : T(0)); } 15810 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 >= t2) ? T(1) : T(0)); } 15811 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_gte; } 15812 | static inline details::operator_type operation() { return details::e_gte; } 15813 | }; 15814 | 15815 | template <typename T> 15816 | struct eq_op : public opr_base<T> 15817 | { 15818 | typedef typename opr_base<T>::Type Type; 15819 | static inline T process(Type t1, Type t2) { return (std::equal_to<T>()(t1,t2) ? T(1) : T(0)); } 15820 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 == t2) ? T(1) : T(0)); } 15821 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_eq; } 15822 | static inline details::operator_type operation() { return details::e_eq; } 15823 | }; 15824 | 15825 | template <typename T> 15826 | struct equal_op : public opr_base<T> 15827 | { 15828 | typedef typename opr_base<T>::Type Type; 15829 | 15830 | static inline T process(Type t1, Type t2) { return numeric::equal(t1,t2); } 15831 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 == t2) ? T(1) : T(0)); } 15832 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_eq; } 15833 | static inline details::operator_type operation() { return details::e_equal; } 15834 | }; 15835 | 15836 | template <typename T> 15837 | struct ne_op : public opr_base<T> 15838 | { 15839 | typedef typename opr_base<T>::Type Type; 15840 | 15841 | static inline T process(Type t1, Type t2) { return (std::not_equal_to<T>()(t1,t2) ? T(1) : T(0)); } 15842 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 != t2) ? T(1) : T(0)); } 15843 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_ne; } 15844 | static inline details::operator_type operation() { return details::e_ne; } 15845 | }; 15846 | 15847 | template <typename T> 15848 | struct and_op : public opr_base<T> 15849 | { 15850 | typedef typename opr_base<T>::Type Type; 15851 | 15852 | static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(1) : T(0); } 15853 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_and; } 15854 | static inline details::operator_type operation() { return details::e_and; } 15855 | }; 15856 | 15857 | template <typename T> 15858 | struct nand_op : public opr_base<T> 15859 | { 15860 | typedef typename opr_base<T>::Type Type; 15861 | 15862 | static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(0) : T(1); } 15863 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nand; } 15864 | static inline details::operator_type operation() { return details::e_nand; } 15865 | }; 15866 | 15867 | template <typename T> 15868 | struct or_op : public opr_base<T> 15869 | { 15870 | typedef typename opr_base<T>::Type Type; 15871 | 15872 | static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(1) : T(0); } 15873 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_or; } 15874 | static inline details::operator_type operation() { return details::e_or; } 15875 | }; 15876 | 15877 | template <typename T> 15878 | struct nor_op : public opr_base<T> 15879 | { 15880 | typedef typename opr_base<T>::Type Type; 15881 | 15882 | static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(0) : T(1); } 15883 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; } 15884 | static inline details::operator_type operation() { return details::e_nor; } 15885 | }; 15886 | 15887 | template <typename T> 15888 | struct xor_op : public opr_base<T> 15889 | { 15890 | typedef typename opr_base<T>::Type Type; 15891 | 15892 | static inline T process(Type t1, Type t2) { return numeric::xor_opr<T>(t1,t2); } 15893 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; } 15894 | static inline details::operator_type operation() { return details::e_xor; } 15895 | }; 15896 | 15897 | template <typename T> 15898 | struct xnor_op : public opr_base<T> 15899 | { 15900 | typedef typename opr_base<T>::Type Type; 15901 | 15902 | static inline T process(Type t1, Type t2) { return numeric::xnor_opr<T>(t1,t2); } 15903 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; } 15904 | static inline details::operator_type operation() { return details::e_xnor; } 15905 | }; 15906 | 15907 | template <typename T> 15908 | struct in_op : public opr_base<T> 15909 | { 15910 | typedef typename opr_base<T>::Type Type; 15911 | 15912 | static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); } 15913 | static inline T process(const std::string& t1, const std::string& t2) { return ((std::string::npos != t2.find(t1)) ? T(1) : T(0)); } 15914 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_in; } 15915 | static inline details::operator_type operation() { return details::e_in; } 15916 | }; 15917 | 15918 | template <typename T> 15919 | struct like_op : public opr_base<T> 15920 | { 15921 | typedef typename opr_base<T>::Type Type; 15922 | 15923 | static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); } 15924 | static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_match(t2,t1) ? T(1) : T(0)); } 15925 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_like; } 15926 | static inline details::operator_type operation() { return details::e_like; } 15927 | }; 15928 | 15929 | template <typename T> 15930 | struct ilike_op : public opr_base<T> 15931 | { 15932 | typedef typename opr_base<T>::Type Type; 15933 | 15934 | static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); } 15935 | static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_imatch(t2,t1) ? T(1) : T(0)); } 15936 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_ilike; } 15937 | static inline details::operator_type operation() { return details::e_ilike; } 15938 | }; 15939 | 15940 | template <typename T> 15941 | struct inrange_op : public opr_base<T> 15942 | { 15943 | typedef typename opr_base<T>::Type Type; 15944 | 15945 | static inline T process(const T& t0, const T& t1, const T& t2) { return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0); } 15946 | static inline T process(const std::string& t0, const std::string& t1, const std::string& t2) 15947 | { 15948 | return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0); 15949 | } 15950 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_inranges; } 15951 | static inline details::operator_type operation() { return details::e_inrange; } 15952 | }; 15953 | 15954 | template <typename T> 15955 | inline T value(details::expression_node<T>* n) 15956 | { 15957 | return n->value(); 15958 | } 15959 | 15960 | template <typename T> 15961 | inline T value(std::pair<details::expression_node<T>*,bool> n) 15962 | { 15963 | return n.first->value(); 15964 | } 15965 | 15966 | template <typename T> 15967 | inline T value(const T* t) 15968 | { 15969 | return (*t); 15970 | } 15971 | 15972 | template <typename T> 15973 | inline T value(const T& t) 15974 | { 15975 | return t; 15976 | } 15977 | 15978 | template <typename T> 15979 | struct vararg_add_op exprtk_final : public opr_base<T> 15980 | { 15981 | typedef typename opr_base<T>::Type Type; 15982 | 15983 | template <typename Type, 15984 | typename Allocator, 15985 | template <typename, typename> class Sequence> 15986 | static inline T process(const Sequence<Type,Allocator>& arg_list) 15987 | { 15988 | switch (arg_list.size()) 15989 | { 15990 | case 0 : return T(0); 15991 | case 1 : return process_1(arg_list); 15992 | case 2 : return process_2(arg_list); 15993 | case 3 : return process_3(arg_list); 15994 | case 4 : return process_4(arg_list); 15995 | case 5 : return process_5(arg_list); 15996 | default : 15997 | { 15998 | T result = T(0); 15999 | 16000 | for (std::size_t i = 0; i < arg_list.size(); ++i) 16001 | { 16002 | result += value(arg_list[i]); 16003 | } 16004 | 16005 | return result; 16006 | } 16007 | } 16008 | } 16009 | 16010 | template <typename Sequence> 16011 | static inline T process_1(const Sequence& arg_list) 16012 | { 16013 | return value(arg_list[0]); 16014 | } 16015 | 16016 | template <typename Sequence> 16017 | static inline T process_2(const Sequence& arg_list) 16018 | { 16019 | return value(arg_list[0]) + value(arg_list[1]); 16020 | } 16021 | 16022 | template <typename Sequence> 16023 | static inline T process_3(const Sequence& arg_list) 16024 | { 16025 | return value(arg_list[0]) + value(arg_list[1]) + 16026 | value(arg_list[2]) ; 16027 | } 16028 | 16029 | template <typename Sequence> 16030 | static inline T process_4(const Sequence& arg_list) 16031 | { 16032 | return value(arg_list[0]) + value(arg_list[1]) + 16033 | value(arg_list[2]) + value(arg_list[3]) ; 16034 | } 16035 | 16036 | template <typename Sequence> 16037 | static inline T process_5(const Sequence& arg_list) 16038 | { 16039 | return value(arg_list[0]) + value(arg_list[1]) + 16040 | value(arg_list[2]) + value(arg_list[3]) + 16041 | value(arg_list[4]) ; 16042 | } 16043 | }; 16044 | 16045 | template <typename T> 16046 | struct vararg_mul_op exprtk_final : public opr_base<T> 16047 | { 16048 | typedef typename opr_base<T>::Type Type; 16049 | 16050 | template <typename Type, 16051 | typename Allocator, 16052 | template <typename, typename> class Sequence> 16053 | static inline T process(const Sequence<Type,Allocator>& arg_list) 16054 | { 16055 | switch (arg_list.size()) 16056 | { 16057 | case 0 : return T(0); 16058 | case 1 : return process_1(arg_list); 16059 | case 2 : return process_2(arg_list); 16060 | case 3 : return process_3(arg_list); 16061 | case 4 : return process_4(arg_list); 16062 | case 5 : return process_5(arg_list); 16063 | default : 16064 | { 16065 | T result = T(value(arg_list[0])); 16066 | 16067 | for (std::size_t i = 1; i < arg_list.size(); ++i) 16068 | { 16069 | result *= value(arg_list[i]); 16070 | } 16071 | 16072 | return result; 16073 | } 16074 | } 16075 | } 16076 | 16077 | template <typename Sequence> 16078 | static inline T process_1(const Sequence& arg_list) 16079 | { 16080 | return value(arg_list[0]); 16081 | } 16082 | 16083 | template <typename Sequence> 16084 | static inline T process_2(const Sequence& arg_list) 16085 | { 16086 | return value(arg_list[0]) * value(arg_list[1]); 16087 | } 16088 | 16089 | template <typename Sequence> 16090 | static inline T process_3(const Sequence& arg_list) 16091 | { 16092 | return value(arg_list[0]) * value(arg_list[1]) * 16093 | value(arg_list[2]) ; 16094 | } 16095 | 16096 | template <typename Sequence> 16097 | static inline T process_4(const Sequence& arg_list) 16098 | { 16099 | return value(arg_list[0]) * value(arg_list[1]) * 16100 | value(arg_list[2]) * value(arg_list[3]) ; 16101 | } 16102 | 16103 | template <typename Sequence> 16104 | static inline T process_5(const Sequence& arg_list) 16105 | { 16106 | return value(arg_list[0]) * value(arg_list[1]) * 16107 | value(arg_list[2]) * value(arg_list[3]) * 16108 | value(arg_list[4]) ; 16109 | } 16110 | }; 16111 | 16112 | template <typename T> 16113 | struct vararg_avg_op exprtk_final : public opr_base<T> 16114 | { 16115 | typedef typename opr_base<T>::Type Type; 16116 | 16117 | template <typename Type, 16118 | typename Allocator, 16119 | template <typename, typename> class Sequence> 16120 | static inline T process(const Sequence<Type,Allocator>& arg_list) 16121 | { 16122 | switch (arg_list.size()) 16123 | { 16124 | case 0 : return T(0); 16125 | case 1 : return process_1(arg_list); 16126 | case 2 : return process_2(arg_list); 16127 | case 3 : return process_3(arg_list); 16128 | case 4 : return process_4(arg_list); 16129 | case 5 : return process_5(arg_list); 16130 | default : return vararg_add_op<T>::process(arg_list) / T(arg_list.size()); 16131 | } 16132 | } 16133 | 16134 | template <typename Sequence> 16135 | static inline T process_1(const Sequence& arg_list) 16136 | { 16137 | return value(arg_list[0]); 16138 | } 16139 | 16140 | template <typename Sequence> 16141 | static inline T process_2(const Sequence& arg_list) 16142 | { 16143 | return (value(arg_list[0]) + value(arg_list[1])) / T(2); 16144 | } 16145 | 16146 | template <typename Sequence> 16147 | static inline T process_3(const Sequence& arg_list) 16148 | { 16149 | return (value(arg_list[0]) + value(arg_list[1]) + value(arg_list[2])) / T(3); 16150 | } 16151 | 16152 | template <typename Sequence> 16153 | static inline T process_4(const Sequence& arg_list) 16154 | { 16155 | return (value(arg_list[0]) + value(arg_list[1]) + 16156 | value(arg_list[2]) + value(arg_list[3])) / T(4); 16157 | } 16158 | 16159 | template <typename Sequence> 16160 | static inline T process_5(const Sequence& arg_list) 16161 | { 16162 | return (value(arg_list[0]) + value(arg_list[1]) + 16163 | value(arg_list[2]) + value(arg_list[3]) + 16164 | value(arg_list[4])) / T(5); 16165 | } 16166 | }; 16167 | 16168 | template <typename T> 16169 | struct vararg_min_op exprtk_final : public opr_base<T> 16170 | { 16171 | typedef typename opr_base<T>::Type Type; 16172 | 16173 | template <typename Type, 16174 | typename Allocator, 16175 | template <typename, typename> class Sequence> 16176 | static inline T process(const Sequence<Type,Allocator>& arg_list) 16177 | { 16178 | switch (arg_list.size()) 16179 | { 16180 | case 0 : return T(0); 16181 | case 1 : return process_1(arg_list); 16182 | case 2 : return process_2(arg_list); 16183 | case 3 : return process_3(arg_list); 16184 | case 4 : return process_4(arg_list); 16185 | case 5 : return process_5(arg_list); 16186 | default : 16187 | { 16188 | T result = T(value(arg_list[0])); 16189 | 16190 | for (std::size_t i = 1; i < arg_list.size(); ++i) 16191 | { 16192 | const T v = value(arg_list[i]); 16193 | 16194 | if (v < result) 16195 | result = v; 16196 | } 16197 | 16198 | return result; 16199 | } 16200 | } 16201 | } 16202 | 16203 | template <typename Sequence> 16204 | static inline T process_1(const Sequence& arg_list) 16205 | { 16206 | return value(arg_list[0]); 16207 | } 16208 | 16209 | template <typename Sequence> 16210 | static inline T process_2(const Sequence& arg_list) 16211 | { 16212 | return std::min<T>(value(arg_list[0]),value(arg_list[1])); 16213 | } 16214 | 16215 | template <typename Sequence> 16216 | static inline T process_3(const Sequence& arg_list) 16217 | { 16218 | return std::min<T>(std::min<T>(value(arg_list[0]),value(arg_list[1])),value(arg_list[2])); 16219 | } 16220 | 16221 | template <typename Sequence> 16222 | static inline T process_4(const Sequence& arg_list) 16223 | { 16224 | return std::min<T>( 16225 | std::min<T>(value(arg_list[0]), value(arg_list[1])), 16226 | std::min<T>(value(arg_list[2]), value(arg_list[3]))); 16227 | } 16228 | 16229 | template <typename Sequence> 16230 | static inline T process_5(const Sequence& arg_list) 16231 | { 16232 | return std::min<T>( 16233 | std::min<T>(std::min<T>(value(arg_list[0]), value(arg_list[1])), 16234 | std::min<T>(value(arg_list[2]), value(arg_list[3]))), 16235 | value(arg_list[4])); 16236 | } 16237 | }; 16238 | 16239 | template <typename T> 16240 | struct vararg_max_op exprtk_final : public opr_base<T> 16241 | { 16242 | typedef typename opr_base<T>::Type Type; 16243 | 16244 | template <typename Type, 16245 | typename Allocator, 16246 | template <typename, typename> class Sequence> 16247 | static inline T process(const Sequence<Type,Allocator>& arg_list) 16248 | { 16249 | switch (arg_list.size()) 16250 | { 16251 | case 0 : return T(0); 16252 | case 1 : return process_1(arg_list); 16253 | case 2 : return process_2(arg_list); 16254 | case 3 : return process_3(arg_list); 16255 | case 4 : return process_4(arg_list); 16256 | case 5 : return process_5(arg_list); 16257 | default : 16258 | { 16259 | T result = T(value(arg_list[0])); 16260 | 16261 | for (std::size_t i = 1; i < arg_list.size(); ++i) 16262 | { 16263 | const T v = value(arg_list[i]); 16264 | 16265 | if (v > result) 16266 | result = v; 16267 | } 16268 | 16269 | return result; 16270 | } 16271 | } 16272 | } 16273 | 16274 | template <typename Sequence> 16275 | static inline T process_1(const Sequence& arg_list) 16276 | { 16277 | return value(arg_list[0]); 16278 | } 16279 | 16280 | template <typename Sequence> 16281 | static inline T process_2(const Sequence& arg_list) 16282 | { 16283 | return std::max<T>(value(arg_list[0]),value(arg_list[1])); 16284 | } 16285 | 16286 | template <typename Sequence> 16287 | static inline T process_3(const Sequence& arg_list) 16288 | { 16289 | return std::max<T>(std::max<T>(value(arg_list[0]),value(arg_list[1])),value(arg_list[2])); 16290 | } 16291 | 16292 | template <typename Sequence> 16293 | static inline T process_4(const Sequence& arg_list) 16294 | { 16295 | return std::max<T>( 16296 | std::max<T>(value(arg_list[0]), value(arg_list[1])), 16297 | std::max<T>(value(arg_list[2]), value(arg_list[3]))); 16298 | } 16299 | 16300 | template <typename Sequence> 16301 | static inline T process_5(const Sequence& arg_list) 16302 | { 16303 | return std::max<T>( 16304 | std::max<T>(std::max<T>(value(arg_list[0]), value(arg_list[1])), 16305 | std::max<T>(value(arg_list[2]), value(arg_list[3]))), 16306 | value(arg_list[4])); 16307 | } 16308 | }; 16309 | 16310 | template <typename T> 16311 | struct vararg_mand_op exprtk_final : public opr_base<T> 16312 | { 16313 | typedef typename opr_base<T>::Type Type; 16314 | 16315 | template <typename Type, 16316 | typename Allocator, 16317 | template <typename, typename> class Sequence> 16318 | static inline T process(const Sequence<Type,Allocator>& arg_list) 16319 | { 16320 | switch (arg_list.size()) 16321 | { 16322 | case 1 : return process_1(arg_list); 16323 | case 2 : return process_2(arg_list); 16324 | case 3 : return process_3(arg_list); 16325 | case 4 : return process_4(arg_list); 16326 | case 5 : return process_5(arg_list); 16327 | default : 16328 | { 16329 | for (std::size_t i = 0; i < arg_list.size(); ++i) 16330 | { 16331 | if (std::equal_to<T>()(T(0), value(arg_list[i]))) 16332 | return T(0); 16333 | } 16334 | 16335 | return T(1); 16336 | } 16337 | } 16338 | } 16339 | 16340 | template <typename Sequence> 16341 | static inline T process_1(const Sequence& arg_list) 16342 | { 16343 | return std::not_equal_to<T>() 16344 | (T(0), value(arg_list[0])) ? T(1) : T(0); 16345 | } 16346 | 16347 | template <typename Sequence> 16348 | static inline T process_2(const Sequence& arg_list) 16349 | { 16350 | return ( 16351 | std::not_equal_to<T>()(T(0), value(arg_list[0])) && 16352 | std::not_equal_to<T>()(T(0), value(arg_list[1])) 16353 | ) ? T(1) : T(0); 16354 | } 16355 | 16356 | template <typename Sequence> 16357 | static inline T process_3(const Sequence& arg_list) 16358 | { 16359 | return ( 16360 | std::not_equal_to<T>()(T(0), value(arg_list[0])) && 16361 | std::not_equal_to<T>()(T(0), value(arg_list[1])) && 16362 | std::not_equal_to<T>()(T(0), value(arg_list[2])) 16363 | ) ? T(1) : T(0); 16364 | } 16365 | 16366 | template <typename Sequence> 16367 | static inline T process_4(const Sequence& arg_list) 16368 | { 16369 | return ( 16370 | std::not_equal_to<T>()(T(0), value(arg_list[0])) && 16371 | std::not_equal_to<T>()(T(0), value(arg_list[1])) && 16372 | std::not_equal_to<T>()(T(0), value(arg_list[2])) && 16373 | std::not_equal_to<T>()(T(0), value(arg_list[3])) 16374 | ) ? T(1) : T(0); 16375 | } 16376 | 16377 | template <typename Sequence> 16378 | static inline T process_5(const Sequence& arg_list) 16379 | { 16380 | return ( 16381 | std::not_equal_to<T>()(T(0), value(arg_list[0])) && 16382 | std::not_equal_to<T>()(T(0), value(arg_list[1])) && 16383 | std::not_equal_to<T>()(T(0), value(arg_list[2])) && 16384 | std::not_equal_to<T>()(T(0), value(arg_list[3])) && 16385 | std::not_equal_to<T>()(T(0), value(arg_list[4])) 16386 | ) ? T(1) : T(0); 16387 | } 16388 | }; 16389 | 16390 | template <typename T> 16391 | struct vararg_mor_op exprtk_final : public opr_base<T> 16392 | { 16393 | typedef typename opr_base<T>::Type Type; 16394 | 16395 | template <typename Type, 16396 | typename Allocator, 16397 | template <typename, typename> class Sequence> 16398 | static inline T process(const Sequence<Type,Allocator>& arg_list) 16399 | { 16400 | switch (arg_list.size()) 16401 | { 16402 | case 1 : return process_1(arg_list); 16403 | case 2 : return process_2(arg_list); 16404 | case 3 : return process_3(arg_list); 16405 | case 4 : return process_4(arg_list); 16406 | case 5 : return process_5(arg_list); 16407 | default : 16408 | { 16409 | for (std::size_t i = 0; i < arg_list.size(); ++i) 16410 | { 16411 | if (std::not_equal_to<T>()(T(0), value(arg_list[i]))) 16412 | return T(1); 16413 | } 16414 | 16415 | return T(0); 16416 | } 16417 | } 16418 | } 16419 | 16420 | template <typename Sequence> 16421 | static inline T process_1(const Sequence& arg_list) 16422 | { 16423 | return std::not_equal_to<T>() 16424 | (T(0), value(arg_list[0])) ? T(1) : T(0); 16425 | } 16426 | 16427 | template <typename Sequence> 16428 | static inline T process_2(const Sequence& arg_list) 16429 | { 16430 | return ( 16431 | std::not_equal_to<T>()(T(0), value(arg_list[0])) || 16432 | std::not_equal_to<T>()(T(0), value(arg_list[1])) 16433 | ) ? T(1) : T(0); 16434 | } 16435 | 16436 | template <typename Sequence> 16437 | static inline T process_3(const Sequence& arg_list) 16438 | { 16439 | return ( 16440 | std::not_equal_to<T>()(T(0), value(arg_list[0])) || 16441 | std::not_equal_to<T>()(T(0), value(arg_list[1])) || 16442 | std::not_equal_to<T>()(T(0), value(arg_list[2])) 16443 | ) ? T(1) : T(0); 16444 | } 16445 | 16446 | template <typename Sequence> 16447 | static inline T process_4(const Sequence& arg_list) 16448 | { 16449 | return ( 16450 | std::not_equal_to<T>()(T(0), value(arg_list[0])) || 16451 | std::not_equal_to<T>()(T(0), value(arg_list[1])) || 16452 | std::not_equal_to<T>()(T(0), value(arg_list[2])) || 16453 | std::not_equal_to<T>()(T(0), value(arg_list[3])) 16454 | ) ? T(1) : T(0); 16455 | } 16456 | 16457 | template <typename Sequence> 16458 | static inline T process_5(const Sequence& arg_list) 16459 | { 16460 | return ( 16461 | std::not_equal_to<T>()(T(0), value(arg_list[0])) || 16462 | std::not_equal_to<T>()(T(0), value(arg_list[1])) || 16463 | std::not_equal_to<T>()(T(0), value(arg_list[2])) || 16464 | std::not_equal_to<T>()(T(0), value(arg_list[3])) || 16465 | std::not_equal_to<T>()(T(0), value(arg_list[4])) 16466 | ) ? T(1) : T(0); 16467 | } 16468 | }; 16469 | 16470 | template <typename T> 16471 | struct vararg_multi_op exprtk_final : public opr_base<T> 16472 | { 16473 | typedef typename opr_base<T>::Type Type; 16474 | 16475 | template <typename Type, 16476 | typename Allocator, 16477 | template <typename, typename> class Sequence> 16478 | static inline T process(const Sequence<Type,Allocator>& arg_list) 16479 | { 16480 | switch (arg_list.size()) 16481 | { 16482 | case 0 : return std::numeric_limits<T>::quiet_NaN(); 16483 | case 1 : return process_1(arg_list); 16484 | case 2 : return process_2(arg_list); 16485 | case 3 : return process_3(arg_list); 16486 | case 4 : return process_4(arg_list); 16487 | case 5 : return process_5(arg_list); 16488 | case 6 : return process_6(arg_list); 16489 | case 7 : return process_7(arg_list); 16490 | case 8 : return process_8(arg_list); 16491 | default : 16492 | { 16493 | for (std::size_t i = 0; i < (arg_list.size() - 1); ++i) 16494 | { 16495 | value(arg_list[i]); 16496 | } 16497 | return value(arg_list.back()); 16498 | } 16499 | } 16500 | } 16501 | 16502 | template <typename Sequence> 16503 | static inline T process_1(const Sequence& arg_list) 16504 | { 16505 | return value(arg_list[0]); 16506 | } 16507 | 16508 | template <typename Sequence> 16509 | static inline T process_2(const Sequence& arg_list) 16510 | { 16511 | value(arg_list[0]); 16512 | return value(arg_list[1]); 16513 | } 16514 | 16515 | template <typename Sequence> 16516 | static inline T process_3(const Sequence& arg_list) 16517 | { 16518 | value(arg_list[0]); 16519 | value(arg_list[1]); 16520 | return value(arg_list[2]); 16521 | } 16522 | 16523 | template <typename Sequence> 16524 | static inline T process_4(const Sequence& arg_list) 16525 | { 16526 | value(arg_list[0]); 16527 | value(arg_list[1]); 16528 | value(arg_list[2]); 16529 | return value(arg_list[3]); 16530 | } 16531 | 16532 | template <typename Sequence> 16533 | static inline T process_5(const Sequence& arg_list) 16534 | { 16535 | value(arg_list[0]); 16536 | value(arg_list[1]); 16537 | value(arg_list[2]); 16538 | value(arg_list[3]); 16539 | return value(arg_list[4]); 16540 | } 16541 | 16542 | template <typename Sequence> 16543 | static inline T process_6(const Sequence& arg_list) 16544 | { 16545 | value(arg_list[0]); 16546 | value(arg_list[1]); 16547 | value(arg_list[2]); 16548 | value(arg_list[3]); 16549 | value(arg_list[4]); 16550 | return value(arg_list[5]); 16551 | } 16552 | 16553 | template <typename Sequence> 16554 | static inline T process_7(const Sequence& arg_list) 16555 | { 16556 | value(arg_list[0]); 16557 | value(arg_list[1]); 16558 | value(arg_list[2]); 16559 | value(arg_list[3]); 16560 | value(arg_list[4]); 16561 | value(arg_list[5]); 16562 | return value(arg_list[6]); 16563 | } 16564 | 16565 | template <typename Sequence> 16566 | static inline T process_8(const Sequence& arg_list) 16567 | { 16568 | value(arg_list[0]); 16569 | value(arg_list[1]); 16570 | value(arg_list[2]); 16571 | value(arg_list[3]); 16572 | value(arg_list[4]); 16573 | value(arg_list[5]); 16574 | value(arg_list[6]); 16575 | return value(arg_list[7]); 16576 | } 16577 | }; 16578 | 16579 | template <typename T> 16580 | struct vec_add_op 16581 | { 16582 | typedef vector_interface<T>* ivector_ptr; 16583 | 16584 | static inline T process(const ivector_ptr v) 16585 | { 16586 | const T* vec = v->vec()->vds().data(); 16587 | const std::size_t vec_size = v->size(); 16588 | 16589 | loop_unroll::details lud(vec_size); 16590 | 16591 | if (vec_size <= static_cast<std::size_t>(lud.batch_size)) 16592 | { 16593 | T result = T(0); 16594 | int i = 0; 16595 | 16596 | switch (vec_size) 16597 | { 16598 | #define case_stmt(N,fall_through) \ 16599 | case N : result += vec[i++]; \ 16600 | fall_through \ 16601 | 16602 | #ifndef exprtk_disable_superscalar_unroll 16603 | case_stmt(16, exprtk_fallthrough) case_stmt(15, exprtk_fallthrough) 16604 | case_stmt(14, exprtk_fallthrough) case_stmt(13, exprtk_fallthrough) 16605 | case_stmt(12, exprtk_fallthrough) case_stmt(11, exprtk_fallthrough) 16606 | case_stmt(10, exprtk_fallthrough) case_stmt( 9, exprtk_fallthrough) 16607 | case_stmt( 8, exprtk_fallthrough) case_stmt( 7, exprtk_fallthrough) 16608 | case_stmt( 6, exprtk_fallthrough) case_stmt( 5, exprtk_fallthrough) 16609 | 16610 | #endif 16611 | case_stmt( 4, exprtk_fallthrough) case_stmt( 3, exprtk_fallthrough) 16612 | case_stmt( 2, exprtk_fallthrough) case_stmt( 1, (void)0;) 16613 | } 16614 | 16615 | #undef case_stmt 16616 | 16617 | return result; 16618 | } 16619 | 16620 | T r[] = { 16621 | T(0), T(0), T(0), T(0), T(0), T(0), T(0), T(0), 16622 | T(0), T(0), T(0), T(0), T(0), T(0), T(0), T(0) 16623 | }; 16624 | 16625 | const T* upper_bound = vec + lud.upper_bound; 16626 | 16627 | while (vec < upper_bound) 16628 | { 16629 | #define exprtk_loop(N) \ 16630 | r[N] += vec[N]; \ 16631 | 16632 | exprtk_loop( 0) exprtk_loop( 1) 16633 | exprtk_loop( 2) exprtk_loop( 3) 16634 | #ifndef exprtk_disable_superscalar_unroll 16635 | exprtk_loop( 4) exprtk_loop( 5) 16636 | exprtk_loop( 6) exprtk_loop( 7) 16637 | exprtk_loop( 8) exprtk_loop( 9) 16638 | exprtk_loop(10) exprtk_loop(11) 16639 | exprtk_loop(12) exprtk_loop(13) 16640 | exprtk_loop(14) exprtk_loop(15) 16641 | #endif 16642 | 16643 | vec += lud.batch_size; 16644 | } 16645 | 16646 | int i = 0; 16647 | 16648 | switch (lud.remainder) 16649 | { 16650 | #define case_stmt(N,fall_through) \ 16651 | case N : r[0] += vec[i++]; \ 16652 | fall_through \ 16653 | 16654 | #ifndef exprtk_disable_superscalar_unroll 16655 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 16656 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 16657 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 16658 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 16659 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 16660 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 16661 | #endif 16662 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 16663 | case_stmt( 1, (void)0;) 16664 | } 16665 | 16666 | #undef exprtk_loop 16667 | #undef case_stmt 16668 | 16669 | return (r[ 0] + r[ 1] + r[ 2] + r[ 3]) 16670 | #ifndef exprtk_disable_superscalar_unroll 16671 | + (r[ 4] + r[ 5] + r[ 6] + r[ 7]) 16672 | + (r[ 8] + r[ 9] + r[10] + r[11]) 16673 | + (r[12] + r[13] + r[14] + r[15]) 16674 | #endif 16675 | ; 16676 | } 16677 | }; 16678 | 16679 | template <typename T> 16680 | struct vec_mul_op 16681 | { 16682 | typedef vector_interface<T>* ivector_ptr; 16683 | 16684 | static inline T process(const ivector_ptr v) 16685 | { 16686 | const T* vec = v->vec()->vds().data(); 16687 | const std::size_t vec_size = v->vec()->size(); 16688 | 16689 | loop_unroll::details lud(vec_size); 16690 | 16691 | if (vec_size <= static_cast<std::size_t>(lud.batch_size)) 16692 | { 16693 | T result = T(1); 16694 | int i = 0; 16695 | 16696 | switch (vec_size) 16697 | { 16698 | #define case_stmt(N,fall_through) \ 16699 | case N : result *= vec[i++]; \ 16700 | fall_through \ 16701 | 16702 | #ifndef exprtk_disable_superscalar_unroll 16703 | case_stmt(16, exprtk_fallthrough) case_stmt(15, exprtk_fallthrough) 16704 | case_stmt(14, exprtk_fallthrough) case_stmt(13, exprtk_fallthrough) 16705 | case_stmt(12, exprtk_fallthrough) case_stmt(11, exprtk_fallthrough) 16706 | case_stmt(10, exprtk_fallthrough) case_stmt( 9, exprtk_fallthrough) 16707 | case_stmt( 8, exprtk_fallthrough) case_stmt( 7, exprtk_fallthrough) 16708 | case_stmt( 6, exprtk_fallthrough) case_stmt( 5, exprtk_fallthrough) 16709 | #endif 16710 | case_stmt( 4, exprtk_fallthrough) case_stmt( 3, exprtk_fallthrough) 16711 | case_stmt( 2, exprtk_fallthrough) case_stmt( 1, (void)0;) 16712 | } 16713 | 16714 | #undef case_stmt 16715 | 16716 | return result; 16717 | } 16718 | 16719 | T r[] = { 16720 | T(1), T(1), T(1), T(1), T(1), T(1), T(1), T(1), 16721 | T(1), T(1), T(1), T(1), T(1), T(1), T(1), T(1) 16722 | }; 16723 | 16724 | const T* upper_bound = vec + lud.upper_bound; 16725 | 16726 | while (vec < upper_bound) 16727 | { 16728 | #define exprtk_loop(N) \ 16729 | r[N] *= vec[N]; \ 16730 | 16731 | exprtk_loop( 0) exprtk_loop( 1) 16732 | exprtk_loop( 2) exprtk_loop( 3) 16733 | #ifndef exprtk_disable_superscalar_unroll 16734 | exprtk_loop( 4) exprtk_loop( 5) 16735 | exprtk_loop( 6) exprtk_loop( 7) 16736 | exprtk_loop( 8) exprtk_loop( 9) 16737 | exprtk_loop(10) exprtk_loop(11) 16738 | exprtk_loop(12) exprtk_loop(13) 16739 | exprtk_loop(14) exprtk_loop(15) 16740 | #endif 16741 | 16742 | vec += lud.batch_size; 16743 | } 16744 | 16745 | int i = 0; 16746 | 16747 | switch (lud.remainder) 16748 | { 16749 | #define case_stmt(N,fall_through) \ 16750 | case N : r[0] *= vec[i++]; \ 16751 | fall_through \ 16752 | 16753 | #ifndef exprtk_disable_superscalar_unroll 16754 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 16755 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 16756 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 16757 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 16758 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 16759 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 16760 | #endif 16761 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 16762 | case_stmt( 1, (void)0;) 16763 | } 16764 | 16765 | #undef exprtk_loop 16766 | #undef case_stmt 16767 | 16768 | return (r[ 0] * r[ 1] * r[ 2] * r[ 3]) 16769 | #ifndef exprtk_disable_superscalar_unroll 16770 | * (r[ 4] * r[ 5] * r[ 6] * r[ 7]) 16771 | * (r[ 8] * r[ 9] * r[10] * r[11]) 16772 | * (r[12] * r[13] * r[14] * r[15]) 16773 | #endif 16774 | ; 16775 | } 16776 | }; 16777 | 16778 | template <typename T> 16779 | struct vec_avg_op 16780 | { 16781 | typedef vector_interface<T>* ivector_ptr; 16782 | 16783 | static inline T process(const ivector_ptr v) 16784 | { 16785 | const T vec_size = T(v->vec()->size()); 16786 | return vec_add_op<T>::process(v) / vec_size; 16787 | } 16788 | }; 16789 | 16790 | template <typename T> 16791 | struct vec_min_op 16792 | { 16793 | typedef vector_interface<T>* ivector_ptr; 16794 | 16795 | static inline T process(const ivector_ptr v) 16796 | { 16797 | const T* vec = v->vec()->vds().data(); 16798 | const std::size_t vec_size = v->vec()->size(); 16799 | 16800 | T result = vec[0]; 16801 | 16802 | for (std::size_t i = 1; i < vec_size; ++i) 16803 | { 16804 | const T v_i = vec[i]; 16805 | 16806 | if (v_i < result) 16807 | result = v_i; 16808 | } 16809 | 16810 | return result; 16811 | } 16812 | }; 16813 | 16814 | template <typename T> 16815 | struct vec_max_op 16816 | { 16817 | typedef vector_interface<T>* ivector_ptr; 16818 | 16819 | static inline T process(const ivector_ptr v) 16820 | { 16821 | const T* vec = v->vec()->vds().data(); 16822 | const std::size_t vec_size = v->vec()->size(); 16823 | 16824 | T result = vec[0]; 16825 | 16826 | for (std::size_t i = 1; i < vec_size; ++i) 16827 | { 16828 | const T v_i = vec[i]; 16829 | 16830 | if (v_i > result) 16831 | result = v_i; 16832 | } 16833 | 16834 | return result; 16835 | } 16836 | }; 16837 | 16838 | template <typename T> 16839 | class vov_base_node : public expression_node<T> 16840 | { 16841 | public: 16842 | 16843 | virtual ~vov_base_node() 16844 | {} 16845 | 16846 | inline virtual operator_type operation() const 16847 | { 16848 | return details::e_default; 16849 | } 16850 | 16851 | virtual const T& v0() const = 0; 16852 | 16853 | virtual const T& v1() const = 0; 16854 | }; 16855 | 16856 | template <typename T> 16857 | class cov_base_node : public expression_node<T> 16858 | { 16859 | public: 16860 | 16861 | virtual ~cov_base_node() 16862 | {} 16863 | 16864 | inline virtual operator_type operation() const 16865 | { 16866 | return details::e_default; 16867 | } 16868 | 16869 | virtual const T c() const = 0; 16870 | 16871 | virtual const T& v() const = 0; 16872 | }; 16873 | 16874 | template <typename T> 16875 | class voc_base_node : public expression_node<T> 16876 | { 16877 | public: 16878 | 16879 | virtual ~voc_base_node() 16880 | {} 16881 | 16882 | inline virtual operator_type operation() const 16883 | { 16884 | return details::e_default; 16885 | } 16886 | 16887 | virtual const T c() const = 0; 16888 | 16889 | virtual const T& v() const = 0; 16890 | }; 16891 | 16892 | template <typename T> 16893 | class vob_base_node : public expression_node<T> 16894 | { 16895 | public: 16896 | 16897 | virtual ~vob_base_node() 16898 | {} 16899 | 16900 | virtual const T& v() const = 0; 16901 | }; 16902 | 16903 | template <typename T> 16904 | class bov_base_node : public expression_node<T> 16905 | { 16906 | public: 16907 | 16908 | virtual ~bov_base_node() 16909 | {} 16910 | 16911 | virtual const T& v() const = 0; 16912 | }; 16913 | 16914 | template <typename T> 16915 | class cob_base_node : public expression_node<T> 16916 | { 16917 | public: 16918 | 16919 | virtual ~cob_base_node() 16920 | {} 16921 | 16922 | inline virtual operator_type operation() const 16923 | { 16924 | return details::e_default; 16925 | } 16926 | 16927 | virtual const T c() const = 0; 16928 | 16929 | virtual void set_c(const T) = 0; 16930 | 16931 | virtual expression_node<T>* move_branch(const std::size_t& index) = 0; 16932 | }; 16933 | 16934 | template <typename T> 16935 | class boc_base_node : public expression_node<T> 16936 | { 16937 | public: 16938 | 16939 | virtual ~boc_base_node() 16940 | {} 16941 | 16942 | inline virtual operator_type operation() const 16943 | { 16944 | return details::e_default; 16945 | } 16946 | 16947 | virtual const T c() const = 0; 16948 | 16949 | virtual void set_c(const T) = 0; 16950 | 16951 | virtual expression_node<T>* move_branch(const std::size_t& index) = 0; 16952 | }; 16953 | 16954 | template <typename T> 16955 | class uv_base_node : public expression_node<T> 16956 | { 16957 | public: 16958 | 16959 | virtual ~uv_base_node() 16960 | {} 16961 | 16962 | inline virtual operator_type operation() const 16963 | { 16964 | return details::e_default; 16965 | } 16966 | 16967 | virtual const T& v() const = 0; 16968 | }; 16969 | 16970 | template <typename T> 16971 | class sos_base_node : public expression_node<T> 16972 | { 16973 | public: 16974 | 16975 | virtual ~sos_base_node() 16976 | {} 16977 | 16978 | inline virtual operator_type operation() const 16979 | { 16980 | return details::e_default; 16981 | } 16982 | }; 16983 | 16984 | template <typename T> 16985 | class sosos_base_node : public expression_node<T> 16986 | { 16987 | public: 16988 | 16989 | virtual ~sosos_base_node() 16990 | {} 16991 | 16992 | inline virtual operator_type operation() const 16993 | { 16994 | return details::e_default; 16995 | } 16996 | }; 16997 | 16998 | template <typename T> 16999 | class T0oT1oT2_base_node : public expression_node<T> 17000 | { 17001 | public: 17002 | 17003 | virtual ~T0oT1oT2_base_node() 17004 | {} 17005 | 17006 | virtual std::string type_id() const = 0; 17007 | }; 17008 | 17009 | template <typename T> 17010 | class T0oT1oT2oT3_base_node : public expression_node<T> 17011 | { 17012 | public: 17013 | 17014 | virtual ~T0oT1oT2oT3_base_node() 17015 | {} 17016 | 17017 | virtual std::string type_id() const = 0; 17018 | }; 17019 | 17020 | template <typename T, typename Operation> 17021 | class unary_variable_node exprtk_final : public uv_base_node<T> 17022 | { 17023 | public: 17024 | 17025 | typedef expression_node<T>* expression_ptr; 17026 | typedef Operation operation_t; 17027 | 17028 | explicit unary_variable_node(const T& var) 17029 | : v_(var) 17030 | {} 17031 | 17032 | inline T value() const exprtk_override 17033 | { 17034 | return Operation::process(v_); 17035 | } 17036 | 17037 | inline typename expression_node<T>::node_type type() const exprtk_override 17038 | { 17039 | return Operation::type(); 17040 | } 17041 | 17042 | inline operator_type operation() const exprtk_override 17043 | { 17044 | return Operation::operation(); 17045 | } 17046 | 17047 | inline const T& v() const exprtk_override 17048 | { 17049 | return v_; 17050 | } 17051 | 17052 | private: 17053 | 17054 | unary_variable_node(const unary_variable_node<T,Operation>&) exprtk_delete; 17055 | unary_variable_node<T,Operation>& operator=(const unary_variable_node<T,Operation>&) exprtk_delete; 17056 | 17057 | const T& v_; 17058 | }; 17059 | 17060 | template <typename T> 17061 | class uvouv_node exprtk_final : public expression_node<T> 17062 | { 17063 | public: 17064 | 17065 | // UOpr1(v0) Op UOpr2(v1) 17066 | typedef typename details::functor_t<T> functor_t; 17067 | typedef typename functor_t::bfunc_t bfunc_t; 17068 | typedef typename functor_t::ufunc_t ufunc_t; 17069 | typedef expression_node<T>* expression_ptr; 17070 | 17071 | explicit uvouv_node(const T& var0,const T& var1, 17072 | ufunc_t uf0, ufunc_t uf1, bfunc_t bf) 17073 | : v0_(var0) 17074 | , v1_(var1) 17075 | , u0_(uf0 ) 17076 | , u1_(uf1 ) 17077 | , f_ (bf ) 17078 | {} 17079 | 17080 | inline T value() const exprtk_override 17081 | { 17082 | return f_(u0_(v0_),u1_(v1_)); 17083 | } 17084 | 17085 | inline typename expression_node<T>::node_type type() const exprtk_override 17086 | { 17087 | return expression_node<T>::e_uvouv; 17088 | } 17089 | 17090 | inline const T& v0() 17091 | { 17092 | return v0_; 17093 | } 17094 | 17095 | inline const T& v1() 17096 | { 17097 | return v1_; 17098 | } 17099 | 17100 | inline ufunc_t u0() 17101 | { 17102 | return u0_; 17103 | } 17104 | 17105 | inline ufunc_t u1() 17106 | { 17107 | return u1_; 17108 | } 17109 | 17110 | inline ufunc_t f() 17111 | { 17112 | return f_; 17113 | } 17114 | 17115 | private: 17116 | 17117 | uvouv_node(const uvouv_node<T>&) exprtk_delete; 17118 | uvouv_node<T>& operator=(const uvouv_node<T>&) exprtk_delete; 17119 | 17120 | const T& v0_; 17121 | const T& v1_; 17122 | const ufunc_t u0_; 17123 | const ufunc_t u1_; 17124 | const bfunc_t f_; 17125 | }; 17126 | 17127 | template <typename T, typename Operation> 17128 | class unary_branch_node exprtk_final : public expression_node<T> 17129 | { 17130 | public: 17131 | 17132 | typedef Operation operation_t; 17133 | typedef expression_node<T>* expression_ptr; 17134 | typedef std::pair<expression_ptr,bool> branch_t; 17135 | 17136 | explicit unary_branch_node(expression_ptr branch) 17137 | { 17138 | construct_branch_pair(branch_, branch); 17139 | } 17140 | 17141 | inline T value() const exprtk_override 17142 | { 17143 | return Operation::process(branch_.first->value()); 17144 | } 17145 | 17146 | inline typename expression_node<T>::node_type type() const exprtk_override 17147 | { 17148 | return Operation::type(); 17149 | } 17150 | 17151 | inline bool valid() const exprtk_override 17152 | { 17153 | return branch_.first && branch_.first->valid(); 17154 | } 17155 | 17156 | inline operator_type operation() 17157 | { 17158 | return Operation::operation(); 17159 | } 17160 | 17161 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 17162 | { 17163 | return branch_.first; 17164 | } 17165 | 17166 | inline void release() 17167 | { 17168 | branch_.second = false; 17169 | } 17170 | 17171 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 17172 | { 17173 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 17174 | } 17175 | 17176 | std::size_t node_depth() const exprtk_override 17177 | { 17178 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 17179 | } 17180 | 17181 | private: 17182 | 17183 | unary_branch_node(const unary_branch_node<T,Operation>&) exprtk_delete; 17184 | unary_branch_node<T,Operation>& operator=(const unary_branch_node<T,Operation>&) exprtk_delete; 17185 | 17186 | branch_t branch_; 17187 | }; 17188 | 17189 | template <typename T> struct is_const { enum {result = 0}; }; 17190 | template <typename T> struct is_const <const T> { enum {result = 1}; }; 17191 | template <typename T> struct is_const_ref { enum {result = 0}; }; 17192 | template <typename T> struct is_const_ref <const T&> { enum {result = 1}; }; 17193 | template <typename T> struct is_ref { enum {result = 0}; }; 17194 | template <typename T> struct is_ref<T&> { enum {result = 1}; }; 17195 | template <typename T> struct is_ref<const T&> { enum {result = 0}; }; 17196 | 17197 | template <std::size_t State> 17198 | struct param_to_str { static std::string result() { static const std::string r("v"); return r; } }; 17199 | 17200 | template <> 17201 | struct param_to_str<0> { static std::string result() { static const std::string r("c"); return r; } }; 17202 | 17203 | #define exprtk_crtype(Type) \ 17204 | param_to_str<is_const_ref< Type >::result>::result() \ 17205 | 17206 | template <typename T> 17207 | struct T0oT1oT2process 17208 | { 17209 | typedef typename details::functor_t<T> functor_t; 17210 | typedef typename functor_t::bfunc_t bfunc_t; 17211 | 17212 | struct mode0 17213 | { 17214 | static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1) 17215 | { 17216 | // (T0 o0 T1) o1 T2 17217 | return bf1(bf0(t0,t1),t2); 17218 | } 17219 | 17220 | template <typename T0, typename T1, typename T2> 17221 | static inline std::string id() 17222 | { 17223 | static const std::string result = "(" + exprtk_crtype(T0) + "o" + 17224 | exprtk_crtype(T1) + ")o(" + 17225 | exprtk_crtype(T2) + ")" ; 17226 | return result; 17227 | } 17228 | }; 17229 | 17230 | struct mode1 17231 | { 17232 | static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1) 17233 | { 17234 | // T0 o0 (T1 o1 T2) 17235 | return bf0(t0,bf1(t1,t2)); 17236 | } 17237 | 17238 | template <typename T0, typename T1, typename T2> 17239 | static inline std::string id() 17240 | { 17241 | static const std::string result = "(" + exprtk_crtype(T0) + ")o(" + 17242 | exprtk_crtype(T1) + "o" + 17243 | exprtk_crtype(T2) + ")" ; 17244 | return result; 17245 | } 17246 | }; 17247 | }; 17248 | 17249 | template <typename T> 17250 | struct T0oT1oT20T3process 17251 | { 17252 | typedef typename details::functor_t<T> functor_t; 17253 | typedef typename functor_t::bfunc_t bfunc_t; 17254 | 17255 | struct mode0 17256 | { 17257 | static inline T process(const T& t0, const T& t1, 17258 | const T& t2, const T& t3, 17259 | const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) 17260 | { 17261 | // (T0 o0 T1) o1 (T2 o2 T3) 17262 | return bf1(bf0(t0,t1),bf2(t2,t3)); 17263 | } 17264 | 17265 | template <typename T0, typename T1, typename T2, typename T3> 17266 | static inline std::string id() 17267 | { 17268 | static const std::string result = "(" + exprtk_crtype(T0) + "o" + 17269 | exprtk_crtype(T1) + ")o" + 17270 | "(" + exprtk_crtype(T2) + "o" + 17271 | exprtk_crtype(T3) + ")" ; 17272 | return result; 17273 | } 17274 | }; 17275 | 17276 | struct mode1 17277 | { 17278 | static inline T process(const T& t0, const T& t1, 17279 | const T& t2, const T& t3, 17280 | const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) 17281 | { 17282 | // (T0 o0 (T1 o1 (T2 o2 T3)) 17283 | return bf0(t0,bf1(t1,bf2(t2,t3))); 17284 | } 17285 | template <typename T0, typename T1, typename T2, typename T3> 17286 | static inline std::string id() 17287 | { 17288 | static const std::string result = "(" + exprtk_crtype(T0) + ")o((" + 17289 | exprtk_crtype(T1) + ")o(" + 17290 | exprtk_crtype(T2) + "o" + 17291 | exprtk_crtype(T3) + "))" ; 17292 | return result; 17293 | } 17294 | }; 17295 | 17296 | struct mode2 17297 | { 17298 | static inline T process(const T& t0, const T& t1, 17299 | const T& t2, const T& t3, 17300 | const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) 17301 | { 17302 | // (T0 o0 ((T1 o1 T2) o2 T3) 17303 | return bf0(t0,bf2(bf1(t1,t2),t3)); 17304 | } 17305 | 17306 | template <typename T0, typename T1, typename T2, typename T3> 17307 | static inline std::string id() 17308 | { 17309 | static const std::string result = "(" + exprtk_crtype(T0) + ")o((" + 17310 | exprtk_crtype(T1) + "o" + 17311 | exprtk_crtype(T2) + ")o(" + 17312 | exprtk_crtype(T3) + "))" ; 17313 | return result; 17314 | } 17315 | }; 17316 | 17317 | struct mode3 17318 | { 17319 | static inline T process(const T& t0, const T& t1, 17320 | const T& t2, const T& t3, 17321 | const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) 17322 | { 17323 | // (((T0 o0 T1) o1 T2) o2 T3) 17324 | return bf2(bf1(bf0(t0,t1),t2),t3); 17325 | } 17326 | 17327 | template <typename T0, typename T1, typename T2, typename T3> 17328 | static inline std::string id() 17329 | { 17330 | static const std::string result = "((" + exprtk_crtype(T0) + "o" + 17331 | exprtk_crtype(T1) + ")o(" + 17332 | exprtk_crtype(T2) + "))o(" + 17333 | exprtk_crtype(T3) + ")" 17334 | return result; 17335 | } 17336 | }; 17337 | 17338 | struct mode4 17339 | { 17340 | static inline T process(const T& t0, const T& t1, 17341 | const T& t2, const T& t3, 17342 | const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) 17343 | { 17344 | // ((T0 o0 (T1 o1 T2)) o2 T3 17345 | return bf2(bf0(t0,bf1(t1,t2)),t3); 17346 | } 17347 | 17348 | template <typename T0, typename T1, typename T2, typename T3> 17349 | static inline std::string id() 17350 | { 17351 | static const std::string result = "((" + exprtk_crtype(T0) + ")o(" + 17352 | exprtk_crtype(T1) + "o" + 17353 | exprtk_crtype(T2) + "))o(" + 17354 | exprtk_crtype(T3) + ")" ; 17355 | return result; 17356 | } 17357 | }; 17358 | }; 17359 | 17360 | #undef exprtk_crtype 17361 | 17362 | template <typename T, typename T0, typename T1> 17363 | struct nodetype_T0oT1 { static const typename expression_node<T>::node_type result; }; 17364 | template <typename T, typename T0, typename T1> 17365 | const typename expression_node<T>::node_type nodetype_T0oT1<T,T0,T1>::result = expression_node<T>::e_none; 17366 | 17367 | #define synthesis_node_type_define(T0_, T1_, v_) \ 17368 | template <typename T, typename T0, typename T1> \ 17369 | struct nodetype_T0oT1<T,T0_,T1_> { static const typename expression_node<T>::node_type result; }; \ 17370 | template <typename T, typename T0, typename T1> \ 17371 | const typename expression_node<T>::node_type nodetype_T0oT1<T,T0_,T1_>::result = expression_node<T>:: v_; \ 17372 | 17373 | synthesis_node_type_define(const T0&, const T1&, e_vov) 17374 | synthesis_node_type_define(const T0&, const T1 , e_voc) 17375 | synthesis_node_type_define(const T0 , const T1&, e_cov) 17376 | synthesis_node_type_define( T0&, T1&, e_none) 17377 | synthesis_node_type_define(const T0 , const T1 , e_none) 17378 | synthesis_node_type_define( T0&, const T1 , e_none) 17379 | synthesis_node_type_define(const T0 , T1&, e_none) 17380 | synthesis_node_type_define(const T0&, T1&, e_none) 17381 | synthesis_node_type_define( T0&, const T1&, e_none) 17382 | #undef synthesis_node_type_define 17383 | 17384 | template <typename T, typename T0, typename T1, typename T2> 17385 | struct nodetype_T0oT1oT2 { static const typename expression_node<T>::node_type result; }; 17386 | template <typename T, typename T0, typename T1, typename T2> 17387 | const typename expression_node<T>::node_type nodetype_T0oT1oT2<T,T0,T1,T2>::result = expression_node<T>::e_none; 17388 | 17389 | #define synthesis_node_type_define(T0_, T1_, T2_, v_) \ 17390 | template <typename T, typename T0, typename T1, typename T2> \ 17391 | struct nodetype_T0oT1oT2<T,T0_,T1_,T2_> { static const typename expression_node<T>::node_type result; }; \ 17392 | template <typename T, typename T0, typename T1, typename T2> \ 17393 | const typename expression_node<T>::node_type nodetype_T0oT1oT2<T,T0_,T1_,T2_>::result = expression_node<T>:: v_; \ 17394 | 17395 | synthesis_node_type_define(const T0&, const T1&, const T2&, e_vovov) 17396 | synthesis_node_type_define(const T0&, const T1&, const T2 , e_vovoc) 17397 | synthesis_node_type_define(const T0&, const T1 , const T2&, e_vocov) 17398 | synthesis_node_type_define(const T0 , const T1&, const T2&, e_covov) 17399 | synthesis_node_type_define(const T0 , const T1&, const T2 , e_covoc) 17400 | synthesis_node_type_define(const T0 , const T1 , const T2 , e_none ) 17401 | synthesis_node_type_define(const T0 , const T1 , const T2&, e_none ) 17402 | synthesis_node_type_define(const T0&, const T1 , const T2 , e_none ) 17403 | synthesis_node_type_define( T0&, T1&, T2&, e_none ) 17404 | #undef synthesis_node_type_define 17405 | 17406 | template <typename T, typename T0, typename T1, typename T2, typename T3> 17407 | struct nodetype_T0oT1oT2oT3 { static const typename expression_node<T>::node_type result; }; 17408 | template <typename T, typename T0, typename T1, typename T2, typename T3> 17409 | const typename expression_node<T>::node_type nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result = expression_node<T>::e_none; 17410 | 17411 | #define synthesis_node_type_define(T0_, T1_, T2_, T3_, v_) \ 17412 | template <typename T, typename T0, typename T1, typename T2, typename T3> \ 17413 | struct nodetype_T0oT1oT2oT3<T,T0_,T1_,T2_,T3_> { static const typename expression_node<T>::node_type result; }; \ 17414 | template <typename T, typename T0, typename T1, typename T2, typename T3> \ 17415 | const typename expression_node<T>::node_type nodetype_T0oT1oT2oT3<T,T0_,T1_,T2_,T3_>::result = expression_node<T>:: v_; \ 17416 | 17417 | synthesis_node_type_define(const T0&, const T1&, const T2&, const T3&, e_vovovov) 17418 | synthesis_node_type_define(const T0&, const T1&, const T2&, const T3 , e_vovovoc) 17419 | synthesis_node_type_define(const T0&, const T1&, const T2 , const T3&, e_vovocov) 17420 | synthesis_node_type_define(const T0&, const T1 , const T2&, const T3&, e_vocovov) 17421 | synthesis_node_type_define(const T0 , const T1&, const T2&, const T3&, e_covovov) 17422 | synthesis_node_type_define(const T0 , const T1&, const T2 , const T3&, e_covocov) 17423 | synthesis_node_type_define(const T0&, const T1 , const T2&, const T3 , e_vocovoc) 17424 | synthesis_node_type_define(const T0 , const T1&, const T2&, const T3 , e_covovoc) 17425 | synthesis_node_type_define(const T0&, const T1 , const T2 , const T3&, e_vococov) 17426 | synthesis_node_type_define(const T0 , const T1 , const T2 , const T3 , e_none ) 17427 | synthesis_node_type_define(const T0 , const T1 , const T2 , const T3&, e_none ) 17428 | synthesis_node_type_define(const T0 , const T1 , const T2&, const T3 , e_none ) 17429 | synthesis_node_type_define(const T0 , const T1&, const T2 , const T3 , e_none ) 17430 | synthesis_node_type_define(const T0&, const T1 , const T2 , const T3 , e_none ) 17431 | synthesis_node_type_define(const T0 , const T1 , const T2&, const T3&, e_none ) 17432 | synthesis_node_type_define(const T0&, const T1&, const T2 , const T3 , e_none ) 17433 | #undef synthesis_node_type_define 17434 | 17435 | template <typename T, typename T0, typename T1> 17436 | class T0oT1 exprtk_final : public expression_node<T> 17437 | { 17438 | public: 17439 | 17440 | typedef typename details::functor_t<T> functor_t; 17441 | typedef typename functor_t::bfunc_t bfunc_t; 17442 | typedef T value_type; 17443 | typedef T0oT1<T,T0,T1> node_type; 17444 | 17445 | T0oT1(T0 p0, T1 p1, const bfunc_t p2) 17446 | : t0_(p0) 17447 | , t1_(p1) 17448 | , f_ (p2) 17449 | {} 17450 | 17451 | inline typename expression_node<T>::node_type type() const exprtk_override 17452 | { 17453 | static const typename expression_node<T>::node_type result = nodetype_T0oT1<T,T0,T1>::result; 17454 | return result; 17455 | } 17456 | 17457 | inline operator_type operation() const exprtk_override 17458 | { 17459 | return e_default; 17460 | } 17461 | 17462 | inline T value() const exprtk_override 17463 | { 17464 | return f_(t0_,t1_); 17465 | } 17466 | 17467 | inline T0 t0() const 17468 | { 17469 | return t0_; 17470 | } 17471 | 17472 | inline T1 t1() const 17473 | { 17474 | return t1_; 17475 | } 17476 | 17477 | inline bfunc_t f() const 17478 | { 17479 | return f_; 17480 | } 17481 | 17482 | template <typename Allocator> 17483 | static inline expression_node<T>* allocate(Allocator& allocator, 17484 | T0 p0, T1 p1, 17485 | bfunc_t p2) 17486 | { 17487 | return allocator 17488 | .template allocate_type<node_type, T0, T1, bfunc_t&> 17489 | (p0, p1, p2); 17490 | } 17491 | 17492 | private: 17493 | 17494 | T0oT1(const T0oT1<T,T0,T1>&) exprtk_delete; 17495 | T0oT1<T,T0,T1>& operator=(const T0oT1<T,T0,T1>&) { return (*this); } 17496 | 17497 | T0 t0_; 17498 | T1 t1_; 17499 | const bfunc_t f_; 17500 | }; 17501 | 17502 | template <typename T, typename T0, typename T1, typename T2, typename ProcessMode> 17503 | class T0oT1oT2 exprtk_final : public T0oT1oT2_base_node<T> 17504 | { 17505 | public: 17506 | 17507 | typedef typename details::functor_t<T> functor_t; 17508 | typedef typename functor_t::bfunc_t bfunc_t; 17509 | typedef T value_type; 17510 | typedef T0oT1oT2<T,T0,T1,T2,ProcessMode> node_type; 17511 | typedef ProcessMode process_mode_t; 17512 | 17513 | T0oT1oT2(T0 p0, T1 p1, T2 p2, const bfunc_t p3, const bfunc_t p4) 17514 | : t0_(p0) 17515 | , t1_(p1) 17516 | , t2_(p2) 17517 | , f0_(p3) 17518 | , f1_(p4) 17519 | {} 17520 | 17521 | inline typename expression_node<T>::node_type type() const exprtk_override 17522 | { 17523 | static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result; 17524 | return result; 17525 | } 17526 | 17527 | inline operator_type operation() 17528 | { 17529 | return e_default; 17530 | } 17531 | 17532 | inline T value() const exprtk_override 17533 | { 17534 | return ProcessMode::process(t0_, t1_, t2_, f0_, f1_); 17535 | } 17536 | 17537 | inline T0 t0() const 17538 | { 17539 | return t0_; 17540 | } 17541 | 17542 | inline T1 t1() const 17543 | { 17544 | return t1_; 17545 | } 17546 | 17547 | inline T2 t2() const 17548 | { 17549 | return t2_; 17550 | } 17551 | 17552 | bfunc_t f0() const 17553 | { 17554 | return f0_; 17555 | } 17556 | 17557 | bfunc_t f1() const 17558 | { 17559 | return f1_; 17560 | } 17561 | 17562 | std::string type_id() const exprtk_override 17563 | { 17564 | return id(); 17565 | } 17566 | 17567 | static inline std::string id() 17568 | { 17569 | return process_mode_t::template id<T0,T1,T2>(); 17570 | } 17571 | 17572 | template <typename Allocator> 17573 | static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, bfunc_t p3, bfunc_t p4) 17574 | { 17575 | return allocator 17576 | .template allocate_type<node_type, T0, T1, T2, bfunc_t, bfunc_t> 17577 | (p0, p1, p2, p3, p4); 17578 | } 17579 | 17580 | private: 17581 | 17582 | T0oT1oT2(const node_type&) exprtk_delete; 17583 | node_type& operator=(const node_type&) exprtk_delete; 17584 | 17585 | T0 t0_; 17586 | T1 t1_; 17587 | T2 t2_; 17588 | const bfunc_t f0_; 17589 | const bfunc_t f1_; 17590 | }; 17591 | 17592 | template <typename T, typename T0_, typename T1_, typename T2_, typename T3_, typename ProcessMode> 17593 | class T0oT1oT2oT3 exprtk_final : public T0oT1oT2oT3_base_node<T> 17594 | { 17595 | public: 17596 | 17597 | typedef typename details::functor_t<T> functor_t; 17598 | typedef typename functor_t::bfunc_t bfunc_t; 17599 | typedef T value_type; 17600 | typedef T0_ T0; 17601 | typedef T1_ T1; 17602 | typedef T2_ T2; 17603 | typedef T3_ T3; 17604 | typedef T0oT1oT2oT3<T,T0,T1,T2,T3,ProcessMode> node_type; 17605 | typedef ProcessMode process_mode_t; 17606 | 17607 | T0oT1oT2oT3(T0 p0, T1 p1, T2 p2, T3 p3, bfunc_t p4, bfunc_t p5, bfunc_t p6) 17608 | : t0_(p0) 17609 | , t1_(p1) 17610 | , t2_(p2) 17611 | , t3_(p3) 17612 | , f0_(p4) 17613 | , f1_(p5) 17614 | , f2_(p6) 17615 | {} 17616 | 17617 | inline T value() const exprtk_override 17618 | { 17619 | return ProcessMode::process(t0_, t1_, t2_, t3_, f0_, f1_, f2_); 17620 | } 17621 | 17622 | inline T0 t0() const 17623 | { 17624 | return t0_; 17625 | } 17626 | 17627 | inline T1 t1() const 17628 | { 17629 | return t1_; 17630 | } 17631 | 17632 | inline T2 t2() const 17633 | { 17634 | return t2_; 17635 | } 17636 | 17637 | inline T3 t3() const 17638 | { 17639 | return t3_; 17640 | } 17641 | 17642 | inline bfunc_t f0() const 17643 | { 17644 | return f0_; 17645 | } 17646 | 17647 | inline bfunc_t f1() const 17648 | { 17649 | return f1_; 17650 | } 17651 | 17652 | inline bfunc_t f2() const 17653 | { 17654 | return f2_; 17655 | } 17656 | 17657 | inline std::string type_id() const exprtk_override 17658 | { 17659 | return id(); 17660 | } 17661 | 17662 | static inline std::string id() 17663 | { 17664 | return process_mode_t::template id<T0, T1, T2, T3>(); 17665 | } 17666 | 17667 | template <typename Allocator> 17668 | static inline expression_node<T>* allocate(Allocator& allocator, 17669 | T0 p0, T1 p1, T2 p2, T3 p3, 17670 | bfunc_t p4, bfunc_t p5, bfunc_t p6) 17671 | { 17672 | return allocator 17673 | .template allocate_type<node_type, T0, T1, T2, T3, bfunc_t, bfunc_t> 17674 | (p0, p1, p2, p3, p4, p5, p6); 17675 | } 17676 | 17677 | private: 17678 | 17679 | T0oT1oT2oT3(const node_type&) exprtk_delete; 17680 | node_type& operator=(const node_type&) exprtk_delete; 17681 | 17682 | T0 t0_; 17683 | T1 t1_; 17684 | T2 t2_; 17685 | T3 t3_; 17686 | const bfunc_t f0_; 17687 | const bfunc_t f1_; 17688 | const bfunc_t f2_; 17689 | }; 17690 | 17691 | template <typename T, typename T0, typename T1, typename T2> 17692 | class T0oT1oT2_sf3 exprtk_final : public T0oT1oT2_base_node<T> 17693 | { 17694 | public: 17695 | 17696 | typedef typename details::functor_t<T> functor_t; 17697 | typedef typename functor_t::tfunc_t tfunc_t; 17698 | typedef T value_type; 17699 | typedef T0oT1oT2_sf3<T,T0,T1,T2> node_type; 17700 | 17701 | T0oT1oT2_sf3(T0 p0, T1 p1, T2 p2, const tfunc_t p3) 17702 | : t0_(p0) 17703 | , t1_(p1) 17704 | , t2_(p2) 17705 | , f_ (p3) 17706 | {} 17707 | 17708 | inline typename expression_node<T>::node_type type() const exprtk_override 17709 | { 17710 | static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result; 17711 | return result; 17712 | } 17713 | 17714 | inline operator_type operation() const exprtk_override 17715 | { 17716 | return e_default; 17717 | } 17718 | 17719 | inline T value() const exprtk_override 17720 | { 17721 | return f_(t0_, t1_, t2_); 17722 | } 17723 | 17724 | inline T0 t0() const 17725 | { 17726 | return t0_; 17727 | } 17728 | 17729 | inline T1 t1() const 17730 | { 17731 | return t1_; 17732 | } 17733 | 17734 | inline T2 t2() const 17735 | { 17736 | return t2_; 17737 | } 17738 | 17739 | tfunc_t f() const 17740 | { 17741 | return f_; 17742 | } 17743 | 17744 | std::string type_id() const 17745 | { 17746 | return id(); 17747 | } 17748 | 17749 | static inline std::string id() 17750 | { 17751 | return "sf3" 17752 | } 17753 | 17754 | template <typename Allocator> 17755 | static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, tfunc_t p3) 17756 | { 17757 | return allocator 17758 | .template allocate_type<node_type, T0, T1, T2, tfunc_t> 17759 | (p0, p1, p2, p3); 17760 | } 17761 | 17762 | private: 17763 | 17764 | T0oT1oT2_sf3(const node_type&) exprtk_delete; 17765 | node_type& operator=(const node_type&) exprtk_delete; 17766 | 17767 | T0 t0_; 17768 | T1 t1_; 17769 | T2 t2_; 17770 | const tfunc_t f_; 17771 | }; 17772 | 17773 | template <typename T, typename T0, typename T1, typename T2> 17774 | class sf3ext_type_node : public T0oT1oT2_base_node<T> 17775 | { 17776 | public: 17777 | 17778 | virtual ~sf3ext_type_node() 17779 | {} 17780 | 17781 | virtual T0 t0() const = 0; 17782 | 17783 | virtual T1 t1() const = 0; 17784 | 17785 | virtual T2 t2() const = 0; 17786 | }; 17787 | 17788 | template <typename T, typename T0, typename T1, typename T2, typename SF3Operation> 17789 | class T0oT1oT2_sf3ext exprtk_final : public sf3ext_type_node<T,T0,T1,T2> 17790 | { 17791 | public: 17792 | 17793 | typedef T value_type; 17794 | typedef T0oT1oT2_sf3ext<T, T0, T1, T2, SF3Operation> node_type; 17795 | 17796 | T0oT1oT2_sf3ext(T0 p0, T1 p1, T2 p2) 17797 | : t0_(p0) 17798 | , t1_(p1) 17799 | , t2_(p2) 17800 | {} 17801 | 17802 | inline typename expression_node<T>::node_type type() const exprtk_override 17803 | { 17804 | static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result; 17805 | return result; 17806 | } 17807 | 17808 | inline operator_type operation() 17809 | { 17810 | return e_default; 17811 | } 17812 | 17813 | inline T value() const exprtk_override 17814 | { 17815 | return SF3Operation::process(t0_, t1_, t2_); 17816 | } 17817 | 17818 | T0 t0() const exprtk_override 17819 | { 17820 | return t0_; 17821 | } 17822 | 17823 | T1 t1() const exprtk_override 17824 | { 17825 | return t1_; 17826 | } 17827 | 17828 | T2 t2() const exprtk_override 17829 | { 17830 | return t2_; 17831 | } 17832 | 17833 | std::string type_id() const exprtk_override 17834 | { 17835 | return id(); 17836 | } 17837 | 17838 | static inline std::string id() 17839 | { 17840 | return SF3Operation::id(); 17841 | } 17842 | 17843 | template <typename Allocator> 17844 | static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2) 17845 | { 17846 | return allocator 17847 | .template allocate_type<node_type, T0, T1, T2> 17848 | (p0, p1, p2); 17849 | } 17850 | 17851 | private: 17852 | 17853 | T0oT1oT2_sf3ext(const node_type&) exprtk_delete; 17854 | node_type& operator=(const node_type&) exprtk_delete; 17855 | 17856 | T0 t0_; 17857 | T1 t1_; 17858 | T2 t2_; 17859 | }; 17860 | 17861 | template <typename T> 17862 | inline bool is_sf3ext_node(const expression_node<T>* n) 17863 | { 17864 | switch (n->type()) 17865 | { 17866 | case expression_node<T>::e_vovov : return true; 17867 | case expression_node<T>::e_vovoc : return true; 17868 | case expression_node<T>::e_vocov : return true; 17869 | case expression_node<T>::e_covov : return true; 17870 | case expression_node<T>::e_covoc : return true; 17871 | default : return false; 17872 | } 17873 | } 17874 | 17875 | template <typename T, typename T0, typename T1, typename T2, typename T3> 17876 | class T0oT1oT2oT3_sf4 exprtk_final : public T0oT1oT2_base_node<T> 17877 | { 17878 | public: 17879 | 17880 | typedef typename details::functor_t<T> functor_t; 17881 | typedef typename functor_t::qfunc_t qfunc_t; 17882 | typedef T value_type; 17883 | typedef T0oT1oT2oT3_sf4<T, T0, T1, T2, T3> node_type; 17884 | 17885 | T0oT1oT2oT3_sf4(T0 p0, T1 p1, T2 p2, T3 p3, const qfunc_t p4) 17886 | : t0_(p0) 17887 | , t1_(p1) 17888 | , t2_(p2) 17889 | , t3_(p3) 17890 | , f_ (p4) 17891 | {} 17892 | 17893 | inline typename expression_node<T>::node_type type() const exprtk_override 17894 | { 17895 | static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result; 17896 | return result; 17897 | } 17898 | 17899 | inline operator_type operation() const exprtk_override 17900 | { 17901 | return e_default; 17902 | } 17903 | 17904 | inline T value() const exprtk_override 17905 | { 17906 | return f_(t0_, t1_, t2_, t3_); 17907 | } 17908 | 17909 | inline T0 t0() const 17910 | { 17911 | return t0_; 17912 | } 17913 | 17914 | inline T1 t1() const 17915 | { 17916 | return t1_; 17917 | } 17918 | 17919 | inline T2 t2() const 17920 | { 17921 | return t2_; 17922 | } 17923 | 17924 | inline T3 t3() const 17925 | { 17926 | return t3_; 17927 | } 17928 | 17929 | qfunc_t f() const 17930 | { 17931 | return f_; 17932 | } 17933 | 17934 | std::string type_id() const 17935 | { 17936 | return id(); 17937 | } 17938 | 17939 | static inline std::string id() 17940 | { 17941 | return "sf4" 17942 | } 17943 | 17944 | template <typename Allocator> 17945 | static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, T3 p3, qfunc_t p4) 17946 | { 17947 | return allocator 17948 | .template allocate_type<node_type, T0, T1, T2, T3, qfunc_t> 17949 | (p0, p1, p2, p3, p4); 17950 | } 17951 | 17952 | private: 17953 | 17954 | T0oT1oT2oT3_sf4(const node_type&) exprtk_delete; 17955 | node_type& operator=(const node_type&) exprtk_delete; 17956 | 17957 | T0 t0_; 17958 | T1 t1_; 17959 | T2 t2_; 17960 | T3 t3_; 17961 | const qfunc_t f_; 17962 | }; 17963 | 17964 | template <typename T, typename T0, typename T1, typename T2, typename T3, typename SF4Operation> 17965 | class T0oT1oT2oT3_sf4ext exprtk_final : public T0oT1oT2oT3_base_node<T> 17966 | { 17967 | public: 17968 | 17969 | typedef T value_type; 17970 | typedef T0oT1oT2oT3_sf4ext<T, T0, T1, T2, T3, SF4Operation> node_type; 17971 | 17972 | T0oT1oT2oT3_sf4ext(T0 p0, T1 p1, T2 p2, T3 p3) 17973 | : t0_(p0) 17974 | , t1_(p1) 17975 | , t2_(p2) 17976 | , t3_(p3) 17977 | {} 17978 | 17979 | inline typename expression_node<T>::node_type type() const exprtk_override 17980 | { 17981 | static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result; 17982 | return result; 17983 | } 17984 | 17985 | inline T value() const exprtk_override 17986 | { 17987 | return SF4Operation::process(t0_, t1_, t2_, t3_); 17988 | } 17989 | 17990 | inline T0 t0() const 17991 | { 17992 | return t0_; 17993 | } 17994 | 17995 | inline T1 t1() const 17996 | { 17997 | return t1_; 17998 | } 17999 | 18000 | inline T2 t2() const 18001 | { 18002 | return t2_; 18003 | } 18004 | 18005 | inline T3 t3() const 18006 | { 18007 | return t3_; 18008 | } 18009 | 18010 | std::string type_id() const exprtk_override 18011 | { 18012 | return id(); 18013 | } 18014 | 18015 | static inline std::string id() 18016 | { 18017 | return SF4Operation::id(); 18018 | } 18019 | 18020 | template <typename Allocator> 18021 | static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, T3 p3) 18022 | { 18023 | return allocator 18024 | .template allocate_type<node_type, T0, T1, T2, T3> 18025 | (p0, p1, p2, p3); 18026 | } 18027 | 18028 | private: 18029 | 18030 | T0oT1oT2oT3_sf4ext(const node_type&) exprtk_delete; 18031 | node_type& operator=(const node_type&) exprtk_delete; 18032 | 18033 | T0 t0_; 18034 | T1 t1_; 18035 | T2 t2_; 18036 | T3 t3_; 18037 | }; 18038 | 18039 | template <typename T> 18040 | inline bool is_sf4ext_node(const expression_node<T>* n) 18041 | { 18042 | switch (n->type()) 18043 | { 18044 | case expression_node<T>::e_vovovov : return true; 18045 | case expression_node<T>::e_vovovoc : return true; 18046 | case expression_node<T>::e_vovocov : return true; 18047 | case expression_node<T>::e_vocovov : return true; 18048 | case expression_node<T>::e_covovov : return true; 18049 | case expression_node<T>::e_covocov : return true; 18050 | case expression_node<T>::e_vocovoc : return true; 18051 | case expression_node<T>::e_covovoc : return true; 18052 | case expression_node<T>::e_vococov : return true; 18053 | default : return false; 18054 | } 18055 | } 18056 | 18057 | template <typename T, typename T0, typename T1> 18058 | struct T0oT1_define 18059 | { 18060 | typedef details::T0oT1<T, T0, T1> type0; 18061 | }; 18062 | 18063 | template <typename T, typename T0, typename T1, typename T2> 18064 | struct T0oT1oT2_define 18065 | { 18066 | typedef details::T0oT1oT2<T, T0, T1, T2, typename T0oT1oT2process<T>::mode0> type0; 18067 | typedef details::T0oT1oT2<T, T0, T1, T2, typename T0oT1oT2process<T>::mode1> type1; 18068 | typedef details::T0oT1oT2_sf3<T, T0, T1, T2> sf3_type; 18069 | typedef details::sf3ext_type_node<T, T0, T1, T2> sf3_type_node; 18070 | }; 18071 | 18072 | template <typename T, typename T0, typename T1, typename T2, typename T3> 18073 | struct T0oT1oT2oT3_define 18074 | { 18075 | typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode0> type0; 18076 | typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode1> type1; 18077 | typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode2> type2; 18078 | typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode3> type3; 18079 | typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode4> type4; 18080 | typedef details::T0oT1oT2oT3_sf4<T, T0, T1, T2, T3> sf4_type; 18081 | }; 18082 | 18083 | template <typename T, typename Operation> 18084 | class vov_node exprtk_final : public vov_base_node<T> 18085 | { 18086 | public: 18087 | 18088 | typedef expression_node<T>* expression_ptr; 18089 | typedef Operation operation_t; 18090 | 18091 | // variable op variable node 18092 | explicit vov_node(const T& var0, const T& var1) 18093 | : v0_(var0) 18094 | , v1_(var1) 18095 | {} 18096 | 18097 | inline T value() const exprtk_override 18098 | { 18099 | return Operation::process(v0_,v1_); 18100 | } 18101 | 18102 | inline typename expression_node<T>::node_type type() const exprtk_override 18103 | { 18104 | return Operation::type(); 18105 | } 18106 | 18107 | inline operator_type operation() const exprtk_override 18108 | { 18109 | return Operation::operation(); 18110 | } 18111 | 18112 | inline const T& v0() const exprtk_override 18113 | { 18114 | return v0_; 18115 | } 18116 | 18117 | inline const T& v1() const exprtk_override 18118 | { 18119 | return v1_; 18120 | } 18121 | 18122 | protected: 18123 | 18124 | const T& v0_; 18125 | const T& v1_; 18126 | 18127 | private: 18128 | 18129 | vov_node(const vov_node<T,Operation>&) exprtk_delete; 18130 | vov_node<T,Operation>& operator=(const vov_node<T,Operation>&) exprtk_delete; 18131 | }; 18132 | 18133 | template <typename T, typename Operation> 18134 | class cov_node exprtk_final : public cov_base_node<T> 18135 | { 18136 | public: 18137 | 18138 | typedef expression_node<T>* expression_ptr; 18139 | typedef Operation operation_t; 18140 | 18141 | // constant op variable node 18142 | explicit cov_node(const T& const_var, const T& var) 18143 | : c_(const_var) 18144 | , v_(var) 18145 | {} 18146 | 18147 | inline T value() const exprtk_override 18148 | { 18149 | return Operation::process(c_,v_); 18150 | } 18151 | 18152 | inline typename expression_node<T>::node_type type() const exprtk_override 18153 | { 18154 | return Operation::type(); 18155 | } 18156 | 18157 | inline operator_type operation() const exprtk_override 18158 | { 18159 | return Operation::operation(); 18160 | } 18161 | 18162 | inline const T c() const exprtk_override 18163 | { 18164 | return c_; 18165 | } 18166 | 18167 | inline const T& v() const exprtk_override 18168 | { 18169 | return v_; 18170 | } 18171 | 18172 | protected: 18173 | 18174 | const T c_; 18175 | const T& v_; 18176 | 18177 | private: 18178 | 18179 | cov_node(const cov_node<T,Operation>&) exprtk_delete; 18180 | cov_node<T,Operation>& operator=(const cov_node<T,Operation>&) exprtk_delete; 18181 | }; 18182 | 18183 | template <typename T, typename Operation> 18184 | class voc_node exprtk_final : public voc_base_node<T> 18185 | { 18186 | public: 18187 | 18188 | typedef expression_node<T>* expression_ptr; 18189 | typedef Operation operation_t; 18190 | 18191 | // variable op constant node 18192 | explicit voc_node(const T& var, const T& const_var) 18193 | : v_(var) 18194 | , c_(const_var) 18195 | {} 18196 | 18197 | inline T value() const exprtk_override 18198 | { 18199 | return Operation::process(v_,c_); 18200 | } 18201 | 18202 | inline operator_type operation() const exprtk_override 18203 | { 18204 | return Operation::operation(); 18205 | } 18206 | 18207 | inline const T c() const exprtk_override 18208 | { 18209 | return c_; 18210 | } 18211 | 18212 | inline const T& v() const exprtk_override 18213 | { 18214 | return v_; 18215 | } 18216 | 18217 | protected: 18218 | 18219 | const T& v_; 18220 | const T c_; 18221 | 18222 | private: 18223 | 18224 | voc_node(const voc_node<T,Operation>&) exprtk_delete; 18225 | voc_node<T,Operation>& operator=(const voc_node<T,Operation>&) exprtk_delete; 18226 | }; 18227 | 18228 | template <typename T, typename Operation> 18229 | class vob_node exprtk_final : public vob_base_node<T> 18230 | { 18231 | public: 18232 | 18233 | typedef expression_node<T>* expression_ptr; 18234 | typedef std::pair<expression_ptr,bool> branch_t; 18235 | typedef Operation operation_t; 18236 | 18237 | // variable op binary node 18238 | explicit vob_node(const T& var, const expression_ptr branch) 18239 | : v_(var) 18240 | { 18241 | construct_branch_pair(branch_, branch); 18242 | assert(valid()); 18243 | } 18244 | 18245 | inline T value() const exprtk_override 18246 | { 18247 | return Operation::process(v_,branch_.first->value()); 18248 | } 18249 | 18250 | inline const T& v() const exprtk_override 18251 | { 18252 | return v_; 18253 | } 18254 | 18255 | inline bool valid() const exprtk_override 18256 | { 18257 | return branch_.first && branch_.first->valid(); 18258 | } 18259 | 18260 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 18261 | { 18262 | return branch_.first; 18263 | } 18264 | 18265 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 18266 | { 18267 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 18268 | } 18269 | 18270 | std::size_t node_depth() const exprtk_override 18271 | { 18272 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 18273 | } 18274 | 18275 | private: 18276 | 18277 | vob_node(const vob_node<T,Operation>&) exprtk_delete; 18278 | vob_node<T,Operation>& operator=(const vob_node<T,Operation>&) exprtk_delete; 18279 | 18280 | const T& v_; 18281 | branch_t branch_; 18282 | }; 18283 | 18284 | template <typename T, typename Operation> 18285 | class bov_node exprtk_final : public bov_base_node<T> 18286 | { 18287 | public: 18288 | 18289 | typedef expression_node<T>* expression_ptr; 18290 | typedef std::pair<expression_ptr,bool> branch_t; 18291 | typedef Operation operation_t; 18292 | 18293 | // binary node op variable node 18294 | explicit bov_node(const expression_ptr branch, const T& var) 18295 | : v_(var) 18296 | { 18297 | construct_branch_pair(branch_, branch); 18298 | assert(valid()); 18299 | } 18300 | 18301 | inline T value() const exprtk_override 18302 | { 18303 | return Operation::process(branch_.first->value(),v_); 18304 | } 18305 | 18306 | inline const T& v() const exprtk_override 18307 | { 18308 | return v_; 18309 | } 18310 | 18311 | inline bool valid() const exprtk_override 18312 | { 18313 | return branch_.first && branch_.first->valid(); 18314 | } 18315 | 18316 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 18317 | { 18318 | return branch_.first; 18319 | } 18320 | 18321 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 18322 | { 18323 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 18324 | } 18325 | 18326 | std::size_t node_depth() const exprtk_override 18327 | { 18328 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 18329 | } 18330 | 18331 | private: 18332 | 18333 | bov_node(const bov_node<T,Operation>&) exprtk_delete; 18334 | bov_node<T,Operation>& operator=(const bov_node<T,Operation>&) exprtk_delete; 18335 | 18336 | const T& v_; 18337 | branch_t branch_; 18338 | }; 18339 | 18340 | template <typename T, typename Operation> 18341 | class cob_node exprtk_final : public cob_base_node<T> 18342 | { 18343 | public: 18344 | 18345 | typedef expression_node<T>* expression_ptr; 18346 | typedef std::pair<expression_ptr,bool> branch_t; 18347 | typedef Operation operation_t; 18348 | 18349 | // constant op variable node 18350 | explicit cob_node(const T const_var, const expression_ptr branch) 18351 | : c_(const_var) 18352 | { 18353 | construct_branch_pair(branch_, branch); 18354 | assert(valid()); 18355 | } 18356 | 18357 | inline T value() const exprtk_override 18358 | { 18359 | return Operation::process(c_,branch_.first->value()); 18360 | } 18361 | 18362 | inline operator_type operation() const exprtk_override 18363 | { 18364 | return Operation::operation(); 18365 | } 18366 | 18367 | inline const T c() const exprtk_override 18368 | { 18369 | return c_; 18370 | } 18371 | 18372 | inline void set_c(const T new_c) exprtk_override 18373 | { 18374 | (*const_cast<T*>(&c_)) = new_c; 18375 | } 18376 | 18377 | inline bool valid() const exprtk_override 18378 | { 18379 | return branch_.first && branch_.first->valid(); 18380 | } 18381 | 18382 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 18383 | { 18384 | return branch_.first; 18385 | } 18386 | 18387 | inline expression_node<T>* move_branch(const std::size_t&) exprtk_override 18388 | { 18389 | branch_.second = false; 18390 | return branch_.first; 18391 | } 18392 | 18393 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 18394 | { 18395 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 18396 | } 18397 | 18398 | std::size_t node_depth() const exprtk_override 18399 | { 18400 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 18401 | } 18402 | 18403 | private: 18404 | 18405 | cob_node(const cob_node<T,Operation>&) exprtk_delete; 18406 | cob_node<T,Operation>& operator=(const cob_node<T,Operation>&) exprtk_delete; 18407 | 18408 | const T c_; 18409 | branch_t branch_; 18410 | }; 18411 | 18412 | template <typename T, typename Operation> 18413 | class boc_node exprtk_final : public boc_base_node<T> 18414 | { 18415 | public: 18416 | 18417 | typedef expression_node<T>* expression_ptr; 18418 | typedef std::pair<expression_ptr,bool> branch_t; 18419 | typedef Operation operation_t; 18420 | 18421 | // binary node op constant node 18422 | explicit boc_node(const expression_ptr branch, const T const_var) 18423 | : c_(const_var) 18424 | { 18425 | construct_branch_pair(branch_, branch); 18426 | assert(valid()); 18427 | } 18428 | 18429 | inline T value() const exprtk_override 18430 | { 18431 | return Operation::process(branch_.first->value(),c_); 18432 | } 18433 | 18434 | inline operator_type operation() const exprtk_override 18435 | { 18436 | return Operation::operation(); 18437 | } 18438 | 18439 | inline const T c() const exprtk_override 18440 | { 18441 | return c_; 18442 | } 18443 | 18444 | inline void set_c(const T new_c) exprtk_override 18445 | { 18446 | (*const_cast<T*>(&c_)) = new_c; 18447 | } 18448 | 18449 | inline bool valid() const exprtk_override 18450 | { 18451 | return branch_.first && branch_.first->valid(); 18452 | } 18453 | 18454 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 18455 | { 18456 | return branch_.first; 18457 | } 18458 | 18459 | inline expression_node<T>* move_branch(const std::size_t&) exprtk_override 18460 | { 18461 | branch_.second = false; 18462 | return branch_.first; 18463 | } 18464 | 18465 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 18466 | { 18467 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 18468 | } 18469 | 18470 | std::size_t node_depth() const exprtk_override 18471 | { 18472 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 18473 | } 18474 | 18475 | private: 18476 | 18477 | boc_node(const boc_node<T,Operation>&) exprtk_delete; 18478 | boc_node<T,Operation>& operator=(const boc_node<T,Operation>&) exprtk_delete; 18479 | 18480 | const T c_; 18481 | branch_t branch_; 18482 | }; 18483 | 18484 | #ifndef exprtk_disable_string_capabilities 18485 | template <typename T, typename SType0, typename SType1, typename Operation> 18486 | class sos_node exprtk_final : public sos_base_node<T> 18487 | { 18488 | public: 18489 | 18490 | typedef expression_node<T>* expression_ptr; 18491 | typedef Operation operation_t; 18492 | 18493 | // string op string node 18494 | explicit sos_node(SType0 p0, SType1 p1) 18495 | : s0_(p0) 18496 | , s1_(p1) 18497 | {} 18498 | 18499 | inline T value() const exprtk_override 18500 | { 18501 | return Operation::process(s0_,s1_); 18502 | } 18503 | 18504 | inline typename expression_node<T>::node_type type() const exprtk_override 18505 | { 18506 | return Operation::type(); 18507 | } 18508 | 18509 | inline operator_type operation() const exprtk_override 18510 | { 18511 | return Operation::operation(); 18512 | } 18513 | 18514 | inline std::string& s0() 18515 | { 18516 | return s0_; 18517 | } 18518 | 18519 | inline std::string& s1() 18520 | { 18521 | return s1_; 18522 | } 18523 | 18524 | protected: 18525 | 18526 | SType0 s0_; 18527 | SType1 s1_; 18528 | 18529 | private: 18530 | 18531 | sos_node(const sos_node<T,SType0,SType1,Operation>&) exprtk_delete; 18532 | sos_node<T,SType0,SType1,Operation>& operator=(const sos_node<T,SType0,SType1,Operation>&) exprtk_delete; 18533 | }; 18534 | 18535 | template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation> 18536 | class str_xrox_node exprtk_final : public sos_base_node<T> 18537 | { 18538 | public: 18539 | 18540 | typedef expression_node<T>* expression_ptr; 18541 | typedef Operation operation_t; 18542 | typedef str_xrox_node<T,SType0,SType1,RangePack,Operation> node_type; 18543 | 18544 | // string-range op string node 18545 | explicit str_xrox_node(SType0 p0, SType1 p1, RangePack rp0) 18546 | : s0_ (p0 ) 18547 | , s1_ (p1 ) 18548 | , rp0_(rp0) 18549 | {} 18550 | 18551 | ~str_xrox_node() exprtk_override 18552 | { 18553 | rp0_.free(); 18554 | } 18555 | 18556 | inline T value() const exprtk_override 18557 | { 18558 | std::size_t r0 = 0; 18559 | std::size_t r1 = 0; 18560 | 18561 | if (rp0_(r0, r1, s0_.size())) 18562 | return Operation::process(s0_.substr(r0, (r1 - r0) + 1), s1_); 18563 | else 18564 | return T(0); 18565 | } 18566 | 18567 | inline typename expression_node<T>::node_type type() const exprtk_override 18568 | { 18569 | return Operation::type(); 18570 | } 18571 | 18572 | inline operator_type operation() const exprtk_override 18573 | { 18574 | return Operation::operation(); 18575 | } 18576 | 18577 | inline std::string& s0() 18578 | { 18579 | return s0_; 18580 | } 18581 | 18582 | inline std::string& s1() 18583 | { 18584 | return s1_; 18585 | } 18586 | 18587 | protected: 18588 | 18589 | SType0 s0_; 18590 | SType1 s1_; 18591 | RangePack rp0_; 18592 | 18593 | private: 18594 | 18595 | str_xrox_node(const node_type&) exprtk_delete; 18596 | node_type& operator=(const node_type&) exprtk_delete; 18597 | }; 18598 | 18599 | template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation> 18600 | class str_xoxr_node exprtk_final : public sos_base_node<T> 18601 | { 18602 | public: 18603 | 18604 | typedef expression_node<T>* expression_ptr; 18605 | typedef Operation operation_t; 18606 | typedef str_xoxr_node<T,SType0,SType1,RangePack,Operation> node_type; 18607 | 18608 | // string op string range node 18609 | explicit str_xoxr_node(SType0 p0, SType1 p1, RangePack rp1) 18610 | : s0_ (p0 ) 18611 | , s1_ (p1 ) 18612 | , rp1_(rp1) 18613 | {} 18614 | 18615 | ~str_xoxr_node() 18616 | { 18617 | rp1_.free(); 18618 | } 18619 | 18620 | inline T value() const exprtk_override 18621 | { 18622 | std::size_t r0 = 0; 18623 | std::size_t r1 = 0; 18624 | 18625 | if (rp1_(r0, r1, s1_.size())) 18626 | { 18627 | return Operation::process 18628 | ( 18629 | s0_, 18630 | s1_.substr(r0, (r1 - r0) + 1) 18631 | ); 18632 | } 18633 | else 18634 | return T(0); 18635 | } 18636 | 18637 | inline typename expression_node<T>::node_type type() const exprtk_override 18638 | { 18639 | return Operation::type(); 18640 | } 18641 | 18642 | inline operator_type operation() const exprtk_override 18643 | { 18644 | return Operation::operation(); 18645 | } 18646 | 18647 | inline std::string& s0() 18648 | { 18649 | return s0_; 18650 | } 18651 | 18652 | inline std::string& s1() 18653 | { 18654 | return s1_; 18655 | } 18656 | 18657 | protected: 18658 | 18659 | SType0 s0_; 18660 | SType1 s1_; 18661 | RangePack rp1_; 18662 | 18663 | private: 18664 | 18665 | str_xoxr_node(const node_type&) exprtk_delete; 18666 | node_type& operator=(const node_type&) exprtk_delete; 18667 | }; 18668 | 18669 | template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation> 18670 | class str_xroxr_node exprtk_final : public sos_base_node<T> 18671 | { 18672 | public: 18673 | 18674 | typedef expression_node<T>* expression_ptr; 18675 | typedef Operation operation_t; 18676 | typedef str_xroxr_node<T,SType0,SType1,RangePack,Operation> node_type; 18677 | 18678 | // string-range op string-range node 18679 | explicit str_xroxr_node(SType0 p0, SType1 p1, RangePack rp0, RangePack rp1) 18680 | : s0_ (p0 ) 18681 | , s1_ (p1 ) 18682 | , rp0_(rp0) 18683 | , rp1_(rp1) 18684 | {} 18685 | 18686 | ~str_xroxr_node() exprtk_override 18687 | { 18688 | rp0_.free(); 18689 | rp1_.free(); 18690 | } 18691 | 18692 | inline T value() const exprtk_override 18693 | { 18694 | std::size_t r0_0 = 0; 18695 | std::size_t r0_1 = 0; 18696 | std::size_t r1_0 = 0; 18697 | std::size_t r1_1 = 0; 18698 | 18699 | if ( 18700 | rp0_(r0_0, r1_0, s0_.size()) && 18701 | rp1_(r0_1, r1_1, s1_.size()) 18702 | ) 18703 | { 18704 | return Operation::process 18705 | ( 18706 | s0_.substr(r0_0, (r1_0 - r0_0) + 1), 18707 | s1_.substr(r0_1, (r1_1 - r0_1) + 1) 18708 | ); 18709 | } 18710 | else 18711 | return T(0); 18712 | } 18713 | 18714 | inline typename expression_node<T>::node_type type() const exprtk_override 18715 | { 18716 | return Operation::type(); 18717 | } 18718 | 18719 | inline operator_type operation() const exprtk_override 18720 | { 18721 | return Operation::operation(); 18722 | } 18723 | 18724 | inline std::string& s0() 18725 | { 18726 | return s0_; 18727 | } 18728 | 18729 | inline std::string& s1() 18730 | { 18731 | return s1_; 18732 | } 18733 | 18734 | protected: 18735 | 18736 | SType0 s0_; 18737 | SType1 s1_; 18738 | RangePack rp0_; 18739 | RangePack rp1_; 18740 | 18741 | private: 18742 | 18743 | str_xroxr_node(const node_type&) exprtk_delete; 18744 | node_type& operator=(const node_type&) exprtk_delete; 18745 | }; 18746 | 18747 | template <typename T, typename Operation> 18748 | class str_sogens_node exprtk_final : public binary_node<T> 18749 | { 18750 | public: 18751 | 18752 | typedef expression_node <T>* expression_ptr; 18753 | typedef string_base_node<T>* str_base_ptr; 18754 | typedef range_pack <T> range_t; 18755 | typedef range_t* range_ptr; 18756 | typedef range_interface <T> irange_t; 18757 | typedef irange_t* irange_ptr; 18758 | 18759 | using binary_node<T>::branch; 18760 | 18761 | str_sogens_node(const operator_type& opr, 18762 | expression_ptr branch0, 18763 | expression_ptr branch1) 18764 | : binary_node<T>(opr, branch0, branch1) 18765 | , str0_base_ptr_ (0) 18766 | , str1_base_ptr_ (0) 18767 | , str0_range_ptr_(0) 18768 | , str1_range_ptr_(0) 18769 | , initialised_ (false) 18770 | { 18771 | if (is_generally_string_node(branch(0))) 18772 | { 18773 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0)); 18774 | 18775 | if (0 == str0_base_ptr_) 18776 | return; 18777 | 18778 | irange_ptr range = dynamic_cast<irange_ptr>(branch(0)); 18779 | 18780 | if (0 == range) 18781 | return; 18782 | 18783 | str0_range_ptr_ = &(range->range_ref()); 18784 | } 18785 | 18786 | if (is_generally_string_node(branch(1))) 18787 | { 18788 | str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1)); 18789 | 18790 | if (0 == str1_base_ptr_) 18791 | return; 18792 | 18793 | irange_ptr range = dynamic_cast<irange_ptr>(branch(1)); 18794 | 18795 | if (0 == range) 18796 | return; 18797 | 18798 | str1_range_ptr_ = &(range->range_ref()); 18799 | } 18800 | 18801 | initialised_ = 18802 | str0_base_ptr_ && 18803 | str1_base_ptr_ && 18804 | str0_range_ptr_ && 18805 | str1_range_ptr_; 18806 | 18807 | assert(valid()); 18808 | } 18809 | 18810 | inline T value() const exprtk_override 18811 | { 18812 | branch(0)->value(); 18813 | branch(1)->value(); 18814 | 18815 | std::size_t str0_r0 = 0; 18816 | std::size_t str0_r1 = 0; 18817 | 18818 | std::size_t str1_r0 = 0; 18819 | std::size_t str1_r1 = 0; 18820 | 18821 | const range_t& range0 = (*str0_range_ptr_); 18822 | const range_t& range1 = (*str1_range_ptr_); 18823 | 18824 | if ( 18825 | range0(str0_r0, str0_r1, str0_base_ptr_->size()) && 18826 | range1(str1_r0, str1_r1, str1_base_ptr_->size()) 18827 | ) 18828 | { 18829 | return Operation::process 18830 | ( 18831 | str0_base_ptr_->str().substr(str0_r0,(str0_r1 - str0_r0)), 18832 | str1_base_ptr_->str().substr(str1_r0,(str1_r1 - str1_r0)) 18833 | ); 18834 | } 18835 | 18836 | return std::numeric_limits<T>::quiet_NaN(); 18837 | } 18838 | 18839 | inline typename expression_node<T>::node_type type() const exprtk_override 18840 | { 18841 | return Operation::type(); 18842 | } 18843 | 18844 | inline bool valid() const exprtk_override 18845 | { 18846 | return initialised_; 18847 | } 18848 | 18849 | private: 18850 | 18851 | str_sogens_node(const str_sogens_node<T,Operation>&) exprtk_delete; 18852 | str_sogens_node<T,Operation>& operator=(const str_sogens_node<T,Operation>&) exprtk_delete; 18853 | 18854 | str_base_ptr str0_base_ptr_; 18855 | str_base_ptr str1_base_ptr_; 18856 | range_ptr str0_range_ptr_; 18857 | range_ptr str1_range_ptr_; 18858 | bool initialised_; 18859 | }; 18860 | 18861 | template <typename T, typename SType0, typename SType1, typename SType2, typename Operation> 18862 | class sosos_node exprtk_final : public sosos_base_node<T> 18863 | { 18864 | public: 18865 | 18866 | typedef expression_node<T>* expression_ptr; 18867 | typedef Operation operation_t; 18868 | typedef sosos_node<T, SType0, SType1, SType2, Operation> node_type; 18869 | 18870 | // string op string op string node 18871 | explicit sosos_node(SType0 p0, SType1 p1, SType2 p2) 18872 | : s0_(p0) 18873 | , s1_(p1) 18874 | , s2_(p2) 18875 | {} 18876 | 18877 | inline T value() const exprtk_override 18878 | { 18879 | return Operation::process(s0_, s1_, s2_); 18880 | } 18881 | 18882 | inline typename expression_node<T>::node_type type() const exprtk_override 18883 | { 18884 | return Operation::type(); 18885 | } 18886 | 18887 | inline operator_type operation() const exprtk_override 18888 | { 18889 | return Operation::operation(); 18890 | } 18891 | 18892 | inline std::string& s0() 18893 | { 18894 | return s0_; 18895 | } 18896 | 18897 | inline std::string& s1() 18898 | { 18899 | return s1_; 18900 | } 18901 | 18902 | inline std::string& s2() 18903 | { 18904 | return s2_; 18905 | } 18906 | 18907 | protected: 18908 | 18909 | SType0 s0_; 18910 | SType1 s1_; 18911 | SType2 s2_; 18912 | 18913 | private: 18914 | 18915 | sosos_node(const node_type&) exprtk_delete; 18916 | node_type& operator=(const node_type&) exprtk_delete; 18917 | }; 18918 | #endif 18919 | 18920 | template <typename T, typename PowOp> 18921 | class ipow_node exprtk_final: public expression_node<T> 18922 | { 18923 | public: 18924 | 18925 | typedef expression_node<T>* expression_ptr; 18926 | typedef PowOp operation_t; 18927 | 18928 | explicit ipow_node(const T& v) 18929 | : v_(v) 18930 | {} 18931 | 18932 | inline T value() const exprtk_override 18933 | { 18934 | return PowOp::result(v_); 18935 | } 18936 | 18937 | inline typename expression_node<T>::node_type type() const exprtk_override 18938 | { 18939 | return expression_node<T>::e_ipow; 18940 | } 18941 | 18942 | private: 18943 | 18944 | ipow_node(const ipow_node<T,PowOp>&) exprtk_delete; 18945 | ipow_node<T,PowOp>& operator=(const ipow_node<T,PowOp>&) exprtk_delete; 18946 | 18947 | const T& v_; 18948 | }; 18949 | 18950 | template <typename T, typename PowOp> 18951 | class bipow_node exprtk_final : public expression_node<T> 18952 | { 18953 | public: 18954 | 18955 | typedef expression_node<T>* expression_ptr; 18956 | typedef std::pair<expression_ptr, bool> branch_t; 18957 | typedef PowOp operation_t; 18958 | 18959 | explicit bipow_node(expression_ptr branch) 18960 | { 18961 | construct_branch_pair(branch_, branch); 18962 | assert(valid()); 18963 | } 18964 | 18965 | inline T value() const exprtk_override 18966 | { 18967 | return PowOp::result(branch_.first->value()); 18968 | } 18969 | 18970 | inline typename expression_node<T>::node_type type() const exprtk_override 18971 | { 18972 | return expression_node<T>::e_ipow; 18973 | } 18974 | 18975 | inline bool valid() const exprtk_override 18976 | { 18977 | return branch_.first && branch_.first->valid(); 18978 | } 18979 | 18980 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 18981 | { 18982 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 18983 | } 18984 | 18985 | std::size_t node_depth() const exprtk_override 18986 | { 18987 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 18988 | } 18989 | 18990 | private: 18991 | 18992 | bipow_node(const bipow_node<T,PowOp>&) exprtk_delete; 18993 | bipow_node<T,PowOp>& operator=(const bipow_node<T,PowOp>&) exprtk_delete; 18994 | 18995 | branch_t branch_; 18996 | }; 18997 | 18998 | template <typename T, typename PowOp> 18999 | class ipowinv_node exprtk_final : public expression_node<T> 19000 | { 19001 | public: 19002 | 19003 | typedef expression_node<T>* expression_ptr; 19004 | typedef PowOp operation_t; 19005 | 19006 | explicit ipowinv_node(const T& v) 19007 | : v_(v) 19008 | {} 19009 | 19010 | inline T value() const exprtk_override 19011 | { 19012 | return (T(1) / PowOp::result(v_)); 19013 | } 19014 | 19015 | inline typename expression_node<T>::node_type type() const exprtk_override 19016 | { 19017 | return expression_node<T>::e_ipowinv; 19018 | } 19019 | 19020 | private: 19021 | 19022 | ipowinv_node(const ipowinv_node<T,PowOp>&) exprtk_delete; 19023 | ipowinv_node<T,PowOp>& operator=(const ipowinv_node<T,PowOp>&) exprtk_delete; 19024 | 19025 | const T& v_; 19026 | }; 19027 | 19028 | template <typename T, typename PowOp> 19029 | class bipowinv_node exprtk_final : public expression_node<T> 19030 | { 19031 | public: 19032 | 19033 | typedef expression_node<T>* expression_ptr; 19034 | typedef std::pair<expression_ptr, bool> branch_t; 19035 | typedef PowOp operation_t; 19036 | 19037 | explicit bipowinv_node(expression_ptr branch) 19038 | { 19039 | construct_branch_pair(branch_, branch); 19040 | assert(valid()); 19041 | } 19042 | 19043 | inline T value() const exprtk_override 19044 | { 19045 | return (T(1) / PowOp::result(branch_.first->value())); 19046 | } 19047 | 19048 | inline typename expression_node<T>::node_type type() const exprtk_override 19049 | { 19050 | return expression_node<T>::e_ipowinv; 19051 | } 19052 | 19053 | inline bool valid() const exprtk_override 19054 | { 19055 | return branch_.first && branch_.first->valid(); 19056 | } 19057 | 19058 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 19059 | { 19060 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 19061 | } 19062 | 19063 | std::size_t node_depth() const exprtk_override 19064 | { 19065 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 19066 | } 19067 | 19068 | private: 19069 | 19070 | bipowinv_node(const bipowinv_node<T,PowOp>&) exprtk_delete; 19071 | bipowinv_node<T,PowOp>& operator=(const bipowinv_node<T,PowOp>&) exprtk_delete; 19072 | 19073 | branch_t branch_; 19074 | }; 19075 | 19076 | template <typename T> 19077 | inline bool is_vov_node(const expression_node<T>* node) 19078 | { 19079 | return (0 != dynamic_cast<const vov_base_node<T>*>(node)); 19080 | } 19081 | 19082 | template <typename T> 19083 | inline bool is_cov_node(const expression_node<T>* node) 19084 | { 19085 | return (0 != dynamic_cast<const cov_base_node<T>*>(node)); 19086 | } 19087 | 19088 | template <typename T> 19089 | inline bool is_voc_node(const expression_node<T>* node) 19090 | { 19091 | return (0 != dynamic_cast<const voc_base_node<T>*>(node)); 19092 | } 19093 | 19094 | template <typename T> 19095 | inline bool is_cob_node(const expression_node<T>* node) 19096 | { 19097 | return (0 != dynamic_cast<const cob_base_node<T>*>(node)); 19098 | } 19099 | 19100 | template <typename T> 19101 | inline bool is_boc_node(const expression_node<T>* node) 19102 | { 19103 | return (0 != dynamic_cast<const boc_base_node<T>*>(node)); 19104 | } 19105 | 19106 | template <typename T> 19107 | inline bool is_t0ot1ot2_node(const expression_node<T>* node) 19108 | { 19109 | return (0 != dynamic_cast<const T0oT1oT2_base_node<T>*>(node)); 19110 | } 19111 | 19112 | template <typename T> 19113 | inline bool is_t0ot1ot2ot3_node(const expression_node<T>* node) 19114 | { 19115 | return (0 != dynamic_cast<const T0oT1oT2oT3_base_node<T>*>(node)); 19116 | } 19117 | 19118 | template <typename T> 19119 | inline bool is_uv_node(const expression_node<T>* node) 19120 | { 19121 | return (0 != dynamic_cast<const uv_base_node<T>*>(node)); 19122 | } 19123 | 19124 | template <typename T> 19125 | inline bool is_string_node(const expression_node<T>* node) 19126 | { 19127 | return node && (expression_node<T>::e_stringvar == node->type()); 19128 | } 19129 | 19130 | template <typename T> 19131 | inline bool is_string_range_node(const expression_node<T>* node) 19132 | { 19133 | return node && (expression_node<T>::e_stringvarrng == node->type()); 19134 | } 19135 | 19136 | template <typename T> 19137 | inline bool is_const_string_node(const expression_node<T>* node) 19138 | { 19139 | return node && (expression_node<T>::e_stringconst == node->type()); 19140 | } 19141 | 19142 | template <typename T> 19143 | inline bool is_const_string_range_node(const expression_node<T>* node) 19144 | { 19145 | return node && (expression_node<T>::e_cstringvarrng == node->type()); 19146 | } 19147 | 19148 | template <typename T> 19149 | inline bool is_string_assignment_node(const expression_node<T>* node) 19150 | { 19151 | return node && (expression_node<T>::e_strass == node->type()); 19152 | } 19153 | 19154 | template <typename T> 19155 | inline bool is_string_concat_node(const expression_node<T>* node) 19156 | { 19157 | return node && (expression_node<T>::e_strconcat == node->type()); 19158 | } 19159 | 19160 | template <typename T> 19161 | inline bool is_string_function_node(const expression_node<T>* node) 19162 | { 19163 | return node && (expression_node<T>::e_strfunction == node->type()); 19164 | } 19165 | 19166 | template <typename T> 19167 | inline bool is_string_condition_node(const expression_node<T>* node) 19168 | { 19169 | return node && (expression_node<T>::e_strcondition == node->type()); 19170 | } 19171 | 19172 | template <typename T> 19173 | inline bool is_string_ccondition_node(const expression_node<T>* node) 19174 | { 19175 | return node && (expression_node<T>::e_strccondition == node->type()); 19176 | } 19177 | 19178 | template <typename T> 19179 | inline bool is_string_vararg_node(const expression_node<T>* node) 19180 | { 19181 | return node && (expression_node<T>::e_stringvararg == node->type()); 19182 | } 19183 | 19184 | template <typename T> 19185 | inline bool is_genricstring_range_node(const expression_node<T>* node) 19186 | { 19187 | return node && (expression_node<T>::e_strgenrange == node->type()); 19188 | } 19189 | 19190 | template <typename T> 19191 | inline bool is_generally_string_node(const expression_node<T>* node) 19192 | { 19193 | if (node) 19194 | { 19195 | switch (node->type()) 19196 | { 19197 | case expression_node<T>::e_stringvar : 19198 | case expression_node<T>::e_stringconst : 19199 | case expression_node<T>::e_stringvarrng : 19200 | case expression_node<T>::e_cstringvarrng : 19201 | case expression_node<T>::e_strgenrange : 19202 | case expression_node<T>::e_strass : 19203 | case expression_node<T>::e_strconcat : 19204 | case expression_node<T>::e_strfunction : 19205 | case expression_node<T>::e_strcondition : 19206 | case expression_node<T>::e_strccondition : 19207 | case expression_node<T>::e_stringvararg : return true; 19208 | default : return false; 19209 | } 19210 | } 19211 | 19212 | return false; 19213 | } 19214 | 19215 | template <typename T> 19216 | inline bool is_loop_node(const expression_node<T>* node) 19217 | { 19218 | if (node) 19219 | { 19220 | switch (node->type()) 19221 | { 19222 | case expression_node<T>::e_for : 19223 | case expression_node<T>::e_repeat : 19224 | case expression_node<T>::e_while : return true; 19225 | default : return false; 19226 | } 19227 | } 19228 | 19229 | return false; 19230 | } 19231 | 19232 | template <typename T> 19233 | inline bool is_block_node(const expression_node<T>* node) 19234 | { 19235 | if (node) 19236 | { 19237 | if (is_loop_node(node)) 19238 | { 19239 | return true; 19240 | } 19241 | 19242 | switch (node->type()) 19243 | { 19244 | case expression_node<T>::e_conditional : 19245 | case expression_node<T>::e_mswitch : 19246 | case expression_node<T>::e_switch : 19247 | case expression_node<T>::e_vararg : return true; 19248 | default : return false; 19249 | } 19250 | } 19251 | 19252 | return false; 19253 | } 19254 | 19255 | class node_allocator 19256 | { 19257 | public: 19258 | 19259 | template <typename ResultNode, typename OpType, typename ExprNode> 19260 | inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[1]) 19261 | { 19262 | expression_node<typename ResultNode::value_type>* result = 19263 | allocate<ResultNode>(operation, branch[0]); 19264 | result->node_depth(); 19265 | return result; 19266 | } 19267 | 19268 | template <typename ResultNode, typename OpType, typename ExprNode> 19269 | inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[2]) 19270 | { 19271 | expression_node<typename ResultNode::value_type>* result = 19272 | allocate<ResultNode>(operation, branch[0], branch[1]); 19273 | result->node_depth(); 19274 | return result; 19275 | } 19276 | 19277 | template <typename ResultNode, typename OpType, typename ExprNode> 19278 | inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[3]) 19279 | { 19280 | expression_node<typename ResultNode::value_type>* result = 19281 | allocate<ResultNode>(operation, branch[0], branch[1], branch[2]); 19282 | result->node_depth(); 19283 | return result; 19284 | } 19285 | 19286 | template <typename ResultNode, typename OpType, typename ExprNode> 19287 | inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[4]) 19288 | { 19289 | expression_node<typename ResultNode::value_type>* result = 19290 | allocate<ResultNode>(operation, branch[0], branch[1], branch[2], branch[3]); 19291 | result->node_depth(); 19292 | return result; 19293 | } 19294 | 19295 | template <typename ResultNode, typename OpType, typename ExprNode> 19296 | inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[5]) 19297 | { 19298 | expression_node<typename ResultNode::value_type>* result = 19299 | allocate<ResultNode>(operation, branch[0],branch[1], branch[2], branch[3], branch[4]); 19300 | result->node_depth(); 19301 | return result; 19302 | } 19303 | 19304 | template <typename ResultNode, typename OpType, typename ExprNode> 19305 | inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[6]) 19306 | { 19307 | expression_node<typename ResultNode::value_type>* result = 19308 | allocate<ResultNode>(operation, branch[0], branch[1], branch[2], branch[3], branch[4], branch[5]); 19309 | result->node_depth(); 19310 | return result; 19311 | } 19312 | 19313 | template <typename node_type> 19314 | inline expression_node<typename node_type::value_type>* allocate() const 19315 | { 19316 | return (new node_type()); 19317 | } 19318 | 19319 | template <typename node_type, 19320 | typename Type, 19321 | typename Allocator, 19322 | template <typename, typename> class Sequence> 19323 | inline expression_node<typename node_type::value_type>* allocate(const Sequence<Type,Allocator>& seq) const 19324 | { 19325 | expression_node<typename node_type::value_type>* 19326 | result = (new node_type(seq)); 19327 | result->node_depth(); 19328 | return result; 19329 | } 19330 | 19331 | template <typename node_type, typename T1> 19332 | inline expression_node<typename node_type::value_type>* allocate(T1& t1) const 19333 | { 19334 | expression_node<typename node_type::value_type>* 19335 | result = (new node_type(t1)); 19336 | result->node_depth(); 19337 | return result; 19338 | } 19339 | 19340 | template <typename node_type, typename T1> 19341 | inline expression_node<typename node_type::value_type>* allocate_c(const T1& t1) const 19342 | { 19343 | expression_node<typename node_type::value_type>* 19344 | result = (new node_type(t1)); 19345 | result->node_depth(); 19346 | return result; 19347 | } 19348 | 19349 | template <typename node_type, 19350 | typename T1, typename T2> 19351 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2) const 19352 | { 19353 | expression_node<typename node_type::value_type>* 19354 | result = (new node_type(t1, t2)); 19355 | result->node_depth(); 19356 | return result; 19357 | } 19358 | 19359 | template <typename node_type, 19360 | typename T1, typename T2> 19361 | inline expression_node<typename node_type::value_type>* allocate_cr(const T1& t1, T2& t2) const 19362 | { 19363 | expression_node<typename node_type::value_type>* 19364 | result = (new node_type(t1, t2)); 19365 | result->node_depth(); 19366 | return result; 19367 | } 19368 | 19369 | template <typename node_type, 19370 | typename T1, typename T2> 19371 | inline expression_node<typename node_type::value_type>* allocate_rc(T1& t1, const T2& t2) const 19372 | { 19373 | expression_node<typename node_type::value_type>* 19374 | result = (new node_type(t1, t2)); 19375 | result->node_depth(); 19376 | return result; 19377 | } 19378 | 19379 | template <typename node_type, 19380 | typename T1, typename T2> 19381 | inline expression_node<typename node_type::value_type>* allocate_rr(T1& t1, T2& t2) const 19382 | { 19383 | expression_node<typename node_type::value_type>* 19384 | result = (new node_type(t1, t2)); 19385 | result->node_depth(); 19386 | return result; 19387 | } 19388 | 19389 | template <typename node_type, 19390 | typename T1, typename T2> 19391 | inline expression_node<typename node_type::value_type>* allocate_tt(T1 t1, T2 t2) const 19392 | { 19393 | expression_node<typename node_type::value_type>* 19394 | result = (new node_type(t1, t2)); 19395 | result->node_depth(); 19396 | return result; 19397 | } 19398 | 19399 | template <typename node_type, 19400 | typename T1, typename T2, typename T3> 19401 | inline expression_node<typename node_type::value_type>* allocate_ttt(T1 t1, T2 t2, T3 t3) const 19402 | { 19403 | expression_node<typename node_type::value_type>* 19404 | result = (new node_type(t1, t2, t3)); 19405 | result->node_depth(); 19406 | return result; 19407 | } 19408 | 19409 | template <typename node_type, 19410 | typename T1, typename T2, typename T3, typename T4> 19411 | inline expression_node<typename node_type::value_type>* allocate_tttt(T1 t1, T2 t2, T3 t3, T4 t4) const 19412 | { 19413 | expression_node<typename node_type::value_type>* 19414 | result = (new node_type(t1, t2, t3, t4)); 19415 | result->node_depth(); 19416 | return result; 19417 | } 19418 | 19419 | template <typename node_type, 19420 | typename T1, typename T2, typename T3> 19421 | inline expression_node<typename node_type::value_type>* allocate_rrr(T1& t1, T2& t2, T3& t3) const 19422 | { 19423 | expression_node<typename node_type::value_type>* 19424 | result = (new node_type(t1, t2, t3)); 19425 | result->node_depth(); 19426 | return result; 19427 | } 19428 | 19429 | template <typename node_type, 19430 | typename T1, typename T2, typename T3, typename T4> 19431 | inline expression_node<typename node_type::value_type>* allocate_rrrr(T1& t1, T2& t2, T3& t3, T4& t4) const 19432 | { 19433 | expression_node<typename node_type::value_type>* 19434 | result = (new node_type(t1, t2, t3, t4)); 19435 | result->node_depth(); 19436 | return result; 19437 | } 19438 | 19439 | template <typename node_type, 19440 | typename T1, typename T2, typename T3, typename T4, typename T5> 19441 | inline expression_node<typename node_type::value_type>* allocate_rrrrr(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5) const 19442 | { 19443 | expression_node<typename node_type::value_type>* 19444 | result = (new node_type(t1, t2, t3, t4, t5)); 19445 | result->node_depth(); 19446 | return result; 19447 | } 19448 | 19449 | template <typename node_type, 19450 | typename T1, typename T2, typename T3> 19451 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19452 | const T3& t3) const 19453 | { 19454 | expression_node<typename node_type::value_type>* 19455 | result = (new node_type(t1, t2, t3)); 19456 | result->node_depth(); 19457 | return result; 19458 | } 19459 | 19460 | template <typename node_type, 19461 | typename T1, typename T2, 19462 | typename T3, typename T4> 19463 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19464 | const T3& t3, const T4& t4) const 19465 | { 19466 | expression_node<typename node_type::value_type>* 19467 | result = (new node_type(t1, t2, t3, t4)); 19468 | result->node_depth(); 19469 | return result; 19470 | } 19471 | 19472 | template <typename node_type, 19473 | typename T1, typename T2, 19474 | typename T3, typename T4, typename T5> 19475 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19476 | const T3& t3, const T4& t4, 19477 | const T5& t5) const 19478 | { 19479 | expression_node<typename node_type::value_type>* 19480 | result = (new node_type(t1, t2, t3, t4, t5)); 19481 | result->node_depth(); 19482 | return result; 19483 | } 19484 | 19485 | template <typename node_type, 19486 | typename T1, typename T2, 19487 | typename T3, typename T4, typename T5, typename T6> 19488 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19489 | const T3& t3, const T4& t4, 19490 | const T5& t5, const T6& t6) const 19491 | { 19492 | expression_node<typename node_type::value_type>* 19493 | result = (new node_type(t1, t2, t3, t4, t5, t6)); 19494 | result->node_depth(); 19495 | return result; 19496 | } 19497 | 19498 | template <typename node_type, 19499 | typename T1, typename T2, 19500 | typename T3, typename T4, 19501 | typename T5, typename T6, typename T7> 19502 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19503 | const T3& t3, const T4& t4, 19504 | const T5& t5, const T6& t6, 19505 | const T7& t7) const 19506 | { 19507 | expression_node<typename node_type::value_type>* 19508 | result = (new node_type(t1, t2, t3, t4, t5, t6, t7)); 19509 | result->node_depth(); 19510 | return result; 19511 | } 19512 | 19513 | template <typename node_type, 19514 | typename T1, typename T2, 19515 | typename T3, typename T4, 19516 | typename T5, typename T6, 19517 | typename T7, typename T8> 19518 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19519 | const T3& t3, const T4& t4, 19520 | const T5& t5, const T6& t6, 19521 | const T7& t7, const T8& t8) const 19522 | { 19523 | expression_node<typename node_type::value_type>* 19524 | result = (new node_type(t1, t2, t3, t4, t5, t6, t7, t8)); 19525 | result->node_depth(); 19526 | return result; 19527 | } 19528 | 19529 | template <typename node_type, 19530 | typename T1, typename T2, 19531 | typename T3, typename T4, 19532 | typename T5, typename T6, 19533 | typename T7, typename T8, typename T9> 19534 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19535 | const T3& t3, const T4& t4, 19536 | const T5& t5, const T6& t6, 19537 | const T7& t7, const T8& t8, 19538 | const T9& t9) const 19539 | { 19540 | expression_node<typename node_type::value_type>* 19541 | result = (new node_type(t1, t2, t3, t4, t5, t6, t7, t8, t9)); 19542 | result->node_depth(); 19543 | return result; 19544 | } 19545 | 19546 | template <typename node_type, 19547 | typename T1, typename T2, 19548 | typename T3, typename T4, 19549 | typename T5, typename T6, 19550 | typename T7, typename T8, 19551 | typename T9, typename T10> 19552 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19553 | const T3& t3, const T4& t4, 19554 | const T5& t5, const T6& t6, 19555 | const T7& t7, const T8& t8, 19556 | const T9& t9, const T10& t10) const 19557 | { 19558 | expression_node<typename node_type::value_type>* 19559 | result = (new node_type(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10)); 19560 | result->node_depth(); 19561 | return result; 19562 | } 19563 | 19564 | template <typename node_type, 19565 | typename T1, typename T2, typename T3> 19566 | inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, T3 t3) const 19567 | { 19568 | expression_node<typename node_type::value_type>* 19569 | result = (new node_type(t1, t2, t3)); 19570 | result->node_depth(); 19571 | return result; 19572 | } 19573 | 19574 | template <typename node_type, 19575 | typename T1, typename T2, 19576 | typename T3, typename T4> 19577 | inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, 19578 | T3 t3, T4 t4) const 19579 | { 19580 | expression_node<typename node_type::value_type>* 19581 | result = (new node_type(t1, t2, t3, t4)); 19582 | result->node_depth(); 19583 | return result; 19584 | } 19585 | 19586 | template <typename node_type, 19587 | typename T1, typename T2, 19588 | typename T3, typename T4, 19589 | typename T5> 19590 | inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, 19591 | T3 t3, T4 t4, 19592 | T5 t5) const 19593 | { 19594 | expression_node<typename node_type::value_type>* 19595 | result = (new node_type(t1, t2, t3, t4, t5)); 19596 | result->node_depth(); 19597 | return result; 19598 | } 19599 | 19600 | template <typename node_type, 19601 | typename T1, typename T2, 19602 | typename T3, typename T4, 19603 | typename T5, typename T6> 19604 | inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, 19605 | T3 t3, T4 t4, 19606 | T5 t5, T6 t6) const 19607 | { 19608 | expression_node<typename node_type::value_type>* 19609 | result = (new node_type(t1, t2, t3, t4, t5, t6)); 19610 | result->node_depth(); 19611 | return result; 19612 | } 19613 | 19614 | template <typename node_type, 19615 | typename T1, typename T2, 19616 | typename T3, typename T4, 19617 | typename T5, typename T6, typename T7> 19618 | inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, 19619 | T3 t3, T4 t4, 19620 | T5 t5, T6 t6, 19621 | T7 t7) const 19622 | { 19623 | expression_node<typename node_type::value_type>* 19624 | result = (new node_type(t1, t2, t3, t4, t5, t6, t7)); 19625 | result->node_depth(); 19626 | return result; 19627 | } 19628 | 19629 | template <typename T> 19630 | void inline free(expression_node<T>*& e) const 19631 | { 19632 | exprtk_debug(("node_allocator::free() - deleting expression_node " 19633 | "type: %03d addr: %p\n", 19634 | static_cast<int>(e->type()), 19635 | reinterpret_cast<void*>(e))); 19636 | delete e; 19637 | e = 0; 19638 | } 19639 | }; 19640 | 19641 | inline void load_operations_map(std::multimap<std::string,details::base_operation_t,details::ilesscompare>& m) 19642 | { 19643 | #define register_op(Symbol, Type, Args) \ 19644 | m.insert(std::make_pair(std::string(Symbol),details::base_operation_t(Type,Args))); \ 19645 | 19646 | register_op("abs" , e_abs , 1) 19647 | register_op("acos" , e_acos , 1) 19648 | register_op("acosh" , e_acosh , 1) 19649 | register_op("asin" , e_asin , 1) 19650 | register_op("asinh" , e_asinh , 1) 19651 | register_op("atan" , e_atan , 1) 19652 | register_op("atanh" , e_atanh , 1) 19653 | register_op("ceil" , e_ceil , 1) 19654 | register_op("cos" , e_cos , 1) 19655 | register_op("cosh" , e_cosh , 1) 19656 | register_op("exp" , e_exp , 1) 19657 | register_op("expm1" , e_expm1 , 1) 19658 | register_op("floor" , e_floor , 1) 19659 | register_op("log" , e_log , 1) 19660 | register_op("log10" , e_log10 , 1) 19661 | register_op("log2" , e_log2 , 1) 19662 | register_op("log1p" , e_log1p , 1) 19663 | register_op("round" , e_round , 1) 19664 | register_op("sin" , e_sin , 1) 19665 | register_op("sinc" , e_sinc , 1) 19666 | register_op("sinh" , e_sinh , 1) 19667 | register_op("sec" , e_sec , 1) 19668 | register_op("csc" , e_csc , 1) 19669 | register_op("sqrt" , e_sqrt , 1) 19670 | register_op("tan" , e_tan , 1) 19671 | register_op("tanh" , e_tanh , 1) 19672 | register_op("cot" , e_cot , 1) 19673 | register_op("rad2deg" , e_r2d , 1) 19674 | register_op("deg2rad" , e_d2r , 1) 19675 | register_op("deg2grad" , e_d2g , 1) 19676 | register_op("grad2deg" , e_g2d , 1) 19677 | register_op("sgn" , e_sgn , 1) 19678 | register_op("not" , e_notl , 1) 19679 | register_op("erf" , e_erf , 1) 19680 | register_op("erfc" , e_erfc , 1) 19681 | register_op("ncdf" , e_ncdf , 1) 19682 | register_op("frac" , e_frac , 1) 19683 | register_op("trunc" , e_trunc , 1) 19684 | register_op("atan2" , e_atan2 , 2) 19685 | register_op("mod" , e_mod , 2) 19686 | register_op("logn" , e_logn , 2) 19687 | register_op("pow" , e_pow , 2) 19688 | register_op("root" , e_root , 2) 19689 | register_op("roundn" , e_roundn , 2) 19690 | register_op("equal" , e_equal , 2) 19691 | register_op("not_equal" , e_nequal , 2) 19692 | register_op("hypot" , e_hypot , 2) 19693 | register_op("shr" , e_shr , 2) 19694 | register_op("shl" , e_shl , 2) 19695 | register_op("clamp" , e_clamp , 3) 19696 | register_op("iclamp" , e_iclamp , 3) 19697 | register_op("inrange" , e_inrange , 3) 19698 | #undef register_op 19699 | } 19700 | 19701 | } // namespace details 19702 | 19703 | class function_traits 19704 | { 19705 | public: 19706 | 19707 | function_traits() 19708 | : allow_zero_parameters_(false) 19709 | , has_side_effects_(true) 19710 | , min_num_args_(0) 19711 | , max_num_args_(std::numeric_limits<std::size_t>::max()) 19712 | {} 19713 | 19714 | inline bool& allow_zero_parameters() 19715 | { 19716 | return allow_zero_parameters_; 19717 | } 19718 | 19719 | inline bool& has_side_effects() 19720 | { 19721 | return has_side_effects_; 19722 | } 19723 | 19724 | std::size_t& min_num_args() 19725 | { 19726 | return min_num_args_; 19727 | } 19728 | 19729 | std::size_t& max_num_args() 19730 | { 19731 | return max_num_args_; 19732 | } 19733 | 19734 | private: 19735 | 19736 | bool allow_zero_parameters_; 19737 | bool has_side_effects_; 19738 | std::size_t min_num_args_; 19739 | std::size_t max_num_args_; 19740 | }; 19741 | 19742 | template <typename FunctionType> 19743 | void enable_zero_parameters(FunctionType& func) 19744 | { 19745 | func.allow_zero_parameters() = true; 19746 | 19747 | if (0 != func.min_num_args()) 19748 | { 19749 | func.min_num_args() = 0; 19750 | } 19751 | } 19752 | 19753 | template <typename FunctionType> 19754 | void disable_zero_parameters(FunctionType& func) 19755 | { 19756 | func.allow_zero_parameters() = false; 19757 | } 19758 | 19759 | template <typename FunctionType> 19760 | void enable_has_side_effects(FunctionType& func) 19761 | { 19762 | func.has_side_effects() = true; 19763 | } 19764 | 19765 | template <typename FunctionType> 19766 | void disable_has_side_effects(FunctionType& func) 19767 | { 19768 | func.has_side_effects() = false; 19769 | } 19770 | 19771 | template <typename FunctionType> 19772 | void set_min_num_args(FunctionType& func, const std::size_t& num_args) 19773 | { 19774 | func.min_num_args() = num_args; 19775 | 19776 | if ((0 != func.min_num_args()) && func.allow_zero_parameters()) 19777 | func.allow_zero_parameters() = false; 19778 | } 19779 | 19780 | template <typename FunctionType> 19781 | void set_max_num_args(FunctionType& func, const std::size_t& num_args) 19782 | { 19783 | func.max_num_args() = num_args; 19784 | } 19785 | 19786 | template <typename T> 19787 | class ifunction : public function_traits 19788 | { 19789 | public: 19790 | 19791 | explicit ifunction(const std::size_t& pc) 19792 | : param_count(pc) 19793 | {} 19794 | 19795 | virtual ~ifunction() 19796 | {} 19797 | 19798 | #define empty_method_body(N) \ 19799 | { \ 19800 | exprtk_debug(("ifunction::operator() - Operator(" #N ") has not been overridden\n")); \ 19801 | return std::numeric_limits<T>::quiet_NaN(); \ 19802 | } \ 19803 | 19804 | inline virtual T operator() () 19805 | empty_method_body(0) 19806 | 19807 | inline virtual T operator() (const T&) 19808 | empty_method_body(1) 19809 | 19810 | inline virtual T operator() (const T&,const T&) 19811 | empty_method_body(2) 19812 | 19813 | inline virtual T operator() (const T&, const T&, const T&) 19814 | empty_method_body(3) 19815 | 19816 | inline virtual T operator() (const T&, const T&, const T&, const T&) 19817 | empty_method_body(4) 19818 | 19819 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&) 19820 | empty_method_body(5) 19821 | 19822 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&) 19823 | empty_method_body(6) 19824 | 19825 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19826 | empty_method_body(7) 19827 | 19828 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19829 | empty_method_body(8) 19830 | 19831 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19832 | empty_method_body(9) 19833 | 19834 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19835 | empty_method_body(10) 19836 | 19837 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19838 | const T&) 19839 | empty_method_body(11) 19840 | 19841 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19842 | const T&, const T&) 19843 | empty_method_body(12) 19844 | 19845 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19846 | const T&, const T&, const T&) 19847 | empty_method_body(13) 19848 | 19849 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19850 | const T&, const T&, const T&, const T&) 19851 | empty_method_body(14) 19852 | 19853 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19854 | const T&, const T&, const T&, const T&, const T&) 19855 | empty_method_body(15) 19856 | 19857 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19858 | const T&, const T&, const T&, const T&, const T&, const T&) 19859 | empty_method_body(16) 19860 | 19861 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19862 | const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19863 | empty_method_body(17) 19864 | 19865 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19866 | const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19867 | empty_method_body(18) 19868 | 19869 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19870 | const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19871 | empty_method_body(19) 19872 | 19873 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19874 | const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19875 | empty_method_body(20) 19876 | 19877 | #undef empty_method_body 19878 | 19879 | std::size_t param_count; 19880 | }; 19881 | 19882 | template <typename T> 19883 | class ivararg_function : public function_traits 19884 | { 19885 | public: 19886 | 19887 | virtual ~ivararg_function() 19888 | {} 19889 | 19890 | inline virtual T operator() (const std::vector<T>&) 19891 | { 19892 | exprtk_debug(("ivararg_function::operator() - Operator has not been overridden\n")); 19893 | return std::numeric_limits<T>::quiet_NaN(); 19894 | } 19895 | }; 19896 | 19897 | template <typename T> 19898 | class igeneric_function : public function_traits 19899 | { 19900 | public: 19901 | 19902 | enum return_type 19903 | { 19904 | e_rtrn_scalar = 0, 19905 | e_rtrn_string = 1, 19906 | e_rtrn_overload = 2 19907 | }; 19908 | 19909 | typedef T type; 19910 | typedef type_store<T> generic_type; 19911 | typedef typename generic_type::parameter_list parameter_list_t; 19912 | 19913 | explicit igeneric_function(const std::string& param_seq = "", const return_type rtr_type = e_rtrn_scalar) 19914 | : parameter_sequence(param_seq) 19915 | , rtrn_type(rtr_type) 19916 | {} 19917 | 19918 | virtual ~igeneric_function() 19919 | {} 19920 | 19921 | #define igeneric_function_empty_body(N) \ 19922 | { \ 19923 | exprtk_debug(("igeneric_function::operator() - Operator(" #N ") has not been overridden\n")); \ 19924 | return std::numeric_limits<T>::quiet_NaN(); \ 19925 | } \ 19926 | 19927 | // f(i_0,i_1,....,i_N) --> Scalar 19928 | inline virtual T operator() (parameter_list_t) 19929 | igeneric_function_empty_body(1) 19930 | 19931 | // f(i_0,i_1,....,i_N) --> String 19932 | inline virtual T operator() (std::string&, parameter_list_t) 19933 | igeneric_function_empty_body(2) 19934 | 19935 | // f(psi,i_0,i_1,....,i_N) --> Scalar 19936 | inline virtual T operator() (const std::size_t&, parameter_list_t) 19937 | igeneric_function_empty_body(3) 19938 | 19939 | // f(psi,i_0,i_1,....,i_N) --> String 19940 | inline virtual T operator() (const std::size_t&, std::string&, parameter_list_t) 19941 | igeneric_function_empty_body(4) 19942 | 19943 | #undef igeneric_function_empty_body 19944 | 19945 | std::string parameter_sequence; 19946 | return_type rtrn_type; 19947 | 19948 | static inline std::string generate_prefix_args(const std::string& prefix_args, std::size_t start = 0, std::size_t end = 10) 19949 | { 19950 | std::string result; 19951 | 19952 | for (std::size_t i = start; i <= end; ++i) 19953 | { 19954 | result += prefix_args + std::string(i,'?'); 19955 | result += (i != end) ? "|" : "" 19956 | } 19957 | 19958 | return result; 19959 | } 19960 | 19961 | static inline std::string generate_suffix_args(const std::string& suffix_args, std::size_t start = 0, std::size_t end = 10) 19962 | { 19963 | std::string result; 19964 | 19965 | for (std::size_t i = start; i <= end; ++i) 19966 | { 19967 | result += std::string(i,'?') + suffix_args; 19968 | result += (i != end) ? "|" : "" 19969 | } 19970 | 19971 | return result; 19972 | } 19973 | }; 19974 | 19975 | #ifndef exprtk_disable_string_capabilities 19976 | template <typename T> 19977 | class stringvar_base 19978 | { 19979 | public: 19980 | 19981 | typedef typename details::stringvar_node<T> stringvar_node_t; 19982 | 19983 | stringvar_base(const std::string& name, stringvar_node_t* svn) 19984 | : name_(name) 19985 | , string_varnode_(svn) 19986 | {} 19987 | 19988 | bool valid() const 19989 | { 19990 | return !name_.empty() && (0 != string_varnode_); 19991 | } 19992 | 19993 | std::string name() const 19994 | { 19995 | assert(string_varnode_); 19996 | return name_; 19997 | } 19998 | 19999 | void rebase(std::string& s) 20000 | { 20001 | assert(string_varnode_); 20002 | string_varnode_->rebase(s); 20003 | } 20004 | 20005 | private: 20006 | 20007 | std::string name_; 20008 | stringvar_node_t* string_varnode_; 20009 | }; 20010 | #endif 20011 | 20012 | template <typename T> class parser; 20013 | template <typename T> class expression_helper; 20014 | 20015 | template <typename T> 20016 | class symbol_table 20017 | { 20018 | public: 20019 | 20020 | enum symtab_mutability_type 20021 | { 20022 | e_unknown = 0, 20023 | e_mutable = 1, 20024 | e_immutable = 2 20025 | }; 20026 | 20027 | typedef T (*ff00_functor)(); 20028 | typedef T (*ff01_functor)(T); 20029 | typedef T (*ff02_functor)(T, T); 20030 | typedef T (*ff03_functor)(T, T, T); 20031 | typedef T (*ff04_functor)(T, T, T, T); 20032 | typedef T (*ff05_functor)(T, T, T, T, T); 20033 | typedef T (*ff06_functor)(T, T, T, T, T, T); 20034 | typedef T (*ff07_functor)(T, T, T, T, T, T, T); 20035 | typedef T (*ff08_functor)(T, T, T, T, T, T, T, T); 20036 | typedef T (*ff09_functor)(T, T, T, T, T, T, T, T, T); 20037 | typedef T (*ff10_functor)(T, T, T, T, T, T, T, T, T, T); 20038 | typedef T (*ff11_functor)(T, T, T, T, T, T, T, T, T, T, T); 20039 | typedef T (*ff12_functor)(T, T, T, T, T, T, T, T, T, T, T, T); 20040 | typedef T (*ff13_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T); 20041 | typedef T (*ff14_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T); 20042 | typedef T (*ff15_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T, T); 20043 | 20044 | protected: 20045 | 20046 | struct freefunc00 exprtk_final : public exprtk::ifunction<T> 20047 | { 20048 | using exprtk::ifunction<T>::operator(); 20049 | 20050 | explicit freefunc00(ff00_functor ff) : exprtk::ifunction<T>(0), f(ff) {} 20051 | inline T operator() () exprtk_override 20052 | { return f(); } 20053 | ff00_functor f; 20054 | }; 20055 | 20056 | struct freefunc01 exprtk_final : public exprtk::ifunction<T> 20057 | { 20058 | using exprtk::ifunction<T>::operator(); 20059 | 20060 | explicit freefunc01(ff01_functor ff) : exprtk::ifunction<T>(1), f(ff) {} 20061 | inline T operator() (const T& v0) exprtk_override 20062 | { return f(v0); } 20063 | ff01_functor f; 20064 | }; 20065 | 20066 | struct freefunc02 exprtk_final : public exprtk::ifunction<T> 20067 | { 20068 | using exprtk::ifunction<T>::operator(); 20069 | 20070 | explicit freefunc02(ff02_functor ff) : exprtk::ifunction<T>(2), f(ff) {} 20071 | inline T operator() (const T& v0, const T& v1) exprtk_override 20072 | { return f(v0, v1); } 20073 | ff02_functor f; 20074 | }; 20075 | 20076 | struct freefunc03 exprtk_final : public exprtk::ifunction<T> 20077 | { 20078 | using exprtk::ifunction<T>::operator(); 20079 | 20080 | explicit freefunc03(ff03_functor ff) : exprtk::ifunction<T>(3), f(ff) {} 20081 | inline T operator() (const T& v0, const T& v1, const T& v2) exprtk_override 20082 | { return f(v0, v1, v2); } 20083 | ff03_functor f; 20084 | }; 20085 | 20086 | struct freefunc04 exprtk_final : public exprtk::ifunction<T> 20087 | { 20088 | using exprtk::ifunction<T>::operator(); 20089 | 20090 | explicit freefunc04(ff04_functor ff) : exprtk::ifunction<T>(4), f(ff) {} 20091 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3) exprtk_override 20092 | { return f(v0, v1, v2, v3); } 20093 | ff04_functor f; 20094 | }; 20095 | 20096 | struct freefunc05 : public exprtk::ifunction<T> 20097 | { 20098 | using exprtk::ifunction<T>::operator(); 20099 | 20100 | explicit freefunc05(ff05_functor ff) : exprtk::ifunction<T>(5), f(ff) {} 20101 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4) exprtk_override 20102 | { return f(v0, v1, v2, v3, v4); } 20103 | ff05_functor f; 20104 | }; 20105 | 20106 | struct freefunc06 exprtk_final : public exprtk::ifunction<T> 20107 | { 20108 | using exprtk::ifunction<T>::operator(); 20109 | 20110 | explicit freefunc06(ff06_functor ff) : exprtk::ifunction<T>(6), f(ff) {} 20111 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5) exprtk_override 20112 | { return f(v0, v1, v2, v3, v4, v5); } 20113 | ff06_functor f; 20114 | }; 20115 | 20116 | struct freefunc07 exprtk_final : public exprtk::ifunction<T> 20117 | { 20118 | using exprtk::ifunction<T>::operator(); 20119 | 20120 | explicit freefunc07(ff07_functor ff) : exprtk::ifunction<T>(7), f(ff) {} 20121 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, 20122 | const T& v5, const T& v6) exprtk_override 20123 | { return f(v0, v1, v2, v3, v4, v5, v6); } 20124 | ff07_functor f; 20125 | }; 20126 | 20127 | struct freefunc08 exprtk_final : public exprtk::ifunction<T> 20128 | { 20129 | using exprtk::ifunction<T>::operator(); 20130 | 20131 | explicit freefunc08(ff08_functor ff) : exprtk::ifunction<T>(8), f(ff) {} 20132 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, 20133 | const T& v5, const T& v6, const T& v7) exprtk_override 20134 | { return f(v0, v1, v2, v3, v4, v5, v6, v7); } 20135 | ff08_functor f; 20136 | }; 20137 | 20138 | struct freefunc09 exprtk_final : public exprtk::ifunction<T> 20139 | { 20140 | using exprtk::ifunction<T>::operator(); 20141 | 20142 | explicit freefunc09(ff09_functor ff) : exprtk::ifunction<T>(9), f(ff) {} 20143 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, 20144 | const T& v5, const T& v6, const T& v7, const T& v8) exprtk_override 20145 | { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8); } 20146 | ff09_functor f; 20147 | }; 20148 | 20149 | struct freefunc10 exprtk_final : public exprtk::ifunction<T> 20150 | { 20151 | using exprtk::ifunction<T>::operator(); 20152 | 20153 | explicit freefunc10(ff10_functor ff) : exprtk::ifunction<T>(10), f(ff) {} 20154 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, 20155 | const T& v5, const T& v6, const T& v7, const T& v8, const T& v9) exprtk_override 20156 | { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9); } 20157 | ff10_functor f; 20158 | }; 20159 | 20160 | struct freefunc11 exprtk_final : public exprtk::ifunction<T> 20161 | { 20162 | using exprtk::ifunction<T>::operator(); 20163 | 20164 | explicit freefunc11(ff11_functor ff) : exprtk::ifunction<T>(11), f(ff) {} 20165 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, 20166 | const T& v5, const T& v6, const T& v7, const T& v8, const T& v9, const T& v10) exprtk_override 20167 | { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10); } 20168 | ff11_functor f; 20169 | }; 20170 | 20171 | struct freefunc12 exprtk_final : public exprtk::ifunction<T> 20172 | { 20173 | using exprtk::ifunction<T>::operator(); 20174 | 20175 | explicit freefunc12(ff12_functor ff) : exprtk::ifunction<T>(12), f(ff) {} 20176 | inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04, 20177 | const T& v05, const T& v06, const T& v07, const T& v08, const T& v09, 20178 | const T& v10, const T& v11) exprtk_override 20179 | { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11); } 20180 | ff12_functor f; 20181 | }; 20182 | 20183 | struct freefunc13 exprtk_final : public exprtk::ifunction<T> 20184 | { 20185 | using exprtk::ifunction<T>::operator(); 20186 | 20187 | explicit freefunc13(ff13_functor ff) : exprtk::ifunction<T>(13), f(ff) {} 20188 | inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04, 20189 | const T& v05, const T& v06, const T& v07, const T& v08, const T& v09, 20190 | const T& v10, const T& v11, const T& v12) exprtk_override 20191 | { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12); } 20192 | ff13_functor f; 20193 | }; 20194 | 20195 | struct freefunc14 exprtk_final : public exprtk::ifunction<T> 20196 | { 20197 | using exprtk::ifunction<T>::operator(); 20198 | 20199 | explicit freefunc14(ff14_functor ff) : exprtk::ifunction<T>(14), f(ff) {} 20200 | inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04, 20201 | const T& v05, const T& v06, const T& v07, const T& v08, const T& v09, 20202 | const T& v10, const T& v11, const T& v12, const T& v13) exprtk_override 20203 | { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12, v13); } 20204 | ff14_functor f; 20205 | }; 20206 | 20207 | struct freefunc15 exprtk_final : public exprtk::ifunction<T> 20208 | { 20209 | using exprtk::ifunction<T>::operator(); 20210 | 20211 | explicit freefunc15(ff15_functor ff) : exprtk::ifunction<T>(15), f(ff) {} 20212 | inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04, 20213 | const T& v05, const T& v06, const T& v07, const T& v08, const T& v09, 20214 | const T& v10, const T& v11, const T& v12, const T& v13, const T& v14) exprtk_override 20215 | { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12, v13, v14); } 20216 | ff15_functor f; 20217 | }; 20218 | 20219 | template <typename Type, typename RawType> 20220 | struct type_store 20221 | { 20222 | typedef details::expression_node<T>* expression_ptr; 20223 | typedef typename details::variable_node<T> variable_node_t; 20224 | typedef ifunction<T> ifunction_t; 20225 | typedef ivararg_function<T> ivararg_function_t; 20226 | typedef igeneric_function<T> igeneric_function_t; 20227 | typedef details::vector_holder<T> vector_t; 20228 | #ifndef exprtk_disable_string_capabilities 20229 | typedef typename details::stringvar_node<T> stringvar_node_t; 20230 | #endif 20231 | 20232 | typedef Type type_t; 20233 | typedef type_t* type_ptr; 20234 | typedef std::pair<bool,type_ptr> type_pair_t; 20235 | typedef std::map<std::string,type_pair_t,details::ilesscompare> type_map_t; 20236 | typedef typename type_map_t::iterator tm_itr_t; 20237 | typedef typename type_map_t::const_iterator tm_const_itr_t; 20238 | 20239 | enum { lut_size = 256 }; 20240 | 20241 | type_map_t map; 20242 | std::size_t size; 20243 | 20244 | type_store() 20245 | : size(0) 20246 | {} 20247 | 20248 | struct deleter 20249 | { 20250 | #define exprtk_define_process(Type) \ 20251 | static inline void process(std::pair<bool,Type*>& n) \ 20252 | { \ 20253 | delete n.second; \ 20254 | } \ 20255 | 20256 | exprtk_define_process(variable_node_t ) 20257 | exprtk_define_process(vector_t ) 20258 | #ifndef exprtk_disable_string_capabilities 20259 | exprtk_define_process(stringvar_node_t) 20260 | #endif 20261 | 20262 | #undef exprtk_define_process 20263 | 20264 | template <typename DeleteType> 20265 | static inline void process(std::pair<bool,DeleteType*>&) 20266 | {} 20267 | }; 20268 | 20269 | inline bool symbol_exists(const std::string& symbol_name) const 20270 | { 20271 | if (symbol_name.empty()) 20272 | return false; 20273 | else if (map.end() != map.find(symbol_name)) 20274 | return true; 20275 | else 20276 | return false; 20277 | } 20278 | 20279 | template <typename PtrType> 20280 | inline std::string entity_name(const PtrType& ptr) const 20281 | { 20282 | if (map.empty()) 20283 | return std::string(); 20284 | 20285 | tm_const_itr_t itr = map.begin(); 20286 | 20287 | while (map.end() != itr) 20288 | { 20289 | if (itr->second.second == ptr) 20290 | { 20291 | return itr->first; 20292 | } 20293 | else 20294 | ++itr; 20295 | } 20296 | 20297 | return std::string(); 20298 | } 20299 | 20300 | inline bool is_constant(const std::string& symbol_name) const 20301 | { 20302 | if (symbol_name.empty()) 20303 | return false; 20304 | else 20305 | { 20306 | const tm_const_itr_t itr = map.find(symbol_name); 20307 | 20308 | if (map.end() == itr) 20309 | return false; 20310 | else 20311 | return (*itr).second.first; 20312 | } 20313 | } 20314 | 20315 | template <typename Tie, typename RType> 20316 | inline bool add_impl(const std::string& symbol_name, RType t, const bool is_const) 20317 | { 20318 | if (symbol_name.size() > 1) 20319 | { 20320 | for (std::size_t i = 0; i < details::reserved_symbols_size; ++i) 20321 | { 20322 | if (details::imatch(symbol_name, details::reserved_symbols[i])) 20323 | { 20324 | return false; 20325 | } 20326 | } 20327 | } 20328 | 20329 | const tm_itr_t itr = map.find(symbol_name); 20330 | 20331 | if (map.end() == itr) 20332 | { 20333 | map[symbol_name] = Tie::make(t,is_const); 20334 | ++size; 20335 | } 20336 | 20337 | return true; 20338 | } 20339 | 20340 | struct tie_array 20341 | { 20342 | static inline std::pair<bool,vector_t*> make(std::pair<T*,std::size_t> v, const bool is_const = false) 20343 | { 20344 | return std::make_pair(is_const, new vector_t(v.first, v.second)); 20345 | } 20346 | }; 20347 | 20348 | struct tie_stdvec 20349 | { 20350 | template <typename Allocator> 20351 | static inline std::pair<bool,vector_t*> make(std::vector<T,Allocator>& v, const bool is_const = false) 20352 | { 20353 | return std::make_pair(is_const, new vector_t(v)); 20354 | } 20355 | }; 20356 | 20357 | struct tie_vecview 20358 | { 20359 | static inline std::pair<bool,vector_t*> make(exprtk::vector_view<T>& v, const bool is_const = false) 20360 | { 20361 | return std::make_pair(is_const, new vector_t(v)); 20362 | } 20363 | }; 20364 | 20365 | struct tie_stddeq 20366 | { 20367 | template <typename Allocator> 20368 | static inline std::pair<bool,vector_t*> make(std::deque<T,Allocator>& v, const bool is_const = false) 20369 | { 20370 | return std::make_pair(is_const, new vector_t(v)); 20371 | } 20372 | }; 20373 | 20374 | template <std::size_t v_size> 20375 | inline bool add(const std::string& symbol_name, T (&v)[v_size], const bool is_const = false) 20376 | { 20377 | return add_impl<tie_array,std::pair<T*,std::size_t> > 20378 | (symbol_name, std::make_pair(v,v_size), is_const); 20379 | } 20380 | 20381 | inline bool add(const std::string& symbol_name, T* v, const std::size_t v_size, const bool is_const = false) 20382 | { 20383 | return add_impl<tie_array,std::pair<T*,std::size_t> > 20384 | (symbol_name, std::make_pair(v,v_size), is_const); 20385 | } 20386 | 20387 | template <typename Allocator> 20388 | inline bool add(const std::string& symbol_name, std::vector<T,Allocator>& v, const bool is_const = false) 20389 | { 20390 | return add_impl<tie_stdvec,std::vector<T,Allocator>&> 20391 | (symbol_name, v, is_const); 20392 | } 20393 | 20394 | inline bool add(const std::string& symbol_name, exprtk::vector_view<T>& v, const bool is_const = false) 20395 | { 20396 | return add_impl<tie_vecview,exprtk::vector_view<T>&> 20397 | (symbol_name, v, is_const); 20398 | } 20399 | 20400 | template <typename Allocator> 20401 | inline bool add(const std::string& symbol_name, std::deque<T,Allocator>& v, const bool is_const = false) 20402 | { 20403 | return add_impl<tie_stddeq,std::deque<T,Allocator>&> 20404 | (symbol_name, v, is_const); 20405 | } 20406 | 20407 | inline bool add(const std::string& symbol_name, RawType& t_, const bool is_const = false) 20408 | { 20409 | struct tie 20410 | { 20411 | static inline std::pair<bool,variable_node_t*> make(T& t, const bool is_constant = false) 20412 | { 20413 | return std::make_pair(is_constant, new variable_node_t(t)); 20414 | } 20415 | 20416 | #ifndef exprtk_disable_string_capabilities 20417 | static inline std::pair<bool,stringvar_node_t*> make(std::string& t, const bool is_constant = false) 20418 | { 20419 | return std::make_pair(is_constant, new stringvar_node_t(t)); 20420 | } 20421 | #endif 20422 | 20423 | static inline std::pair<bool,function_t*> make(function_t& t, const bool is_constant = false) 20424 | { 20425 | return std::make_pair(is_constant,&t); 20426 | } 20427 | 20428 | static inline std::pair<bool,vararg_function_t*> make(vararg_function_t& t, const bool is_constant = false) 20429 | { 20430 | return std::make_pair(is_constant,&t); 20431 | } 20432 | 20433 | static inline std::pair<bool,generic_function_t*> make(generic_function_t& t, const bool is_constant = false) 20434 | { 20435 | return std::make_pair(is_constant,&t); 20436 | } 20437 | }; 20438 | 20439 | const tm_itr_t itr = map.find(symbol_name); 20440 | 20441 | if (map.end() == itr) 20442 | { 20443 | map[symbol_name] = tie::make(t_,is_const); 20444 | ++size; 20445 | } 20446 | 20447 | return true; 20448 | } 20449 | 20450 | inline type_ptr get(const std::string& symbol_name) const 20451 | { 20452 | const tm_const_itr_t itr = map.find(symbol_name); 20453 | 20454 | if (map.end() == itr) 20455 | return reinterpret_cast<type_ptr>(0); 20456 | else 20457 | return itr->second.second; 20458 | } 20459 | 20460 | template <typename TType, typename TRawType, typename PtrType> 20461 | struct ptr_match 20462 | { 20463 | static inline bool test(const PtrType, const void*) 20464 | { 20465 | return false; 20466 | } 20467 | }; 20468 | 20469 | template <typename TType, typename TRawType> 20470 | struct ptr_match<TType,TRawType,variable_node_t*> 20471 | { 20472 | static inline bool test(const variable_node_t* p, const void* ptr) 20473 | { 20474 | exprtk_debug(("ptr_match::test() - %p <--> %p\n", reinterpret_cast<const void*>(&(p->ref())), ptr)); 20475 | return (&(p->ref()) == ptr); 20476 | } 20477 | }; 20478 | 20479 | inline type_ptr get_from_varptr(const void* ptr) const 20480 | { 20481 | tm_const_itr_t itr = map.begin(); 20482 | 20483 | while (map.end() != itr) 20484 | { 20485 | type_ptr ret_ptr = itr->second.second; 20486 | 20487 | if (ptr_match<Type,RawType,type_ptr>::test(ret_ptr,ptr)) 20488 | { 20489 | return ret_ptr; 20490 | } 20491 | 20492 | ++itr; 20493 | } 20494 | 20495 | return type_ptr(0); 20496 | } 20497 | 20498 | inline bool remove(const std::string& symbol_name, const bool delete_node = true) 20499 | { 20500 | const tm_itr_t itr = map.find(symbol_name); 20501 | 20502 | if (map.end() != itr) 20503 | { 20504 | if (delete_node) 20505 | { 20506 | deleter::process((*itr).second); 20507 | } 20508 | 20509 | map.erase(itr); 20510 | --size; 20511 | 20512 | return true; 20513 | } 20514 | else 20515 | return false; 20516 | } 20517 | 20518 | inline RawType& type_ref(const std::string& symbol_name) 20519 | { 20520 | struct init_type 20521 | { 20522 | static inline double set(double) { return (0.0); } 20523 | static inline double set(long double) { return (0.0); } 20524 | static inline float set(float) { return (0.0f); } 20525 | static inline std::string set(std::string&) { return std::string(""); } 20526 | }; 20527 | 20528 | static RawType null_type = init_type::set(RawType()); 20529 | 20530 | const tm_const_itr_t itr = map.find(symbol_name); 20531 | 20532 | if (map.end() == itr) 20533 | return null_type; 20534 | else 20535 | return itr->second.second->ref(); 20536 | } 20537 | 20538 | inline void clear(const bool delete_node = true) 20539 | { 20540 | if (!map.empty()) 20541 | { 20542 | if (delete_node) 20543 | { 20544 | tm_itr_t itr = map.begin(); 20545 | tm_itr_t end = map.end (); 20546 | 20547 | while (end != itr) 20548 | { 20549 | deleter::process((*itr).second); 20550 | ++itr; 20551 | } 20552 | } 20553 | 20554 | map.clear(); 20555 | } 20556 | 20557 | size = 0; 20558 | } 20559 | 20560 | template <typename Allocator, 20561 | template <typename, typename> class Sequence> 20562 | inline std::size_t get_list(Sequence<std::pair<std::string,RawType>,Allocator>& list) const 20563 | { 20564 | std::size_t count = 0; 20565 | 20566 | if (!map.empty()) 20567 | { 20568 | tm_const_itr_t itr = map.begin(); 20569 | tm_const_itr_t end = map.end (); 20570 | 20571 | while (end != itr) 20572 | { 20573 | list.push_back(std::make_pair((*itr).first,itr->second.second->ref())); 20574 | ++itr; 20575 | ++count; 20576 | } 20577 | } 20578 | 20579 | return count; 20580 | } 20581 | 20582 | template <typename Allocator, 20583 | template <typename, typename> class Sequence> 20584 | inline std::size_t get_list(Sequence<std::string,Allocator>& vlist) const 20585 | { 20586 | std::size_t count = 0; 20587 | 20588 | if (!map.empty()) 20589 | { 20590 | tm_const_itr_t itr = map.begin(); 20591 | tm_const_itr_t end = map.end (); 20592 | 20593 | while (end != itr) 20594 | { 20595 | vlist.push_back((*itr).first); 20596 | ++itr; 20597 | ++count; 20598 | } 20599 | } 20600 | 20601 | return count; 20602 | } 20603 | }; 20604 | 20605 | typedef details::expression_node<T>* expression_ptr; 20606 | typedef typename details::variable_node<T> variable_t; 20607 | typedef typename details::vector_holder<T> vector_holder_t; 20608 | typedef variable_t* variable_ptr; 20609 | #ifndef exprtk_disable_string_capabilities 20610 | typedef typename details::stringvar_node<T> stringvar_t; 20611 | typedef stringvar_t* stringvar_ptr; 20612 | #endif 20613 | typedef ifunction <T> function_t; 20614 | typedef ivararg_function <T> vararg_function_t; 20615 | typedef igeneric_function<T> generic_function_t; 20616 | typedef function_t* function_ptr; 20617 | typedef vararg_function_t* vararg_function_ptr; 20618 | typedef generic_function_t* generic_function_ptr; 20619 | 20620 | static const std::size_t lut_size = 256; 20621 | 20622 | // Symbol Table Holder 20623 | struct control_block 20624 | { 20625 | struct st_data 20626 | { 20627 | type_store<variable_t , T > variable_store; 20628 | type_store<function_t , function_t > function_store; 20629 | type_store<vararg_function_t , vararg_function_t > vararg_function_store; 20630 | type_store<generic_function_t, generic_function_t> generic_function_store; 20631 | type_store<generic_function_t, generic_function_t> string_function_store; 20632 | type_store<generic_function_t, generic_function_t> overload_function_store; 20633 | type_store<vector_holder_t , vector_holder_t > vector_store; 20634 | #ifndef exprtk_disable_string_capabilities 20635 | type_store<stringvar_t , std::string > stringvar_store; 20636 | #endif 20637 | 20638 | st_data() 20639 | { 20640 | for (std::size_t i = 0; i < details::reserved_words_size; ++i) 20641 | { 20642 | reserved_symbol_table_.insert(details::reserved_words[i]); 20643 | } 20644 | 20645 | for (std::size_t i = 0; i < details::reserved_symbols_size; ++i) 20646 | { 20647 | reserved_symbol_table_.insert(details::reserved_symbols[i]); 20648 | } 20649 | } 20650 | 20651 | ~st_data() 20652 | { 20653 | for (std::size_t i = 0; i < free_function_list_.size(); ++i) 20654 | { 20655 | delete free_function_list_[i]; 20656 | } 20657 | } 20658 | 20659 | inline bool is_reserved_symbol(const std::string& symbol) const 20660 | { 20661 | return (reserved_symbol_table_.end() != reserved_symbol_table_.find(symbol)); 20662 | } 20663 | 20664 | static inline st_data* create() 20665 | { 20666 | return (new st_data); 20667 | } 20668 | 20669 | static inline void destroy(st_data*& sd) 20670 | { 20671 | delete sd; 20672 | sd = reinterpret_cast<st_data*>(0); 20673 | } 20674 | 20675 | std::list<T> local_symbol_list_; 20676 | std::list<std::string> local_stringvar_list_; 20677 | std::set<std::string> reserved_symbol_table_; 20678 | std::vector<ifunction<T>*> free_function_list_; 20679 | }; 20680 | 20681 | control_block() 20682 | : ref_count(1) 20683 | , data_(st_data::create()) 20684 | , mutability_(e_mutable) 20685 | {} 20686 | 20687 | explicit control_block(st_data* data) 20688 | : ref_count(1) 20689 | , data_(data) 20690 | , mutability_(e_mutable) 20691 | {} 20692 | 20693 | ~control_block() 20694 | { 20695 | if (data_ && (0 == ref_count)) 20696 | { 20697 | st_data::destroy(data_); 20698 | } 20699 | } 20700 | 20701 | static inline control_block* create() 20702 | { 20703 | return (new control_block); 20704 | } 20705 | 20706 | template <typename SymTab> 20707 | static inline void destroy(control_block*& cntrl_blck, SymTab* sym_tab) 20708 | { 20709 | if (cntrl_blck) 20710 | { 20711 | if ( 20712 | (0 != cntrl_blck->ref_count) && 20713 | (0 == --cntrl_blck->ref_count) 20714 | ) 20715 | { 20716 | if (sym_tab) 20717 | sym_tab->clear(); 20718 | 20719 | delete cntrl_blck; 20720 | } 20721 | 20722 | cntrl_blck = 0; 20723 | } 20724 | } 20725 | 20726 | void set_mutability(const symtab_mutability_type mutability) 20727 | { 20728 | mutability_ = mutability; 20729 | } 20730 | 20731 | std::size_t ref_count; 20732 | st_data* data_; 20733 | symtab_mutability_type mutability_; 20734 | }; 20735 | 20736 | public: 20737 | 20738 | explicit symbol_table(const symtab_mutability_type mutability = e_mutable) 20739 | : control_block_(control_block::create()) 20740 | { 20741 | control_block_->set_mutability(mutability); 20742 | clear(); 20743 | } 20744 | 20745 | ~symbol_table() 20746 | { 20747 | exprtk::details::dump_ptr("~symbol_table", this); 20748 | control_block::destroy(control_block_, this); 20749 | } 20750 | 20751 | symbol_table(const symbol_table<T>& st) 20752 | { 20753 | control_block_ = st.control_block_; 20754 | control_block_->ref_count++; 20755 | } 20756 | 20757 | inline symbol_table<T>& operator=(const symbol_table<T>& st) 20758 | { 20759 | if (this != &st) 20760 | { 20761 | control_block::destroy(control_block_,reinterpret_cast<symbol_table<T>*>(0)); 20762 | 20763 | control_block_ = st.control_block_; 20764 | control_block_->ref_count++; 20765 | } 20766 | 20767 | return (*this); 20768 | } 20769 | 20770 | inline bool operator==(const symbol_table<T>& st) const 20771 | { 20772 | return (this == &st) || (control_block_ == st.control_block_); 20773 | } 20774 | 20775 | inline symtab_mutability_type mutability() const 20776 | { 20777 | return valid() ? control_block_->mutability_ : e_unknown; 20778 | } 20779 | 20780 | inline void clear_variables(const bool delete_node = true) 20781 | { 20782 | local_data().variable_store.clear(delete_node); 20783 | } 20784 | 20785 | inline void clear_functions() 20786 | { 20787 | local_data().function_store.clear(); 20788 | } 20789 | 20790 | inline void clear_strings() 20791 | { 20792 | #ifndef exprtk_disable_string_capabilities 20793 | local_data().stringvar_store.clear(); 20794 | #endif 20795 | } 20796 | 20797 | inline void clear_vectors() 20798 | { 20799 | local_data().vector_store.clear(); 20800 | } 20801 | 20802 | inline void clear_local_constants() 20803 | { 20804 | local_data().local_symbol_list_.clear(); 20805 | } 20806 | 20807 | inline void clear() 20808 | { 20809 | if (!valid()) return; 20810 | clear_variables (); 20811 | clear_functions (); 20812 | clear_strings (); 20813 | clear_vectors (); 20814 | clear_local_constants(); 20815 | } 20816 | 20817 | inline std::size_t variable_count() const 20818 | { 20819 | if (valid()) 20820 | return local_data().variable_store.size; 20821 | else 20822 | return 0; 20823 | } 20824 | 20825 | #ifndef exprtk_disable_string_capabilities 20826 | inline std::size_t stringvar_count() const 20827 | { 20828 | if (valid()) 20829 | return local_data().stringvar_store.size; 20830 | else 20831 | return 0; 20832 | } 20833 | #endif 20834 | 20835 | inline std::size_t function_count() const 20836 | { 20837 | if (valid()) 20838 | return local_data().function_store.size; 20839 | else 20840 | return 0; 20841 | } 20842 | 20843 | inline std::size_t vector_count() const 20844 | { 20845 | if (valid()) 20846 | return local_data().vector_store.size; 20847 | else 20848 | return 0; 20849 | } 20850 | 20851 | inline variable_ptr get_variable(const std::string& variable_name) const 20852 | { 20853 | if (!valid()) 20854 | return reinterpret_cast<variable_ptr>(0); 20855 | else if (!valid_symbol(variable_name)) 20856 | return reinterpret_cast<variable_ptr>(0); 20857 | else 20858 | return local_data().variable_store.get(variable_name); 20859 | } 20860 | 20861 | inline variable_ptr get_variable(const T& var_ref) const 20862 | { 20863 | if (!valid()) 20864 | return reinterpret_cast<variable_ptr>(0); 20865 | else 20866 | return local_data().variable_store.get_from_varptr( 20867 | reinterpret_cast<const void*>(&var_ref)); 20868 | } 20869 | 20870 | #ifndef exprtk_disable_string_capabilities 20871 | inline stringvar_ptr get_stringvar(const std::string& string_name) const 20872 | { 20873 | if (!valid()) 20874 | return reinterpret_cast<stringvar_ptr>(0); 20875 | else if (!valid_symbol(string_name)) 20876 | return reinterpret_cast<stringvar_ptr>(0); 20877 | else 20878 | return local_data().stringvar_store.get(string_name); 20879 | } 20880 | 20881 | inline stringvar_base<T> get_stringvar_base(const std::string& string_name) const 20882 | { 20883 | static stringvar_base<T> null_stringvar_base("",reinterpret_cast<stringvar_ptr>(0)); 20884 | if (!valid()) 20885 | return null_stringvar_base; 20886 | else if (!valid_symbol(string_name)) 20887 | return null_stringvar_base; 20888 | 20889 | stringvar_ptr stringvar = local_data().stringvar_store.get(string_name); 20890 | 20891 | if (0 == stringvar) 20892 | { 20893 | return null_stringvar_base; 20894 | } 20895 | 20896 | return stringvar_base<T>(string_name,stringvar); 20897 | } 20898 | #endif 20899 | 20900 | inline function_ptr get_function(const std::string& function_name) const 20901 | { 20902 | if (!valid()) 20903 | return reinterpret_cast<function_ptr>(0); 20904 | else if (!valid_symbol(function_name)) 20905 | return reinterpret_cast<function_ptr>(0); 20906 | else 20907 | return local_data().function_store.get(function_name); 20908 | } 20909 | 20910 | inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name) const 20911 | { 20912 | if (!valid()) 20913 | return reinterpret_cast<vararg_function_ptr>(0); 20914 | else if (!valid_symbol(vararg_function_name)) 20915 | return reinterpret_cast<vararg_function_ptr>(0); 20916 | else 20917 | return local_data().vararg_function_store.get(vararg_function_name); 20918 | } 20919 | 20920 | inline generic_function_ptr get_generic_function(const std::string& function_name) const 20921 | { 20922 | if (!valid()) 20923 | return reinterpret_cast<generic_function_ptr>(0); 20924 | else if (!valid_symbol(function_name)) 20925 | return reinterpret_cast<generic_function_ptr>(0); 20926 | else 20927 | return local_data().generic_function_store.get(function_name); 20928 | } 20929 | 20930 | inline generic_function_ptr get_string_function(const std::string& function_name) const 20931 | { 20932 | if (!valid()) 20933 | return reinterpret_cast<generic_function_ptr>(0); 20934 | else if (!valid_symbol(function_name)) 20935 | return reinterpret_cast<generic_function_ptr>(0); 20936 | else 20937 | return local_data().string_function_store.get(function_name); 20938 | } 20939 | 20940 | inline generic_function_ptr get_overload_function(const std::string& function_name) const 20941 | { 20942 | if (!valid()) 20943 | return reinterpret_cast<generic_function_ptr>(0); 20944 | else if (!valid_symbol(function_name)) 20945 | return reinterpret_cast<generic_function_ptr>(0); 20946 | else 20947 | return local_data().overload_function_store.get(function_name); 20948 | } 20949 | 20950 | typedef vector_holder_t* vector_holder_ptr; 20951 | 20952 | inline vector_holder_ptr get_vector(const std::string& vector_name) const 20953 | { 20954 | if (!valid()) 20955 | return reinterpret_cast<vector_holder_ptr>(0); 20956 | else if (!valid_symbol(vector_name)) 20957 | return reinterpret_cast<vector_holder_ptr>(0); 20958 | else 20959 | return local_data().vector_store.get(vector_name); 20960 | } 20961 | 20962 | inline T& variable_ref(const std::string& symbol_name) 20963 | { 20964 | static T null_var = T(0); 20965 | if (!valid()) 20966 | return null_var; 20967 | else if (!valid_symbol(symbol_name)) 20968 | return null_var; 20969 | else 20970 | return local_data().variable_store.type_ref(symbol_name); 20971 | } 20972 | 20973 | #ifndef exprtk_disable_string_capabilities 20974 | inline std::string& stringvar_ref(const std::string& symbol_name) 20975 | { 20976 | static std::string null_stringvar; 20977 | if (!valid()) 20978 | return null_stringvar; 20979 | else if (!valid_symbol(symbol_name)) 20980 | return null_stringvar; 20981 | else 20982 | return local_data().stringvar_store.type_ref(symbol_name); 20983 | } 20984 | #endif 20985 | 20986 | inline bool is_constant_node(const std::string& symbol_name) const 20987 | { 20988 | if (!valid()) 20989 | return false; 20990 | else if (!valid_symbol(symbol_name)) 20991 | return false; 20992 | else 20993 | return local_data().variable_store.is_constant(symbol_name); 20994 | } 20995 | 20996 | #ifndef exprtk_disable_string_capabilities 20997 | inline bool is_constant_string(const std::string& symbol_name) const 20998 | { 20999 | if (!valid()) 21000 | return false; 21001 | else if (!valid_symbol(symbol_name)) 21002 | return false; 21003 | else if (!local_data().stringvar_store.symbol_exists(symbol_name)) 21004 | return false; 21005 | else 21006 | return local_data().stringvar_store.is_constant(symbol_name); 21007 | } 21008 | #endif 21009 | 21010 | inline bool create_variable(const std::string& variable_name, const T& value = T(0)) 21011 | { 21012 | if (!valid()) 21013 | return false; 21014 | else if (!valid_symbol(variable_name)) 21015 | return false; 21016 | else if (symbol_exists(variable_name)) 21017 | return false; 21018 | 21019 | local_data().local_symbol_list_.push_back(value); 21020 | T& t = local_data().local_symbol_list_.back(); 21021 | 21022 | return add_variable(variable_name,t); 21023 | } 21024 | 21025 | #ifndef exprtk_disable_string_capabilities 21026 | inline bool create_stringvar(const std::string& stringvar_name, const std::string& value = std::string("")) 21027 | { 21028 | if (!valid()) 21029 | return false; 21030 | else if (!valid_symbol(stringvar_name)) 21031 | return false; 21032 | else if (symbol_exists(stringvar_name)) 21033 | return false; 21034 | 21035 | local_data().local_stringvar_list_.push_back(value); 21036 | std::string& s = local_data().local_stringvar_list_.back(); 21037 | 21038 | return add_stringvar(stringvar_name,s); 21039 | } 21040 | #endif 21041 | 21042 | inline bool add_variable(const std::string& variable_name, T& t, const bool is_constant = false) 21043 | { 21044 | if (!valid()) 21045 | return false; 21046 | else if (!valid_symbol(variable_name)) 21047 | return false; 21048 | else if (symbol_exists(variable_name)) 21049 | return false; 21050 | else 21051 | return local_data().variable_store.add(variable_name, t, is_constant); 21052 | } 21053 | 21054 | inline bool add_constant(const std::string& constant_name, const T& value) 21055 | { 21056 | if (!valid()) 21057 | return false; 21058 | else if (!valid_symbol(constant_name)) 21059 | return false; 21060 | else if (symbol_exists(constant_name)) 21061 | return false; 21062 | 21063 | local_data().local_symbol_list_.push_back(value); 21064 | T& t = local_data().local_symbol_list_.back(); 21065 | 21066 | return add_variable(constant_name, t, true); 21067 | } 21068 | 21069 | #ifndef exprtk_disable_string_capabilities 21070 | inline bool add_stringvar(const std::string& stringvar_name, std::string& s, const bool is_constant = false) 21071 | { 21072 | if (!valid()) 21073 | return false; 21074 | else if (!valid_symbol(stringvar_name)) 21075 | return false; 21076 | else if (symbol_exists(stringvar_name)) 21077 | return false; 21078 | else 21079 | return local_data().stringvar_store.add(stringvar_name, s, is_constant); 21080 | } 21081 | #endif 21082 | 21083 | inline bool add_function(const std::string& function_name, function_t& function) 21084 | { 21085 | if (!valid()) 21086 | return false; 21087 | else if (!valid_symbol(function_name)) 21088 | return false; 21089 | else if (symbol_exists(function_name)) 21090 | return false; 21091 | else 21092 | return local_data().function_store.add(function_name,function); 21093 | } 21094 | 21095 | inline bool add_function(const std::string& vararg_function_name, vararg_function_t& vararg_function) 21096 | { 21097 | if (!valid()) 21098 | return false; 21099 | else if (!valid_symbol(vararg_function_name)) 21100 | return false; 21101 | else if (symbol_exists(vararg_function_name)) 21102 | return false; 21103 | else 21104 | return local_data().vararg_function_store.add(vararg_function_name,vararg_function); 21105 | } 21106 | 21107 | inline bool add_function(const std::string& function_name, generic_function_t& function) 21108 | { 21109 | if (!valid()) 21110 | return false; 21111 | else if (!valid_symbol(function_name)) 21112 | return false; 21113 | else if (symbol_exists(function_name)) 21114 | return false; 21115 | else 21116 | { 21117 | switch (function.rtrn_type) 21118 | { 21119 | case generic_function_t::e_rtrn_scalar : 21120 | return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ? 21121 | local_data().generic_function_store.add(function_name,function) : false; 21122 | 21123 | case generic_function_t::e_rtrn_string : 21124 | return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ? 21125 | local_data().string_function_store.add(function_name,function) : false; 21126 | 21127 | case generic_function_t::e_rtrn_overload : 21128 | return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|:")) ? 21129 | local_data().overload_function_store.add(function_name,function) : false; 21130 | } 21131 | } 21132 | 21133 | return false; 21134 | } 21135 | 21136 | #define exprtk_define_freefunction(NN) \ 21137 | inline bool add_function(const std::string& function_name, ff##NN##_functor function) \ 21138 | { \ 21139 | if (!valid()) \ 21140 | { return false; } \ 21141 | if (!valid_symbol(function_name)) \ 21142 | { return false; } \ 21143 | if (symbol_exists(function_name)) \ 21144 | { return false; } \ 21145 | \ 21146 | exprtk::ifunction<T>* ifunc = new freefunc##NN(function); \ 21147 | \ 21148 | local_data().free_function_list_.push_back(ifunc); \ 21149 | \ 21150 | return add_function(function_name,(*local_data().free_function_list_.back())); \ 21151 | } \ 21152 | 21153 | exprtk_define_freefunction(00) exprtk_define_freefunction(01) 21154 | exprtk_define_freefunction(02) exprtk_define_freefunction(03) 21155 | exprtk_define_freefunction(04) exprtk_define_freefunction(05) 21156 | exprtk_define_freefunction(06) exprtk_define_freefunction(07) 21157 | exprtk_define_freefunction(08) exprtk_define_freefunction(09) 21158 | exprtk_define_freefunction(10) exprtk_define_freefunction(11) 21159 | exprtk_define_freefunction(12) exprtk_define_freefunction(13) 21160 | exprtk_define_freefunction(14) exprtk_define_freefunction(15) 21161 | 21162 | #undef exprtk_define_freefunction 21163 | 21164 | inline bool add_reserved_function(const std::string& function_name, function_t& function) 21165 | { 21166 | if (!valid()) 21167 | return false; 21168 | else if (!valid_symbol(function_name,false)) 21169 | return false; 21170 | else if (symbol_exists(function_name,false)) 21171 | return false; 21172 | else 21173 | return local_data().function_store.add(function_name,function); 21174 | } 21175 | 21176 | inline bool add_reserved_function(const std::string& vararg_function_name, vararg_function_t& vararg_function) 21177 | { 21178 | if (!valid()) 21179 | return false; 21180 | else if (!valid_symbol(vararg_function_name,false)) 21181 | return false; 21182 | else if (symbol_exists(vararg_function_name,false)) 21183 | return false; 21184 | else 21185 | return local_data().vararg_function_store.add(vararg_function_name,vararg_function); 21186 | } 21187 | 21188 | inline bool add_reserved_function(const std::string& function_name, generic_function_t& function) 21189 | { 21190 | if (!valid()) 21191 | return false; 21192 | else if (!valid_symbol(function_name,false)) 21193 | return false; 21194 | else if (symbol_exists(function_name,false)) 21195 | return false; 21196 | else 21197 | { 21198 | switch (function.rtrn_type) 21199 | { 21200 | case generic_function_t::e_rtrn_scalar : 21201 | return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ? 21202 | local_data().generic_function_store.add(function_name,function) : false; 21203 | 21204 | case generic_function_t::e_rtrn_string : 21205 | return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ? 21206 | local_data().string_function_store.add(function_name,function) : false; 21207 | 21208 | case generic_function_t::e_rtrn_overload : 21209 | return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|:")) ? 21210 | local_data().overload_function_store.add(function_name,function) : false; 21211 | } 21212 | } 21213 | 21214 | return false; 21215 | } 21216 | 21217 | #define exprtk_define_reserved_function(NN) \ 21218 | inline bool add_reserved_function(const std::string& function_name, ff##NN##_functor function) \ 21219 | { \ 21220 | if (!valid()) \ 21221 | { return false; } \ 21222 | if (!valid_symbol(function_name,false)) \ 21223 | { return false; } \ 21224 | if (symbol_exists(function_name,false)) \ 21225 | { return false; } \ 21226 | \ 21227 | exprtk::ifunction<T>* ifunc = new freefunc##NN(function); \ 21228 | \ 21229 | local_data().free_function_list_.push_back(ifunc); \ 21230 | \ 21231 | return add_reserved_function(function_name,(*local_data().free_function_list_.back())); \ 21232 | } \ 21233 | 21234 | exprtk_define_reserved_function(00) exprtk_define_reserved_function(01) 21235 | exprtk_define_reserved_function(02) exprtk_define_reserved_function(03) 21236 | exprtk_define_reserved_function(04) exprtk_define_reserved_function(05) 21237 | exprtk_define_reserved_function(06) exprtk_define_reserved_function(07) 21238 | exprtk_define_reserved_function(08) exprtk_define_reserved_function(09) 21239 | exprtk_define_reserved_function(10) exprtk_define_reserved_function(11) 21240 | exprtk_define_reserved_function(12) exprtk_define_reserved_function(13) 21241 | exprtk_define_reserved_function(14) exprtk_define_reserved_function(15) 21242 | 21243 | #undef exprtk_define_reserved_function 21244 | 21245 | template <std::size_t N> 21246 | inline bool add_vector(const std::string& vector_name, T (&v)[N]) 21247 | { 21248 | if (!valid()) 21249 | return false; 21250 | else if (!valid_symbol(vector_name)) 21251 | return false; 21252 | else if (symbol_exists(vector_name)) 21253 | return false; 21254 | else 21255 | return local_data().vector_store.add(vector_name,v); 21256 | } 21257 | 21258 | inline bool add_vector(const std::string& vector_name, T* v, const std::size_t& v_size) 21259 | { 21260 | if (!valid()) 21261 | return false; 21262 | else if (!valid_symbol(vector_name)) 21263 | return false; 21264 | else if (symbol_exists(vector_name)) 21265 | return false; 21266 | else if (0 == v_size) 21267 | return false; 21268 | else 21269 | return local_data().vector_store.add(vector_name, v, v_size); 21270 | } 21271 | 21272 | template <typename Allocator> 21273 | inline bool add_vector(const std::string& vector_name, std::vector<T,Allocator>& v) 21274 | { 21275 | if (!valid()) 21276 | return false; 21277 | else if (!valid_symbol(vector_name)) 21278 | return false; 21279 | else if (symbol_exists(vector_name)) 21280 | return false; 21281 | else if (0 == v.size()) 21282 | return false; 21283 | else 21284 | return local_data().vector_store.add(vector_name,v); 21285 | } 21286 | 21287 | inline bool add_vector(const std::string& vector_name, exprtk::vector_view<T>& v) 21288 | { 21289 | if (!valid()) 21290 | return false; 21291 | else if (!valid_symbol(vector_name)) 21292 | return false; 21293 | else if (symbol_exists(vector_name)) 21294 | return false; 21295 | else if (0 == v.size()) 21296 | return false; 21297 | else 21298 | return local_data().vector_store.add(vector_name,v); 21299 | } 21300 | 21301 | inline bool remove_variable(const std::string& variable_name, const bool delete_node = true) 21302 | { 21303 | if (!valid()) 21304 | return false; 21305 | else 21306 | return local_data().variable_store.remove(variable_name, delete_node); 21307 | } 21308 | 21309 | #ifndef exprtk_disable_string_capabilities 21310 | inline bool remove_stringvar(const std::string& string_name) 21311 | { 21312 | if (!valid()) 21313 | return false; 21314 | else 21315 | return local_data().stringvar_store.remove(string_name); 21316 | } 21317 | #endif 21318 | 21319 | inline bool remove_function(const std::string& function_name) 21320 | { 21321 | if (!valid()) 21322 | return false; 21323 | else 21324 | return local_data().function_store.remove(function_name); 21325 | } 21326 | 21327 | inline bool remove_vararg_function(const std::string& vararg_function_name) 21328 | { 21329 | if (!valid()) 21330 | return false; 21331 | else 21332 | return local_data().vararg_function_store.remove(vararg_function_name); 21333 | } 21334 | 21335 | inline bool remove_vector(const std::string& vector_name) 21336 | { 21337 | if (!valid()) 21338 | return false; 21339 | else 21340 | return local_data().vector_store.remove(vector_name); 21341 | } 21342 | 21343 | inline bool add_constants() 21344 | { 21345 | return add_pi () && 21346 | add_epsilon () && 21347 | add_infinity() ; 21348 | } 21349 | 21350 | inline bool add_pi() 21351 | { 21352 | const typename details::numeric::details::number_type<T>::type num_type; 21353 | static const T local_pi = details::numeric::details::const_pi_impl<T>(num_type); 21354 | return add_constant("pi",local_pi); 21355 | } 21356 | 21357 | inline bool add_epsilon() 21358 | { 21359 | static const T local_epsilon = details::numeric::details::epsilon_type<T>::value(); 21360 | return add_constant("epsilon",local_epsilon); 21361 | } 21362 | 21363 | inline bool add_infinity() 21364 | { 21365 | static const T local_infinity = std::numeric_limits<T>::infinity(); 21366 | return add_constant("inf",local_infinity); 21367 | } 21368 | 21369 | template <typename Package> 21370 | inline bool add_package(Package& package) 21371 | { 21372 | return package.register_package(*this); 21373 | } 21374 | 21375 | template <typename Allocator, 21376 | template <typename, typename> class Sequence> 21377 | inline std::size_t get_variable_list(Sequence<std::pair<std::string,T>,Allocator>& vlist) const 21378 | { 21379 | if (!valid()) 21380 | return 0; 21381 | else 21382 | return local_data().variable_store.get_list(vlist); 21383 | } 21384 | 21385 | template <typename Allocator, 21386 | template <typename, typename> class Sequence> 21387 | inline std::size_t get_variable_list(Sequence<std::string,Allocator>& vlist) const 21388 | { 21389 | if (!valid()) 21390 | return 0; 21391 | else 21392 | return local_data().variable_store.get_list(vlist); 21393 | } 21394 | 21395 | #ifndef exprtk_disable_string_capabilities 21396 | template <typename Allocator, 21397 | template <typename, typename> class Sequence> 21398 | inline std::size_t get_stringvar_list(Sequence<std::pair<std::string,std::string>,Allocator>& svlist) const 21399 | { 21400 | if (!valid()) 21401 | return 0; 21402 | else 21403 | return local_data().stringvar_store.get_list(svlist); 21404 | } 21405 | 21406 | template <typename Allocator, 21407 | template <typename, typename> class Sequence> 21408 | inline std::size_t get_stringvar_list(Sequence<std::string,Allocator>& svlist) const 21409 | { 21410 | if (!valid()) 21411 | return 0; 21412 | else 21413 | return local_data().stringvar_store.get_list(svlist); 21414 | } 21415 | #endif 21416 | 21417 | template <typename Allocator, 21418 | template <typename, typename> class Sequence> 21419 | inline std::size_t get_vector_list(Sequence<std::string,Allocator>& vec_list) const 21420 | { 21421 | if (!valid()) 21422 | return 0; 21423 | else 21424 | return local_data().vector_store.get_list(vec_list); 21425 | } 21426 | 21427 | template <typename Allocator, 21428 | template <typename, typename> class Sequence> 21429 | inline std::size_t get_function_list(Sequence<std::string,Allocator>& function_list) const 21430 | { 21431 | if (!valid()) 21432 | return 0; 21433 | 21434 | std::vector<std::string> function_names; 21435 | std::size_t count = 0; 21436 | 21437 | count += local_data().function_store .get_list(function_names); 21438 | count += local_data().vararg_function_store .get_list(function_names); 21439 | count += local_data().generic_function_store .get_list(function_names); 21440 | count += local_data().string_function_store .get_list(function_names); 21441 | count += local_data().overload_function_store.get_list(function_names); 21442 | 21443 | std::set<std::string> function_set; 21444 | 21445 | for (std::size_t i = 0; i < function_names.size(); ++i) 21446 | { 21447 | function_set.insert(function_names[i]); 21448 | } 21449 | 21450 | std::copy(function_set.begin(), function_set.end(), 21451 | std::back_inserter(function_list)); 21452 | 21453 | return count; 21454 | } 21455 | 21456 | inline std::vector<std::string> get_function_list() const 21457 | { 21458 | std::vector<std::string> result; 21459 | get_function_list(result); 21460 | return result; 21461 | } 21462 | 21463 | inline bool symbol_exists(const std::string& symbol_name, const bool check_reserved_symb = true) const 21464 | { 21465 | /* 21466 | Function will return true if symbol_name exists as either a 21467 | reserved symbol, variable, stringvar, vector or function name 21468 | in any of the type stores. 21469 | */ 21470 | if (!valid()) 21471 | return false; 21472 | else if (local_data().variable_store.symbol_exists(symbol_name)) 21473 | return true; 21474 | #ifndef exprtk_disable_string_capabilities 21475 | else if (local_data().stringvar_store.symbol_exists(symbol_name)) 21476 | return true; 21477 | #endif 21478 | else if (local_data().vector_store.symbol_exists(symbol_name)) 21479 | return true; 21480 | else if (local_data().function_store.symbol_exists(symbol_name)) 21481 | return true; 21482 | else if (check_reserved_symb && local_data().is_reserved_symbol(symbol_name)) 21483 | return true; 21484 | else 21485 | return false; 21486 | } 21487 | 21488 | inline bool is_variable(const std::string& variable_name) const 21489 | { 21490 | if (!valid()) 21491 | return false; 21492 | else 21493 | return local_data().variable_store.symbol_exists(variable_name); 21494 | } 21495 | 21496 | #ifndef exprtk_disable_string_capabilities 21497 | inline bool is_stringvar(const std::string& stringvar_name) const 21498 | { 21499 | if (!valid()) 21500 | return false; 21501 | else 21502 | return local_data().stringvar_store.symbol_exists(stringvar_name); 21503 | } 21504 | 21505 | inline bool is_conststr_stringvar(const std::string& symbol_name) const 21506 | { 21507 | if (!valid()) 21508 | return false; 21509 | else if (!valid_symbol(symbol_name)) 21510 | return false; 21511 | else if (!local_data().stringvar_store.symbol_exists(symbol_name)) 21512 | return false; 21513 | 21514 | return ( 21515 | local_data().stringvar_store.symbol_exists(symbol_name) || 21516 | local_data().stringvar_store.is_constant (symbol_name) 21517 | ); 21518 | } 21519 | #endif 21520 | 21521 | inline bool is_function(const std::string& function_name) const 21522 | { 21523 | if (!valid()) 21524 | return false; 21525 | else 21526 | return local_data().function_store.symbol_exists(function_name); 21527 | } 21528 | 21529 | inline bool is_vararg_function(const std::string& vararg_function_name) const 21530 | { 21531 | if (!valid()) 21532 | return false; 21533 | else 21534 | return local_data().vararg_function_store.symbol_exists(vararg_function_name); 21535 | } 21536 | 21537 | inline bool is_vector(const std::string& vector_name) const 21538 | { 21539 | if (!valid()) 21540 | return false; 21541 | else 21542 | return local_data().vector_store.symbol_exists(vector_name); 21543 | } 21544 | 21545 | inline std::string get_variable_name(const expression_ptr& ptr) const 21546 | { 21547 | return local_data().variable_store.entity_name(ptr); 21548 | } 21549 | 21550 | inline std::string get_vector_name(const vector_holder_ptr& ptr) const 21551 | { 21552 | return local_data().vector_store.entity_name(ptr); 21553 | } 21554 | 21555 | #ifndef exprtk_disable_string_capabilities 21556 | inline std::string get_stringvar_name(const expression_ptr& ptr) const 21557 | { 21558 | return local_data().stringvar_store.entity_name(ptr); 21559 | } 21560 | 21561 | inline std::string get_conststr_stringvar_name(const expression_ptr& ptr) const 21562 | { 21563 | return local_data().stringvar_store.entity_name(ptr); 21564 | } 21565 | #endif 21566 | 21567 | inline bool valid() const 21568 | { 21569 | // Symbol table sanity check. 21570 | return control_block_ && control_block_->data_; 21571 | } 21572 | 21573 | inline void load_from(const symbol_table<T>& st) 21574 | { 21575 | { 21576 | std::vector<std::string> name_list; 21577 | 21578 | st.local_data().function_store.get_list(name_list); 21579 | 21580 | if (!name_list.empty()) 21581 | { 21582 | for (std::size_t i = 0; i < name_list.size(); ++i) 21583 | { 21584 | exprtk::ifunction<T>& ifunc = *st.get_function(name_list[i]); 21585 | add_function(name_list[i],ifunc); 21586 | } 21587 | } 21588 | } 21589 | 21590 | { 21591 | std::vector<std::string> name_list; 21592 | 21593 | st.local_data().vararg_function_store.get_list(name_list); 21594 | 21595 | if (!name_list.empty()) 21596 | { 21597 | for (std::size_t i = 0; i < name_list.size(); ++i) 21598 | { 21599 | exprtk::ivararg_function<T>& ivafunc = *st.get_vararg_function(name_list[i]); 21600 | add_function(name_list[i],ivafunc); 21601 | } 21602 | } 21603 | } 21604 | 21605 | { 21606 | std::vector<std::string> name_list; 21607 | 21608 | st.local_data().generic_function_store.get_list(name_list); 21609 | 21610 | if (!name_list.empty()) 21611 | { 21612 | for (std::size_t i = 0; i < name_list.size(); ++i) 21613 | { 21614 | exprtk::igeneric_function<T>& ifunc = *st.get_generic_function(name_list[i]); 21615 | add_function(name_list[i],ifunc); 21616 | } 21617 | } 21618 | } 21619 | 21620 | { 21621 | std::vector<std::string> name_list; 21622 | 21623 | st.local_data().string_function_store.get_list(name_list); 21624 | 21625 | if (!name_list.empty()) 21626 | { 21627 | for (std::size_t i = 0; i < name_list.size(); ++i) 21628 | { 21629 | exprtk::igeneric_function<T>& ifunc = *st.get_string_function(name_list[i]); 21630 | add_function(name_list[i],ifunc); 21631 | } 21632 | } 21633 | } 21634 | 21635 | { 21636 | std::vector<std::string> name_list; 21637 | 21638 | st.local_data().overload_function_store.get_list(name_list); 21639 | 21640 | if (!name_list.empty()) 21641 | { 21642 | for (std::size_t i = 0; i < name_list.size(); ++i) 21643 | { 21644 | exprtk::igeneric_function<T>& ifunc = *st.get_overload_function(name_list[i]); 21645 | add_function(name_list[i],ifunc); 21646 | } 21647 | } 21648 | } 21649 | } 21650 | 21651 | inline void load_variables_from(const symbol_table<T>& st) 21652 | { 21653 | std::vector<std::string> name_list; 21654 | 21655 | st.local_data().variable_store.get_list(name_list); 21656 | 21657 | if (!name_list.empty()) 21658 | { 21659 | for (std::size_t i = 0; i < name_list.size(); ++i) 21660 | { 21661 | T& variable = st.get_variable(name_list[i])->ref(); 21662 | add_variable(name_list[i], variable); 21663 | } 21664 | } 21665 | } 21666 | 21667 | inline void load_vectors_from(const symbol_table<T>& st) 21668 | { 21669 | std::vector<std::string> name_list; 21670 | 21671 | st.local_data().vector_store.get_list(name_list); 21672 | 21673 | if (!name_list.empty()) 21674 | { 21675 | for (std::size_t i = 0; i < name_list.size(); ++i) 21676 | { 21677 | vector_holder_t& vecholder = *st.get_vector(name_list[i]); 21678 | add_vector(name_list[i], vecholder.data(), vecholder.size()); 21679 | } 21680 | } 21681 | } 21682 | 21683 | private: 21684 | 21685 | inline bool valid_symbol(const std::string& symbol, const bool check_reserved_symb = true) const 21686 | { 21687 | if (symbol.empty()) 21688 | return false; 21689 | else if (!details::is_letter(symbol[0])) 21690 | return false; 21691 | else if (symbol.size() > 1) 21692 | { 21693 | for (std::size_t i = 1; i < symbol.size(); ++i) 21694 | { 21695 | if ( 21696 | !details::is_letter_or_digit(symbol[i]) && 21697 | ('_' != symbol[i]) 21698 | ) 21699 | { 21700 | if ((i < (symbol.size() - 1)) && ('.' == symbol[i])) 21701 | continue; 21702 | else 21703 | return false; 21704 | } 21705 | } 21706 | } 21707 | 21708 | return (check_reserved_symb) ? (!local_data().is_reserved_symbol(symbol)) : true; 21709 | } 21710 | 21711 | inline bool valid_function(const std::string& symbol) const 21712 | { 21713 | if (symbol.empty()) 21714 | return false; 21715 | else if (!details::is_letter(symbol[0])) 21716 | return false; 21717 | else if (symbol.size() > 1) 21718 | { 21719 | for (std::size_t i = 1; i < symbol.size(); ++i) 21720 | { 21721 | if ( 21722 | !details::is_letter_or_digit(symbol[i]) && 21723 | ('_' != symbol[i]) 21724 | ) 21725 | { 21726 | if ((i < (symbol.size() - 1)) && ('.' == symbol[i])) 21727 | continue; 21728 | else 21729 | return false; 21730 | } 21731 | } 21732 | } 21733 | 21734 | return true; 21735 | } 21736 | 21737 | typedef typename control_block::st_data local_data_t; 21738 | 21739 | inline local_data_t& local_data() 21740 | { 21741 | return *(control_block_->data_); 21742 | } 21743 | 21744 | inline const local_data_t& local_data() const 21745 | { 21746 | return *(control_block_->data_); 21747 | } 21748 | 21749 | control_block* control_block_; 21750 | 21751 | friend class parser<T>; 21752 | }; // class symbol_table 21753 | 21754 | template <typename T> 21755 | class function_compositor; 21756 | 21757 | template <typename T> 21758 | class expression 21759 | { 21760 | private: 21761 | 21762 | typedef details::expression_node<T>* expression_ptr; 21763 | typedef details::vector_holder<T>* vector_holder_ptr; 21764 | typedef std::vector<symbol_table<T> > symtab_list_t; 21765 | 21766 | struct control_block 21767 | { 21768 | enum data_type 21769 | { 21770 | e_unknown , 21771 | e_expr , 21772 | e_vecholder, 21773 | e_data , 21774 | e_vecdata , 21775 | e_string 21776 | }; 21777 | 21778 | static std::string to_str(data_type dt) 21779 | { 21780 | switch (dt) 21781 | { 21782 | case e_unknown : return "e_unknown " 21783 | case e_expr : return "e_expr" ; 21784 | case e_vecholder : return "e_vecholder" 21785 | case e_data : return "e_data" ; 21786 | case e_vecdata : return "e_vecdata" ; 21787 | case e_string : return "e_string" ; 21788 | } 21789 | 21790 | return "" 21791 | } 21792 | 21793 | struct data_pack 21794 | { 21795 | data_pack() 21796 | : pointer(0) 21797 | , type(e_unknown) 21798 | , size(0) 21799 | {} 21800 | 21801 | data_pack(void* ptr, const data_type dt, const std::size_t sz = 0) 21802 | : pointer(ptr) 21803 | , type(dt) 21804 | , size(sz) 21805 | {} 21806 | 21807 | void* pointer; 21808 | data_type type; 21809 | std::size_t size; 21810 | }; 21811 | 21812 | typedef std::vector<data_pack> local_data_list_t; 21813 | typedef results_context<T> results_context_t; 21814 | typedef control_block* cntrl_blck_ptr_t; 21815 | 21816 | control_block() 21817 | : ref_count(0) 21818 | , expr (0) 21819 | , results (0) 21820 | , retinv_null(false) 21821 | , return_invoked(&retinv_null) 21822 | {} 21823 | 21824 | explicit control_block(expression_ptr e) 21825 | : ref_count(1) 21826 | , expr (e) 21827 | , results (0) 21828 | , retinv_null(false) 21829 | , return_invoked(&retinv_null) 21830 | {} 21831 | 21832 | ~control_block() 21833 | { 21834 | if (expr && details::branch_deletable(expr)) 21835 | { 21836 | destroy_node(expr); 21837 | } 21838 | 21839 | if (!local_data_list.empty()) 21840 | { 21841 | for (std::size_t i = 0; i < local_data_list.size(); ++i) 21842 | { 21843 | switch (local_data_list[i].type) 21844 | { 21845 | case e_expr : delete reinterpret_cast<expression_ptr>(local_data_list[i].pointer); 21846 | break; 21847 | 21848 | case e_vecholder : delete reinterpret_cast<vector_holder_ptr>(local_data_list[i].pointer); 21849 | break; 21850 | 21851 | case e_data : delete reinterpret_cast<T*>(local_data_list[i].pointer); 21852 | break; 21853 | 21854 | case e_vecdata : delete [] reinterpret_cast<T*>(local_data_list[i].pointer); 21855 | break; 21856 | 21857 | case e_string : delete reinterpret_cast<std::string*>(local_data_list[i].pointer); 21858 | break; 21859 | 21860 | default : break; 21861 | } 21862 | } 21863 | } 21864 | 21865 | if (results) 21866 | { 21867 | delete results; 21868 | } 21869 | } 21870 | 21871 | static inline cntrl_blck_ptr_t create(expression_ptr e) 21872 | { 21873 | return new control_block(e); 21874 | } 21875 | 21876 | static inline void destroy(cntrl_blck_ptr_t& cntrl_blck) 21877 | { 21878 | if (cntrl_blck) 21879 | { 21880 | if ( 21881 | (0 != cntrl_blck->ref_count) && 21882 | (0 == --cntrl_blck->ref_count) 21883 | ) 21884 | { 21885 | delete cntrl_blck; 21886 | } 21887 | 21888 | cntrl_blck = 0; 21889 | } 21890 | } 21891 | 21892 | std::size_t ref_count; 21893 | expression_ptr expr; 21894 | local_data_list_t local_data_list; 21895 | results_context_t* results; 21896 | bool retinv_null; 21897 | bool* return_invoked; 21898 | 21899 | friend class function_compositor<T>; 21900 | }; 21901 | 21902 | public: 21903 | 21904 | expression() 21905 | : control_block_(0) 21906 | { 21907 | set_expression(new details::null_node<T>()); 21908 | } 21909 | 21910 | expression(const expression<T>& e) 21911 | : control_block_ (e.control_block_ ) 21912 | , symbol_table_list_(e.symbol_table_list_) 21913 | { 21914 | control_block_->ref_count++; 21915 | } 21916 | 21917 | explicit expression(const symbol_table<T>& symbol_table) 21918 | : control_block_(0) 21919 | { 21920 | set_expression(new details::null_node<T>()); 21921 | symbol_table_list_.push_back(symbol_table); 21922 | } 21923 | 21924 | inline expression<T>& operator=(const expression<T>& e) 21925 | { 21926 | if (this != &e) 21927 | { 21928 | if (control_block_) 21929 | { 21930 | if ( 21931 | (0 != control_block_->ref_count) && 21932 | (0 == --control_block_->ref_count) 21933 | ) 21934 | { 21935 | delete control_block_; 21936 | } 21937 | 21938 | control_block_ = 0; 21939 | } 21940 | 21941 | control_block_ = e.control_block_; 21942 | control_block_->ref_count++; 21943 | symbol_table_list_ = e.symbol_table_list_; 21944 | } 21945 | 21946 | return *this; 21947 | } 21948 | 21949 | inline bool operator==(const expression<T>& e) const 21950 | { 21951 | return (this == &e); 21952 | } 21953 | 21954 | inline bool operator!() const 21955 | { 21956 | return ( 21957 | (0 == control_block_ ) || 21958 | (0 == control_block_->expr) 21959 | ); 21960 | } 21961 | 21962 | inline expression<T>& release() 21963 | { 21964 | exprtk::details::dump_ptr("expression::release", this); 21965 | control_block::destroy(control_block_); 21966 | 21967 | return (*this); 21968 | } 21969 | 21970 | ~expression() 21971 | { 21972 | control_block::destroy(control_block_); 21973 | } 21974 | 21975 | inline T value() const 21976 | { 21977 | assert(control_block_ ); 21978 | assert(control_block_->expr); 21979 | 21980 | return control_block_->expr->value(); 21981 | } 21982 | 21983 | inline T operator() () const 21984 | { 21985 | return value(); 21986 | } 21987 | 21988 | inline operator T() const 21989 | { 21990 | return value(); 21991 | } 21992 | 21993 | inline operator bool() const 21994 | { 21995 | return details::is_true(value()); 21996 | } 21997 | 21998 | inline bool register_symbol_table(symbol_table<T>& st) 21999 | { 22000 | for (std::size_t i = 0; i < symbol_table_list_.size(); ++i) 22001 | { 22002 | if (st == symbol_table_list_[i]) 22003 | { 22004 | return false; 22005 | } 22006 | } 22007 | 22008 | symbol_table_list_.push_back(st); 22009 | return true; 22010 | } 22011 | 22012 | inline const symbol_table<T>& get_symbol_table(const std::size_t& index = 0) const 22013 | { 22014 | return symbol_table_list_[index]; 22015 | } 22016 | 22017 | inline symbol_table<T>& get_symbol_table(const std::size_t& index = 0) 22018 | { 22019 | return symbol_table_list_[index]; 22020 | } 22021 | 22022 | std::size_t num_symbol_tables() const 22023 | { 22024 | return symbol_table_list_.size(); 22025 | } 22026 | 22027 | typedef results_context<T> results_context_t; 22028 | 22029 | inline const results_context_t& results() const 22030 | { 22031 | if (control_block_->results) 22032 | return (*control_block_->results); 22033 | else 22034 | { 22035 | static const results_context_t null_results; 22036 | return null_results; 22037 | } 22038 | } 22039 | 22040 | inline bool return_invoked() const 22041 | { 22042 | assert(control_block_); 22043 | 22044 | return control_block_ && 22045 | control_block_->return_invoked && 22046 | (*control_block_->return_invoked); 22047 | } 22048 | 22049 | private: 22050 | 22051 | inline symtab_list_t get_symbol_table_list() const 22052 | { 22053 | return symbol_table_list_; 22054 | } 22055 | 22056 | inline void set_expression(const expression_ptr expr) 22057 | { 22058 | if (expr) 22059 | { 22060 | if (control_block_) 22061 | { 22062 | if (0 == --control_block_->ref_count) 22063 | { 22064 | delete control_block_; 22065 | } 22066 | } 22067 | 22068 | control_block_ = control_block::create(expr); 22069 | } 22070 | } 22071 | 22072 | inline void register_local_var(expression_ptr expr) 22073 | { 22074 | if (expr) 22075 | { 22076 | if (control_block_) 22077 | { 22078 | control_block_-> 22079 | local_data_list.push_back( 22080 | typename expression<T>::control_block:: 22081 | data_pack(reinterpret_cast<void*>(expr), 22082 | control_block::e_expr)); 22083 | } 22084 | } 22085 | } 22086 | 22087 | inline void register_local_var(vector_holder_ptr vec_holder) 22088 | { 22089 | if (vec_holder) 22090 | { 22091 | if (control_block_) 22092 | { 22093 | control_block_-> 22094 | local_data_list.push_back( 22095 | typename expression<T>::control_block:: 22096 | data_pack(reinterpret_cast<void*>(vec_holder), 22097 | control_block::e_vecholder)); 22098 | } 22099 | } 22100 | } 22101 | 22102 | inline void register_local_data(void* data, const std::size_t& size = 0, const std::size_t data_mode = 0) 22103 | { 22104 | if (data) 22105 | { 22106 | if (control_block_) 22107 | { 22108 | typename control_block::data_type dt = control_block::e_data; 22109 | 22110 | switch (data_mode) 22111 | { 22112 | case 0 : dt = control_block::e_data; break; 22113 | case 1 : dt = control_block::e_vecdata; break; 22114 | case 2 : dt = control_block::e_string; break; 22115 | } 22116 | 22117 | control_block_-> 22118 | local_data_list.push_back( 22119 | typename expression<T>::control_block:: 22120 | data_pack(reinterpret_cast<void*>(data), dt, size)); 22121 | } 22122 | } 22123 | } 22124 | 22125 | inline const typename control_block::local_data_list_t& local_data_list() 22126 | { 22127 | if (control_block_) 22128 | { 22129 | return control_block_->local_data_list; 22130 | } 22131 | else 22132 | { 22133 | static typename control_block::local_data_list_t null_local_data_list; 22134 | return null_local_data_list; 22135 | } 22136 | } 22137 | 22138 | inline void register_return_results(results_context_t* rc) 22139 | { 22140 | if (control_block_ && rc) 22141 | { 22142 | control_block_->results = rc; 22143 | } 22144 | } 22145 | 22146 | inline void set_retinvk(bool* retinvk_ptr) 22147 | { 22148 | if (control_block_) 22149 | { 22150 | control_block_->return_invoked = retinvk_ptr; 22151 | } 22152 | } 22153 | 22154 | control_block* control_block_; 22155 | symtab_list_t symbol_table_list_; 22156 | 22157 | friend class parser<T>; 22158 | friend class expression_helper<T>; 22159 | friend class function_compositor<T>; 22160 | template <typename TT> 22161 | friend bool is_valid(const expression<TT>& expr); 22162 | }; // class expression 22163 | 22164 | template <typename T> 22165 | class expression_helper 22166 | { 22167 | public: 22168 | 22169 | enum node_types 22170 | { 22171 | e_literal, 22172 | e_variable, 22173 | e_string, 22174 | e_unary, 22175 | e_binary, 22176 | e_function, 22177 | e_vararg, 22178 | e_null, 22179 | e_assert, 22180 | e_sf3ext, 22181 | e_sf4ext 22182 | }; 22183 | 22184 | static inline bool is_literal(const expression<T>& expr) 22185 | { 22186 | return expr.control_block_ && details::is_literal_node(expr.control_block_->expr); 22187 | } 22188 | 22189 | static inline bool is_variable(const expression<T>& expr) 22190 | { 22191 | return expr.control_block_ && details::is_variable_node(expr.control_block_->expr); 22192 | } 22193 | 22194 | static inline bool is_string(const expression<T>& expr) 22195 | { 22196 | return expr.control_block_ && details::is_generally_string_node(expr.control_block_->expr); 22197 | } 22198 | 22199 | static inline bool is_unary(const expression<T>& expr) 22200 | { 22201 | return expr.control_block_ && details::is_unary_node(expr.control_block_->expr); 22202 | } 22203 | 22204 | static inline bool is_binary(const expression<T>& expr) 22205 | { 22206 | return expr.control_block_ && details::is_binary_node(expr.control_block_->expr); 22207 | } 22208 | 22209 | static inline bool is_function(const expression<T>& expr) 22210 | { 22211 | return expr.control_block_ && details::is_function(expr.control_block_->expr); 22212 | } 22213 | 22214 | static inline bool is_vararg(const expression<T>& expr) 22215 | { 22216 | return expr.control_block_ && details::is_vararg_node(expr.control_block_->expr); 22217 | } 22218 | 22219 | static inline bool is_null(const expression<T>& expr) 22220 | { 22221 | return expr.control_block_ && details::is_null_node(expr.control_block_->expr); 22222 | } 22223 | 22224 | static inline bool is_assert(const expression<T>& expr) 22225 | { 22226 | return expr.control_block_ && details::is_assert_node(expr.control_block_->expr); 22227 | } 22228 | 22229 | static inline bool is_sf3ext(const expression<T>& expr) 22230 | { 22231 | return expr.control_block_ && details::is_sf3ext_node(expr.control_block_->expr); 22232 | } 22233 | 22234 | static inline bool is_sf4ext(const expression<T>& expr) 22235 | { 22236 | return expr.control_block_ && details::is_sf4ext_node(expr.control_block_->expr); 22237 | } 22238 | 22239 | static inline bool is_type(const expression<T>& expr, const node_types node_type) 22240 | { 22241 | if (0 == expr.control_block_) 22242 | { 22243 | return false; 22244 | } 22245 | 22246 | switch (node_type) 22247 | { 22248 | case e_literal : return is_literal_node(expr); 22249 | case e_variable : return is_variable (expr); 22250 | case e_string : return is_string (expr); 22251 | case e_unary : return is_unary (expr); 22252 | case e_binary : return is_binary (expr); 22253 | case e_function : return is_function (expr); 22254 | case e_null : return is_null (expr); 22255 | case e_assert : return is_assert (expr); 22256 | case e_sf3ext : return is_sf3ext (expr); 22257 | case e_sf4ext : return is_sf4ext (expr); 22258 | }; 22259 | 22260 | return false; 22261 | } 22262 | 22263 | static inline bool match_type_sequence(const expression<T>& expr, const std::vector<node_types>& type_seq) 22264 | { 22265 | if ((0 == expr.control_block_) || !is_vararg(expr)) 22266 | { 22267 | return false; 22268 | } 22269 | 22270 | typedef details::vararg_node<T, exprtk::details::vararg_multi_op<T> > mo_vararg_t; 22271 | 22272 | mo_vararg_t* vnode = dynamic_cast<mo_vararg_t*>(expr.control_block_->expr); 22273 | 22274 | if ( 22275 | (0 == vnode) || 22276 | type_seq.empty() || 22277 | (vnode->size() < type_seq.size()) 22278 | ) 22279 | { 22280 | return false; 22281 | } 22282 | 22283 | for (std::size_t i = 0; i < type_seq.size(); ++i) 22284 | { 22285 | assert((*vnode)[i]); 22286 | 22287 | switch (type_seq[i]) 22288 | { 22289 | case e_literal : { if (details::is_literal_node ((*vnode)[i])) continue; } break; 22290 | case e_variable : { if (details::is_variable_node ((*vnode)[i])) continue; } break; 22291 | case e_string : { if (details::is_generally_string_node((*vnode)[i])) continue; } break; 22292 | case e_unary : { if (details::is_unary_node ((*vnode)[i])) continue; } break; 22293 | case e_binary : { if (details::is_binary_node ((*vnode)[i])) continue; } break; 22294 | case e_function : { if (details::is_function ((*vnode)[i])) continue; } break; 22295 | case e_null : { if (details::is_null_node ((*vnode)[i])) continue; } break; 22296 | case e_assert : { if (details::is_assert_node ((*vnode)[i])) continue; } break; 22297 | case e_sf3ext : { if (details::is_sf3ext_node ((*vnode)[i])) continue; } break; 22298 | case e_sf4ext : { if (details::is_sf4ext_node ((*vnode)[i])) continue; } break; 22299 | case e_vararg : break; 22300 | } 22301 | 22302 | return false; 22303 | } 22304 | 22305 | return true; 22306 | } 22307 | }; 22308 | 22309 | template <typename T> 22310 | inline bool is_valid(const expression<T>& expr) 22311 | { 22312 | return expr.control_block_ && !expression_helper<T>::is_null(expr); 22313 | } 22314 | 22315 | namespace parser_error 22316 | { 22317 | enum error_mode 22318 | { 22319 | e_unknown = 0, 22320 | e_syntax = 1, 22321 | e_token = 2, 22322 | e_numeric = 4, 22323 | e_symtab = 5, 22324 | e_lexer = 6, 22325 | e_synthesis = 7, 22326 | e_helper = 8, 22327 | e_parser = 9 22328 | }; 22329 | 22330 | struct type 22331 | { 22332 | type() 22333 | : mode(parser_error::e_unknown) 22334 | , line_no (0) 22335 | , column_no(0) 22336 | {} 22337 | 22338 | lexer::token token; 22339 | error_mode mode; 22340 | std::string diagnostic; 22341 | std::string src_location; 22342 | std::string error_line; 22343 | std::size_t line_no; 22344 | std::size_t column_no; 22345 | }; 22346 | 22347 | inline type make_error(const error_mode mode, 22348 | const std::string& diagnostic = "", 22349 | const std::string& src_location = "") 22350 | { 22351 | type t; 22352 | t.mode = mode; 22353 | t.token.type = lexer::token::e_error; 22354 | t.diagnostic = diagnostic; 22355 | t.src_location = src_location; 22356 | exprtk_debug(("%s\n", diagnostic .c_str())); 22357 | return t; 22358 | } 22359 | 22360 | inline type make_error(const error_mode mode, 22361 | const lexer::token& tk, 22362 | const std::string& diagnostic = "", 22363 | const std::string& src_location = "") 22364 | { 22365 | type t; 22366 | t.mode = mode; 22367 | t.token = tk; 22368 | t.diagnostic = diagnostic; 22369 | t.src_location = src_location; 22370 | exprtk_debug(("%s\n", diagnostic .c_str())); 22371 | return t; 22372 | } 22373 | 22374 | inline std::string to_str(error_mode mode) 22375 | { 22376 | switch (mode) 22377 | { 22378 | case e_unknown : return std::string("Unknown Error"); 22379 | case e_syntax : return std::string("Syntax Error" ); 22380 | case e_token : return std::string("Token Error" ); 22381 | case e_numeric : return std::string("Numeric Error"); 22382 | case e_symtab : return std::string("Symbol Error" ); 22383 | case e_lexer : return std::string("Lexer Error" ); 22384 | case e_helper : return std::string("Helper Error" ); 22385 | case e_parser : return std::string("Parser Error" ); 22386 | default : return std::string("Unknown Error"); 22387 | } 22388 | } 22389 | 22390 | inline bool update_error(type& error, const std::string& expression) 22391 | { 22392 | if ( 22393 | expression.empty() || 22394 | (error.token.position > expression.size()) || 22395 | (std::numeric_limits<std::size_t>::max() == error.token.position) 22396 | ) 22397 | { 22398 | return false; 22399 | } 22400 | 22401 | std::size_t error_line_start = 0; 22402 | 22403 | for (std::size_t i = error.token.position; i > 0; --i) 22404 | { 22405 | const details::char_t c = expression[i]; 22406 | 22407 | if (('\n' == c) || ('\r' == c)) 22408 | { 22409 | error_line_start = i + 1; 22410 | break; 22411 | } 22412 | } 22413 | 22414 | std::size_t next_nl_position = std::min(expression.size(), 22415 | expression.find_first_of('\n',error.token.position + 1)); 22416 | 22417 | error.column_no = error.token.position - error_line_start; 22418 | error.error_line = expression.substr(error_line_start, 22419 | next_nl_position - error_line_start); 22420 | 22421 | error.line_no = 0; 22422 | 22423 | for (std::size_t i = 0; i < next_nl_position; ++i) 22424 | { 22425 | if ('\n' == expression[i]) 22426 | ++error.line_no; 22427 | } 22428 | 22429 | return true; 22430 | } 22431 | 22432 | inline void dump_error(const type& error) 22433 | { 22434 | printf("Position: %02d Type: [%s] Msg: %s\n", 22435 | static_cast<int>(error.token.position), 22436 | exprtk::parser_error::to_str(error.mode).c_str(), 22437 | error.diagnostic.c_str()); 22438 | } 22439 | } 22440 | 22441 | namespace details 22442 | { 22443 | template <typename Parser> 22444 | inline void disable_type_checking(Parser& p) 22445 | { 22446 | p.state_.type_check_enabled = false; 22447 | } 22448 | } 22449 | 22450 | template <typename T> 22451 | class parser : public lexer::parser_helper 22452 | { 22453 | private: 22454 | 22455 | enum precedence_level 22456 | { 22457 | e_level00, e_level01, e_level02, e_level03, e_level04, 22458 | e_level05, e_level06, e_level07, e_level08, e_level09, 22459 | e_level10, e_level11, e_level12, e_level13, e_level14 22460 | }; 22461 | 22462 | typedef const T& cref_t; 22463 | typedef const T const_t; 22464 | typedef ifunction<T> F; 22465 | typedef ivararg_function<T> VAF; 22466 | typedef igeneric_function<T> GF; 22467 | typedef ifunction<T> ifunction_t; 22468 | typedef ivararg_function<T> ivararg_function_t; 22469 | typedef igeneric_function<T> igeneric_function_t; 22470 | typedef details::expression_node<T> expression_node_t; 22471 | typedef details::literal_node<T> literal_node_t; 22472 | typedef details::unary_node<T> unary_node_t; 22473 | typedef details::binary_node<T> binary_node_t; 22474 | typedef details::trinary_node<T> trinary_node_t; 22475 | typedef details::quaternary_node<T> quaternary_node_t; 22476 | typedef details::conditional_node<T> conditional_node_t; 22477 | typedef details::cons_conditional_node<T> cons_conditional_node_t; 22478 | typedef details::while_loop_node<T> while_loop_node_t; 22479 | typedef details::repeat_until_loop_node<T> repeat_until_loop_node_t; 22480 | typedef details::for_loop_node<T> for_loop_node_t; 22481 | typedef details::while_loop_rtc_node<T> while_loop_rtc_node_t; 22482 | typedef details::repeat_until_loop_rtc_node<T> repeat_until_loop_rtc_node_t; 22483 | typedef details::for_loop_rtc_node<T> for_loop_rtc_node_t; 22484 | #ifndef exprtk_disable_break_continue 22485 | typedef details::while_loop_bc_node<T> while_loop_bc_node_t; 22486 | typedef details::repeat_until_loop_bc_node<T> repeat_until_loop_bc_node_t; 22487 | typedef details::for_loop_bc_node<T> for_loop_bc_node_t; 22488 | typedef details::while_loop_bc_rtc_node<T> while_loop_bc_rtc_node_t; 22489 | typedef details::repeat_until_loop_bc_rtc_node<T> repeat_until_loop_bc_rtc_node_t; 22490 | typedef details::for_loop_bc_rtc_node<T> for_loop_bc_rtc_node_t; 22491 | #endif 22492 | typedef details::switch_node<T> switch_node_t; 22493 | typedef details::variable_node<T> variable_node_t; 22494 | typedef details::vector_elem_node<T> vector_elem_node_t; 22495 | typedef details::vector_celem_node<T> vector_celem_node_t; 22496 | typedef details::vector_elem_rtc_node<T> vector_elem_rtc_node_t; 22497 | typedef details::vector_celem_rtc_node<T> vector_celem_rtc_node_t; 22498 | typedef details::rebasevector_elem_node<T> rebasevector_elem_node_t; 22499 | typedef details::rebasevector_celem_node<T> rebasevector_celem_node_t; 22500 | typedef details::rebasevector_elem_rtc_node<T> rebasevector_elem_rtc_node_t; 22501 | typedef details::rebasevector_celem_rtc_node<T> rebasevector_celem_rtc_node_t; 22502 | typedef details::vector_node<T> vector_node_t; 22503 | typedef details::vector_size_node<T> vector_size_node_t; 22504 | typedef details::range_pack<T> range_t; 22505 | #ifndef exprtk_disable_string_capabilities 22506 | typedef details::stringvar_node<T> stringvar_node_t; 22507 | typedef details::string_literal_node<T> string_literal_node_t; 22508 | typedef details::string_range_node<T> string_range_node_t; 22509 | typedef details::const_string_range_node<T> const_string_range_node_t; 22510 | typedef details::generic_string_range_node<T> generic_string_range_node_t; 22511 | typedef details::string_concat_node<T> string_concat_node_t; 22512 | typedef details::assignment_string_node<T> assignment_string_node_t; 22513 | typedef details::assignment_string_range_node<T> assignment_string_range_node_t; 22514 | typedef details::conditional_string_node<T> conditional_string_node_t; 22515 | typedef details::cons_conditional_str_node<T> cons_conditional_str_node_t; 22516 | #endif 22517 | typedef details::assignment_node<T> assignment_node_t; 22518 | typedef details::assignment_vec_elem_node<T> assignment_vec_elem_node_t; 22519 | typedef details::assignment_vec_elem_rtc_node<T> assignment_vec_elem_rtc_node_t; 22520 | typedef details::assignment_rebasevec_elem_node<T> assignment_rebasevec_elem_node_t; 22521 | typedef details::assignment_rebasevec_elem_rtc_node<T> assignment_rebasevec_elem_rtc_node_t; 22522 | typedef details::assignment_rebasevec_celem_node<T> assignment_rebasevec_celem_node_t; 22523 | typedef details::assignment_vec_node<T> assignment_vec_node_t; 22524 | typedef details::assignment_vecvec_node<T> assignment_vecvec_node_t; 22525 | typedef details::conditional_vector_node<T> conditional_vector_node_t; 22526 | typedef details::scand_node<T> scand_node_t; 22527 | typedef details::scor_node<T> scor_node_t; 22528 | typedef lexer::token token_t; 22529 | typedef expression_node_t* expression_node_ptr; 22530 | typedef expression<T> expression_t; 22531 | typedef symbol_table<T> symbol_table_t; 22532 | typedef typename expression<T>::symtab_list_t symbol_table_list_t; 22533 | typedef details::vector_holder<T> vector_holder_t; 22534 | typedef vector_holder_t* vector_holder_ptr; 22535 | 22536 | typedef typename details::functor_t<T> functor_t; 22537 | typedef typename functor_t::qfunc_t quaternary_functor_t; 22538 | typedef typename functor_t::tfunc_t trinary_functor_t; 22539 | typedef typename functor_t::bfunc_t binary_functor_t; 22540 | typedef typename functor_t::ufunc_t unary_functor_t; 22541 | 22542 | typedef details::operator_type operator_t; 22543 | 22544 | typedef std::map<operator_t, unary_functor_t > unary_op_map_t; 22545 | typedef std::map<operator_t, binary_functor_t > binary_op_map_t; 22546 | typedef std::map<operator_t, trinary_functor_t> trinary_op_map_t; 22547 | 22548 | typedef std::map<std::string,std::pair<trinary_functor_t ,operator_t> > sf3_map_t; 22549 | typedef std::map<std::string,std::pair<quaternary_functor_t,operator_t> > sf4_map_t; 22550 | 22551 | typedef std::map<binary_functor_t,operator_t> inv_binary_op_map_t; 22552 | typedef std::multimap<std::string,details::base_operation_t,details::ilesscompare> base_ops_map_t; 22553 | typedef std::set<std::string,details::ilesscompare> disabled_func_set_t; 22554 | 22555 | typedef details::T0oT1_define<T, cref_t , cref_t > vov_t; 22556 | typedef details::T0oT1_define<T, const_t, cref_t > cov_t; 22557 | typedef details::T0oT1_define<T, cref_t , const_t> voc_t; 22558 | 22559 | typedef details::T0oT1oT2_define<T, cref_t , cref_t , cref_t > vovov_t; 22560 | typedef details::T0oT1oT2_define<T, cref_t , cref_t , const_t> vovoc_t; 22561 | typedef details::T0oT1oT2_define<T, cref_t , const_t, cref_t > vocov_t; 22562 | typedef details::T0oT1oT2_define<T, const_t, cref_t , cref_t > covov_t; 22563 | typedef details::T0oT1oT2_define<T, const_t, cref_t , const_t> covoc_t; 22564 | typedef details::T0oT1oT2_define<T, const_t, const_t, cref_t > cocov_t; 22565 | typedef details::T0oT1oT2_define<T, cref_t , const_t, const_t> vococ_t; 22566 | 22567 | typedef details::T0oT1oT2oT3_define<T, cref_t , cref_t , cref_t , cref_t > vovovov_t; 22568 | typedef details::T0oT1oT2oT3_define<T, cref_t , cref_t , cref_t , const_t> vovovoc_t; 22569 | typedef details::T0oT1oT2oT3_define<T, cref_t , cref_t , const_t, cref_t > vovocov_t; 22570 | typedef details::T0oT1oT2oT3_define<T, cref_t , const_t, cref_t , cref_t > vocovov_t; 22571 | typedef details::T0oT1oT2oT3_define<T, const_t, cref_t , cref_t , cref_t > covovov_t; 22572 | 22573 | typedef details::T0oT1oT2oT3_define<T, const_t, cref_t , const_t, cref_t > covocov_t; 22574 | typedef details::T0oT1oT2oT3_define<T, cref_t , const_t, cref_t , const_t> vocovoc_t; 22575 | typedef details::T0oT1oT2oT3_define<T, const_t, cref_t , cref_t , const_t> covovoc_t; 22576 | typedef details::T0oT1oT2oT3_define<T, cref_t , const_t, const_t, cref_t > vococov_t; 22577 | 22578 | typedef results_context<T> results_context_t; 22579 | 22580 | typedef parser_helper prsrhlpr_t; 22581 | 22582 | struct scope_element 22583 | { 22584 | enum element_type 22585 | { 22586 | e_none , 22587 | e_literal , 22588 | e_variable, 22589 | e_vector , 22590 | e_vecelem , 22591 | e_string 22592 | }; 22593 | 22594 | typedef details::vector_holder<T> vector_holder_t; 22595 | typedef literal_node_t* literal_node_ptr; 22596 | typedef variable_node_t* variable_node_ptr; 22597 | typedef vector_holder_t* vector_holder_ptr; 22598 | typedef expression_node_t* expression_node_ptr; 22599 | #ifndef exprtk_disable_string_capabilities 22600 | typedef stringvar_node_t* stringvar_node_ptr; 22601 | #endif 22602 | 22603 | scope_element() 22604 | : name("???") 22605 | , size (std::numeric_limits<std::size_t>::max()) 22606 | , index(std::numeric_limits<std::size_t>::max()) 22607 | , depth(std::numeric_limits<std::size_t>::max()) 22608 | , ref_count(0) 22609 | , ip_index (0) 22610 | , type (e_none) 22611 | , active (false) 22612 | , data (0) 22613 | , var_node (0) 22614 | , vec_node (0) 22615 | #ifndef exprtk_disable_string_capabilities 22616 | , str_node(0) 22617 | #endif 22618 | {} 22619 | 22620 | bool operator < (const scope_element& se) const 22621 | { 22622 | if (ip_index < se.ip_index) 22623 | return true; 22624 | else if (ip_index > se.ip_index) 22625 | return false; 22626 | else if (depth < se.depth) 22627 | return true; 22628 | else if (depth > se.depth) 22629 | return false; 22630 | else if (index < se.index) 22631 | return true; 22632 | else if (index > se.index) 22633 | return false; 22634 | else 22635 | return (name < se.name); 22636 | } 22637 | 22638 | void clear() 22639 | { 22640 | name = "???" 22641 | size = std::numeric_limits<std::size_t>::max(); 22642 | index = std::numeric_limits<std::size_t>::max(); 22643 | depth = std::numeric_limits<std::size_t>::max(); 22644 | type = e_none; 22645 | active = false; 22646 | ref_count = 0; 22647 | ip_index = 0; 22648 | data = 0; 22649 | var_node = 0; 22650 | vec_node = 0; 22651 | #ifndef exprtk_disable_string_capabilities 22652 | str_node = 0; 22653 | #endif 22654 | } 22655 | 22656 | std::string name; 22657 | std::size_t size; 22658 | std::size_t index; 22659 | std::size_t depth; 22660 | std::size_t ref_count; 22661 | std::size_t ip_index; 22662 | element_type type; 22663 | bool active; 22664 | void* data; 22665 | expression_node_ptr var_node; 22666 | vector_holder_ptr vec_node; 22667 | #ifndef exprtk_disable_string_capabilities 22668 | stringvar_node_ptr str_node; 22669 | #endif 22670 | }; 22671 | 22672 | class scope_element_manager 22673 | { 22674 | public: 22675 | 22676 | typedef expression_node_t* expression_node_ptr; 22677 | typedef variable_node_t* variable_node_ptr; 22678 | typedef parser<T> parser_t; 22679 | 22680 | explicit scope_element_manager(parser<T>& p) 22681 | : parser_(p) 22682 | , input_param_cnt_(0) 22683 | , total_local_symb_size_bytes_(0) 22684 | {} 22685 | 22686 | inline std::size_t size() const 22687 | { 22688 | return element_.size(); 22689 | } 22690 | 22691 | inline bool empty() const 22692 | { 22693 | return element_.empty(); 22694 | } 22695 | 22696 | inline scope_element& get_element(const std::size_t& index) 22697 | { 22698 | if (index < element_.size()) 22699 | return element_[index]; 22700 | else 22701 | return null_element_; 22702 | } 22703 | 22704 | inline scope_element& get_element(const std::string& var_name, 22705 | const std::size_t index = std::numeric_limits<std::size_t>::max()) 22706 | { 22707 | const std::size_t current_depth = parser_.state_.scope_depth; 22708 | 22709 | for (std::size_t i = 0; i < element_.size(); ++i) 22710 | { 22711 | scope_element& se = element_[i]; 22712 | 22713 | if (se.depth > current_depth) 22714 | continue; 22715 | else if ( 22716 | details::imatch(se.name, var_name) && 22717 | (se.index == index) 22718 | ) 22719 | return se; 22720 | } 22721 | 22722 | return null_element_; 22723 | } 22724 | 22725 | inline scope_element& get_active_element(const std::string& var_name, 22726 | const std::size_t index = std::numeric_limits<std::size_t>::max()) 22727 | { 22728 | const std::size_t current_depth = parser_.state_.scope_depth; 22729 | 22730 | for (std::size_t i = 0; i < element_.size(); ++i) 22731 | { 22732 | scope_element& se = element_[i]; 22733 | 22734 | if (se.depth > current_depth) 22735 | continue; 22736 | else if ( 22737 | details::imatch(se.name, var_name) && 22738 | (se.index == index) && 22739 | (se.active) 22740 | ) 22741 | return se; 22742 | } 22743 | 22744 | return null_element_; 22745 | } 22746 | 22747 | inline bool add_element(const scope_element& se) 22748 | { 22749 | for (std::size_t i = 0; i < element_.size(); ++i) 22750 | { 22751 | scope_element& cse = element_[i]; 22752 | 22753 | if ( 22754 | details::imatch(cse.name, se.name) && 22755 | (cse.depth <= se.depth) && 22756 | (cse.index == se.index) && 22757 | (cse.size == se.size ) && 22758 | (cse.type == se.type ) && 22759 | (cse.active) 22760 | ) 22761 | return false; 22762 | } 22763 | 22764 | switch (se.type) 22765 | { 22766 | case scope_element::e_variable : total_local_symb_size_bytes_ += sizeof(T); 22767 | break; 22768 | 22769 | case scope_element::e_literal : total_local_symb_size_bytes_ += sizeof(T); 22770 | break; 22771 | 22772 | case scope_element::e_vector : total_local_symb_size_bytes_ += sizeof(T) * se.size; 22773 | break; 22774 | 22775 | default : break; 22776 | } 22777 | 22778 | element_.push_back(se); 22779 | std::sort(element_.begin(),element_.end()); 22780 | 22781 | return true; 22782 | } 22783 | 22784 | inline void deactivate(const std::size_t& scope_depth) 22785 | { 22786 | exprtk_debug(("deactivate() - Scope depth: %d\n", 22787 | static_cast<int>(parser_.state_.scope_depth))); 22788 | 22789 | for (std::size_t i = 0; i < element_.size(); ++i) 22790 | { 22791 | scope_element& se = element_[i]; 22792 | 22793 | if (se.active && (se.depth >= scope_depth)) 22794 | { 22795 | exprtk_debug(("deactivate() - element[%02d] '%s'\n", 22796 | static_cast<int>(i), 22797 | se.name.c_str())); 22798 | 22799 | se.active = false; 22800 | } 22801 | } 22802 | } 22803 | 22804 | inline void free_element(scope_element& se) 22805 | { 22806 | exprtk_debug(("free_element() - se[%s]\n", se.name.c_str())); 22807 | 22808 | switch (se.type) 22809 | { 22810 | case scope_element::e_literal : delete reinterpret_cast<T*>(se.data); 22811 | delete se.var_node; 22812 | break; 22813 | 22814 | case scope_element::e_variable : delete reinterpret_cast<T*>(se.data); 22815 | delete se.var_node; 22816 | break; 22817 | 22818 | case scope_element::e_vector : delete[] reinterpret_cast<T*>(se.data); 22819 | delete se.vec_node; 22820 | break; 22821 | 22822 | case scope_element::e_vecelem : delete se.var_node; 22823 | break; 22824 | 22825 | #ifndef exprtk_disable_string_capabilities 22826 | case scope_element::e_string : delete reinterpret_cast<std::string*>(se.data); 22827 | delete se.str_node; 22828 | break; 22829 | #endif 22830 | 22831 | default : return; 22832 | } 22833 | 22834 | se.clear(); 22835 | } 22836 | 22837 | inline void cleanup() 22838 | { 22839 | for (std::size_t i = 0; i < element_.size(); ++i) 22840 | { 22841 | free_element(element_[i]); 22842 | } 22843 | 22844 | element_.clear(); 22845 | 22846 | input_param_cnt_ = 0; 22847 | total_local_symb_size_bytes_ = 0; 22848 | } 22849 | 22850 | inline std::size_t total_local_symb_size_bytes() const 22851 | { 22852 | return total_local_symb_size_bytes_; 22853 | } 22854 | 22855 | inline std::size_t next_ip_index() 22856 | { 22857 | return ++input_param_cnt_; 22858 | } 22859 | 22860 | inline expression_node_ptr get_variable(const T& v) 22861 | { 22862 | for (std::size_t i = 0; i < element_.size(); ++i) 22863 | { 22864 | scope_element& se = element_[i]; 22865 | 22866 | if ( 22867 | se.active && 22868 | se.var_node && 22869 | details::is_variable_node(se.var_node) 22870 | ) 22871 | { 22872 | variable_node_ptr vn = reinterpret_cast<variable_node_ptr>(se.var_node); 22873 | 22874 | if (&(vn->ref()) == (&v)) 22875 | { 22876 | return se.var_node; 22877 | } 22878 | } 22879 | } 22880 | 22881 | return expression_node_ptr(0); 22882 | } 22883 | 22884 | inline std::string get_vector_name(const T* data) 22885 | { 22886 | for (std::size_t i = 0; i < element_.size(); ++i) 22887 | { 22888 | scope_element& se = element_[i]; 22889 | 22890 | if ( 22891 | se.active && 22892 | se.vec_node && 22893 | (se.vec_node->data() == data) 22894 | ) 22895 | { 22896 | return se.name; 22897 | } 22898 | } 22899 | 22900 | return "neo-vector" 22901 | } 22902 | 22903 | private: 22904 | 22905 | scope_element_manager(const scope_element_manager&) exprtk_delete; 22906 | scope_element_manager& operator=(const scope_element_manager&) exprtk_delete; 22907 | 22908 | parser_t& parser_; 22909 | std::vector<scope_element> element_; 22910 | scope_element null_element_; 22911 | std::size_t input_param_cnt_; 22912 | std::size_t total_local_symb_size_bytes_; 22913 | }; 22914 | 22915 | class scope_handler 22916 | { 22917 | public: 22918 | 22919 | typedef parser<T> parser_t; 22920 | 22921 | explicit scope_handler(parser<T>& p) 22922 | : parser_(p) 22923 | { 22924 | parser_.state_.scope_depth++; 22925 | #ifdef exprtk_enable_debugging 22926 | const std::string depth(2 * parser_.state_.scope_depth,'-'); 22927 | exprtk_debug(("%s> Scope Depth: %02d\n", 22928 | depth.c_str(), 22929 | static_cast<int>(parser_.state_.scope_depth))); 22930 | #endif 22931 | } 22932 | 22933 | ~scope_handler() 22934 | { 22935 | parser_.sem_.deactivate(parser_.state_.scope_depth); 22936 | parser_.state_.scope_depth--; 22937 | #ifdef exprtk_enable_debugging 22938 | const std::string depth(2 * parser_.state_.scope_depth,'-'); 22939 | exprtk_debug(("<%s Scope Depth: %02d\n", 22940 | depth.c_str(), 22941 | static_cast<int>(parser_.state_.scope_depth))); 22942 | #endif 22943 | } 22944 | 22945 | private: 22946 | 22947 | scope_handler(const scope_handler&) exprtk_delete; 22948 | scope_handler& operator=(const scope_handler&) exprtk_delete; 22949 | 22950 | parser_t& parser_; 22951 | }; 22952 | 22953 | template <typename T_> 22954 | struct halfopen_range_policy 22955 | { 22956 | static inline bool is_within(const T_& v, const T_& begin, const T_& end) 22957 | { 22958 | assert(begin <= end); 22959 | return (begin <= v) && (v < end); 22960 | } 22961 | 22962 | static inline bool is_less(const T_& v, const T_& begin) 22963 | { 22964 | return (v < begin); 22965 | } 22966 | 22967 | static inline bool is_greater(const T_& v, const T_& end) 22968 | { 22969 | return (end <= v); 22970 | } 22971 | 22972 | static inline bool end_inclusive() 22973 | { 22974 | return false; 22975 | } 22976 | }; 22977 | 22978 | template <typename T_> 22979 | struct closed_range_policy 22980 | { 22981 | static inline bool is_within(const T_& v, const T_& begin, const T_& end) 22982 | { 22983 | assert(begin <= end); 22984 | return (begin <= v) && (v <= end); 22985 | } 22986 | 22987 | static inline bool is_less(const T_& v, const T_& begin) 22988 | { 22989 | return (v < begin); 22990 | } 22991 | 22992 | static inline bool is_greater(const T_& v, const T_& end) 22993 | { 22994 | return (end < v); 22995 | } 22996 | 22997 | static inline bool end_inclusive() 22998 | { 22999 | return true; 23000 | } 23001 | }; 23002 | 23003 | template <typename IntervalPointType, 23004 | typename RangePolicy = halfopen_range_policy<IntervalPointType> > 23005 | class interval_container_t 23006 | { 23007 | public: 23008 | 23009 | typedef IntervalPointType interval_point_t; 23010 | typedef std::pair<interval_point_t, interval_point_t> interval_t; 23011 | typedef std::map<interval_point_t, interval_t> interval_map_t; 23012 | typedef typename interval_map_t::const_iterator interval_map_citr_t; 23013 | 23014 | std::size_t size() const 23015 | { 23016 | return interval_map_.size(); 23017 | } 23018 | 23019 | void reset() 23020 | { 23021 | interval_map_.clear(); 23022 | } 23023 | 23024 | bool in_interval(const interval_point_t point, interval_t& interval) const 23025 | { 23026 | interval_map_citr_t itr = RangePolicy::end_inclusive() ? 23027 | interval_map_.lower_bound(point): 23028 | interval_map_.upper_bound(point); 23029 | 23030 | for (; itr != interval_map_.end(); ++itr) 23031 | { 23032 | const interval_point_t& begin = itr->second.first; 23033 | const interval_point_t& end = itr->second.second; 23034 | 23035 | if (RangePolicy::is_within(point, begin, end)) 23036 | { 23037 | interval = interval_t(begin,end); 23038 | return true; 23039 | } 23040 | else if (RangePolicy::is_greater(point, end)) 23041 | { 23042 | break; 23043 | } 23044 | } 23045 | 23046 | return false; 23047 | } 23048 | 23049 | bool in_interval(const interval_point_t point) const 23050 | { 23051 | interval_t interval; 23052 | return in_interval(point,interval); 23053 | } 23054 | 23055 | bool add_interval(const interval_point_t begin, const interval_point_t end) 23056 | { 23057 | if ((end <= begin) || in_interval(begin) || in_interval(end)) 23058 | { 23059 | return false; 23060 | } 23061 | 23062 | interval_map_[end] = std::make_pair(begin, end); 23063 | 23064 | return true; 23065 | } 23066 | 23067 | bool add_interval(const interval_t interval) 23068 | { 23069 | return add_interval(interval.first, interval.second); 23070 | } 23071 | 23072 | private: 23073 | 23074 | interval_map_t interval_map_; 23075 | }; 23076 | 23077 | class stack_limit_handler 23078 | { 23079 | public: 23080 | 23081 | typedef parser<T> parser_t; 23082 | 23083 | explicit stack_limit_handler(parser<T>& p) 23084 | : parser_(p) 23085 | , limit_exceeded_(false) 23086 | { 23087 | if (++parser_.state_.stack_depth > parser_.settings_.max_stack_depth_) 23088 | { 23089 | limit_exceeded_ = true; 23090 | parser_.set_error(make_error( 23091 | parser_error::e_parser, 23092 | "ERR000 - Current stack depth " + details::to_str(parser_.state_.stack_depth) + 23093 | " exceeds maximum allowed stack depth of " + details::to_str(parser_.settings_.max_stack_depth_), 23094 | exprtk_error_location)); 23095 | } 23096 | } 23097 | 23098 | ~stack_limit_handler() 23099 | { 23100 | assert(parser_.state_.stack_depth > 0); 23101 | parser_.state_.stack_depth--; 23102 | } 23103 | 23104 | bool operator!() 23105 | { 23106 | return limit_exceeded_; 23107 | } 23108 | 23109 | private: 23110 | 23111 | stack_limit_handler(const stack_limit_handler&) exprtk_delete; 23112 | stack_limit_handler& operator=(const stack_limit_handler&) exprtk_delete; 23113 | 23114 | parser_t& parser_; 23115 | bool limit_exceeded_; 23116 | }; 23117 | 23118 | struct symtab_store 23119 | { 23120 | symbol_table_list_t symtab_list_; 23121 | 23122 | typedef typename symbol_table_t::local_data_t local_data_t; 23123 | typedef typename symbol_table_t::variable_ptr variable_ptr; 23124 | typedef typename symbol_table_t::function_ptr function_ptr; 23125 | #ifndef exprtk_disable_string_capabilities 23126 | typedef typename symbol_table_t::stringvar_ptr stringvar_ptr; 23127 | #endif 23128 | typedef typename symbol_table_t::vector_holder_ptr vector_holder_ptr; 23129 | typedef typename symbol_table_t::vararg_function_ptr vararg_function_ptr; 23130 | typedef typename symbol_table_t::generic_function_ptr generic_function_ptr; 23131 | 23132 | struct variable_context 23133 | { 23134 | variable_context() 23135 | : symbol_table(0) 23136 | , variable(0) 23137 | {} 23138 | 23139 | const symbol_table_t* symbol_table; 23140 | variable_ptr variable; 23141 | }; 23142 | 23143 | struct vector_context 23144 | { 23145 | vector_context() 23146 | : symbol_table(0) 23147 | , vector_holder(0) 23148 | {} 23149 | 23150 | const symbol_table_t* symbol_table; 23151 | vector_holder_ptr vector_holder; 23152 | }; 23153 | 23154 | #ifndef exprtk_disable_string_capabilities 23155 | struct string_context 23156 | { 23157 | string_context() 23158 | : symbol_table(0) 23159 | , str_var(0) 23160 | {} 23161 | 23162 | const symbol_table_t* symbol_table; 23163 | stringvar_ptr str_var; 23164 | }; 23165 | #endif 23166 | 23167 | inline bool empty() const 23168 | { 23169 | return symtab_list_.empty(); 23170 | } 23171 | 23172 | inline void clear() 23173 | { 23174 | symtab_list_.clear(); 23175 | } 23176 | 23177 | inline bool valid() const 23178 | { 23179 | if (!empty()) 23180 | { 23181 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23182 | { 23183 | if (symtab_list_[i].valid()) 23184 | return true; 23185 | } 23186 | } 23187 | 23188 | return false; 23189 | } 23190 | 23191 | inline bool valid_symbol(const std::string& symbol) const 23192 | { 23193 | if (!symtab_list_.empty()) 23194 | return symtab_list_[0].valid_symbol(symbol); 23195 | else 23196 | return false; 23197 | } 23198 | 23199 | inline bool valid_function_name(const std::string& symbol) const 23200 | { 23201 | if (!symtab_list_.empty()) 23202 | return symtab_list_[0].valid_function(symbol); 23203 | else 23204 | return false; 23205 | } 23206 | 23207 | inline variable_context get_variable_context(const std::string& variable_name) const 23208 | { 23209 | variable_context result; 23210 | 23211 | if (valid_symbol(variable_name)) 23212 | { 23213 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23214 | { 23215 | if (!symtab_list_[i].valid()) 23216 | { 23217 | continue; 23218 | } 23219 | 23220 | result.variable = local_data(i) 23221 | .variable_store.get(variable_name); 23222 | if (result.variable) 23223 | { 23224 | result.symbol_table = &symtab_list_[i]; 23225 | break; 23226 | } 23227 | } 23228 | } 23229 | 23230 | return result; 23231 | } 23232 | 23233 | inline variable_ptr get_variable(const std::string& variable_name) const 23234 | { 23235 | if (!valid_symbol(variable_name)) 23236 | return reinterpret_cast<variable_ptr>(0); 23237 | 23238 | variable_ptr result = reinterpret_cast<variable_ptr>(0); 23239 | 23240 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23241 | { 23242 | if (!symtab_list_[i].valid()) 23243 | continue; 23244 | else 23245 | result = local_data(i) 23246 | .variable_store.get(variable_name); 23247 | 23248 | if (result) break; 23249 | } 23250 | 23251 | return result; 23252 | } 23253 | 23254 | inline variable_ptr get_variable(const T& var_ref) const 23255 | { 23256 | variable_ptr result = reinterpret_cast<variable_ptr>(0); 23257 | 23258 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23259 | { 23260 | if (!symtab_list_[i].valid()) 23261 | continue; 23262 | else 23263 | result = local_data(i).variable_store 23264 | .get_from_varptr(reinterpret_cast<const void*>(&var_ref)); 23265 | 23266 | if (result) break; 23267 | } 23268 | 23269 | return result; 23270 | } 23271 | 23272 | #ifndef exprtk_disable_string_capabilities 23273 | inline string_context get_string_context(const std::string& string_name) const 23274 | { 23275 | string_context result; 23276 | 23277 | if (!valid_symbol(string_name)) 23278 | return result; 23279 | 23280 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23281 | { 23282 | if (!symtab_list_[i].valid()) 23283 | { 23284 | continue; 23285 | } 23286 | 23287 | result.str_var = local_data(i).stringvar_store.get(string_name); 23288 | 23289 | if (result.str_var) 23290 | { 23291 | result.symbol_table = &symtab_list_[i]; 23292 | break; 23293 | } 23294 | } 23295 | 23296 | return result; 23297 | } 23298 | 23299 | inline stringvar_ptr get_stringvar(const std::string& string_name) const 23300 | { 23301 | if (!valid_symbol(string_name)) 23302 | return reinterpret_cast<stringvar_ptr>(0); 23303 | 23304 | stringvar_ptr result = reinterpret_cast<stringvar_ptr>(0); 23305 | 23306 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23307 | { 23308 | if (!symtab_list_[i].valid()) 23309 | continue; 23310 | else 23311 | result = local_data(i) 23312 | .stringvar_store.get(string_name); 23313 | 23314 | if (result) break; 23315 | } 23316 | 23317 | return result; 23318 | } 23319 | #endif 23320 | 23321 | inline function_ptr get_function(const std::string& function_name) const 23322 | { 23323 | if (!valid_function_name(function_name)) 23324 | return reinterpret_cast<function_ptr>(0); 23325 | 23326 | function_ptr result = reinterpret_cast<function_ptr>(0); 23327 | 23328 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23329 | { 23330 | if (!symtab_list_[i].valid()) 23331 | continue; 23332 | else 23333 | result = local_data(i) 23334 | .function_store.get(function_name); 23335 | 23336 | if (result) break; 23337 | } 23338 | 23339 | return result; 23340 | } 23341 | 23342 | inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name) const 23343 | { 23344 | if (!valid_function_name(vararg_function_name)) 23345 | return reinterpret_cast<vararg_function_ptr>(0); 23346 | 23347 | vararg_function_ptr result = reinterpret_cast<vararg_function_ptr>(0); 23348 | 23349 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23350 | { 23351 | if (!symtab_list_[i].valid()) 23352 | continue; 23353 | else 23354 | result = local_data(i) 23355 | .vararg_function_store.get(vararg_function_name); 23356 | 23357 | if (result) break; 23358 | } 23359 | 23360 | return result; 23361 | } 23362 | 23363 | inline generic_function_ptr get_generic_function(const std::string& function_name) const 23364 | { 23365 | if (!valid_function_name(function_name)) 23366 | return reinterpret_cast<generic_function_ptr>(0); 23367 | 23368 | generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0); 23369 | 23370 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23371 | { 23372 | if (!symtab_list_[i].valid()) 23373 | continue; 23374 | else 23375 | result = local_data(i) 23376 | .generic_function_store.get(function_name); 23377 | 23378 | if (result) break; 23379 | } 23380 | 23381 | return result; 23382 | } 23383 | 23384 | inline generic_function_ptr get_string_function(const std::string& function_name) const 23385 | { 23386 | if (!valid_function_name(function_name)) 23387 | return reinterpret_cast<generic_function_ptr>(0); 23388 | 23389 | generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0); 23390 | 23391 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23392 | { 23393 | if (!symtab_list_[i].valid()) 23394 | continue; 23395 | else 23396 | result = 23397 | local_data(i).string_function_store.get(function_name); 23398 | 23399 | if (result) break; 23400 | } 23401 | 23402 | return result; 23403 | } 23404 | 23405 | inline generic_function_ptr get_overload_function(const std::string& function_name) const 23406 | { 23407 | if (!valid_function_name(function_name)) 23408 | return reinterpret_cast<generic_function_ptr>(0); 23409 | 23410 | generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0); 23411 | 23412 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23413 | { 23414 | if (!symtab_list_[i].valid()) 23415 | continue; 23416 | else 23417 | result = 23418 | local_data(i).overload_function_store.get(function_name); 23419 | 23420 | if (result) break; 23421 | } 23422 | 23423 | return result; 23424 | } 23425 | 23426 | inline vector_context get_vector_context(const std::string& vector_name) const 23427 | { 23428 | vector_context result; 23429 | if (!valid_symbol(vector_name)) 23430 | return result; 23431 | 23432 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23433 | { 23434 | if (!symtab_list_[i].valid()) 23435 | { 23436 | continue; 23437 | } 23438 | 23439 | result.vector_holder = local_data(i).vector_store.get(vector_name); 23440 | 23441 | if (result.vector_holder) 23442 | { 23443 | result.symbol_table = &symtab_list_[i]; 23444 | break; 23445 | } 23446 | } 23447 | 23448 | return result; 23449 | } 23450 | 23451 | inline vector_holder_ptr get_vector(const std::string& vector_name) const 23452 | { 23453 | if (!valid_symbol(vector_name)) 23454 | return reinterpret_cast<vector_holder_ptr>(0); 23455 | 23456 | vector_holder_ptr result = reinterpret_cast<vector_holder_ptr>(0); 23457 | 23458 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23459 | { 23460 | if (!symtab_list_[i].valid()) 23461 | { 23462 | continue; 23463 | } 23464 | 23465 | result = local_data(i).vector_store.get(vector_name); 23466 | 23467 | if (result) 23468 | { 23469 | break; 23470 | } 23471 | } 23472 | 23473 | return result; 23474 | } 23475 | 23476 | inline bool is_constant_node(const std::string& symbol_name) const 23477 | { 23478 | if (!valid_symbol(symbol_name)) 23479 | return false; 23480 | 23481 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23482 | { 23483 | if (!symtab_list_[i].valid()) 23484 | { 23485 | continue; 23486 | } 23487 | 23488 | if (local_data(i).variable_store.is_constant(symbol_name)) 23489 | { 23490 | return true; 23491 | } 23492 | } 23493 | 23494 | return false; 23495 | } 23496 | 23497 | #ifndef exprtk_disable_string_capabilities 23498 | inline bool is_constant_string(const std::string& symbol_name) const 23499 | { 23500 | if (!valid_symbol(symbol_name)) 23501 | return false; 23502 | 23503 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23504 | { 23505 | if (!symtab_list_[i].valid()) 23506 | continue; 23507 | else if (!local_data(i).stringvar_store.symbol_exists(symbol_name)) 23508 | continue; 23509 | else if (local_data(i).stringvar_store.is_constant(symbol_name)) 23510 | return true; 23511 | } 23512 | 23513 | return false; 23514 | } 23515 | #endif 23516 | 23517 | inline bool symbol_exists(const std::string& symbol) const 23518 | { 23519 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23520 | { 23521 | if (!symtab_list_[i].valid()) 23522 | { 23523 | continue; 23524 | } 23525 | 23526 | if (symtab_list_[i].symbol_exists(symbol)) 23527 | { 23528 | return true; 23529 | } 23530 | } 23531 | 23532 | return false; 23533 | } 23534 | 23535 | inline bool is_variable(const std::string& variable_name) const 23536 | { 23537 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23538 | { 23539 | if (!symtab_list_[i].valid()) 23540 | continue; 23541 | else if ( 23542 | symtab_list_[i].local_data().variable_store 23543 | .symbol_exists(variable_name) 23544 | ) 23545 | return true; 23546 | } 23547 | 23548 | return false; 23549 | } 23550 | 23551 | #ifndef exprtk_disable_string_capabilities 23552 | inline bool is_stringvar(const std::string& stringvar_name) const 23553 | { 23554 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23555 | { 23556 | if (!symtab_list_[i].valid()) 23557 | continue; 23558 | else if ( 23559 | symtab_list_[i].local_data().stringvar_store 23560 | .symbol_exists(stringvar_name) 23561 | ) 23562 | return true; 23563 | } 23564 | 23565 | return false; 23566 | } 23567 | 23568 | inline bool is_conststr_stringvar(const std::string& symbol_name) const 23569 | { 23570 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23571 | { 23572 | if (!symtab_list_[i].valid()) 23573 | continue; 23574 | else if ( 23575 | symtab_list_[i].local_data().stringvar_store 23576 | .symbol_exists(symbol_name) 23577 | ) 23578 | { 23579 | return ( 23580 | local_data(i).stringvar_store.symbol_exists(symbol_name) || 23581 | local_data(i).stringvar_store.is_constant (symbol_name) 23582 | ); 23583 | 23584 | } 23585 | } 23586 | 23587 | return false; 23588 | } 23589 | #endif 23590 | 23591 | inline bool is_function(const std::string& function_name) const 23592 | { 23593 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23594 | { 23595 | if (!symtab_list_[i].valid()) 23596 | continue; 23597 | else if ( 23598 | local_data(i).vararg_function_store 23599 | .symbol_exists(function_name) 23600 | ) 23601 | return true; 23602 | } 23603 | 23604 | return false; 23605 | } 23606 | 23607 | inline bool is_vararg_function(const std::string& vararg_function_name) const 23608 | { 23609 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23610 | { 23611 | if (!symtab_list_[i].valid()) 23612 | continue; 23613 | else if ( 23614 | local_data(i).vararg_function_store 23615 | .symbol_exists(vararg_function_name) 23616 | ) 23617 | return true; 23618 | } 23619 | 23620 | return false; 23621 | } 23622 | 23623 | inline bool is_vector(const std::string& vector_name) const 23624 | { 23625 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23626 | { 23627 | if (!symtab_list_[i].valid()) 23628 | continue; 23629 | else if ( 23630 | local_data(i).vector_store 23631 | .symbol_exists(vector_name) 23632 | ) 23633 | return true; 23634 | } 23635 | 23636 | return false; 23637 | } 23638 | 23639 | inline std::string get_variable_name(const expression_node_ptr& ptr) const 23640 | { 23641 | return local_data().variable_store.entity_name(ptr); 23642 | } 23643 | 23644 | inline std::string get_vector_name(const vector_holder_ptr& ptr) const 23645 | { 23646 | return local_data().vector_store.entity_name(ptr); 23647 | } 23648 | 23649 | #ifndef exprtk_disable_string_capabilities 23650 | inline std::string get_stringvar_name(const expression_node_ptr& ptr) const 23651 | { 23652 | return local_data().stringvar_store.entity_name(ptr); 23653 | } 23654 | 23655 | inline std::string get_conststr_stringvar_name(const expression_node_ptr& ptr) const 23656 | { 23657 | return local_data().stringvar_store.entity_name(ptr); 23658 | } 23659 | #endif 23660 | 23661 | inline local_data_t& local_data(const std::size_t& index = 0) 23662 | { 23663 | return symtab_list_[index].local_data(); 23664 | } 23665 | 23666 | inline const local_data_t& local_data(const std::size_t& index = 0) const 23667 | { 23668 | return symtab_list_[index].local_data(); 23669 | } 23670 | 23671 | inline symbol_table_t& get_symbol_table(const std::size_t& index = 0) 23672 | { 23673 | return symtab_list_[index]; 23674 | } 23675 | }; 23676 | 23677 | struct parser_state 23678 | { 23679 | parser_state() 23680 | : type_check_enabled(true) 23681 | { 23682 | reset(); 23683 | } 23684 | 23685 | void reset() 23686 | { 23687 | parsing_return_stmt = false; 23688 | parsing_break_stmt = false; 23689 | parsing_assert_stmt = false; 23690 | return_stmt_present = false; 23691 | side_effect_present = false; 23692 | scope_depth = 0; 23693 | stack_depth = 0; 23694 | parsing_loop_stmt_count = 0; 23695 | } 23696 | 23697 | #ifndef exprtk_enable_debugging 23698 | void activate_side_effect(const std::string&) 23699 | #else 23700 | void activate_side_effect(const std::string& source) 23701 | #endif 23702 | { 23703 | if (!side_effect_present) 23704 | { 23705 | side_effect_present = true; 23706 | 23707 | exprtk_debug(("activate_side_effect() - caller: %s\n", source.c_str())); 23708 | } 23709 | } 23710 | 23711 | bool parsing_return_stmt; 23712 | bool parsing_break_stmt; 23713 | bool parsing_assert_stmt; 23714 | bool return_stmt_present; 23715 | bool side_effect_present; 23716 | bool type_check_enabled; 23717 | std::size_t scope_depth; 23718 | std::size_t stack_depth; 23719 | std::size_t parsing_loop_stmt_count; 23720 | }; 23721 | 23722 | public: 23723 | 23724 | struct unknown_symbol_resolver 23725 | { 23726 | 23727 | enum usr_symbol_type 23728 | { 23729 | e_usr_unknown_type = 0, 23730 | e_usr_variable_type = 1, 23731 | e_usr_constant_type = 2 23732 | }; 23733 | 23734 | enum usr_mode 23735 | { 23736 | e_usrmode_default = 0, 23737 | e_usrmode_extended = 1 23738 | }; 23739 | 23740 | usr_mode mode; 23741 | 23742 | explicit unknown_symbol_resolver(const usr_mode m = e_usrmode_default) 23743 | : mode(m) 23744 | {} 23745 | 23746 | virtual ~unknown_symbol_resolver() 23747 | {} 23748 | 23749 | virtual bool process(const std::string& /*unknown_symbol*/, 23750 | usr_symbol_type& st, 23751 | T& default_value, 23752 | std::string& error_message) 23753 | { 23754 | if (e_usrmode_default != mode) 23755 | return false; 23756 | 23757 | st = e_usr_variable_type; 23758 | default_value = T(0); 23759 | error_message.clear(); 23760 | 23761 | return true; 23762 | } 23763 | 23764 | virtual bool process(const std::string& /* unknown_symbol */, 23765 | symbol_table_t& /* symbol_table */, 23766 | std::string& /* error_message */) 23767 | { 23768 | return false; 23769 | } 23770 | }; 23771 | 23772 | enum collect_type 23773 | { 23774 | e_ct_none = 0, 23775 | e_ct_variables = 1, 23776 | e_ct_functions = 2, 23777 | e_ct_assignments = 4 23778 | }; 23779 | 23780 | enum symbol_type 23781 | { 23782 | e_st_unknown = 0, 23783 | e_st_variable = 1, 23784 | e_st_vector = 2, 23785 | e_st_vecelem = 3, 23786 | e_st_string = 4, 23787 | e_st_function = 5, 23788 | e_st_local_variable = 6, 23789 | e_st_local_vector = 7, 23790 | e_st_local_string = 8 23791 | }; 23792 | 23793 | class dependent_entity_collector 23794 | { 23795 | public: 23796 | 23797 | typedef std::pair<std::string,symbol_type> symbol_t; 23798 | typedef std::vector<symbol_t> symbol_list_t; 23799 | 23800 | explicit dependent_entity_collector(const std::size_t options = e_ct_none) 23801 | : options_(options) 23802 | , collect_variables_ ((options_ & e_ct_variables ) == e_ct_variables ) 23803 | , collect_functions_ ((options_ & e_ct_functions ) == e_ct_functions ) 23804 | , collect_assignments_((options_ & e_ct_assignments) == e_ct_assignments) 23805 | , return_present_ (false) 23806 | , final_stmt_return_(false) 23807 | {} 23808 | 23809 | template <typename Allocator, 23810 | template <typename, typename> class Sequence> 23811 | inline std::size_t symbols(Sequence<symbol_t,Allocator>& symbols_list) 23812 | { 23813 | if (!collect_variables_ && !collect_functions_) 23814 | return 0; 23815 | else if (symbol_name_list_.empty()) 23816 | return 0; 23817 | 23818 | for (std::size_t i = 0; i < symbol_name_list_.size(); ++i) 23819 | { 23820 | details::case_normalise(symbol_name_list_[i].first); 23821 | } 23822 | 23823 | std::sort(symbol_name_list_.begin(), symbol_name_list_.end()); 23824 | 23825 | std::unique_copy 23826 | ( 23827 | symbol_name_list_.begin(), 23828 | symbol_name_list_.end (), 23829 | std::back_inserter(symbols_list) 23830 | ); 23831 | 23832 | return symbols_list.size(); 23833 | } 23834 | 23835 | template <typename Allocator, 23836 | template <typename, typename> class Sequence> 23837 | inline std::size_t assignment_symbols(Sequence<symbol_t,Allocator>& assignment_list) 23838 | { 23839 | if (!collect_assignments_) 23840 | return 0; 23841 | else if (assignment_name_list_.empty()) 23842 | return 0; 23843 | 23844 | for (std::size_t i = 0; i < assignment_name_list_.size(); ++i) 23845 | { 23846 | details::case_normalise(assignment_name_list_[i].first); 23847 | } 23848 | 23849 | std::sort(assignment_name_list_.begin(),assignment_name_list_.end()); 23850 | 23851 | std::unique_copy 23852 | ( 23853 | assignment_name_list_.begin(), 23854 | assignment_name_list_.end (), 23855 | std::back_inserter(assignment_list) 23856 | ); 23857 | 23858 | return assignment_list.size(); 23859 | } 23860 | 23861 | void clear() 23862 | { 23863 | symbol_name_list_ .clear(); 23864 | assignment_name_list_.clear(); 23865 | retparam_list_ .clear(); 23866 | return_present_ = false; 23867 | final_stmt_return_ = false; 23868 | } 23869 | 23870 | bool& collect_variables() 23871 | { 23872 | return collect_variables_; 23873 | } 23874 | 23875 | bool& collect_functions() 23876 | { 23877 | return collect_functions_; 23878 | } 23879 | 23880 | bool& collect_assignments() 23881 | { 23882 | return collect_assignments_; 23883 | } 23884 | 23885 | bool return_present() const 23886 | { 23887 | return return_present_; 23888 | } 23889 | 23890 | bool final_stmt_return() const 23891 | { 23892 | return final_stmt_return_; 23893 | } 23894 | 23895 | typedef std::vector<std::string> retparam_list_t; 23896 | 23897 | retparam_list_t return_param_type_list() const 23898 | { 23899 | return retparam_list_; 23900 | } 23901 | 23902 | private: 23903 | 23904 | inline void add_symbol(const std::string& symbol, const symbol_type st) 23905 | { 23906 | switch (st) 23907 | { 23908 | case e_st_variable : 23909 | case e_st_vector : 23910 | case e_st_string : 23911 | case e_st_local_variable : 23912 | case e_st_local_vector : 23913 | case e_st_local_string : if (collect_variables_) 23914 | symbol_name_list_ 23915 | .push_back(std::make_pair(symbol, st)); 23916 | break; 23917 | 23918 | case e_st_function : if (collect_functions_) 23919 | symbol_name_list_ 23920 | .push_back(std::make_pair(symbol, st)); 23921 | break; 23922 | 23923 | default : return; 23924 | } 23925 | } 23926 | 23927 | inline void add_assignment(const std::string& symbol, const symbol_type st) 23928 | { 23929 | switch (st) 23930 | { 23931 | case e_st_variable : 23932 | case e_st_vector : 23933 | case e_st_string : if (collect_assignments_) 23934 | assignment_name_list_ 23935 | .push_back(std::make_pair(symbol, st)); 23936 | break; 23937 | 23938 | default : return; 23939 | } 23940 | } 23941 | 23942 | std::size_t options_; 23943 | bool collect_variables_; 23944 | bool collect_functions_; 23945 | bool collect_assignments_; 23946 | bool return_present_; 23947 | bool final_stmt_return_; 23948 | symbol_list_t symbol_name_list_; 23949 | symbol_list_t assignment_name_list_; 23950 | retparam_list_t retparam_list_; 23951 | 23952 | friend class parser<T>; 23953 | }; 23954 | 23955 | class settings_store 23956 | { 23957 | private: 23958 | 23959 | typedef std::set<std::string,details::ilesscompare> disabled_entity_set_t; 23960 | typedef disabled_entity_set_t::iterator des_itr_t; 23961 | 23962 | public: 23963 | 23964 | enum settings_compilation_options 23965 | { 23966 | e_unknown = 0, 23967 | e_replacer = 1, 23968 | e_joiner = 2, 23969 | e_numeric_check = 4, 23970 | e_bracket_check = 8, 23971 | e_sequence_check = 16, 23972 | e_commutative_check = 32, 23973 | e_strength_reduction = 64, 23974 | e_disable_vardef = 128, 23975 | e_collect_vars = 256, 23976 | e_collect_funcs = 512, 23977 | e_collect_assings = 1024, 23978 | e_disable_usr_on_rsrvd = 2048, 23979 | e_disable_zero_return = 4096 23980 | }; 23981 | 23982 | enum settings_base_funcs 23983 | { 23984 | e_bf_unknown = 0, 23985 | e_bf_abs , e_bf_acos , e_bf_acosh , e_bf_asin , 23986 | e_bf_asinh , e_bf_atan , e_bf_atan2 , e_bf_atanh , 23987 | e_bf_avg , e_bf_ceil , e_bf_clamp , e_bf_cos , 23988 | e_bf_cosh , e_bf_cot , e_bf_csc , e_bf_equal , 23989 | e_bf_erf , e_bf_erfc , e_bf_exp , e_bf_expm1 , 23990 | e_bf_floor , e_bf_frac , e_bf_hypot , e_bf_iclamp , 23991 | e_bf_like , e_bf_log , e_bf_log10 , e_bf_log1p , 23992 | e_bf_log2 , e_bf_logn , e_bf_mand , e_bf_max , 23993 | e_bf_min , e_bf_mod , e_bf_mor , e_bf_mul , 23994 | e_bf_ncdf , e_bf_pow , e_bf_root , e_bf_round , 23995 | e_bf_roundn , e_bf_sec , e_bf_sgn , e_bf_sin , 23996 | e_bf_sinc , e_bf_sinh , e_bf_sqrt , e_bf_sum , 23997 | e_bf_swap , e_bf_tan , e_bf_tanh , e_bf_trunc , 23998 | e_bf_not_equal , e_bf_inrange , e_bf_deg2grad , e_bf_deg2rad , 23999 | e_bf_rad2deg , e_bf_grad2deg 24000 | }; 24001 | 24002 | enum settings_control_structs 24003 | { 24004 | e_ctrl_unknown = 0, 24005 | e_ctrl_ifelse, 24006 | e_ctrl_switch, 24007 | e_ctrl_for_loop, 24008 | e_ctrl_while_loop, 24009 | e_ctrl_repeat_loop, 24010 | e_ctrl_return 24011 | }; 24012 | 24013 | enum settings_logic_opr 24014 | { 24015 | e_logic_unknown = 0, 24016 | e_logic_and, e_logic_nand , e_logic_nor , 24017 | e_logic_not, e_logic_or , e_logic_xnor, 24018 | e_logic_xor, e_logic_scand, e_logic_scor 24019 | }; 24020 | 24021 | enum settings_arithmetic_opr 24022 | { 24023 | e_arith_unknown = 0, 24024 | e_arith_add, e_arith_sub, e_arith_mul, 24025 | e_arith_div, e_arith_mod, e_arith_pow 24026 | }; 24027 | 24028 | enum settings_assignment_opr 24029 | { 24030 | e_assign_unknown = 0, 24031 | e_assign_assign, e_assign_addass, e_assign_subass, 24032 | e_assign_mulass, e_assign_divass, e_assign_modass 24033 | }; 24034 | 24035 | enum settings_inequality_opr 24036 | { 24037 | e_ineq_unknown = 0, 24038 | e_ineq_lt , e_ineq_lte, e_ineq_eq , 24039 | e_ineq_equal, e_ineq_ne , e_ineq_nequal, 24040 | e_ineq_gte , e_ineq_gt 24041 | }; 24042 | 24043 | static const std::size_t default_compile_all_opts = 24044 | e_replacer + 24045 | e_joiner + 24046 | e_numeric_check + 24047 | e_bracket_check + 24048 | e_sequence_check + 24049 | e_commutative_check + 24050 | e_strength_reduction; 24051 | 24052 | settings_store(const std::size_t compile_options = default_compile_all_opts) 24053 | : max_stack_depth_(400) 24054 | , max_node_depth_(10000) 24055 | , max_total_local_symbol_size_bytes_(2000000000) 24056 | , max_local_vector_size_(max_total_local_symbol_size_bytes_ / sizeof(T)) 24057 | { 24058 | load_compile_options(compile_options); 24059 | } 24060 | 24061 | settings_store& enable_all_base_functions() 24062 | { 24063 | disabled_func_set_.clear(); 24064 | return (*this); 24065 | } 24066 | 24067 | settings_store& enable_all_control_structures() 24068 | { 24069 | disabled_ctrl_set_.clear(); 24070 | return (*this); 24071 | } 24072 | 24073 | settings_store& enable_all_logic_ops() 24074 | { 24075 | disabled_logic_set_.clear(); 24076 | return (*this); 24077 | } 24078 | 24079 | settings_store& enable_all_arithmetic_ops() 24080 | { 24081 | disabled_arithmetic_set_.clear(); 24082 | return (*this); 24083 | } 24084 | 24085 | settings_store& enable_all_assignment_ops() 24086 | { 24087 | disabled_assignment_set_.clear(); 24088 | return (*this); 24089 | } 24090 | 24091 | settings_store& enable_all_inequality_ops() 24092 | { 24093 | disabled_inequality_set_.clear(); 24094 | return (*this); 24095 | } 24096 | 24097 | settings_store& enable_local_vardef() 24098 | { 24099 | disable_vardef_ = false; 24100 | return (*this); 24101 | } 24102 | 24103 | settings_store& enable_commutative_check() 24104 | { 24105 | enable_commutative_check_ = true; 24106 | return (*this); 24107 | } 24108 | 24109 | settings_store& enable_strength_reduction() 24110 | { 24111 | enable_strength_reduction_ = true; 24112 | return (*this); 24113 | } 24114 | 24115 | settings_store& disable_all_base_functions() 24116 | { 24117 | std::copy(details::base_function_list, 24118 | details::base_function_list + details::base_function_list_size, 24119 | std::insert_iterator<disabled_entity_set_t> 24120 | (disabled_func_set_, disabled_func_set_.begin())); 24121 | return (*this); 24122 | } 24123 | 24124 | settings_store& disable_all_control_structures() 24125 | { 24126 | std::copy(details::cntrl_struct_list, 24127 | details::cntrl_struct_list + details::cntrl_struct_list_size, 24128 | std::insert_iterator<disabled_entity_set_t> 24129 | (disabled_ctrl_set_, disabled_ctrl_set_.begin())); 24130 | return (*this); 24131 | } 24132 | 24133 | settings_store& disable_all_logic_ops() 24134 | { 24135 | std::copy(details::logic_ops_list, 24136 | details::logic_ops_list + details::logic_ops_list_size, 24137 | std::insert_iterator<disabled_entity_set_t> 24138 | (disabled_logic_set_, disabled_logic_set_.begin())); 24139 | return (*this); 24140 | } 24141 | 24142 | settings_store& disable_all_arithmetic_ops() 24143 | { 24144 | std::copy(details::arithmetic_ops_list, 24145 | details::arithmetic_ops_list + details::arithmetic_ops_list_size, 24146 | std::insert_iterator<disabled_entity_set_t> 24147 | (disabled_arithmetic_set_, disabled_arithmetic_set_.begin())); 24148 | return (*this); 24149 | } 24150 | 24151 | settings_store& disable_all_assignment_ops() 24152 | { 24153 | std::copy(details::assignment_ops_list, 24154 | details::assignment_ops_list + details::assignment_ops_list_size, 24155 | std::insert_iterator<disabled_entity_set_t> 24156 | (disabled_assignment_set_, disabled_assignment_set_.begin())); 24157 | return (*this); 24158 | } 24159 | 24160 | settings_store& disable_all_inequality_ops() 24161 | { 24162 | std::copy(details::inequality_ops_list, 24163 | details::inequality_ops_list + details::inequality_ops_list_size, 24164 | std::insert_iterator<disabled_entity_set_t> 24165 | (disabled_inequality_set_, disabled_inequality_set_.begin())); 24166 | return (*this); 24167 | } 24168 | 24169 | settings_store& disable_local_vardef() 24170 | { 24171 | disable_vardef_ = true; 24172 | return (*this); 24173 | } 24174 | 24175 | settings_store& disable_commutative_check() 24176 | { 24177 | enable_commutative_check_ = false; 24178 | return (*this); 24179 | } 24180 | 24181 | settings_store& disable_strength_reduction() 24182 | { 24183 | enable_strength_reduction_ = false; 24184 | return (*this); 24185 | } 24186 | 24187 | bool replacer_enabled () const { return enable_replacer_; } 24188 | bool commutative_check_enabled () const { return enable_commutative_check_; } 24189 | bool joiner_enabled () const { return enable_joiner_; } 24190 | bool numeric_check_enabled () const { return enable_numeric_check_; } 24191 | bool bracket_check_enabled () const { return enable_bracket_check_; } 24192 | bool sequence_check_enabled () const { return enable_sequence_check_; } 24193 | bool strength_reduction_enabled () const { return enable_strength_reduction_; } 24194 | bool collect_variables_enabled () const { return enable_collect_vars_; } 24195 | bool collect_functions_enabled () const { return enable_collect_funcs_; } 24196 | bool collect_assignments_enabled() const { return enable_collect_assings_; } 24197 | bool vardef_disabled () const { return disable_vardef_; } 24198 | bool rsrvd_sym_usr_disabled () const { return disable_rsrvd_sym_usr_; } 24199 | bool zero_return_disabled () const { return disable_zero_return_; } 24200 | 24201 | bool function_enabled(const std::string& function_name) const 24202 | { 24203 | if (disabled_func_set_.empty()) 24204 | return true; 24205 | else 24206 | return (disabled_func_set_.end() == disabled_func_set_.find(function_name)); 24207 | } 24208 | 24209 | bool control_struct_enabled(const std::string& control_struct) const 24210 | { 24211 | if (disabled_ctrl_set_.empty()) 24212 | return true; 24213 | else 24214 | return (disabled_ctrl_set_.end() == disabled_ctrl_set_.find(control_struct)); 24215 | } 24216 | 24217 | bool logic_enabled(const std::string& logic_operation) const 24218 | { 24219 | if (disabled_logic_set_.empty()) 24220 | return true; 24221 | else 24222 | return (disabled_logic_set_.end() == disabled_logic_set_.find(logic_operation)); 24223 | } 24224 | 24225 | bool arithmetic_enabled(const details::operator_type& arithmetic_operation) const 24226 | { 24227 | if (disabled_logic_set_.empty()) 24228 | return true; 24229 | else 24230 | return disabled_arithmetic_set_.end() == disabled_arithmetic_set_ 24231 | .find(arith_opr_to_string(arithmetic_operation)); 24232 | } 24233 | 24234 | bool assignment_enabled(const details::operator_type& assignment) const 24235 | { 24236 | if (disabled_assignment_set_.empty()) 24237 | return true; 24238 | else 24239 | return disabled_assignment_set_.end() == disabled_assignment_set_ 24240 | .find(assign_opr_to_string(assignment)); 24241 | } 24242 | 24243 | bool inequality_enabled(const details::operator_type& inequality) const 24244 | { 24245 | if (disabled_inequality_set_.empty()) 24246 | return true; 24247 | else 24248 | return disabled_inequality_set_.end() == disabled_inequality_set_ 24249 | .find(inequality_opr_to_string(inequality)); 24250 | } 24251 | 24252 | bool function_disabled(const std::string& function_name) const 24253 | { 24254 | if (disabled_func_set_.empty()) 24255 | return false; 24256 | else 24257 | return (disabled_func_set_.end() != disabled_func_set_.find(function_name)); 24258 | } 24259 | 24260 | bool control_struct_disabled(const std::string& control_struct) const 24261 | { 24262 | if (disabled_ctrl_set_.empty()) 24263 | return false; 24264 | else 24265 | return (disabled_ctrl_set_.end() != disabled_ctrl_set_.find(control_struct)); 24266 | } 24267 | 24268 | bool logic_disabled(const std::string& logic_operation) const 24269 | { 24270 | if (disabled_logic_set_.empty()) 24271 | return false; 24272 | else 24273 | return (disabled_logic_set_.end() != disabled_logic_set_.find(logic_operation)); 24274 | } 24275 | 24276 | bool assignment_disabled(const details::operator_type assignment_operation) const 24277 | { 24278 | if (disabled_assignment_set_.empty()) 24279 | return false; 24280 | else 24281 | return disabled_assignment_set_.end() != disabled_assignment_set_ 24282 | .find(assign_opr_to_string(assignment_operation)); 24283 | } 24284 | 24285 | bool logic_disabled(const details::operator_type logic_operation) const 24286 | { 24287 | if (disabled_logic_set_.empty()) 24288 | return false; 24289 | else 24290 | return disabled_logic_set_.end() != disabled_logic_set_ 24291 | .find(logic_opr_to_string(logic_operation)); 24292 | } 24293 | 24294 | bool arithmetic_disabled(const details::operator_type arithmetic_operation) const 24295 | { 24296 | if (disabled_arithmetic_set_.empty()) 24297 | return false; 24298 | else 24299 | return disabled_arithmetic_set_.end() != disabled_arithmetic_set_ 24300 | .find(arith_opr_to_string(arithmetic_operation)); 24301 | } 24302 | 24303 | bool inequality_disabled(const details::operator_type& inequality) const 24304 | { 24305 | if (disabled_inequality_set_.empty()) 24306 | return false; 24307 | else 24308 | return disabled_inequality_set_.end() != disabled_inequality_set_ 24309 | .find(inequality_opr_to_string(inequality)); 24310 | } 24311 | 24312 | settings_store& disable_base_function(const settings_base_funcs bf) 24313 | { 24314 | if ( 24315 | (e_bf_unknown != bf) && 24316 | (static_cast<std::size_t>(bf) < (details::base_function_list_size + 1)) 24317 | ) 24318 | { 24319 | disabled_func_set_.insert(details::base_function_list[bf - 1]); 24320 | } 24321 | 24322 | return (*this); 24323 | } 24324 | 24325 | settings_store& disable_control_structure(const settings_control_structs ctrl_struct) 24326 | { 24327 | if ( 24328 | (e_ctrl_unknown != ctrl_struct) && 24329 | (static_cast<std::size_t>(ctrl_struct) < (details::cntrl_struct_list_size + 1)) 24330 | ) 24331 | { 24332 | disabled_ctrl_set_.insert(details::cntrl_struct_list[ctrl_struct - 1]); 24333 | } 24334 | 24335 | return (*this); 24336 | } 24337 | 24338 | settings_store& disable_logic_operation(const settings_logic_opr logic) 24339 | { 24340 | if ( 24341 | (e_logic_unknown != logic) && 24342 | (static_cast<std::size_t>(logic) < (details::logic_ops_list_size + 1)) 24343 | ) 24344 | { 24345 | disabled_logic_set_.insert(details::logic_ops_list[logic - 1]); 24346 | } 24347 | 24348 | return (*this); 24349 | } 24350 | 24351 | settings_store& disable_arithmetic_operation(const settings_arithmetic_opr arithmetic) 24352 | { 24353 | if ( 24354 | (e_arith_unknown != arithmetic) && 24355 | (static_cast<std::size_t>(arithmetic) < (details::arithmetic_ops_list_size + 1)) 24356 | ) 24357 | { 24358 | disabled_arithmetic_set_.insert(details::arithmetic_ops_list[arithmetic - 1]); 24359 | } 24360 | 24361 | return (*this); 24362 | } 24363 | 24364 | settings_store& disable_assignment_operation(const settings_assignment_opr assignment) 24365 | { 24366 | if ( 24367 | (e_assign_unknown != assignment) && 24368 | (static_cast<std::size_t>(assignment) < (details::assignment_ops_list_size + 1)) 24369 | ) 24370 | { 24371 | disabled_assignment_set_.insert(details::assignment_ops_list[assignment - 1]); 24372 | } 24373 | 24374 | return (*this); 24375 | } 24376 | 24377 | settings_store& disable_inequality_operation(const settings_inequality_opr inequality) 24378 | { 24379 | if ( 24380 | (e_ineq_unknown != inequality) && 24381 | (static_cast<std::size_t>(inequality) < (details::inequality_ops_list_size + 1)) 24382 | ) 24383 | { 24384 | disabled_inequality_set_.insert(details::inequality_ops_list[inequality - 1]); 24385 | } 24386 | 24387 | return (*this); 24388 | } 24389 | 24390 | settings_store& enable_base_function(const settings_base_funcs bf) 24391 | { 24392 | if ( 24393 | (e_bf_unknown != bf) && 24394 | (static_cast<std::size_t>(bf) < (details::base_function_list_size + 1)) 24395 | ) 24396 | { 24397 | const des_itr_t itr = disabled_func_set_.find(details::base_function_list[bf - 1]); 24398 | 24399 | if (disabled_func_set_.end() != itr) 24400 | { 24401 | disabled_func_set_.erase(itr); 24402 | } 24403 | } 24404 | 24405 | return (*this); 24406 | } 24407 | 24408 | settings_store& enable_control_structure(const settings_control_structs ctrl_struct) 24409 | { 24410 | if ( 24411 | (e_ctrl_unknown != ctrl_struct) && 24412 | (static_cast<std::size_t>(ctrl_struct) < (details::cntrl_struct_list_size + 1)) 24413 | ) 24414 | { 24415 | const des_itr_t itr = disabled_ctrl_set_.find(details::cntrl_struct_list[ctrl_struct - 1]); 24416 | 24417 | if (disabled_ctrl_set_.end() != itr) 24418 | { 24419 | disabled_ctrl_set_.erase(itr); 24420 | } 24421 | } 24422 | 24423 | return (*this); 24424 | } 24425 | 24426 | settings_store& enable_logic_operation(const settings_logic_opr logic) 24427 | { 24428 | if ( 24429 | (e_logic_unknown != logic) && 24430 | (static_cast<std::size_t>(logic) < (details::logic_ops_list_size + 1)) 24431 | ) 24432 | { 24433 | const des_itr_t itr = disabled_logic_set_.find(details::logic_ops_list[logic - 1]); 24434 | 24435 | if (disabled_logic_set_.end() != itr) 24436 | { 24437 | disabled_logic_set_.erase(itr); 24438 | } 24439 | } 24440 | 24441 | return (*this); 24442 | } 24443 | 24444 | settings_store& enable_arithmetic_operation(const settings_arithmetic_opr arithmetic) 24445 | { 24446 | if ( 24447 | (e_arith_unknown != arithmetic) && 24448 | (static_cast<std::size_t>(arithmetic) < (details::arithmetic_ops_list_size + 1)) 24449 | ) 24450 | { 24451 | const des_itr_t itr = disabled_arithmetic_set_.find(details::arithmetic_ops_list[arithmetic - 1]); 24452 | 24453 | if (disabled_arithmetic_set_.end() != itr) 24454 | { 24455 | disabled_arithmetic_set_.erase(itr); 24456 | } 24457 | } 24458 | 24459 | return (*this); 24460 | } 24461 | 24462 | settings_store& enable_assignment_operation(const settings_assignment_opr assignment) 24463 | { 24464 | if ( 24465 | (e_assign_unknown != assignment) && 24466 | (static_cast<std::size_t>(assignment) < (details::assignment_ops_list_size + 1)) 24467 | ) 24468 | { 24469 | const des_itr_t itr = disabled_assignment_set_.find(details::assignment_ops_list[assignment - 1]); 24470 | 24471 | if (disabled_assignment_set_.end() != itr) 24472 | { 24473 | disabled_assignment_set_.erase(itr); 24474 | } 24475 | } 24476 | 24477 | return (*this); 24478 | } 24479 | 24480 | settings_store& enable_inequality_operation(const settings_inequality_opr inequality) 24481 | { 24482 | if ( 24483 | (e_ineq_unknown != inequality) && 24484 | (static_cast<std::size_t>(inequality) < (details::inequality_ops_list_size + 1)) 24485 | ) 24486 | { 24487 | const des_itr_t itr = disabled_inequality_set_.find(details::inequality_ops_list[inequality - 1]); 24488 | 24489 | if (disabled_inequality_set_.end() != itr) 24490 | { 24491 | disabled_inequality_set_.erase(itr); 24492 | } 24493 | } 24494 | 24495 | return (*this); 24496 | } 24497 | 24498 | void set_max_stack_depth(const std::size_t max_stack_depth) 24499 | { 24500 | max_stack_depth_ = max_stack_depth; 24501 | } 24502 | 24503 | void set_max_node_depth(const std::size_t max_node_depth) 24504 | { 24505 | max_node_depth_ = max_node_depth; 24506 | } 24507 | 24508 | void set_max_local_vector_size(const std::size_t max_local_vector_size) 24509 | { 24510 | max_local_vector_size_ = max_local_vector_size; 24511 | } 24512 | 24513 | void set_max_total_local_symbol_size_bytes(const std::size_t max_total_lcl_symb_size) 24514 | { 24515 | max_total_local_symbol_size_bytes_ = max_total_lcl_symb_size; 24516 | } 24517 | 24518 | std::size_t max_stack_depth() const 24519 | { 24520 | return max_stack_depth_; 24521 | } 24522 | 24523 | std::size_t max_node_depth() const 24524 | { 24525 | return max_node_depth_; 24526 | } 24527 | 24528 | std::size_t max_local_vector_size() const 24529 | { 24530 | return max_local_vector_size_; 24531 | } 24532 | 24533 | std::size_t max_total_local_symbol_size_bytes() const 24534 | { 24535 | return max_total_local_symbol_size_bytes_; 24536 | } 24537 | 24538 | private: 24539 | 24540 | void load_compile_options(const std::size_t compile_options) 24541 | { 24542 | enable_replacer_ = (compile_options & e_replacer ) == e_replacer; 24543 | enable_joiner_ = (compile_options & e_joiner ) == e_joiner; 24544 | enable_numeric_check_ = (compile_options & e_numeric_check ) == e_numeric_check; 24545 | enable_bracket_check_ = (compile_options & e_bracket_check ) == e_bracket_check; 24546 | enable_sequence_check_ = (compile_options & e_sequence_check ) == e_sequence_check; 24547 | enable_commutative_check_ = (compile_options & e_commutative_check ) == e_commutative_check; 24548 | enable_strength_reduction_ = (compile_options & e_strength_reduction ) == e_strength_reduction; 24549 | enable_collect_vars_ = (compile_options & e_collect_vars ) == e_collect_vars; 24550 | enable_collect_funcs_ = (compile_options & e_collect_funcs ) == e_collect_funcs; 24551 | enable_collect_assings_ = (compile_options & e_collect_assings ) == e_collect_assings; 24552 | disable_vardef_ = (compile_options & e_disable_vardef ) == e_disable_vardef; 24553 | disable_rsrvd_sym_usr_ = (compile_options & e_disable_usr_on_rsrvd) == e_disable_usr_on_rsrvd; 24554 | disable_zero_return_ = (compile_options & e_disable_zero_return ) == e_disable_zero_return; 24555 | } 24556 | 24557 | std::string assign_opr_to_string(details::operator_type opr) const 24558 | { 24559 | switch (opr) 24560 | { 24561 | case details::e_assign : return ":=" 24562 | case details::e_addass : return "+=" 24563 | case details::e_subass : return "-=" 24564 | case details::e_mulass : return "*=" 24565 | case details::e_divass : return "/=" 24566 | case details::e_modass : return "%=" 24567 | default : return "" ; 24568 | } 24569 | } 24570 | 24571 | std::string arith_opr_to_string(details::operator_type opr) const 24572 | { 24573 | switch (opr) 24574 | { 24575 | case details::e_add : return "+" 24576 | case details::e_sub : return "-" 24577 | case details::e_mul : return "*" 24578 | case details::e_div : return "/" 24579 | case details::e_mod : return "%" 24580 | case details::e_pow : return "^" 24581 | default : return "" ; 24582 | } 24583 | } 24584 | 24585 | std::string inequality_opr_to_string(details::operator_type opr) const 24586 | { 24587 | switch (opr) 24588 | { 24589 | case details::e_lt : return "<" ; 24590 | case details::e_lte : return "<=" 24591 | case details::e_eq : return "==" 24592 | case details::e_equal : return "=" ; 24593 | case details::e_ne : return "!=" 24594 | case details::e_nequal: return "<>" 24595 | case details::e_gte : return ">=" 24596 | case details::e_gt : return ">" ; 24597 | default : return "" ; 24598 | } 24599 | } 24600 | 24601 | std::string logic_opr_to_string(details::operator_type opr) const 24602 | { 24603 | switch (opr) 24604 | { 24605 | case details::e_and : return "and" ; 24606 | case details::e_or : return "or" ; 24607 | case details::e_xor : return "xor" ; 24608 | case details::e_nand : return "nand" 24609 | case details::e_nor : return "nor" ; 24610 | case details::e_xnor : return "xnor" 24611 | case details::e_notl : return "not" ; 24612 | default : return "" ; 24613 | } 24614 | } 24615 | 24616 | bool enable_replacer_; 24617 | bool enable_joiner_; 24618 | bool enable_numeric_check_; 24619 | bool enable_bracket_check_; 24620 | bool enable_sequence_check_; 24621 | bool enable_commutative_check_; 24622 | bool enable_strength_reduction_; 24623 | bool enable_collect_vars_; 24624 | bool enable_collect_funcs_; 24625 | bool enable_collect_assings_; 24626 | bool disable_vardef_; 24627 | bool disable_rsrvd_sym_usr_; 24628 | bool disable_zero_return_; 24629 | 24630 | disabled_entity_set_t disabled_func_set_ ; 24631 | disabled_entity_set_t disabled_ctrl_set_ ; 24632 | disabled_entity_set_t disabled_logic_set_; 24633 | disabled_entity_set_t disabled_arithmetic_set_; 24634 | disabled_entity_set_t disabled_assignment_set_; 24635 | disabled_entity_set_t disabled_inequality_set_; 24636 | 24637 | std::size_t max_stack_depth_; 24638 | std::size_t max_node_depth_; 24639 | std::size_t max_total_local_symbol_size_bytes_; 24640 | std::size_t max_local_vector_size_; 24641 | 24642 | friend class parser<T>; 24643 | }; 24644 | 24645 | typedef settings_store settings_t; 24646 | 24647 | explicit parser(const settings_t& settings = settings_t()) 24648 | : settings_(settings) 24649 | , resolve_unknown_symbol_(false) 24650 | , results_context_(0) 24651 | , unknown_symbol_resolver_(reinterpret_cast<unknown_symbol_resolver*>(0)) 24652 | #ifdef _MSC_VER 24653 | #pragma warning(push) 24654 | #pragma warning (disable:4355) 24655 | #endif 24656 | , sem_(*this) 24657 | #ifdef _MSC_VER 24658 | #pragma warning(pop) 24659 | #endif 24660 | , operator_joiner_2_(2) 24661 | , operator_joiner_3_(3) 24662 | , loop_runtime_check_(0) 24663 | , vector_access_runtime_check_(0) 24664 | , compilation_check_ptr_(0) 24665 | , assert_check_(0) 24666 | { 24667 | init_precompilation(); 24668 | 24669 | load_operations_map (base_ops_map_ ); 24670 | load_unary_operations_map (unary_op_map_ ); 24671 | load_binary_operations_map (binary_op_map_ ); 24672 | load_inv_binary_operations_map(inv_binary_op_map_); 24673 | load_sf3_map (sf3_map_ ); 24674 | load_sf4_map (sf4_map_ ); 24675 | 24676 | expression_generator_.init_synthesize_map(); 24677 | expression_generator_.set_parser(*this); 24678 | expression_generator_.set_uom (unary_op_map_ ); 24679 | expression_generator_.set_bom (binary_op_map_ ); 24680 | expression_generator_.set_ibom(inv_binary_op_map_); 24681 | expression_generator_.set_sf3m(sf3_map_ ); 24682 | expression_generator_.set_sf4m(sf4_map_ ); 24683 | expression_generator_.set_strength_reduction_state(settings_.strength_reduction_enabled()); 24684 | } 24685 | 24686 | ~parser() 24687 | {} 24688 | 24689 | inline void init_precompilation() 24690 | { 24691 | dec_.collect_variables() = 24692 | settings_.collect_variables_enabled(); 24693 | 24694 | dec_.collect_functions() = 24695 | settings_.collect_functions_enabled(); 24696 | 24697 | dec_.collect_assignments() = 24698 | settings_.collect_assignments_enabled(); 24699 | 24700 | if (settings_.replacer_enabled()) 24701 | { 24702 | symbol_replacer_.clear(); 24703 | symbol_replacer_.add_replace("true" , "1", lexer::token::e_number); 24704 | symbol_replacer_.add_replace("false", "0", lexer::token::e_number); 24705 | helper_assembly_.token_modifier_list.clear(); 24706 | helper_assembly_.register_modifier(&symbol_replacer_); 24707 | } 24708 | 24709 | if (settings_.commutative_check_enabled()) 24710 | { 24711 | for (std::size_t i = 0; i < details::reserved_words_size; ++i) 24712 | { 24713 | commutative_inserter_.ignore_symbol(details::reserved_words[i]); 24714 | } 24715 | 24716 | helper_assembly_.token_inserter_list.clear(); 24717 | helper_assembly_.register_inserter(&commutative_inserter_); 24718 | } 24719 | 24720 | if (settings_.joiner_enabled()) 24721 | { 24722 | helper_assembly_.token_joiner_list.clear(); 24723 | helper_assembly_.register_joiner(&operator_joiner_2_); 24724 | helper_assembly_.register_joiner(&operator_joiner_3_); 24725 | } 24726 | 24727 | if ( 24728 | settings_.numeric_check_enabled () || 24729 | settings_.bracket_check_enabled () || 24730 | settings_.sequence_check_enabled() 24731 | ) 24732 | { 24733 | helper_assembly_.token_scanner_list.clear(); 24734 | 24735 | if (settings_.numeric_check_enabled()) 24736 | { 24737 | helper_assembly_.register_scanner(&numeric_checker_); 24738 | } 24739 | 24740 | if (settings_.bracket_check_enabled()) 24741 | { 24742 | helper_assembly_.register_scanner(&bracket_checker_); 24743 | } 24744 | 24745 | if (settings_.sequence_check_enabled()) 24746 | { 24747 | helper_assembly_.register_scanner(&sequence_validator_ ); 24748 | helper_assembly_.register_scanner(&sequence_validator_3tkns_); 24749 | } 24750 | } 24751 | } 24752 | 24753 | inline bool compile(const std::string& expression_string, expression<T>& expr) 24754 | { 24755 | state_ .reset(); 24756 | error_list_ .clear(); 24757 | brkcnt_list_ .clear(); 24758 | synthesis_error_ .clear(); 24759 | immutable_memory_map_.reset(); 24760 | immutable_symtok_map_.clear(); 24761 | current_state_stack_ .clear(); 24762 | assert_ids_ .clear(); 24763 | sem_ .cleanup(); 24764 | 24765 | return_cleanup(); 24766 | 24767 | if (!valid_settings()) 24768 | { 24769 | return false; 24770 | } 24771 | 24772 | expression_generator_.set_allocator(node_allocator_); 24773 | 24774 | if (expression_string.empty()) 24775 | { 24776 | set_error(make_error( 24777 | parser_error::e_syntax, 24778 | "ERR001 - Empty expression!", 24779 | exprtk_error_location)); 24780 | 24781 | return false; 24782 | } 24783 | 24784 | if (!init(expression_string)) 24785 | { 24786 | process_lexer_errors(); 24787 | return false; 24788 | } 24789 | 24790 | if (lexer().empty()) 24791 | { 24792 | set_error(make_error( 24793 | parser_error::e_syntax, 24794 | "ERR002 - Empty expression!", 24795 | exprtk_error_location)); 24796 | 24797 | return false; 24798 | } 24799 | 24800 | if (halt_compilation_check()) 24801 | { 24802 | exprtk_debug(("halt_compilation_check() - compile checkpoint 0\n")); 24803 | sem_.cleanup(); 24804 | return false; 24805 | } 24806 | 24807 | if (!run_assemblies()) 24808 | { 24809 | sem_.cleanup(); 24810 | return false; 24811 | } 24812 | 24813 | if (halt_compilation_check()) 24814 | { 24815 | exprtk_debug(("halt_compilation_check() - compile checkpoint 1\n")); 24816 | sem_.cleanup(); 24817 | return false; 24818 | } 24819 | 24820 | symtab_store_.symtab_list_ = expr.get_symbol_table_list(); 24821 | dec_.clear(); 24822 | 24823 | lexer().begin(); 24824 | 24825 | next_token(); 24826 | 24827 | expression_node_ptr e = parse_corpus(); 24828 | 24829 | if ((0 != e) && (token_t::e_eof == current_token().type)) 24830 | { 24831 | bool* retinvk_ptr = 0; 24832 | 24833 | if (state_.return_stmt_present) 24834 | { 24835 | dec_.return_present_ = true; 24836 | 24837 | e = expression_generator_ 24838 | .return_envelope(e, results_context_, retinvk_ptr); 24839 | } 24840 | 24841 | expr.set_expression(e); 24842 | expr.set_retinvk(retinvk_ptr); 24843 | 24844 | register_local_vars(expr); 24845 | register_return_results(expr); 24846 | 24847 | return !(!expr); 24848 | } 24849 | else 24850 | { 24851 | if (error_list_.empty()) 24852 | { 24853 | set_error(make_error( 24854 | parser_error::e_syntax, 24855 | current_token(), 24856 | "ERR003 - Invalid expression encountered", 24857 | exprtk_error_location)); 24858 | } 24859 | 24860 | if ((0 != e) && branch_deletable(e)) 24861 | { 24862 | destroy_node(e); 24863 | } 24864 | 24865 | dec_.clear (); 24866 | sem_.cleanup (); 24867 | return_cleanup(); 24868 | expr = expression_t(); 24869 | 24870 | return false; 24871 | } 24872 | } 24873 | 24874 | inline expression_t compile(const std::string& expression_string, symbol_table_t& symtab) 24875 | { 24876 | expression_t expression; 24877 | expression.register_symbol_table(symtab); 24878 | compile(expression_string,expression); 24879 | return expression; 24880 | } 24881 | 24882 | void process_lexer_errors() 24883 | { 24884 | for (std::size_t i = 0; i < lexer().size(); ++i) 24885 | { 24886 | if (lexer()[i].is_error()) 24887 | { 24888 | std::string diagnostic = "ERR004 - " 24889 | 24890 | switch (lexer()[i].type) 24891 | { 24892 | case lexer::token::e_error : diagnostic += "General token error" 24893 | break; 24894 | 24895 | case lexer::token::e_err_symbol : diagnostic += "Symbol error" 24896 | break; 24897 | 24898 | case lexer::token::e_err_number : diagnostic += "Invalid numeric token" 24899 | break; 24900 | 24901 | case lexer::token::e_err_string : diagnostic += "Invalid string token" 24902 | break; 24903 | 24904 | case lexer::token::e_err_sfunc : diagnostic += "Invalid special function token" 24905 | break; 24906 | 24907 | default : diagnostic += "Unknown compiler error" 24908 | } 24909 | 24910 | set_error(make_error( 24911 | parser_error::e_lexer, 24912 | lexer()[i], 24913 | diagnostic + ": " + lexer()[i].value, 24914 | exprtk_error_location)); 24915 | } 24916 | } 24917 | } 24918 | 24919 | inline bool run_assemblies() 24920 | { 24921 | if (settings_.commutative_check_enabled()) 24922 | { 24923 | helper_assembly_.run_inserters(lexer()); 24924 | } 24925 | 24926 | if (settings_.joiner_enabled()) 24927 | { 24928 | helper_assembly_.run_joiners(lexer()); 24929 | } 24930 | 24931 | if (settings_.replacer_enabled()) 24932 | { 24933 | helper_assembly_.run_modifiers(lexer()); 24934 | } 24935 | 24936 | if ( 24937 | settings_.numeric_check_enabled () || 24938 | settings_.bracket_check_enabled () || 24939 | settings_.sequence_check_enabled() 24940 | ) 24941 | { 24942 | if (!helper_assembly_.run_scanners(lexer())) 24943 | { 24944 | if (helper_assembly_.error_token_scanner) 24945 | { 24946 | lexer::helper::bracket_checker* bracket_checker_ptr = 0; 24947 | lexer::helper::numeric_checker<T>* numeric_checker_ptr = 0; 24948 | lexer::helper::sequence_validator* sequence_validator_ptr = 0; 24949 | lexer::helper::sequence_validator_3tokens* sequence_validator3_ptr = 0; 24950 | 24951 | if (0 != (bracket_checker_ptr = dynamic_cast<lexer::helper::bracket_checker*>(helper_assembly_.error_token_scanner))) 24952 | { 24953 | set_error(make_error( 24954 | parser_error::e_token, 24955 | bracket_checker_ptr->error_token(), 24956 | "ERR005 - Mismatched brackets: '" + bracket_checker_ptr->error_token().value + "'", 24957 | exprtk_error_location)); 24958 | } 24959 | else if (0 != (numeric_checker_ptr = dynamic_cast<lexer::helper::numeric_checker<T>*>(helper_assembly_.error_token_scanner))) 24960 | { 24961 | for (std::size_t i = 0; i < numeric_checker_ptr->error_count(); ++i) 24962 | { 24963 | lexer::token error_token = lexer()[numeric_checker_ptr->error_index(i)]; 24964 | 24965 | set_error(make_error( 24966 | parser_error::e_token, 24967 | error_token, 24968 | "ERR006 - Invalid numeric token: '" + error_token.value + "'", 24969 | exprtk_error_location)); 24970 | } 24971 | 24972 | if (numeric_checker_ptr->error_count()) 24973 | { 24974 | numeric_checker_ptr->clear_errors(); 24975 | } 24976 | } 24977 | else if (0 != (sequence_validator_ptr = dynamic_cast<lexer::helper::sequence_validator*>(helper_assembly_.error_token_scanner))) 24978 | { 24979 | for (std::size_t i = 0; i < sequence_validator_ptr->error_count(); ++i) 24980 | { 24981 | std::pair<lexer::token,lexer::token> error_token = sequence_validator_ptr->error(i); 24982 | 24983 | set_error(make_error( 24984 | parser_error::e_token, 24985 | error_token.first, 24986 | "ERR007 - Invalid token sequence: '" + 24987 | error_token.first.value + "' and '" + 24988 | error_token.second.value + "'", 24989 | exprtk_error_location)); 24990 | } 24991 | 24992 | if (sequence_validator_ptr->error_count()) 24993 | { 24994 | sequence_validator_ptr->clear_errors(); 24995 | } 24996 | } 24997 | else if (0 != (sequence_validator3_ptr = dynamic_cast<lexer::helper::sequence_validator_3tokens*>(helper_assembly_.error_token_scanner))) 24998 | { 24999 | for (std::size_t i = 0; i < sequence_validator3_ptr->error_count(); ++i) 25000 | { 25001 | std::pair<lexer::token,lexer::token> error_token = sequence_validator3_ptr->error(i); 25002 | 25003 | set_error(make_error( 25004 | parser_error::e_token, 25005 | error_token.first, 25006 | "ERR008 - Invalid token sequence: '" + 25007 | error_token.first.value + "' and '" + 25008 | error_token.second.value + "'", 25009 | exprtk_error_location)); 25010 | } 25011 | 25012 | if (sequence_validator3_ptr->error_count()) 25013 | { 25014 | sequence_validator3_ptr->clear_errors(); 25015 | } 25016 | } 25017 | } 25018 | 25019 | return false; 25020 | } 25021 | } 25022 | 25023 | return true; 25024 | } 25025 | 25026 | inline settings_store& settings() 25027 | { 25028 | return settings_; 25029 | } 25030 | 25031 | inline parser_error::type get_error(const std::size_t& index) const 25032 | { 25033 | if (index < error_list_.size()) 25034 | { 25035 | return error_list_[index]; 25036 | } 25037 | 25038 | throw std::invalid_argument("parser::get_error() - Invalid error index specified"); 25039 | } 25040 | 25041 | inline std::string error() const 25042 | { 25043 | if (!error_list_.empty()) 25044 | { 25045 | return error_list_[0].diagnostic; 25046 | } 25047 | else 25048 | return std::string("No Error"); 25049 | } 25050 | 25051 | inline std::size_t error_count() const 25052 | { 25053 | return error_list_.size(); 25054 | } 25055 | 25056 | inline dependent_entity_collector& dec() 25057 | { 25058 | return dec_; 25059 | } 25060 | 25061 | inline std::size_t total_local_symbol_size_bytes() const 25062 | { 25063 | return sem_.total_local_symb_size_bytes(); 25064 | } 25065 | 25066 | inline bool replace_symbol(const std::string& old_symbol, const std::string& new_symbol) 25067 | { 25068 | if (!settings_.replacer_enabled()) 25069 | return false; 25070 | else if (details::is_reserved_word(old_symbol)) 25071 | return false; 25072 | else 25073 | return symbol_replacer_.add_replace(old_symbol,new_symbol,lexer::token::e_symbol); 25074 | } 25075 | 25076 | inline bool remove_replace_symbol(const std::string& symbol) 25077 | { 25078 | if (!settings_.replacer_enabled()) 25079 | return false; 25080 | else if (details::is_reserved_word(symbol)) 25081 | return false; 25082 | else 25083 | return symbol_replacer_.remove(symbol); 25084 | } 25085 | 25086 | inline void enable_unknown_symbol_resolver(unknown_symbol_resolver* usr = reinterpret_cast<unknown_symbol_resolver*>(0)) 25087 | { 25088 | resolve_unknown_symbol_ = true; 25089 | 25090 | if (usr) 25091 | unknown_symbol_resolver_ = usr; 25092 | else 25093 | unknown_symbol_resolver_ = &default_usr_; 25094 | } 25095 | 25096 | inline void enable_unknown_symbol_resolver(unknown_symbol_resolver& usr) 25097 | { 25098 | enable_unknown_symbol_resolver(&usr); 25099 | } 25100 | 25101 | inline void disable_unknown_symbol_resolver() 25102 | { 25103 | resolve_unknown_symbol_ = false; 25104 | unknown_symbol_resolver_ = &default_usr_; 25105 | } 25106 | 25107 | inline void register_loop_runtime_check(loop_runtime_check& lrtchk) 25108 | { 25109 | loop_runtime_check_ = &lrtchk; 25110 | } 25111 | 25112 | inline void register_vector_access_runtime_check(vector_access_runtime_check& vartchk) 25113 | { 25114 | vector_access_runtime_check_ = &vartchk; 25115 | } 25116 | 25117 | inline void register_compilation_timeout_check(compilation_check& compchk) 25118 | { 25119 | compilation_check_ptr_ = &compchk; 25120 | } 25121 | 25122 | inline void register_assert_check(assert_check& assrt_chck) 25123 | { 25124 | assert_check_ = &assrt_chck; 25125 | } 25126 | 25127 | inline void clear_loop_runtime_check() 25128 | { 25129 | loop_runtime_check_ = loop_runtime_check_ptr(0); 25130 | } 25131 | 25132 | inline void clear_vector_access_runtime_check() 25133 | { 25134 | vector_access_runtime_check_ = vector_access_runtime_check_ptr(0); 25135 | } 25136 | 25137 | inline void clear_compilation_timeout_check() 25138 | { 25139 | compilation_check_ptr_ = compilation_check_ptr(0); 25140 | } 25141 | 25142 | inline void clear_assert_check() 25143 | { 25144 | assert_check_ = assert_check_ptr(0); 25145 | } 25146 | 25147 | private: 25148 | 25149 | inline bool valid_base_operation(const std::string& symbol) const 25150 | { 25151 | const std::size_t length = symbol.size(); 25152 | 25153 | if ( 25154 | (length < 3) || // Shortest base op symbol length 25155 | (length > 9) // Longest base op symbol length 25156 | ) 25157 | return false; 25158 | else 25159 | return settings_.function_enabled(symbol) && 25160 | (base_ops_map_.end() != base_ops_map_.find(symbol)); 25161 | } 25162 | 25163 | inline bool valid_vararg_operation(const std::string& symbol) const 25164 | { 25165 | static const std::string s_sum = "sum" ; 25166 | static const std::string s_mul = "mul" ; 25167 | static const std::string s_avg = "avg" ; 25168 | static const std::string s_min = "min" ; 25169 | static const std::string s_max = "max" ; 25170 | static const std::string s_mand = "mand" 25171 | static const std::string s_mor = "mor" ; 25172 | static const std::string s_multi = "~" ; 25173 | static const std::string s_mswitch = "[*]" ; 25174 | 25175 | return 25176 | ( 25177 | details::imatch(symbol,s_sum ) || 25178 | details::imatch(symbol,s_mul ) || 25179 | details::imatch(symbol,s_avg ) || 25180 | details::imatch(symbol,s_min ) || 25181 | details::imatch(symbol,s_max ) || 25182 | details::imatch(symbol,s_mand ) || 25183 | details::imatch(symbol,s_mor ) || 25184 | details::imatch(symbol,s_multi ) || 25185 | details::imatch(symbol,s_mswitch) 25186 | ) && 25187 | settings_.function_enabled(symbol); 25188 | } 25189 | 25190 | bool is_invalid_logic_operation(const details::operator_type operation) const 25191 | { 25192 | return settings_.logic_disabled(operation); 25193 | } 25194 | 25195 | bool is_invalid_arithmetic_operation(const details::operator_type operation) const 25196 | { 25197 | return settings_.arithmetic_disabled(operation); 25198 | } 25199 | 25200 | bool is_invalid_assignment_operation(const details::operator_type operation) const 25201 | { 25202 | return settings_.assignment_disabled(operation); 25203 | } 25204 | 25205 | bool is_invalid_inequality_operation(const details::operator_type operation) const 25206 | { 25207 | return settings_.inequality_disabled(operation); 25208 | } 25209 | 25210 | #ifdef exprtk_enable_debugging 25211 | inline void next_token() 25212 | { 25213 | const std::string ct_str = current_token().value; 25214 | const std::size_t ct_pos = current_token().position; 25215 | parser_helper::next_token(); 25216 | const std::string depth(2 * state_.scope_depth,' '); 25217 | exprtk_debug(("%s" 25218 | "prev[%s | %04d] --> curr[%s | %04d] stack_level: %3d\n", 25219 | depth.c_str(), 25220 | ct_str.c_str(), 25221 | static_cast<unsigned int>(ct_pos), 25222 | current_token().value.c_str(), 25223 | static_cast<unsigned int>(current_token().position), 25224 | static_cast<unsigned int>(state_.stack_depth))); 25225 | } 25226 | #endif 25227 | 25228 | inline expression_node_ptr parse_corpus() 25229 | { 25230 | std::vector<expression_node_ptr> arg_list; 25231 | std::vector<bool> side_effect_list; 25232 | 25233 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 25234 | 25235 | lexer::token begin_token; 25236 | lexer::token end_token; 25237 | 25238 | for ( ; ; ) 25239 | { 25240 | state_.side_effect_present = false; 25241 | 25242 | begin_token = current_token(); 25243 | 25244 | expression_node_ptr arg = parse_expression(); 25245 | 25246 | if (0 == arg) 25247 | { 25248 | if (error_list_.empty()) 25249 | { 25250 | set_error(make_error( 25251 | parser_error::e_syntax, 25252 | current_token(), 25253 | "ERR009 - Invalid expression encountered", 25254 | exprtk_error_location)); 25255 | } 25256 | 25257 | return error_node(); 25258 | } 25259 | else 25260 | { 25261 | arg_list.push_back(arg); 25262 | 25263 | side_effect_list.push_back(state_.side_effect_present); 25264 | 25265 | end_token = current_token(); 25266 | 25267 | const std::string sub_expr = construct_subexpr(begin_token, end_token); 25268 | 25269 | exprtk_debug(("parse_corpus(%02d) Subexpr: %s\n", 25270 | static_cast<int>(arg_list.size() - 1), 25271 | sub_expr.c_str())); 25272 | 25273 | exprtk_debug(("parse_corpus(%02d) - Side effect present: %s\n", 25274 | static_cast<int>(arg_list.size() - 1), 25275 | state_.side_effect_present ? "true" : "false")); 25276 | 25277 | exprtk_debug(("-------------------------------------------------\n")); 25278 | } 25279 | 25280 | if (token_is(token_t::e_eof,prsrhlpr_t::e_hold)) 25281 | { 25282 | if (lexer().finished()) 25283 | break; 25284 | else 25285 | next_token(); 25286 | } 25287 | else if ( 25288 | !settings_.commutative_check_enabled() && 25289 | ( 25290 | current_token().type == token_t::e_symbol || 25291 | current_token().type == token_t::e_number || 25292 | current_token().type == token_t::e_string || 25293 | token_is_bracket(prsrhlpr_t::e_hold) 25294 | ) 25295 | ) 25296 | { 25297 | set_error(make_error( 25298 | parser_error::e_syntax, 25299 | current_token(), 25300 | "ERR010 - Invalid syntax '" + current_token().value + "' possible missing operator or context", 25301 | exprtk_error_location)); 25302 | 25303 | return error_node(); 25304 | } 25305 | } 25306 | 25307 | if ( 25308 | !arg_list.empty() && 25309 | is_return_node(arg_list.back()) 25310 | ) 25311 | { 25312 | dec_.final_stmt_return_ = true; 25313 | } 25314 | 25315 | const expression_node_ptr result = simplify(arg_list,side_effect_list); 25316 | 25317 | svd.delete_ptr = (0 == result); 25318 | 25319 | return result; 25320 | } 25321 | 25322 | std::string construct_subexpr(lexer::token& begin_token, 25323 | lexer::token& end_token, 25324 | const bool cleanup_whitespace = true) 25325 | { 25326 | std::string result = lexer().substr(begin_token.position,end_token.position); 25327 | if (cleanup_whitespace) 25328 | { 25329 | for (std::size_t i = 0; i < result.size(); ++i) 25330 | { 25331 | if (details::is_whitespace(result[i])) result[i] = ' '; 25332 | } 25333 | } 25334 | 25335 | return result; 25336 | } 25337 | 25338 | static const precedence_level default_precedence = e_level00; 25339 | 25340 | struct state_t 25341 | { 25342 | inline void set(const precedence_level& l, 25343 | const precedence_level& r, 25344 | const details::operator_type& o, 25345 | const token_t& tkn = token_t()) 25346 | { 25347 | left = l; 25348 | right = r; 25349 | operation = o; 25350 | token = tkn; 25351 | } 25352 | 25353 | inline void reset() 25354 | { 25355 | left = e_level00; 25356 | right = e_level00; 25357 | operation = details::e_default; 25358 | } 25359 | 25360 | precedence_level left; 25361 | precedence_level right; 25362 | details::operator_type operation; 25363 | token_t token; 25364 | }; 25365 | 25366 | inline void push_current_state(const state_t current_state) 25367 | { 25368 | current_state_stack_.push_back(current_state); 25369 | } 25370 | 25371 | inline void pop_current_state() 25372 | { 25373 | if (!current_state_stack_.empty()) 25374 | { 25375 | current_state_stack_.pop_back(); 25376 | } 25377 | } 25378 | 25379 | inline state_t current_state() const 25380 | { 25381 | return (!current_state_stack_.empty()) ? 25382 | current_state_stack_.back() : 25383 | state_t(); 25384 | } 25385 | 25386 | inline bool halt_compilation_check() 25387 | { 25388 | compilation_check::compilation_context context; 25389 | 25390 | if (compilation_check_ptr_ && !compilation_check_ptr_->continue_compilation(context)) 25391 | { 25392 | const std::string error_message = 25393 | !context.error_message.empty() ? " Details: " + context.error_message : "" 25394 | 25395 | set_error(make_error( 25396 | parser_error::e_parser, 25397 | token_t(), 25398 | "ERR011 - Internal compilation check failed." + error_message, 25399 | exprtk_error_location)); 25400 | 25401 | return true; 25402 | } 25403 | 25404 | return false; 25405 | } 25406 | 25407 | inline expression_node_ptr parse_expression(precedence_level precedence = e_level00) 25408 | { 25409 | if (halt_compilation_check()) 25410 | { 25411 | exprtk_debug(("halt_compilation_check() - parse_expression checkpoint 2\n")); 25412 | return error_node(); 25413 | } 25414 | 25415 | stack_limit_handler slh(*this); 25416 | 25417 | if (!slh) 25418 | { 25419 | return error_node(); 25420 | } 25421 | 25422 | expression_node_ptr expression = parse_branch(precedence); 25423 | 25424 | if (0 == expression) 25425 | { 25426 | return error_node(); 25427 | } 25428 | 25429 | if (token_is(token_t::e_eof,prsrhlpr_t::e_hold)) 25430 | { 25431 | return expression; 25432 | } 25433 | 25434 | bool break_loop = false; 25435 | 25436 | state_t current_state; 25437 | 25438 | for ( ; ; ) 25439 | { 25440 | current_state.reset(); 25441 | 25442 | switch (current_token().type) 25443 | { 25444 | case token_t::e_assign : current_state.set(e_level00, e_level00, details::e_assign, current_token()); break; 25445 | case token_t::e_addass : current_state.set(e_level00, e_level00, details::e_addass, current_token()); break; 25446 | case token_t::e_subass : current_state.set(e_level00, e_level00, details::e_subass, current_token()); break; 25447 | case token_t::e_mulass : current_state.set(e_level00, e_level00, details::e_mulass, current_token()); break; 25448 | case token_t::e_divass : current_state.set(e_level00, e_level00, details::e_divass, current_token()); break; 25449 | case token_t::e_modass : current_state.set(e_level00, e_level00, details::e_modass, current_token()); break; 25450 | case token_t::e_swap : current_state.set(e_level00, e_level00, details::e_swap , current_token()); break; 25451 | case token_t::e_lt : current_state.set(e_level05, e_level06, details::e_lt , current_token()); break; 25452 | case token_t::e_lte : current_state.set(e_level05, e_level06, details::e_lte , current_token()); break; 25453 | case token_t::e_eq : current_state.set(e_level05, e_level06, details::e_eq , current_token()); break; 25454 | case token_t::e_ne : current_state.set(e_level05, e_level06, details::e_ne , current_token()); break; 25455 | case token_t::e_gte : current_state.set(e_level05, e_level06, details::e_gte , current_token()); break; 25456 | case token_t::e_gt : current_state.set(e_level05, e_level06, details::e_gt , current_token()); break; 25457 | case token_t::e_add : current_state.set(e_level07, e_level08, details::e_add , current_token()); break; 25458 | case token_t::e_sub : current_state.set(e_level07, e_level08, details::e_sub , current_token()); break; 25459 | case token_t::e_div : current_state.set(e_level10, e_level11, details::e_div , current_token()); break; 25460 | case token_t::e_mul : current_state.set(e_level10, e_level11, details::e_mul , current_token()); break; 25461 | case token_t::e_mod : current_state.set(e_level10, e_level11, details::e_mod , current_token()); break; 25462 | case token_t::e_pow : current_state.set(e_level12, e_level12, details::e_pow , current_token()); break; 25463 | default : 25464 | if (token_t::e_symbol == current_token().type) 25465 | { 25466 | static const std::string s_and = "and" ; 25467 | static const std::string s_nand = "nand" ; 25468 | static const std::string s_or = "or" ; 25469 | static const std::string s_nor = "nor" ; 25470 | static const std::string s_xor = "xor" ; 25471 | static const std::string s_xnor = "xnor" ; 25472 | static const std::string s_in = "in" ; 25473 | static const std::string s_like = "like" ; 25474 | static const std::string s_ilike = "ilike" 25475 | static const std::string s_and1 = "&" ; 25476 | static const std::string s_or1 = "|" ; 25477 | static const std::string s_not = "not" ; 25478 | 25479 | if (details::imatch(current_token().value,s_and)) 25480 | { 25481 | current_state.set(e_level03, e_level04, details::e_and, current_token()); 25482 | break; 25483 | } 25484 | else if (details::imatch(current_token().value,s_and1)) 25485 | { 25486 | #ifndef exprtk_disable_sc_andor 25487 | current_state.set(e_level03, e_level04, details::e_scand, current_token()); 25488 | #else 25489 | current_state.set(e_level03, e_level04, details::e_and, current_token()); 25490 | #endif 25491 | break; 25492 | } 25493 | else if (details::imatch(current_token().value,s_nand)) 25494 | { 25495 | current_state.set(e_level03, e_level04, details::e_nand, current_token()); 25496 | break; 25497 | } 25498 | else if (details::imatch(current_token().value,s_or)) 25499 | { 25500 | current_state.set(e_level01, e_level02, details::e_or, current_token()); 25501 | break; 25502 | } 25503 | else if (details::imatch(current_token().value,s_or1)) 25504 | { 25505 | #ifndef exprtk_disable_sc_andor 25506 | current_state.set(e_level01, e_level02, details::e_scor, current_token()); 25507 | #else 25508 | current_state.set(e_level01, e_level02, details::e_or, current_token()); 25509 | #endif 25510 | break; 25511 | } 25512 | else if (details::imatch(current_token().value,s_nor)) 25513 | { 25514 | current_state.set(e_level01, e_level02, details::e_nor, current_token()); 25515 | break; 25516 | } 25517 | else if (details::imatch(current_token().value,s_xor)) 25518 | { 25519 | current_state.set(e_level01, e_level02, details::e_xor, current_token()); 25520 | break; 25521 | } 25522 | else if (details::imatch(current_token().value,s_xnor)) 25523 | { 25524 | current_state.set(e_level01, e_level02, details::e_xnor, current_token()); 25525 | break; 25526 | } 25527 | else if (details::imatch(current_token().value,s_in)) 25528 | { 25529 | current_state.set(e_level04, e_level04, details::e_in, current_token()); 25530 | break; 25531 | } 25532 | else if (details::imatch(current_token().value,s_like)) 25533 | { 25534 | current_state.set(e_level04, e_level04, details::e_like, current_token()); 25535 | break; 25536 | } 25537 | else if (details::imatch(current_token().value,s_ilike)) 25538 | { 25539 | current_state.set(e_level04, e_level04, details::e_ilike, current_token()); 25540 | break; 25541 | } 25542 | else if (details::imatch(current_token().value,s_not)) 25543 | { 25544 | break; 25545 | } 25546 | } 25547 | 25548 | break_loop = true; 25549 | } 25550 | 25551 | if (break_loop) 25552 | { 25553 | parse_pending_string_rangesize(expression); 25554 | break; 25555 | } 25556 | else if (current_state.left < precedence) 25557 | break; 25558 | 25559 | const lexer::token prev_token = current_token(); 25560 | 25561 | next_token(); 25562 | 25563 | expression_node_ptr right_branch = error_node(); 25564 | expression_node_ptr new_expression = error_node(); 25565 | 25566 | if (is_invalid_logic_operation(current_state.operation)) 25567 | { 25568 | free_node(node_allocator_, expression); 25569 | 25570 | set_error(make_error( 25571 | parser_error::e_syntax, 25572 | prev_token, 25573 | "ERR012 - Invalid or disabled logic operation '" + details::to_str(current_state.operation) + "'", 25574 | exprtk_error_location)); 25575 | 25576 | return error_node(); 25577 | } 25578 | else if (is_invalid_arithmetic_operation(current_state.operation)) 25579 | { 25580 | free_node(node_allocator_, expression); 25581 | 25582 | set_error(make_error( 25583 | parser_error::e_syntax, 25584 | prev_token, 25585 | "ERR013 - Invalid or disabled arithmetic operation '" + details::to_str(current_state.operation) + "'", 25586 | exprtk_error_location)); 25587 | 25588 | return error_node(); 25589 | } 25590 | else if (is_invalid_inequality_operation(current_state.operation)) 25591 | { 25592 | free_node(node_allocator_, expression); 25593 | 25594 | set_error(make_error( 25595 | parser_error::e_syntax, 25596 | prev_token, 25597 | "ERR014 - Invalid inequality operation '" + details::to_str(current_state.operation) + "'", 25598 | exprtk_error_location)); 25599 | 25600 | return error_node(); 25601 | } 25602 | else if (is_invalid_assignment_operation(current_state.operation)) 25603 | { 25604 | free_node(node_allocator_, expression); 25605 | 25606 | set_error(make_error( 25607 | parser_error::e_syntax, 25608 | prev_token, 25609 | "ERR015 - Invalid or disabled assignment operation '" + details::to_str(current_state.operation) + "'", 25610 | exprtk_error_location)); 25611 | 25612 | return error_node(); 25613 | } 25614 | 25615 | if (0 != (right_branch = parse_expression(current_state.right))) 25616 | { 25617 | if ( 25618 | details::is_return_node(expression ) || 25619 | details::is_return_node(right_branch) 25620 | ) 25621 | { 25622 | free_node(node_allocator_, expression ); 25623 | free_node(node_allocator_, right_branch); 25624 | 25625 | set_error(make_error( 25626 | parser_error::e_syntax, 25627 | prev_token, 25628 | "ERR016 - Return statements cannot be part of sub-expressions", 25629 | exprtk_error_location)); 25630 | 25631 | return error_node(); 25632 | } 25633 | 25634 | push_current_state(current_state); 25635 | 25636 | new_expression = expression_generator_ 25637 | ( 25638 | current_state.operation, 25639 | expression, 25640 | right_branch 25641 | ); 25642 | 25643 | pop_current_state(); 25644 | } 25645 | 25646 | if (0 == new_expression) 25647 | { 25648 | if (error_list_.empty()) 25649 | { 25650 | set_error(make_error( 25651 | parser_error::e_syntax, 25652 | prev_token, 25653 | !synthesis_error_.empty() ? 25654 | synthesis_error_ : 25655 | "ERR017 - General parsing error at token: '" + prev_token.value + "'", 25656 | exprtk_error_location)); 25657 | } 25658 | 25659 | free_node(node_allocator_, expression ); 25660 | free_node(node_allocator_, right_branch); 25661 | 25662 | return error_node(); 25663 | } 25664 | else 25665 | { 25666 | if ( 25667 | token_is(token_t::e_ternary,prsrhlpr_t::e_hold) && 25668 | (e_level00 == precedence) 25669 | ) 25670 | { 25671 | expression = parse_ternary_conditional_statement(new_expression); 25672 | } 25673 | else 25674 | expression = new_expression; 25675 | 25676 | parse_pending_string_rangesize(expression); 25677 | } 25678 | } 25679 | 25680 | if ((0 != expression) && (expression->node_depth() > settings_.max_node_depth_)) 25681 | { 25682 | set_error(make_error( 25683 | parser_error::e_syntax, 25684 | current_token(), 25685 | "ERR018 - Expression depth of " + details::to_str(static_cast<int>(expression->node_depth())) + 25686 | " exceeds maximum allowed expression depth of " + details::to_str(static_cast<int>(settings_.max_node_depth_)), 25687 | exprtk_error_location)); 25688 | 25689 | free_node(node_allocator_, expression); 25690 | 25691 | return error_node(); 25692 | } 25693 | else if ( 25694 | !settings_.commutative_check_enabled() && 25695 | !details::is_logic_opr(current_token().value) && 25696 | (current_state.operation == details::e_default) && 25697 | ( 25698 | current_token().type == token_t::e_symbol || 25699 | current_token().type == token_t::e_number || 25700 | current_token().type == token_t::e_string 25701 | ) 25702 | ) 25703 | { 25704 | set_error(make_error( 25705 | parser_error::e_syntax, 25706 | current_token(), 25707 | "ERR019 - Invalid syntax '" + current_token().value + "' possible missing operator or context", 25708 | exprtk_error_location)); 25709 | 25710 | free_node(node_allocator_, expression); 25711 | 25712 | return error_node(); 25713 | } 25714 | 25715 | return expression; 25716 | } 25717 | 25718 | bool simplify_unary_negation_branch(expression_node_ptr& node) 25719 | { 25720 | { 25721 | typedef details::unary_branch_node<T,details::neg_op<T> > ubn_t; 25722 | ubn_t* n = dynamic_cast<ubn_t*>(node); 25723 | 25724 | if (n) 25725 | { 25726 | expression_node_ptr un_r = n->branch(0); 25727 | n->release(); 25728 | free_node(node_allocator_, node); 25729 | node = un_r; 25730 | 25731 | return true; 25732 | } 25733 | } 25734 | 25735 | { 25736 | typedef details::unary_variable_node<T,details::neg_op<T> > uvn_t; 25737 | 25738 | uvn_t* n = dynamic_cast<uvn_t*>(node); 25739 | 25740 | if (n) 25741 | { 25742 | const T& v = n->v(); 25743 | expression_node_ptr return_node = error_node(); 25744 | 25745 | if ( 25746 | (0 != (return_node = symtab_store_.get_variable(v))) || 25747 | (0 != (return_node = sem_ .get_variable(v))) 25748 | ) 25749 | { 25750 | free_node(node_allocator_, node); 25751 | node = return_node; 25752 | 25753 | return true; 25754 | } 25755 | else 25756 | { 25757 | set_error(make_error( 25758 | parser_error::e_syntax, 25759 | current_token(), 25760 | "ERR020 - Failed to find variable node in symbol table", 25761 | exprtk_error_location)); 25762 | 25763 | free_node(node_allocator_, node); 25764 | 25765 | return false; 25766 | } 25767 | } 25768 | } 25769 | 25770 | return false; 25771 | } 25772 | 25773 | static inline expression_node_ptr error_node() 25774 | { 25775 | return reinterpret_cast<expression_node_ptr>(0); 25776 | } 25777 | 25778 | struct scoped_expression_delete 25779 | { 25780 | scoped_expression_delete(parser<T>& pr, expression_node_ptr& expression) 25781 | : delete_ptr(true) 25782 | , parser_(pr) 25783 | , expression_(expression) 25784 | {} 25785 | 25786 | ~scoped_expression_delete() 25787 | { 25788 | if (delete_ptr) 25789 | { 25790 | free_node(parser_.node_allocator_, expression_); 25791 | } 25792 | } 25793 | 25794 | bool delete_ptr; 25795 | parser<T>& parser_; 25796 | expression_node_ptr& expression_; 25797 | 25798 | private: 25799 | 25800 | scoped_expression_delete(const scoped_expression_delete&) exprtk_delete; 25801 | scoped_expression_delete& operator=(const scoped_expression_delete&) exprtk_delete; 25802 | }; 25803 | 25804 | template <typename Type, std::size_t N> 25805 | struct scoped_delete 25806 | { 25807 | typedef Type* ptr_t; 25808 | 25809 | scoped_delete(parser<T>& pr, ptr_t& p) 25810 | : delete_ptr(true) 25811 | , parser_(pr) 25812 | , p_(&p) 25813 | {} 25814 | 25815 | scoped_delete(parser<T>& pr, ptr_t (&p)[N]) 25816 | : delete_ptr(true) 25817 | , parser_(pr) 25818 | , p_(&p[0]) 25819 | {} 25820 | 25821 | ~scoped_delete() 25822 | { 25823 | if (delete_ptr) 25824 | { 25825 | for (std::size_t i = 0; i < N; ++i) 25826 | { 25827 | free_node(parser_.node_allocator_, p_[i]); 25828 | } 25829 | } 25830 | } 25831 | 25832 | bool delete_ptr; 25833 | parser<T>& parser_; 25834 | ptr_t* p_; 25835 | 25836 | private: 25837 | 25838 | scoped_delete(const scoped_delete<Type,N>&) exprtk_delete; 25839 | scoped_delete<Type,N>& operator=(const scoped_delete<Type,N>&) exprtk_delete; 25840 | }; 25841 | 25842 | template <typename Type> 25843 | struct scoped_deq_delete 25844 | { 25845 | typedef Type* ptr_t; 25846 | 25847 | scoped_deq_delete(parser<T>& pr, std::deque<ptr_t>& deq) 25848 | : delete_ptr(true) 25849 | , parser_(pr) 25850 | , deq_(deq) 25851 | {} 25852 | 25853 | ~scoped_deq_delete() 25854 | { 25855 | if (delete_ptr && !deq_.empty()) 25856 | { 25857 | for (std::size_t i = 0; i < deq_.size(); ++i) 25858 | { 25859 | exprtk_debug(("~scoped_deq_delete() - deleting node: %p\n", reinterpret_cast<void*>(deq_[i]))); 25860 | free_node(parser_.node_allocator_,deq_[i]); 25861 | } 25862 | 25863 | deq_.clear(); 25864 | } 25865 | } 25866 | 25867 | bool delete_ptr; 25868 | parser<T>& parser_; 25869 | std::deque<ptr_t>& deq_; 25870 | 25871 | private: 25872 | 25873 | scoped_deq_delete(const scoped_deq_delete<Type>&) exprtk_delete; 25874 | scoped_deq_delete<Type>& operator=(const scoped_deq_delete<Type>&) exprtk_delete; 25875 | }; 25876 | 25877 | template <typename Type> 25878 | struct scoped_vec_delete 25879 | { 25880 | typedef Type* ptr_t; 25881 | 25882 | scoped_vec_delete(parser<T>& pr, std::vector<ptr_t>& vec) 25883 | : delete_ptr(true) 25884 | , parser_(pr) 25885 | , vec_(vec) 25886 | {} 25887 | 25888 | ~scoped_vec_delete() 25889 | { 25890 | if (delete_ptr && !vec_.empty()) 25891 | { 25892 | for (std::size_t i = 0; i < vec_.size(); ++i) 25893 | { 25894 | exprtk_debug(("~scoped_vec_delete() - deleting node: %p\n", reinterpret_cast<void*>(vec_[i]))); 25895 | free_node(parser_.node_allocator_,vec_[i]); 25896 | } 25897 | 25898 | vec_.clear(); 25899 | } 25900 | } 25901 | 25902 | ptr_t operator[](const std::size_t index) 25903 | { 25904 | return vec_[index]; 25905 | } 25906 | 25907 | bool delete_ptr; 25908 | parser<T>& parser_; 25909 | std::vector<ptr_t>& vec_; 25910 | 25911 | private: 25912 | 25913 | scoped_vec_delete(const scoped_vec_delete<Type>&) exprtk_delete; 25914 | scoped_vec_delete<Type>& operator=(const scoped_vec_delete<Type>&) exprtk_delete; 25915 | }; 25916 | 25917 | struct scoped_bool_negator 25918 | { 25919 | explicit scoped_bool_negator(bool& bb) 25920 | : b(bb) 25921 | { b = !b; } 25922 | 25923 | ~scoped_bool_negator() 25924 | { b = !b; } 25925 | 25926 | bool& b; 25927 | }; 25928 | 25929 | struct scoped_bool_or_restorer 25930 | { 25931 | explicit scoped_bool_or_restorer(bool& bb) 25932 | : b(bb) 25933 | , original_value_(bb) 25934 | {} 25935 | 25936 | ~scoped_bool_or_restorer() 25937 | { 25938 | b = b || original_value_; 25939 | } 25940 | 25941 | bool& b; 25942 | bool original_value_; 25943 | }; 25944 | 25945 | struct scoped_inc_dec 25946 | { 25947 | explicit scoped_inc_dec(std::size_t& v) 25948 | : v_(v) 25949 | { ++v_; } 25950 | 25951 | ~scoped_inc_dec() 25952 | { 25953 | assert(v_ > 0); 25954 | --v_; 25955 | } 25956 | 25957 | std::size_t& v_; 25958 | }; 25959 | 25960 | inline expression_node_ptr parse_function_invocation(ifunction<T>* function, const std::string& function_name) 25961 | { 25962 | expression_node_ptr func_node = reinterpret_cast<expression_node_ptr>(0); 25963 | 25964 | switch (function->param_count) 25965 | { 25966 | case 0 : func_node = parse_function_call_0 (function,function_name); break; 25967 | case 1 : func_node = parse_function_call< 1>(function,function_name); break; 25968 | case 2 : func_node = parse_function_call< 2>(function,function_name); break; 25969 | case 3 : func_node = parse_function_call< 3>(function,function_name); break; 25970 | case 4 : func_node = parse_function_call< 4>(function,function_name); break; 25971 | case 5 : func_node = parse_function_call< 5>(function,function_name); break; 25972 | case 6 : func_node = parse_function_call< 6>(function,function_name); break; 25973 | case 7 : func_node = parse_function_call< 7>(function,function_name); break; 25974 | case 8 : func_node = parse_function_call< 8>(function,function_name); break; 25975 | case 9 : func_node = parse_function_call< 9>(function,function_name); break; 25976 | case 10 : func_node = parse_function_call<10>(function,function_name); break; 25977 | case 11 : func_node = parse_function_call<11>(function,function_name); break; 25978 | case 12 : func_node = parse_function_call<12>(function,function_name); break; 25979 | case 13 : func_node = parse_function_call<13>(function,function_name); break; 25980 | case 14 : func_node = parse_function_call<14>(function,function_name); break; 25981 | case 15 : func_node = parse_function_call<15>(function,function_name); break; 25982 | case 16 : func_node = parse_function_call<16>(function,function_name); break; 25983 | case 17 : func_node = parse_function_call<17>(function,function_name); break; 25984 | case 18 : func_node = parse_function_call<18>(function,function_name); break; 25985 | case 19 : func_node = parse_function_call<19>(function,function_name); break; 25986 | case 20 : func_node = parse_function_call<20>(function,function_name); break; 25987 | default : { 25988 | set_error(make_error( 25989 | parser_error::e_syntax, 25990 | current_token(), 25991 | "ERR021 - Invalid number of parameters for function: '" + function_name + "'", 25992 | exprtk_error_location)); 25993 | 25994 | return error_node(); 25995 | } 25996 | } 25997 | 25998 | if (func_node) 25999 | return func_node; 26000 | else 26001 | { 26002 | set_error(make_error( 26003 | parser_error::e_syntax, 26004 | current_token(), 26005 | "ERR022 - Failed to generate call to function: '" + function_name + "'", 26006 | exprtk_error_location)); 26007 | 26008 | return error_node(); 26009 | } 26010 | } 26011 | 26012 | template <std::size_t NumberofParameters> 26013 | inline expression_node_ptr parse_function_call(ifunction<T>* function, const std::string& function_name) 26014 | { 26015 | #ifdef _MSC_VER 26016 | #pragma warning(push) 26017 | #pragma warning(disable: 4127) 26018 | #endif 26019 | if (0 == NumberofParameters) 26020 | { 26021 | set_error(make_error( 26022 | parser_error::e_syntax, 26023 | current_token(), 26024 | "ERR023 - Expecting ifunction '" + function_name + "' to have non-zero parameter count", 26025 | exprtk_error_location)); 26026 | 26027 | return error_node(); 26028 | } 26029 | #ifdef _MSC_VER 26030 | #pragma warning(pop) 26031 | #endif 26032 | 26033 | expression_node_ptr branch[NumberofParameters]; 26034 | expression_node_ptr result = error_node(); 26035 | 26036 | std::fill_n(branch, NumberofParameters, reinterpret_cast<expression_node_ptr>(0)); 26037 | 26038 | scoped_delete<expression_node_t,NumberofParameters> sd((*this),branch); 26039 | 26040 | next_token(); 26041 | 26042 | if (!token_is(token_t::e_lbracket)) 26043 | { 26044 | set_error(make_error( 26045 | parser_error::e_syntax, 26046 | current_token(), 26047 | "ERR024 - Expecting argument list for function: '" + function_name + "'", 26048 | exprtk_error_location)); 26049 | 26050 | return error_node(); 26051 | } 26052 | 26053 | for (int i = 0; i < static_cast<int>(NumberofParameters); ++i) 26054 | { 26055 | branch[i] = parse_expression(); 26056 | 26057 | if (0 == branch[i]) 26058 | { 26059 | set_error(make_error( 26060 | parser_error::e_syntax, 26061 | current_token(), 26062 | "ERR025 - Failed to parse argument " + details::to_str(i) + " for function: '" + function_name + "'", 26063 | exprtk_error_location)); 26064 | 26065 | return error_node(); 26066 | } 26067 | else if (i < static_cast<int>(NumberofParameters - 1)) 26068 | { 26069 | if (!token_is(token_t::e_comma)) 26070 | { 26071 | set_error(make_error( 26072 | parser_error::e_syntax, 26073 | current_token(), 26074 | "ERR026 - Invalid number of arguments for function: '" + function_name + "'", 26075 | exprtk_error_location)); 26076 | 26077 | return error_node(); 26078 | } 26079 | } 26080 | } 26081 | 26082 | if (!token_is(token_t::e_rbracket)) 26083 | { 26084 | set_error(make_error( 26085 | parser_error::e_syntax, 26086 | current_token(), 26087 | "ERR027 - Invalid number of arguments for function: '" + function_name + "'", 26088 | exprtk_error_location)); 26089 | 26090 | return error_node(); 26091 | } 26092 | else 26093 | result = expression_generator_.function(function,branch); 26094 | 26095 | sd.delete_ptr = (0 == result); 26096 | 26097 | return result; 26098 | } 26099 | 26100 | inline expression_node_ptr parse_function_call_0(ifunction<T>* function, const std::string& function_name) 26101 | { 26102 | expression_node_ptr result = expression_generator_.function(function); 26103 | 26104 | state_.side_effect_present = function->has_side_effects(); 26105 | 26106 | next_token(); 26107 | 26108 | if ( 26109 | token_is(token_t::e_lbracket) && 26110 | !token_is(token_t::e_rbracket) 26111 | ) 26112 | { 26113 | set_error(make_error( 26114 | parser_error::e_syntax, 26115 | current_token(), 26116 | "ERR028 - Expecting '()' to proceed call to function: '" + function_name + "'", 26117 | exprtk_error_location)); 26118 | 26119 | free_node(node_allocator_, result); 26120 | 26121 | return error_node(); 26122 | } 26123 | else 26124 | return result; 26125 | } 26126 | 26127 | template <std::size_t MaxNumberofParameters> 26128 | inline std::size_t parse_base_function_call(expression_node_ptr (¶m_list)[MaxNumberofParameters], const std::string& function_name = "") 26129 | { 26130 | std::fill_n(param_list, MaxNumberofParameters, reinterpret_cast<expression_node_ptr>(0)); 26131 | 26132 | scoped_delete<expression_node_t,MaxNumberofParameters> sd((*this),param_list); 26133 | 26134 | next_token(); 26135 | 26136 | if (!token_is(token_t::e_lbracket)) 26137 | { 26138 | set_error(make_error( 26139 | parser_error::e_syntax, 26140 | current_token(), 26141 | "ERR029 - Expected a '(' at start of function call to '" + function_name + 26142 | "', instead got: '" + current_token().value + "'", 26143 | exprtk_error_location)); 26144 | 26145 | return 0; 26146 | } 26147 | 26148 | if (token_is(token_t::e_rbracket, e_hold)) 26149 | { 26150 | set_error(make_error( 26151 | parser_error::e_syntax, 26152 | current_token(), 26153 | "ERR030 - Expected at least one input parameter for function call '" + function_name + "'", 26154 | exprtk_error_location)); 26155 | 26156 | return 0; 26157 | } 26158 | 26159 | std::size_t param_index = 0; 26160 | 26161 | for (; param_index < MaxNumberofParameters; ++param_index) 26162 | { 26163 | param_list[param_index] = parse_expression(); 26164 | 26165 | if (0 == param_list[param_index]) 26166 | return 0; 26167 | else if (token_is(token_t::e_rbracket)) 26168 | { 26169 | sd.delete_ptr = false; 26170 | break; 26171 | } 26172 | else if (token_is(token_t::e_comma)) 26173 | continue; 26174 | else 26175 | { 26176 | set_error(make_error( 26177 | parser_error::e_syntax, 26178 | current_token(), 26179 | "ERR031 - Expected a ',' between function input parameters, instead got: '" + current_token().value + "'", 26180 | exprtk_error_location)); 26181 | 26182 | return 0; 26183 | } 26184 | } 26185 | 26186 | if (sd.delete_ptr) 26187 | { 26188 | set_error(make_error( 26189 | parser_error::e_syntax, 26190 | current_token(), 26191 | "ERR032 - Invalid number of input parameters passed to function '" + function_name + "'", 26192 | exprtk_error_location)); 26193 | 26194 | return 0; 26195 | } 26196 | 26197 | return (param_index + 1); 26198 | } 26199 | 26200 | inline expression_node_ptr parse_base_operation() 26201 | { 26202 | typedef std::pair<base_ops_map_t::iterator,base_ops_map_t::iterator> map_range_t; 26203 | 26204 | const std::string operation_name = current_token().value; 26205 | const token_t diagnostic_token = current_token(); 26206 | 26207 | map_range_t itr_range = base_ops_map_.equal_range(operation_name); 26208 | 26209 | if (0 == std::distance(itr_range.first,itr_range.second)) 26210 | { 26211 | set_error(make_error( 26212 | parser_error::e_syntax, 26213 | diagnostic_token, 26214 | "ERR033 - No entry found for base operation: " + operation_name, 26215 | exprtk_error_location)); 26216 | 26217 | return error_node(); 26218 | } 26219 | 26220 | static const std::size_t MaxNumberofParameters = 4; 26221 | expression_node_ptr param_list[MaxNumberofParameters] = {0}; 26222 | 26223 | const std::size_t parameter_count = parse_base_function_call(param_list, operation_name); 26224 | 26225 | if ((parameter_count > 0) && (parameter_count <= MaxNumberofParameters)) 26226 | { 26227 | for (base_ops_map_t::iterator itr = itr_range.first; itr != itr_range.second; ++itr) 26228 | { 26229 | const details::base_operation_t& operation = itr->second; 26230 | 26231 | if (operation.num_params == parameter_count) 26232 | { 26233 | switch (parameter_count) 26234 | { 26235 | #define base_opr_case(N) \ 26236 | case N : { \ 26237 | expression_node_ptr pl##N[N] = {0}; \ 26238 | std::copy(param_list, param_list + N, pl##N); \ 26239 | lodge_symbol(operation_name, e_st_function); \ 26240 | return expression_generator_(operation.type, pl##N); \ 26241 | } \ 26242 | 26243 | base_opr_case(1) 26244 | base_opr_case(2) 26245 | base_opr_case(3) 26246 | base_opr_case(4) 26247 | #undef base_opr_case 26248 | } 26249 | } 26250 | } 26251 | } 26252 | 26253 | for (std::size_t i = 0; i < MaxNumberofParameters; ++i) 26254 | { 26255 | free_node(node_allocator_, param_list[i]); 26256 | } 26257 | 26258 | set_error(make_error( 26259 | parser_error::e_syntax, 26260 | diagnostic_token, 26261 | "ERR034 - Invalid number of input parameters for call to function: '" + operation_name + "'", 26262 | exprtk_error_location)); 26263 | 26264 | return error_node(); 26265 | } 26266 | 26267 | inline expression_node_ptr parse_conditional_statement_01(expression_node_ptr condition) 26268 | { 26269 | // Parse: [if][(][condition][,][consequent][,][alternative][)] 26270 | 26271 | expression_node_ptr consequent = error_node(); 26272 | expression_node_ptr alternative = error_node(); 26273 | 26274 | bool result = true; 26275 | 26276 | if (!token_is(token_t::e_comma)) 26277 | { 26278 | set_error(make_error( 26279 | parser_error::e_syntax, 26280 | current_token(), 26281 | "ERR035 - Expected ',' between if-statement condition and consequent", 26282 | exprtk_error_location)); 26283 | 26284 | result = false; 26285 | } 26286 | else if (0 == (consequent = parse_expression())) 26287 | { 26288 | set_error(make_error( 26289 | parser_error::e_syntax, 26290 | current_token(), 26291 | "ERR036 - Failed to parse consequent for if-statement", 26292 | exprtk_error_location)); 26293 | 26294 | result = false; 26295 | } 26296 | else if (!token_is(token_t::e_comma)) 26297 | { 26298 | set_error(make_error( 26299 | parser_error::e_syntax, 26300 | current_token(), 26301 | "ERR037 - Expected ',' between if-statement consequent and alternative", 26302 | exprtk_error_location)); 26303 | 26304 | result = false; 26305 | } 26306 | else if (0 == (alternative = parse_expression())) 26307 | { 26308 | set_error(make_error( 26309 | parser_error::e_syntax, 26310 | current_token(), 26311 | "ERR038 - Failed to parse alternative for if-statement", 26312 | exprtk_error_location)); 26313 | 26314 | result = false; 26315 | } 26316 | else if (!token_is(token_t::e_rbracket)) 26317 | { 26318 | set_error(make_error( 26319 | parser_error::e_syntax, 26320 | current_token(), 26321 | "ERR039 - Expected ')' at the end of if-statement", 26322 | exprtk_error_location)); 26323 | 26324 | result = false; 26325 | } 26326 | 26327 | #ifndef exprtk_disable_string_capabilities 26328 | if (result) 26329 | { 26330 | const bool consq_is_str = is_generally_string_node(consequent ); 26331 | const bool alter_is_str = is_generally_string_node(alternative); 26332 | 26333 | if (consq_is_str || alter_is_str) 26334 | { 26335 | if (consq_is_str && alter_is_str) 26336 | { 26337 | expression_node_ptr result_node = 26338 | expression_generator_ 26339 | .conditional_string(condition, consequent, alternative); 26340 | 26341 | if (result_node && result_node->valid()) 26342 | { 26343 | return result_node; 26344 | } 26345 | 26346 | set_error(make_error( 26347 | parser_error::e_synthesis, 26348 | current_token(), 26349 | "ERR040 - Failed to synthesize node: conditional_string", 26350 | exprtk_error_location)); 26351 | 26352 | free_node(node_allocator_, result_node); 26353 | return error_node(); 26354 | } 26355 | 26356 | set_error(make_error( 26357 | parser_error::e_syntax, 26358 | current_token(), 26359 | "ERR041 - Return types of if-statement differ: string/non-string", 26360 | exprtk_error_location)); 26361 | 26362 | result = false; 26363 | } 26364 | } 26365 | #endif 26366 | 26367 | if (result) 26368 | { 26369 | const bool consq_is_vec = is_ivector_node(consequent ); 26370 | const bool alter_is_vec = is_ivector_node(alternative); 26371 | 26372 | if (consq_is_vec || alter_is_vec) 26373 | { 26374 | if (consq_is_vec && alter_is_vec) 26375 | { 26376 | return expression_generator_ 26377 | .conditional_vector(condition, consequent, alternative); 26378 | } 26379 | 26380 | set_error(make_error( 26381 | parser_error::e_syntax, 26382 | current_token(), 26383 | "ERR042 - Return types of if-statement differ: vector/non-vector", 26384 | exprtk_error_location)); 26385 | 26386 | result = false; 26387 | } 26388 | } 26389 | 26390 | if (!result) 26391 | { 26392 | free_node(node_allocator_, condition ); 26393 | free_node(node_allocator_, consequent ); 26394 | free_node(node_allocator_, alternative); 26395 | 26396 | return error_node(); 26397 | } 26398 | else 26399 | return expression_generator_ 26400 | .conditional(condition, consequent, alternative); 26401 | } 26402 | 26403 | inline expression_node_ptr parse_conditional_statement_02(expression_node_ptr condition) 26404 | { 26405 | expression_node_ptr consequent = error_node(); 26406 | expression_node_ptr alternative = error_node(); 26407 | 26408 | bool result = true; 26409 | 26410 | if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) 26411 | { 26412 | if (0 == (consequent = parse_multi_sequence("if-statement-01"))) 26413 | { 26414 | set_error(make_error( 26415 | parser_error::e_syntax, 26416 | current_token(), 26417 | "ERR043 - Failed to parse body of consequent for if-statement", 26418 | exprtk_error_location)); 26419 | 26420 | result = false; 26421 | } 26422 | else if 26423 | ( 26424 | !settings_.commutative_check_enabled() && 26425 | !token_is("else",prsrhlpr_t::e_hold) && 26426 | !token_is_loop(prsrhlpr_t::e_hold) && 26427 | !token_is_arithmetic_opr(prsrhlpr_t::e_hold) && 26428 | !token_is_right_bracket (prsrhlpr_t::e_hold) && 26429 | !token_is_ineq_opr (prsrhlpr_t::e_hold) && 26430 | !token_is(token_t::e_ternary,prsrhlpr_t::e_hold) && 26431 | !token_is(token_t::e_eof ,prsrhlpr_t::e_hold) 26432 | ) 26433 | { 26434 | set_error(make_error( 26435 | parser_error::e_syntax, 26436 | current_token(), 26437 | "ERR044 - Expected ';' at the end of the consequent for if-statement (1)", 26438 | exprtk_error_location)); 26439 | 26440 | result = false; 26441 | } 26442 | } 26443 | else 26444 | { 26445 | if ( 26446 | settings_.commutative_check_enabled() && 26447 | token_is(token_t::e_mul,prsrhlpr_t::e_hold) 26448 | ) 26449 | { 26450 | next_token(); 26451 | } 26452 | 26453 | if (0 != (consequent = parse_expression())) 26454 | { 26455 | if (!token_is(token_t::e_eof, prsrhlpr_t::e_hold)) 26456 | { 26457 | set_error(make_error( 26458 | parser_error::e_syntax, 26459 | current_token(), 26460 | "ERR045 - Expected ';' at the end of the consequent for if-statement (2)", 26461 | exprtk_error_location)); 26462 | 26463 | result = false; 26464 | } 26465 | } 26466 | else 26467 | { 26468 | set_error(make_error( 26469 | parser_error::e_syntax, 26470 | current_token(), 26471 | "ERR046 - Failed to parse body of consequent for if-statement", 26472 | exprtk_error_location)); 26473 | 26474 | result = false; 26475 | } 26476 | } 26477 | 26478 | if (result) 26479 | { 26480 | if ( 26481 | details::imatch(current_token().value,"else") || 26482 | (token_is(token_t::e_eof, prsrhlpr_t::e_hold) && peek_token_is("else")) 26483 | ) 26484 | { 26485 | next_token(); 26486 | 26487 | if (details::imatch(current_token().value,"else")) 26488 | { 26489 | next_token(); 26490 | } 26491 | 26492 | if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) 26493 | { 26494 | if (0 == (alternative = parse_multi_sequence("else-statement-01"))) 26495 | { 26496 | set_error(make_error( 26497 | parser_error::e_syntax, 26498 | current_token(), 26499 | "ERR047 - Failed to parse body of the 'else' for if-statement", 26500 | exprtk_error_location)); 26501 | 26502 | result = false; 26503 | } 26504 | } 26505 | else if (details::imatch(current_token().value,"if")) 26506 | { 26507 | if (0 == (alternative = parse_conditional_statement())) 26508 | { 26509 | set_error(make_error( 26510 | parser_error::e_syntax, 26511 | current_token(), 26512 | "ERR048 - Failed to parse body of if-else statement", 26513 | exprtk_error_location)); 26514 | 26515 | result = false; 26516 | } 26517 | } 26518 | else if (0 != (alternative = parse_expression())) 26519 | { 26520 | if ( 26521 | !token_is(token_t::e_ternary , prsrhlpr_t::e_hold) && 26522 | !token_is(token_t::e_rcrlbracket, prsrhlpr_t::e_hold) && 26523 | !token_is(token_t::e_eof) 26524 | ) 26525 | { 26526 | set_error(make_error( 26527 | parser_error::e_syntax, 26528 | current_token(), 26529 | "ERR049 - Expected ';' at the end of the 'else-if' for the if-statement", 26530 | exprtk_error_location)); 26531 | 26532 | result = false; 26533 | } 26534 | } 26535 | else 26536 | { 26537 | set_error(make_error( 26538 | parser_error::e_syntax, 26539 | current_token(), 26540 | "ERR050 - Failed to parse body of the 'else' for if-statement", 26541 | exprtk_error_location)); 26542 | 26543 | result = false; 26544 | } 26545 | } 26546 | } 26547 | 26548 | #ifndef exprtk_disable_string_capabilities 26549 | if (result) 26550 | { 26551 | const bool consq_is_str = is_generally_string_node(consequent ); 26552 | const bool alter_is_str = is_generally_string_node(alternative); 26553 | 26554 | if (consq_is_str || alter_is_str) 26555 | { 26556 | if (consq_is_str && alter_is_str) 26557 | { 26558 | return expression_generator_ 26559 | .conditional_string(condition, consequent, alternative); 26560 | } 26561 | 26562 | set_error(make_error( 26563 | parser_error::e_syntax, 26564 | current_token(), 26565 | "ERR051 - Return types of if-statement differ: string/non-string", 26566 | exprtk_error_location)); 26567 | 26568 | result = false; 26569 | } 26570 | } 26571 | #endif 26572 | 26573 | if (result) 26574 | { 26575 | const bool consq_is_vec = is_ivector_node(consequent ); 26576 | const bool alter_is_vec = is_ivector_node(alternative); 26577 | 26578 | if (consq_is_vec || alter_is_vec) 26579 | { 26580 | if (consq_is_vec && alter_is_vec) 26581 | { 26582 | return expression_generator_ 26583 | .conditional_vector(condition, consequent, alternative); 26584 | } 26585 | 26586 | set_error(make_error( 26587 | parser_error::e_syntax, 26588 | current_token(), 26589 | "ERR052 - Return types of if-statement differ: vector/non-vector", 26590 | exprtk_error_location)); 26591 | 26592 | result = false; 26593 | } 26594 | } 26595 | 26596 | if (!result) 26597 | { 26598 | free_node(node_allocator_, condition ); 26599 | free_node(node_allocator_, consequent ); 26600 | free_node(node_allocator_, alternative); 26601 | 26602 | return error_node(); 26603 | } 26604 | else 26605 | return expression_generator_ 26606 | .conditional(condition, consequent, alternative); 26607 | } 26608 | 26609 | inline expression_node_ptr parse_conditional_statement() 26610 | { 26611 | expression_node_ptr condition = error_node(); 26612 | 26613 | next_token(); 26614 | 26615 | if (!token_is(token_t::e_lbracket)) 26616 | { 26617 | set_error(make_error( 26618 | parser_error::e_syntax, 26619 | current_token(), 26620 | "ERR053 - Expected '(' at start of if-statement, instead got: '" + current_token().value + "'", 26621 | exprtk_error_location)); 26622 | 26623 | return error_node(); 26624 | } 26625 | else if (0 == (condition = parse_expression())) 26626 | { 26627 | set_error(make_error( 26628 | parser_error::e_syntax, 26629 | current_token(), 26630 | "ERR054 - Failed to parse condition for if-statement", 26631 | exprtk_error_location)); 26632 | 26633 | return error_node(); 26634 | } 26635 | else if (token_is(token_t::e_comma,prsrhlpr_t::e_hold)) 26636 | { 26637 | // if (x,y,z) 26638 | return parse_conditional_statement_01(condition); 26639 | } 26640 | else if (token_is(token_t::e_rbracket)) 26641 | { 26642 | /* 26643 | 00. if (x) y; 26644 | 01. if (x) y; else z; 26645 | 02. if (x) y; else {z0; ... zn;} 26646 | 03. if (x) y; else if (z) w; 26647 | 04. if (x) y; else if (z) w; else u; 26648 | 05. if (x) y; else if (z) w; else {u0; ... un;} 26649 | 06. if (x) y; else if (z) {w0; ... wn;} 26650 | 07. if (x) {y0; ... yn;} 26651 | 08. if (x) {y0; ... yn;} else z; 26652 | 09. if (x) {y0; ... yn;} else {z0; ... zn;}; 26653 | 10. if (x) {y0; ... yn;} else if (z) w; 26654 | 11. if (x) {y0; ... yn;} else if (z) w; else u; 26655 | 12. if (x) {y0; ... nex;} else if (z) w; else {u0 ... un;} 26656 | 13. if (x) {y0; ... yn;} else if (z) {w0; ... wn;} 26657 | */ 26658 | return parse_conditional_statement_02(condition); 26659 | } 26660 | 26661 | set_error(make_error( 26662 | parser_error::e_syntax, 26663 | current_token(), 26664 | "ERR055 - Invalid if-statement", 26665 | exprtk_error_location)); 26666 | 26667 | free_node(node_allocator_, condition); 26668 | 26669 | return error_node(); 26670 | } 26671 | 26672 | inline expression_node_ptr parse_ternary_conditional_statement(expression_node_ptr condition) 26673 | { 26674 | // Parse: [condition][?][consequent][:][alternative] 26675 | expression_node_ptr consequent = error_node(); 26676 | expression_node_ptr alternative = error_node(); 26677 | 26678 | bool result = true; 26679 | 26680 | if (0 == condition) 26681 | { 26682 | set_error(make_error( 26683 | parser_error::e_syntax, 26684 | current_token(), 26685 | "ERR056 - Encountered invalid condition branch for ternary if-statement", 26686 | exprtk_error_location)); 26687 | 26688 | return error_node(); 26689 | } 26690 | else if (!token_is(token_t::e_ternary)) 26691 | { 26692 | set_error(make_error( 26693 | parser_error::e_syntax, 26694 | current_token(), 26695 | "ERR057 - Expected '?' after condition of ternary if-statement", 26696 | exprtk_error_location)); 26697 | 26698 | result = false; 26699 | } 26700 | else if (0 == (consequent = parse_expression())) 26701 | { 26702 | set_error(make_error( 26703 | parser_error::e_syntax, 26704 | current_token(), 26705 | "ERR058 - Failed to parse consequent for ternary if-statement", 26706 | exprtk_error_location)); 26707 | 26708 | result = false; 26709 | } 26710 | else if (!token_is(token_t::e_colon)) 26711 | { 26712 | set_error(make_error( 26713 | parser_error::e_syntax, 26714 | current_token(), 26715 | "ERR059 - Expected ':' between ternary if-statement consequent and alternative", 26716 | exprtk_error_location)); 26717 | 26718 | result = false; 26719 | } 26720 | else if (0 == (alternative = parse_expression())) 26721 | { 26722 | set_error(make_error( 26723 | parser_error::e_syntax, 26724 | current_token(), 26725 | "ERR060 - Failed to parse alternative for ternary if-statement", 26726 | exprtk_error_location)); 26727 | 26728 | result = false; 26729 | } 26730 | 26731 | #ifndef exprtk_disable_string_capabilities 26732 | if (result) 26733 | { 26734 | const bool consq_is_str = is_generally_string_node(consequent ); 26735 | const bool alter_is_str = is_generally_string_node(alternative); 26736 | 26737 | if (consq_is_str || alter_is_str) 26738 | { 26739 | if (consq_is_str && alter_is_str) 26740 | { 26741 | return expression_generator_ 26742 | .conditional_string(condition, consequent, alternative); 26743 | } 26744 | 26745 | set_error(make_error( 26746 | parser_error::e_syntax, 26747 | current_token(), 26748 | "ERR061 - Return types of ternary differ: string/non-string", 26749 | exprtk_error_location)); 26750 | 26751 | result = false; 26752 | } 26753 | } 26754 | #endif 26755 | 26756 | if (result) 26757 | { 26758 | const bool consq_is_vec = is_ivector_node(consequent ); 26759 | const bool alter_is_vec = is_ivector_node(alternative); 26760 | 26761 | if (consq_is_vec || alter_is_vec) 26762 | { 26763 | if (consq_is_vec && alter_is_vec) 26764 | { 26765 | return expression_generator_ 26766 | .conditional_vector(condition, consequent, alternative); 26767 | } 26768 | 26769 | set_error(make_error( 26770 | parser_error::e_syntax, 26771 | current_token(), 26772 | "ERR062 - Return types of ternary differ: vector/non-vector", 26773 | exprtk_error_location)); 26774 | 26775 | result = false; 26776 | } 26777 | } 26778 | 26779 | if (!result) 26780 | { 26781 | free_node(node_allocator_, condition ); 26782 | free_node(node_allocator_, consequent ); 26783 | free_node(node_allocator_, alternative); 26784 | 26785 | return error_node(); 26786 | } 26787 | else 26788 | return expression_generator_ 26789 | .conditional(condition, consequent, alternative); 26790 | } 26791 | 26792 | inline expression_node_ptr parse_not_statement() 26793 | { 26794 | if (settings_.logic_disabled("not")) 26795 | { 26796 | set_error(make_error( 26797 | parser_error::e_syntax, 26798 | current_token(), 26799 | "ERR063 - Invalid or disabled logic operation 'not'", 26800 | exprtk_error_location)); 26801 | 26802 | return error_node(); 26803 | } 26804 | 26805 | return parse_base_operation(); 26806 | } 26807 | 26808 | void handle_brkcnt_scope_exit() 26809 | { 26810 | assert(!brkcnt_list_.empty()); 26811 | brkcnt_list_.pop_front(); 26812 | } 26813 | 26814 | inline expression_node_ptr parse_while_loop() 26815 | { 26816 | // Parse: [while][(][test expr][)][{][expression][}] 26817 | expression_node_ptr condition = error_node(); 26818 | expression_node_ptr branch = error_node(); 26819 | expression_node_ptr result_node = error_node(); 26820 | 26821 | bool result = true; 26822 | 26823 | next_token(); 26824 | 26825 | if (!token_is(token_t::e_lbracket)) 26826 | { 26827 | set_error(make_error( 26828 | parser_error::e_syntax, 26829 | current_token(), 26830 | "ERR064 - Expected '(' at start of while-loop condition statement", 26831 | exprtk_error_location)); 26832 | 26833 | return error_node(); 26834 | } 26835 | else if (0 == (condition = parse_expression())) 26836 | { 26837 | set_error(make_error( 26838 | parser_error::e_syntax, 26839 | current_token(), 26840 | "ERR065 - Failed to parse condition for while-loop", 26841 | exprtk_error_location)); 26842 | 26843 | return error_node(); 26844 | } 26845 | else if (!token_is(token_t::e_rbracket)) 26846 | { 26847 | set_error(make_error( 26848 | parser_error::e_syntax, 26849 | current_token(), 26850 | "ERR066 - Expected ')' at end of while-loop condition statement", 26851 | exprtk_error_location)); 26852 | 26853 | result = false; 26854 | } 26855 | 26856 | brkcnt_list_.push_front(false); 26857 | 26858 | if (result) 26859 | { 26860 | scoped_inc_dec sid(state_.parsing_loop_stmt_count); 26861 | 26862 | if (0 == (branch = parse_multi_sequence("while-loop", true))) 26863 | { 26864 | set_error(make_error( 26865 | parser_error::e_syntax, 26866 | current_token(), 26867 | "ERR067 - Failed to parse body of while-loop")); 26868 | result = false; 26869 | } 26870 | else if (0 == (result_node = expression_generator_.while_loop(condition, 26871 | branch, 26872 | brkcnt_list_.front()))) 26873 | { 26874 | set_error(make_error( 26875 | parser_error::e_syntax, 26876 | current_token(), 26877 | "ERR068 - Failed to synthesize while-loop", 26878 | exprtk_error_location)); 26879 | 26880 | result = false; 26881 | } 26882 | } 26883 | 26884 | handle_brkcnt_scope_exit(); 26885 | 26886 | if (!result) 26887 | { 26888 | free_node(node_allocator_, branch ); 26889 | free_node(node_allocator_, condition ); 26890 | free_node(node_allocator_, result_node); 26891 | 26892 | return error_node(); 26893 | } 26894 | 26895 | if (result_node && result_node->valid()) 26896 | { 26897 | return result_node; 26898 | } 26899 | 26900 | set_error(make_error( 26901 | parser_error::e_synthesis, 26902 | current_token(), 26903 | "ERR069 - Failed to synthesize 'valid' while-loop", 26904 | exprtk_error_location)); 26905 | 26906 | free_node(node_allocator_, result_node); 26907 | 26908 | return error_node(); 26909 | } 26910 | 26911 | inline expression_node_ptr parse_repeat_until_loop() 26912 | { 26913 | // Parse: [repeat][{][expression][}][until][(][test expr][)] 26914 | expression_node_ptr condition = error_node(); 26915 | expression_node_ptr branch = error_node(); 26916 | next_token(); 26917 | 26918 | std::vector<expression_node_ptr> arg_list; 26919 | std::vector<bool> side_effect_list; 26920 | 26921 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 26922 | 26923 | brkcnt_list_.push_front(false); 26924 | 26925 | if (details::imatch(current_token().value,"until")) 26926 | { 26927 | next_token(); 26928 | branch = node_allocator_.allocate<details::null_node<T> >(); 26929 | } 26930 | else 26931 | { 26932 | const token_t::token_type separator = token_t::e_eof; 26933 | 26934 | scope_handler sh(*this); 26935 | 26936 | scoped_bool_or_restorer sbr(state_.side_effect_present); 26937 | 26938 | scoped_inc_dec sid(state_.parsing_loop_stmt_count); 26939 | 26940 | for ( ; ; ) 26941 | { 26942 | state_.side_effect_present = false; 26943 | 26944 | expression_node_ptr arg = parse_expression(); 26945 | 26946 | if (0 == arg) 26947 | return error_node(); 26948 | else 26949 | { 26950 | arg_list.push_back(arg); 26951 | side_effect_list.push_back(state_.side_effect_present); 26952 | } 26953 | 26954 | if (details::imatch(current_token().value,"until")) 26955 | { 26956 | next_token(); 26957 | break; 26958 | } 26959 | 26960 | const bool is_next_until = peek_token_is(token_t::e_symbol) && 26961 | peek_token_is("until"); 26962 | 26963 | if (!token_is(separator) && is_next_until) 26964 | { 26965 | set_error(make_error( 26966 | parser_error::e_syntax, 26967 | current_token(), 26968 | "ERR070 - Expected '" + token_t::to_str(separator) + "' in body of repeat until loop", 26969 | exprtk_error_location)); 26970 | 26971 | return error_node(); 26972 | } 26973 | 26974 | if (details::imatch(current_token().value,"until")) 26975 | { 26976 | next_token(); 26977 | break; 26978 | } 26979 | } 26980 | 26981 | branch = simplify(arg_list,side_effect_list); 26982 | 26983 | svd.delete_ptr = (0 == branch); 26984 | 26985 | if (svd.delete_ptr) 26986 | { 26987 | set_error(make_error( 26988 | parser_error::e_syntax, 26989 | current_token(), 26990 | "ERR071 - Failed to parse body of repeat until loop", 26991 | exprtk_error_location)); 26992 | 26993 | return error_node(); 26994 | } 26995 | } 26996 | 26997 | if (!token_is(token_t::e_lbracket)) 26998 | { 26999 | set_error(make_error( 27000 | parser_error::e_syntax, 27001 | current_token(), 27002 | "ERR072 - Expected '(' before condition statement of repeat until loop", 27003 | exprtk_error_location)); 27004 | 27005 | free_node(node_allocator_, branch); 27006 | return error_node(); 27007 | } 27008 | else if (0 == (condition = parse_expression())) 27009 | { 27010 | set_error(make_error( 27011 | parser_error::e_syntax, 27012 | current_token(), 27013 | "ERR073 - Failed to parse condition for repeat until loop", 27014 | exprtk_error_location)); 27015 | 27016 | free_node(node_allocator_, branch); 27017 | return error_node(); 27018 | } 27019 | else if (!token_is(token_t::e_rbracket)) 27020 | { 27021 | set_error(make_error( 27022 | parser_error::e_syntax, 27023 | current_token(), 27024 | "ERR074 - Expected ')' after condition of repeat until loop", 27025 | exprtk_error_location)); 27026 | 27027 | free_node(node_allocator_, branch ); 27028 | free_node(node_allocator_, condition); 27029 | 27030 | return error_node(); 27031 | } 27032 | 27033 | expression_node_ptr result_node = 27034 | expression_generator_ 27035 | .repeat_until_loop( 27036 | condition, 27037 | branch, 27038 | brkcnt_list_.front()); 27039 | 27040 | if (0 == result_node) 27041 | { 27042 | set_error(make_error( 27043 | parser_error::e_syntax, 27044 | current_token(), 27045 | "ERR075 - Failed to synthesize repeat until loop", 27046 | exprtk_error_location)); 27047 | 27048 | free_node(node_allocator_, condition); 27049 | 27050 | return error_node(); 27051 | } 27052 | 27053 | handle_brkcnt_scope_exit(); 27054 | 27055 | if (result_node && result_node->valid()) 27056 | { 27057 | return result_node; 27058 | } 27059 | 27060 | set_error(make_error( 27061 | parser_error::e_synthesis, 27062 | current_token(), 27063 | "ERR076 - Failed to synthesize 'valid' repeat until loop", 27064 | exprtk_error_location)); 27065 | 27066 | free_node(node_allocator_, result_node); 27067 | 27068 | return error_node(); 27069 | } 27070 | 27071 | inline expression_node_ptr parse_for_loop() 27072 | { 27073 | expression_node_ptr initialiser = error_node(); 27074 | expression_node_ptr condition = error_node(); 27075 | expression_node_ptr incrementor = error_node(); 27076 | expression_node_ptr loop_body = error_node(); 27077 | 27078 | scope_element* se = 0; 27079 | bool result = true; 27080 | 27081 | next_token(); 27082 | 27083 | scope_handler sh(*this); 27084 | 27085 | if (!token_is(token_t::e_lbracket)) 27086 | { 27087 | set_error(make_error( 27088 | parser_error::e_syntax, 27089 | current_token(), 27090 | "ERR077 - Expected '(' at start of for-loop", 27091 | exprtk_error_location)); 27092 | 27093 | return error_node(); 27094 | } 27095 | 27096 | if (!token_is(token_t::e_eof)) 27097 | { 27098 | if ( 27099 | !token_is(token_t::e_symbol,prsrhlpr_t::e_hold) && 27100 | details::imatch(current_token().value,"var") 27101 | ) 27102 | { 27103 | next_token(); 27104 | 27105 | if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold)) 27106 | { 27107 | set_error(make_error( 27108 | parser_error::e_syntax, 27109 | current_token(), 27110 | "ERR078 - Expected a variable at the start of initialiser section of for-loop", 27111 | exprtk_error_location)); 27112 | 27113 | return error_node(); 27114 | } 27115 | else if (!peek_token_is(token_t::e_assign)) 27116 | { 27117 | set_error(make_error( 27118 | parser_error::e_syntax, 27119 | current_token(), 27120 | "ERR079 - Expected variable assignment of initialiser section of for-loop", 27121 | exprtk_error_location)); 27122 | 27123 | return error_node(); 27124 | } 27125 | 27126 | const std::string loop_counter_symbol = current_token().value; 27127 | 27128 | se = &sem_.get_element(loop_counter_symbol); 27129 | 27130 | if ((se->name == loop_counter_symbol) && se->active) 27131 | { 27132 | set_error(make_error( 27133 | parser_error::e_syntax, 27134 | current_token(), 27135 | "ERR080 - For-loop variable '" + loop_counter_symbol+ "' is being shadowed by a previous declaration", 27136 | exprtk_error_location)); 27137 | 27138 | return error_node(); 27139 | } 27140 | else if (!symtab_store_.is_variable(loop_counter_symbol)) 27141 | { 27142 | if ( 27143 | !se->active && 27144 | (se->name == loop_counter_symbol) && 27145 | (se->type == scope_element::e_variable) 27146 | ) 27147 | { 27148 | se->active = true; 27149 | se->ref_count++; 27150 | } 27151 | else 27152 | { 27153 | scope_element nse; 27154 | nse.name = loop_counter_symbol; 27155 | nse.active = true; 27156 | nse.ref_count = 1; 27157 | nse.type = scope_element::e_variable; 27158 | nse.depth = state_.scope_depth; 27159 | nse.data = new T(T(0)); 27160 | nse.var_node = node_allocator_.allocate<variable_node_t>(*reinterpret_cast<T*>(nse.data)); 27161 | 27162 | if (!sem_.add_element(nse)) 27163 | { 27164 | set_error(make_error( 27165 | parser_error::e_syntax, 27166 | current_token(), 27167 | "ERR081 - Failed to add new local variable '" + loop_counter_symbol + "' to SEM", 27168 | exprtk_error_location)); 27169 | 27170 | sem_.free_element(nse); 27171 | 27172 | result = false; 27173 | } 27174 | else 27175 | { 27176 | exprtk_debug(("parse_for_loop() - INFO - Added new local variable: %s\n", nse.name.c_str())); 27177 | 27178 | state_.activate_side_effect("parse_for_loop()"); 27179 | } 27180 | } 27181 | } 27182 | } 27183 | 27184 | if (0 == (initialiser = parse_expression())) 27185 | { 27186 | set_error(make_error( 27187 | parser_error::e_syntax, 27188 | current_token(), 27189 | "ERR082 - Failed to parse initialiser of for-loop", 27190 | exprtk_error_location)); 27191 | 27192 | result = false; 27193 | } 27194 | else if (!token_is(token_t::e_eof)) 27195 | { 27196 | set_error(make_error( 27197 | parser_error::e_syntax, 27198 | current_token(), 27199 | "ERR083 - Expected ';' after initialiser of for-loop", 27200 | exprtk_error_location)); 27201 | 27202 | result = false; 27203 | } 27204 | } 27205 | 27206 | if (!token_is(token_t::e_eof)) 27207 | { 27208 | if (0 == (condition = parse_expression())) 27209 | { 27210 | set_error(make_error( 27211 | parser_error::e_syntax, 27212 | current_token(), 27213 | "ERR084 - Failed to parse condition of for-loop", 27214 | exprtk_error_location)); 27215 | 27216 | result = false; 27217 | } 27218 | else if (!token_is(token_t::e_eof)) 27219 | { 27220 | set_error(make_error( 27221 | parser_error::e_syntax, 27222 | current_token(), 27223 | "ERR085 - Expected ';' after condition section of for-loop", 27224 | exprtk_error_location)); 27225 | 27226 | result = false; 27227 | } 27228 | } 27229 | 27230 | if (!token_is(token_t::e_rbracket)) 27231 | { 27232 | if (0 == (incrementor = parse_expression())) 27233 | { 27234 | set_error(make_error( 27235 | parser_error::e_syntax, 27236 | current_token(), 27237 | "ERR086 - Failed to parse incrementor of for-loop", 27238 | exprtk_error_location)); 27239 | 27240 | result = false; 27241 | } 27242 | else if (!token_is(token_t::e_rbracket)) 27243 | { 27244 | set_error(make_error( 27245 | parser_error::e_syntax, 27246 | current_token(), 27247 | "ERR087 - Expected ')' after incrementor section of for-loop", 27248 | exprtk_error_location)); 27249 | 27250 | result = false; 27251 | } 27252 | } 27253 | 27254 | if (result) 27255 | { 27256 | brkcnt_list_.push_front(false); 27257 | 27258 | scoped_inc_dec sid(state_.parsing_loop_stmt_count); 27259 | 27260 | if (0 == (loop_body = parse_multi_sequence("for-loop", true))) 27261 | { 27262 | set_error(make_error( 27263 | parser_error::e_syntax, 27264 | current_token(), 27265 | "ERR088 - Failed to parse body of for-loop", 27266 | exprtk_error_location)); 27267 | 27268 | result = false; 27269 | } 27270 | } 27271 | 27272 | if (!result) 27273 | { 27274 | if (se) 27275 | { 27276 | se->ref_count--; 27277 | } 27278 | 27279 | free_node(node_allocator_, initialiser); 27280 | free_node(node_allocator_, condition ); 27281 | free_node(node_allocator_, incrementor); 27282 | free_node(node_allocator_, loop_body ); 27283 | return error_node(); 27284 | } 27285 | 27286 | expression_node_ptr result_node = 27287 | expression_generator_.for_loop(initialiser, 27288 | condition, 27289 | incrementor, 27290 | loop_body, 27291 | brkcnt_list_.front()); 27292 | handle_brkcnt_scope_exit(); 27293 | 27294 | if (result_node && result_node->valid()) 27295 | { 27296 | return result_node; 27297 | } 27298 | 27299 | set_error(make_error( 27300 | parser_error::e_synthesis, 27301 | current_token(), 27302 | "ERR089 - Failed to synthesize 'valid' for-loop", 27303 | exprtk_error_location)); 27304 | 27305 | free_node(node_allocator_, result_node); 27306 | 27307 | return error_node(); 27308 | } 27309 | 27310 | inline expression_node_ptr parse_switch_statement() 27311 | { 27312 | std::vector<expression_node_ptr> arg_list; 27313 | 27314 | if (!details::imatch(current_token().value,"switch")) 27315 | { 27316 | set_error(make_error( 27317 | parser_error::e_syntax, 27318 | current_token(), 27319 | "ERR090 - Expected keyword 'switch'", 27320 | exprtk_error_location)); 27321 | 27322 | return error_node(); 27323 | } 27324 | 27325 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 27326 | 27327 | next_token(); 27328 | 27329 | if (!token_is(token_t::e_lcrlbracket)) 27330 | { 27331 | set_error(make_error( 27332 | parser_error::e_syntax, 27333 | current_token(), 27334 | "ERR091 - Expected '{' for call to switch statement", 27335 | exprtk_error_location)); 27336 | 27337 | return error_node(); 27338 | } 27339 | 27340 | expression_node_ptr default_statement = error_node(); 27341 | 27342 | scoped_expression_delete defstmt_delete((*this), default_statement); 27343 | 27344 | for ( ; ; ) 27345 | { 27346 | if (details::imatch("case",current_token().value)) 27347 | { 27348 | next_token(); 27349 | 27350 | expression_node_ptr condition = parse_expression(); 27351 | 27352 | if (0 == condition) 27353 | return error_node(); 27354 | else if (!token_is(token_t::e_colon)) 27355 | { 27356 | set_error(make_error( 27357 | parser_error::e_syntax, 27358 | current_token(), 27359 | "ERR092 - Expected ':' for case of switch statement", 27360 | exprtk_error_location)); 27361 | 27362 | free_node(node_allocator_, condition); 27363 | 27364 | return error_node(); 27365 | } 27366 | 27367 | expression_node_ptr consequent = 27368 | (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) ? 27369 | parse_multi_sequence("switch-consequent") : 27370 | parse_expression(); 27371 | 27372 | if (0 == consequent) 27373 | { 27374 | free_node(node_allocator_, condition); 27375 | 27376 | return error_node(); 27377 | } 27378 | else if (!token_is(token_t::e_eof)) 27379 | { 27380 | set_error(make_error( 27381 | parser_error::e_syntax, 27382 | current_token(), 27383 | "ERR093 - Expected ';' at end of case for switch statement", 27384 | exprtk_error_location)); 27385 | 27386 | free_node(node_allocator_, condition ); 27387 | free_node(node_allocator_, consequent); 27388 | 27389 | return error_node(); 27390 | } 27391 | 27392 | // Can we optimise away the case statement? 27393 | if (is_constant_node(condition) && is_false(condition)) 27394 | { 27395 | free_node(node_allocator_, condition ); 27396 | free_node(node_allocator_, consequent); 27397 | } 27398 | else 27399 | { 27400 | arg_list.push_back(condition ); 27401 | arg_list.push_back(consequent); 27402 | } 27403 | 27404 | } 27405 | else if (details::imatch("default",current_token().value)) 27406 | { 27407 | if (0 != default_statement) 27408 | { 27409 | set_error(make_error( 27410 | parser_error::e_syntax, 27411 | current_token(), 27412 | "ERR094 - Multiple default cases for switch statement", 27413 | exprtk_error_location)); 27414 | 27415 | return error_node(); 27416 | } 27417 | 27418 | next_token(); 27419 | 27420 | if (!token_is(token_t::e_colon)) 27421 | { 27422 | set_error(make_error( 27423 | parser_error::e_syntax, 27424 | current_token(), 27425 | "ERR095 - Expected ':' for default of switch statement", 27426 | exprtk_error_location)); 27427 | 27428 | return error_node(); 27429 | } 27430 | 27431 | default_statement = 27432 | (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) ? 27433 | parse_multi_sequence("switch-default"): 27434 | parse_expression(); 27435 | 27436 | if (0 == default_statement) 27437 | return error_node(); 27438 | else if (!token_is(token_t::e_eof)) 27439 | { 27440 | set_error(make_error( 27441 | parser_error::e_syntax, 27442 | current_token(), 27443 | "ERR096 - Expected ';' at end of default for switch statement", 27444 | exprtk_error_location)); 27445 | 27446 | return error_node(); 27447 | } 27448 | } 27449 | else if (token_is(token_t::e_rcrlbracket)) 27450 | break; 27451 | else 27452 | { 27453 | set_error(make_error( 27454 | parser_error::e_syntax, 27455 | current_token(), 27456 | "ERR097 - Expected '}' at end of switch statement", 27457 | exprtk_error_location)); 27458 | 27459 | return error_node(); 27460 | } 27461 | } 27462 | 27463 | const bool default_statement_present = (0 != default_statement); 27464 | 27465 | if (default_statement_present) 27466 | { 27467 | arg_list.push_back(default_statement); 27468 | } 27469 | else 27470 | { 27471 | arg_list.push_back(node_allocator_.allocate_c<literal_node_t>(std::numeric_limits<T>::quiet_NaN())); 27472 | } 27473 | 27474 | expression_node_ptr result = expression_generator_.switch_statement(arg_list, (0 != default_statement)); 27475 | 27476 | svd.delete_ptr = (0 == result); 27477 | defstmt_delete.delete_ptr = (0 == result); 27478 | 27479 | return result; 27480 | } 27481 | 27482 | inline expression_node_ptr parse_multi_switch_statement() 27483 | { 27484 | std::vector<expression_node_ptr> arg_list; 27485 | 27486 | if (!details::imatch(current_token().value,"[*]")) 27487 | { 27488 | set_error(make_error( 27489 | parser_error::e_syntax, 27490 | current_token(), 27491 | "ERR098 - Expected token '[*]'", 27492 | exprtk_error_location)); 27493 | 27494 | return error_node(); 27495 | } 27496 | 27497 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 27498 | 27499 | next_token(); 27500 | 27501 | if (!token_is(token_t::e_lcrlbracket)) 27502 | { 27503 | set_error(make_error( 27504 | parser_error::e_syntax, 27505 | current_token(), 27506 | "ERR099 - Expected '{' for call to [*] statement", 27507 | exprtk_error_location)); 27508 | 27509 | return error_node(); 27510 | } 27511 | 27512 | for ( ; ; ) 27513 | { 27514 | if (!details::imatch("case",current_token().value)) 27515 | { 27516 | set_error(make_error( 27517 | parser_error::e_syntax, 27518 | current_token(), 27519 | "ERR100 - Expected a 'case' statement for multi-switch", 27520 | exprtk_error_location)); 27521 | 27522 | return error_node(); 27523 | } 27524 | 27525 | next_token(); 27526 | 27527 | expression_node_ptr condition = parse_expression(); 27528 | 27529 | if (0 == condition) 27530 | return error_node(); 27531 | 27532 | if (!token_is(token_t::e_colon)) 27533 | { 27534 | set_error(make_error( 27535 | parser_error::e_syntax, 27536 | current_token(), 27537 | "ERR101 - Expected ':' for case of [*] statement", 27538 | exprtk_error_location)); 27539 | 27540 | return error_node(); 27541 | } 27542 | 27543 | expression_node_ptr consequent = 27544 | (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) ? 27545 | parse_multi_sequence("multi-switch-consequent") : 27546 | parse_expression(); 27547 | 27548 | if (0 == consequent) 27549 | return error_node(); 27550 | 27551 | if (!token_is(token_t::e_eof)) 27552 | { 27553 | set_error(make_error( 27554 | parser_error::e_syntax, 27555 | current_token(), 27556 | "ERR102 - Expected ';' at end of case for [*] statement", 27557 | exprtk_error_location)); 27558 | 27559 | return error_node(); 27560 | } 27561 | 27562 | // Can we optimise away the case statement? 27563 | if (is_constant_node(condition) && is_false(condition)) 27564 | { 27565 | free_node(node_allocator_, condition ); 27566 | free_node(node_allocator_, consequent); 27567 | } 27568 | else 27569 | { 27570 | arg_list.push_back(condition ); 27571 | arg_list.push_back(consequent); 27572 | } 27573 | 27574 | if (token_is(token_t::e_rcrlbracket,prsrhlpr_t::e_hold)) 27575 | { 27576 | break; 27577 | } 27578 | } 27579 | 27580 | if (!token_is(token_t::e_rcrlbracket)) 27581 | { 27582 | set_error(make_error( 27583 | parser_error::e_syntax, 27584 | current_token(), 27585 | "ERR103 - Expected '}' at end of [*] statement", 27586 | exprtk_error_location)); 27587 | 27588 | return error_node(); 27589 | } 27590 | 27591 | const expression_node_ptr result = expression_generator_.multi_switch_statement(arg_list); 27592 | 27593 | svd.delete_ptr = (0 == result); 27594 | 27595 | return result; 27596 | } 27597 | 27598 | inline expression_node_ptr parse_vararg_function() 27599 | { 27600 | std::vector<expression_node_ptr> arg_list; 27601 | 27602 | details::operator_type opt_type = details::e_default; 27603 | const std::string symbol = current_token().value; 27604 | 27605 | if (details::imatch(symbol,"~")) 27606 | { 27607 | next_token(); 27608 | return check_block_statement_closure(parse_multi_sequence()); 27609 | } 27610 | else if (details::imatch(symbol,"[*]")) 27611 | { 27612 | return check_block_statement_closure(parse_multi_switch_statement()); 27613 | } 27614 | else if (details::imatch(symbol, "avg" )) opt_type = details::e_avg ; 27615 | else if (details::imatch(symbol, "mand")) opt_type = details::e_mand; 27616 | else if (details::imatch(symbol, "max" )) opt_type = details::e_max ; 27617 | else if (details::imatch(symbol, "min" )) opt_type = details::e_min ; 27618 | else if (details::imatch(symbol, "mor" )) opt_type = details::e_mor ; 27619 | else if (details::imatch(symbol, "mul" )) opt_type = details::e_prod; 27620 | else if (details::imatch(symbol, "sum" )) opt_type = details::e_sum ; 27621 | else 27622 | { 27623 | set_error(make_error( 27624 | parser_error::e_syntax, 27625 | current_token(), 27626 | "ERR104 - Unsupported built-in vararg function: " + symbol, 27627 | exprtk_error_location)); 27628 | 27629 | return error_node(); 27630 | } 27631 | 27632 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 27633 | 27634 | lodge_symbol(symbol, e_st_function); 27635 | 27636 | next_token(); 27637 | 27638 | if (!token_is(token_t::e_lbracket)) 27639 | { 27640 | set_error(make_error( 27641 | parser_error::e_syntax, 27642 | current_token(), 27643 | "ERR105 - Expected '(' for call to vararg function: " + symbol, 27644 | exprtk_error_location)); 27645 | 27646 | return error_node(); 27647 | } 27648 | 27649 | if (token_is(token_t::e_rbracket)) 27650 | { 27651 | set_error(make_error( 27652 | parser_error::e_syntax, 27653 | current_token(), 27654 | "ERR106 - vararg function: " + symbol + 27655 | " requires at least one input parameter", 27656 | exprtk_error_location)); 27657 | 27658 | return error_node(); 27659 | } 27660 | 27661 | for ( ; ; ) 27662 | { 27663 | expression_node_ptr arg = parse_expression(); 27664 | 27665 | if (0 == arg) 27666 | return error_node(); 27667 | else 27668 | arg_list.push_back(arg); 27669 | 27670 | if (token_is(token_t::e_rbracket)) 27671 | break; 27672 | else if (!token_is(token_t::e_comma)) 27673 | { 27674 | set_error(make_error( 27675 | parser_error::e_syntax, 27676 | current_token(), 27677 | "ERR107 - Expected ',' for call to vararg function: " + symbol, 27678 | exprtk_error_location)); 27679 | 27680 | return error_node(); 27681 | } 27682 | } 27683 | 27684 | const expression_node_ptr result = expression_generator_.vararg_function(opt_type,arg_list); 27685 | 27686 | svd.delete_ptr = (0 == result); 27687 | return result; 27688 | } 27689 | 27690 | #ifndef exprtk_disable_string_capabilities 27691 | inline expression_node_ptr parse_string_range_statement(expression_node_ptr& expression) 27692 | { 27693 | if (!token_is(token_t::e_lsqrbracket)) 27694 | { 27695 | set_error(make_error( 27696 | parser_error::e_syntax, 27697 | current_token(), 27698 | "ERR108 - Expected '[' as start of string range definition", 27699 | exprtk_error_location)); 27700 | 27701 | free_node(node_allocator_, expression); 27702 | 27703 | return error_node(); 27704 | } 27705 | else if (token_is(token_t::e_rsqrbracket)) 27706 | { 27707 | return node_allocator_.allocate<details::string_size_node<T> >(expression); 27708 | } 27709 | 27710 | range_t rp; 27711 | 27712 | if (!parse_range(rp,true)) 27713 | { 27714 | free_node(node_allocator_, expression); 27715 | 27716 | return error_node(); 27717 | } 27718 | 27719 | expression_node_ptr result = expression_generator_(expression,rp); 27720 | 27721 | if (0 == result) 27722 | { 27723 | set_error(make_error( 27724 | parser_error::e_syntax, 27725 | current_token(), 27726 | "ERR109 - Failed to generate string range node", 27727 | exprtk_error_location)); 27728 | 27729 | free_node(node_allocator_, expression); 27730 | rp.free(); 27731 | } 27732 | 27733 | rp.clear(); 27734 | 27735 | if (result && result->valid()) 27736 | { 27737 | return result; 27738 | } 27739 | 27740 | set_error(make_error( 27741 | parser_error::e_synthesis, 27742 | current_token(), 27743 | "ERR110 - Failed to synthesize node: string_range_node", 27744 | exprtk_error_location)); 27745 | 27746 | free_node(node_allocator_, result); 27747 | rp.free(); 27748 | return error_node(); 27749 | } 27750 | #else 27751 | inline expression_node_ptr parse_string_range_statement(expression_node_ptr&) 27752 | { 27753 | return error_node(); 27754 | } 27755 | #endif 27756 | 27757 | inline bool parse_pending_string_rangesize(expression_node_ptr& expression) 27758 | { 27759 | // Allow no more than 100 range calls, eg: s[][][]...[][] 27760 | const std::size_t max_rangesize_parses = 100; 27761 | 27762 | std::size_t i = 0; 27763 | 27764 | while 27765 | ( 27766 | (0 != expression) && 27767 | (i++ < max_rangesize_parses) && 27768 | error_list_.empty() && 27769 | is_generally_string_node(expression) && 27770 | token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold) 27771 | ) 27772 | { 27773 | expression = parse_string_range_statement(expression); 27774 | } 27775 | 27776 | return (i > 1); 27777 | } 27778 | 27779 | inline void parse_pending_vector_index_operator(expression_node_ptr& expression) 27780 | { 27781 | if 27782 | ( 27783 | (0 != expression) && 27784 | error_list_.empty() && 27785 | is_ivector_node(expression) 27786 | ) 27787 | { 27788 | if ( 27789 | settings_.commutative_check_enabled() && 27790 | token_is(token_t::e_mul,prsrhlpr_t::e_hold) && 27791 | peek_token_is(token_t::e_lsqrbracket) 27792 | ) 27793 | { 27794 | token_is(token_t::e_mul); 27795 | token_is(token_t::e_lsqrbracket); 27796 | } 27797 | else if (token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold)) 27798 | { 27799 | token_is(token_t::e_lsqrbracket); 27800 | } 27801 | else if ( 27802 | token_is(token_t::e_rbracket,prsrhlpr_t::e_hold) && 27803 | peek_token_is(token_t::e_lsqrbracket) 27804 | ) 27805 | { 27806 | token_is(token_t::e_rbracket ); 27807 | token_is(token_t::e_lsqrbracket); 27808 | } 27809 | else 27810 | return; 27811 | 27812 | details::vector_interface<T>* vi = dynamic_cast<details::vector_interface<T>*>(expression); 27813 | 27814 | if (vi) 27815 | { 27816 | details::vector_holder<T>& vec = vi->vec()->vec_holder(); 27817 | const std::string vector_name = sem_.get_vector_name(vec.data()); 27818 | expression_node_ptr index = parse_vector_index(vector_name); 27819 | 27820 | if (index) 27821 | { 27822 | expression = synthesize_vector_element(vector_name, &vec, expression, index); 27823 | return; 27824 | } 27825 | } 27826 | 27827 | free_node(node_allocator_, expression); 27828 | expression = error_node(); 27829 | } 27830 | } 27831 | 27832 | template <typename Allocator1, 27833 | typename Allocator2, 27834 | template <typename, typename> class Sequence> 27835 | inline expression_node_ptr simplify(Sequence<expression_node_ptr,Allocator1>& expression_list, 27836 | Sequence<bool,Allocator2>& side_effect_list, 27837 | const bool specialise_on_final_type = false) 27838 | { 27839 | if (expression_list.empty()) 27840 | return error_node(); 27841 | else if (1 == expression_list.size()) 27842 | return expression_list[0]; 27843 | 27844 | Sequence<expression_node_ptr,Allocator1> tmp_expression_list; 27845 | 27846 | exprtk_debug(("simplify() - expression_list.size: %d side_effect_list.size(): %d\n", 27847 | static_cast<int>(expression_list .size()), 27848 | static_cast<int>(side_effect_list.size()))); 27849 | 27850 | bool return_node_present = false; 27851 | 27852 | for (std::size_t i = 0; i < (expression_list.size() - 1); ++i) 27853 | { 27854 | if (is_variable_node(expression_list[i])) 27855 | continue; 27856 | else if ( 27857 | is_return_node (expression_list[i]) || 27858 | is_break_node (expression_list[i]) || 27859 | is_continue_node(expression_list[i]) 27860 | ) 27861 | { 27862 | tmp_expression_list.push_back(expression_list[i]); 27863 | 27864 | // Remove all subexpressions after first short-circuit 27865 | // node has been encountered. 27866 | 27867 | for (std::size_t j = i + 1; j < expression_list.size(); ++j) 27868 | { 27869 | free_node(node_allocator_, expression_list[j]); 27870 | } 27871 | 27872 | return_node_present = true; 27873 | 27874 | break; 27875 | } 27876 | else if ( 27877 | is_constant_node(expression_list[i]) || 27878 | is_null_node (expression_list[i]) || 27879 | !side_effect_list[i] 27880 | ) 27881 | { 27882 | free_node(node_allocator_, expression_list[i]); 27883 | continue; 27884 | } 27885 | else 27886 | tmp_expression_list.push_back(expression_list[i]); 27887 | } 27888 | 27889 | if (!return_node_present) 27890 | { 27891 | tmp_expression_list.push_back(expression_list.back()); 27892 | } 27893 | 27894 | expression_list.swap(tmp_expression_list); 27895 | 27896 | if (tmp_expression_list.size() > expression_list.size()) 27897 | { 27898 | exprtk_debug(("simplify() - Reduced subexpressions from %d to %d\n", 27899 | static_cast<int>(tmp_expression_list.size()), 27900 | static_cast<int>(expression_list .size()))); 27901 | } 27902 | 27903 | if ( 27904 | return_node_present || 27905 | side_effect_list.back() || 27906 | (expression_list.size() > 1) 27907 | ) 27908 | state_.activate_side_effect("simplify()"); 27909 | 27910 | if (1 == expression_list.size()) 27911 | return expression_list[0]; 27912 | else if (specialise_on_final_type && is_generally_string_node(expression_list.back())) 27913 | return expression_generator_.vararg_function(details::e_smulti,expression_list); 27914 | else 27915 | return expression_generator_.vararg_function(details::e_multi,expression_list); 27916 | } 27917 | 27918 | inline expression_node_ptr parse_multi_sequence(const std::string& source = "", 27919 | const bool enforce_crlbrackets = false) 27920 | { 27921 | token_t::token_type open_bracket = token_t::e_lcrlbracket; 27922 | token_t::token_type close_bracket = token_t::e_rcrlbracket; 27923 | token_t::token_type separator = token_t::e_eof; 27924 | 27925 | if (!token_is(open_bracket)) 27926 | { 27927 | if (!enforce_crlbrackets && token_is(token_t::e_lbracket)) 27928 | { 27929 | open_bracket = token_t::e_lbracket; 27930 | close_bracket = token_t::e_rbracket; 27931 | separator = token_t::e_comma; 27932 | } 27933 | else 27934 | { 27935 | set_error(make_error( 27936 | parser_error::e_syntax, 27937 | current_token(), 27938 | "ERR111 - Expected '" + token_t::to_str(open_bracket) + "' for call to multi-sequence" + 27939 | ((!source.empty()) ? std::string(" section of " + source): ""), 27940 | exprtk_error_location)); 27941 | 27942 | return error_node(); 27943 | } 27944 | } 27945 | else if (token_is(close_bracket)) 27946 | { 27947 | return node_allocator_.allocate<details::null_node<T> >(); 27948 | } 27949 | 27950 | std::vector<expression_node_ptr> arg_list; 27951 | std::vector<bool> side_effect_list; 27952 | 27953 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 27954 | 27955 | scope_handler sh(*this); 27956 | 27957 | scoped_bool_or_restorer sbr(state_.side_effect_present); 27958 | 27959 | for ( ; ; ) 27960 | { 27961 | state_.side_effect_present = false; 27962 | 27963 | expression_node_ptr arg = parse_expression(); 27964 | 27965 | if (0 == arg) 27966 | return error_node(); 27967 | else 27968 | { 27969 | arg_list.push_back(arg); 27970 | side_effect_list.push_back(state_.side_effect_present); 27971 | } 27972 | 27973 | if (token_is(close_bracket)) 27974 | break; 27975 | 27976 | const bool is_next_close = peek_token_is(close_bracket); 27977 | 27978 | if (!token_is(separator) && is_next_close) 27979 | { 27980 | set_error(make_error( 27981 | parser_error::e_syntax, 27982 | current_token(), 27983 | "ERR112 - Expected '" + lexer::token::seperator_to_str(separator) + "' for call to multi-sequence section of " + source, 27984 | exprtk_error_location)); 27985 | 27986 | return error_node(); 27987 | } 27988 | 27989 | if (token_is(close_bracket)) 27990 | break; 27991 | } 27992 | 27993 | expression_node_ptr result = simplify(arg_list, side_effect_list, source.empty()); 27994 | 27995 | svd.delete_ptr = (0 == result); 27996 | return result; 27997 | } 27998 | 27999 | inline bool parse_range(range_t& rp, const bool skip_lsqr = false) 28000 | { 28001 | // Examples of valid ranges: 28002 | // 1. [1:5] -> [1,5) 28003 | // 2. [ :5] -> [0,5) 28004 | // 3. [1: ] -> [1,end) 28005 | // 4. [x:y] -> [x,y) where x <= y 28006 | // 5. [x+1:y/2] -> [x+1,y/2) where x+1 <= y/2 28007 | // 6. [ :y] -> [0,y) where 0 <= y 28008 | // 7. [x: ] -> [x,end) where x <= end 28009 | 28010 | rp.clear(); 28011 | 28012 | if (!skip_lsqr && !token_is(token_t::e_lsqrbracket)) 28013 | { 28014 | set_error(make_error( 28015 | parser_error::e_syntax, 28016 | current_token(), 28017 | "ERR113 - Expected '[' for start of range", 28018 | exprtk_error_location)); 28019 | 28020 | return false; 28021 | } 28022 | 28023 | if (token_is(token_t::e_colon)) 28024 | { 28025 | rp.n0_c.first = true; 28026 | rp.n0_c.second = 0; 28027 | rp.cache.first = 0; 28028 | } 28029 | else 28030 | { 28031 | expression_node_ptr r0 = parse_expression(); 28032 | 28033 | if (0 == r0) 28034 | { 28035 | set_error(make_error( 28036 | parser_error::e_syntax, 28037 | current_token(), 28038 | "ERR114 - Failed parse begin section of range", 28039 | exprtk_error_location)); 28040 | 28041 | return false; 28042 | } 28043 | else if (is_constant_node(r0)) 28044 | { 28045 | const T r0_value = r0->value(); 28046 | 28047 | if (r0_value >= T(0)) 28048 | { 28049 | rp.n0_c.first = true; 28050 | rp.n0_c.second = static_cast<std::size_t>(details::numeric::to_int64(r0_value)); 28051 | rp.cache.first = rp.n0_c.second; 28052 | } 28053 | 28054 | free_node(node_allocator_, r0); 28055 | 28056 | if (r0_value < T(0)) 28057 | { 28058 | set_error(make_error( 28059 | parser_error::e_syntax, 28060 | current_token(), 28061 | "ERR115 - Range lower bound less than zero! Constraint: r0 >= 0", 28062 | exprtk_error_location)); 28063 | 28064 | return false; 28065 | } 28066 | } 28067 | else 28068 | { 28069 | rp.n0_e.first = true; 28070 | rp.n0_e.second = r0; 28071 | } 28072 | 28073 | if (!token_is(token_t::e_colon)) 28074 | { 28075 | set_error(make_error( 28076 | parser_error::e_syntax, 28077 | current_token(), 28078 | "ERR116 - Expected ':' for break in range", 28079 | exprtk_error_location)); 28080 | 28081 | rp.free(); 28082 | 28083 | return false; 28084 | } 28085 | } 28086 | 28087 | if (token_is(token_t::e_rsqrbracket)) 28088 | { 28089 | rp.n1_c.first = true; 28090 | rp.n1_c.second = std::numeric_limits<std::size_t>::max(); 28091 | } 28092 | else 28093 | { 28094 | expression_node_ptr r1 = parse_expression(); 28095 | 28096 | if (0 == r1) 28097 | { 28098 | set_error(make_error( 28099 | parser_error::e_syntax, 28100 | current_token(), 28101 | "ERR117 - Failed parse end section of range", 28102 | exprtk_error_location)); 28103 | 28104 | rp.free(); 28105 | 28106 | return false; 28107 | } 28108 | else if (is_constant_node(r1)) 28109 | { 28110 | const T r1_value = r1->value(); 28111 | 28112 | if (r1_value >= T(0)) 28113 | { 28114 | rp.n1_c.first = true; 28115 | rp.n1_c.second = static_cast<std::size_t>(details::numeric::to_int64(r1_value)); 28116 | rp.cache.second = rp.n1_c.second; 28117 | } 28118 | 28119 | free_node(node_allocator_, r1); 28120 | 28121 | if (r1_value < T(0)) 28122 | { 28123 | set_error(make_error( 28124 | parser_error::e_syntax, 28125 | current_token(), 28126 | "ERR118 - Range upper bound less than zero! Constraint: r1 >= 0", 28127 | exprtk_error_location)); 28128 | 28129 | rp.free(); 28130 | 28131 | return false; 28132 | } 28133 | } 28134 | else 28135 | { 28136 | rp.n1_e.first = true; 28137 | rp.n1_e.second = r1; 28138 | } 28139 | 28140 | if (!token_is(token_t::e_rsqrbracket)) 28141 | { 28142 | set_error(make_error( 28143 | parser_error::e_syntax, 28144 | current_token(), 28145 | "ERR119 - Expected ']' for start of range", 28146 | exprtk_error_location)); 28147 | 28148 | rp.free(); 28149 | 28150 | return false; 28151 | } 28152 | } 28153 | 28154 | if (rp.const_range()) 28155 | { 28156 | std::size_t r0 = 0; 28157 | std::size_t r1 = 0; 28158 | 28159 | bool rp_result = false; 28160 | 28161 | try 28162 | { 28163 | rp_result = rp(r0, r1); 28164 | } 28165 | catch (std::runtime_error&) 28166 | {} 28167 | 28168 | if (!rp_result || (r0 > r1)) 28169 | { 28170 | set_error(make_error( 28171 | parser_error::e_syntax, 28172 | current_token(), 28173 | "ERR120 - Invalid range, Constraint: r0 <= r1", 28174 | exprtk_error_location)); 28175 | 28176 | return false; 28177 | } 28178 | } 28179 | 28180 | return true; 28181 | } 28182 | 28183 | inline void lodge_symbol(const std::string& symbol, 28184 | const symbol_type st) 28185 | { 28186 | dec_.add_symbol(symbol,st); 28187 | } 28188 | 28189 | #ifndef exprtk_disable_string_capabilities 28190 | inline expression_node_ptr parse_string() 28191 | { 28192 | const std::string symbol = current_token().value; 28193 | 28194 | typedef details::stringvar_node<T>* strvar_node_t; 28195 | 28196 | expression_node_ptr result = error_node(); 28197 | strvar_node_t const_str_node = static_cast<strvar_node_t>(0); 28198 | 28199 | scope_element& se = sem_.get_active_element(symbol); 28200 | 28201 | if (scope_element::e_string == se.type) 28202 | { 28203 | se.active = true; 28204 | result = se.str_node; 28205 | lodge_symbol(symbol, e_st_local_string); 28206 | } 28207 | else 28208 | { 28209 | typedef typename symtab_store::string_context str_ctxt_t; 28210 | str_ctxt_t str_ctx = symtab_store_.get_string_context(symbol); 28211 | 28212 | if ((0 == str_ctx.str_var) || !symtab_store_.is_conststr_stringvar(symbol)) 28213 | { 28214 | set_error(make_error( 28215 | parser_error::e_syntax, 28216 | current_token(), 28217 | "ERR121 - Unknown string symbol", 28218 | exprtk_error_location)); 28219 | 28220 | return error_node(); 28221 | } 28222 | 28223 | assert(str_ctx.str_var != 0); 28224 | assert(str_ctx.symbol_table != 0); 28225 | 28226 | result = str_ctx.str_var; 28227 | 28228 | if (symtab_store_.is_constant_string(symbol)) 28229 | { 28230 | const_str_node = static_cast<strvar_node_t>(result); 28231 | result = expression_generator_(const_str_node->str()); 28232 | } 28233 | else if (symbol_table_t::e_immutable == str_ctx.symbol_table->mutability()) 28234 | { 28235 | lodge_immutable_symbol( 28236 | current_token(), 28237 | make_memory_range(str_ctx.str_var->base(), str_ctx.str_var->size())); 28238 | } 28239 | 28240 | lodge_symbol(symbol, e_st_string); 28241 | } 28242 | 28243 | if (peek_token_is(token_t::e_lsqrbracket)) 28244 | { 28245 | next_token(); 28246 | 28247 | if (peek_token_is(token_t::e_rsqrbracket)) 28248 | { 28249 | next_token(); 28250 | next_token(); 28251 | 28252 | if (const_str_node) 28253 | { 28254 | free_node(node_allocator_, result); 28255 | 28256 | return expression_generator_(T(const_str_node->size())); 28257 | } 28258 | else 28259 | return node_allocator_.allocate<details::stringvar_size_node<T> > 28260 | (static_cast<details::stringvar_node<T>*>(result)->ref()); 28261 | } 28262 | 28263 | range_t rp; 28264 | 28265 | if (!parse_range(rp)) 28266 | { 28267 | free_node(node_allocator_, result); 28268 | 28269 | return error_node(); 28270 | } 28271 | else if (const_str_node) 28272 | { 28273 | free_node(node_allocator_, result); 28274 | result = expression_generator_(const_str_node->ref(),rp); 28275 | } 28276 | else 28277 | result = expression_generator_(static_cast<details::stringvar_node<T>*> 28278 | (result)->ref(), rp); 28279 | 28280 | if (result) 28281 | rp.clear(); 28282 | } 28283 | else 28284 | next_token(); 28285 | 28286 | return result; 28287 | } 28288 | #else 28289 | inline expression_node_ptr parse_string() 28290 | { 28291 | return error_node(); 28292 | } 28293 | #endif 28294 | 28295 | #ifndef exprtk_disable_string_capabilities 28296 | inline expression_node_ptr parse_const_string() 28297 | { 28298 | const std::string const_str = current_token().value; 28299 | expression_node_ptr result = expression_generator_(const_str); 28300 | 28301 | if (peek_token_is(token_t::e_lsqrbracket)) 28302 | { 28303 | next_token(); 28304 | 28305 | if (peek_token_is(token_t::e_rsqrbracket)) 28306 | { 28307 | next_token(); 28308 | next_token(); 28309 | 28310 | free_node(node_allocator_, result); 28311 | 28312 | return expression_generator_(T(const_str.size())); 28313 | } 28314 | 28315 | range_t rp; 28316 | 28317 | if (!parse_range(rp)) 28318 | { 28319 | free_node(node_allocator_, result); 28320 | rp.free(); 28321 | 28322 | return error_node(); 28323 | } 28324 | 28325 | free_node(node_allocator_, result); 28326 | 28327 | if (rp.n1_c.first && (rp.n1_c.second == std::numeric_limits<std::size_t>::max())) 28328 | { 28329 | rp.n1_c.second = const_str.size() - 1; 28330 | rp.cache.second = rp.n1_c.second; 28331 | } 28332 | 28333 | if ( 28334 | (rp.n0_c.first && (rp.n0_c.second >= const_str.size())) || 28335 | (rp.n1_c.first && (rp.n1_c.second >= const_str.size())) 28336 | ) 28337 | { 28338 | set_error(make_error( 28339 | parser_error::e_syntax, 28340 | current_token(), 28341 | "ERR122 - Overflow in range for string: '" + const_str + "'[" + 28342 | (rp.n0_c.first ? details::to_str(static_cast<int>(rp.n0_c.second)) : "?") + ":" + 28343 | (rp.n1_c.first ? details::to_str(static_cast<int>(rp.n1_c.second)) : "?") + "]", 28344 | exprtk_error_location)); 28345 | 28346 | rp.free(); 28347 | 28348 | return error_node(); 28349 | } 28350 | 28351 | result = expression_generator_(const_str,rp); 28352 | 28353 | if (result) 28354 | rp.clear(); 28355 | } 28356 | else 28357 | next_token(); 28358 | 28359 | return result; 28360 | } 28361 | #else 28362 | inline expression_node_ptr parse_const_string() 28363 | { 28364 | return error_node(); 28365 | } 28366 | #endif 28367 | 28368 | inline expression_node_ptr parse_vector_index(const std::string& vector_name = "") 28369 | { 28370 | expression_node_ptr index_expr = error_node(); 28371 | 28372 | if (0 == (index_expr = parse_expression())) 28373 | { 28374 | set_error(make_error( 28375 | parser_error::e_syntax, 28376 | current_token(), 28377 | "ERR123 - Failed to parse index for vector: '" + vector_name + "'", 28378 | exprtk_error_location)); 28379 | 28380 | return error_node(); 28381 | } 28382 | else if (!token_is(token_t::e_rsqrbracket)) 28383 | { 28384 | set_error(make_error( 28385 | parser_error::e_syntax, 28386 | current_token(), 28387 | "ERR124 - Expected ']' for index of vector: '" + vector_name + "'", 28388 | exprtk_error_location)); 28389 | 28390 | free_node(node_allocator_, index_expr); 28391 | 28392 | return error_node(); 28393 | } 28394 | 28395 | return index_expr; 28396 | } 28397 | 28398 | inline expression_node_ptr parse_vector() 28399 | { 28400 | const std::string vector_name = current_token().value; 28401 | 28402 | vector_holder_ptr vec = vector_holder_ptr(0); 28403 | 28404 | const scope_element& se = sem_.get_active_element(vector_name); 28405 | 28406 | if ( 28407 | !details::imatch(se.name, vector_name) || 28408 | (se.depth > state_.scope_depth) || 28409 | (scope_element::e_vector != se.type) 28410 | ) 28411 | { 28412 | typedef typename symtab_store::vector_context vec_ctxt_t; 28413 | vec_ctxt_t vec_ctx = symtab_store_.get_vector_context(vector_name); 28414 | 28415 | if (0 == vec_ctx.vector_holder) 28416 | { 28417 | set_error(make_error( 28418 | parser_error::e_syntax, 28419 | current_token(), 28420 | "ERR125 - Symbol '" + vector_name + " not a vector", 28421 | exprtk_error_location)); 28422 | 28423 | return error_node(); 28424 | } 28425 | 28426 | assert(0 != vec_ctx.vector_holder); 28427 | assert(0 != vec_ctx.symbol_table ); 28428 | 28429 | vec = vec_ctx.vector_holder; 28430 | 28431 | if (symbol_table_t::e_immutable == vec_ctx.symbol_table->mutability()) 28432 | { 28433 | lodge_immutable_symbol( 28434 | current_token(), 28435 | make_memory_range(vec->data(), vec->size())); 28436 | } 28437 | } 28438 | else 28439 | { 28440 | vec = se.vec_node; 28441 | } 28442 | 28443 | assert(0 != vec); 28444 | 28445 | next_token(); 28446 | 28447 | if (!token_is(token_t::e_lsqrbracket)) 28448 | { 28449 | return node_allocator_.allocate<vector_node_t>(vec); 28450 | } 28451 | else if (token_is(token_t::e_rsqrbracket)) 28452 | { 28453 | return (vec->rebaseable()) ? 28454 | node_allocator_.allocate<vector_size_node_t>(vec) : 28455 | expression_generator_(T(vec->size())); 28456 | } 28457 | 28458 | expression_node_ptr index_expr = parse_vector_index(vector_name); 28459 | 28460 | if (index_expr) 28461 | { 28462 | expression_node_ptr vec_node = node_allocator_.allocate<vector_node_t>(vec); 28463 | 28464 | return synthesize_vector_element(vector_name, vec, vec_node, index_expr); 28465 | } 28466 | 28467 | return error_node(); 28468 | } 28469 | 28470 | inline expression_node_ptr synthesize_vector_element(const std::string& vector_name, 28471 | vector_holder_ptr vec, 28472 | expression_node_ptr vec_node, 28473 | expression_node_ptr index_expr) 28474 | { 28475 | // Perform compile-time range check 28476 | if (details::is_constant_node(index_expr)) 28477 | { 28478 | const std::size_t index = static_cast<std::size_t>(details::numeric::to_int32(index_expr->value())); 28479 | const std::size_t vec_size = vec->size(); 28480 | 28481 | if (index >= vec_size) 28482 | { 28483 | set_error(make_error( 28484 | parser_error::e_syntax, 28485 | current_token(), 28486 | "ERR126 - Index of " + details::to_str(index) + " out of range for " 28487 | "vector '" + vector_name + "' of size " + details::to_str(vec_size), 28488 | exprtk_error_location)); 28489 | 28490 | free_node(node_allocator_, vec_node ); 28491 | free_node(node_allocator_, index_expr); 28492 | 28493 | return error_node(); 28494 | } 28495 | } 28496 | 28497 | return expression_generator_.vector_element(vector_name, vec, vec_node, index_expr); 28498 | } 28499 | 28500 | inline expression_node_ptr parse_vararg_function_call(ivararg_function<T>* vararg_function, const std::string& vararg_function_name) 28501 | { 28502 | std::vector<expression_node_ptr> arg_list; 28503 | 28504 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 28505 | 28506 | next_token(); 28507 | 28508 | if (token_is(token_t::e_lbracket)) 28509 | { 28510 | if (token_is(token_t::e_rbracket)) 28511 | { 28512 | if (!vararg_function->allow_zero_parameters()) 28513 | { 28514 | set_error(make_error( 28515 | parser_error::e_syntax, 28516 | current_token(), 28517 | "ERR127 - Zero parameter call to vararg function: " 28518 | + vararg_function_name + " not allowed", 28519 | exprtk_error_location)); 28520 | 28521 | return error_node(); 28522 | } 28523 | } 28524 | else 28525 | { 28526 | for ( ; ; ) 28527 | { 28528 | expression_node_ptr arg = parse_expression(); 28529 | 28530 | if (0 == arg) 28531 | return error_node(); 28532 | else 28533 | arg_list.push_back(arg); 28534 | 28535 | if (token_is(token_t::e_rbracket)) 28536 | break; 28537 | else if (!token_is(token_t::e_comma)) 28538 | { 28539 | set_error(make_error( 28540 | parser_error::e_syntax, 28541 | current_token(), 28542 | "ERR128 - Expected ',' for call to vararg function: " 28543 | + vararg_function_name, 28544 | exprtk_error_location)); 28545 | 28546 | return error_node(); 28547 | } 28548 | } 28549 | } 28550 | } 28551 | else if (!vararg_function->allow_zero_parameters()) 28552 | { 28553 | set_error(make_error( 28554 | parser_error::e_syntax, 28555 | current_token(), 28556 | "ERR129 - Zero parameter call to vararg function: " 28557 | + vararg_function_name + " not allowed", 28558 | exprtk_error_location)); 28559 | 28560 | return error_node(); 28561 | } 28562 | 28563 | if (arg_list.size() < vararg_function->min_num_args()) 28564 | { 28565 | set_error(make_error( 28566 | parser_error::e_syntax, 28567 | current_token(), 28568 | "ERR130 - Invalid number of parameters to call to vararg function: " 28569 | + vararg_function_name + ", require at least " 28570 | + details::to_str(static_cast<int>(vararg_function->min_num_args())) + " parameters", 28571 | exprtk_error_location)); 28572 | 28573 | return error_node(); 28574 | } 28575 | else if (arg_list.size() > vararg_function->max_num_args()) 28576 | { 28577 | set_error(make_error( 28578 | parser_error::e_syntax, 28579 | current_token(), 28580 | "ERR131 - Invalid number of parameters to call to vararg function: " 28581 | + vararg_function_name + ", require no more than " 28582 | + details::to_str(static_cast<int>(vararg_function->max_num_args())) + " parameters", 28583 | exprtk_error_location)); 28584 | 28585 | return error_node(); 28586 | } 28587 | 28588 | expression_node_ptr result = expression_generator_.vararg_function_call(vararg_function,arg_list); 28589 | 28590 | svd.delete_ptr = (0 == result); 28591 | 28592 | return result; 28593 | } 28594 | 28595 | class type_checker 28596 | { 28597 | public: 28598 | 28599 | enum return_type_t 28600 | { 28601 | e_overload = ' ', 28602 | e_numeric = 'T', 28603 | e_string = 'S' 28604 | }; 28605 | 28606 | struct function_prototype_t 28607 | { 28608 | return_type_t return_type; 28609 | std::string param_seq; 28610 | }; 28611 | 28612 | typedef parser<T> parser_t; 28613 | typedef std::vector<function_prototype_t> function_definition_list_t; 28614 | 28615 | type_checker(parser_t& p, 28616 | const std::string& func_name, 28617 | const std::string& func_prototypes, 28618 | const return_type_t default_return_type) 28619 | : invalid_state_(true) 28620 | , parser_(p) 28621 | , function_name_(func_name) 28622 | , default_return_type_(default_return_type) 28623 | { 28624 | parse_function_prototypes(func_prototypes); 28625 | } 28626 | 28627 | bool verify(const std::string& param_seq, std::size_t& pseq_index) 28628 | { 28629 | if (function_definition_list_.empty()) 28630 | return true; 28631 | 28632 | std::vector<std::pair<std::size_t,char> > error_list; 28633 | 28634 | for (std::size_t i = 0; i < function_definition_list_.size(); ++i) 28635 | { 28636 | details::char_t diff_value = 0; 28637 | std::size_t diff_index = 0; 28638 | 28639 | const bool result = details::sequence_match(function_definition_list_[i].param_seq, 28640 | param_seq, 28641 | diff_index, diff_value); 28642 | 28643 | if (result) 28644 | { 28645 | pseq_index = i; 28646 | return true; 28647 | } 28648 | else 28649 | error_list.push_back(std::make_pair(diff_index, diff_value)); 28650 | } 28651 | 28652 | if (1 == error_list.size()) 28653 | { 28654 | parser_.set_error(make_error( 28655 | parser_error::e_syntax, 28656 | parser_.current_token(), 28657 | "ERR132 - Failed parameter type check for function '" + function_name_ + "', " 28658 | "Expected '" + function_definition_list_[0].param_seq + 28659 | "' call set: '" + param_seq + "'", 28660 | exprtk_error_location)); 28661 | } 28662 | else 28663 | { 28664 | // find first with largest diff_index; 28665 | std::size_t max_diff_index = 0; 28666 | 28667 | for (std::size_t i = 1; i < error_list.size(); ++i) 28668 | { 28669 | if (error_list[i].first > error_list[max_diff_index].first) 28670 | { 28671 | max_diff_index = i; 28672 | } 28673 | } 28674 | 28675 | parser_.set_error(make_error( 28676 | parser_error::e_syntax, 28677 | parser_.current_token(), 28678 | "ERR133 - Failed parameter type check for function '" + function_name_ + "', " 28679 | "Best match: '" + function_definition_list_[max_diff_index].param_seq + 28680 | "' call set: '" + param_seq + "'", 28681 | exprtk_error_location)); 28682 | } 28683 | 28684 | return false; 28685 | } 28686 | 28687 | std::size_t paramseq_count() const 28688 | { 28689 | return function_definition_list_.size(); 28690 | } 28691 | 28692 | std::string paramseq(const std::size_t& index) const 28693 | { 28694 | return function_definition_list_[index].param_seq; 28695 | } 28696 | 28697 | return_type_t return_type(const std::size_t& index) const 28698 | { 28699 | return function_definition_list_[index].return_type; 28700 | } 28701 | 28702 | bool invalid() const 28703 | { 28704 | return !invalid_state_; 28705 | } 28706 | 28707 | bool allow_zero_parameters() const 28708 | { 28709 | 28710 | for (std::size_t i = 0; i < function_definition_list_.size(); ++i) 28711 | { 28712 | if (std::string::npos != function_definition_list_[i].param_seq.find("Z")) 28713 | { 28714 | return true; 28715 | } 28716 | } 28717 | 28718 | return false; 28719 | } 28720 | 28721 | private: 28722 | 28723 | std::vector<std::string> split_param_seq(const std::string& param_seq, const details::char_t delimiter = '|') const 28724 | { 28725 | std::string::const_iterator current_begin = param_seq.begin(); 28726 | std::string::const_iterator iter = param_seq.begin(); 28727 | 28728 | std::vector<std::string> result; 28729 | 28730 | while (iter != param_seq.end()) 28731 | { 28732 | if (*iter == delimiter) 28733 | { 28734 | result.push_back(std::string(current_begin, iter)); 28735 | current_begin = ++iter; 28736 | } 28737 | else 28738 | ++iter; 28739 | } 28740 | 28741 | if (current_begin != iter) 28742 | { 28743 | result.push_back(std::string(current_begin, iter)); 28744 | } 28745 | 28746 | return result; 28747 | } 28748 | 28749 | inline bool is_valid_token(std::string param_seq, 28750 | function_prototype_t& funcproto) const 28751 | { 28752 | // Determine return type 28753 | funcproto.return_type = default_return_type_; 28754 | 28755 | if (param_seq.size() > 2) 28756 | { 28757 | if (':' == param_seq[1]) 28758 | { 28759 | // Note: Only overloaded igeneric functions can have return 28760 | // type definitions. 28761 | if (type_checker::e_overload != default_return_type_) 28762 | return false; 28763 | 28764 | switch (param_seq[0]) 28765 | { 28766 | case 'T' : funcproto.return_type = type_checker::e_numeric; 28767 | break; 28768 | 28769 | case 'S' : funcproto.return_type = type_checker::e_string; 28770 | break; 28771 | 28772 | default : return false; 28773 | } 28774 | 28775 | param_seq.erase(0,2); 28776 | } 28777 | } 28778 | 28779 | if ( 28780 | (std::string::npos != param_seq.find("?*")) || 28781 | (std::string::npos != param_seq.find("**")) 28782 | ) 28783 | { 28784 | return false; 28785 | } 28786 | else if ( 28787 | (std::string::npos == param_seq.find_first_not_of("STV*?|")) || 28788 | ("Z" == param_seq) 28789 | ) 28790 | { 28791 | funcproto.param_seq = param_seq; 28792 | return true; 28793 | } 28794 | 28795 | return false; 28796 | } 28797 | 28798 | void parse_function_prototypes(const std::string& func_prototypes) 28799 | { 28800 | if (func_prototypes.empty()) 28801 | return; 28802 | 28803 | std::vector<std::string> param_seq_list = split_param_seq(func_prototypes); 28804 | 28805 | typedef std::map<std::string,std::size_t> param_seq_map_t; 28806 | param_seq_map_t param_seq_map; 28807 | 28808 | for (std::size_t i = 0; i < param_seq_list.size(); ++i) 28809 | { 28810 | function_prototype_t func_proto; 28811 | 28812 | if (!is_valid_token(param_seq_list[i], func_proto)) 28813 | { 28814 | invalid_state_ = false; 28815 | 28816 | parser_.set_error(make_error( 28817 | parser_error::e_syntax, 28818 | parser_.current_token(), 28819 | "ERR134 - Invalid parameter sequence of '" + param_seq_list[i] + 28820 | "' for function: " + function_name_, 28821 | exprtk_error_location)); 28822 | return; 28823 | } 28824 | 28825 | param_seq_map_t::const_iterator seq_itr = param_seq_map.find(param_seq_list[i]); 28826 | 28827 | if (param_seq_map.end() != seq_itr) 28828 | { 28829 | invalid_state_ = false; 28830 | 28831 | parser_.set_error(make_error( 28832 | parser_error::e_syntax, 28833 | parser_.current_token(), 28834 | "ERR135 - Function '" + function_name_ + "' has a parameter sequence conflict between " + 28835 | "pseq_idx[" + details::to_str(seq_itr->second) + "] and" + 28836 | "pseq_idx[" + details::to_str(i) + "] " + 28837 | "param seq: " + param_seq_list[i], 28838 | exprtk_error_location)); 28839 | return; 28840 | } 28841 | 28842 | function_definition_list_.push_back(func_proto); 28843 | } 28844 | } 28845 | 28846 | type_checker(const type_checker&) exprtk_delete; 28847 | type_checker& operator=(const type_checker&) exprtk_delete; 28848 | 28849 | bool invalid_state_; 28850 | parser_t& parser_; 28851 | std::string function_name_; 28852 | const return_type_t default_return_type_; 28853 | function_definition_list_t function_definition_list_; 28854 | }; 28855 | 28856 | inline expression_node_ptr parse_generic_function_call(igeneric_function<T>* function, const std::string& function_name) 28857 | { 28858 | std::vector<expression_node_ptr> arg_list; 28859 | 28860 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 28861 | 28862 | next_token(); 28863 | 28864 | std::string param_type_list; 28865 | 28866 | type_checker tc( 28867 | (*this), 28868 | function_name, 28869 | function->parameter_sequence, 28870 | type_checker::e_string); 28871 | 28872 | if (tc.invalid()) 28873 | { 28874 | set_error(make_error( 28875 | parser_error::e_syntax, 28876 | current_token(), 28877 | "ERR136 - Type checker instantiation failure for generic function: " + function_name, 28878 | exprtk_error_location)); 28879 | 28880 | return error_node(); 28881 | } 28882 | 28883 | if (token_is(token_t::e_lbracket)) 28884 | { 28885 | if (token_is(token_t::e_rbracket)) 28886 | { 28887 | if ( 28888 | !function->allow_zero_parameters() && 28889 | !tc .allow_zero_parameters() 28890 | ) 28891 | { 28892 | set_error(make_error( 28893 | parser_error::e_syntax, 28894 | current_token(), 28895 | "ERR137 - Zero parameter call to generic function: " 28896 | + function_name + " not allowed", 28897 | exprtk_error_location)); 28898 | 28899 | return error_node(); 28900 | } 28901 | } 28902 | else 28903 | { 28904 | for ( ; ; ) 28905 | { 28906 | expression_node_ptr arg = parse_expression(); 28907 | 28908 | if (0 == arg) 28909 | return error_node(); 28910 | 28911 | if (is_ivector_node(arg)) 28912 | param_type_list += 'V'; 28913 | else if (is_generally_string_node(arg)) 28914 | param_type_list += 'S'; 28915 | else // Everything else is assumed to be a scalar returning expression 28916 | param_type_list += 'T'; 28917 | 28918 | arg_list.push_back(arg); 28919 | 28920 | if (token_is(token_t::e_rbracket)) 28921 | break; 28922 | else if (!token_is(token_t::e_comma)) 28923 | { 28924 | set_error(make_error( 28925 | parser_error::e_syntax, 28926 | current_token(), 28927 | "ERR138 - Expected ',' for call to generic function: " + function_name, 28928 | exprtk_error_location)); 28929 | 28930 | return error_node(); 28931 | } 28932 | } 28933 | } 28934 | } 28935 | else if ( 28936 | !function->parameter_sequence.empty() && 28937 | function->allow_zero_parameters () && 28938 | !tc .allow_zero_parameters () 28939 | ) 28940 | { 28941 | set_error(make_error( 28942 | parser_error::e_syntax, 28943 | current_token(), 28944 | "ERR139 - Zero parameter call to generic function: " 28945 | + function_name + " not allowed", 28946 | exprtk_error_location)); 28947 | 28948 | return error_node(); 28949 | } 28950 | 28951 | std::size_t param_seq_index = 0; 28952 | 28953 | if ( 28954 | state_.type_check_enabled && 28955 | !tc.verify(param_type_list, param_seq_index) 28956 | ) 28957 | { 28958 | set_error(make_error( 28959 | parser_error::e_syntax, 28960 | current_token(), 28961 | "ERR140 - Invalid input parameter sequence for call to generic function: " + function_name, 28962 | exprtk_error_location)); 28963 | 28964 | return error_node(); 28965 | } 28966 | 28967 | expression_node_ptr result = 28968 | (tc.paramseq_count() <= 1) ? 28969 | expression_generator_ 28970 | .generic_function_call(function, arg_list) : 28971 | expression_generator_ 28972 | .generic_function_call(function, arg_list, param_seq_index); 28973 | 28974 | svd.delete_ptr = (0 == result); 28975 | 28976 | return result; 28977 | } 28978 | 28979 | inline bool parse_igeneric_function_params(std::string& param_type_list, 28980 | std::vector<expression_node_ptr>& arg_list, 28981 | const std::string& function_name, 28982 | igeneric_function<T>* function, 28983 | const type_checker& tc) 28984 | { 28985 | if (token_is(token_t::e_lbracket)) 28986 | { 28987 | if (token_is(token_t::e_rbracket)) 28988 | { 28989 | if ( 28990 | !function->allow_zero_parameters() && 28991 | !tc .allow_zero_parameters() 28992 | ) 28993 | { 28994 | set_error(make_error( 28995 | parser_error::e_syntax, 28996 | current_token(), 28997 | "ERR141 - Zero parameter call to generic function: " 28998 | + function_name + " not allowed", 28999 | exprtk_error_location)); 29000 | 29001 | return false; 29002 | } 29003 | } 29004 | else 29005 | { 29006 | for ( ; ; ) 29007 | { 29008 | expression_node_ptr arg = parse_expression(); 29009 | 29010 | if (0 == arg) 29011 | return false; 29012 | 29013 | if (is_ivector_node(arg)) 29014 | param_type_list += 'V'; 29015 | else if (is_generally_string_node(arg)) 29016 | param_type_list += 'S'; 29017 | else // Everything else is a scalar returning expression 29018 | param_type_list += 'T'; 29019 | 29020 | arg_list.push_back(arg); 29021 | 29022 | if (token_is(token_t::e_rbracket)) 29023 | break; 29024 | else if (!token_is(token_t::e_comma)) 29025 | { 29026 | set_error(make_error( 29027 | parser_error::e_syntax, 29028 | current_token(), 29029 | "ERR142 - Expected ',' for call to string function: " + function_name, 29030 | exprtk_error_location)); 29031 | 29032 | return false; 29033 | } 29034 | } 29035 | } 29036 | 29037 | return true; 29038 | } 29039 | else 29040 | return false; 29041 | } 29042 | 29043 | #ifndef exprtk_disable_string_capabilities 29044 | inline expression_node_ptr parse_string_function_call(igeneric_function<T>* function, const std::string& function_name) 29045 | { 29046 | // Move pass the function name 29047 | next_token(); 29048 | 29049 | std::string param_type_list; 29050 | 29051 | type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_string); 29052 | 29053 | if ( 29054 | (!function->parameter_sequence.empty()) && 29055 | (0 == tc.paramseq_count()) 29056 | ) 29057 | { 29058 | return error_node(); 29059 | } 29060 | 29061 | std::vector<expression_node_ptr> arg_list; 29062 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 29063 | 29064 | if (!parse_igeneric_function_params(param_type_list, arg_list, function_name, function, tc)) 29065 | { 29066 | return error_node(); 29067 | } 29068 | 29069 | std::size_t param_seq_index = 0; 29070 | 29071 | if (!tc.verify(param_type_list, param_seq_index)) 29072 | { 29073 | set_error(make_error( 29074 | parser_error::e_syntax, 29075 | current_token(), 29076 | "ERR143 - Invalid input parameter sequence for call to string function: " + function_name, 29077 | exprtk_error_location)); 29078 | 29079 | return error_node(); 29080 | } 29081 | 29082 | expression_node_ptr result = 29083 | (tc.paramseq_count() <= 1) ? 29084 | expression_generator_ 29085 | .string_function_call(function, arg_list) : 29086 | expression_generator_ 29087 | .string_function_call(function, arg_list, param_seq_index); 29088 | 29089 | svd.delete_ptr = (0 == result); 29090 | 29091 | return result; 29092 | } 29093 | 29094 | inline expression_node_ptr parse_overload_function_call(igeneric_function<T>* function, const std::string& function_name) 29095 | { 29096 | // Move pass the function name 29097 | next_token(); 29098 | 29099 | std::string param_type_list; 29100 | 29101 | type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_overload); 29102 | 29103 | if ( 29104 | (!function->parameter_sequence.empty()) && 29105 | (0 == tc.paramseq_count()) 29106 | ) 29107 | { 29108 | return error_node(); 29109 | } 29110 | 29111 | std::vector<expression_node_ptr> arg_list; 29112 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 29113 | 29114 | if (!parse_igeneric_function_params(param_type_list, arg_list, function_name, function, tc)) 29115 | { 29116 | return error_node(); 29117 | } 29118 | 29119 | std::size_t param_seq_index = 0; 29120 | 29121 | if (!tc.verify(param_type_list, param_seq_index)) 29122 | { 29123 | set_error(make_error( 29124 | parser_error::e_syntax, 29125 | current_token(), 29126 | "ERR144 - Invalid input parameter sequence for call to overloaded function: " + function_name, 29127 | exprtk_error_location)); 29128 | 29129 | return error_node(); 29130 | } 29131 | 29132 | expression_node_ptr result = error_node(); 29133 | 29134 | if (type_checker::e_numeric == tc.return_type(param_seq_index)) 29135 | { 29136 | if (tc.paramseq_count() <= 1) 29137 | result = expression_generator_ 29138 | .generic_function_call(function, arg_list); 29139 | else 29140 | result = expression_generator_ 29141 | .generic_function_call(function, arg_list, param_seq_index); 29142 | } 29143 | else if (type_checker::e_string == tc.return_type(param_seq_index)) 29144 | { 29145 | if (tc.paramseq_count() <= 1) 29146 | result = expression_generator_ 29147 | .string_function_call(function, arg_list); 29148 | else 29149 | result = expression_generator_ 29150 | .string_function_call(function, arg_list, param_seq_index); 29151 | } 29152 | else 29153 | { 29154 | set_error(make_error( 29155 | parser_error::e_syntax, 29156 | current_token(), 29157 | "ERR145 - Invalid return type for call to overloaded function: " + function_name, 29158 | exprtk_error_location)); 29159 | } 29160 | 29161 | svd.delete_ptr = (0 == result); 29162 | return result; 29163 | } 29164 | #endif 29165 | 29166 | template <typename Type, std::size_t NumberOfParameters> 29167 | struct parse_special_function_impl 29168 | { 29169 | static inline expression_node_ptr process(parser<Type>& p, const details::operator_type opt_type, const std::string& sf_name) 29170 | { 29171 | expression_node_ptr branch[NumberOfParameters]; 29172 | expression_node_ptr result = error_node(); 29173 | 29174 | std::fill_n(branch, NumberOfParameters, reinterpret_cast<expression_node_ptr>(0)); 29175 | 29176 | scoped_delete<expression_node_t,NumberOfParameters> sd(p,branch); 29177 | 29178 | p.next_token(); 29179 | 29180 | if (!p.token_is(token_t::e_lbracket)) 29181 | { 29182 | p.set_error(make_error( 29183 | parser_error::e_syntax, 29184 | p.current_token(), 29185 | "ERR146 - Expected '(' for special function '" + sf_name + "'", 29186 | exprtk_error_location)); 29187 | 29188 | return error_node(); 29189 | } 29190 | 29191 | for (std::size_t i = 0; i < NumberOfParameters; ++i) 29192 | { 29193 | branch[i] = p.parse_expression(); 29194 | 29195 | if (0 == branch[i]) 29196 | { 29197 | return p.error_node(); 29198 | } 29199 | else if (i < (NumberOfParameters - 1)) 29200 | { 29201 | if (!p.token_is(token_t::e_comma)) 29202 | { 29203 | p.set_error(make_error( 29204 | parser_error::e_syntax, 29205 | p.current_token(), 29206 | "ERR147 - Expected ',' before next parameter of special function '" + sf_name + "'", 29207 | exprtk_error_location)); 29208 | 29209 | return p.error_node(); 29210 | } 29211 | } 29212 | } 29213 | 29214 | if (!p.token_is(token_t::e_rbracket)) 29215 | { 29216 | p.set_error(make_error( 29217 | parser_error::e_syntax, 29218 | p.current_token(), 29219 | "ERR148 - Invalid number of parameters for special function '" + sf_name + "'", 29220 | exprtk_error_location)); 29221 | 29222 | return p.error_node(); 29223 | } 29224 | else 29225 | result = p.expression_generator_.special_function(opt_type,branch); 29226 | 29227 | sd.delete_ptr = (0 == result); 29228 | 29229 | return result; 29230 | } 29231 | }; 29232 | 29233 | inline expression_node_ptr parse_special_function() 29234 | { 29235 | const std::string sf_name = current_token().value; 29236 | 29237 | // Expect: $fDD(expr0,expr1,expr2) or $fDD(expr0,expr1,expr2,expr3) 29238 | if ( 29239 | !details::is_digit(sf_name[2]) || 29240 | !details::is_digit(sf_name[3]) 29241 | ) 29242 | { 29243 | set_error(make_error( 29244 | parser_error::e_token, 29245 | current_token(), 29246 | "ERR149 - Invalid special function[1]: " + sf_name, 29247 | exprtk_error_location)); 29248 | 29249 | return error_node(); 29250 | } 29251 | 29252 | const int id = (sf_name[2] - '0') * 10 + 29253 | (sf_name[3] - '0'); 29254 | 29255 | if (id >= details::e_sffinal) 29256 | { 29257 | set_error(make_error( 29258 | parser_error::e_token, 29259 | current_token(), 29260 | "ERR150 - Invalid special function[2]: " + sf_name, 29261 | exprtk_error_location)); 29262 | 29263 | return error_node(); 29264 | } 29265 | 29266 | const int sf_3_to_4 = details::e_sf48; 29267 | const details::operator_type opt_type = details::operator_type(id + 1000); 29268 | const std::size_t NumberOfParameters = (id < (sf_3_to_4 - 1000)) ? 3U : 4U; 29269 | 29270 | switch (NumberOfParameters) 29271 | { 29272 | case 3 : return parse_special_function_impl<T,3>::process((*this), opt_type, sf_name); 29273 | case 4 : return parse_special_function_impl<T,4>::process((*this), opt_type, sf_name); 29274 | default : return error_node(); 29275 | } 29276 | } 29277 | 29278 | inline expression_node_ptr parse_null_statement() 29279 | { 29280 | next_token(); 29281 | return node_allocator_.allocate<details::null_node<T> >(); 29282 | } 29283 | 29284 | #ifndef exprtk_disable_break_continue 29285 | inline expression_node_ptr parse_break_statement() 29286 | { 29287 | if (state_.parsing_break_stmt) 29288 | { 29289 | set_error(make_error( 29290 | parser_error::e_syntax, 29291 | current_token(), 29292 | "ERR151 - Invoking 'break' within a break call is not allowed", 29293 | exprtk_error_location)); 29294 | 29295 | return error_node(); 29296 | } 29297 | else if (0 == state_.parsing_loop_stmt_count) 29298 | { 29299 | set_error(make_error( 29300 | parser_error::e_syntax, 29301 | current_token(), 29302 | "ERR152 - Invalid use of 'break', allowed only in the scope of a loop", 29303 | exprtk_error_location)); 29304 | 29305 | return error_node(); 29306 | } 29307 | 29308 | scoped_bool_negator sbn(state_.parsing_break_stmt); 29309 | 29310 | if (!brkcnt_list_.empty()) 29311 | { 29312 | next_token(); 29313 | 29314 | brkcnt_list_.front() = true; 29315 | 29316 | expression_node_ptr return_expr = error_node(); 29317 | 29318 | if (token_is(token_t::e_lsqrbracket)) 29319 | { 29320 | if (0 == (return_expr = parse_expression())) 29321 | { 29322 | set_error(make_error( 29323 | parser_error::e_syntax, 29324 | current_token(), 29325 | "ERR153 - Failed to parse return expression for 'break' statement", 29326 | exprtk_error_location)); 29327 | 29328 | return error_node(); 29329 | } 29330 | else if (!token_is(token_t::e_rsqrbracket)) 29331 | { 29332 | set_error(make_error( 29333 | parser_error::e_syntax, 29334 | current_token(), 29335 | "ERR154 - Expected ']' at the completion of break's return expression", 29336 | exprtk_error_location)); 29337 | 29338 | free_node(node_allocator_, return_expr); 29339 | 29340 | return error_node(); 29341 | } 29342 | } 29343 | 29344 | state_.activate_side_effect("parse_break_statement()"); 29345 | 29346 | return node_allocator_.allocate<details::break_node<T> >(return_expr); 29347 | } 29348 | else 29349 | { 29350 | set_error(make_error( 29351 | parser_error::e_syntax, 29352 | current_token(), 29353 | "ERR155 - Invalid use of 'break', allowed only in the scope of a loop", 29354 | exprtk_error_location)); 29355 | } 29356 | 29357 | return error_node(); 29358 | } 29359 | 29360 | inline expression_node_ptr parse_continue_statement() 29361 | { 29362 | if (0 == state_.parsing_loop_stmt_count) 29363 | { 29364 | set_error(make_error( 29365 | parser_error::e_syntax, 29366 | current_token(), 29367 | "ERR156 - Invalid use of 'continue', allowed only in the scope of a loop", 29368 | exprtk_error_location)); 29369 | 29370 | return error_node(); 29371 | } 29372 | else 29373 | { 29374 | next_token(); 29375 | 29376 | brkcnt_list_.front() = true; 29377 | state_.activate_side_effect("parse_continue_statement()"); 29378 | 29379 | return node_allocator_.allocate<details::continue_node<T> >(); 29380 | } 29381 | } 29382 | #endif 29383 | 29384 | inline expression_node_ptr parse_define_vector_statement(const std::string& vec_name) 29385 | { 29386 | expression_node_ptr size_expression_node = error_node(); 29387 | 29388 | if (!token_is(token_t::e_lsqrbracket)) 29389 | { 29390 | set_error(make_error( 29391 | parser_error::e_syntax, 29392 | current_token(), 29393 | "ERR157 - Expected '[' as part of vector size definition", 29394 | exprtk_error_location)); 29395 | 29396 | return error_node(); 29397 | } 29398 | else if (0 == (size_expression_node = parse_expression())) 29399 | { 29400 | set_error(make_error( 29401 | parser_error::e_syntax, 29402 | current_token(), 29403 | "ERR158 - Failed to determine size of vector '" + vec_name + "'", 29404 | exprtk_error_location)); 29405 | 29406 | return error_node(); 29407 | } 29408 | else if (!is_constant_node(size_expression_node)) 29409 | { 29410 | const bool is_rebaseble_vector = 29411 | (size_expression_node->type() == details::expression_node<T>::e_vecsize) && 29412 | static_cast<details::vector_size_node<T>*>(size_expression_node)->vec_holder()->rebaseable(); 29413 | 29414 | free_node(node_allocator_, size_expression_node); 29415 | 29416 | const std::string error_msg = (is_rebaseble_vector) ? 29417 | std::string("Rebasable/Resizable vector cannot be used to define the size of vector") : 29418 | std::string("Expected a constant literal number as size of vector"); 29419 | set_error(make_error( 29420 | parser_error::e_syntax, 29421 | current_token(), 29422 | "ERR159 - " + error_msg + " '" + vec_name + "'", 29423 | exprtk_error_location)); 29424 | 29425 | return error_node(); 29426 | } 29427 | 29428 | const T vector_size = size_expression_node->value(); 29429 | 29430 | free_node(node_allocator_, size_expression_node); 29431 | 29432 | const std::size_t max_vector_size = settings_.max_local_vector_size(); 29433 | 29434 | if ( 29435 | (vector_size <= T(0)) || 29436 | std::not_equal_to<T>() 29437 | (T(0),vector_size - details::numeric::trunc(vector_size)) || 29438 | (static_cast<std::size_t>(vector_size) > max_vector_size) 29439 | ) 29440 | { 29441 | set_error(make_error( 29442 | parser_error::e_syntax, 29443 | current_token(), 29444 | "ERR160 - Invalid vector size. Must be an integer in the " 29445 | "range [0," + details::to_str(static_cast<std::size_t>(max_vector_size)) + "], size: " + 29446 | details::to_str(details::numeric::to_int32(vector_size)), 29447 | exprtk_error_location)); 29448 | 29449 | return error_node(); 29450 | } 29451 | 29452 | typename symbol_table_t::vector_holder_ptr vec_holder = typename symbol_table_t::vector_holder_ptr(0); 29453 | 29454 | const std::size_t vec_size = static_cast<std::size_t>(details::numeric::to_int32(vector_size)); 29455 | const std::size_t predicted_total_lclsymb_size = sizeof(T) * vec_size + sem_.total_local_symb_size_bytes(); 29456 | 29457 | if (predicted_total_lclsymb_size > settings().max_total_local_symbol_size_bytes()) 29458 | { 29459 | set_error(make_error( 29460 | parser_error::e_syntax, 29461 | current_token(), 29462 | "ERR161 - Adding vector '" + vec_name + "' of size " + details::to_str(vec_size) + " bytes " 29463 | "will exceed max total local symbol size of: " + details::to_str(settings().max_total_local_symbol_size_bytes()) + " bytes, " 29464 | "current total size: " + details::to_str(sem_.total_local_symb_size_bytes()) + " bytes", 29465 | exprtk_error_location)); 29466 | 29467 | return error_node(); 29468 | } 29469 | 29470 | scope_element& se = sem_.get_element(vec_name); 29471 | 29472 | if (se.name == vec_name) 29473 | { 29474 | if (se.active) 29475 | { 29476 | set_error(make_error( 29477 | parser_error::e_syntax, 29478 | current_token(), 29479 | "ERR162 - Illegal redefinition of local vector: '" + vec_name + "'", 29480 | exprtk_error_location)); 29481 | 29482 | return error_node(); 29483 | } 29484 | else if ( 29485 | (se.size == vec_size) && 29486 | (scope_element::e_vector == se.type) 29487 | ) 29488 | { 29489 | vec_holder = se.vec_node; 29490 | se.active = true; 29491 | se.depth = state_.scope_depth; 29492 | se.ref_count++; 29493 | } 29494 | } 29495 | 29496 | if (0 == vec_holder) 29497 | { 29498 | scope_element nse; 29499 | nse.name = vec_name; 29500 | nse.active = true; 29501 | nse.ref_count = 1; 29502 | nse.type = scope_element::e_vector; 29503 | nse.depth = state_.scope_depth; 29504 | nse.size = vec_size; 29505 | nse.data = new T[vec_size]; 29506 | nse.vec_node = new typename scope_element::vector_holder_t(reinterpret_cast<T*>(nse.data),nse.size); 29507 | 29508 | details::set_zero_value(reinterpret_cast<T*>(nse.data),vec_size); 29509 | 29510 | if (!sem_.add_element(nse)) 29511 | { 29512 | set_error(make_error( 29513 | parser_error::e_syntax, 29514 | current_token(), 29515 | "ERR163 - Failed to add new local vector '" + vec_name + "' to SEM", 29516 | exprtk_error_location)); 29517 | 29518 | sem_.free_element(nse); 29519 | 29520 | return error_node(); 29521 | } 29522 | 29523 | assert(sem_.total_local_symb_size_bytes() <= settings().max_total_local_symbol_size_bytes()); 29524 | 29525 | vec_holder = nse.vec_node; 29526 | 29527 | exprtk_debug(("parse_define_vector_statement() - INFO - Added new local vector: %s[%d]\n", 29528 | nse.name.c_str(), 29529 | static_cast<int>(nse.size))); 29530 | } 29531 | 29532 | state_.activate_side_effect("parse_define_vector_statement()"); 29533 | 29534 | lodge_symbol(vec_name, e_st_local_vector); 29535 | 29536 | std::vector<expression_node_ptr> vec_initilizer_list; 29537 | 29538 | scoped_vec_delete<expression_node_t> svd((*this), vec_initilizer_list); 29539 | 29540 | bool single_value_initialiser = false; 29541 | bool range_value_initialiser = false; 29542 | bool vec_to_vec_initialiser = false; 29543 | bool null_initialisation = false; 29544 | 29545 | if (!token_is(token_t::e_rsqrbracket)) 29546 | { 29547 | set_error(make_error( 29548 | parser_error::e_syntax, 29549 | current_token(), 29550 | "ERR164 - Expected ']' as part of vector size definition", 29551 | exprtk_error_location)); 29552 | 29553 | return error_node(); 29554 | } 29555 | else if (!token_is(token_t::e_eof, prsrhlpr_t::e_hold)) 29556 | { 29557 | if (!token_is(token_t::e_assign)) 29558 | { 29559 | set_error(make_error( 29560 | parser_error::e_syntax, 29561 | current_token(), 29562 | "ERR165 - Expected ':=' as part of vector definition", 29563 | exprtk_error_location)); 29564 | 29565 | return error_node(); 29566 | } 29567 | else if (token_is(token_t::e_lsqrbracket)) 29568 | { 29569 | expression_node_ptr initialiser_component = parse_expression(); 29570 | 29571 | if (0 == initialiser_component) 29572 | { 29573 | set_error(make_error( 29574 | parser_error::e_syntax, 29575 | current_token(), 29576 | "ERR166 - Failed to parse first component of vector initialiser for vector: " + vec_name, 29577 | exprtk_error_location)); 29578 | 29579 | return error_node(); 29580 | } 29581 | 29582 | vec_initilizer_list.push_back(initialiser_component); 29583 | 29584 | if (token_is(token_t::e_colon)) 29585 | { 29586 | initialiser_component = parse_expression(); 29587 | 29588 | if (0 == initialiser_component) 29589 | { 29590 | set_error(make_error( 29591 | parser_error::e_syntax, 29592 | current_token(), 29593 | "ERR167 - Failed to parse second component of vector initialiser for vector: " + vec_name, 29594 | exprtk_error_location)); 29595 | 29596 | return error_node(); 29597 | } 29598 | 29599 | vec_initilizer_list.push_back(initialiser_component); 29600 | } 29601 | 29602 | if (!token_is(token_t::e_rsqrbracket)) 29603 | { 29604 | set_error(make_error( 29605 | parser_error::e_syntax, 29606 | current_token(), 29607 | "ERR168 - Expected ']' to close single value vector initialiser", 29608 | exprtk_error_location)); 29609 | 29610 | return error_node(); 29611 | } 29612 | 29613 | switch (vec_initilizer_list.size()) 29614 | { 29615 | case 1 : single_value_initialiser = true; break; 29616 | case 2 : range_value_initialiser = true; break; 29617 | } 29618 | } 29619 | else if (!token_is(token_t::e_lcrlbracket)) 29620 | { 29621 | expression_node_ptr initialiser = error_node(); 29622 | 29623 | // Is this a vector to vector assignment and initialisation? 29624 | if (token_t::e_symbol == current_token().type) 29625 | { 29626 | // Is it a locally defined vector? 29627 | const scope_element& lcl_se = sem_.get_active_element(current_token().value); 29628 | 29629 | if (scope_element::e_vector == lcl_se.type) 29630 | { 29631 | if (0 != (initialiser = parse_expression())) 29632 | vec_initilizer_list.push_back(initialiser); 29633 | else 29634 | return error_node(); 29635 | } 29636 | // Are we dealing with a user defined vector? 29637 | else if (symtab_store_.is_vector(current_token().value)) 29638 | { 29639 | lodge_symbol(current_token().value, e_st_vector); 29640 | 29641 | if (0 != (initialiser = parse_expression())) 29642 | vec_initilizer_list.push_back(initialiser); 29643 | else 29644 | return error_node(); 29645 | } 29646 | // Are we dealing with a null initialisation vector definition? 29647 | else if (token_is(token_t::e_symbol,"null")) 29648 | null_initialisation = true; 29649 | } 29650 | 29651 | if (!null_initialisation) 29652 | { 29653 | if (0 == initialiser) 29654 | { 29655 | set_error(make_error( 29656 | parser_error::e_syntax, 29657 | current_token(), 29658 | "ERR169 - Expected '{' as part of vector initialiser list", 29659 | exprtk_error_location)); 29660 | 29661 | return error_node(); 29662 | } 29663 | else 29664 | vec_to_vec_initialiser = true; 29665 | } 29666 | } 29667 | else if (!token_is(token_t::e_rcrlbracket)) 29668 | { 29669 | for ( ; ; ) 29670 | { 29671 | expression_node_ptr initialiser = parse_expression(); 29672 | 29673 | if (0 == initialiser) 29674 | { 29675 | set_error(make_error( 29676 | parser_error::e_syntax, 29677 | current_token(), 29678 | "ERR170 - Expected '{' as part of vector initialiser list", 29679 | exprtk_error_location)); 29680 | 29681 | return error_node(); 29682 | } 29683 | else 29684 | vec_initilizer_list.push_back(initialiser); 29685 | 29686 | if (token_is(token_t::e_rcrlbracket)) 29687 | break; 29688 | 29689 | const bool is_next_close = peek_token_is(token_t::e_rcrlbracket); 29690 | 29691 | if (!token_is(token_t::e_comma) && is_next_close) 29692 | { 29693 | set_error(make_error( 29694 | parser_error::e_syntax, 29695 | current_token(), 29696 | "ERR171 - Expected ',' between vector initialisers", 29697 | exprtk_error_location)); 29698 | 29699 | return error_node(); 29700 | } 29701 | 29702 | if (token_is(token_t::e_rcrlbracket)) 29703 | break; 29704 | } 29705 | } 29706 | 29707 | if ( 29708 | !token_is(token_t::e_rbracket , prsrhlpr_t::e_hold) && 29709 | !token_is(token_t::e_rcrlbracket, prsrhlpr_t::e_hold) && 29710 | !token_is(token_t::e_rsqrbracket, prsrhlpr_t::e_hold) 29711 | ) 29712 | { 29713 | if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold)) 29714 | { 29715 | set_error(make_error( 29716 | parser_error::e_syntax, 29717 | current_token(), 29718 | "ERR172 - Expected ';' at end of vector definition", 29719 | exprtk_error_location)); 29720 | 29721 | return error_node(); 29722 | } 29723 | } 29724 | 29725 | if ( 29726 | !single_value_initialiser && 29727 | !range_value_initialiser && 29728 | (T(vec_initilizer_list.size()) > vector_size) 29729 | ) 29730 | { 29731 | set_error(make_error( 29732 | parser_error::e_syntax, 29733 | current_token(), 29734 | "ERR173 - Initialiser list larger than the number of elements in the vector: '" + vec_name + "'", 29735 | exprtk_error_location)); 29736 | 29737 | return error_node(); 29738 | } 29739 | } 29740 | 29741 | expression_node_ptr result = error_node(); 29742 | 29743 | if ( 29744 | (vec_initilizer_list.size() == 1) && 29745 | single_value_initialiser 29746 | ) 29747 | { 29748 | if (details::is_constant_node(vec_initilizer_list[0])) 29749 | { 29750 | // vector_init_zero_value_node var v[10] := [0] 29751 | if (T(0) == vec_initilizer_list[0]->value()) 29752 | { 29753 | result = node_allocator_ 29754 | .allocate<details::vector_init_zero_value_node<T> >( 29755 | (*vec_holder)[0], 29756 | vec_size, 29757 | vec_initilizer_list); 29758 | } 29759 | else 29760 | { 29761 | // vector_init_single_constvalue_node var v[10] := [123] 29762 | result = node_allocator_ 29763 | .allocate<details::vector_init_single_constvalue_node<T> >( 29764 | (*vec_holder)[0], 29765 | vec_size, 29766 | vec_initilizer_list); 29767 | } 29768 | } 29769 | else 29770 | { 29771 | // vector_init_single_value_node var v[10] := [123 + (x / y)] 29772 | result = node_allocator_ 29773 | .allocate<details::vector_init_single_value_node<T> >( 29774 | (*vec_holder)[0], 29775 | vec_size, 29776 | vec_initilizer_list); 29777 | } 29778 | } 29779 | else if ( 29780 | (vec_initilizer_list.size() == 2) && 29781 | range_value_initialiser 29782 | ) 29783 | { 29784 | bool base_const = details::is_constant_node(vec_initilizer_list[0]); 29785 | bool inc_const = details::is_constant_node(vec_initilizer_list[1]); 29786 | 29787 | if (base_const && inc_const) 29788 | { 29789 | // vector_init_single_value_node var v[10] := [1 : 3.5] 29790 | result = node_allocator_ 29791 | .allocate<details::vector_init_iota_constconst_node<T> >( 29792 | (*vec_holder)[0], 29793 | vec_size, 29794 | vec_initilizer_list); 29795 | } 29796 | else if (base_const && !inc_const) 29797 | { 29798 | // vector_init_single_value_node var v[10] := [1 : x + y] 29799 | result = node_allocator_ 29800 | .allocate<details::vector_init_iota_constnconst_node<T> >( 29801 | (*vec_holder)[0], 29802 | vec_size, 29803 | vec_initilizer_list); 29804 | } 29805 | else if (!base_const && inc_const) 29806 | { 29807 | // vector_init_single_value_node var v[10] := [x + y : 3] 29808 | result = node_allocator_ 29809 | .allocate<details::vector_init_iota_nconstconst_node<T> >( 29810 | (*vec_holder)[0], 29811 | vec_size, 29812 | vec_initilizer_list); 29813 | } 29814 | else if (!base_const && !inc_const) 29815 | { 29816 | // vector_init_single_value_node var v[10] := [x + y : z / w] 29817 | result = node_allocator_ 29818 | .allocate<details::vector_init_iota_nconstnconst_node<T> >( 29819 | (*vec_holder)[0], 29820 | vec_size, 29821 | vec_initilizer_list); 29822 | } 29823 | } 29824 | else if (null_initialisation) 29825 | result = expression_generator_(T(0.0)); 29826 | else if (vec_to_vec_initialiser) 29827 | { 29828 | expression_node_ptr vec_node = node_allocator_.allocate<vector_node_t>(vec_holder); 29829 | 29830 | result = expression_generator_( 29831 | details::e_assign, 29832 | vec_node, 29833 | vec_initilizer_list[0]); 29834 | } 29835 | else 29836 | { 29837 | result = node_allocator_ 29838 | .allocate<details::vector_initialisation_node<T> >( 29839 | (*vec_holder)[0], 29840 | vec_size, 29841 | vec_initilizer_list, 29842 | single_value_initialiser); 29843 | } 29844 | 29845 | svd.delete_ptr = false; 29846 | 29847 | if (result && result->valid()) 29848 | { 29849 | return result; 29850 | } 29851 | 29852 | details::free_node(node_allocator_, result); 29853 | 29854 | set_error(make_error( 29855 | parser_error::e_synthesis, 29856 | current_token(), 29857 | "ERR174 - Failed to generate initialisation node for vector: " + vec_name, 29858 | exprtk_error_location)); 29859 | 29860 | return error_node(); 29861 | } 29862 | 29863 | #ifndef exprtk_disable_string_capabilities 29864 | inline expression_node_ptr parse_define_string_statement(const std::string& str_name, expression_node_ptr initialisation_expression) 29865 | { 29866 | stringvar_node_t* str_node = reinterpret_cast<stringvar_node_t*>(0); 29867 | 29868 | scope_element& se = sem_.get_element(str_name); 29869 | 29870 | if (se.name == str_name) 29871 | { 29872 | if (se.active) 29873 | { 29874 | set_error(make_error( 29875 | parser_error::e_syntax, 29876 | current_token(), 29877 | "ERR175 - Illegal redefinition of local variable: '" + str_name + "'", 29878 | exprtk_error_location)); 29879 | 29880 | free_node(node_allocator_, initialisation_expression); 29881 | 29882 | return error_node(); 29883 | } 29884 | else if (scope_element::e_string == se.type) 29885 | { 29886 | str_node = se.str_node; 29887 | se.active = true; 29888 | se.depth = state_.scope_depth; 29889 | se.ref_count++; 29890 | } 29891 | } 29892 | 29893 | if (0 == str_node) 29894 | { 29895 | scope_element nse; 29896 | nse.name = str_name; 29897 | nse.active = true; 29898 | nse.ref_count = 1; 29899 | nse.type = scope_element::e_string; 29900 | nse.depth = state_.scope_depth; 29901 | nse.data = new std::string; 29902 | nse.str_node = new stringvar_node_t(*reinterpret_cast<std::string*>(nse.data)); 29903 | 29904 | if (!sem_.add_element(nse)) 29905 | { 29906 | set_error(make_error( 29907 | parser_error::e_syntax, 29908 | current_token(), 29909 | "ERR176 - Failed to add new local string variable '" + str_name + "' to SEM", 29910 | exprtk_error_location)); 29911 | 29912 | free_node(node_allocator_, initialisation_expression); 29913 | 29914 | sem_.free_element(nse); 29915 | 29916 | return error_node(); 29917 | } 29918 | 29919 | assert(sem_.total_local_symb_size_bytes() <= settings().max_total_local_symbol_size_bytes()); 29920 | 29921 | str_node = nse.str_node; 29922 | 29923 | exprtk_debug(("parse_define_string_statement() - INFO - Added new local string variable: %s\n", nse.name.c_str())); 29924 | } 29925 | 29926 | lodge_symbol(str_name, e_st_local_string); 29927 | 29928 | state_.activate_side_effect("parse_define_string_statement()"); 29929 | 29930 | expression_node_ptr branch[2] = {0}; 29931 | 29932 | branch[0] = str_node; 29933 | branch[1] = initialisation_expression; 29934 | 29935 | return expression_generator_(details::e_assign,branch); 29936 | } 29937 | #else 29938 | inline expression_node_ptr parse_define_string_statement(const std::string&, expression_node_ptr) 29939 | { 29940 | return error_node(); 29941 | } 29942 | #endif 29943 | 29944 | inline bool local_variable_is_shadowed(const std::string& symbol) 29945 | { 29946 | const scope_element& se = sem_.get_element(symbol); 29947 | return (se.name == symbol) && se.active; 29948 | } 29949 | 29950 | inline expression_node_ptr parse_define_var_statement() 29951 | { 29952 | if (settings_.vardef_disabled()) 29953 | { 29954 | set_error(make_error( 29955 | parser_error::e_syntax, 29956 | current_token(), 29957 | "ERR177 - Illegal variable definition", 29958 | exprtk_error_location)); 29959 | 29960 | return error_node(); 29961 | } 29962 | else if (!details::imatch(current_token().value,"var")) 29963 | { 29964 | return error_node(); 29965 | } 29966 | else 29967 | next_token(); 29968 | 29969 | const std::string var_name = current_token().value; 29970 | 29971 | expression_node_ptr initialisation_expression = error_node(); 29972 | 29973 | if (!token_is(token_t::e_symbol)) 29974 | { 29975 | set_error(make_error( 29976 | parser_error::e_syntax, 29977 | current_token(), 29978 | "ERR178 - Expected a symbol for variable definition", 29979 | exprtk_error_location)); 29980 | 29981 | return error_node(); 29982 | } 29983 | else if (details::is_reserved_symbol(var_name)) 29984 | { 29985 | set_error(make_error( 29986 | parser_error::e_syntax, 29987 | current_token(), 29988 | "ERR179 - Illegal redefinition of reserved keyword: '" + var_name + "'", 29989 | exprtk_error_location)); 29990 | 29991 | return error_node(); 29992 | } 29993 | else if (symtab_store_.symbol_exists(var_name)) 29994 | { 29995 | set_error(make_error( 29996 | parser_error::e_syntax, 29997 | current_token(), 29998 | "ERR180 - Illegal redefinition of variable '" + var_name + "'", 29999 | exprtk_error_location)); 30000 | 30001 | return error_node(); 30002 | } 30003 | else if (local_variable_is_shadowed(var_name)) 30004 | { 30005 | set_error(make_error( 30006 | parser_error::e_syntax, 30007 | current_token(), 30008 | "ERR181 - Illegal redefinition of local variable: '" + var_name + "'", 30009 | exprtk_error_location)); 30010 | 30011 | return error_node(); 30012 | } 30013 | else if (token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold)) 30014 | { 30015 | return parse_define_vector_statement(var_name); 30016 | } 30017 | else if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) 30018 | { 30019 | return parse_uninitialised_var_statement(var_name); 30020 | } 30021 | else if (token_is(token_t::e_assign)) 30022 | { 30023 | if (0 == (initialisation_expression = parse_expression())) 30024 | { 30025 | set_error(make_error( 30026 | parser_error::e_syntax, 30027 | current_token(), 30028 | "ERR182 - Failed to parse initialisation expression for variable '" + var_name + "'", 30029 | exprtk_error_location)); 30030 | 30031 | return error_node(); 30032 | } 30033 | } 30034 | 30035 | if ( 30036 | !token_is(token_t::e_rbracket , prsrhlpr_t::e_hold) && 30037 | !token_is(token_t::e_rcrlbracket, prsrhlpr_t::e_hold) && 30038 | !token_is(token_t::e_rsqrbracket, prsrhlpr_t::e_hold) 30039 | ) 30040 | { 30041 | if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold)) 30042 | { 30043 | set_error(make_error( 30044 | parser_error::e_syntax, 30045 | current_token(), 30046 | "ERR183 - Expected ';' after variable '" + var_name + "' definition", 30047 | exprtk_error_location)); 30048 | 30049 | free_node(node_allocator_, initialisation_expression); 30050 | 30051 | return error_node(); 30052 | } 30053 | } 30054 | 30055 | if ( 30056 | (0 != initialisation_expression) && 30057 | details::is_generally_string_node(initialisation_expression) 30058 | ) 30059 | { 30060 | return parse_define_string_statement(var_name,initialisation_expression); 30061 | } 30062 | 30063 | expression_node_ptr var_node = reinterpret_cast<expression_node_ptr>(0); 30064 | 30065 | scope_element& se = sem_.get_element(var_name); 30066 | 30067 | if (se.name == var_name) 30068 | { 30069 | if (se.active) 30070 | { 30071 | set_error(make_error( 30072 | parser_error::e_syntax, 30073 | current_token(), 30074 | "ERR184 - Illegal redefinition of local variable: '" + var_name + "'", 30075 | exprtk_error_location)); 30076 | 30077 | free_node(node_allocator_, initialisation_expression); 30078 | 30079 | return error_node(); 30080 | } 30081 | else if (scope_element::e_variable == se.type) 30082 | { 30083 | var_node = se.var_node; 30084 | se.active = true; 30085 | se.depth = state_.scope_depth; 30086 | se.ref_count++; 30087 | } 30088 | } 30089 | 30090 | if (0 == var_node) 30091 | { 30092 | const std::size_t predicted_total_lclsymb_size = sizeof(T) + sem_.total_local_symb_size_bytes(); 30093 | 30094 | if (predicted_total_lclsymb_size > settings().max_total_local_symbol_size_bytes()) 30095 | { 30096 | set_error(make_error( 30097 | parser_error::e_syntax, 30098 | current_token(), 30099 | "ERR185 - Adding variable '" + var_name + "' " 30100 | "will exceed max total local symbol size of: " + details::to_str(settings().max_total_local_symbol_size_bytes()) + " bytes, " 30101 | "current total size: " + details::to_str(sem_.total_local_symb_size_bytes()) + " bytes", 30102 | exprtk_error_location)); 30103 | 30104 | free_node(node_allocator_, initialisation_expression); 30105 | 30106 | return error_node(); 30107 | } 30108 | 30109 | scope_element nse; 30110 | nse.name = var_name; 30111 | nse.active = true; 30112 | nse.ref_count = 1; 30113 | nse.type = scope_element::e_variable; 30114 | nse.depth = state_.scope_depth; 30115 | nse.data = new T(T(0)); 30116 | nse.var_node = node_allocator_.allocate<variable_node_t>(*reinterpret_cast<T*>(nse.data)); 30117 | 30118 | if (!sem_.add_element(nse)) 30119 | { 30120 | set_error(make_error( 30121 | parser_error::e_syntax, 30122 | current_token(), 30123 | "ERR186 - Failed to add new local variable '" + var_name + "' to SEM", 30124 | exprtk_error_location)); 30125 | 30126 | free_node(node_allocator_, initialisation_expression); 30127 | 30128 | sem_.free_element(nse); 30129 | 30130 | return error_node(); 30131 | } 30132 | 30133 | assert(sem_.total_local_symb_size_bytes() <= settings().max_total_local_symbol_size_bytes()); 30134 | 30135 | var_node = nse.var_node; 30136 | 30137 | exprtk_debug(("parse_define_var_statement() - INFO - Added new local variable: %s\n", nse.name.c_str())); 30138 | } 30139 | 30140 | state_.activate_side_effect("parse_define_var_statement()"); 30141 | 30142 | lodge_symbol(var_name, e_st_local_variable); 30143 | 30144 | expression_node_ptr branch[2] = {0}; 30145 | 30146 | branch[0] = var_node; 30147 | branch[1] = initialisation_expression ? initialisation_expression : expression_generator_(T(0)); 30148 | 30149 | return expression_generator_(details::e_assign,branch); 30150 | } 30151 | 30152 | inline expression_node_ptr parse_define_constvar_statement() 30153 | { 30154 | if (settings_.vardef_disabled()) 30155 | { 30156 | set_error(make_error( 30157 | parser_error::e_syntax, 30158 | current_token(), 30159 | "ERR187 - Illegal const variable definition", 30160 | exprtk_error_location)); 30161 | 30162 | return error_node(); 30163 | } 30164 | else if (!token_is("const")) 30165 | { 30166 | set_error(make_error( 30167 | parser_error::e_syntax, 30168 | current_token(), 30169 | "ERR188 - Expected 'const' keyword for const-variable definition", 30170 | exprtk_error_location)); 30171 | 30172 | return error_node(); 30173 | } 30174 | else if (!token_is("var")) 30175 | { 30176 | set_error(make_error( 30177 | parser_error::e_syntax, 30178 | current_token(), 30179 | "ERR189 - Expected 'var' keyword for const-variable definition", 30180 | exprtk_error_location)); 30181 | 30182 | return error_node(); 30183 | } 30184 | 30185 | const std::string var_name = current_token().value; 30186 | 30187 | expression_node_ptr initialisation_expression = error_node(); 30188 | 30189 | if (!token_is(token_t::e_symbol)) 30190 | { 30191 | set_error(make_error( 30192 | parser_error::e_syntax, 30193 | current_token(), 30194 | "ERR190 - Expected a symbol for const-variable definition", 30195 | exprtk_error_location)); 30196 | 30197 | return error_node(); 30198 | } 30199 | else if (details::is_reserved_symbol(var_name)) 30200 | { 30201 | set_error(make_error( 30202 | parser_error::e_syntax, 30203 | current_token(), 30204 | "ERR191 - Illegal redefinition of reserved keyword: '" + var_name + "'", 30205 | exprtk_error_location)); 30206 | 30207 | return error_node(); 30208 | } 30209 | else if (symtab_store_.symbol_exists(var_name)) 30210 | { 30211 | set_error(make_error( 30212 | parser_error::e_syntax, 30213 | current_token(), 30214 | "ERR192 - Illegal redefinition of variable '" + var_name + "'", 30215 | exprtk_error_location)); 30216 | 30217 | return error_node(); 30218 | } 30219 | else if (local_variable_is_shadowed(var_name)) 30220 | { 30221 | set_error(make_error( 30222 | parser_error::e_syntax, 30223 | current_token(), 30224 | "ERR193 - Illegal redefinition of local variable: '" + var_name + "'", 30225 | exprtk_error_location)); 30226 | 30227 | return error_node(); 30228 | } 30229 | else if (!token_is(token_t::e_assign)) 30230 | { 30231 | set_error(make_error( 30232 | parser_error::e_syntax, 30233 | current_token(), 30234 | "ERR194 - Expected assignment operator after const-variable: '" + var_name + "' definition", 30235 | exprtk_error_location)); 30236 | 30237 | return error_node(); 30238 | } 30239 | else if (0 == (initialisation_expression = parse_expression())) 30240 | { 30241 | set_error(make_error( 30242 | parser_error::e_syntax, 30243 | current_token(), 30244 | "ERR195 - Failed to parse initialisation expression for const-variable: '" + var_name + "'", 30245 | exprtk_error_location)); 30246 | 30247 | return error_node(); 30248 | } 30249 | 30250 | if (!details::is_literal_node(initialisation_expression)) 30251 | { 30252 | set_error(make_error( 30253 | parser_error::e_syntax, 30254 | current_token(), 30255 | "ERR196 - initialisation expression for const-variable: '" + var_name + "' must be a constant/literal", 30256 | exprtk_error_location)); 30257 | 30258 | free_node(node_allocator_, initialisation_expression); 30259 | 30260 | return error_node(); 30261 | } 30262 | 30263 | assert(initialisation_expression); 30264 | 30265 | const T init_value = initialisation_expression->value(); 30266 | 30267 | free_node(node_allocator_, initialisation_expression); 30268 | 30269 | expression_node_ptr var_node = reinterpret_cast<expression_node_ptr>(0); 30270 | 30271 | scope_element& se = sem_.get_element(var_name); 30272 | 30273 | if (se.name == var_name) 30274 | { 30275 | if (se.active) 30276 | { 30277 | set_error(make_error( 30278 | parser_error::e_syntax, 30279 | current_token(), 30280 | "ERR197 - Illegal redefinition of local variable: '" + var_name + "'", 30281 | exprtk_error_location)); 30282 | 30283 | return error_node(); 30284 | } 30285 | else if (scope_element::e_literal == se.type) 30286 | { 30287 | var_node = se.var_node; 30288 | se.active = true; 30289 | se.depth = state_.scope_depth; 30290 | se.ref_count++; 30291 | } 30292 | } 30293 | 30294 | if (0 == var_node) 30295 | { 30296 | const std::size_t predicted_total_lclsymb_size = sizeof(T) + sem_.total_local_symb_size_bytes(); 30297 | 30298 | if (predicted_total_lclsymb_size > settings().max_total_local_symbol_size_bytes()) 30299 | { 30300 | set_error(make_error( 30301 | parser_error::e_syntax, 30302 | current_token(), 30303 | "ERR198 - Adding variable '" + var_name + "' " 30304 | "will exceed max total local symbol size of: " + details::to_str(settings().max_total_local_symbol_size_bytes()) + " bytes, " 30305 | "current total size: " + details::to_str(sem_.total_local_symb_size_bytes()) + " bytes", 30306 | exprtk_error_location)); 30307 | 30308 | return error_node(); 30309 | } 30310 | 30311 | scope_element nse; 30312 | nse.name = var_name; 30313 | nse.active = true; 30314 | nse.ref_count = 1; 30315 | nse.type = scope_element::e_literal; 30316 | nse.depth = state_.scope_depth; 30317 | nse.data = 0; 30318 | nse.var_node = node_allocator_.allocate<literal_node_t>(init_value); 30319 | 30320 | if (!sem_.add_element(nse)) 30321 | { 30322 | set_error(make_error( 30323 | parser_error::e_syntax, 30324 | current_token(), 30325 | "ERR199 - Failed to add new local const-variable '" + var_name + "' to SEM", 30326 | exprtk_error_location)); 30327 | 30328 | sem_.free_element(nse); 30329 | 30330 | return error_node(); 30331 | } 30332 | 30333 | assert(sem_.total_local_symb_size_bytes() <= settings().max_total_local_symbol_size_bytes()); 30334 | 30335 | var_node = nse.var_node; 30336 | 30337 | exprtk_debug(("parse_define_constvar_statement() - INFO - Added new local const-variable: %s\n", nse.name.c_str())); 30338 | } 30339 | 30340 | state_.activate_side_effect("parse_define_constvar_statement()"); 30341 | 30342 | lodge_symbol(var_name, e_st_local_variable); 30343 | 30344 | return expression_generator_(var_node->value()); 30345 | } 30346 | 30347 | inline expression_node_ptr parse_uninitialised_var_statement(const std::string& var_name) 30348 | { 30349 | if ( 30350 | !token_is(token_t::e_lcrlbracket) || 30351 | !token_is(token_t::e_rcrlbracket) 30352 | ) 30353 | { 30354 | set_error(make_error( 30355 | parser_error::e_syntax, 30356 | current_token(), 30357 | "ERR200 - Expected a '{}' for uninitialised var definition", 30358 | exprtk_error_location)); 30359 | 30360 | return error_node(); 30361 | } 30362 | else if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold)) 30363 | { 30364 | set_error(make_error( 30365 | parser_error::e_syntax, 30366 | current_token(), 30367 | "ERR201 - Expected ';' after uninitialised variable definition", 30368 | exprtk_error_location)); 30369 | 30370 | return error_node(); 30371 | } 30372 | 30373 | expression_node_ptr var_node = reinterpret_cast<expression_node_ptr>(0); 30374 | 30375 | scope_element& se = sem_.get_element(var_name); 30376 | 30377 | if (se.name == var_name) 30378 | { 30379 | if (se.active) 30380 | { 30381 | set_error(make_error( 30382 | parser_error::e_syntax, 30383 | current_token(), 30384 | "ERR202 - Illegal redefinition of local variable: '" + var_name + "'", 30385 | exprtk_error_location)); 30386 | 30387 | return error_node(); 30388 | } 30389 | else if (scope_element::e_variable == se.type) 30390 | { 30391 | var_node = se.var_node; 30392 | se.active = true; 30393 | se.ref_count++; 30394 | } 30395 | } 30396 | 30397 | if (0 == var_node) 30398 | { 30399 | const std::size_t predicted_total_lclsymb_size = sizeof(T) + sem_.total_local_symb_size_bytes(); 30400 | 30401 | if (predicted_total_lclsymb_size > settings().max_total_local_symbol_size_bytes()) 30402 | { 30403 | set_error(make_error( 30404 | parser_error::e_syntax, 30405 | current_token(), 30406 | "ERR203 - Adding variable '" + var_name + "' " 30407 | "will exceed max total local symbol size of: " + details::to_str(settings().max_total_local_symbol_size_bytes()) + " bytes, " 30408 | "current total size: " + details::to_str(sem_.total_local_symb_size_bytes()) + " bytes", 30409 | exprtk_error_location)); 30410 | 30411 | return error_node(); 30412 | } 30413 | 30414 | scope_element nse; 30415 | nse.name = var_name; 30416 | nse.active = true; 30417 | nse.ref_count = 1; 30418 | nse.type = scope_element::e_variable; 30419 | nse.depth = state_.scope_depth; 30420 | nse.ip_index = sem_.next_ip_index(); 30421 | nse.data = new T(T(0)); 30422 | nse.var_node = node_allocator_.allocate<variable_node_t>(*reinterpret_cast<T*>(nse.data)); 30423 | 30424 | if (!sem_.add_element(nse)) 30425 | { 30426 | set_error(make_error( 30427 | parser_error::e_syntax, 30428 | current_token(), 30429 | "ERR204 - Failed to add new local variable '" + var_name + "' to SEM", 30430 | exprtk_error_location)); 30431 | 30432 | sem_.free_element(nse); 30433 | 30434 | return error_node(); 30435 | } 30436 | 30437 | assert(sem_.total_local_symb_size_bytes() <= settings().max_total_local_symbol_size_bytes()); 30438 | 30439 | exprtk_debug(("parse_uninitialised_var_statement() - INFO - Added new local variable: %s\n", 30440 | nse.name.c_str())); 30441 | } 30442 | 30443 | lodge_symbol(var_name, e_st_local_variable); 30444 | 30445 | state_.activate_side_effect("parse_uninitialised_var_statement()"); 30446 | 30447 | return expression_generator_(T(0)); 30448 | } 30449 | 30450 | inline expression_node_ptr parse_swap_statement() 30451 | { 30452 | if (!details::imatch(current_token().value,"swap")) 30453 | { 30454 | return error_node(); 30455 | } 30456 | else 30457 | next_token(); 30458 | 30459 | if (!token_is(token_t::e_lbracket)) 30460 | { 30461 | set_error(make_error( 30462 | parser_error::e_syntax, 30463 | current_token(), 30464 | "ERR205 - Expected '(' at start of swap statement", 30465 | exprtk_error_location)); 30466 | 30467 | return error_node(); 30468 | } 30469 | 30470 | expression_node_ptr variable0 = error_node(); 30471 | expression_node_ptr variable1 = error_node(); 30472 | 30473 | bool variable0_generated = false; 30474 | bool variable1_generated = false; 30475 | 30476 | const std::string var0_name = current_token().value; 30477 | 30478 | if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold)) 30479 | { 30480 | set_error(make_error( 30481 | parser_error::e_syntax, 30482 | current_token(), 30483 | "ERR206 - Expected a symbol for variable or vector element definition", 30484 | exprtk_error_location)); 30485 | 30486 | return error_node(); 30487 | } 30488 | else if (peek_token_is(token_t::e_lsqrbracket)) 30489 | { 30490 | if (0 == (variable0 = parse_vector())) 30491 | { 30492 | set_error(make_error( 30493 | parser_error::e_syntax, 30494 | current_token(), 30495 | "ERR207 - First parameter to swap is an invalid vector element: '" + var0_name + "'", 30496 | exprtk_error_location)); 30497 | 30498 | return error_node(); 30499 | } 30500 | 30501 | variable0_generated = true; 30502 | } 30503 | else 30504 | { 30505 | if (symtab_store_.is_variable(var0_name)) 30506 | { 30507 | variable0 = symtab_store_.get_variable(var0_name); 30508 | } 30509 | 30510 | const scope_element& se = sem_.get_element(var0_name); 30511 | 30512 | if ( 30513 | (se.active) && 30514 | (se.name == var0_name) && 30515 | (scope_element::e_variable == se.type) 30516 | ) 30517 | { 30518 | variable0 = se.var_node; 30519 | } 30520 | 30521 | lodge_symbol(var0_name, e_st_variable); 30522 | 30523 | if (0 == variable0) 30524 | { 30525 | set_error(make_error( 30526 | parser_error::e_syntax, 30527 | current_token(), 30528 | "ERR208 - First parameter to swap is an invalid variable: '" + var0_name + "'", 30529 | exprtk_error_location)); 30530 | 30531 | return error_node(); 30532 | } 30533 | else 30534 | next_token(); 30535 | } 30536 | 30537 | if (!token_is(token_t::e_comma)) 30538 | { 30539 | set_error(make_error( 30540 | parser_error::e_syntax, 30541 | current_token(), 30542 | "ERR209 - Expected ',' between parameters to swap", 30543 | exprtk_error_location)); 30544 | 30545 | if (variable0_generated) 30546 | { 30547 | free_node(node_allocator_, variable0); 30548 | } 30549 | 30550 | return error_node(); 30551 | } 30552 | 30553 | const std::string var1_name = current_token().value; 30554 | 30555 | if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold)) 30556 | { 30557 | set_error(make_error( 30558 | parser_error::e_syntax, 30559 | current_token(), 30560 | "ERR210 - Expected a symbol for variable or vector element definition", 30561 | exprtk_error_location)); 30562 | 30563 | if (variable0_generated) 30564 | { 30565 | free_node(node_allocator_, variable0); 30566 | } 30567 | 30568 | return error_node(); 30569 | } 30570 | else if (peek_token_is(token_t::e_lsqrbracket)) 30571 | { 30572 | if (0 == (variable1 = parse_vector())) 30573 | { 30574 | set_error(make_error( 30575 | parser_error::e_syntax, 30576 | current_token(), 30577 | "ERR211 - Second parameter to swap is an invalid vector element: '" + var1_name + "'", 30578 | exprtk_error_location)); 30579 | 30580 | if (variable0_generated) 30581 | { 30582 | free_node(node_allocator_, variable0); 30583 | } 30584 | 30585 | return error_node(); 30586 | } 30587 | 30588 | variable1_generated = true; 30589 | } 30590 | else 30591 | { 30592 | if (symtab_store_.is_variable(var1_name)) 30593 | { 30594 | variable1 = symtab_store_.get_variable(var1_name); 30595 | } 30596 | 30597 | const scope_element& se = sem_.get_element(var1_name); 30598 | 30599 | if ( 30600 | (se.active) && 30601 | (se.name == var1_name) && 30602 | (scope_element::e_variable == se.type) 30603 | ) 30604 | { 30605 | variable1 = se.var_node; 30606 | } 30607 | 30608 | lodge_symbol(var1_name, e_st_variable); 30609 | 30610 | if (0 == variable1) 30611 | { 30612 | set_error(make_error( 30613 | parser_error::e_syntax, 30614 | current_token(), 30615 | "ERR212 - Second parameter to swap is an invalid variable: '" + var1_name + "'", 30616 | exprtk_error_location)); 30617 | 30618 | if (variable0_generated) 30619 | { 30620 | free_node(node_allocator_, variable0); 30621 | } 30622 | 30623 | return error_node(); 30624 | } 30625 | else 30626 | next_token(); 30627 | } 30628 | 30629 | if (!token_is(token_t::e_rbracket)) 30630 | { 30631 | set_error(make_error( 30632 | parser_error::e_syntax, 30633 | current_token(), 30634 | "ERR213 - Expected ')' at end of swap statement", 30635 | exprtk_error_location)); 30636 | 30637 | if (variable0_generated) 30638 | { 30639 | free_node(node_allocator_, variable0); 30640 | } 30641 | 30642 | if (variable1_generated) 30643 | { 30644 | free_node(node_allocator_, variable1); 30645 | } 30646 | 30647 | return error_node(); 30648 | } 30649 | 30650 | typedef details::variable_node<T>* variable_node_ptr; 30651 | 30652 | variable_node_ptr v0 = variable_node_ptr(0); 30653 | variable_node_ptr v1 = variable_node_ptr(0); 30654 | 30655 | expression_node_ptr result = error_node(); 30656 | 30657 | if ( 30658 | (0 != (v0 = dynamic_cast<variable_node_ptr>(variable0))) && 30659 | (0 != (v1 = dynamic_cast<variable_node_ptr>(variable1))) 30660 | ) 30661 | { 30662 | result = node_allocator_.allocate<details::swap_node<T> >(v0, v1); 30663 | 30664 | if (variable0_generated) 30665 | { 30666 | free_node(node_allocator_, variable0); 30667 | } 30668 | 30669 | if (variable1_generated) 30670 | { 30671 | free_node(node_allocator_, variable1); 30672 | } 30673 | } 30674 | else 30675 | result = node_allocator_.allocate<details::swap_generic_node<T> > 30676 | (variable0, variable1); 30677 | 30678 | state_.activate_side_effect("parse_swap_statement()"); 30679 | 30680 | return result; 30681 | } 30682 | 30683 | #ifndef exprtk_disable_return_statement 30684 | inline expression_node_ptr parse_return_statement() 30685 | { 30686 | if (state_.parsing_return_stmt) 30687 | { 30688 | set_error(make_error( 30689 | parser_error::e_syntax, 30690 | current_token(), 30691 | "ERR214 - Return call within a return call is not allowed", 30692 | exprtk_error_location)); 30693 | 30694 | return error_node(); 30695 | } 30696 | 30697 | scoped_bool_negator sbn(state_.parsing_return_stmt); 30698 | 30699 | std::vector<expression_node_ptr> arg_list; 30700 | 30701 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 30702 | 30703 | if (!details::imatch(current_token().value,"return")) 30704 | { 30705 | return error_node(); 30706 | } 30707 | else 30708 | next_token(); 30709 | 30710 | if (!token_is(token_t::e_lsqrbracket)) 30711 | { 30712 | set_error(make_error( 30713 | parser_error::e_syntax, 30714 | current_token(), 30715 | "ERR215 - Expected '[' at start of return statement", 30716 | exprtk_error_location)); 30717 | 30718 | return error_node(); 30719 | } 30720 | else if (!token_is(token_t::e_rsqrbracket)) 30721 | { 30722 | for ( ; ; ) 30723 | { 30724 | expression_node_ptr arg = parse_expression(); 30725 | 30726 | if (0 == arg) 30727 | return error_node(); 30728 | 30729 | arg_list.push_back(arg); 30730 | 30731 | if (token_is(token_t::e_rsqrbracket)) 30732 | break; 30733 | else if (!token_is(token_t::e_comma)) 30734 | { 30735 | set_error(make_error( 30736 | parser_error::e_syntax, 30737 | current_token(), 30738 | "ERR216 - Expected ',' between values during call to return", 30739 | exprtk_error_location)); 30740 | 30741 | return error_node(); 30742 | } 30743 | } 30744 | } 30745 | else if (settings_.zero_return_disabled()) 30746 | { 30747 | set_error(make_error( 30748 | parser_error::e_syntax, 30749 | current_token(), 30750 | "ERR217 - Zero parameter return statement not allowed", 30751 | exprtk_error_location)); 30752 | 30753 | return error_node(); 30754 | } 30755 | 30756 | const lexer::token prev_token = current_token(); 30757 | 30758 | if (token_is(token_t::e_rsqrbracket)) 30759 | { 30760 | if (!arg_list.empty()) 30761 | { 30762 | set_error(make_error( 30763 | parser_error::e_syntax, 30764 | prev_token, 30765 | "ERR218 - Invalid ']' found during return call", 30766 | exprtk_error_location)); 30767 | 30768 | return error_node(); 30769 | } 30770 | } 30771 | 30772 | std::string ret_param_type_list; 30773 | 30774 | for (std::size_t i = 0; i < arg_list.size(); ++i) 30775 | { 30776 | if (0 == arg_list[i]) 30777 | return error_node(); 30778 | else if (is_ivector_node(arg_list[i])) 30779 | ret_param_type_list += 'V'; 30780 | else if (is_generally_string_node(arg_list[i])) 30781 | ret_param_type_list += 'S'; 30782 | else 30783 | ret_param_type_list += 'T'; 30784 | } 30785 | 30786 | dec_.retparam_list_.push_back(ret_param_type_list); 30787 | 30788 | expression_node_ptr result = expression_generator_.return_call(arg_list); 30789 | 30790 | svd.delete_ptr = (0 == result); 30791 | 30792 | state_.return_stmt_present = true; 30793 | 30794 | state_.activate_side_effect("parse_return_statement()"); 30795 | 30796 | return result; 30797 | } 30798 | #else 30799 | inline expression_node_ptr parse_return_statement() 30800 | { 30801 | return error_node(); 30802 | } 30803 | #endif 30804 | 30805 | inline expression_node_ptr parse_assert_statement() 30806 | { 30807 | assert(details::imatch(current_token().value, "assert")); 30808 | 30809 | if (state_.parsing_assert_stmt) 30810 | { 30811 | set_error(make_error( 30812 | parser_error::e_syntax, 30813 | current_token(), 30814 | "ERR219 - Assert statement within an assert statement is not allowed", 30815 | exprtk_error_location)); 30816 | 30817 | return error_node(); 30818 | } 30819 | 30820 | scoped_bool_negator sbn(state_.parsing_assert_stmt); 30821 | 30822 | next_token(); 30823 | 30824 | std::vector<expression_node_ptr> assert_arg_list(3, error_node()); 30825 | scoped_vec_delete<expression_node_t> svd((*this), assert_arg_list); 30826 | 30827 | expression_node_ptr& assert_condition = assert_arg_list[0]; 30828 | expression_node_ptr& assert_message = assert_arg_list[1]; 30829 | expression_node_ptr& assert_id = assert_arg_list[2]; 30830 | 30831 | if (!token_is(token_t::e_lbracket)) 30832 | { 30833 | set_error(make_error( 30834 | parser_error::e_syntax, 30835 | current_token(), 30836 | "ERR220 - Expected '(' at start of assert statement", 30837 | exprtk_error_location)); 30838 | 30839 | return error_node(); 30840 | } 30841 | 30842 | const token_t start_token = current_token(); 30843 | 30844 | // Parse the assert condition 30845 | if (0 == (assert_condition = parse_expression())) 30846 | { 30847 | set_error(make_error( 30848 | parser_error::e_syntax, 30849 | current_token(), 30850 | "ERR221 - Failed to parse condition for assert statement", 30851 | exprtk_error_location)); 30852 | 30853 | return error_node(); 30854 | } 30855 | 30856 | const token_t end_token = current_token(); 30857 | 30858 | if (!token_is(token_t::e_rbracket)) 30859 | { 30860 | if (!token_is(token_t::e_comma)) 30861 | { 30862 | set_error(make_error( 30863 | parser_error::e_syntax, 30864 | current_token(), 30865 | "ERR222 - Expected ',' between condition and message for assert statement", 30866 | exprtk_error_location)); 30867 | 30868 | return error_node(); 30869 | } 30870 | // Parse the assert message 30871 | else if ( 30872 | (0 == (assert_message = parse_expression())) || 30873 | !details::is_generally_string_node(assert_message) 30874 | ) 30875 | { 30876 | set_error(make_error( 30877 | parser_error::e_syntax, 30878 | current_token(), 30879 | "ERR223 - " + 30880 | (assert_message ? 30881 | std::string("Expected string for assert message") : 30882 | std::string("Failed to parse message for assert statement")), 30883 | exprtk_error_location)); 30884 | 30885 | return error_node(); 30886 | } 30887 | else if (!token_is(token_t::e_rbracket)) 30888 | { 30889 | if (!token_is(token_t::e_comma)) 30890 | { 30891 | set_error(make_error( 30892 | parser_error::e_syntax, 30893 | current_token(), 30894 | "ERR224 - Expected ',' between message and ID for assert statement", 30895 | exprtk_error_location)); 30896 | 30897 | return error_node(); 30898 | } 30899 | // Parse assert ID 30900 | else if ( 30901 | (0 == (assert_id = parse_expression())) || 30902 | !details::is_const_string_node(assert_id) 30903 | ) 30904 | { 30905 | set_error(make_error( 30906 | parser_error::e_syntax, 30907 | current_token(), 30908 | "ERR225 - " + 30909 | (assert_id ? 30910 | std::string("Expected literal string for assert ID") : 30911 | std::string("Failed to parse string for assert ID")), 30912 | exprtk_error_location)); 30913 | 30914 | return error_node(); 30915 | } 30916 | else if (!token_is(token_t::e_rbracket)) 30917 | { 30918 | set_error(make_error( 30919 | parser_error::e_syntax, 30920 | current_token(), 30921 | "ERR226 - Expected ')' at start of assert statement", 30922 | exprtk_error_location)); 30923 | 30924 | return error_node(); 30925 | } 30926 | } 30927 | } 30928 | 30929 | exprtk::assert_check::assert_context context; 30930 | context.condition = lexer().substr(start_token.position, end_token.position); 30931 | context.offet = start_token.position; 30932 | 30933 | if (0 == assert_check_) 30934 | { 30935 | exprtk_debug(("parse_assert_statement() - assert functionality is disabled. assert condition: %s\n", 30936 | context.condition.c_str())); 30937 | 30938 | return new details::null_node<T>(); 30939 | } 30940 | 30941 | #ifndef exprtk_disable_string_capabilities 30942 | if (assert_message && details::is_const_string_node(assert_message)) 30943 | { 30944 | context.message = dynamic_cast<details::string_base_node<T>*>(assert_message)->str(); 30945 | } 30946 | 30947 | if (assert_id && details::is_const_string_node(assert_id)) 30948 | { 30949 | context.id = dynamic_cast<details::string_base_node<T>*>(assert_id)->str(); 30950 | 30951 | if (assert_ids_.end() != assert_ids_.find(context.id)) 30952 | { 30953 | set_error(make_error( 30954 | parser_error::e_syntax, 30955 | current_token(), 30956 | "ERR227 - Duplicate assert ID: " + context.id, 30957 | exprtk_error_location)); 30958 | 30959 | return error_node(); 30960 | } 30961 | 30962 | assert_ids_.insert(context.id); 30963 | free_node(node_allocator_, assert_id); 30964 | } 30965 | #endif 30966 | 30967 | expression_node_ptr result_node = 30968 | expression_generator_.assert_call( 30969 | assert_condition, 30970 | assert_message, 30971 | context); 30972 | 30973 | exprtk_debug(("parse_assert_statement() - assert condition: [%s]\n", context.condition.c_str() )); 30974 | exprtk_debug(("parse_assert_statement() - assert message: [%s]\n", context.message .c_str() )); 30975 | exprtk_debug(("parse_assert_statement() - assert id: [%s]\n", context.id .c_str() )); 30976 | exprtk_debug(("parse_assert_statement() - assert offset: [%d]\n", static_cast<int>(context.offet))); 30977 | 30978 | if (0 == result_node) 30979 | { 30980 | set_error(make_error( 30981 | parser_error::e_syntax, 30982 | current_token(), 30983 | "ERR228 - Failed to synthesize assert", 30984 | exprtk_error_location)); 30985 | 30986 | return error_node(); 30987 | } 30988 | 30989 | svd.delete_ptr = false; 30990 | return result_node; 30991 | } 30992 | 30993 | inline bool post_variable_process(const std::string& symbol) 30994 | { 30995 | if ( 30996 | peek_token_is(token_t::e_lbracket ) || 30997 | peek_token_is(token_t::e_lcrlbracket) || 30998 | peek_token_is(token_t::e_lsqrbracket) 30999 | ) 31000 | { 31001 | if (!settings_.commutative_check_enabled()) 31002 | { 31003 | set_error(make_error( 31004 | parser_error::e_syntax, 31005 | current_token(), 31006 | "ERR229 - Invalid sequence of variable '" + symbol + "' and bracket", 31007 | exprtk_error_location)); 31008 | 31009 | return false; 31010 | } 31011 | 31012 | lexer().insert_front(token_t::e_mul); 31013 | } 31014 | 31015 | return true; 31016 | } 31017 | 31018 | inline bool post_bracket_process(const typename token_t::token_type& token, expression_node_ptr& branch) 31019 | { 31020 | bool implied_mul = false; 31021 | 31022 | if (details::is_generally_string_node(branch)) 31023 | return true; 31024 | 31025 | if (details::is_ivector_node(branch)) 31026 | return true; 31027 | 31028 | const lexer::parser_helper::token_advance_mode hold = prsrhlpr_t::e_hold; 31029 | 31030 | switch (token) 31031 | { 31032 | case token_t::e_lcrlbracket : implied_mul = token_is(token_t::e_lbracket , hold) || 31033 | token_is(token_t::e_lcrlbracket, hold) || 31034 | token_is(token_t::e_lsqrbracket, hold) ; 31035 | break; 31036 | 31037 | case token_t::e_lbracket : implied_mul = token_is(token_t::e_lbracket , hold) || 31038 | token_is(token_t::e_lcrlbracket, hold) || 31039 | token_is(token_t::e_lsqrbracket, hold) ; 31040 | break; 31041 | 31042 | case token_t::e_lsqrbracket : implied_mul = token_is(token_t::e_lbracket , hold) || 31043 | token_is(token_t::e_lcrlbracket, hold) || 31044 | token_is(token_t::e_lsqrbracket, hold) ; 31045 | break; 31046 | 31047 | default : return true; 31048 | } 31049 | 31050 | if (implied_mul) 31051 | { 31052 | if (!settings_.commutative_check_enabled()) 31053 | { 31054 | set_error(make_error( 31055 | parser_error::e_syntax, 31056 | current_token(), 31057 | "ERR230 - Invalid sequence of brackets", 31058 | exprtk_error_location)); 31059 | 31060 | return false; 31061 | } 31062 | else if (token_t::e_eof != current_token().type) 31063 | { 31064 | lexer().insert_front(current_token().type); 31065 | lexer().insert_front(token_t::e_mul); 31066 | next_token(); 31067 | } 31068 | } 31069 | 31070 | return true; 31071 | } 31072 | 31073 | typedef typename interval_container_t<const void*>::interval_t interval_t; 31074 | typedef interval_container_t<const void*> immutable_memory_map_t; 31075 | typedef std::map<interval_t,token_t> immutable_symtok_map_t; 31076 | 31077 | inline interval_t make_memory_range(const T& t) 31078 | { 31079 | const T* begin = reinterpret_cast<const T*>(&t); 31080 | const T* end = begin + 1; 31081 | return interval_t(begin, end); 31082 | } 31083 | 31084 | inline interval_t make_memory_range(const T* begin, const std::size_t size) 31085 | { 31086 | return interval_t(begin, begin + size); 31087 | } 31088 | 31089 | inline interval_t make_memory_range(details::char_cptr begin, const std::size_t size) 31090 | { 31091 | return interval_t(begin, begin + size); 31092 | } 31093 | 31094 | void lodge_immutable_symbol(const lexer::token& token, const interval_t interval) 31095 | { 31096 | immutable_memory_map_.add_interval(interval); 31097 | immutable_symtok_map_[interval] = token; 31098 | } 31099 | 31100 | inline expression_node_ptr parse_symtab_symbol() 31101 | { 31102 | const std::string symbol = current_token().value; 31103 | 31104 | // Are we dealing with a variable or a special constant? 31105 | typedef typename symtab_store::variable_context var_ctxt_t; 31106 | var_ctxt_t var_ctx = symtab_store_.get_variable_context(symbol); 31107 | 31108 | if (var_ctx.variable) 31109 | { 31110 | assert(var_ctx.symbol_table); 31111 | 31112 | expression_node_ptr result_variable = var_ctx.variable; 31113 | 31114 | if (symtab_store_.is_constant_node(symbol)) 31115 | { 31116 | result_variable = expression_generator_(var_ctx.variable->value()); 31117 | } 31118 | else if (symbol_table_t::e_immutable == var_ctx.symbol_table->mutability()) 31119 | { 31120 | lodge_immutable_symbol(current_token(), make_memory_range(var_ctx.variable->ref())); 31121 | result_variable = var_ctx.variable; 31122 | } 31123 | 31124 | if (!post_variable_process(symbol)) 31125 | return error_node(); 31126 | 31127 | lodge_symbol(symbol, e_st_variable); 31128 | 31129 | next_token(); 31130 | 31131 | return result_variable; 31132 | } 31133 | 31134 | // Are we dealing with a locally defined variable, vector or string? 31135 | if (!sem_.empty()) 31136 | { 31137 | scope_element& se = sem_.get_active_element(symbol); 31138 | 31139 | if (se.active && details::imatch(se.name, symbol)) 31140 | { 31141 | if ( 31142 | (scope_element::e_variable == se.type) || 31143 | (scope_element::e_literal == se.type) 31144 | ) 31145 | { 31146 | se.active = true; 31147 | lodge_symbol(symbol, e_st_local_variable); 31148 | 31149 | if (!post_variable_process(symbol)) 31150 | return error_node(); 31151 | 31152 | next_token(); 31153 | 31154 | return (scope_element::e_variable == se.type) ? 31155 | se.var_node : 31156 | expression_generator_(se.var_node->value()); 31157 | } 31158 | else if (scope_element::e_vector == se.type) 31159 | { 31160 | return parse_vector(); 31161 | } 31162 | #ifndef exprtk_disable_string_capabilities 31163 | else if (scope_element::e_string == se.type) 31164 | { 31165 | return parse_string(); 31166 | } 31167 | #endif 31168 | } 31169 | } 31170 | 31171 | #ifndef exprtk_disable_string_capabilities 31172 | // Are we dealing with a string variable? 31173 | if (symtab_store_.is_stringvar(symbol)) 31174 | { 31175 | return parse_string(); 31176 | } 31177 | #endif 31178 | 31179 | { 31180 | // Are we dealing with a function? 31181 | ifunction<T>* function = symtab_store_.get_function(symbol); 31182 | 31183 | if (function) 31184 | { 31185 | lodge_symbol(symbol, e_st_function); 31186 | 31187 | expression_node_ptr func_node = 31188 | parse_function_invocation(function,symbol); 31189 | 31190 | if (func_node) 31191 | return func_node; 31192 | else 31193 | { 31194 | set_error(make_error( 31195 | parser_error::e_syntax, 31196 | current_token(), 31197 | "ERR231 - Failed to generate node for function: '" + symbol + "'", 31198 | exprtk_error_location)); 31199 | 31200 | return error_node(); 31201 | } 31202 | } 31203 | } 31204 | 31205 | { 31206 | // Are we dealing with a vararg function? 31207 | ivararg_function<T>* vararg_function = symtab_store_.get_vararg_function(symbol); 31208 | 31209 | if (vararg_function) 31210 | { 31211 | lodge_symbol(symbol, e_st_function); 31212 | 31213 | expression_node_ptr vararg_func_node = 31214 | parse_vararg_function_call(vararg_function, symbol); 31215 | 31216 | if (vararg_func_node) 31217 | return vararg_func_node; 31218 | else 31219 | { 31220 | set_error(make_error( 31221 | parser_error::e_syntax, 31222 | current_token(), 31223 | "ERR232 - Failed to generate node for vararg function: '" + symbol + "'", 31224 | exprtk_error_location)); 31225 | 31226 | return error_node(); 31227 | } 31228 | } 31229 | } 31230 | 31231 | { 31232 | // Are we dealing with a vararg generic function? 31233 | igeneric_function<T>* generic_function = symtab_store_.get_generic_function(symbol); 31234 | 31235 | if (generic_function) 31236 | { 31237 | lodge_symbol(symbol, e_st_function); 31238 | 31239 | expression_node_ptr genericfunc_node = 31240 | parse_generic_function_call(generic_function, symbol); 31241 | 31242 | if (genericfunc_node) 31243 | return genericfunc_node; 31244 | else 31245 | { 31246 | set_error(make_error( 31247 | parser_error::e_syntax, 31248 | current_token(), 31249 | "ERR233 - Failed to generate node for generic function: '" + symbol + "'", 31250 | exprtk_error_location)); 31251 | 31252 | return error_node(); 31253 | } 31254 | } 31255 | } 31256 | 31257 | #ifndef exprtk_disable_string_capabilities 31258 | { 31259 | // Are we dealing with a vararg string returning function? 31260 | igeneric_function<T>* string_function = symtab_store_.get_string_function(symbol); 31261 | 31262 | if (string_function) 31263 | { 31264 | lodge_symbol(symbol, e_st_function); 31265 | 31266 | expression_node_ptr stringfunc_node = 31267 | parse_string_function_call(string_function, symbol); 31268 | 31269 | if (stringfunc_node) 31270 | return stringfunc_node; 31271 | else 31272 | { 31273 | set_error(make_error( 31274 | parser_error::e_syntax, 31275 | current_token(), 31276 | "ERR234 - Failed to generate node for string function: '" + symbol + "'", 31277 | exprtk_error_location)); 31278 | 31279 | return error_node(); 31280 | } 31281 | } 31282 | } 31283 | 31284 | { 31285 | // Are we dealing with a vararg overloaded scalar/string returning function? 31286 | igeneric_function<T>* overload_function = symtab_store_.get_overload_function(symbol); 31287 | 31288 | if (overload_function) 31289 | { 31290 | lodge_symbol(symbol, e_st_function); 31291 | 31292 | expression_node_ptr overloadfunc_node = 31293 | parse_overload_function_call(overload_function, symbol); 31294 | 31295 | if (overloadfunc_node) 31296 | return overloadfunc_node; 31297 | else 31298 | { 31299 | set_error(make_error( 31300 | parser_error::e_syntax, 31301 | current_token(), 31302 | "ERR235 - Failed to generate node for overload function: '" + symbol + "'", 31303 | exprtk_error_location)); 31304 | 31305 | return error_node(); 31306 | } 31307 | } 31308 | } 31309 | #endif 31310 | 31311 | // Are we dealing with a vector? 31312 | if (symtab_store_.is_vector(symbol)) 31313 | { 31314 | lodge_symbol(symbol, e_st_vector); 31315 | return parse_vector(); 31316 | } 31317 | 31318 | if (details::is_reserved_symbol(symbol)) 31319 | { 31320 | if ( 31321 | settings_.function_enabled(symbol) || 31322 | !details::is_base_function(symbol) 31323 | ) 31324 | { 31325 | set_error(make_error( 31326 | parser_error::e_syntax, 31327 | current_token(), 31328 | "ERR236 - Invalid use of reserved symbol '" + symbol + "'", 31329 | exprtk_error_location)); 31330 | 31331 | return error_node(); 31332 | } 31333 | } 31334 | 31335 | // Should we handle unknown symbols? 31336 | if (resolve_unknown_symbol_ && unknown_symbol_resolver_) 31337 | { 31338 | if (!(settings_.rsrvd_sym_usr_disabled() && details::is_reserved_symbol(symbol))) 31339 | { 31340 | symbol_table_t& symtab = symtab_store_.get_symbol_table(); 31341 | 31342 | std::string error_message; 31343 | 31344 | if (unknown_symbol_resolver::e_usrmode_default == unknown_symbol_resolver_->mode) 31345 | { 31346 | T default_value = T(0); 31347 | 31348 | typename unknown_symbol_resolver::usr_symbol_type usr_symbol_type = unknown_symbol_resolver::e_usr_unknown_type; 31349 | 31350 | if (unknown_symbol_resolver_->process(symbol, usr_symbol_type, default_value, error_message)) 31351 | { 31352 | bool create_result = false; 31353 | 31354 | switch (usr_symbol_type) 31355 | { 31356 | case unknown_symbol_resolver::e_usr_variable_type : 31357 | create_result = symtab.create_variable(symbol, default_value); 31358 | break; 31359 | 31360 | case unknown_symbol_resolver::e_usr_constant_type : 31361 | create_result = symtab.add_constant(symbol, default_value); 31362 | break; 31363 | 31364 | default : create_result = false; 31365 | } 31366 | 31367 | if (create_result) 31368 | { 31369 | expression_node_ptr var = symtab_store_.get_variable(symbol); 31370 | 31371 | if (var) 31372 | { 31373 | if (symtab_store_.is_constant_node(symbol)) 31374 | { 31375 | var = expression_generator_(var->value()); 31376 | } 31377 | 31378 | lodge_symbol(symbol, e_st_variable); 31379 | 31380 | if (!post_variable_process(symbol)) 31381 | return error_node(); 31382 | 31383 | next_token(); 31384 | 31385 | return var; 31386 | } 31387 | } 31388 | } 31389 | 31390 | set_error(make_error( 31391 | parser_error::e_symtab, 31392 | current_token(), 31393 | "ERR237 - Failed to create variable: '" + symbol + "'" + 31394 | (error_message.empty() ? "" : " - " + error_message), 31395 | exprtk_error_location)); 31396 | 31397 | } 31398 | else if (unknown_symbol_resolver::e_usrmode_extended == unknown_symbol_resolver_->mode) 31399 | { 31400 | if (unknown_symbol_resolver_->process(symbol, symtab, error_message)) 31401 | { 31402 | expression_node_ptr result = parse_symtab_symbol(); 31403 | 31404 | if (result) 31405 | { 31406 | return result; 31407 | } 31408 | } 31409 | 31410 | set_error(make_error( 31411 | parser_error::e_symtab, 31412 | current_token(), 31413 | "ERR238 - Failed to resolve symbol: '" + symbol + "'" + 31414 | (error_message.empty() ? "" : " - " + error_message), 31415 | exprtk_error_location)); 31416 | } 31417 | 31418 | return error_node(); 31419 | } 31420 | } 31421 | 31422 | set_error(make_error( 31423 | parser_error::e_syntax, 31424 | current_token(), 31425 | "ERR239 - Undefined symbol: '" + symbol + "'", 31426 | exprtk_error_location)); 31427 | 31428 | return error_node(); 31429 | } 31430 | 31431 | inline expression_node_ptr check_block_statement_closure(expression_node_ptr expression) 31432 | { 31433 | if ( 31434 | expression && 31435 | ( 31436 | (current_token().type == token_t::e_symbol) || 31437 | (current_token().type == token_t::e_number) 31438 | ) 31439 | ) 31440 | { 31441 | free_node(node_allocator_, expression); 31442 | 31443 | set_error(make_error( 31444 | parser_error::e_syntax, 31445 | current_token(), 31446 | "ERR240 - Invalid syntax '" + current_token().value + "' possible missing operator or context", 31447 | exprtk_error_location)); 31448 | 31449 | return error_node(); 31450 | } 31451 | 31452 | return expression; 31453 | } 31454 | 31455 | inline expression_node_ptr parse_symbol() 31456 | { 31457 | static const std::string symbol_if = "if" ; 31458 | static const std::string symbol_while = "while" ; 31459 | static const std::string symbol_repeat = "repeat" ; 31460 | static const std::string symbol_for = "for" ; 31461 | static const std::string symbol_switch = "switch" ; 31462 | static const std::string symbol_null = "null" ; 31463 | static const std::string symbol_break = "break" ; 31464 | static const std::string symbol_continue = "continue" 31465 | static const std::string symbol_var = "var" ; 31466 | static const std::string symbol_const = "const" ; 31467 | static const std::string symbol_swap = "swap" ; 31468 | static const std::string symbol_return = "return" ; 31469 | static const std::string symbol_not = "not" ; 31470 | static const std::string symbol_assert = "assert" ; 31471 | 31472 | const std::string symbol = current_token().value; 31473 | 31474 | if (valid_vararg_operation(symbol)) 31475 | { 31476 | return parse_vararg_function(); 31477 | } 31478 | else if (details::imatch(symbol, symbol_not)) 31479 | { 31480 | return parse_not_statement(); 31481 | } 31482 | else if (valid_base_operation(symbol)) 31483 | { 31484 | return parse_base_operation(); 31485 | } 31486 | else if ( 31487 | details::imatch(symbol, symbol_if) && 31488 | settings_.control_struct_enabled(symbol) 31489 | ) 31490 | { 31491 | return parse_conditional_statement(); 31492 | } 31493 | else if ( 31494 | details::imatch(symbol, symbol_while) && 31495 | settings_.control_struct_enabled(symbol) 31496 | ) 31497 | { 31498 | return check_block_statement_closure(parse_while_loop()); 31499 | } 31500 | else if ( 31501 | details::imatch(symbol, symbol_repeat) && 31502 | settings_.control_struct_enabled(symbol) 31503 | ) 31504 | { 31505 | return check_block_statement_closure(parse_repeat_until_loop()); 31506 | } 31507 | else if ( 31508 | details::imatch(symbol, symbol_for) && 31509 | settings_.control_struct_enabled(symbol) 31510 | ) 31511 | { 31512 | return check_block_statement_closure(parse_for_loop()); 31513 | } 31514 | else if ( 31515 | details::imatch(symbol, symbol_switch) && 31516 | settings_.control_struct_enabled(symbol) 31517 | ) 31518 | { 31519 | return check_block_statement_closure(parse_switch_statement()); 31520 | } 31521 | else if (details::is_valid_sf_symbol(symbol)) 31522 | { 31523 | return parse_special_function(); 31524 | } 31525 | else if (details::imatch(symbol, symbol_null)) 31526 | { 31527 | return parse_null_statement(); 31528 | } 31529 | #ifndef exprtk_disable_break_continue 31530 | else if (details::imatch(symbol, symbol_break)) 31531 | { 31532 | return parse_break_statement(); 31533 | } 31534 | else if (details::imatch(symbol, symbol_continue)) 31535 | { 31536 | return parse_continue_statement(); 31537 | } 31538 | #endif 31539 | else if (details::imatch(symbol, symbol_var)) 31540 | { 31541 | return parse_define_var_statement(); 31542 | } 31543 | else if (details::imatch(symbol, symbol_const)) 31544 | { 31545 | return parse_define_constvar_statement(); 31546 | } 31547 | else if (details::imatch(symbol, symbol_swap)) 31548 | { 31549 | return parse_swap_statement(); 31550 | } 31551 | #ifndef exprtk_disable_return_statement 31552 | else if ( 31553 | details::imatch(symbol, symbol_return) && 31554 | settings_.control_struct_enabled(symbol) 31555 | ) 31556 | { 31557 | return check_block_statement_closure(parse_return_statement()); 31558 | } 31559 | #endif 31560 | else if (details::imatch(symbol, symbol_assert)) 31561 | { 31562 | return parse_assert_statement(); 31563 | } 31564 | else if (symtab_store_.valid() || !sem_.empty()) 31565 | { 31566 | return parse_symtab_symbol(); 31567 | } 31568 | else 31569 | { 31570 | set_error(make_error( 31571 | parser_error::e_symtab, 31572 | current_token(), 31573 | "ERR241 - Unknown variable or function encountered. Symbol table(s) " 31574 | "is either invalid or does not contain symbol: '" + symbol + "'", 31575 | exprtk_error_location)); 31576 | 31577 | return error_node(); 31578 | } 31579 | } 31580 | 31581 | inline expression_node_ptr parse_branch(precedence_level precedence = e_level00) 31582 | { 31583 | stack_limit_handler slh(*this); 31584 | 31585 | if (!slh) 31586 | { 31587 | return error_node(); 31588 | } 31589 | 31590 | expression_node_ptr branch = error_node(); 31591 | 31592 | if (token_t::e_number == current_token().type) 31593 | { 31594 | T numeric_value = T(0); 31595 | 31596 | if (details::string_to_real(current_token().value, numeric_value)) 31597 | { 31598 | expression_node_ptr literal_exp = expression_generator_(numeric_value); 31599 | 31600 | if (0 == literal_exp) 31601 | { 31602 | set_error(make_error( 31603 | parser_error::e_numeric, 31604 | current_token(), 31605 | "ERR242 - Failed generate node for scalar: '" + current_token().value + "'", 31606 | exprtk_error_location)); 31607 | 31608 | return error_node(); 31609 | } 31610 | 31611 | next_token(); 31612 | branch = literal_exp; 31613 | } 31614 | else 31615 | { 31616 | set_error(make_error( 31617 | parser_error::e_numeric, 31618 | current_token(), 31619 | "ERR243 - Failed to convert '" + current_token().value + "' to a number", 31620 | exprtk_error_location)); 31621 | 31622 | return error_node(); 31623 | } 31624 | } 31625 | else if (token_t::e_symbol == current_token().type) 31626 | { 31627 | branch = parse_symbol(); 31628 | } 31629 | #ifndef exprtk_disable_string_capabilities 31630 | else if (token_t::e_string == current_token().type) 31631 | { 31632 | branch = parse_const_string(); 31633 | } 31634 | #endif 31635 | else if (token_t::e_lbracket == current_token().type) 31636 | { 31637 | next_token(); 31638 | 31639 | if (0 == (branch = parse_expression())) 31640 | { 31641 | return error_node(); 31642 | } 31643 | 31644 | token_is(token_t::e_eof); 31645 | 31646 | if (!token_is(token_t::e_rbracket)) 31647 | { 31648 | set_error(make_error( 31649 | parser_error::e_syntax, 31650 | current_token(), 31651 | "ERR244 - Expected ')' instead of: '" + current_token().value + "'", 31652 | exprtk_error_location)); 31653 | 31654 | details::free_node(node_allocator_, branch); 31655 | 31656 | return error_node(); 31657 | } 31658 | else if (!post_bracket_process(token_t::e_lbracket,branch)) 31659 | { 31660 | details::free_node(node_allocator_, branch); 31661 | 31662 | return error_node(); 31663 | } 31664 | 31665 | parse_pending_vector_index_operator(branch); 31666 | } 31667 | else if (token_t::e_lsqrbracket == current_token().type) 31668 | { 31669 | next_token(); 31670 | 31671 | if (0 == (branch = parse_expression())) 31672 | return error_node(); 31673 | else if (!token_is(token_t::e_rsqrbracket)) 31674 | { 31675 | set_error(make_error( 31676 | parser_error::e_syntax, 31677 | current_token(), 31678 | "ERR245 - Expected ']' instead of: '" + current_token().value + "'", 31679 | exprtk_error_location)); 31680 | 31681 | details::free_node(node_allocator_, branch); 31682 | 31683 | return error_node(); 31684 | } 31685 | else if (!post_bracket_process(token_t::e_lsqrbracket,branch)) 31686 | { 31687 | details::free_node(node_allocator_, branch); 31688 | 31689 | return error_node(); 31690 | } 31691 | } 31692 | else if (token_t::e_lcrlbracket == current_token().type) 31693 | { 31694 | next_token(); 31695 | 31696 | if (0 == (branch = parse_expression())) 31697 | return error_node(); 31698 | else if (!token_is(token_t::e_rcrlbracket)) 31699 | { 31700 | set_error(make_error( 31701 | parser_error::e_syntax, 31702 | current_token(), 31703 | "ERR246 - Expected '}' instead of: '" + current_token().value + "'", 31704 | exprtk_error_location)); 31705 | 31706 | details::free_node(node_allocator_, branch); 31707 | 31708 | return error_node(); 31709 | } 31710 | else if (!post_bracket_process(token_t::e_lcrlbracket,branch)) 31711 | { 31712 | details::free_node(node_allocator_, branch); 31713 | 31714 | return error_node(); 31715 | } 31716 | } 31717 | else if (token_t::e_sub == current_token().type) 31718 | { 31719 | next_token(); 31720 | branch = parse_expression(e_level11); 31721 | 31722 | if ( 31723 | branch && 31724 | !( 31725 | details::is_neg_unary_node (branch) && 31726 | simplify_unary_negation_branch(branch) 31727 | ) 31728 | ) 31729 | { 31730 | expression_node_ptr result = expression_generator_(details::e_neg,branch); 31731 | 31732 | if (0 == result) 31733 | { 31734 | details::free_node(node_allocator_, branch); 31735 | 31736 | return error_node(); 31737 | } 31738 | else 31739 | branch = result; 31740 | } 31741 | } 31742 | else if (token_t::e_add == current_token().type) 31743 | { 31744 | next_token(); 31745 | branch = parse_expression(e_level13); 31746 | } 31747 | else if (token_t::e_eof == current_token().type) 31748 | { 31749 | set_error(make_error( 31750 | parser_error::e_syntax, 31751 | current_token(), 31752 | "ERR247 - Premature end of expression[1]", 31753 | exprtk_error_location)); 31754 | 31755 | return error_node(); 31756 | } 31757 | else 31758 | { 31759 | set_error(make_error( 31760 | parser_error::e_syntax, 31761 | current_token(), 31762 | "ERR248 - Premature end of expression[2]", 31763 | exprtk_error_location)); 31764 | 31765 | return error_node(); 31766 | } 31767 | 31768 | if ( 31769 | branch && 31770 | (e_level00 == precedence) && 31771 | token_is(token_t::e_ternary,prsrhlpr_t::e_hold) 31772 | ) 31773 | { 31774 | branch = parse_ternary_conditional_statement(branch); 31775 | } 31776 | 31777 | parse_pending_string_rangesize(branch); 31778 | 31779 | return branch; 31780 | } 31781 | 31782 | template <typename Type> 31783 | class expression_generator 31784 | { 31785 | public: 31786 | 31787 | typedef details::expression_node<Type>* expression_node_ptr; 31788 | typedef expression_node_ptr (*synthesize_functor_t)(expression_generator<T>&, const details::operator_type& operation, expression_node_ptr (&branch)[2]); 31789 | typedef std::map<std::string,synthesize_functor_t> synthesize_map_t; 31790 | typedef typename exprtk::parser<Type> parser_t; 31791 | typedef const Type& vtype; 31792 | typedef const Type ctype; 31793 | 31794 | inline void init_synthesize_map() 31795 | { 31796 | #ifndef exprtk_disable_enhanced_features 31797 | synthesize_map_["(v)o(v)"] = synthesize_vov_expression::process; 31798 | synthesize_map_["(c)o(v)"] = synthesize_cov_expression::process; 31799 | synthesize_map_["(v)o(c)"] = synthesize_voc_expression::process; 31800 | 31801 | #define register_synthezier(S) \ 31802 | synthesize_map_[S ::node_type::id()] = S ::process; \ 31803 | 31804 | register_synthezier(synthesize_vovov_expression0) 31805 | register_synthezier(synthesize_vovov_expression1) 31806 | register_synthezier(synthesize_vovoc_expression0) 31807 | register_synthezier(synthesize_vovoc_expression1) 31808 | register_synthezier(synthesize_vocov_expression0) 31809 | register_synthezier(synthesize_vocov_expression1) 31810 | register_synthezier(synthesize_covov_expression0) 31811 | register_synthezier(synthesize_covov_expression1) 31812 | register_synthezier(synthesize_covoc_expression0) 31813 | register_synthezier(synthesize_covoc_expression1) 31814 | register_synthezier(synthesize_cocov_expression1) 31815 | register_synthezier(synthesize_vococ_expression0) 31816 | 31817 | register_synthezier(synthesize_vovovov_expression0) 31818 | register_synthezier(synthesize_vovovoc_expression0) 31819 | register_synthezier(synthesize_vovocov_expression0) 31820 | register_synthezier(synthesize_vocovov_expression0) 31821 | register_synthezier(synthesize_covovov_expression0) 31822 | register_synthezier(synthesize_covocov_expression0) 31823 | register_synthezier(synthesize_vocovoc_expression0) 31824 | register_synthezier(synthesize_covovoc_expression0) 31825 | register_synthezier(synthesize_vococov_expression0) 31826 | 31827 | register_synthezier(synthesize_vovovov_expression1) 31828 | register_synthezier(synthesize_vovovoc_expression1) 31829 | register_synthezier(synthesize_vovocov_expression1) 31830 | register_synthezier(synthesize_vocovov_expression1) 31831 | register_synthezier(synthesize_covovov_expression1) 31832 | register_synthezier(synthesize_covocov_expression1) 31833 | register_synthezier(synthesize_vocovoc_expression1) 31834 | register_synthezier(synthesize_covovoc_expression1) 31835 | register_synthezier(synthesize_vococov_expression1) 31836 | 31837 | register_synthezier(synthesize_vovovov_expression2) 31838 | register_synthezier(synthesize_vovovoc_expression2) 31839 | register_synthezier(synthesize_vovocov_expression2) 31840 | register_synthezier(synthesize_vocovov_expression2) 31841 | register_synthezier(synthesize_covovov_expression2) 31842 | register_synthezier(synthesize_covocov_expression2) 31843 | register_synthezier(synthesize_vocovoc_expression2) 31844 | register_synthezier(synthesize_covovoc_expression2) 31845 | 31846 | register_synthezier(synthesize_vovovov_expression3) 31847 | register_synthezier(synthesize_vovovoc_expression3) 31848 | register_synthezier(synthesize_vovocov_expression3) 31849 | register_synthezier(synthesize_vocovov_expression3) 31850 | register_synthezier(synthesize_covovov_expression3) 31851 | register_synthezier(synthesize_covocov_expression3) 31852 | register_synthezier(synthesize_vocovoc_expression3) 31853 | register_synthezier(synthesize_covovoc_expression3) 31854 | register_synthezier(synthesize_vococov_expression3) 31855 | 31856 | register_synthezier(synthesize_vovovov_expression4) 31857 | register_synthezier(synthesize_vovovoc_expression4) 31858 | register_synthezier(synthesize_vovocov_expression4) 31859 | register_synthezier(synthesize_vocovov_expression4) 31860 | register_synthezier(synthesize_covovov_expression4) 31861 | register_synthezier(synthesize_covocov_expression4) 31862 | register_synthezier(synthesize_vocovoc_expression4) 31863 | register_synthezier(synthesize_covovoc_expression4) 31864 | 31865 | #undef register_synthezier 31866 | #endif 31867 | } 31868 | 31869 | inline void set_parser(parser_t& p) 31870 | { 31871 | parser_ = &p; 31872 | } 31873 | 31874 | inline void set_uom(unary_op_map_t& unary_op_map) 31875 | { 31876 | unary_op_map_ = &unary_op_map; 31877 | } 31878 | 31879 | inline void set_bom(binary_op_map_t& binary_op_map) 31880 | { 31881 | binary_op_map_ = &binary_op_map; 31882 | } 31883 | 31884 | inline void set_ibom(inv_binary_op_map_t& inv_binary_op_map) 31885 | { 31886 | inv_binary_op_map_ = &inv_binary_op_map; 31887 | } 31888 | 31889 | inline void set_sf3m(sf3_map_t& sf3_map) 31890 | { 31891 | sf3_map_ = &sf3_map; 31892 | } 31893 | 31894 | inline void set_sf4m(sf4_map_t& sf4_map) 31895 | { 31896 | sf4_map_ = &sf4_map; 31897 | } 31898 | 31899 | inline void set_allocator(details::node_allocator& na) 31900 | { 31901 | node_allocator_ = &na; 31902 | } 31903 | 31904 | inline void set_strength_reduction_state(const bool enabled) 31905 | { 31906 | strength_reduction_enabled_ = enabled; 31907 | } 31908 | 31909 | inline bool strength_reduction_enabled() const 31910 | { 31911 | return strength_reduction_enabled_; 31912 | } 31913 | 31914 | inline bool valid_operator(const details::operator_type& operation, binary_functor_t& bop) 31915 | { 31916 | typename binary_op_map_t::iterator bop_itr = binary_op_map_->find(operation); 31917 | 31918 | if (binary_op_map_->end() == bop_itr) 31919 | return false; 31920 | 31921 | bop = bop_itr->second; 31922 | 31923 | return true; 31924 | } 31925 | 31926 | inline bool valid_operator(const details::operator_type& operation, unary_functor_t& uop) 31927 | { 31928 | typename unary_op_map_t::iterator uop_itr = unary_op_map_->find(operation); 31929 | 31930 | if ((*unary_op_map_).end() == uop_itr) 31931 | return false; 31932 | 31933 | uop = uop_itr->second; 31934 | 31935 | return true; 31936 | } 31937 | 31938 | inline details::operator_type get_operator(const binary_functor_t& bop) const 31939 | { 31940 | return (*inv_binary_op_map_).find(bop)->second; 31941 | } 31942 | 31943 | inline expression_node_ptr operator() (const Type& v) const 31944 | { 31945 | return node_allocator_->allocate<literal_node_t>(v); 31946 | } 31947 | 31948 | #ifndef exprtk_disable_string_capabilities 31949 | inline expression_node_ptr operator() (const std::string& s) const 31950 | { 31951 | return node_allocator_->allocate<string_literal_node_t>(s); 31952 | } 31953 | 31954 | inline expression_node_ptr operator() (std::string& s, range_t& rp) const 31955 | { 31956 | return node_allocator_->allocate_rr<string_range_node_t>(s,rp); 31957 | } 31958 | 31959 | inline expression_node_ptr operator() (const std::string& s, range_t& rp) const 31960 | { 31961 | return node_allocator_->allocate_tt<const_string_range_node_t>(s,rp); 31962 | } 31963 | 31964 | inline expression_node_ptr operator() (expression_node_ptr branch, range_t& rp) const 31965 | { 31966 | if (is_generally_string_node(branch)) 31967 | return node_allocator_->allocate_tt<generic_string_range_node_t>(branch,rp); 31968 | else 31969 | return error_node(); 31970 | } 31971 | #endif 31972 | 31973 | inline bool unary_optimisable(const details::operator_type& operation) const 31974 | { 31975 | return (details::e_abs == operation) || (details::e_acos == operation) || 31976 | (details::e_acosh == operation) || (details::e_asin == operation) || 31977 | (details::e_asinh == operation) || (details::e_atan == operation) || 31978 | (details::e_atanh == operation) || (details::e_ceil == operation) || 31979 | (details::e_cos == operation) || (details::e_cosh == operation) || 31980 | (details::e_exp == operation) || (details::e_expm1 == operation) || 31981 | (details::e_floor == operation) || (details::e_log == operation) || 31982 | (details::e_log10 == operation) || (details::e_log2 == operation) || 31983 | (details::e_log1p == operation) || (details::e_neg == operation) || 31984 | (details::e_pos == operation) || (details::e_round == operation) || 31985 | (details::e_sin == operation) || (details::e_sinc == operation) || 31986 | (details::e_sinh == operation) || (details::e_sqrt == operation) || 31987 | (details::e_tan == operation) || (details::e_tanh == operation) || 31988 | (details::e_cot == operation) || (details::e_sec == operation) || 31989 | (details::e_csc == operation) || (details::e_r2d == operation) || 31990 | (details::e_d2r == operation) || (details::e_d2g == operation) || 31991 | (details::e_g2d == operation) || (details::e_notl == operation) || 31992 | (details::e_sgn == operation) || (details::e_erf == operation) || 31993 | (details::e_erfc == operation) || (details::e_ncdf == operation) || 31994 | (details::e_frac == operation) || (details::e_trunc == operation) ; 31995 | } 31996 | 31997 | inline bool sf3_optimisable(const std::string& sf3id, trinary_functor_t& tfunc) const 31998 | { 31999 | typename sf3_map_t::const_iterator itr = sf3_map_->find(sf3id); 32000 | 32001 | if (sf3_map_->end() == itr) 32002 | return false; 32003 | else 32004 | tfunc = itr->second.first; 32005 | 32006 | return true; 32007 | } 32008 | 32009 | inline bool sf4_optimisable(const std::string& sf4id, quaternary_functor_t& qfunc) const 32010 | { 32011 | typename sf4_map_t::const_iterator itr = sf4_map_->find(sf4id); 32012 | 32013 | if (sf4_map_->end() == itr) 32014 | return false; 32015 | else 32016 | qfunc = itr->second.first; 32017 | 32018 | return true; 32019 | } 32020 | 32021 | inline bool sf3_optimisable(const std::string& sf3id, details::operator_type& operation) const 32022 | { 32023 | typename sf3_map_t::const_iterator itr = sf3_map_->find(sf3id); 32024 | 32025 | if (sf3_map_->end() == itr) 32026 | return false; 32027 | else 32028 | operation = itr->second.second; 32029 | 32030 | return true; 32031 | } 32032 | 32033 | inline bool sf4_optimisable(const std::string& sf4id, details::operator_type& operation) const 32034 | { 32035 | typename sf4_map_t::const_iterator itr = sf4_map_->find(sf4id); 32036 | 32037 | if (sf4_map_->end() == itr) 32038 | return false; 32039 | else 32040 | operation = itr->second.second; 32041 | 32042 | return true; 32043 | } 32044 | 32045 | inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[1]) 32046 | { 32047 | if (0 == branch[0]) 32048 | { 32049 | return error_node(); 32050 | } 32051 | else if (details::is_null_node(branch[0])) 32052 | { 32053 | return branch[0]; 32054 | } 32055 | else if (details::is_break_node(branch[0])) 32056 | { 32057 | return error_node(); 32058 | } 32059 | else if (details::is_continue_node(branch[0])) 32060 | { 32061 | return error_node(); 32062 | } 32063 | else if (details::is_constant_node(branch[0])) 32064 | { 32065 | return synthesize_expression<unary_node_t,1>(operation,branch); 32066 | } 32067 | else if (unary_optimisable(operation) && details::is_variable_node(branch[0])) 32068 | { 32069 | return synthesize_uv_expression(operation,branch); 32070 | } 32071 | else if (unary_optimisable(operation) && details::is_ivector_node(branch[0])) 32072 | { 32073 | return synthesize_uvec_expression(operation,branch); 32074 | } 32075 | else 32076 | return synthesize_unary_expression(operation,branch); 32077 | } 32078 | 32079 | inline bool is_assignment_operation(const details::operator_type& operation) const 32080 | { 32081 | return ( 32082 | (details::e_addass == operation) || 32083 | (details::e_subass == operation) || 32084 | (details::e_mulass == operation) || 32085 | (details::e_divass == operation) || 32086 | (details::e_modass == operation) 32087 | ) && 32088 | parser_->settings_.assignment_enabled(operation); 32089 | } 32090 | 32091 | #ifndef exprtk_disable_string_capabilities 32092 | inline bool valid_string_operation(const details::operator_type& operation) const 32093 | { 32094 | return (details::e_add == operation) || 32095 | (details::e_lt == operation) || 32096 | (details::e_lte == operation) || 32097 | (details::e_gt == operation) || 32098 | (details::e_gte == operation) || 32099 | (details::e_eq == operation) || 32100 | (details::e_ne == operation) || 32101 | (details::e_in == operation) || 32102 | (details::e_like == operation) || 32103 | (details::e_ilike == operation) || 32104 | (details::e_assign == operation) || 32105 | (details::e_addass == operation) || 32106 | (details::e_swap == operation) ; 32107 | } 32108 | #else 32109 | inline bool valid_string_operation(const details::operator_type&) const 32110 | { 32111 | return false; 32112 | } 32113 | #endif 32114 | 32115 | inline std::string to_str(const details::operator_type& operation) const 32116 | { 32117 | switch (operation) 32118 | { 32119 | case details::e_add : return "+" ; 32120 | case details::e_sub : return "-" ; 32121 | case details::e_mul : return "*" ; 32122 | case details::e_div : return "/" ; 32123 | case details::e_mod : return "%" ; 32124 | case details::e_pow : return "^" ; 32125 | case details::e_lt : return "<" ; 32126 | case details::e_lte : return "<=" ; 32127 | case details::e_gt : return ">" ; 32128 | case details::e_gte : return ">=" ; 32129 | case details::e_eq : return "==" ; 32130 | case details::e_ne : return "!=" ; 32131 | case details::e_and : return "and" ; 32132 | case details::e_nand : return "nand" ; 32133 | case details::e_or : return "or" ; 32134 | case details::e_nor : return "nor" ; 32135 | case details::e_xor : return "xor" ; 32136 | case details::e_xnor : return "xnor" ; 32137 | default : return "UNKNOWN" 32138 | } 32139 | } 32140 | 32141 | inline bool operation_optimisable(const details::operator_type& operation) const 32142 | { 32143 | return (details::e_add == operation) || 32144 | (details::e_sub == operation) || 32145 | (details::e_mul == operation) || 32146 | (details::e_div == operation) || 32147 | (details::e_mod == operation) || 32148 | (details::e_pow == operation) || 32149 | (details::e_lt == operation) || 32150 | (details::e_lte == operation) || 32151 | (details::e_gt == operation) || 32152 | (details::e_gte == operation) || 32153 | (details::e_eq == operation) || 32154 | (details::e_ne == operation) || 32155 | (details::e_and == operation) || 32156 | (details::e_nand == operation) || 32157 | (details::e_or == operation) || 32158 | (details::e_nor == operation) || 32159 | (details::e_xor == operation) || 32160 | (details::e_xnor == operation) ; 32161 | } 32162 | 32163 | inline std::string branch_to_id(expression_node_ptr branch) const 32164 | { 32165 | static const std::string null_str ("(null)" ); 32166 | static const std::string const_str ("(c)" ); 32167 | static const std::string var_str ("(v)" ); 32168 | static const std::string vov_str ("(vov)" ); 32169 | static const std::string cov_str ("(cov)" ); 32170 | static const std::string voc_str ("(voc)" ); 32171 | static const std::string str_str ("(s)" ); 32172 | static const std::string strrng_str ("(rngs)" ); 32173 | static const std::string cs_str ("(cs)" ); 32174 | static const std::string cstrrng_str("(crngs)"); 32175 | 32176 | if (details::is_null_node(branch)) 32177 | return null_str; 32178 | else if (details::is_constant_node(branch)) 32179 | return const_str; 32180 | else if (details::is_variable_node(branch)) 32181 | return var_str; 32182 | else if (details::is_vov_node(branch)) 32183 | return vov_str; 32184 | else if (details::is_cov_node(branch)) 32185 | return cov_str; 32186 | else if (details::is_voc_node(branch)) 32187 | return voc_str; 32188 | else if (details::is_string_node(branch)) 32189 | return str_str; 32190 | else if (details::is_const_string_node(branch)) 32191 | return cs_str; 32192 | else if (details::is_string_range_node(branch)) 32193 | return strrng_str; 32194 | else if (details::is_const_string_range_node(branch)) 32195 | return cstrrng_str; 32196 | else if (details::is_t0ot1ot2_node(branch)) 32197 | return "(" + dynamic_cast<details::T0oT1oT2_base_node<T>*>(branch)->type_id() + ")" 32198 | else if (details::is_t0ot1ot2ot3_node(branch)) 32199 | return "(" + dynamic_cast<details::T0oT1oT2oT3_base_node<T>*>(branch)->type_id() + ")" 32200 | else 32201 | return "ERROR" 32202 | } 32203 | 32204 | inline std::string branch_to_id(expression_node_ptr (&branch)[2]) const 32205 | { 32206 | return branch_to_id(branch[0]) + std::string("o") + branch_to_id(branch[1]); 32207 | } 32208 | 32209 | inline bool cov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32210 | { 32211 | if (!operation_optimisable(operation)) 32212 | return false; 32213 | else 32214 | return details::is_constant_node(branch[0]) && 32215 | details::is_variable_node(branch[1]) ; 32216 | } 32217 | 32218 | inline bool voc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32219 | { 32220 | if (!operation_optimisable(operation)) 32221 | return false; 32222 | else 32223 | return details::is_variable_node(branch[0]) && 32224 | details::is_constant_node(branch[1]) ; 32225 | } 32226 | 32227 | inline bool vov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32228 | { 32229 | if (!operation_optimisable(operation)) 32230 | return false; 32231 | else 32232 | return details::is_variable_node(branch[0]) && 32233 | details::is_variable_node(branch[1]) ; 32234 | } 32235 | 32236 | inline bool cob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32237 | { 32238 | if (!operation_optimisable(operation)) 32239 | return false; 32240 | else 32241 | return details::is_constant_node(branch[0]) && 32242 | !details::is_constant_node(branch[1]) ; 32243 | } 32244 | 32245 | inline bool boc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32246 | { 32247 | if (!operation_optimisable(operation)) 32248 | return false; 32249 | else 32250 | return !details::is_constant_node(branch[0]) && 32251 | details::is_constant_node(branch[1]) ; 32252 | } 32253 | 32254 | inline bool cocob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32255 | { 32256 | if ( 32257 | (details::e_add == operation) || 32258 | (details::e_sub == operation) || 32259 | (details::e_mul == operation) || 32260 | (details::e_div == operation) 32261 | ) 32262 | { 32263 | return (details::is_constant_node(branch[0]) && details::is_cob_node(branch[1])) || 32264 | (details::is_constant_node(branch[1]) && details::is_cob_node(branch[0])) ; 32265 | } 32266 | else 32267 | return false; 32268 | } 32269 | 32270 | inline bool coboc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32271 | { 32272 | if ( 32273 | (details::e_add == operation) || 32274 | (details::e_sub == operation) || 32275 | (details::e_mul == operation) || 32276 | (details::e_div == operation) 32277 | ) 32278 | { 32279 | return (details::is_constant_node(branch[0]) && details::is_boc_node(branch[1])) || 32280 | (details::is_constant_node(branch[1]) && details::is_boc_node(branch[0])) ; 32281 | } 32282 | else 32283 | return false; 32284 | } 32285 | 32286 | inline bool uvouv_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32287 | { 32288 | if (!operation_optimisable(operation)) 32289 | return false; 32290 | else 32291 | return details::is_uv_node(branch[0]) && 32292 | details::is_uv_node(branch[1]) ; 32293 | } 32294 | 32295 | inline bool vob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32296 | { 32297 | if (!operation_optimisable(operation)) 32298 | return false; 32299 | else 32300 | return details::is_variable_node(branch[0]) && 32301 | !details::is_variable_node(branch[1]) ; 32302 | } 32303 | 32304 | inline bool bov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32305 | { 32306 | if (!operation_optimisable(operation)) 32307 | return false; 32308 | else 32309 | return !details::is_variable_node(branch[0]) && 32310 | details::is_variable_node(branch[1]) ; 32311 | } 32312 | 32313 | inline bool binext_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32314 | { 32315 | if (!operation_optimisable(operation)) 32316 | return false; 32317 | else 32318 | return !details::is_constant_node(branch[0]) || 32319 | !details::is_constant_node(branch[1]) ; 32320 | } 32321 | 32322 | inline bool is_invalid_assignment_op(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32323 | { 32324 | if (is_assignment_operation(operation)) 32325 | { 32326 | const bool b1_is_genstring = details::is_generally_string_node(branch[1]); 32327 | 32328 | if (details::is_string_node(branch[0])) 32329 | return !b1_is_genstring; 32330 | else if (details::is_literal_node(branch[0])) 32331 | return true; 32332 | else 32333 | return ( 32334 | !details::is_variable_node (branch[0]) && 32335 | !details::is_vector_elem_node (branch[0]) && 32336 | !details::is_vector_celem_node (branch[0]) && 32337 | !details::is_vector_elem_rtc_node (branch[0]) && 32338 | !details::is_vector_celem_rtc_node (branch[0]) && 32339 | !details::is_rebasevector_elem_node (branch[0]) && 32340 | !details::is_rebasevector_celem_node (branch[0]) && 32341 | !details::is_rebasevector_elem_rtc_node (branch[0]) && 32342 | !details::is_rebasevector_celem_rtc_node(branch[0]) && 32343 | !details::is_vector_node (branch[0]) 32344 | ) 32345 | || b1_is_genstring; 32346 | } 32347 | else 32348 | return false; 32349 | } 32350 | 32351 | inline bool is_constpow_operation(const details::operator_type& operation, expression_node_ptr(&branch)[2]) const 32352 | { 32353 | if ( 32354 | !details::is_constant_node(branch[1]) || 32355 | details::is_constant_node(branch[0]) || 32356 | details::is_variable_node(branch[0]) || 32357 | details::is_vector_node (branch[0]) || 32358 | details::is_generally_string_node(branch[0]) 32359 | ) 32360 | return false; 32361 | 32362 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 32363 | 32364 | return cardinal_pow_optimisable(operation, c); 32365 | } 32366 | 32367 | inline bool is_invalid_break_continue_op(expression_node_ptr (&branch)[2]) const 32368 | { 32369 | return ( 32370 | details::is_break_node (branch[0]) || 32371 | details::is_break_node (branch[1]) || 32372 | details::is_continue_node(branch[0]) || 32373 | details::is_continue_node(branch[1]) 32374 | ); 32375 | } 32376 | 32377 | inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32378 | { 32379 | const bool b0_string = is_generally_string_node(branch[0]); 32380 | const bool b1_string = is_generally_string_node(branch[1]); 32381 | 32382 | bool result = false; 32383 | 32384 | if (b0_string != b1_string) 32385 | result = true; 32386 | else if (!valid_string_operation(operation) && b0_string && b1_string) 32387 | result = true; 32388 | 32389 | if (result) 32390 | { 32391 | parser_->set_synthesis_error("Invalid string operation"); 32392 | } 32393 | 32394 | return result; 32395 | } 32396 | 32397 | inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[3]) const 32398 | { 32399 | const bool b0_string = is_generally_string_node(branch[0]); 32400 | const bool b1_string = is_generally_string_node(branch[1]); 32401 | const bool b2_string = is_generally_string_node(branch[2]); 32402 | 32403 | bool result = false; 32404 | 32405 | if ((b0_string != b1_string) || (b1_string != b2_string)) 32406 | result = true; 32407 | else if ((details::e_inrange != operation) && b0_string && b1_string && b2_string) 32408 | result = true; 32409 | 32410 | if (result) 32411 | { 32412 | parser_->set_synthesis_error("Invalid string operation"); 32413 | } 32414 | 32415 | return result; 32416 | } 32417 | 32418 | inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32419 | { 32420 | const bool b0_string = is_generally_string_node(branch[0]); 32421 | const bool b1_string = is_generally_string_node(branch[1]); 32422 | 32423 | return (b0_string && b1_string && valid_string_operation(operation)); 32424 | } 32425 | 32426 | inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[3]) const 32427 | { 32428 | const bool b0_string = is_generally_string_node(branch[0]); 32429 | const bool b1_string = is_generally_string_node(branch[1]); 32430 | const bool b2_string = is_generally_string_node(branch[2]); 32431 | 32432 | return (b0_string && b1_string && b2_string && (details::e_inrange == operation)); 32433 | } 32434 | 32435 | #ifndef exprtk_disable_sc_andor 32436 | inline bool is_shortcircuit_expression(const details::operator_type& operation) const 32437 | { 32438 | return ( 32439 | (details::e_scand == operation) || 32440 | (details::e_scor == operation) 32441 | ); 32442 | } 32443 | #else 32444 | inline bool is_shortcircuit_expression(const details::operator_type&) const 32445 | { 32446 | return false; 32447 | } 32448 | #endif 32449 | 32450 | inline bool is_null_present(expression_node_ptr (&branch)[2]) const 32451 | { 32452 | return ( 32453 | details::is_null_node(branch[0]) || 32454 | details::is_null_node(branch[1]) 32455 | ); 32456 | } 32457 | 32458 | inline bool is_vector_eqineq_logic_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32459 | { 32460 | if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1])) 32461 | return false; 32462 | else 32463 | return ( 32464 | (details::e_lt == operation) || 32465 | (details::e_lte == operation) || 32466 | (details::e_gt == operation) || 32467 | (details::e_gte == operation) || 32468 | (details::e_eq == operation) || 32469 | (details::e_ne == operation) || 32470 | (details::e_equal == operation) || 32471 | (details::e_and == operation) || 32472 | (details::e_nand == operation) || 32473 | (details::e_or == operation) || 32474 | (details::e_nor == operation) || 32475 | (details::e_xor == operation) || 32476 | (details::e_xnor == operation) 32477 | ); 32478 | } 32479 | 32480 | inline bool is_vector_arithmetic_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32481 | { 32482 | if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1])) 32483 | return false; 32484 | else 32485 | return ( 32486 | (details::e_add == operation) || 32487 | (details::e_sub == operation) || 32488 | (details::e_mul == operation) || 32489 | (details::e_div == operation) || 32490 | (details::e_pow == operation) 32491 | ); 32492 | } 32493 | 32494 | inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[2]) 32495 | { 32496 | if ((0 == branch[0]) || (0 == branch[1])) 32497 | { 32498 | parser_->set_error(parser_error::make_error( 32499 | parser_error::e_syntax, 32500 | parser_->current_state().token, 32501 | "ERR249 - Invalid branches received for operator '" + details::to_str(operation) + "'", 32502 | exprtk_error_location)); 32503 | 32504 | return error_node(); 32505 | } 32506 | else if (is_invalid_string_op(operation,branch)) 32507 | { 32508 | parser_->set_error(parser_error::make_error( 32509 | parser_error::e_syntax, 32510 | parser_->current_state().token, 32511 | "ERR250 - Invalid branch pair for string operator '" + details::to_str(operation) + "'", 32512 | exprtk_error_location)); 32513 | 32514 | return error_node(); 32515 | } 32516 | else if (is_invalid_assignment_op(operation,branch)) 32517 | { 32518 | parser_->set_error(parser_error::make_error( 32519 | parser_error::e_syntax, 32520 | parser_->current_state().token, 32521 | "ERR251 - Invalid branch pair for assignment operator '" + details::to_str(operation) + "'", 32522 | exprtk_error_location)); 32523 | 32524 | return error_node(); 32525 | } 32526 | else if (is_invalid_break_continue_op(branch)) 32527 | { 32528 | parser_->set_error(parser_error::make_error( 32529 | parser_error::e_syntax, 32530 | parser_->current_state().token, 32531 | "ERR252 - Invalid branch pair for break/continue operator '" + details::to_str(operation) + "'", 32532 | exprtk_error_location)); 32533 | 32534 | return error_node(); 32535 | } 32536 | else if (details::e_assign == operation) 32537 | { 32538 | return synthesize_assignment_expression(operation, branch); 32539 | } 32540 | else if (details::e_swap == operation) 32541 | { 32542 | return synthesize_swap_expression(branch); 32543 | } 32544 | else if (is_assignment_operation(operation)) 32545 | { 32546 | return synthesize_assignment_operation_expression(operation, branch); 32547 | } 32548 | else if (is_vector_eqineq_logic_operation(operation, branch)) 32549 | { 32550 | return synthesize_veceqineqlogic_operation_expression(operation, branch); 32551 | } 32552 | else if (is_vector_arithmetic_operation(operation, branch)) 32553 | { 32554 | return synthesize_vecarithmetic_operation_expression(operation, branch); 32555 | } 32556 | else if (is_shortcircuit_expression(operation)) 32557 | { 32558 | return synthesize_shortcircuit_expression(operation, branch); 32559 | } 32560 | else if (is_string_operation(operation, branch)) 32561 | { 32562 | return synthesize_string_expression(operation, branch); 32563 | } 32564 | else if (is_null_present(branch)) 32565 | { 32566 | return synthesize_null_expression(operation, branch); 32567 | } 32568 | #ifndef exprtk_disable_cardinal_pow_optimisation 32569 | else if (is_constpow_operation(operation, branch)) 32570 | { 32571 | return cardinal_pow_optimisation(branch); 32572 | } 32573 | #endif 32574 | 32575 | expression_node_ptr result = error_node(); 32576 | 32577 | #ifndef exprtk_disable_enhanced_features 32578 | if (synthesize_expression(operation, branch, result)) 32579 | { 32580 | return result; 32581 | } 32582 | else 32583 | #endif 32584 | 32585 | { 32586 | /* 32587 | Possible reductions: 32588 | 1. c o cob -> cob 32589 | 2. cob o c -> cob 32590 | 3. c o boc -> boc 32591 | 4. boc o c -> boc 32592 | */ 32593 | result = error_node(); 32594 | 32595 | if (cocob_optimisable(operation, branch)) 32596 | { 32597 | result = synthesize_cocob_expression::process((*this), operation, branch); 32598 | } 32599 | else if (coboc_optimisable(operation, branch) && (0 == result)) 32600 | { 32601 | result = synthesize_coboc_expression::process((*this), operation, branch); 32602 | } 32603 | 32604 | if (result) 32605 | return result; 32606 | } 32607 | 32608 | if (uvouv_optimisable(operation, branch)) 32609 | { 32610 | return synthesize_uvouv_expression(operation, branch); 32611 | } 32612 | else if (vob_optimisable(operation, branch)) 32613 | { 32614 | return synthesize_vob_expression::process((*this), operation, branch); 32615 | } 32616 | else if (bov_optimisable(operation, branch)) 32617 | { 32618 | return synthesize_bov_expression::process((*this), operation, branch); 32619 | } 32620 | else if (cob_optimisable(operation, branch)) 32621 | { 32622 | return synthesize_cob_expression::process((*this), operation, branch); 32623 | } 32624 | else if (boc_optimisable(operation, branch)) 32625 | { 32626 | return synthesize_boc_expression::process((*this), operation, branch); 32627 | } 32628 | #ifndef exprtk_disable_enhanced_features 32629 | else if (cov_optimisable(operation, branch)) 32630 | { 32631 | return synthesize_cov_expression::process((*this), operation, branch); 32632 | } 32633 | #endif 32634 | else if (binext_optimisable(operation, branch)) 32635 | { 32636 | return synthesize_binary_ext_expression::process((*this), operation, branch); 32637 | } 32638 | else 32639 | return synthesize_expression<binary_node_t,2>(operation, branch); 32640 | } 32641 | 32642 | inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[3]) 32643 | { 32644 | if ( 32645 | (0 == branch[0]) || 32646 | (0 == branch[1]) || 32647 | (0 == branch[2]) 32648 | ) 32649 | { 32650 | details::free_all_nodes(*node_allocator_,branch); 32651 | 32652 | parser_->set_error(parser_error::make_error( 32653 | parser_error::e_syntax, 32654 | parser_->current_state().token, 32655 | "ERR253 - Invalid branches operator '" + details::to_str(operation) + "'", 32656 | exprtk_error_location)); 32657 | 32658 | return error_node(); 32659 | } 32660 | else if (is_invalid_string_op(operation, branch)) 32661 | { 32662 | parser_->set_error(parser_error::make_error( 32663 | parser_error::e_syntax, 32664 | parser_->current_state().token, 32665 | "ERR254 - Invalid branches for string operator '" + details::to_str(operation) + "'", 32666 | exprtk_error_location)); 32667 | 32668 | return error_node(); 32669 | } 32670 | else if (is_string_operation(operation, branch)) 32671 | { 32672 | return synthesize_string_expression(operation, branch); 32673 | } 32674 | else 32675 | return synthesize_expression<trinary_node_t,3>(operation, branch); 32676 | } 32677 | 32678 | inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[4]) 32679 | { 32680 | return synthesize_expression<quaternary_node_t,4>(operation,branch); 32681 | } 32682 | 32683 | inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr b0) 32684 | { 32685 | expression_node_ptr branch[1] = { b0 }; 32686 | return (*this)(operation,branch); 32687 | } 32688 | 32689 | inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr& b0, expression_node_ptr& b1) 32690 | { 32691 | expression_node_ptr result = error_node(); 32692 | 32693 | if ((0 != b0) && (0 != b1)) 32694 | { 32695 | expression_node_ptr branch[2] = { b0, b1 }; 32696 | result = expression_generator<Type>::operator()(operation, branch); 32697 | b0 = branch[0]; 32698 | b1 = branch[1]; 32699 | } 32700 | 32701 | return result; 32702 | } 32703 | 32704 | inline expression_node_ptr conditional(expression_node_ptr condition, 32705 | expression_node_ptr consequent, 32706 | expression_node_ptr alternative) const 32707 | { 32708 | if ((0 == condition) || (0 == consequent)) 32709 | { 32710 | details::free_node(*node_allocator_, condition ); 32711 | details::free_node(*node_allocator_, consequent ); 32712 | details::free_node(*node_allocator_, alternative); 32713 | 32714 | const std::string invalid_branches = 32715 | ((0 == condition ) ? std::string("condition ") : "") + 32716 | ((0 == consequent) ? std::string("consequent") : "") ; 32717 | 32718 | parser_->set_error(parser_error::make_error( 32719 | parser_error::e_parser, 32720 | parser_->current_state().token, 32721 | "ERR255 - Invalid " + invalid_branches + " for conditional statement", 32722 | exprtk_error_location)); 32723 | 32724 | return error_node(); 32725 | } 32726 | // Can the condition be immediately evaluated? if so optimise. 32727 | else if (details::is_constant_node(condition)) 32728 | { 32729 | // True branch 32730 | if (details::is_true(condition)) 32731 | { 32732 | details::free_node(*node_allocator_, condition ); 32733 | details::free_node(*node_allocator_, alternative); 32734 | 32735 | return consequent; 32736 | } 32737 | // False branch 32738 | else 32739 | { 32740 | details::free_node(*node_allocator_, condition ); 32741 | details::free_node(*node_allocator_, consequent); 32742 | 32743 | if (alternative) 32744 | return alternative; 32745 | else 32746 | return node_allocator_->allocate<details::null_node<T> >(); 32747 | } 32748 | } 32749 | 32750 | expression_node_ptr result = error_node(); 32751 | std::string node_name = "Unknown!" 32752 | 32753 | if ((0 != consequent) && (0 != alternative)) 32754 | { 32755 | result = node_allocator_->allocate<conditional_node_t>(condition, consequent, alternative); 32756 | node_name = "conditional_node_t" 32757 | } 32758 | else 32759 | { 32760 | result = node_allocator_->allocate<cons_conditional_node_t>(condition, consequent); 32761 | node_name = "cons_conditional_node_t" 32762 | } 32763 | 32764 | if (result && result->valid()) 32765 | { 32766 | return result; 32767 | } 32768 | 32769 | parser_->set_error(parser_error::make_error( 32770 | parser_error::e_parser, 32771 | token_t(), 32772 | "ERR256 - Failed to synthesize node: " + node_name, 32773 | exprtk_error_location)); 32774 | 32775 | details::free_node(*node_allocator_, result); 32776 | return error_node(); 32777 | } 32778 | 32779 | #ifndef exprtk_disable_string_capabilities 32780 | inline expression_node_ptr conditional_string(expression_node_ptr condition, 32781 | expression_node_ptr consequent, 32782 | expression_node_ptr alternative) const 32783 | { 32784 | if ((0 == condition) || (0 == consequent)) 32785 | { 32786 | details::free_node(*node_allocator_, condition ); 32787 | details::free_node(*node_allocator_, consequent ); 32788 | details::free_node(*node_allocator_, alternative); 32789 | 32790 | const std::string invalid_branches = 32791 | ((0 == condition ) ? std::string("condition ") : "") + 32792 | ((0 == consequent) ? std::string("consequent") : "") ; 32793 | 32794 | parser_->set_error(parser_error::make_error( 32795 | parser_error::e_parser, 32796 | parser_->current_state().token, 32797 | "ERR257 - Invalid " + invalid_branches + " for string conditional statement", 32798 | exprtk_error_location)); 32799 | 32800 | return error_node(); 32801 | } 32802 | // Can the condition be immediately evaluated? if so optimise. 32803 | else if (details::is_constant_node(condition)) 32804 | { 32805 | // True branch 32806 | if (details::is_true(condition)) 32807 | { 32808 | details::free_node(*node_allocator_, condition ); 32809 | details::free_node(*node_allocator_, alternative); 32810 | 32811 | return consequent; 32812 | } 32813 | // False branch 32814 | else 32815 | { 32816 | details::free_node(*node_allocator_, condition ); 32817 | details::free_node(*node_allocator_, consequent); 32818 | 32819 | if (alternative) 32820 | return alternative; 32821 | else 32822 | return node_allocator_-> 32823 | allocate_c<details::string_literal_node<Type> >(""); 32824 | } 32825 | } 32826 | else if ((0 != consequent) && (0 != alternative)) 32827 | { 32828 | expression_node_ptr result = 32829 | node_allocator_->allocate<conditional_string_node_t>(condition, consequent, alternative); 32830 | 32831 | if (result && result->valid()) 32832 | { 32833 | return result; 32834 | } 32835 | 32836 | parser_->set_error(parser_error::make_error( 32837 | parser_error::e_parser, 32838 | token_t(), 32839 | "ERR258 - Failed to synthesize node: conditional_string_node_t", 32840 | exprtk_error_location)); 32841 | 32842 | details::free_node(*node_allocator_, result); 32843 | } 32844 | 32845 | return error_node(); 32846 | } 32847 | #else 32848 | inline expression_node_ptr conditional_string(expression_node_ptr, 32849 | expression_node_ptr, 32850 | expression_node_ptr) const 32851 | { 32852 | return error_node(); 32853 | } 32854 | #endif 32855 | 32856 | inline expression_node_ptr conditional_vector(expression_node_ptr condition, 32857 | expression_node_ptr consequent, 32858 | expression_node_ptr alternative) const 32859 | { 32860 | if ((0 == condition) || (0 == consequent)) 32861 | { 32862 | details::free_node(*node_allocator_, condition ); 32863 | details::free_node(*node_allocator_, consequent ); 32864 | details::free_node(*node_allocator_, alternative); 32865 | 32866 | const std::string invalid_branches = 32867 | ((0 == condition ) ? std::string("condition ") : "") + 32868 | ((0 == consequent) ? std::string("consequent") : "") ; 32869 | 32870 | parser_->set_error(parser_error::make_error( 32871 | parser_error::e_parser, 32872 | parser_->current_state().token, 32873 | "ERR259 - Invalid " + invalid_branches + " for vector conditional statement", 32874 | exprtk_error_location)); 32875 | 32876 | return error_node(); 32877 | } 32878 | // Can the condition be immediately evaluated? if so optimise. 32879 | else if (details::is_constant_node(condition)) 32880 | { 32881 | // True branch 32882 | if (details::is_true(condition)) 32883 | { 32884 | details::free_node(*node_allocator_, condition ); 32885 | details::free_node(*node_allocator_, alternative); 32886 | 32887 | return consequent; 32888 | } 32889 | // False branch 32890 | else 32891 | { 32892 | details::free_node(*node_allocator_, condition ); 32893 | details::free_node(*node_allocator_, consequent); 32894 | 32895 | if (alternative) 32896 | return alternative; 32897 | else 32898 | return node_allocator_->allocate<details::null_node<T> >(); 32899 | 32900 | } 32901 | } 32902 | else if ((0 != consequent) && (0 != alternative)) 32903 | { 32904 | return node_allocator_-> 32905 | allocate<conditional_vector_node_t>(condition, consequent, alternative); 32906 | } 32907 | else 32908 | return error_node(); 32909 | } 32910 | 32911 | inline loop_runtime_check_ptr get_loop_runtime_check(const loop_runtime_check::loop_types loop_type) const 32912 | { 32913 | if ( 32914 | parser_->loop_runtime_check_ && 32915 | (loop_type == (parser_->loop_runtime_check_->loop_set & loop_type)) 32916 | ) 32917 | { 32918 | return parser_->loop_runtime_check_; 32919 | } 32920 | 32921 | return loop_runtime_check_ptr(0); 32922 | } 32923 | 32924 | inline vector_access_runtime_check_ptr get_vector_access_runtime_check() const 32925 | { 32926 | return parser_->vector_access_runtime_check_; 32927 | } 32928 | 32929 | inline expression_node_ptr while_loop(expression_node_ptr& condition, 32930 | expression_node_ptr& branch, 32931 | const bool break_continue_present = false) const 32932 | { 32933 | if ( 32934 | !break_continue_present && 32935 | !parser_->state_.return_stmt_present && 32936 | details::is_constant_node(condition) 32937 | ) 32938 | { 32939 | expression_node_ptr result = error_node(); 32940 | if (details::is_true(condition)) 32941 | { 32942 | // Infinite loops are not allowed. 32943 | 32944 | parser_->set_error(parser_error::make_error( 32945 | parser_error::e_parser, 32946 | parser_->current_state().token, 32947 | "ERR260 - Infinite loop condition without 'break' or 'return' not allowed in while-loops", 32948 | exprtk_error_location)); 32949 | 32950 | result = error_node(); 32951 | } 32952 | else 32953 | result = node_allocator_->allocate<details::null_node<Type> >(); 32954 | 32955 | details::free_node(*node_allocator_, condition); 32956 | details::free_node(*node_allocator_, branch ); 32957 | 32958 | return result; 32959 | } 32960 | else if (details::is_null_node(condition)) 32961 | { 32962 | details::free_node(*node_allocator_,condition); 32963 | 32964 | return branch; 32965 | } 32966 | 32967 | loop_runtime_check_ptr rtc = get_loop_runtime_check(loop_runtime_check::e_while_loop); 32968 | 32969 | if (!break_continue_present) 32970 | { 32971 | if (rtc) 32972 | return node_allocator_->allocate<while_loop_rtc_node_t> 32973 | (condition, branch, rtc); 32974 | else 32975 | return node_allocator_->allocate<while_loop_node_t> 32976 | (condition, branch); 32977 | } 32978 | #ifndef exprtk_disable_break_continue 32979 | else 32980 | { 32981 | if (rtc) 32982 | return node_allocator_->allocate<while_loop_bc_rtc_node_t> 32983 | (condition, branch, rtc); 32984 | else 32985 | return node_allocator_->allocate<while_loop_bc_node_t> 32986 | (condition, branch); 32987 | } 32988 | #else 32989 | return error_node(); 32990 | #endif 32991 | } 32992 | 32993 | inline expression_node_ptr repeat_until_loop(expression_node_ptr& condition, 32994 | expression_node_ptr& branch, 32995 | const bool break_continue_present = false) const 32996 | { 32997 | if (!break_continue_present && details::is_constant_node(condition)) 32998 | { 32999 | if ( 33000 | details::is_true(condition) && 33001 | details::is_constant_node(branch) 33002 | ) 33003 | { 33004 | free_node(*node_allocator_,condition); 33005 | 33006 | return branch; 33007 | } 33008 | 33009 | details::free_node(*node_allocator_, condition); 33010 | details::free_node(*node_allocator_, branch ); 33011 | 33012 | return error_node(); 33013 | } 33014 | else if (details::is_null_node(condition)) 33015 | { 33016 | details::free_node(*node_allocator_,condition); 33017 | 33018 | return branch; 33019 | } 33020 | 33021 | loop_runtime_check_ptr rtc = get_loop_runtime_check(loop_runtime_check::e_repeat_until_loop); 33022 | 33023 | if (!break_continue_present) 33024 | { 33025 | if (rtc) 33026 | return node_allocator_->allocate<repeat_until_loop_rtc_node_t> 33027 | (condition, branch, rtc); 33028 | else 33029 | return node_allocator_->allocate<repeat_until_loop_node_t> 33030 | (condition, branch); 33031 | } 33032 | #ifndef exprtk_disable_break_continue 33033 | else 33034 | { 33035 | if (rtc) 33036 | return node_allocator_->allocate<repeat_until_loop_bc_rtc_node_t> 33037 | (condition, branch, rtc); 33038 | else 33039 | return node_allocator_->allocate<repeat_until_loop_bc_node_t> 33040 | (condition, branch); 33041 | } 33042 | #else 33043 | return error_node(); 33044 | #endif 33045 | } 33046 | 33047 | inline expression_node_ptr for_loop(expression_node_ptr& initialiser, 33048 | expression_node_ptr& condition, 33049 | expression_node_ptr& incrementor, 33050 | expression_node_ptr& loop_body, 33051 | bool break_continue_present = false) const 33052 | { 33053 | if ( 33054 | !break_continue_present && 33055 | !parser_->state_.return_stmt_present && 33056 | details::is_constant_node(condition) 33057 | ) 33058 | { 33059 | expression_node_ptr result = error_node(); 33060 | 33061 | if (details::is_true(condition)) 33062 | { 33063 | // Infinite loops are not allowed. 33064 | 33065 | parser_->set_error(parser_error::make_error( 33066 | parser_error::e_parser, 33067 | parser_->current_state().token, 33068 | "ERR261 - Infinite loop condition without 'break' or 'return' not allowed in for-loop", 33069 | exprtk_error_location)); 33070 | 33071 | result = error_node(); 33072 | } 33073 | else 33074 | result = node_allocator_->allocate<details::null_node<Type> >(); 33075 | 33076 | details::free_node(*node_allocator_, initialiser); 33077 | details::free_node(*node_allocator_, condition ); 33078 | details::free_node(*node_allocator_, incrementor); 33079 | details::free_node(*node_allocator_, loop_body ); 33080 | 33081 | return result; 33082 | } 33083 | else if (details::is_null_node(condition) || (0 == condition)) 33084 | { 33085 | details::free_node(*node_allocator_, initialiser); 33086 | details::free_node(*node_allocator_, condition ); 33087 | details::free_node(*node_allocator_, incrementor); 33088 | 33089 | return loop_body; 33090 | } 33091 | 33092 | loop_runtime_check_ptr rtc = get_loop_runtime_check(loop_runtime_check::e_for_loop); 33093 | 33094 | if (!break_continue_present) 33095 | { 33096 | if (rtc) 33097 | return node_allocator_->allocate<for_loop_rtc_node_t> 33098 | ( 33099 | initialiser, 33100 | condition, 33101 | incrementor, 33102 | loop_body, 33103 | rtc 33104 | ); 33105 | else 33106 | return node_allocator_->allocate<for_loop_node_t> 33107 | ( 33108 | initialiser, 33109 | condition, 33110 | incrementor, 33111 | loop_body 33112 | ); 33113 | } 33114 | #ifndef exprtk_disable_break_continue 33115 | else 33116 | { 33117 | if (rtc) 33118 | return node_allocator_->allocate<for_loop_bc_rtc_node_t> 33119 | ( 33120 | initialiser, 33121 | condition, 33122 | incrementor, 33123 | loop_body, 33124 | rtc 33125 | ); 33126 | else 33127 | return node_allocator_->allocate<for_loop_bc_node_t> 33128 | ( 33129 | initialiser, 33130 | condition, 33131 | incrementor, 33132 | loop_body 33133 | ); 33134 | } 33135 | #else 33136 | return error_node(); 33137 | #endif 33138 | } 33139 | 33140 | template <typename Allocator, 33141 | template <typename, typename> class Sequence> 33142 | inline expression_node_ptr const_optimise_switch(Sequence<expression_node_ptr,Allocator>& arg_list) 33143 | { 33144 | expression_node_ptr result = error_node(); 33145 | 33146 | for (std::size_t i = 0; i < (arg_list.size() / 2); ++i) 33147 | { 33148 | expression_node_ptr condition = arg_list[(2 * i) ]; 33149 | expression_node_ptr consequent = arg_list[(2 * i) + 1]; 33150 | 33151 | if ((0 == result) && details::is_true(condition)) 33152 | { 33153 | result = consequent; 33154 | break; 33155 | } 33156 | } 33157 | 33158 | if (0 == result) 33159 | { 33160 | result = arg_list.back(); 33161 | } 33162 | 33163 | for (std::size_t i = 0; i < arg_list.size(); ++i) 33164 | { 33165 | expression_node_ptr current_expr = arg_list[i]; 33166 | 33167 | if (current_expr && (current_expr != result)) 33168 | { 33169 | free_node(*node_allocator_,current_expr); 33170 | } 33171 | } 33172 | 33173 | return result; 33174 | } 33175 | 33176 | template <typename Allocator, 33177 | template <typename, typename> class Sequence> 33178 | inline expression_node_ptr const_optimise_mswitch(Sequence<expression_node_ptr,Allocator>& arg_list) 33179 | { 33180 | expression_node_ptr result = error_node(); 33181 | 33182 | for (std::size_t i = 0; i < (arg_list.size() / 2); ++i) 33183 | { 33184 | expression_node_ptr condition = arg_list[(2 * i) ]; 33185 | expression_node_ptr consequent = arg_list[(2 * i) + 1]; 33186 | 33187 | if (details::is_true(condition)) 33188 | { 33189 | result = consequent; 33190 | } 33191 | } 33192 | 33193 | if (0 == result) 33194 | { 33195 | const T zero = T(0); 33196 | result = node_allocator_->allocate<literal_node_t>(zero); 33197 | } 33198 | 33199 | for (std::size_t i = 0; i < arg_list.size(); ++i) 33200 | { 33201 | expression_node_ptr& current_expr = arg_list[i]; 33202 | 33203 | if (current_expr && (current_expr != result)) 33204 | { 33205 | details::free_node(*node_allocator_,current_expr); 33206 | } 33207 | } 33208 | 33209 | return result; 33210 | } 33211 | 33212 | struct switch_nodes 33213 | { 33214 | typedef std::vector<std::pair<expression_node_ptr,bool> > arg_list_t; 33215 | 33216 | #define case_stmt(N) \ 33217 | if (is_true(arg[(2 * N)].first)) { return arg[(2 * N) + 1].first->value(); } \ 33218 | 33219 | struct switch_impl_1 33220 | { 33221 | static inline T process(const arg_list_t& arg) 33222 | { 33223 | case_stmt(0) 33224 | 33225 | assert(arg.size() == ((2 * 1) + 1)); 33226 | 33227 | return arg.back().first->value(); 33228 | } 33229 | }; 33230 | 33231 | struct switch_impl_2 33232 | { 33233 | static inline T process(const arg_list_t& arg) 33234 | { 33235 | case_stmt(0) case_stmt(1) 33236 | 33237 | assert(arg.size() == ((2 * 2) + 1)); 33238 | 33239 | return arg.back().first->value(); 33240 | } 33241 | }; 33242 | 33243 | struct switch_impl_3 33244 | { 33245 | static inline T process(const arg_list_t& arg) 33246 | { 33247 | case_stmt(0) case_stmt(1) 33248 | case_stmt(2) 33249 | 33250 | assert(arg.size() == ((2 * 3) + 1)); 33251 | 33252 | return arg.back().first->value(); 33253 | } 33254 | }; 33255 | 33256 | struct switch_impl_4 33257 | { 33258 | static inline T process(const arg_list_t& arg) 33259 | { 33260 | case_stmt(0) case_stmt(1) 33261 | case_stmt(2) case_stmt(3) 33262 | 33263 | assert(arg.size() == ((2 * 4) + 1)); 33264 | 33265 | return arg.back().first->value(); 33266 | } 33267 | }; 33268 | 33269 | struct switch_impl_5 33270 | { 33271 | static inline T process(const arg_list_t& arg) 33272 | { 33273 | case_stmt(0) case_stmt(1) 33274 | case_stmt(2) case_stmt(3) 33275 | case_stmt(4) 33276 | 33277 | assert(arg.size() == ((2 * 5) + 1)); 33278 | 33279 | return arg.back().first->value(); 33280 | } 33281 | }; 33282 | 33283 | struct switch_impl_6 33284 | { 33285 | static inline T process(const arg_list_t& arg) 33286 | { 33287 | case_stmt(0) case_stmt(1) 33288 | case_stmt(2) case_stmt(3) 33289 | case_stmt(4) case_stmt(5) 33290 | 33291 | assert(arg.size() == ((2 * 6) + 1)); 33292 | 33293 | return arg.back().first->value(); 33294 | } 33295 | }; 33296 | 33297 | struct switch_impl_7 33298 | { 33299 | static inline T process(const arg_list_t& arg) 33300 | { 33301 | case_stmt(0) case_stmt(1) 33302 | case_stmt(2) case_stmt(3) 33303 | case_stmt(4) case_stmt(5) 33304 | case_stmt(6) 33305 | 33306 | assert(arg.size() == ((2 * 7) + 1)); 33307 | 33308 | return arg.back().first->value(); 33309 | } 33310 | }; 33311 | 33312 | #undef case_stmt 33313 | }; 33314 | 33315 | template <typename Allocator, 33316 | template <typename, typename> class Sequence> 33317 | inline expression_node_ptr switch_statement(Sequence<expression_node_ptr,Allocator>& arg_list, const bool default_statement_present) 33318 | { 33319 | if (arg_list.empty()) 33320 | return error_node(); 33321 | else if ( 33322 | !all_nodes_valid(arg_list) || 33323 | (!default_statement_present && (arg_list.size() < 2)) 33324 | ) 33325 | { 33326 | details::free_all_nodes(*node_allocator_,arg_list); 33327 | 33328 | return error_node(); 33329 | } 33330 | else if (is_constant_foldable(arg_list)) 33331 | return const_optimise_switch(arg_list); 33332 | 33333 | switch ((arg_list.size() - 1) / 2) 33334 | { 33335 | #define case_stmt(N) \ 33336 | case N : \ 33337 | return node_allocator_-> \ 33338 | allocate<details::switch_n_node \ 33339 | <Type,typename switch_nodes::switch_impl_##N > >(arg_list); \ 33340 | 33341 | case_stmt(1) 33342 | case_stmt(2) 33343 | case_stmt(3) 33344 | case_stmt(4) 33345 | case_stmt(5) 33346 | case_stmt(6) 33347 | case_stmt(7) 33348 | #undef case_stmt 33349 | 33350 | default : return node_allocator_->allocate<details::switch_node<Type> >(arg_list); 33351 | } 33352 | } 33353 | 33354 | template <typename Allocator, 33355 | template <typename, typename> class Sequence> 33356 | inline expression_node_ptr multi_switch_statement(Sequence<expression_node_ptr,Allocator>& arg_list) 33357 | { 33358 | if (!all_nodes_valid(arg_list)) 33359 | { 33360 | details::free_all_nodes(*node_allocator_,arg_list); 33361 | 33362 | return error_node(); 33363 | } 33364 | else if (is_constant_foldable(arg_list)) 33365 | return const_optimise_mswitch(arg_list); 33366 | else 33367 | return node_allocator_->allocate<details::multi_switch_node<Type> >(arg_list); 33368 | } 33369 | 33370 | inline expression_node_ptr assert_call(expression_node_ptr& assert_condition, 33371 | expression_node_ptr& assert_message, 33372 | const assert_check::assert_context& context) 33373 | { 33374 | typedef details::assert_node<Type> alloc_type; 33375 | 33376 | expression_node_ptr result = node_allocator_->allocate_rrrr<alloc_type> 33377 | (assert_condition, assert_message, parser_->assert_check_, context); 33378 | 33379 | if (result && result->valid()) 33380 | { 33381 | parser_->state_.activate_side_effect("assert_call()"); 33382 | return result; 33383 | } 33384 | 33385 | details::free_node(*node_allocator_, result ); 33386 | details::free_node(*node_allocator_, assert_condition); 33387 | details::free_node(*node_allocator_, assert_message ); 33388 | 33389 | return error_node(); 33390 | } 33391 | 33392 | #define unary_opr_switch_statements \ 33393 | case_stmt(details::e_abs , details::abs_op ) \ 33394 | case_stmt(details::e_acos , details::acos_op ) \ 33395 | case_stmt(details::e_acosh , details::acosh_op) \ 33396 | case_stmt(details::e_asin , details::asin_op ) \ 33397 | case_stmt(details::e_asinh , details::asinh_op) \ 33398 | case_stmt(details::e_atan , details::atan_op ) \ 33399 | case_stmt(details::e_atanh , details::atanh_op) \ 33400 | case_stmt(details::e_ceil , details::ceil_op ) \ 33401 | case_stmt(details::e_cos , details::cos_op ) \ 33402 | case_stmt(details::e_cosh , details::cosh_op ) \ 33403 | case_stmt(details::e_exp , details::exp_op ) \ 33404 | case_stmt(details::e_expm1 , details::expm1_op) \ 33405 | case_stmt(details::e_floor , details::floor_op) \ 33406 | case_stmt(details::e_log , details::log_op ) \ 33407 | case_stmt(details::e_log10 , details::log10_op) \ 33408 | case_stmt(details::e_log2 , details::log2_op ) \ 33409 | case_stmt(details::e_log1p , details::log1p_op) \ 33410 | case_stmt(details::e_neg , details::neg_op ) \ 33411 | case_stmt(details::e_pos , details::pos_op ) \ 33412 | case_stmt(details::e_round , details::round_op) \ 33413 | case_stmt(details::e_sin , details::sin_op ) \ 33414 | case_stmt(details::e_sinc , details::sinc_op ) \ 33415 | case_stmt(details::e_sinh , details::sinh_op ) \ 33416 | case_stmt(details::e_sqrt , details::sqrt_op ) \ 33417 | case_stmt(details::e_tan , details::tan_op ) \ 33418 | case_stmt(details::e_tanh , details::tanh_op ) \ 33419 | case_stmt(details::e_cot , details::cot_op ) \ 33420 | case_stmt(details::e_sec , details::sec_op ) \ 33421 | case_stmt(details::e_csc , details::csc_op ) \ 33422 | case_stmt(details::e_r2d , details::r2d_op ) \ 33423 | case_stmt(details::e_d2r , details::d2r_op ) \ 33424 | case_stmt(details::e_d2g , details::d2g_op ) \ 33425 | case_stmt(details::e_g2d , details::g2d_op ) \ 33426 | case_stmt(details::e_notl , details::notl_op ) \ 33427 | case_stmt(details::e_sgn , details::sgn_op ) \ 33428 | case_stmt(details::e_erf , details::erf_op ) \ 33429 | case_stmt(details::e_erfc , details::erfc_op ) \ 33430 | case_stmt(details::e_ncdf , details::ncdf_op ) \ 33431 | case_stmt(details::e_frac , details::frac_op ) \ 33432 | case_stmt(details::e_trunc , details::trunc_op) \ 33433 | 33434 | inline expression_node_ptr synthesize_uv_expression(const details::operator_type& operation, 33435 | expression_node_ptr (&branch)[1]) 33436 | { 33437 | T& v = static_cast<details::variable_node<T>*>(branch[0])->ref(); 33438 | 33439 | switch (operation) 33440 | { 33441 | #define case_stmt(op0, op1) \ 33442 | case op0 : return node_allocator_-> \ 33443 | allocate<typename details::unary_variable_node<Type,op1<Type> > >(v); \ 33444 | 33445 | unary_opr_switch_statements 33446 | #undef case_stmt 33447 | default : return error_node(); 33448 | } 33449 | } 33450 | 33451 | inline expression_node_ptr synthesize_uvec_expression(const details::operator_type& operation, 33452 | expression_node_ptr (&branch)[1]) 33453 | { 33454 | switch (operation) 33455 | { 33456 | #define case_stmt(op0, op1) \ 33457 | case op0 : return node_allocator_-> \ 33458 | allocate<typename details::unary_vector_node<Type,op1<Type> > > \ 33459 | (operation, branch[0]); \ 33460 | 33461 | unary_opr_switch_statements 33462 | #undef case_stmt 33463 | default : return error_node(); 33464 | } 33465 | } 33466 | 33467 | inline expression_node_ptr synthesize_unary_expression(const details::operator_type& operation, 33468 | expression_node_ptr (&branch)[1]) 33469 | { 33470 | switch (operation) 33471 | { 33472 | #define case_stmt(op0, op1) \ 33473 | case op0 : return node_allocator_-> \ 33474 | allocate<typename details::unary_branch_node<Type,op1<Type> > >(branch[0]); \ 33475 | 33476 | unary_opr_switch_statements 33477 | #undef case_stmt 33478 | default : return error_node(); 33479 | } 33480 | } 33481 | 33482 | inline expression_node_ptr const_optimise_sf3(const details::operator_type& operation, 33483 | expression_node_ptr (&branch)[3]) 33484 | { 33485 | expression_node_ptr temp_node = error_node(); 33486 | 33487 | switch (operation) 33488 | { 33489 | #define case_stmt(op) \ 33490 | case details::e_sf##op : temp_node = node_allocator_-> \ 33491 | allocate<details::sf3_node<Type,details::sf##op##_op<Type> > > \ 33492 | (operation, branch); \ 33493 | break; \ 33494 | 33495 | case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03) 33496 | case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07) 33497 | case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11) 33498 | case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15) 33499 | case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19) 33500 | case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23) 33501 | case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27) 33502 | case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31) 33503 | case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35) 33504 | case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39) 33505 | case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43) 33506 | case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47) 33507 | #undef case_stmt 33508 | default : return error_node(); 33509 | } 33510 | 33511 | assert(temp_node); 33512 | 33513 | const T v = temp_node->value(); 33514 | 33515 | details::free_node(*node_allocator_,temp_node); 33516 | 33517 | return node_allocator_->allocate<literal_node_t>(v); 33518 | } 33519 | 33520 | inline expression_node_ptr varnode_optimise_sf3(const details::operator_type& operation, expression_node_ptr (&branch)[3]) 33521 | { 33522 | typedef details::variable_node<Type>* variable_ptr; 33523 | 33524 | const Type& v0 = static_cast<variable_ptr>(branch[0])->ref(); 33525 | const Type& v1 = static_cast<variable_ptr>(branch[1])->ref(); 33526 | const Type& v2 = static_cast<variable_ptr>(branch[2])->ref(); 33527 | 33528 | switch (operation) 33529 | { 33530 | #define case_stmt(op) \ 33531 | case details::e_sf##op : return node_allocator_-> \ 33532 | allocate_rrr<details::sf3_var_node<Type,details::sf##op##_op<Type> > > \ 33533 | (v0, v1, v2); \ 33534 | 33535 | case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03) 33536 | case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07) 33537 | case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11) 33538 | case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15) 33539 | case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19) 33540 | case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23) 33541 | case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27) 33542 | case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31) 33543 | case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35) 33544 | case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39) 33545 | case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43) 33546 | case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47) 33547 | #undef case_stmt 33548 | default : return error_node(); 33549 | } 33550 | } 33551 | 33552 | inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[3]) 33553 | { 33554 | if (!all_nodes_valid(branch)) 33555 | return error_node(); 33556 | else if (is_constant_foldable(branch)) 33557 | return const_optimise_sf3(operation,branch); 33558 | else if (all_nodes_variables(branch)) 33559 | return varnode_optimise_sf3(operation,branch); 33560 | else 33561 | { 33562 | switch (operation) 33563 | { 33564 | #define case_stmt(op) \ 33565 | case details::e_sf##op : return node_allocator_-> \ 33566 | allocate<details::sf3_node<Type,details::sf##op##_op<Type> > > \ 33567 | (operation, branch); \ 33568 | 33569 | case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03) 33570 | case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07) 33571 | case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11) 33572 | case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15) 33573 | case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19) 33574 | case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23) 33575 | case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27) 33576 | case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31) 33577 | case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35) 33578 | case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39) 33579 | case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43) 33580 | case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47) 33581 | #undef case_stmt 33582 | default : return error_node(); 33583 | } 33584 | } 33585 | } 33586 | 33587 | inline expression_node_ptr const_optimise_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4]) 33588 | { 33589 | expression_node_ptr temp_node = error_node(); 33590 | 33591 | switch (operation) 33592 | { 33593 | #define case_stmt(op) \ 33594 | case details::e_sf##op : temp_node = node_allocator_-> \ 33595 | allocate<details::sf4_node<Type,details::sf##op##_op<Type> > > \ 33596 | (operation, branch); \ 33597 | break; \ 33598 | 33599 | case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51) 33600 | case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55) 33601 | case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59) 33602 | case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63) 33603 | case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67) 33604 | case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71) 33605 | case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75) 33606 | case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79) 33607 | case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83) 33608 | case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87) 33609 | case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91) 33610 | case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95) 33611 | case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99) 33612 | #undef case_stmt 33613 | default : return error_node(); 33614 | } 33615 | 33616 | assert(temp_node); 33617 | 33618 | const T v = temp_node->value(); 33619 | 33620 | details::free_node(*node_allocator_,temp_node); 33621 | 33622 | return node_allocator_->allocate<literal_node_t>(v); 33623 | } 33624 | 33625 | inline expression_node_ptr varnode_optimise_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4]) 33626 | { 33627 | typedef details::variable_node<Type>* variable_ptr; 33628 | 33629 | const Type& v0 = static_cast<variable_ptr>(branch[0])->ref(); 33630 | const Type& v1 = static_cast<variable_ptr>(branch[1])->ref(); 33631 | const Type& v2 = static_cast<variable_ptr>(branch[2])->ref(); 33632 | const Type& v3 = static_cast<variable_ptr>(branch[3])->ref(); 33633 | 33634 | switch (operation) 33635 | { 33636 | #define case_stmt(op) \ 33637 | case details::e_sf##op : return node_allocator_-> \ 33638 | allocate_rrrr<details::sf4_var_node<Type,details::sf##op##_op<Type> > > \ 33639 | (v0, v1, v2, v3); \ 33640 | 33641 | case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51) 33642 | case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55) 33643 | case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59) 33644 | case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63) 33645 | case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67) 33646 | case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71) 33647 | case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75) 33648 | case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79) 33649 | case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83) 33650 | case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87) 33651 | case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91) 33652 | case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95) 33653 | case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99) 33654 | #undef case_stmt 33655 | default : return error_node(); 33656 | } 33657 | } 33658 | 33659 | inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[4]) 33660 | { 33661 | if (!all_nodes_valid(branch)) 33662 | return error_node(); 33663 | else if (is_constant_foldable(branch)) 33664 | return const_optimise_sf4(operation,branch); 33665 | else if (all_nodes_variables(branch)) 33666 | return varnode_optimise_sf4(operation,branch); 33667 | switch (operation) 33668 | { 33669 | #define case_stmt(op) \ 33670 | case details::e_sf##op : return node_allocator_-> \ 33671 | allocate<details::sf4_node<Type,details::sf##op##_op<Type> > > \ 33672 | (operation, branch); \ 33673 | 33674 | case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51) 33675 | case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55) 33676 | case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59) 33677 | case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63) 33678 | case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67) 33679 | case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71) 33680 | case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75) 33681 | case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79) 33682 | case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83) 33683 | case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87) 33684 | case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91) 33685 | case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95) 33686 | case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99) 33687 | #undef case_stmt 33688 | default : return error_node(); 33689 | } 33690 | } 33691 | 33692 | template <typename Allocator, 33693 | template <typename, typename> class Sequence> 33694 | inline expression_node_ptr const_optimise_varargfunc(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list) 33695 | { 33696 | expression_node_ptr temp_node = error_node(); 33697 | 33698 | switch (operation) 33699 | { 33700 | #define case_stmt(op0, op1) \ 33701 | case op0 : temp_node = node_allocator_-> \ 33702 | allocate<details::vararg_node<Type,op1<Type> > > \ 33703 | (arg_list); \ 33704 | break; \ 33705 | 33706 | case_stmt(details::e_sum , details::vararg_add_op ) 33707 | case_stmt(details::e_prod , details::vararg_mul_op ) 33708 | case_stmt(details::e_avg , details::vararg_avg_op ) 33709 | case_stmt(details::e_min , details::vararg_min_op ) 33710 | case_stmt(details::e_max , details::vararg_max_op ) 33711 | case_stmt(details::e_mand , details::vararg_mand_op ) 33712 | case_stmt(details::e_mor , details::vararg_mor_op ) 33713 | case_stmt(details::e_multi , details::vararg_multi_op) 33714 | #undef case_stmt 33715 | default : return error_node(); 33716 | } 33717 | 33718 | const T v = temp_node->value(); 33719 | 33720 | details::free_node(*node_allocator_,temp_node); 33721 | 33722 | return node_allocator_->allocate<literal_node_t>(v); 33723 | } 33724 | 33725 | inline bool special_one_parameter_vararg(const details::operator_type& operation) const 33726 | { 33727 | return ( 33728 | (details::e_sum == operation) || 33729 | (details::e_prod == operation) || 33730 | (details::e_avg == operation) || 33731 | (details::e_min == operation) || 33732 | (details::e_max == operation) 33733 | ); 33734 | } 33735 | 33736 | template <typename Allocator, 33737 | template <typename, typename> class Sequence> 33738 | inline expression_node_ptr varnode_optimise_varargfunc(const details::operator_type& operation, 33739 | Sequence<expression_node_ptr,Allocator>& arg_list) 33740 | { 33741 | switch (operation) 33742 | { 33743 | #define case_stmt(op0, op1) \ 33744 | case op0 : return node_allocator_-> \ 33745 | allocate<details::vararg_varnode<Type,op1<Type> > >(arg_list); \ 33746 | 33747 | case_stmt(details::e_sum , details::vararg_add_op ) 33748 | case_stmt(details::e_prod , details::vararg_mul_op ) 33749 | case_stmt(details::e_avg , details::vararg_avg_op ) 33750 | case_stmt(details::e_min , details::vararg_min_op ) 33751 | case_stmt(details::e_max , details::vararg_max_op ) 33752 | case_stmt(details::e_mand , details::vararg_mand_op ) 33753 | case_stmt(details::e_mor , details::vararg_mor_op ) 33754 | case_stmt(details::e_multi , details::vararg_multi_op) 33755 | #undef case_stmt 33756 | default : return error_node(); 33757 | } 33758 | } 33759 | 33760 | template <typename Allocator, 33761 | template <typename, typename> class Sequence> 33762 | inline expression_node_ptr vectorize_func(const details::operator_type& operation, 33763 | Sequence<expression_node_ptr,Allocator>& arg_list) 33764 | { 33765 | if (1 == arg_list.size()) 33766 | { 33767 | switch (operation) 33768 | { 33769 | #define case_stmt(op0, op1) \ 33770 | case op0 : return node_allocator_-> \ 33771 | allocate<details::vectorize_node<Type,op1<Type> > >(arg_list[0]); \ 33772 | 33773 | case_stmt(details::e_sum , details::vec_add_op) 33774 | case_stmt(details::e_prod , details::vec_mul_op) 33775 | case_stmt(details::e_avg , details::vec_avg_op) 33776 | case_stmt(details::e_min , details::vec_min_op) 33777 | case_stmt(details::e_max , details::vec_max_op) 33778 | #undef case_stmt 33779 | default : return error_node(); 33780 | } 33781 | } 33782 | else 33783 | return error_node(); 33784 | } 33785 | 33786 | template <typename Allocator, 33787 | template <typename, typename> class Sequence> 33788 | inline expression_node_ptr vararg_function(const details::operator_type& operation, 33789 | Sequence<expression_node_ptr,Allocator>& arg_list) 33790 | { 33791 | if (!all_nodes_valid(arg_list)) 33792 | { 33793 | details::free_all_nodes(*node_allocator_,arg_list); 33794 | 33795 | return error_node(); 33796 | } 33797 | else if (is_constant_foldable(arg_list)) 33798 | return const_optimise_varargfunc(operation,arg_list); 33799 | else if ((1 == arg_list.size()) && details::is_ivector_node(arg_list[0])) 33800 | return vectorize_func(operation,arg_list); 33801 | else if ((1 == arg_list.size()) && special_one_parameter_vararg(operation)) 33802 | return arg_list[0]; 33803 | else if (all_nodes_variables(arg_list)) 33804 | return varnode_optimise_varargfunc(operation,arg_list); 33805 | 33806 | #ifndef exprtk_disable_string_capabilities 33807 | if (details::e_smulti == operation) 33808 | { 33809 | expression_node_ptr result = node_allocator_-> 33810 | allocate<details::str_vararg_node<Type,details::vararg_multi_op<Type> > >(arg_list); 33811 | if (result && result->valid()) 33812 | { 33813 | return result; 33814 | } 33815 | 33816 | parser_->set_error(parser_error::make_error( 33817 | parser_error::e_synthesis, 33818 | token_t(), 33819 | "ERR262 - Failed to synthesize node: str_vararg_node<vararg_multi_op>", 33820 | exprtk_error_location)); 33821 | 33822 | details::free_node(*node_allocator_, result); 33823 | } 33824 | else 33825 | #endif 33826 | { 33827 | expression_node_ptr result = error_node(); 33828 | 33829 | switch (operation) 33830 | { 33831 | #define case_stmt(op0, op1) \ 33832 | case op0 : result = node_allocator_-> \ 33833 | allocate<details::vararg_node<Type,op1<Type> > >(arg_list); \ 33834 | break; \ 33835 | 33836 | case_stmt(details::e_sum , details::vararg_add_op ) 33837 | case_stmt(details::e_prod , details::vararg_mul_op ) 33838 | case_stmt(details::e_avg , details::vararg_avg_op ) 33839 | case_stmt(details::e_min , details::vararg_min_op ) 33840 | case_stmt(details::e_max , details::vararg_max_op ) 33841 | case_stmt(details::e_mand , details::vararg_mand_op ) 33842 | case_stmt(details::e_mor , details::vararg_mor_op ) 33843 | case_stmt(details::e_multi , details::vararg_multi_op) 33844 | #undef case_stmt 33845 | default : return error_node(); 33846 | } 33847 | 33848 | if (result && result->valid()) 33849 | { 33850 | return result; 33851 | } 33852 | 33853 | parser_->set_error(parser_error::make_error( 33854 | parser_error::e_synthesis, 33855 | token_t(), 33856 | "ERR263 - Failed to synthesize node: vararg_node", 33857 | exprtk_error_location)); 33858 | 33859 | details::free_node(*node_allocator_, result); 33860 | } 33861 | 33862 | return error_node(); 33863 | } 33864 | 33865 | template <std::size_t N> 33866 | inline expression_node_ptr function(ifunction_t* f, expression_node_ptr (&b)[N]) 33867 | { 33868 | typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t; 33869 | expression_node_ptr result = synthesize_expression<function_N_node_t,N>(f,b); 33870 | 33871 | if (0 == result) 33872 | return error_node(); 33873 | else 33874 | { 33875 | // Can the function call be completely optimised? 33876 | if (details::is_constant_node(result)) 33877 | return result; 33878 | else if (!all_nodes_valid(b)) 33879 | { 33880 | details::free_node(*node_allocator_,result); 33881 | std::fill_n(b, N, reinterpret_cast<expression_node_ptr>(0)); 33882 | 33883 | return error_node(); 33884 | } 33885 | else if (N != f->param_count) 33886 | { 33887 | details::free_node(*node_allocator_,result); 33888 | std::fill_n(b, N, reinterpret_cast<expression_node_ptr>(0)); 33889 | 33890 | return error_node(); 33891 | } 33892 | 33893 | function_N_node_t* func_node_ptr = reinterpret_cast<function_N_node_t*>(result); 33894 | 33895 | if (!func_node_ptr->init_branches(b)) 33896 | { 33897 | details::free_node(*node_allocator_,result); 33898 | std::fill_n(b, N, reinterpret_cast<expression_node_ptr>(0)); 33899 | 33900 | return error_node(); 33901 | } 33902 | 33903 | if (result && result->valid()) 33904 | { 33905 | return result; 33906 | } 33907 | 33908 | parser_->set_error(parser_error::make_error( 33909 | parser_error::e_synthesis, 33910 | token_t(), 33911 | "ERR264 - Failed to synthesize node: function_N_node_t", 33912 | exprtk_error_location)); 33913 | 33914 | details::free_node(*node_allocator_, result); 33915 | return error_node(); 33916 | } 33917 | } 33918 | 33919 | inline expression_node_ptr function(ifunction_t* f) 33920 | { 33921 | typedef typename details::function_N_node<Type,ifunction_t,0> function_N_node_t; 33922 | return node_allocator_->allocate<function_N_node_t>(f); 33923 | } 33924 | 33925 | inline expression_node_ptr vararg_function_call(ivararg_function_t* vaf, 33926 | std::vector<expression_node_ptr>& arg_list) 33927 | { 33928 | if (!all_nodes_valid(arg_list)) 33929 | { 33930 | details::free_all_nodes(*node_allocator_,arg_list); 33931 | 33932 | return error_node(); 33933 | } 33934 | 33935 | typedef details::vararg_function_node<Type,ivararg_function_t> alloc_type; 33936 | 33937 | expression_node_ptr result = node_allocator_->allocate<alloc_type>(vaf,arg_list); 33938 | 33939 | if ( 33940 | !arg_list.empty() && 33941 | !vaf->has_side_effects() && 33942 | is_constant_foldable(arg_list) 33943 | ) 33944 | { 33945 | const Type v = result->value(); 33946 | details::free_node(*node_allocator_,result); 33947 | result = node_allocator_->allocate<literal_node_t>(v); 33948 | } 33949 | 33950 | parser_->state_.activate_side_effect("vararg_function_call()"); 33951 | 33952 | if (result && result->valid()) 33953 | { 33954 | return result; 33955 | } 33956 | 33957 | parser_->set_error(parser_error::make_error( 33958 | parser_error::e_synthesis, 33959 | token_t(), 33960 | "ERR265 - Failed to synthesize node: vararg_function_node<ivararg_function_t>", 33961 | exprtk_error_location)); 33962 | 33963 | details::free_node(*node_allocator_, result); 33964 | return error_node(); 33965 | } 33966 | 33967 | inline expression_node_ptr generic_function_call(igeneric_function_t* gf, 33968 | std::vector<expression_node_ptr>& arg_list, 33969 | const std::size_t& param_seq_index = std::numeric_limits<std::size_t>::max()) 33970 | { 33971 | if (!all_nodes_valid(arg_list)) 33972 | { 33973 | details::free_all_nodes(*node_allocator_,arg_list); 33974 | return error_node(); 33975 | } 33976 | 33977 | typedef details::generic_function_node <Type,igeneric_function_t> alloc_type1; 33978 | typedef details::multimode_genfunction_node<Type,igeneric_function_t> alloc_type2; 33979 | 33980 | const std::size_t no_psi = std::numeric_limits<std::size_t>::max(); 33981 | 33982 | expression_node_ptr result = error_node(); 33983 | std::string node_name = "Unknown" 33984 | 33985 | if (no_psi == param_seq_index) 33986 | { 33987 | result = node_allocator_->allocate<alloc_type1>(arg_list,gf); 33988 | node_name = "generic_function_node<igeneric_function_t>" 33989 | } 33990 | else 33991 | { 33992 | result = node_allocator_->allocate<alloc_type2>(gf, param_seq_index, arg_list); 33993 | node_name = "multimode_genfunction_node<igeneric_function_t>" 33994 | } 33995 | 33996 | alloc_type1* genfunc_node_ptr = static_cast<alloc_type1*>(result); 33997 | 33998 | assert(genfunc_node_ptr); 33999 | 34000 | if ( 34001 | !arg_list.empty() && 34002 | !gf->has_side_effects() && 34003 | parser_->state_.type_check_enabled && 34004 | is_constant_foldable(arg_list) 34005 | ) 34006 | { 34007 | genfunc_node_ptr->init_branches(); 34008 | 34009 | const Type v = result->value(); 34010 | 34011 | details::free_node(*node_allocator_,result); 34012 | 34013 | return node_allocator_->allocate<literal_node_t>(v); 34014 | } 34015 | else if (genfunc_node_ptr->init_branches()) 34016 | { 34017 | if (result && result->valid()) 34018 | { 34019 | parser_->state_.activate_side_effect("generic_function_call()"); 34020 | return result; 34021 | } 34022 | 34023 | parser_->set_error(parser_error::make_error( 34024 | parser_error::e_synthesis, 34025 | token_t(), 34026 | "ERR266 - Failed to synthesize node: " + node_name, 34027 | exprtk_error_location)); 34028 | 34029 | details::free_node(*node_allocator_, result); 34030 | return error_node(); 34031 | } 34032 | else 34033 | { 34034 | details::free_node(*node_allocator_, result); 34035 | details::free_all_nodes(*node_allocator_, arg_list); 34036 | 34037 | return error_node(); 34038 | } 34039 | } 34040 | 34041 | #ifndef exprtk_disable_string_capabilities 34042 | inline expression_node_ptr string_function_call(igeneric_function_t* gf, 34043 | std::vector<expression_node_ptr>& arg_list, 34044 | const std::size_t& param_seq_index = std::numeric_limits<std::size_t>::max()) 34045 | { 34046 | if (!all_nodes_valid(arg_list)) 34047 | { 34048 | details::free_all_nodes(*node_allocator_,arg_list); 34049 | return error_node(); 34050 | } 34051 | 34052 | typedef details::string_function_node <Type,igeneric_function_t> alloc_type1; 34053 | typedef details::multimode_strfunction_node<Type,igeneric_function_t> alloc_type2; 34054 | 34055 | const std::size_t no_psi = std::numeric_limits<std::size_t>::max(); 34056 | 34057 | expression_node_ptr result = error_node(); 34058 | std::string node_name = "Unknown" 34059 | 34060 | if (no_psi == param_seq_index) 34061 | { 34062 | result = node_allocator_->allocate<alloc_type1>(gf,arg_list); 34063 | node_name = "string_function_node<igeneric_function_t>" 34064 | } 34065 | else 34066 | { 34067 | result = node_allocator_->allocate<alloc_type2>(gf, param_seq_index, arg_list); 34068 | node_name = "multimode_strfunction_node<igeneric_function_t>" 34069 | } 34070 | 34071 | alloc_type1* strfunc_node_ptr = static_cast<alloc_type1*>(result); 34072 | 34073 | assert(strfunc_node_ptr); 34074 | 34075 | if ( 34076 | !arg_list.empty() && 34077 | !gf->has_side_effects() && 34078 | is_constant_foldable(arg_list) 34079 | ) 34080 | { 34081 | strfunc_node_ptr->init_branches(); 34082 | 34083 | const Type v = result->value(); 34084 | 34085 | details::free_node(*node_allocator_,result); 34086 | 34087 | return node_allocator_->allocate<literal_node_t>(v); 34088 | } 34089 | else if (strfunc_node_ptr->init_branches()) 34090 | { 34091 | if (result && result->valid()) 34092 | { 34093 | parser_->state_.activate_side_effect("string_function_call()"); 34094 | return result; 34095 | } 34096 | 34097 | parser_->set_error(parser_error::make_error( 34098 | parser_error::e_synthesis, 34099 | token_t(), 34100 | "ERR267 - Failed to synthesize node: " + node_name, 34101 | exprtk_error_location)); 34102 | 34103 | details::free_node(*node_allocator_, result); 34104 | return error_node(); 34105 | } 34106 | else 34107 | { 34108 | details::free_node (*node_allocator_,result ); 34109 | details::free_all_nodes(*node_allocator_,arg_list); 34110 | 34111 | return error_node(); 34112 | } 34113 | } 34114 | #endif 34115 | 34116 | #ifndef exprtk_disable_return_statement 34117 | inline expression_node_ptr return_call(std::vector<expression_node_ptr>& arg_list) 34118 | { 34119 | if (!all_nodes_valid(arg_list)) 34120 | { 34121 | details::free_all_nodes(*node_allocator_,arg_list); 34122 | return error_node(); 34123 | } 34124 | 34125 | typedef details::return_node<Type> alloc_type; 34126 | 34127 | expression_node_ptr result = node_allocator_-> 34128 | allocate_rr<alloc_type>(arg_list,parser_->results_ctx()); 34129 | 34130 | alloc_type* return_node_ptr = static_cast<alloc_type*>(result); 34131 | 34132 | assert(return_node_ptr); 34133 | 34134 | if (return_node_ptr->init_branches()) 34135 | { 34136 | if (result && result->valid()) 34137 | { 34138 | parser_->state_.activate_side_effect("return_call()"); 34139 | return result; 34140 | } 34141 | 34142 | parser_->set_error(parser_error::make_error( 34143 | parser_error::e_synthesis, 34144 | token_t(), 34145 | "ERR268 - Failed to synthesize node: return_node", 34146 | exprtk_error_location)); 34147 | 34148 | details::free_node(*node_allocator_, result); 34149 | return error_node(); 34150 | } 34151 | else 34152 | { 34153 | details::free_node (*node_allocator_, result ); 34154 | details::free_all_nodes(*node_allocator_, arg_list); 34155 | 34156 | return error_node(); 34157 | } 34158 | } 34159 | 34160 | inline expression_node_ptr return_envelope(expression_node_ptr body, 34161 | results_context_t* rc, 34162 | bool*& return_invoked) 34163 | { 34164 | typedef details::return_envelope_node<Type> alloc_type; 34165 | 34166 | expression_node_ptr result = node_allocator_-> 34167 | allocate_cr<alloc_type>(body,(*rc)); 34168 | 34169 | return_invoked = static_cast<alloc_type*>(result)->retinvk_ptr(); 34170 | 34171 | return result; 34172 | } 34173 | #else 34174 | inline expression_node_ptr return_call(std::vector<expression_node_ptr>&) 34175 | { 34176 | return error_node(); 34177 | } 34178 | 34179 | inline expression_node_ptr return_envelope(expression_node_ptr, 34180 | results_context_t*, 34181 | bool*&) 34182 | { 34183 | return error_node(); 34184 | } 34185 | #endif 34186 | 34187 | inline expression_node_ptr vector_element(const std::string& symbol, 34188 | vector_holder_ptr vector_base, 34189 | expression_node_ptr vec_node, 34190 | expression_node_ptr index) 34191 | { 34192 | expression_node_ptr result = error_node(); 34193 | std::string node_name = "Unknown" 34194 | 34195 | if (details::is_constant_node(index)) 34196 | { 34197 | const std::size_t vec_index = static_cast<std::size_t>(details::numeric::to_int64(index->value())); 34198 | 34199 | details::free_node(*node_allocator_,index); 34200 | 34201 | if (vec_index >= vector_base->size()) 34202 | { 34203 | parser_->set_error(parser_error::make_error( 34204 | parser_error::e_parser, 34205 | token_t(), 34206 | "ERR269 - Index of " + details::to_str(vec_index) + " out of range for " 34207 | "vector '" + symbol + "' of size " + details::to_str(vector_base->size()), 34208 | exprtk_error_location)); 34209 | 34210 | details::free_node(*node_allocator_,vec_node); 34211 | 34212 | return error_node(); 34213 | } 34214 | 34215 | if (vector_base->rebaseable()) 34216 | { 34217 | vector_access_runtime_check_ptr rtc = get_vector_access_runtime_check(); 34218 | 34219 | result = (rtc) ? 34220 | node_allocator_->allocate<rebasevector_celem_rtc_node_t>(vec_node, vec_index, vector_base, rtc) : 34221 | node_allocator_->allocate<rebasevector_celem_node_t >(vec_node, vec_index, vector_base ) ; 34222 | 34223 | node_name = (rtc) ? 34224 | "rebasevector_elem_rtc_node_t" : 34225 | "rebasevector_elem_node_t" ; 34226 | 34227 | if (result && result->valid()) 34228 | { 34229 | return result; 34230 | } 34231 | 34232 | parser_->set_error(parser_error::make_error( 34233 | parser_error::e_synthesis, 34234 | token_t(), 34235 | "ERR270 - Failed to synthesize node: " + node_name + " for vector: " + symbol, 34236 | exprtk_error_location)); 34237 | 34238 | details::free_node(*node_allocator_, result); 34239 | return error_node(); 34240 | } 34241 | else if (details::is_ivector_node(vec_node) && !details::is_vector_node(vec_node)) 34242 | { 34243 | vector_access_runtime_check_ptr rtc = get_vector_access_runtime_check(); 34244 | 34245 | result = (rtc) ? 34246 | node_allocator_->allocate<vector_celem_rtc_node_t>(vec_node, vec_index, vector_base, rtc) : 34247 | node_allocator_->allocate<vector_celem_node_t >(vec_node, vec_index, vector_base ) ; 34248 | 34249 | node_name = (rtc) ? 34250 | "vector_elem_rtc_node_t" : 34251 | "vector_elem_node_t" ; 34252 | 34253 | if (result && result->valid()) 34254 | { 34255 | return result; 34256 | } 34257 | 34258 | parser_->set_error(parser_error::make_error( 34259 | parser_error::e_synthesis, 34260 | token_t(), 34261 | "ERR271 - Failed to synthesize node: " + node_name + " for vector: " + symbol, 34262 | exprtk_error_location)); 34263 | 34264 | details::free_node(*node_allocator_, result); 34265 | return error_node(); 34266 | } 34267 | 34268 | const scope_element& se = parser_->sem_.get_element(symbol,vec_index); 34269 | 34270 | if (se.index == vec_index) 34271 | { 34272 | result = se.var_node; 34273 | details::free_node(*node_allocator_,vec_node); 34274 | } 34275 | else 34276 | { 34277 | scope_element nse; 34278 | nse.name = symbol; 34279 | nse.active = true; 34280 | nse.ref_count = 1; 34281 | nse.type = scope_element::e_vecelem; 34282 | nse.index = vec_index; 34283 | nse.depth = parser_->state_.scope_depth; 34284 | nse.data = 0; 34285 | nse.var_node = node_allocator_->allocate<variable_node_t>((*(*vector_base)[vec_index])); 34286 | 34287 | if (!parser_->sem_.add_element(nse)) 34288 | { 34289 | parser_->set_synthesis_error("Failed to add new local vector element to SEM [1]"); 34290 | 34291 | parser_->sem_.free_element(nse); 34292 | 34293 | result = error_node(); 34294 | } 34295 | 34296 | assert(parser_->sem_.total_local_symb_size_bytes() <= parser_->settings().max_total_local_symbol_size_bytes()); 34297 | 34298 | details::free_node(*node_allocator_,vec_node); 34299 | 34300 | exprtk_debug(("vector_element() - INFO - Added new local vector element: %s\n", nse.name.c_str())); 34301 | 34302 | parser_->state_.activate_side_effect("vector_element()"); 34303 | 34304 | result = nse.var_node; 34305 | node_name = "variable_node_t" 34306 | } 34307 | } 34308 | else 34309 | { 34310 | vector_access_runtime_check_ptr rtc = get_vector_access_runtime_check(); 34311 | 34312 | if (vector_base->rebaseable()) 34313 | { 34314 | result = (rtc) ? 34315 | node_allocator_->allocate<rebasevector_elem_rtc_node_t>(vec_node, index, vector_base, rtc) : 34316 | node_allocator_->allocate<rebasevector_elem_node_t >(vec_node, index, vector_base ) ; 34317 | 34318 | node_name = (rtc) ? 34319 | "rebasevector_elem_rtc_node_t" : 34320 | "rebasevector_elem_node_t" ; 34321 | } 34322 | else 34323 | { 34324 | result = rtc ? 34325 | node_allocator_->allocate<vector_elem_rtc_node_t>(vec_node, index, vector_base, rtc) : 34326 | node_allocator_->allocate<vector_elem_node_t >(vec_node, index, vector_base ) ; 34327 | 34328 | node_name = (rtc) ? 34329 | "vector_elem_rtc_node_t" : 34330 | "vector_elem_node_t" ; 34331 | } 34332 | } 34333 | 34334 | if (result && result->valid()) 34335 | { 34336 | return result; 34337 | } 34338 | 34339 | parser_->set_error(parser_error::make_error( 34340 | parser_error::e_synthesis, 34341 | token_t(), 34342 | "ERR272 - Failed to synthesize node: " + node_name, 34343 | exprtk_error_location)); 34344 | 34345 | details::free_node(*node_allocator_, result); 34346 | return error_node(); 34347 | } 34348 | 34349 | private: 34350 | 34351 | template <std::size_t N, typename NodePtr> 34352 | inline bool is_constant_foldable(NodePtr (&b)[N]) const 34353 | { 34354 | for (std::size_t i = 0; i < N; ++i) 34355 | { 34356 | if (0 == b[i]) 34357 | return false; 34358 | else if (!details::is_constant_node(b[i])) 34359 | return false; 34360 | } 34361 | 34362 | return true; 34363 | } 34364 | 34365 | template <typename NodePtr, 34366 | typename Allocator, 34367 | template <typename, typename> class Sequence> 34368 | inline bool is_constant_foldable(const Sequence<NodePtr,Allocator>& b) const 34369 | { 34370 | for (std::size_t i = 0; i < b.size(); ++i) 34371 | { 34372 | if (0 == b[i]) 34373 | return false; 34374 | else if (!details::is_constant_node(b[i])) 34375 | return false; 34376 | } 34377 | 34378 | return true; 34379 | } 34380 | 34381 | void lodge_assignment(symbol_type cst, expression_node_ptr node) 34382 | { 34383 | parser_->state_.activate_side_effect("lodge_assignment()"); 34384 | 34385 | if (!parser_->dec_.collect_assignments()) 34386 | return; 34387 | 34388 | std::string symbol_name; 34389 | 34390 | switch (cst) 34391 | { 34392 | case e_st_variable : symbol_name = parser_->symtab_store_ 34393 | .get_variable_name(node); 34394 | break; 34395 | 34396 | #ifndef exprtk_disable_string_capabilities 34397 | case e_st_string : symbol_name = parser_->symtab_store_ 34398 | .get_stringvar_name(node); 34399 | break; 34400 | #endif 34401 | 34402 | case e_st_vector : { 34403 | typedef details::vector_holder<T> vector_holder_t; 34404 | 34405 | vector_holder_t& vh = static_cast<vector_node_t*>(node)->vec_holder(); 34406 | 34407 | symbol_name = parser_->symtab_store_.get_vector_name(&vh); 34408 | } 34409 | break; 34410 | 34411 | case e_st_vecelem : { 34412 | typedef details::vector_holder<T> vector_holder_t; 34413 | 34414 | vector_holder_t& vh = static_cast<vector_elem_node_t*>(node)->vec_holder(); 34415 | 34416 | symbol_name = parser_->symtab_store_.get_vector_name(&vh); 34417 | 34418 | cst = e_st_vector; 34419 | } 34420 | break; 34421 | 34422 | default : return; 34423 | } 34424 | 34425 | if (!symbol_name.empty()) 34426 | { 34427 | parser_->dec_.add_assignment(symbol_name,cst); 34428 | } 34429 | } 34430 | 34431 | const void* base_ptr(expression_node_ptr node) 34432 | { 34433 | if (node) 34434 | { 34435 | switch (node->type()) 34436 | { 34437 | case details::expression_node<T>::e_variable: 34438 | return reinterpret_cast<const void*>(&static_cast<variable_node_t*>(node)->ref()); 34439 | 34440 | case details::expression_node<T>::e_vecelem: 34441 | return reinterpret_cast<const void*>(&static_cast<vector_elem_node_t*>(node)->ref()); 34442 | 34443 | case details::expression_node<T>::e_veccelem: 34444 | return reinterpret_cast<const void*>(&static_cast<vector_celem_node_t*>(node)->ref()); 34445 | 34446 | case details::expression_node<T>::e_vecelemrtc: 34447 | return reinterpret_cast<const void*>(&static_cast<vector_elem_rtc_node_t*>(node)->ref()); 34448 | 34449 | case details::expression_node<T>::e_veccelemrtc: 34450 | return reinterpret_cast<const void*>(&static_cast<vector_celem_rtc_node_t*>(node)->ref()); 34451 | 34452 | case details::expression_node<T>::e_rbvecelem: 34453 | return reinterpret_cast<const void*>(&static_cast<rebasevector_elem_node_t*>(node)->ref()); 34454 | 34455 | case details::expression_node<T>::e_rbvecelemrtc: 34456 | return reinterpret_cast<const void*>(&static_cast<rebasevector_elem_rtc_node_t*>(node)->ref()); 34457 | 34458 | case details::expression_node<T>::e_rbveccelem: 34459 | return reinterpret_cast<const void*>(&static_cast<rebasevector_celem_node_t*>(node)->ref()); 34460 | 34461 | case details::expression_node<T>::e_rbveccelemrtc: 34462 | return reinterpret_cast<const void*>(&static_cast<rebasevector_celem_rtc_node_t*>(node)->ref()); 34463 | 34464 | case details::expression_node<T>::e_vector: 34465 | return reinterpret_cast<const void*>(static_cast<vector_node_t*>(node)->vec_holder().data()); 34466 | 34467 | #ifndef exprtk_disable_string_capabilities 34468 | case details::expression_node<T>::e_stringvar: 34469 | return reinterpret_cast<const void*>((static_cast<stringvar_node_t*>(node)->base())); 34470 | 34471 | case details::expression_node<T>::e_stringvarrng: 34472 | return reinterpret_cast<const void*>((static_cast<string_range_node_t*>(node)->base())); 34473 | #endif 34474 | default : return reinterpret_cast<const void*>(0); 34475 | } 34476 | } 34477 | 34478 | return reinterpret_cast<const void*>(0); 34479 | } 34480 | 34481 | bool assign_immutable_symbol(expression_node_ptr node) 34482 | { 34483 | interval_t interval; 34484 | const void* baseptr_addr = base_ptr(node); 34485 | 34486 | exprtk_debug(("assign_immutable_symbol - base ptr addr: %p\n", baseptr_addr)); 34487 | 34488 | if (parser_->immutable_memory_map_.in_interval(baseptr_addr,interval)) 34489 | { 34490 | typename immutable_symtok_map_t::iterator itr = parser_->immutable_symtok_map_.find(interval); 34491 | 34492 | if (parser_->immutable_symtok_map_.end() != itr) 34493 | { 34494 | token_t& token = itr->second; 34495 | parser_->set_error(parser_error::make_error( 34496 | parser_error::e_parser, 34497 | token, 34498 | "ERR273 - Symbol '" + token.value + "' cannot be assigned-to as it is immutable.", 34499 | exprtk_error_location)); 34500 | } 34501 | else 34502 | parser_->set_synthesis_error("Unable to assign symbol is immutable."); 34503 | 34504 | return true; 34505 | } 34506 | 34507 | return false; 34508 | } 34509 | 34510 | inline expression_node_ptr synthesize_assignment_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2]) 34511 | { 34512 | if (assign_immutable_symbol(branch[0])) 34513 | { 34514 | return error_node(); 34515 | } 34516 | else if (details::is_variable_node(branch[0])) 34517 | { 34518 | lodge_assignment(e_st_variable,branch[0]); 34519 | return synthesize_expression<assignment_node_t,2>(operation,branch); 34520 | } 34521 | else if (details::is_vector_elem_node(branch[0]) || details::is_vector_celem_node(branch[0])) 34522 | { 34523 | lodge_assignment(e_st_vecelem,branch[0]); 34524 | return synthesize_expression<assignment_vec_elem_node_t, 2>(operation, branch); 34525 | } 34526 | else if (details::is_vector_elem_rtc_node(branch[0]) || details::is_vector_celem_rtc_node(branch[0])) 34527 | { 34528 | lodge_assignment(e_st_vecelem,branch[0]); 34529 | return synthesize_expression<assignment_vec_elem_rtc_node_t, 2>(operation, branch); 34530 | } 34531 | else if (details::is_rebasevector_elem_node(branch[0])) 34532 | { 34533 | lodge_assignment(e_st_vecelem,branch[0]); 34534 | return synthesize_expression<assignment_rebasevec_elem_node_t, 2>(operation, branch); 34535 | } 34536 | else if (details::is_rebasevector_elem_rtc_node(branch[0])) 34537 | { 34538 | lodge_assignment(e_st_vecelem,branch[0]); 34539 | return synthesize_expression<assignment_rebasevec_elem_rtc_node_t, 2>(operation, branch); 34540 | } 34541 | else if (details::is_rebasevector_celem_node(branch[0])) 34542 | { 34543 | lodge_assignment(e_st_vecelem,branch[0]); 34544 | return synthesize_expression<assignment_rebasevec_celem_node_t, 2>(operation, branch); 34545 | } 34546 | #ifndef exprtk_disable_string_capabilities 34547 | else if (details::is_string_node(branch[0])) 34548 | { 34549 | lodge_assignment(e_st_string,branch[0]); 34550 | return synthesize_expression<assignment_string_node_t,2>(operation, branch); 34551 | } 34552 | else if (details::is_string_range_node(branch[0])) 34553 | { 34554 | lodge_assignment(e_st_string,branch[0]); 34555 | return synthesize_expression<assignment_string_range_node_t,2>(operation, branch); 34556 | } 34557 | #endif 34558 | else if (details::is_vector_node(branch[0])) 34559 | { 34560 | lodge_assignment(e_st_vector,branch[0]); 34561 | 34562 | if (details::is_ivector_node(branch[1])) 34563 | return synthesize_expression<assignment_vecvec_node_t,2>(operation, branch); 34564 | else 34565 | return synthesize_expression<assignment_vec_node_t,2>(operation, branch); 34566 | } 34567 | else if (details::is_literal_node(branch[0])) 34568 | { 34569 | parser_->set_error(parser_error::make_error( 34570 | parser_error::e_syntax, 34571 | parser_->current_state().token, 34572 | "ERR274 - Cannot assign value to const variable", 34573 | exprtk_error_location)); 34574 | 34575 | return error_node(); 34576 | } 34577 | else 34578 | { 34579 | parser_->set_error(parser_error::make_error( 34580 | parser_error::e_syntax, 34581 | parser_->current_state().token, 34582 | "ERR275 - Invalid branches for assignment operator '" + details::to_str(operation) + "'", 34583 | exprtk_error_location)); 34584 | 34585 | return error_node(); 34586 | } 34587 | } 34588 | 34589 | inline expression_node_ptr synthesize_assignment_operation_expression(const details::operator_type& operation, 34590 | expression_node_ptr (&branch)[2]) 34591 | { 34592 | if (assign_immutable_symbol(branch[0])) 34593 | { 34594 | return error_node(); 34595 | } 34596 | 34597 | expression_node_ptr result = error_node(); 34598 | std::string node_name = "Unknown" 34599 | 34600 | if (details::is_variable_node(branch[0])) 34601 | { 34602 | lodge_assignment(e_st_variable,branch[0]); 34603 | 34604 | switch (operation) 34605 | { 34606 | #define case_stmt(op0, op1) \ 34607 | case op0 : result = node_allocator_-> \ 34608 | template allocate_rrr<typename details::assignment_op_node<Type,op1<Type> > > \ 34609 | (operation, branch[0], branch[1]); \ 34610 | node_name = "assignment_op_node" \ 34611 | break; \ 34612 | 34613 | case_stmt(details::e_addass , details::add_op) 34614 | case_stmt(details::e_subass , details::sub_op) 34615 | case_stmt(details::e_mulass , details::mul_op) 34616 | case_stmt(details::e_divass , details::div_op) 34617 | case_stmt(details::e_modass , details::mod_op) 34618 | #undef case_stmt 34619 | default : return error_node(); 34620 | } 34621 | } 34622 | else if (details::is_vector_elem_node(branch[0])) 34623 | { 34624 | lodge_assignment(e_st_vecelem,branch[0]); 34625 | 34626 | switch (operation) 34627 | { 34628 | #define case_stmt(op0, op1) \ 34629 | case op0 : result = node_allocator_-> \ 34630 | template allocate_rrr<typename details::assignment_vec_elem_op_node<Type,op1<Type> > > \ 34631 | (operation, branch[0], branch[1]); \ 34632 | node_name = "assignment_vec_elem_op_node" \ 34633 | break; \ 34634 | 34635 | case_stmt(details::e_addass , details::add_op) 34636 | case_stmt(details::e_subass , details::sub_op) 34637 | case_stmt(details::e_mulass , details::mul_op) 34638 | case_stmt(details::e_divass , details::div_op) 34639 | case_stmt(details::e_modass , details::mod_op) 34640 | #undef case_stmt 34641 | default : return error_node(); 34642 | } 34643 | } 34644 | else if (details::is_vector_elem_rtc_node(branch[0])) 34645 | { 34646 | lodge_assignment(e_st_vecelem,branch[0]); 34647 | 34648 | switch (operation) 34649 | { 34650 | #define case_stmt(op0, op1) \ 34651 | case op0 : result = node_allocator_-> \ 34652 | template allocate_rrr<typename details::assignment_vec_elem_op_rtc_node<Type,op1<Type> > > \ 34653 | (operation, branch[0], branch[1]); \ 34654 | node_name = "assignment_vec_elem_op_rtc_node" \ 34655 | break; \ 34656 | 34657 | case_stmt(details::e_addass , details::add_op) 34658 | case_stmt(details::e_subass , details::sub_op) 34659 | case_stmt(details::e_mulass , details::mul_op) 34660 | case_stmt(details::e_divass , details::div_op) 34661 | case_stmt(details::e_modass , details::mod_op) 34662 | #undef case_stmt 34663 | default : return error_node(); 34664 | } 34665 | } 34666 | else if (details::is_vector_celem_rtc_node(branch[0])) 34667 | { 34668 | lodge_assignment(e_st_vecelem,branch[0]); 34669 | 34670 | switch (operation) 34671 | { 34672 | #define case_stmt(op0, op1) \ 34673 | case op0 : result = node_allocator_-> \ 34674 | template allocate_rrr<typename details::assignment_vec_celem_op_rtc_node<Type,op1<Type> > > \ 34675 | (operation, branch[0], branch[1]); \ 34676 | node_name = "assignment_vec_celem_op_rtc_node" \ 34677 | break; \ 34678 | 34679 | case_stmt(details::e_addass , details::add_op) 34680 | case_stmt(details::e_subass , details::sub_op) 34681 | case_stmt(details::e_mulass , details::mul_op) 34682 | case_stmt(details::e_divass , details::div_op) 34683 | case_stmt(details::e_modass , details::mod_op) 34684 | #undef case_stmt 34685 | default : return error_node(); 34686 | } 34687 | } 34688 | else if (details::is_rebasevector_elem_node(branch[0])) 34689 | { 34690 | lodge_assignment(e_st_vecelem,branch[0]); 34691 | 34692 | switch (operation) 34693 | { 34694 | #define case_stmt(op0, op1) \ 34695 | case op0 : result = node_allocator_-> \ 34696 | template allocate_rrr<typename details::assignment_rebasevec_elem_op_node<Type,op1<Type> > > \ 34697 | (operation, branch[0], branch[1]); \ 34698 | node_name = "assignment_rebasevec_elem_op_node" \ 34699 | break; \ 34700 | 34701 | case_stmt(details::e_addass , details::add_op) 34702 | case_stmt(details::e_subass , details::sub_op) 34703 | case_stmt(details::e_mulass , details::mul_op) 34704 | case_stmt(details::e_divass , details::div_op) 34705 | case_stmt(details::e_modass , details::mod_op) 34706 | #undef case_stmt 34707 | default : return error_node(); 34708 | } 34709 | } 34710 | else if (details::is_rebasevector_celem_node(branch[0])) 34711 | { 34712 | lodge_assignment(e_st_vecelem,branch[0]); 34713 | 34714 | switch (operation) 34715 | { 34716 | #define case_stmt(op0, op1) \ 34717 | case op0 : result = node_allocator_-> \ 34718 | template allocate_rrr<typename details::assignment_rebasevec_celem_op_node<Type,op1<Type> > > \ 34719 | (operation, branch[0], branch[1]); \ 34720 | node_name = "assignment_rebasevec_celem_op_node" \ 34721 | break; \ 34722 | 34723 | case_stmt(details::e_addass , details::add_op) 34724 | case_stmt(details::e_subass , details::sub_op) 34725 | case_stmt(details::e_mulass , details::mul_op) 34726 | case_stmt(details::e_divass , details::div_op) 34727 | case_stmt(details::e_modass , details::mod_op) 34728 | #undef case_stmt 34729 | default : return error_node(); 34730 | } 34731 | } 34732 | else if (details::is_rebasevector_elem_rtc_node(branch[0])) 34733 | { 34734 | lodge_assignment(e_st_vecelem,branch[0]); 34735 | 34736 | switch (operation) 34737 | { 34738 | #define case_stmt(op0, op1) \ 34739 | case op0 : result = node_allocator_-> \ 34740 | template allocate_rrr<typename details::assignment_rebasevec_elem_op_rtc_node<Type,op1<Type> > > \ 34741 | (operation, branch[0], branch[1]); \ 34742 | node_name = "assignment_rebasevec_elem_op_rtc_node" \ 34743 | break; \ 34744 | 34745 | case_stmt(details::e_addass , details::add_op) 34746 | case_stmt(details::e_subass , details::sub_op) 34747 | case_stmt(details::e_mulass , details::mul_op) 34748 | case_stmt(details::e_divass , details::div_op) 34749 | case_stmt(details::e_modass , details::mod_op) 34750 | #undef case_stmt 34751 | default : return error_node(); 34752 | } 34753 | } 34754 | else if (details::is_rebasevector_celem_rtc_node(branch[0])) 34755 | { 34756 | lodge_assignment(e_st_vecelem,branch[0]); 34757 | 34758 | switch (operation) 34759 | { 34760 | #define case_stmt(op0, op1) \ 34761 | case op0 : result = node_allocator_-> \ 34762 | template allocate_rrr<typename details::assignment_rebasevec_celem_op_rtc_node<Type,op1<Type> > > \ 34763 | (operation, branch[0], branch[1]); \ 34764 | node_name = "assignment_rebasevec_celem_op_rtc_node" \ 34765 | break; \ 34766 | 34767 | case_stmt(details::e_addass , details::add_op) 34768 | case_stmt(details::e_subass , details::sub_op) 34769 | case_stmt(details::e_mulass , details::mul_op) 34770 | case_stmt(details::e_divass , details::div_op) 34771 | case_stmt(details::e_modass , details::mod_op) 34772 | #undef case_stmt 34773 | default : return error_node(); 34774 | } 34775 | } 34776 | else if (details::is_vector_node(branch[0])) 34777 | { 34778 | lodge_assignment(e_st_vector,branch[0]); 34779 | 34780 | if (details::is_ivector_node(branch[1])) 34781 | { 34782 | switch (operation) 34783 | { 34784 | #define case_stmt(op0, op1) \ 34785 | case op0 : result = node_allocator_-> \ 34786 | template allocate_rrr<typename details::assignment_vecvec_op_node<Type,op1<Type> > > \ 34787 | (operation, branch[0], branch[1]); \ 34788 | node_name = "assignment_rebasevec_celem_op_node" \ 34789 | break; \ 34790 | 34791 | case_stmt(details::e_addass , details::add_op) 34792 | case_stmt(details::e_subass , details::sub_op) 34793 | case_stmt(details::e_mulass , details::mul_op) 34794 | case_stmt(details::e_divass , details::div_op) 34795 | case_stmt(details::e_modass , details::mod_op) 34796 | #undef case_stmt 34797 | default : return error_node(); 34798 | } 34799 | } 34800 | else 34801 | { 34802 | switch (operation) 34803 | { 34804 | #define case_stmt(op0, op1) \ 34805 | case op0 : result = node_allocator_-> \ 34806 | template allocate_rrr<typename details::assignment_vec_op_node<Type,op1<Type> > > \ 34807 | (operation, branch[0], branch[1]); \ 34808 | node_name = "assignment_vec_op_node" \ 34809 | break; \ 34810 | 34811 | case_stmt(details::e_addass , details::add_op) 34812 | case_stmt(details::e_subass , details::sub_op) 34813 | case_stmt(details::e_mulass , details::mul_op) 34814 | case_stmt(details::e_divass , details::div_op) 34815 | case_stmt(details::e_modass , details::mod_op) 34816 | #undef case_stmt 34817 | default : return error_node(); 34818 | } 34819 | } 34820 | } 34821 | #ifndef exprtk_disable_string_capabilities 34822 | else if ( 34823 | (details::e_addass == operation) && 34824 | details::is_string_node(branch[0]) 34825 | ) 34826 | { 34827 | typedef details::assignment_string_node<T,details::asn_addassignment> addass_t; 34828 | 34829 | lodge_assignment(e_st_string,branch[0]); 34830 | 34831 | result = synthesize_expression<addass_t,2>(operation,branch); 34832 | node_name = "assignment_string_node<T,details::asn_addassignment>" 34833 | } 34834 | #endif 34835 | else 34836 | { 34837 | parser_->set_error(parser_error::make_error( 34838 | parser_error::e_syntax, 34839 | parser_->current_state().token, 34840 | "ERR276 - Invalid branches for assignment operator '" + details::to_str(operation) + "'", 34841 | exprtk_error_location)); 34842 | 34843 | return error_node(); 34844 | } 34845 | 34846 | if (result && result->valid()) 34847 | { 34848 | return result; 34849 | } 34850 | 34851 | parser_->set_error(parser_error::make_error( 34852 | parser_error::e_synthesis, 34853 | token_t(), 34854 | "ERR277 - Failed to synthesize node: " + node_name, 34855 | exprtk_error_location)); 34856 | 34857 | details::free_node(*node_allocator_, result); 34858 | return error_node(); 34859 | } 34860 | 34861 | inline expression_node_ptr synthesize_veceqineqlogic_operation_expression(const details::operator_type& operation, 34862 | expression_node_ptr (&branch)[2]) 34863 | { 34864 | const bool is_b0_ivec = details::is_ivector_node(branch[0]); 34865 | const bool is_b1_ivec = details::is_ivector_node(branch[1]); 34866 | 34867 | #define batch_eqineq_logic_case \ 34868 | case_stmt(details::e_lt , details::lt_op ) \ 34869 | case_stmt(details::e_lte , details::lte_op ) \ 34870 | case_stmt(details::e_gt , details::gt_op ) \ 34871 | case_stmt(details::e_gte , details::gte_op ) \ 34872 | case_stmt(details::e_eq , details::eq_op ) \ 34873 | case_stmt(details::e_ne , details::ne_op ) \ 34874 | case_stmt(details::e_equal , details::equal_op) \ 34875 | case_stmt(details::e_and , details::and_op ) \ 34876 | case_stmt(details::e_nand , details::nand_op ) \ 34877 | case_stmt(details::e_or , details::or_op ) \ 34878 | case_stmt(details::e_nor , details::nor_op ) \ 34879 | case_stmt(details::e_xor , details::xor_op ) \ 34880 | case_stmt(details::e_xnor , details::xnor_op ) \ 34881 | 34882 | expression_node_ptr result = error_node(); 34883 | std::string node_name = "Unknown" 34884 | 34885 | if (is_b0_ivec && is_b1_ivec) 34886 | { 34887 | switch (operation) 34888 | { 34889 | #define case_stmt(op0, op1) \ 34890 | case op0 : result = node_allocator_-> \ 34891 | template allocate_rrr<typename details::vec_binop_vecvec_node<Type,op1<Type> > > \ 34892 | (operation, branch[0], branch[1]); \ 34893 | node_name = "vec_binop_vecvec_node" \ 34894 | break; \ 34895 | 34896 | batch_eqineq_logic_case 34897 | #undef case_stmt 34898 | default : return error_node(); 34899 | } 34900 | } 34901 | else if (is_b0_ivec && !is_b1_ivec) 34902 | { 34903 | switch (operation) 34904 | { 34905 | #define case_stmt(op0, op1) \ 34906 | case op0 : result = node_allocator_-> \ 34907 | template allocate_rrr<typename details::vec_binop_vecval_node<Type,op1<Type> > > \ 34908 | (operation, branch[0], branch[1]); \ 34909 | node_name = "vec_binop_vecval_node" \ 34910 | break; \ 34911 | 34912 | batch_eqineq_logic_case 34913 | #undef case_stmt 34914 | default : return error_node(); 34915 | } 34916 | } 34917 | else if (!is_b0_ivec && is_b1_ivec) 34918 | { 34919 | switch (operation) 34920 | { 34921 | #define case_stmt(op0, op1) \ 34922 | case op0 : result = node_allocator_-> \ 34923 | template allocate_rrr<typename details::vec_binop_valvec_node<Type,op1<Type> > > \ 34924 | (operation, branch[0], branch[1]); \ 34925 | node_name = "vec_binop_valvec_node" \ 34926 | break; \ 34927 | 34928 | batch_eqineq_logic_case 34929 | #undef case_stmt 34930 | default : return error_node(); 34931 | } 34932 | } 34933 | else 34934 | return error_node(); 34935 | 34936 | if (result && result->valid()) 34937 | { 34938 | return result; 34939 | } 34940 | 34941 | parser_->set_error(parser_error::make_error( 34942 | parser_error::e_synthesis, 34943 | token_t(), 34944 | "ERR278 - Failed to synthesize node: " + node_name, 34945 | exprtk_error_location)); 34946 | 34947 | details::free_node(*node_allocator_, result); 34948 | return error_node(); 34949 | 34950 | #undef batch_eqineq_logic_case 34951 | } 34952 | 34953 | inline expression_node_ptr synthesize_vecarithmetic_operation_expression(const details::operator_type& operation, 34954 | expression_node_ptr (&branch)[2]) 34955 | { 34956 | const bool is_b0_ivec = details::is_ivector_node(branch[0]); 34957 | const bool is_b1_ivec = details::is_ivector_node(branch[1]); 34958 | 34959 | #define vector_ops \ 34960 | case_stmt(details::e_add , details::add_op) \ 34961 | case_stmt(details::e_sub , details::sub_op) \ 34962 | case_stmt(details::e_mul , details::mul_op) \ 34963 | case_stmt(details::e_div , details::div_op) \ 34964 | case_stmt(details::e_mod , details::mod_op) \ 34965 | 34966 | expression_node_ptr result = error_node(); 34967 | std::string node_name = "Unknown" 34968 | 34969 | if (is_b0_ivec && is_b1_ivec) 34970 | { 34971 | switch (operation) 34972 | { 34973 | #define case_stmt(op0, op1) \ 34974 | case op0 : result = node_allocator_-> \ 34975 | template allocate_rrr<typename details::vec_binop_vecvec_node<Type,op1<Type> > > \ 34976 | (operation, branch[0], branch[1]); \ 34977 | node_name = "vec_binop_vecvec_node" \ 34978 | break; \ 34979 | 34980 | vector_ops 34981 | case_stmt(details::e_pow,details:: pow_op) 34982 | #undef case_stmt 34983 | default : return error_node(); 34984 | } 34985 | } 34986 | else if (is_b0_ivec && !is_b1_ivec) 34987 | { 34988 | switch (operation) 34989 | { 34990 | #define case_stmt(op0, op1) \ 34991 | case op0 : result = node_allocator_-> \ 34992 | template allocate_rrr<typename details::vec_binop_vecval_node<Type,op1<Type> > > \ 34993 | (operation, branch[0], branch[1]); \ 34994 | node_name = "vec_binop_vecval_node(b0ivec,!b1ivec)" \ 34995 | break; \ 34996 | 34997 | vector_ops 34998 | case_stmt(details::e_pow,details:: pow_op) 34999 | #undef case_stmt 35000 | default : return error_node(); 35001 | } 35002 | } 35003 | else if (!is_b0_ivec && is_b1_ivec) 35004 | { 35005 | switch (operation) 35006 | { 35007 | #define case_stmt(op0, op1) \ 35008 | case op0 : result = node_allocator_-> \ 35009 | template allocate_rrr<typename details::vec_binop_valvec_node<Type,op1<Type> > > \ 35010 | (operation, branch[0], branch[1]); \ 35011 | node_name = "vec_binop_vecval_node(!b0ivec,b1ivec)" \ 35012 | break; \ 35013 | 35014 | vector_ops 35015 | #undef case_stmt 35016 | default : return error_node(); 35017 | } 35018 | } 35019 | else 35020 | return error_node(); 35021 | 35022 | if (result && result->valid()) 35023 | { 35024 | return result; 35025 | } 35026 | 35027 | parser_->set_error(parser_error::make_error( 35028 | parser_error::e_synthesis, 35029 | token_t(), 35030 | "ERR279 - Failed to synthesize node: " + node_name, 35031 | exprtk_error_location)); 35032 | 35033 | details::free_node(*node_allocator_, result); 35034 | return error_node(); 35035 | 35036 | #undef vector_ops 35037 | } 35038 | 35039 | inline expression_node_ptr synthesize_swap_expression(expression_node_ptr (&branch)[2]) 35040 | { 35041 | const bool v0_is_ivar = details::is_ivariable_node(branch[0]); 35042 | const bool v1_is_ivar = details::is_ivariable_node(branch[1]); 35043 | 35044 | const bool v0_is_ivec = details::is_ivector_node (branch[0]); 35045 | const bool v1_is_ivec = details::is_ivector_node (branch[1]); 35046 | 35047 | #ifndef exprtk_disable_string_capabilities 35048 | const bool v0_is_str = details::is_generally_string_node(branch[0]); 35049 | const bool v1_is_str = details::is_generally_string_node(branch[1]); 35050 | #endif 35051 | 35052 | expression_node_ptr result = error_node(); 35053 | std::string node_name = "Unknown" 35054 | 35055 | if (v0_is_ivar && v1_is_ivar) 35056 | { 35057 | typedef details::variable_node<T>* variable_node_ptr; 35058 | 35059 | variable_node_ptr v0 = variable_node_ptr(0); 35060 | variable_node_ptr v1 = variable_node_ptr(0); 35061 | 35062 | if ( 35063 | (0 != (v0 = dynamic_cast<variable_node_ptr>(branch[0]))) && 35064 | (0 != (v1 = dynamic_cast<variable_node_ptr>(branch[1]))) 35065 | ) 35066 | { 35067 | result = node_allocator_->allocate<details::swap_node<T> >(v0,v1); 35068 | node_name = "swap_node" 35069 | } 35070 | else 35071 | { 35072 | result = node_allocator_->allocate<details::swap_generic_node<T> >(branch[0],branch[1]); 35073 | node_name = "swap_generic_node" 35074 | } 35075 | } 35076 | else if (v0_is_ivec && v1_is_ivec) 35077 | { 35078 | result = node_allocator_->allocate<details::swap_vecvec_node<T> >(branch[0],branch[1]); 35079 | node_name = "swap_vecvec_node" 35080 | } 35081 | #ifndef exprtk_disable_string_capabilities 35082 | else if (v0_is_str && v1_is_str) 35083 | { 35084 | if (is_string_node(branch[0]) && is_string_node(branch[1])) 35085 | { 35086 | result = node_allocator_->allocate<details::swap_string_node<T> > 35087 | (branch[0], branch[1]); 35088 | node_name = "swap_string_node" 35089 | } 35090 | else 35091 | { 35092 | result = node_allocator_->allocate<details::swap_genstrings_node<T> > 35093 | (branch[0], branch[1]); 35094 | node_name = "swap_genstrings_node" 35095 | } 35096 | } 35097 | #endif 35098 | else 35099 | { 35100 | parser_->set_synthesis_error("Only variables, strings, vectors or vector elements can be swapped"); 35101 | return error_node(); 35102 | } 35103 | 35104 | if (result && result->valid()) 35105 | { 35106 | parser_->state_.activate_side_effect("synthesize_swap_expression()"); 35107 | return result; 35108 | } 35109 | 35110 | parser_->set_error(parser_error::make_error( 35111 | parser_error::e_synthesis, 35112 | token_t(), 35113 | "ERR280 - Failed to synthesize node: " + node_name, 35114 | exprtk_error_location)); 35115 | 35116 | details::free_node(*node_allocator_, result); 35117 | return error_node(); 35118 | } 35119 | 35120 | #ifndef exprtk_disable_sc_andor 35121 | inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2]) 35122 | { 35123 | expression_node_ptr result = error_node(); 35124 | 35125 | if (details::is_constant_node(branch[0])) 35126 | { 35127 | if ( 35128 | (details::e_scand == operation) && 35129 | std::equal_to<T>()(T(0),branch[0]->value()) 35130 | ) 35131 | result = node_allocator_->allocate_c<literal_node_t>(T(0)); 35132 | else if ( 35133 | (details::e_scor == operation) && 35134 | std::not_equal_to<T>()(T(0),branch[0]->value()) 35135 | ) 35136 | result = node_allocator_->allocate_c<literal_node_t>(T(1)); 35137 | } 35138 | 35139 | if (details::is_constant_node(branch[1]) && (0 == result)) 35140 | { 35141 | if ( 35142 | (details::e_scand == operation) && 35143 | std::equal_to<T>()(T(0),branch[1]->value()) 35144 | ) 35145 | result = node_allocator_->allocate_c<literal_node_t>(T(0)); 35146 | else if ( 35147 | (details::e_scor == operation) && 35148 | std::not_equal_to<T>()(T(0),branch[1]->value()) 35149 | ) 35150 | result = node_allocator_->allocate_c<literal_node_t>(T(1)); 35151 | } 35152 | 35153 | if (result) 35154 | { 35155 | details::free_node(*node_allocator_, branch[0]); 35156 | details::free_node(*node_allocator_, branch[1]); 35157 | 35158 | return result; 35159 | } 35160 | else if (details::e_scand == operation) 35161 | { 35162 | return synthesize_expression<scand_node_t,2>(operation, branch); 35163 | } 35164 | else if (details::e_scor == operation) 35165 | { 35166 | return synthesize_expression<scor_node_t,2>(operation, branch); 35167 | } 35168 | else 35169 | return error_node(); 35170 | } 35171 | #else 35172 | inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type&, expression_node_ptr (&)[2]) 35173 | { 35174 | return error_node(); 35175 | } 35176 | #endif 35177 | 35178 | #define basic_opr_switch_statements \ 35179 | case_stmt(details::e_add , details::add_op) \ 35180 | case_stmt(details::e_sub , details::sub_op) \ 35181 | case_stmt(details::e_mul , details::mul_op) \ 35182 | case_stmt(details::e_div , details::div_op) \ 35183 | case_stmt(details::e_mod , details::mod_op) \ 35184 | case_stmt(details::e_pow , details::pow_op) \ 35185 | 35186 | #define extended_opr_switch_statements \ 35187 | case_stmt(details::e_lt , details::lt_op ) \ 35188 | case_stmt(details::e_lte , details::lte_op ) \ 35189 | case_stmt(details::e_gt , details::gt_op ) \ 35190 | case_stmt(details::e_gte , details::gte_op ) \ 35191 | case_stmt(details::e_eq , details::eq_op ) \ 35192 | case_stmt(details::e_ne , details::ne_op ) \ 35193 | case_stmt(details::e_and , details::and_op ) \ 35194 | case_stmt(details::e_nand , details::nand_op) \ 35195 | case_stmt(details::e_or , details::or_op ) \ 35196 | case_stmt(details::e_nor , details::nor_op ) \ 35197 | case_stmt(details::e_xor , details::xor_op ) \ 35198 | case_stmt(details::e_xnor , details::xnor_op) \ 35199 | 35200 | #ifndef exprtk_disable_cardinal_pow_optimisation 35201 | template <typename TType, template <typename, typename> class IPowNode> 35202 | inline expression_node_ptr cardinal_pow_optimisation_impl(const TType& v, const unsigned int& p) 35203 | { 35204 | switch (p) 35205 | { 35206 | #define case_stmt(cp) \ 35207 | case cp : return node_allocator_-> \ 35208 | allocate<IPowNode<T,details::numeric::fast_exp<T,cp> > >(v); \ 35209 | 35210 | case_stmt( 1) case_stmt( 2) case_stmt( 3) case_stmt( 4) 35211 | case_stmt( 5) case_stmt( 6) case_stmt( 7) case_stmt( 8) 35212 | case_stmt( 9) case_stmt(10) case_stmt(11) case_stmt(12) 35213 | case_stmt(13) case_stmt(14) case_stmt(15) case_stmt(16) 35214 | case_stmt(17) case_stmt(18) case_stmt(19) case_stmt(20) 35215 | case_stmt(21) case_stmt(22) case_stmt(23) case_stmt(24) 35216 | case_stmt(25) case_stmt(26) case_stmt(27) case_stmt(28) 35217 | case_stmt(29) case_stmt(30) case_stmt(31) case_stmt(32) 35218 | case_stmt(33) case_stmt(34) case_stmt(35) case_stmt(36) 35219 | case_stmt(37) case_stmt(38) case_stmt(39) case_stmt(40) 35220 | case_stmt(41) case_stmt(42) case_stmt(43) case_stmt(44) 35221 | case_stmt(45) case_stmt(46) case_stmt(47) case_stmt(48) 35222 | case_stmt(49) case_stmt(50) case_stmt(51) case_stmt(52) 35223 | case_stmt(53) case_stmt(54) case_stmt(55) case_stmt(56) 35224 | case_stmt(57) case_stmt(58) case_stmt(59) case_stmt(60) 35225 | #undef case_stmt 35226 | default : return error_node(); 35227 | } 35228 | } 35229 | 35230 | inline expression_node_ptr cardinal_pow_optimisation(const T& v, const T& c) 35231 | { 35232 | const bool not_recipricol = (c >= T(0)); 35233 | const unsigned int p = static_cast<unsigned int>(details::numeric::to_int32(details::numeric::abs(c))); 35234 | 35235 | if (0 == p) 35236 | return node_allocator_->allocate_c<literal_node_t>(T(1)); 35237 | else if (std::equal_to<T>()(T(2),c)) 35238 | { 35239 | return node_allocator_-> 35240 | template allocate_rr<typename details::vov_node<Type,details::mul_op<Type> > >(v,v); 35241 | } 35242 | else 35243 | { 35244 | if (not_recipricol) 35245 | return cardinal_pow_optimisation_impl<T,details::ipow_node>(v,p); 35246 | else 35247 | return cardinal_pow_optimisation_impl<T,details::ipowinv_node>(v,p); 35248 | } 35249 | } 35250 | 35251 | inline bool cardinal_pow_optimisable(const details::operator_type& operation, const T& c) const 35252 | { 35253 | return (details::e_pow == operation) && (details::numeric::abs(c) <= T(60)) && details::numeric::is_integer(c); 35254 | } 35255 | 35256 | inline expression_node_ptr cardinal_pow_optimisation(expression_node_ptr (&branch)[2]) 35257 | { 35258 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 35259 | const bool not_recipricol = (c >= T(0)); 35260 | const unsigned int p = static_cast<unsigned int>(details::numeric::to_int32(details::numeric::abs(c))); 35261 | 35262 | node_allocator_->free(branch[1]); 35263 | 35264 | if (0 == p) 35265 | { 35266 | details::free_all_nodes(*node_allocator_, branch); 35267 | 35268 | return node_allocator_->allocate_c<literal_node_t>(T(1)); 35269 | } 35270 | else if (not_recipricol) 35271 | return cardinal_pow_optimisation_impl<expression_node_ptr,details::bipow_node>(branch[0],p); 35272 | else 35273 | return cardinal_pow_optimisation_impl<expression_node_ptr,details::bipowinv_node>(branch[0],p); 35274 | } 35275 | #else 35276 | inline expression_node_ptr cardinal_pow_optimisation(T&, const T&) 35277 | { 35278 | return error_node(); 35279 | } 35280 | 35281 | inline bool cardinal_pow_optimisable(const details::operator_type&, const T&) 35282 | { 35283 | return false; 35284 | } 35285 | 35286 | inline expression_node_ptr cardinal_pow_optimisation(expression_node_ptr(&)[2]) 35287 | { 35288 | return error_node(); 35289 | } 35290 | #endif 35291 | 35292 | struct synthesize_binary_ext_expression 35293 | { 35294 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 35295 | const details::operator_type& operation, 35296 | expression_node_ptr (&branch)[2]) 35297 | { 35298 | const bool left_neg = is_neg_unary_node(branch[0]); 35299 | const bool right_neg = is_neg_unary_node(branch[1]); 35300 | 35301 | if (left_neg && right_neg) 35302 | { 35303 | if ( 35304 | (details::e_add == operation) || 35305 | (details::e_sub == operation) || 35306 | (details::e_mul == operation) || 35307 | (details::e_div == operation) 35308 | ) 35309 | { 35310 | if ( 35311 | !expr_gen.parser_->simplify_unary_negation_branch(branch[0]) || 35312 | !expr_gen.parser_->simplify_unary_negation_branch(branch[1]) 35313 | ) 35314 | { 35315 | details::free_all_nodes(*expr_gen.node_allocator_,branch); 35316 | 35317 | return error_node(); 35318 | } 35319 | } 35320 | 35321 | switch (operation) 35322 | { 35323 | // -f(x + 1) + -g(y + 1) --> -(f(x + 1) + g(y + 1)) 35324 | case details::e_add : return expr_gen(details::e_neg, 35325 | expr_gen.node_allocator_-> 35326 | template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > > 35327 | (branch[0],branch[1])); 35328 | 35329 | // -f(x + 1) - -g(y + 1) --> g(y + 1) - f(x + 1) 35330 | case details::e_sub : return expr_gen.node_allocator_-> 35331 | template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > > 35332 | (branch[1],branch[0]); 35333 | 35334 | default : break; 35335 | } 35336 | } 35337 | else if (left_neg && !right_neg) 35338 | { 35339 | if ( 35340 | (details::e_add == operation) || 35341 | (details::e_sub == operation) || 35342 | (details::e_mul == operation) || 35343 | (details::e_div == operation) 35344 | ) 35345 | { 35346 | if (!expr_gen.parser_->simplify_unary_negation_branch(branch[0])) 35347 | { 35348 | details::free_all_nodes(*expr_gen.node_allocator_,branch); 35349 | 35350 | return error_node(); 35351 | } 35352 | 35353 | switch (operation) 35354 | { 35355 | // -f(x + 1) + g(y + 1) --> g(y + 1) - f(x + 1) 35356 | case details::e_add : return expr_gen.node_allocator_-> 35357 | template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > > 35358 | (branch[1], branch[0]); 35359 | 35360 | // -f(x + 1) - g(y + 1) --> -(f(x + 1) + g(y + 1)) 35361 | case details::e_sub : return expr_gen(details::e_neg, 35362 | expr_gen.node_allocator_-> 35363 | template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > > 35364 | (branch[0], branch[1])); 35365 | 35366 | // -f(x + 1) * g(y + 1) --> -(f(x + 1) * g(y + 1)) 35367 | case details::e_mul : return expr_gen(details::e_neg, 35368 | expr_gen.node_allocator_-> 35369 | template allocate<typename details::binary_ext_node<Type,details::mul_op<Type> > > 35370 | (branch[0], branch[1])); 35371 | 35372 | // -f(x + 1) / g(y + 1) --> -(f(x + 1) / g(y + 1)) 35373 | case details::e_div : return expr_gen(details::e_neg, 35374 | expr_gen.node_allocator_-> 35375 | template allocate<typename details::binary_ext_node<Type,details::div_op<Type> > > 35376 | (branch[0], branch[1])); 35377 | 35378 | default : return error_node(); 35379 | } 35380 | } 35381 | } 35382 | else if (!left_neg && right_neg) 35383 | { 35384 | if ( 35385 | (details::e_add == operation) || 35386 | (details::e_sub == operation) || 35387 | (details::e_mul == operation) || 35388 | (details::e_div == operation) 35389 | ) 35390 | { 35391 | if (!expr_gen.parser_->simplify_unary_negation_branch(branch[1])) 35392 | { 35393 | details::free_all_nodes(*expr_gen.node_allocator_,branch); 35394 | 35395 | return error_node(); 35396 | } 35397 | 35398 | switch (operation) 35399 | { 35400 | // f(x + 1) + -g(y + 1) --> f(x + 1) - g(y + 1) 35401 | case details::e_add : return expr_gen.node_allocator_-> 35402 | template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > > 35403 | (branch[0], branch[1]); 35404 | 35405 | // f(x + 1) - - g(y + 1) --> f(x + 1) + g(y + 1) 35406 | case details::e_sub : return expr_gen.node_allocator_-> 35407 | template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > > 35408 | (branch[0], branch[1]); 35409 | 35410 | // f(x + 1) * -g(y + 1) --> -(f(x + 1) * g(y + 1)) 35411 | case details::e_mul : return expr_gen(details::e_neg, 35412 | expr_gen.node_allocator_-> 35413 | template allocate<typename details::binary_ext_node<Type,details::mul_op<Type> > > 35414 | (branch[0], branch[1])); 35415 | 35416 | // f(x + 1) / -g(y + 1) --> -(f(x + 1) / g(y + 1)) 35417 | case details::e_div : return expr_gen(details::e_neg, 35418 | expr_gen.node_allocator_-> 35419 | template allocate<typename details::binary_ext_node<Type,details::div_op<Type> > > 35420 | (branch[0], branch[1])); 35421 | 35422 | default : return error_node(); 35423 | } 35424 | } 35425 | } 35426 | 35427 | switch (operation) 35428 | { 35429 | #define case_stmt(op0, op1) \ 35430 | case op0 : return expr_gen.node_allocator_-> \ 35431 | template allocate<typename details::binary_ext_node<Type,op1<Type> > > \ 35432 | (branch[0], branch[1]); \ 35433 | 35434 | basic_opr_switch_statements 35435 | extended_opr_switch_statements 35436 | #undef case_stmt 35437 | default : return error_node(); 35438 | } 35439 | } 35440 | }; 35441 | 35442 | struct synthesize_vob_expression 35443 | { 35444 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 35445 | const details::operator_type& operation, 35446 | expression_node_ptr (&branch)[2]) 35447 | { 35448 | const Type& v = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 35449 | 35450 | #ifndef exprtk_disable_enhanced_features 35451 | if (details::is_sf3ext_node(branch[1])) 35452 | { 35453 | expression_node_ptr result = error_node(); 35454 | 35455 | const bool synthesis_result = 35456 | synthesize_sf4ext_expression::template compile_right<vtype> 35457 | (expr_gen, v, operation, branch[1], result); 35458 | 35459 | if (synthesis_result) 35460 | { 35461 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35462 | return result; 35463 | } 35464 | } 35465 | #endif 35466 | 35467 | if ( 35468 | (details::e_mul == operation) || 35469 | (details::e_div == operation) 35470 | ) 35471 | { 35472 | if (details::is_uv_node(branch[1])) 35473 | { 35474 | typedef details::uv_base_node<Type>* uvbn_ptr_t; 35475 | 35476 | details::operator_type o = static_cast<uvbn_ptr_t>(branch[1])->operation(); 35477 | 35478 | if (details::e_neg == o) 35479 | { 35480 | const Type& v1 = static_cast<uvbn_ptr_t>(branch[1])->v(); 35481 | 35482 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35483 | 35484 | switch (operation) 35485 | { 35486 | case details::e_mul : return expr_gen(details::e_neg, 35487 | expr_gen.node_allocator_-> 35488 | template allocate_rr<typename details:: 35489 | vov_node<Type,details::mul_op<Type> > >(v,v1)); 35490 | 35491 | case details::e_div : return expr_gen(details::e_neg, 35492 | expr_gen.node_allocator_-> 35493 | template allocate_rr<typename details:: 35494 | vov_node<Type,details::div_op<Type> > >(v,v1)); 35495 | 35496 | default : break; 35497 | } 35498 | } 35499 | } 35500 | } 35501 | 35502 | switch (operation) 35503 | { 35504 | #define case_stmt(op0, op1) \ 35505 | case op0 : return expr_gen.node_allocator_-> \ 35506 | template allocate_rc<typename details::vob_node<Type,op1<Type> > > \ 35507 | (v, branch[1]); \ 35508 | 35509 | basic_opr_switch_statements 35510 | extended_opr_switch_statements 35511 | #undef case_stmt 35512 | default : return error_node(); 35513 | } 35514 | } 35515 | }; 35516 | 35517 | struct synthesize_bov_expression 35518 | { 35519 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 35520 | const details::operator_type& operation, 35521 | expression_node_ptr (&branch)[2]) 35522 | { 35523 | const Type& v = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 35524 | 35525 | #ifndef exprtk_disable_enhanced_features 35526 | if (details::is_sf3ext_node(branch[0])) 35527 | { 35528 | expression_node_ptr result = error_node(); 35529 | 35530 | const bool synthesis_result = 35531 | synthesize_sf4ext_expression::template compile_left<vtype> 35532 | (expr_gen, v, operation, branch[0], result); 35533 | 35534 | if (synthesis_result) 35535 | { 35536 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35537 | 35538 | return result; 35539 | } 35540 | } 35541 | #endif 35542 | 35543 | if ( 35544 | (details::e_add == operation) || 35545 | (details::e_sub == operation) || 35546 | (details::e_mul == operation) || 35547 | (details::e_div == operation) 35548 | ) 35549 | { 35550 | if (details::is_uv_node(branch[0])) 35551 | { 35552 | typedef details::uv_base_node<Type>* uvbn_ptr_t; 35553 | 35554 | details::operator_type o = static_cast<uvbn_ptr_t>(branch[0])->operation(); 35555 | 35556 | if (details::e_neg == o) 35557 | { 35558 | const Type& v0 = static_cast<uvbn_ptr_t>(branch[0])->v(); 35559 | 35560 | details::free_node(*expr_gen.node_allocator_,branch[0]); 35561 | 35562 | switch (operation) 35563 | { 35564 | case details::e_add : return expr_gen.node_allocator_-> 35565 | template allocate_rr<typename details:: 35566 | vov_node<Type,details::sub_op<Type> > >(v,v0); 35567 | 35568 | case details::e_sub : return expr_gen(details::e_neg, 35569 | expr_gen.node_allocator_-> 35570 | template allocate_rr<typename details:: 35571 | vov_node<Type,details::add_op<Type> > >(v0,v)); 35572 | 35573 | case details::e_mul : return expr_gen(details::e_neg, 35574 | expr_gen.node_allocator_-> 35575 | template allocate_rr<typename details:: 35576 | vov_node<Type,details::mul_op<Type> > >(v0,v)); 35577 | 35578 | case details::e_div : return expr_gen(details::e_neg, 35579 | expr_gen.node_allocator_-> 35580 | template allocate_rr<typename details:: 35581 | vov_node<Type,details::div_op<Type> > >(v0,v)); 35582 | default : break; 35583 | } 35584 | } 35585 | } 35586 | } 35587 | 35588 | switch (operation) 35589 | { 35590 | #define case_stmt(op0, op1) \ 35591 | case op0 : return expr_gen.node_allocator_-> \ 35592 | template allocate_cr<typename details::bov_node<Type,op1<Type> > > \ 35593 | (branch[0], v); \ 35594 | 35595 | basic_opr_switch_statements 35596 | extended_opr_switch_statements 35597 | #undef case_stmt 35598 | default : return error_node(); 35599 | } 35600 | } 35601 | }; 35602 | 35603 | struct synthesize_cob_expression 35604 | { 35605 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 35606 | const details::operator_type& operation, 35607 | expression_node_ptr (&branch)[2]) 35608 | { 35609 | const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); 35610 | 35611 | details::free_node(*expr_gen.node_allocator_,branch[0]); 35612 | 35613 | if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation)) 35614 | { 35615 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35616 | 35617 | return expr_gen(T(0)); 35618 | } 35619 | else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation)) 35620 | { 35621 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35622 | 35623 | return expr_gen(T(0)); 35624 | } 35625 | else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation)) 35626 | return branch[1]; 35627 | else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation)) 35628 | return branch[1]; 35629 | 35630 | if (details::is_cob_node(branch[1])) 35631 | { 35632 | // Simplify expressions of the form: 35633 | // 1. (1 * (2 * (3 * (4 * (5 * (6 * (7 * (8 * (9 + x))))))))) --> 40320 * (9 + x) 35634 | // 2. (1 + (2 + (3 + (4 + (5 + (6 + (7 + (8 + (9 + x))))))))) --> 45 + x 35635 | if ( 35636 | (details::e_mul == operation) || 35637 | (details::e_add == operation) 35638 | ) 35639 | { 35640 | details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]); 35641 | 35642 | if (operation == cobnode->operation()) 35643 | { 35644 | switch (operation) 35645 | { 35646 | case details::e_add : cobnode->set_c(c + cobnode->c()); break; 35647 | case details::e_mul : cobnode->set_c(c * cobnode->c()); break; 35648 | default : return error_node(); 35649 | } 35650 | 35651 | return cobnode; 35652 | } 35653 | } 35654 | 35655 | if (operation == details::e_mul) 35656 | { 35657 | details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]); 35658 | details::operator_type cob_opr = cobnode->operation(); 35659 | 35660 | if ( 35661 | (details::e_div == cob_opr) || 35662 | (details::e_mul == cob_opr) 35663 | ) 35664 | { 35665 | switch (cob_opr) 35666 | { 35667 | case details::e_div : cobnode->set_c(c * cobnode->c()); break; 35668 | case details::e_mul : cobnode->set_c(cobnode->c() / c); break; 35669 | default : return error_node(); 35670 | } 35671 | 35672 | return cobnode; 35673 | } 35674 | } 35675 | else if (operation == details::e_div) 35676 | { 35677 | details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]); 35678 | details::operator_type cob_opr = cobnode->operation(); 35679 | 35680 | if ( 35681 | (details::e_div == cob_opr) || 35682 | (details::e_mul == cob_opr) 35683 | ) 35684 | { 35685 | details::expression_node<Type>* new_cobnode = error_node(); 35686 | 35687 | switch (cob_opr) 35688 | { 35689 | case details::e_div : new_cobnode = expr_gen.node_allocator_-> 35690 | template allocate_tt<typename details::cob_node<Type,details::mul_op<Type> > > 35691 | (c / cobnode->c(), cobnode->move_branch(0)); 35692 | break; 35693 | 35694 | case details::e_mul : new_cobnode = expr_gen.node_allocator_-> 35695 | template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > > 35696 | (c / cobnode->c(), cobnode->move_branch(0)); 35697 | break; 35698 | 35699 | default : return error_node(); 35700 | } 35701 | 35702 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35703 | 35704 | return new_cobnode; 35705 | } 35706 | } 35707 | } 35708 | #ifndef exprtk_disable_enhanced_features 35709 | else if (details::is_sf3ext_node(branch[1])) 35710 | { 35711 | expression_node_ptr result = error_node(); 35712 | 35713 | const bool synthesis_result = 35714 | synthesize_sf4ext_expression::template compile_right<ctype> 35715 | (expr_gen, c, operation, branch[1], result); 35716 | 35717 | if (synthesis_result) 35718 | { 35719 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35720 | 35721 | return result; 35722 | } 35723 | } 35724 | #endif 35725 | 35726 | switch (operation) 35727 | { 35728 | #define case_stmt(op0, op1) \ 35729 | case op0 : return expr_gen.node_allocator_-> \ 35730 | template allocate_tt<typename details::cob_node<Type,op1<Type> > > \ 35731 | (c, branch[1]); \ 35732 | 35733 | basic_opr_switch_statements 35734 | extended_opr_switch_statements 35735 | #undef case_stmt 35736 | default : return error_node(); 35737 | } 35738 | } 35739 | }; 35740 | 35741 | struct synthesize_boc_expression 35742 | { 35743 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 35744 | const details::operator_type& operation, 35745 | expression_node_ptr (&branch)[2]) 35746 | { 35747 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 35748 | 35749 | details::free_node(*(expr_gen.node_allocator_), branch[1]); 35750 | 35751 | if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation)) 35752 | { 35753 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35754 | 35755 | return expr_gen(T(0)); 35756 | } 35757 | else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation)) 35758 | { 35759 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35760 | 35761 | return expr_gen(std::numeric_limits<T>::quiet_NaN()); 35762 | } 35763 | else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation)) 35764 | return branch[0]; 35765 | else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation)) 35766 | return branch[0]; 35767 | 35768 | if (details::is_boc_node(branch[0])) 35769 | { 35770 | // Simplify expressions of the form: 35771 | // 1. (((((((((x + 9) * 8) * 7) * 6) * 5) * 4) * 3) * 2) * 1) --> (x + 9) * 40320 35772 | // 2. (((((((((x + 9) + 8) + 7) + 6) + 5) + 4) + 3) + 2) + 1) --> x + 45 35773 | if ( 35774 | (details::e_mul == operation) || 35775 | (details::e_add == operation) 35776 | ) 35777 | { 35778 | details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]); 35779 | 35780 | if (operation == bocnode->operation()) 35781 | { 35782 | switch (operation) 35783 | { 35784 | case details::e_add : bocnode->set_c(c + bocnode->c()); break; 35785 | case details::e_mul : bocnode->set_c(c * bocnode->c()); break; 35786 | default : return error_node(); 35787 | } 35788 | 35789 | return bocnode; 35790 | } 35791 | } 35792 | else if (operation == details::e_div) 35793 | { 35794 | details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]); 35795 | details::operator_type boc_opr = bocnode->operation(); 35796 | 35797 | if ( 35798 | (details::e_div == boc_opr) || 35799 | (details::e_mul == boc_opr) 35800 | ) 35801 | { 35802 | switch (boc_opr) 35803 | { 35804 | case details::e_div : bocnode->set_c(c * bocnode->c()); break; 35805 | case details::e_mul : bocnode->set_c(bocnode->c() / c); break; 35806 | default : return error_node(); 35807 | } 35808 | 35809 | return bocnode; 35810 | } 35811 | } 35812 | else if (operation == details::e_pow) 35813 | { 35814 | // (v ^ c0) ^ c1 --> v ^(c0 * c1) 35815 | details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]); 35816 | details::operator_type boc_opr = bocnode->operation(); 35817 | 35818 | if (details::e_pow == boc_opr) 35819 | { 35820 | bocnode->set_c(bocnode->c() * c); 35821 | 35822 | return bocnode; 35823 | } 35824 | } 35825 | } 35826 | 35827 | #ifndef exprtk_disable_enhanced_features 35828 | if (details::is_sf3ext_node(branch[0])) 35829 | { 35830 | expression_node_ptr result = error_node(); 35831 | 35832 | const bool synthesis_result = 35833 | synthesize_sf4ext_expression::template compile_left<ctype> 35834 | (expr_gen, c, operation, branch[0], result); 35835 | 35836 | if (synthesis_result) 35837 | { 35838 | free_node(*expr_gen.node_allocator_, branch[0]); 35839 | 35840 | return result; 35841 | } 35842 | } 35843 | #endif 35844 | 35845 | switch (operation) 35846 | { 35847 | #define case_stmt(op0, op1) \ 35848 | case op0 : return expr_gen.node_allocator_-> \ 35849 | template allocate_cr<typename details::boc_node<Type,op1<Type> > > \ 35850 | (branch[0], c); \ 35851 | 35852 | basic_opr_switch_statements 35853 | extended_opr_switch_statements 35854 | #undef case_stmt 35855 | default : return error_node(); 35856 | } 35857 | } 35858 | }; 35859 | 35860 | struct synthesize_cocob_expression 35861 | { 35862 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 35863 | const details::operator_type& operation, 35864 | expression_node_ptr (&branch)[2]) 35865 | { 35866 | expression_node_ptr result = error_node(); 35867 | 35868 | // (cob) o c --> cob 35869 | if (details::is_cob_node(branch[0])) 35870 | { 35871 | details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[0]); 35872 | 35873 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 35874 | 35875 | if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation)) 35876 | { 35877 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35878 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35879 | 35880 | return expr_gen(T(0)); 35881 | } 35882 | else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation)) 35883 | { 35884 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35885 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35886 | 35887 | return expr_gen(T(std::numeric_limits<T>::quiet_NaN())); 35888 | } 35889 | else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation)) 35890 | { 35891 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35892 | 35893 | return branch[0]; 35894 | } 35895 | else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation)) 35896 | { 35897 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35898 | 35899 | return branch[0]; 35900 | } 35901 | else if (std::equal_to<T>()(T(1),c) && (details::e_div == operation)) 35902 | { 35903 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35904 | 35905 | return branch[0]; 35906 | } 35907 | 35908 | const bool op_addsub = (details::e_add == cobnode->operation()) || 35909 | (details::e_sub == cobnode->operation()) ; 35910 | 35911 | if (op_addsub) 35912 | { 35913 | switch (operation) 35914 | { 35915 | case details::e_add : cobnode->set_c(cobnode->c() + c); break; 35916 | case details::e_sub : cobnode->set_c(cobnode->c() - c); break; 35917 | default : return error_node(); 35918 | } 35919 | 35920 | result = cobnode; 35921 | } 35922 | else if (details::e_mul == cobnode->operation()) 35923 | { 35924 | switch (operation) 35925 | { 35926 | case details::e_mul : cobnode->set_c(cobnode->c() * c); break; 35927 | case details::e_div : cobnode->set_c(cobnode->c() / c); break; 35928 | default : return error_node(); 35929 | } 35930 | 35931 | result = cobnode; 35932 | } 35933 | else if (details::e_div == cobnode->operation()) 35934 | { 35935 | if (details::e_mul == operation) 35936 | { 35937 | cobnode->set_c(cobnode->c() * c); 35938 | result = cobnode; 35939 | } 35940 | else if (details::e_div == operation) 35941 | { 35942 | result = expr_gen.node_allocator_-> 35943 | template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > > 35944 | (cobnode->c() / c, cobnode->move_branch(0)); 35945 | 35946 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35947 | } 35948 | } 35949 | 35950 | if (result) 35951 | { 35952 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35953 | } 35954 | } 35955 | 35956 | // c o (cob) --> cob 35957 | else if (details::is_cob_node(branch[1])) 35958 | { 35959 | details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]); 35960 | 35961 | const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); 35962 | 35963 | if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation)) 35964 | { 35965 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35966 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35967 | 35968 | return expr_gen(T(0)); 35969 | } 35970 | else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation)) 35971 | { 35972 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35973 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35974 | 35975 | return expr_gen(T(0)); 35976 | } 35977 | else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation)) 35978 | { 35979 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35980 | 35981 | return branch[1]; 35982 | } 35983 | else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation)) 35984 | { 35985 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35986 | 35987 | return branch[1]; 35988 | } 35989 | 35990 | if (details::e_add == cobnode->operation()) 35991 | { 35992 | if (details::e_add == operation) 35993 | { 35994 | cobnode->set_c(c + cobnode->c()); 35995 | result = cobnode; 35996 | } 35997 | else if (details::e_sub == operation) 35998 | { 35999 | result = expr_gen.node_allocator_-> 36000 | template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > > 36001 | (c - cobnode->c(), cobnode->move_branch(0)); 36002 | 36003 | details::free_node(*expr_gen.node_allocator_,branch[1]); 36004 | } 36005 | } 36006 | else if (details::e_sub == cobnode->operation()) 36007 | { 36008 | if (details::e_add == operation) 36009 | { 36010 | cobnode->set_c(c + cobnode->c()); 36011 | result = cobnode; 36012 | } 36013 | else if (details::e_sub == operation) 36014 | { 36015 | result = expr_gen.node_allocator_-> 36016 | template allocate_tt<typename details::cob_node<Type,details::add_op<Type> > > 36017 | (c - cobnode->c(), cobnode->move_branch(0)); 36018 | 36019 | details::free_node(*expr_gen.node_allocator_,branch[1]); 36020 | } 36021 | } 36022 | else if (details::e_mul == cobnode->operation()) 36023 | { 36024 | if (details::e_mul == operation) 36025 | { 36026 | cobnode->set_c(c * cobnode->c()); 36027 | result = cobnode; 36028 | } 36029 | else if (details::e_div == operation) 36030 | { 36031 | result = expr_gen.node_allocator_-> 36032 | template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > > 36033 | (c / cobnode->c(), cobnode->move_branch(0)); 36034 | 36035 | details::free_node(*expr_gen.node_allocator_,branch[1]); 36036 | } 36037 | } 36038 | else if (details::e_div == cobnode->operation()) 36039 | { 36040 | if (details::e_mul == operation) 36041 | { 36042 | cobnode->set_c(c * cobnode->c()); 36043 | result = cobnode; 36044 | } 36045 | else if (details::e_div == operation) 36046 | { 36047 | result = expr_gen.node_allocator_-> 36048 | template allocate_tt<typename details::cob_node<Type,details::mul_op<Type> > > 36049 | (c / cobnode->c(), cobnode->move_branch(0)); 36050 | 36051 | details::free_node(*expr_gen.node_allocator_,branch[1]); 36052 | } 36053 | } 36054 | 36055 | if (result) 36056 | { 36057 | details::free_node(*expr_gen.node_allocator_,branch[0]); 36058 | } 36059 | } 36060 | 36061 | return result; 36062 | } 36063 | }; 36064 | 36065 | struct synthesize_coboc_expression 36066 | { 36067 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36068 | const details::operator_type& operation, 36069 | expression_node_ptr (&branch)[2]) 36070 | { 36071 | expression_node_ptr result = error_node(); 36072 | 36073 | // (boc) o c --> boc 36074 | if (details::is_boc_node(branch[0])) 36075 | { 36076 | details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]); 36077 | 36078 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 36079 | 36080 | if (details::e_add == bocnode->operation()) 36081 | { 36082 | switch (operation) 36083 | { 36084 | case details::e_add : bocnode->set_c(bocnode->c() + c); break; 36085 | case details::e_sub : bocnode->set_c(bocnode->c() - c); break; 36086 | default : return error_node(); 36087 | } 36088 | 36089 | result = bocnode; 36090 | } 36091 | else if (details::e_mul == bocnode->operation()) 36092 | { 36093 | switch (operation) 36094 | { 36095 | case details::e_mul : bocnode->set_c(bocnode->c() * c); break; 36096 | case details::e_div : bocnode->set_c(bocnode->c() / c); break; 36097 | default : return error_node(); 36098 | } 36099 | 36100 | result = bocnode; 36101 | } 36102 | else if (details::e_sub == bocnode->operation()) 36103 | { 36104 | if (details::e_add == operation) 36105 | { 36106 | result = expr_gen.node_allocator_-> 36107 | template allocate_tt<typename details::boc_node<Type,details::add_op<Type> > > 36108 | (bocnode->move_branch(0), c - bocnode->c()); 36109 | 36110 | details::free_node(*expr_gen.node_allocator_,branch[0]); 36111 | } 36112 | else if (details::e_sub == operation) 36113 | { 36114 | bocnode->set_c(bocnode->c() + c); 36115 | result = bocnode; 36116 | } 36117 | } 36118 | else if (details::e_div == bocnode->operation()) 36119 | { 36120 | switch (operation) 36121 | { 36122 | case details::e_div : bocnode->set_c(bocnode->c() * c); break; 36123 | case details::e_mul : bocnode->set_c(bocnode->c() / c); break; 36124 | default : return error_node(); 36125 | } 36126 | 36127 | result = bocnode; 36128 | } 36129 | 36130 | if (result) 36131 | { 36132 | details::free_node(*expr_gen.node_allocator_, branch[1]); 36133 | } 36134 | } 36135 | 36136 | // c o (boc) --> boc 36137 | else if (details::is_boc_node(branch[1])) 36138 | { 36139 | details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[1]); 36140 | 36141 | const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); 36142 | 36143 | if (details::e_add == bocnode->operation()) 36144 | { 36145 | if (details::e_add == operation) 36146 | { 36147 | bocnode->set_c(c + bocnode->c()); 36148 | result = bocnode; 36149 | } 36150 | else if (details::e_sub == operation) 36151 | { 36152 | result = expr_gen.node_allocator_-> 36153 | template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > > 36154 | (c - bocnode->c(), bocnode->move_branch(0)); 36155 | 36156 | details::free_node(*expr_gen.node_allocator_,branch[1]); 36157 | } 36158 | } 36159 | else if (details::e_sub == bocnode->operation()) 36160 | { 36161 | if (details::e_add == operation) 36162 | { 36163 | result = expr_gen.node_allocator_-> 36164 | template allocate_tt<typename details::boc_node<Type,details::add_op<Type> > > 36165 | (bocnode->move_branch(0), c - bocnode->c()); 36166 | 36167 | details::free_node(*expr_gen.node_allocator_,branch[1]); 36168 | } 36169 | else if (details::e_sub == operation) 36170 | { 36171 | result = expr_gen.node_allocator_-> 36172 | template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > > 36173 | (c + bocnode->c(), bocnode->move_branch(0)); 36174 | 36175 | details::free_node(*expr_gen.node_allocator_,branch[1]); 36176 | } 36177 | } 36178 | else if (details::e_mul == bocnode->operation()) 36179 | { 36180 | if (details::e_mul == operation) 36181 | { 36182 | bocnode->set_c(c * bocnode->c()); 36183 | result = bocnode; 36184 | } 36185 | else if (details::e_div == operation) 36186 | { 36187 | result = expr_gen.node_allocator_-> 36188 | template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > > 36189 | (c / bocnode->c(), bocnode->move_branch(0)); 36190 | 36191 | details::free_node(*expr_gen.node_allocator_,branch[1]); 36192 | } 36193 | } 36194 | else if (details::e_div == bocnode->operation()) 36195 | { 36196 | if (details::e_mul == operation) 36197 | { 36198 | bocnode->set_c(bocnode->c() / c); 36199 | result = bocnode; 36200 | } 36201 | else if (details::e_div == operation) 36202 | { 36203 | result = expr_gen.node_allocator_-> 36204 | template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > > 36205 | (c * bocnode->c(), bocnode->move_branch(0)); 36206 | 36207 | details::free_node(*expr_gen.node_allocator_,branch[1]); 36208 | } 36209 | } 36210 | 36211 | if (result) 36212 | { 36213 | details::free_node(*expr_gen.node_allocator_,branch[0]); 36214 | } 36215 | } 36216 | 36217 | return result; 36218 | } 36219 | }; 36220 | 36221 | #ifndef exprtk_disable_enhanced_features 36222 | inline bool synthesize_expression(const details::operator_type& operation, 36223 | expression_node_ptr (&branch)[2], 36224 | expression_node_ptr& result) 36225 | { 36226 | result = error_node(); 36227 | 36228 | if (!operation_optimisable(operation)) 36229 | return false; 36230 | 36231 | const std::string node_id = branch_to_id(branch); 36232 | 36233 | const typename synthesize_map_t::iterator itr = synthesize_map_.find(node_id); 36234 | 36235 | if (synthesize_map_.end() != itr) 36236 | { 36237 | result = itr->second((*this), operation, branch); 36238 | 36239 | return true; 36240 | } 36241 | else 36242 | return false; 36243 | } 36244 | 36245 | struct synthesize_vov_expression 36246 | { 36247 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36248 | const details::operator_type& operation, 36249 | expression_node_ptr (&branch)[2]) 36250 | { 36251 | const Type& v1 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 36252 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 36253 | 36254 | switch (operation) 36255 | { 36256 | #define case_stmt(op0, op1) \ 36257 | case op0 : return expr_gen.node_allocator_-> \ 36258 | template allocate_rr<typename details::vov_node<Type,op1<Type> > > \ 36259 | (v1, v2); \ 36260 | 36261 | basic_opr_switch_statements 36262 | extended_opr_switch_statements 36263 | #undef case_stmt 36264 | default : return error_node(); 36265 | } 36266 | } 36267 | }; 36268 | 36269 | struct synthesize_cov_expression 36270 | { 36271 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36272 | const details::operator_type& operation, 36273 | expression_node_ptr (&branch)[2]) 36274 | { 36275 | const Type c = static_cast<details::literal_node<Type>*> (branch[0])->value(); 36276 | const Type& v = static_cast<details::variable_node<Type>*>(branch[1])->ref (); 36277 | 36278 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 36279 | 36280 | if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation)) 36281 | return expr_gen(T(0)); 36282 | else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation)) 36283 | return expr_gen(T(0)); 36284 | else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation)) 36285 | return static_cast<details::variable_node<Type>*>(branch[1]); 36286 | else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation)) 36287 | return static_cast<details::variable_node<Type>*>(branch[1]); 36288 | 36289 | switch (operation) 36290 | { 36291 | #define case_stmt(op0, op1) \ 36292 | case op0 : return expr_gen.node_allocator_-> \ 36293 | template allocate_cr<typename details::cov_node<Type,op1<Type> > > \ 36294 | (c, v); \ 36295 | 36296 | basic_opr_switch_statements 36297 | extended_opr_switch_statements 36298 | #undef case_stmt 36299 | default : return error_node(); 36300 | } 36301 | } 36302 | }; 36303 | 36304 | struct synthesize_voc_expression 36305 | { 36306 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36307 | const details::operator_type& operation, 36308 | expression_node_ptr (&branch)[2]) 36309 | { 36310 | const Type& v = static_cast<details::variable_node<Type>*>(branch[0])->ref (); 36311 | const Type c = static_cast<details::literal_node<Type>*> (branch[1])->value(); 36312 | 36313 | details::free_node(*(expr_gen.node_allocator_), branch[1]); 36314 | 36315 | if (expr_gen.cardinal_pow_optimisable(operation,c)) 36316 | { 36317 | if (std::equal_to<T>()(T(1),c)) 36318 | return branch[0]; 36319 | else 36320 | return expr_gen.cardinal_pow_optimisation(v,c); 36321 | } 36322 | else if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation)) 36323 | return expr_gen(T(0)); 36324 | else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation)) 36325 | return expr_gen(std::numeric_limits<T>::quiet_NaN()); 36326 | else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation)) 36327 | return static_cast<details::variable_node<Type>*>(branch[0]); 36328 | else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation)) 36329 | return static_cast<details::variable_node<Type>*>(branch[0]); 36330 | else if (std::equal_to<T>()(T(1),c) && (details::e_div == operation)) 36331 | return static_cast<details::variable_node<Type>*>(branch[0]); 36332 | 36333 | switch (operation) 36334 | { 36335 | #define case_stmt(op0, op1) \ 36336 | case op0 : return expr_gen.node_allocator_-> \ 36337 | template allocate_rc<typename details::voc_node<Type,op1<Type> > > \ 36338 | (v, c); \ 36339 | 36340 | basic_opr_switch_statements 36341 | extended_opr_switch_statements 36342 | #undef case_stmt 36343 | default : return error_node(); 36344 | } 36345 | } 36346 | }; 36347 | 36348 | struct synthesize_sf3ext_expression 36349 | { 36350 | template <typename T0, typename T1, typename T2> 36351 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36352 | const details::operator_type& sf3opr, 36353 | T0 t0, T1 t1, T2 t2) 36354 | { 36355 | switch (sf3opr) 36356 | { 36357 | #define case_stmt(op) \ 36358 | case details::e_sf##op : return details::T0oT1oT2_sf3ext<T,T0,T1,T2,details::sf##op##_op<Type> >:: \ 36359 | allocate(*(expr_gen.node_allocator_), t0, t1, t2); \ 36360 | 36361 | case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03) 36362 | case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07) 36363 | case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11) 36364 | case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15) 36365 | case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19) 36366 | case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23) 36367 | case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27) 36368 | case_stmt(28) case_stmt(29) case_stmt(30) 36369 | #undef case_stmt 36370 | default : return error_node(); 36371 | } 36372 | } 36373 | 36374 | template <typename T0, typename T1, typename T2> 36375 | static inline bool compile(expression_generator<Type>& expr_gen, const std::string& id, 36376 | T0 t0, T1 t1, T2 t2, 36377 | expression_node_ptr& result) 36378 | { 36379 | details::operator_type sf3opr; 36380 | 36381 | if (!expr_gen.sf3_optimisable(id,sf3opr)) 36382 | return false; 36383 | else 36384 | result = synthesize_sf3ext_expression::template process<T0, T1, T2> 36385 | (expr_gen, sf3opr, t0, t1, t2); 36386 | 36387 | return true; 36388 | } 36389 | }; 36390 | 36391 | struct synthesize_sf4ext_expression 36392 | { 36393 | template <typename T0, typename T1, typename T2, typename T3> 36394 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36395 | const details::operator_type& sf4opr, 36396 | T0 t0, T1 t1, T2 t2, T3 t3) 36397 | { 36398 | switch (sf4opr) 36399 | { 36400 | #define case_stmt0(op) \ 36401 | case details::e_sf##op : return details::T0oT1oT2oT3_sf4ext<Type,T0,T1,T2,T3,details::sf##op##_op<Type> >:: \ 36402 | allocate(*(expr_gen.node_allocator_), t0, t1, t2, t3); \ 36403 | 36404 | #define case_stmt1(op) \ 36405 | case details::e_sf4ext##op : return details::T0oT1oT2oT3_sf4ext<Type,T0,T1,T2,T3,details::sfext##op##_op<Type> >:: \ 36406 | allocate(*(expr_gen.node_allocator_), t0, t1, t2, t3); \ 36407 | 36408 | case_stmt0(48) case_stmt0(49) case_stmt0(50) case_stmt0(51) 36409 | case_stmt0(52) case_stmt0(53) case_stmt0(54) case_stmt0(55) 36410 | case_stmt0(56) case_stmt0(57) case_stmt0(58) case_stmt0(59) 36411 | case_stmt0(60) case_stmt0(61) case_stmt0(62) case_stmt0(63) 36412 | case_stmt0(64) case_stmt0(65) case_stmt0(66) case_stmt0(67) 36413 | case_stmt0(68) case_stmt0(69) case_stmt0(70) case_stmt0(71) 36414 | case_stmt0(72) case_stmt0(73) case_stmt0(74) case_stmt0(75) 36415 | case_stmt0(76) case_stmt0(77) case_stmt0(78) case_stmt0(79) 36416 | case_stmt0(80) case_stmt0(81) case_stmt0(82) case_stmt0(83) 36417 | 36418 | case_stmt1(00) case_stmt1(01) case_stmt1(02) case_stmt1(03) 36419 | case_stmt1(04) case_stmt1(05) case_stmt1(06) case_stmt1(07) 36420 | case_stmt1(08) case_stmt1(09) case_stmt1(10) case_stmt1(11) 36421 | case_stmt1(12) case_stmt1(13) case_stmt1(14) case_stmt1(15) 36422 | case_stmt1(16) case_stmt1(17) case_stmt1(18) case_stmt1(19) 36423 | case_stmt1(20) case_stmt1(21) case_stmt1(22) case_stmt1(23) 36424 | case_stmt1(24) case_stmt1(25) case_stmt1(26) case_stmt1(27) 36425 | case_stmt1(28) case_stmt1(29) case_stmt1(30) case_stmt1(31) 36426 | case_stmt1(32) case_stmt1(33) case_stmt1(34) case_stmt1(35) 36427 | case_stmt1(36) case_stmt1(37) case_stmt1(38) case_stmt1(39) 36428 | case_stmt1(40) case_stmt1(41) case_stmt1(42) case_stmt1(43) 36429 | case_stmt1(44) case_stmt1(45) case_stmt1(46) case_stmt1(47) 36430 | case_stmt1(48) case_stmt1(49) case_stmt1(50) case_stmt1(51) 36431 | case_stmt1(52) case_stmt1(53) case_stmt1(54) case_stmt1(55) 36432 | case_stmt1(56) case_stmt1(57) case_stmt1(58) case_stmt1(59) 36433 | case_stmt1(60) case_stmt1(61) 36434 | 36435 | #undef case_stmt0 36436 | #undef case_stmt1 36437 | default : return error_node(); 36438 | } 36439 | } 36440 | 36441 | template <typename T0, typename T1, typename T2, typename T3> 36442 | static inline bool compile(expression_generator<Type>& expr_gen, const std::string& id, 36443 | T0 t0, T1 t1, T2 t2, T3 t3, 36444 | expression_node_ptr& result) 36445 | { 36446 | details::operator_type sf4opr; 36447 | 36448 | if (!expr_gen.sf4_optimisable(id,sf4opr)) 36449 | return false; 36450 | else 36451 | result = synthesize_sf4ext_expression::template process<T0, T1, T2, T3> 36452 | (expr_gen, sf4opr, t0, t1, t2, t3); 36453 | 36454 | return true; 36455 | } 36456 | 36457 | // T o (sf3ext) 36458 | template <typename ExternalType> 36459 | static inline bool compile_right(expression_generator<Type>& expr_gen, 36460 | ExternalType t, 36461 | const details::operator_type& operation, 36462 | expression_node_ptr& sf3node, 36463 | expression_node_ptr& result) 36464 | { 36465 | if (!details::is_sf3ext_node(sf3node)) 36466 | return false; 36467 | 36468 | typedef details::T0oT1oT2_base_node<Type>* sf3ext_base_ptr; 36469 | 36470 | sf3ext_base_ptr n = static_cast<sf3ext_base_ptr>(sf3node); 36471 | const std::string id = "t" + expr_gen.to_str(operation) + "(" + n->type_id() + ")" 36472 | 36473 | switch (n->type()) 36474 | { 36475 | case details::expression_node<Type>::e_covoc : return compile_right_impl 36476 | <typename covoc_t::sf3_type_node,ExternalType, ctype, vtype, ctype> 36477 | (expr_gen, id, t, sf3node, result); 36478 | 36479 | case details::expression_node<Type>::e_covov : return compile_right_impl 36480 | <typename covov_t::sf3_type_node,ExternalType, ctype, vtype, vtype> 36481 | (expr_gen, id, t, sf3node, result); 36482 | 36483 | case details::expression_node<Type>::e_vocov : return compile_right_impl 36484 | <typename vocov_t::sf3_type_node,ExternalType, vtype, ctype, vtype> 36485 | (expr_gen, id, t, sf3node, result); 36486 | 36487 | case details::expression_node<Type>::e_vovoc : return compile_right_impl 36488 | <typename vovoc_t::sf3_type_node,ExternalType, vtype, vtype, ctype> 36489 | (expr_gen, id, t, sf3node, result); 36490 | 36491 | case details::expression_node<Type>::e_vovov : return compile_right_impl 36492 | <typename vovov_t::sf3_type_node,ExternalType, vtype, vtype, vtype> 36493 | (expr_gen, id, t, sf3node, result); 36494 | 36495 | default : return false; 36496 | } 36497 | } 36498 | 36499 | // (sf3ext) o T 36500 | template <typename ExternalType> 36501 | static inline bool compile_left(expression_generator<Type>& expr_gen, 36502 | ExternalType t, 36503 | const details::operator_type& operation, 36504 | expression_node_ptr& sf3node, 36505 | expression_node_ptr& result) 36506 | { 36507 | if (!details::is_sf3ext_node(sf3node)) 36508 | return false; 36509 | 36510 | typedef details::T0oT1oT2_base_node<Type>* sf3ext_base_ptr; 36511 | 36512 | sf3ext_base_ptr n = static_cast<sf3ext_base_ptr>(sf3node); 36513 | 36514 | const std::string id = "(" + n->type_id() + ")" + expr_gen.to_str(operation) + "t" 36515 | 36516 | switch (n->type()) 36517 | { 36518 | case details::expression_node<Type>::e_covoc : return compile_left_impl 36519 | <typename covoc_t::sf3_type_node,ExternalType, ctype, vtype, ctype> 36520 | (expr_gen, id, t, sf3node, result); 36521 | 36522 | case details::expression_node<Type>::e_covov : return compile_left_impl 36523 | <typename covov_t::sf3_type_node,ExternalType, ctype, vtype, vtype> 36524 | (expr_gen, id, t, sf3node, result); 36525 | 36526 | case details::expression_node<Type>::e_vocov : return compile_left_impl 36527 | <typename vocov_t::sf3_type_node,ExternalType, vtype, ctype, vtype> 36528 | (expr_gen, id, t, sf3node, result); 36529 | 36530 | case details::expression_node<Type>::e_vovoc : return compile_left_impl 36531 | <typename vovoc_t::sf3_type_node,ExternalType, vtype, vtype, ctype> 36532 | (expr_gen, id, t, sf3node, result); 36533 | 36534 | case details::expression_node<Type>::e_vovov : return compile_left_impl 36535 | <typename vovov_t::sf3_type_node,ExternalType, vtype, vtype, vtype> 36536 | (expr_gen, id, t, sf3node, result); 36537 | 36538 | default : return false; 36539 | } 36540 | } 36541 | 36542 | template <typename SF3TypeNode, typename ExternalType, typename T0, typename T1, typename T2> 36543 | static inline bool compile_right_impl(expression_generator<Type>& expr_gen, 36544 | const std::string& id, 36545 | ExternalType t, 36546 | expression_node_ptr& node, 36547 | expression_node_ptr& result) 36548 | { 36549 | SF3TypeNode* n = dynamic_cast<SF3TypeNode*>(node); 36550 | 36551 | if (n) 36552 | { 36553 | T0 t0 = n->t0(); 36554 | T1 t1 = n->t1(); 36555 | T2 t2 = n->t2(); 36556 | 36557 | return synthesize_sf4ext_expression::template compile<ExternalType, T0, T1, T2> 36558 | (expr_gen, id, t, t0, t1, t2, result); 36559 | } 36560 | else 36561 | return false; 36562 | } 36563 | 36564 | template <typename SF3TypeNode, typename ExternalType, typename T0, typename T1, typename T2> 36565 | static inline bool compile_left_impl(expression_generator<Type>& expr_gen, 36566 | const std::string& id, 36567 | ExternalType t, 36568 | expression_node_ptr& node, 36569 | expression_node_ptr& result) 36570 | { 36571 | SF3TypeNode* n = dynamic_cast<SF3TypeNode*>(node); 36572 | 36573 | if (n) 36574 | { 36575 | T0 t0 = n->t0(); 36576 | T1 t1 = n->t1(); 36577 | T2 t2 = n->t2(); 36578 | 36579 | return synthesize_sf4ext_expression::template compile<T0, T1, T2, ExternalType> 36580 | (expr_gen, id, t0, t1, t2, t, result); 36581 | } 36582 | else 36583 | return false; 36584 | } 36585 | }; 36586 | 36587 | struct synthesize_vovov_expression0 36588 | { 36589 | typedef typename vovov_t::type0 node_type; 36590 | typedef typename vovov_t::sf3_type sf3_type; 36591 | 36592 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36593 | const details::operator_type& operation, 36594 | expression_node_ptr (&branch)[2]) 36595 | { 36596 | // (v0 o0 v1) o1 (v2) 36597 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]); 36598 | const Type& v0 = vov->v0(); 36599 | const Type& v1 = vov->v1(); 36600 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 36601 | const details::operator_type o0 = vov->operation(); 36602 | const details::operator_type o1 = operation; 36603 | 36604 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 36605 | 36606 | expression_node_ptr result = error_node(); 36607 | 36608 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36609 | { 36610 | // (v0 / v1) / v2 --> (vovov) v0 / (v1 * v2) 36611 | if ((details::e_div == o0) && (details::e_div == o1)) 36612 | { 36613 | const bool synthesis_result = 36614 | synthesize_sf3ext_expression:: 36615 | template compile<vtype, vtype, vtype>(expr_gen, "t/(t*t)", v0, v1, v2, result); 36616 | 36617 | exprtk_debug(("(v0 / v1) / v2 --> (vovov) v0 / (v1 * v2)\n")); 36618 | 36619 | return (synthesis_result) ? result : error_node(); 36620 | } 36621 | } 36622 | 36623 | const bool synthesis_result = 36624 | synthesize_sf3ext_expression::template compile<vtype, vtype, vtype> 36625 | (expr_gen, id(expr_gen, o0, o1), v0, v1, v2, result); 36626 | 36627 | if (synthesis_result) 36628 | return result; 36629 | 36630 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36631 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36632 | 36633 | if (!expr_gen.valid_operator(o0,f0)) 36634 | return error_node(); 36635 | else if (!expr_gen.valid_operator(o1,f1)) 36636 | return error_node(); 36637 | else 36638 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, f0, f1); 36639 | } 36640 | 36641 | static inline std::string id(expression_generator<Type>& expr_gen, 36642 | const details::operator_type o0, 36643 | const details::operator_type o1) 36644 | { 36645 | return details::build_string() 36646 | << "(t" << expr_gen.to_str(o0) 36647 | << "t)" << expr_gen.to_str(o1) 36648 | << "t" 36649 | } 36650 | }; 36651 | 36652 | struct synthesize_vovov_expression1 36653 | { 36654 | typedef typename vovov_t::type1 node_type; 36655 | typedef typename vovov_t::sf3_type sf3_type; 36656 | 36657 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36658 | const details::operator_type& operation, 36659 | expression_node_ptr (&branch)[2]) 36660 | { 36661 | // (v0) o0 (v1 o1 v2) 36662 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]); 36663 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 36664 | const Type& v1 = vov->v0(); 36665 | const Type& v2 = vov->v1(); 36666 | const details::operator_type o0 = operation; 36667 | const details::operator_type o1 = vov->operation(); 36668 | 36669 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 36670 | 36671 | expression_node_ptr result = error_node(); 36672 | 36673 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36674 | { 36675 | // v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1 36676 | if ((details::e_div == o0) && (details::e_div == o1)) 36677 | { 36678 | const bool synthesis_result = 36679 | synthesize_sf3ext_expression:: 36680 | template compile<vtype, vtype, vtype>(expr_gen, "(t*t)/t", v0, v2, v1, result); 36681 | 36682 | exprtk_debug(("v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1\n")); 36683 | 36684 | return (synthesis_result) ? result : error_node(); 36685 | } 36686 | } 36687 | 36688 | const bool synthesis_result = 36689 | synthesize_sf3ext_expression::template compile<vtype, vtype, vtype> 36690 | (expr_gen, id(expr_gen, o0, o1), v0, v1, v2, result); 36691 | 36692 | if (synthesis_result) 36693 | return result; 36694 | 36695 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36696 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36697 | 36698 | if (!expr_gen.valid_operator(o0,f0)) 36699 | return error_node(); 36700 | else if (!expr_gen.valid_operator(o1,f1)) 36701 | return error_node(); 36702 | else 36703 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, f0, f1); 36704 | } 36705 | 36706 | static inline std::string id(expression_generator<Type>& expr_gen, 36707 | const details::operator_type o0, 36708 | const details::operator_type o1) 36709 | { 36710 | return details::build_string() 36711 | << "t" << expr_gen.to_str(o0) 36712 | << "(t" << expr_gen.to_str(o1) 36713 | << "t)" 36714 | } 36715 | }; 36716 | 36717 | struct synthesize_vovoc_expression0 36718 | { 36719 | typedef typename vovoc_t::type0 node_type; 36720 | typedef typename vovoc_t::sf3_type sf3_type; 36721 | 36722 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36723 | const details::operator_type& operation, 36724 | expression_node_ptr (&branch)[2]) 36725 | { 36726 | // (v0 o0 v1) o1 (c) 36727 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]); 36728 | const Type& v0 = vov->v0(); 36729 | const Type& v1 = vov->v1(); 36730 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 36731 | const details::operator_type o0 = vov->operation(); 36732 | const details::operator_type o1 = operation; 36733 | 36734 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 36735 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 36736 | 36737 | expression_node_ptr result = error_node(); 36738 | 36739 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36740 | { 36741 | // (v0 / v1) / c --> (vovoc) v0 / (v1 * c) 36742 | if ((details::e_div == o0) && (details::e_div == o1)) 36743 | { 36744 | const bool synthesis_result = 36745 | synthesize_sf3ext_expression:: 36746 | template compile<vtype, vtype, ctype>(expr_gen, "t/(t*t)", v0, v1, c, result); 36747 | 36748 | exprtk_debug(("(v0 / v1) / c --> (vovoc) v0 / (v1 * c)\n")); 36749 | 36750 | return (synthesis_result) ? result : error_node(); 36751 | } 36752 | } 36753 | 36754 | const bool synthesis_result = 36755 | synthesize_sf3ext_expression::template compile<vtype, vtype, ctype> 36756 | (expr_gen, id(expr_gen, o0, o1), v0, v1, c, result); 36757 | 36758 | if (synthesis_result) 36759 | return result; 36760 | 36761 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36762 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36763 | 36764 | if (!expr_gen.valid_operator(o0,f0)) 36765 | return error_node(); 36766 | else if (!expr_gen.valid_operator(o1,f1)) 36767 | return error_node(); 36768 | else 36769 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, f0, f1); 36770 | } 36771 | 36772 | static inline std::string id(expression_generator<Type>& expr_gen, 36773 | const details::operator_type o0, 36774 | const details::operator_type o1) 36775 | { 36776 | return details::build_string() 36777 | << "(t" << expr_gen.to_str(o0) 36778 | << "t)" << expr_gen.to_str(o1) 36779 | << "t" 36780 | } 36781 | }; 36782 | 36783 | struct synthesize_vovoc_expression1 36784 | { 36785 | typedef typename vovoc_t::type1 node_type; 36786 | typedef typename vovoc_t::sf3_type sf3_type; 36787 | 36788 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36789 | const details::operator_type& operation, 36790 | expression_node_ptr (&branch)[2]) 36791 | { 36792 | // (v0) o0 (v1 o1 c) 36793 | const details::voc_base_node<Type>* voc = static_cast<const details::voc_base_node<Type>*>(branch[1]); 36794 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 36795 | const Type& v1 = voc->v(); 36796 | const Type c = voc->c(); 36797 | const details::operator_type o0 = operation; 36798 | const details::operator_type o1 = voc->operation(); 36799 | 36800 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 36801 | 36802 | expression_node_ptr result = error_node(); 36803 | 36804 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36805 | { 36806 | // v0 / (v1 / c) --> (vocov) (v0 * c) / v1 36807 | if ((details::e_div == o0) && (details::e_div == o1)) 36808 | { 36809 | const bool synthesis_result = 36810 | synthesize_sf3ext_expression:: 36811 | template compile<vtype, ctype, vtype>(expr_gen, "(t*t)/t", v0, c, v1, result); 36812 | 36813 | exprtk_debug(("v0 / (v1 / c) --> (vocov) (v0 * c) / v1\n")); 36814 | 36815 | return (synthesis_result) ? result : error_node(); 36816 | } 36817 | } 36818 | 36819 | const bool synthesis_result = 36820 | synthesize_sf3ext_expression::template compile<vtype, vtype, ctype> 36821 | (expr_gen, id(expr_gen, o0, o1), v0, v1, c, result); 36822 | 36823 | if (synthesis_result) 36824 | return result; 36825 | 36826 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36827 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36828 | 36829 | if (!expr_gen.valid_operator(o0,f0)) 36830 | return error_node(); 36831 | else if (!expr_gen.valid_operator(o1,f1)) 36832 | return error_node(); 36833 | else 36834 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, f0, f1); 36835 | } 36836 | 36837 | static inline std::string id(expression_generator<Type>& expr_gen, 36838 | const details::operator_type o0, 36839 | const details::operator_type o1) 36840 | { 36841 | return details::build_string() 36842 | << "t" << expr_gen.to_str(o0) 36843 | << "(t" << expr_gen.to_str(o1) 36844 | << "t)" 36845 | } 36846 | }; 36847 | 36848 | struct synthesize_vocov_expression0 36849 | { 36850 | typedef typename vocov_t::type0 node_type; 36851 | typedef typename vocov_t::sf3_type sf3_type; 36852 | 36853 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36854 | const details::operator_type& operation, 36855 | expression_node_ptr (&branch)[2]) 36856 | { 36857 | // (v0 o0 c) o1 (v1) 36858 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]); 36859 | const Type& v0 = voc->v(); 36860 | const Type c = voc->c(); 36861 | const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 36862 | const details::operator_type o0 = voc->operation(); 36863 | const details::operator_type o1 = operation; 36864 | 36865 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 36866 | 36867 | expression_node_ptr result = error_node(); 36868 | 36869 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36870 | { 36871 | // (v0 / c) / v1 --> (vovoc) v0 / (v1 * c) 36872 | if ((details::e_div == o0) && (details::e_div == o1)) 36873 | { 36874 | const bool synthesis_result = 36875 | synthesize_sf3ext_expression:: 36876 | template compile<vtype, vtype, ctype>(expr_gen, "t/(t*t)", v0, v1, c, result); 36877 | 36878 | exprtk_debug(("(v0 / c) / v1 --> (vovoc) v0 / (v1 * c)\n")); 36879 | 36880 | return (synthesis_result) ? result : error_node(); 36881 | } 36882 | } 36883 | 36884 | const bool synthesis_result = 36885 | synthesize_sf3ext_expression::template compile<vtype, ctype, vtype> 36886 | (expr_gen, id(expr_gen, o0, o1), v0, c, v1, result); 36887 | 36888 | if (synthesis_result) 36889 | return result; 36890 | 36891 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36892 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36893 | 36894 | if (!expr_gen.valid_operator(o0,f0)) 36895 | return error_node(); 36896 | else if (!expr_gen.valid_operator(o1,f1)) 36897 | return error_node(); 36898 | else 36899 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, f0, f1); 36900 | } 36901 | 36902 | static inline std::string id(expression_generator<Type>& expr_gen, 36903 | const details::operator_type o0, 36904 | const details::operator_type o1) 36905 | { 36906 | return details::build_string() 36907 | << "(t" << expr_gen.to_str(o0) 36908 | << "t)" << expr_gen.to_str(o1) 36909 | << "t" 36910 | } 36911 | }; 36912 | 36913 | struct synthesize_vocov_expression1 36914 | { 36915 | typedef typename vocov_t::type1 node_type; 36916 | typedef typename vocov_t::sf3_type sf3_type; 36917 | 36918 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36919 | const details::operator_type& operation, 36920 | expression_node_ptr (&branch)[2]) 36921 | { 36922 | // (v0) o0 (c o1 v1) 36923 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]); 36924 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 36925 | const Type c = cov->c(); 36926 | const Type& v1 = cov->v(); 36927 | const details::operator_type o0 = operation; 36928 | const details::operator_type o1 = cov->operation(); 36929 | 36930 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 36931 | 36932 | expression_node_ptr result = error_node(); 36933 | 36934 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36935 | { 36936 | // v0 / (c / v1) --> (vovoc) (v0 * v1) / c 36937 | if ((details::e_div == o0) && (details::e_div == o1)) 36938 | { 36939 | const bool synthesis_result = 36940 | synthesize_sf3ext_expression:: 36941 | template compile<vtype, vtype, ctype>(expr_gen, "(t*t)/t", v0, v1, c, result); 36942 | 36943 | exprtk_debug(("v0 / (c / v1) --> (vovoc) (v0 * v1) / c\n")); 36944 | 36945 | return (synthesis_result) ? result : error_node(); 36946 | } 36947 | } 36948 | 36949 | const bool synthesis_result = 36950 | synthesize_sf3ext_expression::template compile<vtype, ctype, vtype> 36951 | (expr_gen, id(expr_gen, o0, o1), v0, c, v1, result); 36952 | 36953 | if (synthesis_result) 36954 | return result; 36955 | 36956 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36957 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36958 | 36959 | if (!expr_gen.valid_operator(o0,f0)) 36960 | return error_node(); 36961 | else if (!expr_gen.valid_operator(o1,f1)) 36962 | return error_node(); 36963 | else 36964 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, f0, f1); 36965 | } 36966 | 36967 | static inline std::string id(expression_generator<Type>& expr_gen, 36968 | const details::operator_type o0, 36969 | const details::operator_type o1) 36970 | { 36971 | return details::build_string() 36972 | << "t" << expr_gen.to_str(o0) 36973 | << "(t" << expr_gen.to_str(o1) 36974 | << "t)" 36975 | } 36976 | }; 36977 | 36978 | struct synthesize_covov_expression0 36979 | { 36980 | typedef typename covov_t::type0 node_type; 36981 | typedef typename covov_t::sf3_type sf3_type; 36982 | 36983 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36984 | const details::operator_type& operation, 36985 | expression_node_ptr (&branch)[2]) 36986 | { 36987 | // (c o0 v0) o1 (v1) 36988 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]); 36989 | const Type c = cov->c(); 36990 | const Type& v0 = cov->v(); 36991 | const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 36992 | const details::operator_type o0 = cov->operation(); 36993 | const details::operator_type o1 = operation; 36994 | 36995 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 36996 | 36997 | expression_node_ptr result = error_node(); 36998 | 36999 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37000 | { 37001 | // (c / v0) / v1 --> (covov) c / (v0 * v1) 37002 | if ((details::e_div == o0) && (details::e_div == o1)) 37003 | { 37004 | const bool synthesis_result = 37005 | synthesize_sf3ext_expression:: 37006 | template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", c, v0, v1, result); 37007 | 37008 | exprtk_debug(("(c / v0) / v1 --> (covov) c / (v0 * v1)\n")); 37009 | 37010 | return (synthesis_result) ? result : error_node(); 37011 | } 37012 | } 37013 | 37014 | const bool synthesis_result = 37015 | synthesize_sf3ext_expression::template compile<ctype, vtype, vtype> 37016 | (expr_gen, id(expr_gen, o0, o1), c, v0, v1, result); 37017 | 37018 | if (synthesis_result) 37019 | return result; 37020 | 37021 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37022 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37023 | 37024 | if (!expr_gen.valid_operator(o0,f0)) 37025 | return error_node(); 37026 | else if (!expr_gen.valid_operator(o1,f1)) 37027 | return error_node(); 37028 | else 37029 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, f0, f1); 37030 | } 37031 | 37032 | static inline std::string id(expression_generator<Type>& expr_gen, 37033 | const details::operator_type o0, 37034 | const details::operator_type o1) 37035 | { 37036 | return details::build_string() 37037 | << "(t" << expr_gen.to_str(o0) 37038 | << "t)" << expr_gen.to_str(o1) 37039 | << "t" 37040 | } 37041 | }; 37042 | 37043 | struct synthesize_covov_expression1 37044 | { 37045 | typedef typename covov_t::type1 node_type; 37046 | typedef typename covov_t::sf3_type sf3_type; 37047 | 37048 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37049 | const details::operator_type& operation, 37050 | expression_node_ptr (&branch)[2]) 37051 | { 37052 | // (c) o0 (v0 o1 v1) 37053 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]); 37054 | const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); 37055 | const Type& v0 = vov->v0(); 37056 | const Type& v1 = vov->v1(); 37057 | const details::operator_type o0 = operation; 37058 | const details::operator_type o1 = vov->operation(); 37059 | 37060 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37061 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37062 | 37063 | expression_node_ptr result = error_node(); 37064 | 37065 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37066 | { 37067 | // c / (v0 / v1) --> (covov) (c * v1) / v0 37068 | if ((details::e_div == o0) && (details::e_div == o1)) 37069 | { 37070 | const bool synthesis_result = 37071 | synthesize_sf3ext_expression:: 37072 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", c, v1, v0, result); 37073 | 37074 | exprtk_debug(("c / (v0 / v1) --> (covov) (c * v1) / v0\n")); 37075 | 37076 | return (synthesis_result) ? result : error_node(); 37077 | } 37078 | } 37079 | 37080 | const bool synthesis_result = 37081 | synthesize_sf3ext_expression::template compile<ctype, vtype, vtype> 37082 | (expr_gen, id(expr_gen, o0, o1), c, v0, v1, result); 37083 | 37084 | if (synthesis_result) 37085 | return result; 37086 | 37087 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37088 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37089 | 37090 | if (!expr_gen.valid_operator(o0,f0)) 37091 | return error_node(); 37092 | else if (!expr_gen.valid_operator(o1,f1)) 37093 | return error_node(); 37094 | else 37095 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, f0, f1); 37096 | } 37097 | 37098 | static inline std::string id(expression_generator<Type>& expr_gen, 37099 | const details::operator_type o0, 37100 | const details::operator_type o1) 37101 | { 37102 | return details::build_string() 37103 | << "t" << expr_gen.to_str(o0) 37104 | << "(t" << expr_gen.to_str(o1) 37105 | << "t)" 37106 | } 37107 | }; 37108 | 37109 | struct synthesize_covoc_expression0 37110 | { 37111 | typedef typename covoc_t::type0 node_type; 37112 | typedef typename covoc_t::sf3_type sf3_type; 37113 | 37114 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37115 | const details::operator_type& operation, 37116 | expression_node_ptr (&branch)[2]) 37117 | { 37118 | // (c0 o0 v) o1 (c1) 37119 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]); 37120 | const Type c0 = cov->c(); 37121 | const Type& v = cov->v(); 37122 | const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); 37123 | const details::operator_type o0 = cov->operation(); 37124 | const details::operator_type o1 = operation; 37125 | 37126 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37127 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37128 | 37129 | expression_node_ptr result = error_node(); 37130 | 37131 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37132 | { 37133 | // (c0 + v) + c1 --> (cov) (c0 + c1) + v 37134 | if ((details::e_add == o0) && (details::e_add == o1)) 37135 | { 37136 | exprtk_debug(("(c0 + v) + c1 --> (cov) (c0 + c1) + v\n")); 37137 | 37138 | return expr_gen.node_allocator_-> 37139 | template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v); 37140 | } 37141 | // (c0 + v) - c1 --> (cov) (c0 - c1) + v 37142 | else if ((details::e_add == o0) && (details::e_sub == o1)) 37143 | { 37144 | exprtk_debug(("(c0 + v) - c1 --> (cov) (c0 - c1) + v\n")); 37145 | 37146 | return expr_gen.node_allocator_-> 37147 | template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v); 37148 | } 37149 | // (c0 - v) + c1 --> (cov) (c0 + c1) - v 37150 | else if ((details::e_sub == o0) && (details::e_add == o1)) 37151 | { 37152 | exprtk_debug(("(c0 - v) + c1 --> (cov) (c0 + c1) - v\n")); 37153 | 37154 | return expr_gen.node_allocator_-> 37155 | template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v); 37156 | } 37157 | // (c0 - v) - c1 --> (cov) (c0 - c1) - v 37158 | else if ((details::e_sub == o0) && (details::e_sub == o1)) 37159 | { 37160 | exprtk_debug(("(c0 - v) - c1 --> (cov) (c0 - c1) - v\n")); 37161 | 37162 | return expr_gen.node_allocator_-> 37163 | template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v); 37164 | } 37165 | // (c0 * v) * c1 --> (cov) (c0 * c1) * v 37166 | else if ((details::e_mul == o0) && (details::e_mul == o1)) 37167 | { 37168 | exprtk_debug(("(c0 * v) * c1 --> (cov) (c0 * c1) * v\n")); 37169 | 37170 | return expr_gen.node_allocator_-> 37171 | template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v); 37172 | } 37173 | // (c0 * v) / c1 --> (cov) (c0 / c1) * v 37174 | else if ((details::e_mul == o0) && (details::e_div == o1)) 37175 | { 37176 | exprtk_debug(("(c0 * v) / c1 --> (cov) (c0 / c1) * v\n")); 37177 | 37178 | return expr_gen.node_allocator_-> 37179 | template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v); 37180 | } 37181 | // (c0 / v) * c1 --> (cov) (c0 * c1) / v 37182 | else if ((details::e_div == o0) && (details::e_mul == o1)) 37183 | { 37184 | exprtk_debug(("(c0 / v) * c1 --> (cov) (c0 * c1) / v\n")); 37185 | 37186 | return expr_gen.node_allocator_-> 37187 | template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v); 37188 | } 37189 | // (c0 / v) / c1 --> (cov) (c0 / c1) / v 37190 | else if ((details::e_div == o0) && (details::e_div == o1)) 37191 | { 37192 | exprtk_debug(("(c0 / v) / c1 --> (cov) (c0 / c1) / v\n")); 37193 | 37194 | return expr_gen.node_allocator_-> 37195 | template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v); 37196 | } 37197 | } 37198 | 37199 | const bool synthesis_result = 37200 | synthesize_sf3ext_expression::template compile<ctype, vtype, ctype> 37201 | (expr_gen, id(expr_gen, o0, o1), c0, v, c1, result); 37202 | 37203 | if (synthesis_result) 37204 | return result; 37205 | 37206 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37207 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37208 | 37209 | if (!expr_gen.valid_operator(o0,f0)) 37210 | return error_node(); 37211 | else if (!expr_gen.valid_operator(o1,f1)) 37212 | return error_node(); 37213 | else 37214 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v, c1, f0, f1); 37215 | } 37216 | 37217 | static inline std::string id(expression_generator<Type>& expr_gen, 37218 | const details::operator_type o0, 37219 | const details::operator_type o1) 37220 | { 37221 | return details::build_string() 37222 | << "(t" << expr_gen.to_str(o0) 37223 | << "t)" << expr_gen.to_str(o1) 37224 | << "t" 37225 | } 37226 | }; 37227 | 37228 | struct synthesize_covoc_expression1 37229 | { 37230 | typedef typename covoc_t::type1 node_type; 37231 | typedef typename covoc_t::sf3_type sf3_type; 37232 | 37233 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37234 | const details::operator_type& operation, 37235 | expression_node_ptr (&branch)[2]) 37236 | { 37237 | // (c0) o0 (v o1 c1) 37238 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]); 37239 | const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); 37240 | const Type& v = voc->v(); 37241 | const Type c1 = voc->c(); 37242 | const details::operator_type o0 = operation; 37243 | const details::operator_type o1 = voc->operation(); 37244 | 37245 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37246 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37247 | 37248 | expression_node_ptr result = error_node(); 37249 | 37250 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37251 | { 37252 | // (c0) + (v + c1) --> (cov) (c0 + c1) + v 37253 | if ((details::e_add == o0) && (details::e_add == o1)) 37254 | { 37255 | exprtk_debug(("(c0) + (v + c1) --> (cov) (c0 + c1) + v\n")); 37256 | 37257 | return expr_gen.node_allocator_-> 37258 | template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v); 37259 | } 37260 | // (c0) + (v - c1) --> (cov) (c0 - c1) + v 37261 | else if ((details::e_add == o0) && (details::e_sub == o1)) 37262 | { 37263 | exprtk_debug(("(c0) + (v - c1) --> (cov) (c0 - c1) + v\n")); 37264 | 37265 | return expr_gen.node_allocator_-> 37266 | template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v); 37267 | } 37268 | // (c0) - (v + c1) --> (cov) (c0 - c1) - v 37269 | else if ((details::e_sub == o0) && (details::e_add == o1)) 37270 | { 37271 | exprtk_debug(("(c0) - (v + c1) --> (cov) (c0 - c1) - v\n")); 37272 | 37273 | return expr_gen.node_allocator_-> 37274 | template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v); 37275 | } 37276 | // (c0) - (v - c1) --> (cov) (c0 + c1) - v 37277 | else if ((details::e_sub == o0) && (details::e_sub == o1)) 37278 | { 37279 | exprtk_debug(("(c0) - (v - c1) --> (cov) (c0 + c1) - v\n")); 37280 | 37281 | return expr_gen.node_allocator_-> 37282 | template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v); 37283 | } 37284 | // (c0) * (v * c1) --> (voc) v * (c0 * c1) 37285 | else if ((details::e_mul == o0) && (details::e_mul == o1)) 37286 | { 37287 | exprtk_debug(("(c0) * (v * c1) --> (voc) v * (c0 * c1)\n")); 37288 | 37289 | return expr_gen.node_allocator_-> 37290 | template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v); 37291 | } 37292 | // (c0) * (v / c1) --> (cov) (c0 / c1) * v 37293 | else if ((details::e_mul == o0) && (details::e_div == o1)) 37294 | { 37295 | exprtk_debug(("(c0) * (v / c1) --> (cov) (c0 / c1) * v\n")); 37296 | 37297 | return expr_gen.node_allocator_-> 37298 | template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v); 37299 | } 37300 | // (c0) / (v * c1) --> (cov) (c0 / c1) / v 37301 | else if ((details::e_div == o0) && (details::e_mul == o1)) 37302 | { 37303 | exprtk_debug(("(c0) / (v * c1) --> (cov) (c0 / c1) / v\n")); 37304 | 37305 | return expr_gen.node_allocator_-> 37306 | template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v); 37307 | } 37308 | // (c0) / (v / c1) --> (cov) (c0 * c1) / v 37309 | else if ((details::e_div == o0) && (details::e_div == o1)) 37310 | { 37311 | exprtk_debug(("(c0) / (v / c1) --> (cov) (c0 * c1) / v\n")); 37312 | 37313 | return expr_gen.node_allocator_-> 37314 | template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v); 37315 | } 37316 | } 37317 | 37318 | const bool synthesis_result = 37319 | synthesize_sf3ext_expression::template compile<ctype, vtype, ctype> 37320 | (expr_gen, id(expr_gen, o0, o1), c0, v, c1, result); 37321 | 37322 | if (synthesis_result) 37323 | return result; 37324 | 37325 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37326 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37327 | 37328 | if (!expr_gen.valid_operator(o0,f0)) 37329 | return error_node(); 37330 | else if (!expr_gen.valid_operator(o1,f1)) 37331 | return error_node(); 37332 | else 37333 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v, c1, f0, f1); 37334 | } 37335 | 37336 | static inline std::string id(expression_generator<Type>& expr_gen, 37337 | const details::operator_type o0, 37338 | const details::operator_type o1) 37339 | { 37340 | return details::build_string() 37341 | << "t" << expr_gen.to_str(o0) 37342 | << "(t" << expr_gen.to_str(o1) 37343 | << "t)" 37344 | } 37345 | }; 37346 | 37347 | struct synthesize_cocov_expression0 37348 | { 37349 | typedef typename cocov_t::type0 node_type; 37350 | static inline expression_node_ptr process(expression_generator<Type>&, 37351 | const details::operator_type&, 37352 | expression_node_ptr (&)[2]) 37353 | { 37354 | // (c0 o0 c1) o1 (v) - Not possible. 37355 | return error_node(); 37356 | } 37357 | }; 37358 | 37359 | struct synthesize_cocov_expression1 37360 | { 37361 | typedef typename cocov_t::type1 node_type; 37362 | typedef typename cocov_t::sf3_type sf3_type; 37363 | 37364 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37365 | const details::operator_type& operation, 37366 | expression_node_ptr (&branch)[2]) 37367 | { 37368 | // (c0) o0 (c1 o1 v) 37369 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]); 37370 | const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); 37371 | const Type c1 = cov->c(); 37372 | const Type& v = cov->v(); 37373 | const details::operator_type o0 = operation; 37374 | const details::operator_type o1 = cov->operation(); 37375 | 37376 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37377 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37378 | 37379 | expression_node_ptr result = error_node(); 37380 | 37381 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37382 | { 37383 | // (c0) + (c1 + v) --> (cov) (c0 + c1) + v 37384 | if ((details::e_add == o0) && (details::e_add == o1)) 37385 | { 37386 | exprtk_debug(("(c0) + (c1 + v) --> (cov) (c0 + c1) + v\n")); 37387 | 37388 | return expr_gen.node_allocator_-> 37389 | template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v); 37390 | } 37391 | // (c0) + (c1 - v) --> (cov) (c0 + c1) - v 37392 | else if ((details::e_add == o0) && (details::e_sub == o1)) 37393 | { 37394 | exprtk_debug(("(c0) + (c1 - v) --> (cov) (c0 + c1) - v\n")); 37395 | 37396 | return expr_gen.node_allocator_-> 37397 | template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v); 37398 | } 37399 | // (c0) - (c1 + v) --> (cov) (c0 - c1) - v 37400 | else if ((details::e_sub == o0) && (details::e_add == o1)) 37401 | { 37402 | exprtk_debug(("(c0) - (c1 + v) --> (cov) (c0 - c1) - v\n")); 37403 | 37404 | return expr_gen.node_allocator_-> 37405 | template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v); 37406 | } 37407 | // (c0) - (c1 - v) --> (cov) (c0 - c1) + v 37408 | else if ((details::e_sub == o0) && (details::e_sub == o1)) 37409 | { 37410 | exprtk_debug(("(c0) - (c1 - v) --> (cov) (c0 - c1) + v\n")); 37411 | 37412 | return expr_gen.node_allocator_-> 37413 | template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v); 37414 | } 37415 | // (c0) * (c1 * v) --> (cov) (c0 * c1) * v 37416 | else if ((details::e_mul == o0) && (details::e_mul == o1)) 37417 | { 37418 | exprtk_debug(("(c0) * (c1 * v) --> (cov) (c0 * c1) * v\n")); 37419 | 37420 | return expr_gen.node_allocator_-> 37421 | template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v); 37422 | } 37423 | // (c0) * (c1 / v) --> (cov) (c0 * c1) / v 37424 | else if ((details::e_mul == o0) && (details::e_div == o1)) 37425 | { 37426 | exprtk_debug(("(c0) * (c1 / v) --> (cov) (c0 * c1) / v\n")); 37427 | 37428 | return expr_gen.node_allocator_-> 37429 | template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v); 37430 | } 37431 | // (c0) / (c1 * v) --> (cov) (c0 / c1) / v 37432 | else if ((details::e_div == o0) && (details::e_mul == o1)) 37433 | { 37434 | exprtk_debug(("(c0) / (c1 * v) --> (cov) (c0 / c1) / v\n")); 37435 | 37436 | return expr_gen.node_allocator_-> 37437 | template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v); 37438 | } 37439 | // (c0) / (c1 / v) --> (cov) (c0 / c1) * v 37440 | else if ((details::e_div == o0) && (details::e_div == o1)) 37441 | { 37442 | exprtk_debug(("(c0) / (c1 / v) --> (cov) (c0 / c1) * v\n")); 37443 | 37444 | return expr_gen.node_allocator_-> 37445 | template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v); 37446 | } 37447 | } 37448 | 37449 | const bool synthesis_result = 37450 | synthesize_sf3ext_expression::template compile<ctype, ctype, vtype> 37451 | (expr_gen, id(expr_gen, o0, o1), c0, c1, v, result); 37452 | 37453 | if (synthesis_result) 37454 | return result; 37455 | 37456 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37457 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37458 | 37459 | if (!expr_gen.valid_operator(o0,f0)) 37460 | return error_node(); 37461 | else if (!expr_gen.valid_operator(o1,f1)) 37462 | return error_node(); 37463 | else 37464 | return node_type::allocate(*(expr_gen.node_allocator_), c0, c1, v, f0, f1); 37465 | } 37466 | 37467 | static inline std::string id(expression_generator<Type>& expr_gen, 37468 | const details::operator_type o0, 37469 | const details::operator_type o1) 37470 | { 37471 | return details::build_string() 37472 | << "t" << expr_gen.to_str(o0) 37473 | << "(t" << expr_gen.to_str(o1) 37474 | << "t)" 37475 | } 37476 | }; 37477 | 37478 | struct synthesize_vococ_expression0 37479 | { 37480 | typedef typename vococ_t::type0 node_type; 37481 | typedef typename vococ_t::sf3_type sf3_type; 37482 | 37483 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37484 | const details::operator_type& operation, 37485 | expression_node_ptr (&branch)[2]) 37486 | { 37487 | // (v o0 c0) o1 (c1) 37488 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]); 37489 | const Type& v = voc->v(); 37490 | const Type& c0 = voc->c(); 37491 | const Type& c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); 37492 | const details::operator_type o0 = voc->operation(); 37493 | const details::operator_type o1 = operation; 37494 | 37495 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37496 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37497 | 37498 | expression_node_ptr result = error_node(); 37499 | 37500 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37501 | { 37502 | // (v + c0) + c1 --> (voc) v + (c0 + c1) 37503 | if ((details::e_add == o0) && (details::e_add == o1)) 37504 | { 37505 | exprtk_debug(("(v + c0) + c1 --> (voc) v + (c0 + c1)\n")); 37506 | 37507 | return expr_gen.node_allocator_-> 37508 | template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c0 + c1); 37509 | } 37510 | // (v + c0) - c1 --> (voc) v + (c0 - c1) 37511 | else if ((details::e_add == o0) && (details::e_sub == o1)) 37512 | { 37513 | exprtk_debug(("(v + c0) - c1 --> (voc) v + (c0 - c1)\n")); 37514 | 37515 | return expr_gen.node_allocator_-> 37516 | template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c0 - c1); 37517 | } 37518 | // (v - c0) + c1 --> (voc) v - (c0 + c1) 37519 | else if ((details::e_sub == o0) && (details::e_add == o1)) 37520 | { 37521 | exprtk_debug(("(v - c0) + c1 --> (voc) v - (c0 + c1)\n")); 37522 | 37523 | return expr_gen.node_allocator_-> 37524 | template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c1 - c0); 37525 | } 37526 | // (v - c0) - c1 --> (voc) v - (c0 + c1) 37527 | else if ((details::e_sub == o0) && (details::e_sub == o1)) 37528 | { 37529 | exprtk_debug(("(v - c0) - c1 --> (voc) v - (c0 + c1)\n")); 37530 | 37531 | return expr_gen.node_allocator_-> 37532 | template allocate_rc<typename details::voc_node<Type,details::sub_op<Type> > >(v, c0 + c1); 37533 | } 37534 | // (v * c0) * c1 --> (voc) v * (c0 * c1) 37535 | else if ((details::e_mul == o0) && (details::e_mul == o1)) 37536 | { 37537 | exprtk_debug(("(v * c0) * c1 --> (voc) v * (c0 * c1)\n")); 37538 | 37539 | return expr_gen.node_allocator_-> 37540 | template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c0 * c1); 37541 | } 37542 | // (v * c0) / c1 --> (voc) v * (c0 / c1) 37543 | else if ((details::e_mul == o0) && (details::e_div == o1)) 37544 | { 37545 | exprtk_debug(("(v * c0) / c1 --> (voc) v * (c0 / c1)\n")); 37546 | 37547 | return expr_gen.node_allocator_-> 37548 | template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c0 / c1); 37549 | } 37550 | // (v / c0) * c1 --> (voc) v * (c1 / c0) 37551 | else if ((details::e_div == o0) && (details::e_mul == o1)) 37552 | { 37553 | exprtk_debug(("(v / c0) * c1 --> (voc) v * (c1 / c0)\n")); 37554 | 37555 | return expr_gen.node_allocator_-> 37556 | template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c1 / c0); 37557 | } 37558 | // (v / c0) / c1 --> (voc) v / (c0 * c1) 37559 | else if ((details::e_div == o0) && (details::e_div == o1)) 37560 | { 37561 | exprtk_debug(("(v / c0) / c1 --> (voc) v / (c0 * c1)\n")); 37562 | 37563 | return expr_gen.node_allocator_-> 37564 | template allocate_rc<typename details::voc_node<Type,details::div_op<Type> > >(v, c0 * c1); 37565 | } 37566 | // (v ^ c0) ^ c1 --> (voc) v ^ (c0 * c1) 37567 | else if ((details::e_pow == o0) && (details::e_pow == o1)) 37568 | { 37569 | exprtk_debug(("(v ^ c0) ^ c1 --> (voc) v ^ (c0 * c1)\n")); 37570 | 37571 | return expr_gen.node_allocator_-> 37572 | template allocate_rc<typename details::voc_node<Type,details::pow_op<Type> > >(v, c0 * c1); 37573 | } 37574 | } 37575 | 37576 | const bool synthesis_result = 37577 | synthesize_sf3ext_expression::template compile<vtype, ctype, ctype> 37578 | (expr_gen, id(expr_gen, o0, o1), v, c0, c1, result); 37579 | 37580 | if (synthesis_result) 37581 | return result; 37582 | 37583 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37584 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37585 | 37586 | if (!expr_gen.valid_operator(o0,f0)) 37587 | return error_node(); 37588 | else if (!expr_gen.valid_operator(o1,f1)) 37589 | return error_node(); 37590 | else 37591 | return node_type::allocate(*(expr_gen.node_allocator_), v, c0, c1, f0, f1); 37592 | } 37593 | 37594 | static inline std::string id(expression_generator<Type>& expr_gen, 37595 | const details::operator_type o0, 37596 | const details::operator_type o1) 37597 | { 37598 | return details::build_string() 37599 | << "(t" << expr_gen.to_str(o0) 37600 | << "t)" << expr_gen.to_str(o1) 37601 | << "t" 37602 | } 37603 | }; 37604 | 37605 | struct synthesize_vococ_expression1 37606 | { 37607 | typedef typename vococ_t::type0 node_type; 37608 | 37609 | static inline expression_node_ptr process(expression_generator<Type>&, 37610 | const details::operator_type&, 37611 | expression_node_ptr (&)[2]) 37612 | { 37613 | // (v) o0 (c0 o1 c1) - Not possible. 37614 | exprtk_debug(("(v) o0 (c0 o1 c1) - Not possible.\n")); 37615 | return error_node(); 37616 | } 37617 | }; 37618 | 37619 | struct synthesize_vovovov_expression0 37620 | { 37621 | typedef typename vovovov_t::type0 node_type; 37622 | typedef typename vovovov_t::sf4_type sf4_type; 37623 | typedef typename node_type::T0 T0; 37624 | typedef typename node_type::T1 T1; 37625 | typedef typename node_type::T2 T2; 37626 | typedef typename node_type::T3 T3; 37627 | 37628 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37629 | const details::operator_type& operation, 37630 | expression_node_ptr (&branch)[2]) 37631 | { 37632 | // (v0 o0 v1) o1 (v2 o2 v3) 37633 | const details::vov_base_node<Type>* vov0 = static_cast<details::vov_base_node<Type>*>(branch[0]); 37634 | const details::vov_base_node<Type>* vov1 = static_cast<details::vov_base_node<Type>*>(branch[1]); 37635 | const Type& v0 = vov0->v0(); 37636 | const Type& v1 = vov0->v1(); 37637 | const Type& v2 = vov1->v0(); 37638 | const Type& v3 = vov1->v1(); 37639 | const details::operator_type o0 = vov0->operation(); 37640 | const details::operator_type o1 = operation; 37641 | const details::operator_type o2 = vov1->operation(); 37642 | 37643 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37644 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37645 | 37646 | expression_node_ptr result = error_node(); 37647 | 37648 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37649 | { 37650 | // (v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3) 37651 | if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 37652 | { 37653 | const bool synthesis_result = 37654 | synthesize_sf4ext_expression:: 37655 | template compile<vtype, vtype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, v3, result); 37656 | 37657 | exprtk_debug(("(v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3)\n")); 37658 | 37659 | return (synthesis_result) ? result : error_node(); 37660 | } 37661 | // (v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2) 37662 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 37663 | { 37664 | const bool synthesis_result = 37665 | synthesize_sf4ext_expression:: 37666 | template compile<vtype, vtype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", v0, v3, v1, v2, result); 37667 | 37668 | exprtk_debug(("(v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2)\n")); 37669 | 37670 | return (synthesis_result) ? result : error_node(); 37671 | } 37672 | // (v0 + v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2) 37673 | else if ((details::e_add == o0) && (details::e_div == o1) && (details::e_div == o2)) 37674 | { 37675 | const bool synthesis_result = 37676 | synthesize_sf4ext_expression:: 37677 | template compile<vtype, vtype, vtype, vtype>(expr_gen, "(t+t)*(t/t)", v0, v1, v3, v2, result); 37678 | 37679 | exprtk_debug(("(v0 + v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2)\n")); 37680 | 37681 | return (synthesis_result) ? result : error_node(); 37682 | } 37683 | // (v0 - v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2) 37684 | else if ((details::e_sub == o0) && (details::e_div == o1) && (details::e_div == o2)) 37685 | { 37686 | const bool synthesis_result = 37687 | synthesize_sf4ext_expression:: 37688 | template compile<vtype, vtype, vtype, vtype>(expr_gen, "(t-t)*(t/t)", v0, v1, v3, v2, result); 37689 | 37690 | exprtk_debug(("(v0 - v1) / (v2 / v3) --> (vovovov) (v0 - v1) * (v3 / v2)\n")); 37691 | 37692 | return (synthesis_result) ? result : error_node(); 37693 | } 37694 | // (v0 * v1) / (v2 / v3) --> (vovovov) ((v0 * v1) * v3) / v2 37695 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) 37696 | { 37697 | const bool synthesis_result = 37698 | synthesize_sf4ext_expression:: 37699 | template compile<vtype, vtype, vtype, vtype>(expr_gen, "((t*t)*t)/t", v0, v1, v3, v2, result); 37700 | 37701 | exprtk_debug(("(v0 * v1) / (v2 / v3) --> (vovovov) ((v0 * v1) * v3) / v2\n")); 37702 | 37703 | return (synthesis_result) ? result : error_node(); 37704 | } 37705 | } 37706 | 37707 | const bool synthesis_result = 37708 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 37709 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result); 37710 | 37711 | if (synthesis_result) 37712 | return result; 37713 | 37714 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37715 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37716 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 37717 | 37718 | if (!expr_gen.valid_operator(o0,f0)) 37719 | return error_node(); 37720 | else if (!expr_gen.valid_operator(o1,f1)) 37721 | return error_node(); 37722 | else if (!expr_gen.valid_operator(o2,f2)) 37723 | return error_node(); 37724 | else 37725 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2); 37726 | } 37727 | 37728 | static inline std::string id(expression_generator<Type>& expr_gen, 37729 | const details::operator_type o0, 37730 | const details::operator_type o1, 37731 | const details::operator_type o2) 37732 | { 37733 | return details::build_string() 37734 | << "(t" << expr_gen.to_str(o0) 37735 | << "t)" << expr_gen.to_str(o1) 37736 | << "(t" << expr_gen.to_str(o2) 37737 | << "t)" 37738 | } 37739 | }; 37740 | 37741 | struct synthesize_vovovoc_expression0 37742 | { 37743 | typedef typename vovovoc_t::type0 node_type; 37744 | typedef typename vovovoc_t::sf4_type sf4_type; 37745 | typedef typename node_type::T0 T0; 37746 | typedef typename node_type::T1 T1; 37747 | typedef typename node_type::T2 T2; 37748 | typedef typename node_type::T3 T3; 37749 | 37750 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37751 | const details::operator_type& operation, 37752 | expression_node_ptr (&branch)[2]) 37753 | { 37754 | // (v0 o0 v1) o1 (v2 o2 c) 37755 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]); 37756 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]); 37757 | const Type& v0 = vov->v0(); 37758 | const Type& v1 = vov->v1(); 37759 | const Type& v2 = voc->v (); 37760 | const Type c = voc->c (); 37761 | const details::operator_type o0 = vov->operation(); 37762 | const details::operator_type o1 = operation; 37763 | const details::operator_type o2 = voc->operation(); 37764 | 37765 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37766 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37767 | 37768 | expression_node_ptr result = error_node(); 37769 | 37770 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37771 | { 37772 | // (v0 / v1) * (v2 / c) --> (vovovoc) (v0 * v2) / (v1 * c) 37773 | if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 37774 | { 37775 | const bool synthesis_result = 37776 | synthesize_sf4ext_expression:: 37777 | template compile<vtype, vtype, vtype, ctype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, c, result); 37778 | 37779 | exprtk_debug(("(v0 / v1) * (v2 / c) --> (vovovoc) (v0 * v2) / (v1 * c)\n")); 37780 | 37781 | return (synthesis_result) ? result : error_node(); 37782 | } 37783 | // (v0 / v1) / (v2 / c) --> (vocovov) (v0 * c) / (v1 * v2) 37784 | if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 37785 | { 37786 | const bool synthesis_result = 37787 | synthesize_sf4ext_expression:: 37788 | template compile<vtype, ctype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", v0, c, v1, v2, result); 37789 | 37790 | exprtk_debug(("(v0 / v1) / (v2 / c) --> (vocovov) (v0 * c) / (v1 * v2)\n")); 37791 | 37792 | return (synthesis_result) ? result : error_node(); 37793 | } 37794 | } 37795 | 37796 | const bool synthesis_result = 37797 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 37798 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result); 37799 | 37800 | if (synthesis_result) 37801 | return result; 37802 | 37803 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37804 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37805 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 37806 | 37807 | if (!expr_gen.valid_operator(o0,f0)) 37808 | return error_node(); 37809 | else if (!expr_gen.valid_operator(o1,f1)) 37810 | return error_node(); 37811 | else if (!expr_gen.valid_operator(o2,f2)) 37812 | return error_node(); 37813 | else 37814 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2); 37815 | } 37816 | 37817 | static inline std::string id(expression_generator<Type>& expr_gen, 37818 | const details::operator_type o0, 37819 | const details::operator_type o1, 37820 | const details::operator_type o2) 37821 | { 37822 | return details::build_string() 37823 | << "(t" << expr_gen.to_str(o0) 37824 | << "t)" << expr_gen.to_str(o1) 37825 | << "(t" << expr_gen.to_str(o2) 37826 | << "t)" 37827 | } 37828 | }; 37829 | 37830 | struct synthesize_vovocov_expression0 37831 | { 37832 | typedef typename vovocov_t::type0 node_type; 37833 | typedef typename vovocov_t::sf4_type sf4_type; 37834 | typedef typename node_type::T0 T0; 37835 | typedef typename node_type::T1 T1; 37836 | typedef typename node_type::T2 T2; 37837 | typedef typename node_type::T3 T3; 37838 | 37839 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37840 | const details::operator_type& operation, 37841 | expression_node_ptr (&branch)[2]) 37842 | { 37843 | // (v0 o0 v1) o1 (c o2 v2) 37844 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]); 37845 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]); 37846 | const Type& v0 = vov->v0(); 37847 | const Type& v1 = vov->v1(); 37848 | const Type& v2 = cov->v (); 37849 | const Type c = cov->c (); 37850 | const details::operator_type o0 = vov->operation(); 37851 | const details::operator_type o1 = operation; 37852 | const details::operator_type o2 = cov->operation(); 37853 | 37854 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37855 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37856 | 37857 | expression_node_ptr result = error_node(); 37858 | 37859 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37860 | { 37861 | // (v0 / v1) * (c / v2) --> (vocovov) (v0 * c) / (v1 * v2) 37862 | if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 37863 | { 37864 | const bool synthesis_result = 37865 | synthesize_sf4ext_expression:: 37866 | template compile<vtype, ctype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", v0, c, v1, v2, result); 37867 | 37868 | exprtk_debug(("(v0 / v1) * (c / v2) --> (vocovov) (v0 * c) / (v1 * v2)\n")); 37869 | 37870 | return (synthesis_result) ? result : error_node(); 37871 | } 37872 | // (v0 / v1) / (c / v2) --> (vovovoc) (v0 * v2) / (v1 * c) 37873 | if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 37874 | { 37875 | const bool synthesis_result = 37876 | synthesize_sf4ext_expression:: 37877 | template compile<vtype, vtype, vtype, ctype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, c, result); 37878 | 37879 | exprtk_debug(("(v0 / v1) / (c / v2) --> (vovovoc) (v0 * v2) / (v1 * c)\n")); 37880 | 37881 | return (synthesis_result) ? result : error_node(); 37882 | } 37883 | } 37884 | 37885 | const bool synthesis_result = 37886 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 37887 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result); 37888 | 37889 | if (synthesis_result) 37890 | return result; 37891 | 37892 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37893 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37894 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 37895 | 37896 | if (!expr_gen.valid_operator(o0,f0)) 37897 | return error_node(); 37898 | else if (!expr_gen.valid_operator(o1,f1)) 37899 | return error_node(); 37900 | else if (!expr_gen.valid_operator(o2,f2)) 37901 | return error_node(); 37902 | else 37903 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2); 37904 | } 37905 | 37906 | static inline std::string id(expression_generator<Type>& expr_gen, 37907 | const details::operator_type o0, 37908 | const details::operator_type o1, 37909 | const details::operator_type o2) 37910 | { 37911 | return details::build_string() 37912 | << "(t" << expr_gen.to_str(o0) 37913 | << "t)" << expr_gen.to_str(o1) 37914 | << "(t" << expr_gen.to_str(o2) 37915 | << "t)" 37916 | } 37917 | }; 37918 | 37919 | struct synthesize_vocovov_expression0 37920 | { 37921 | typedef typename vocovov_t::type0 node_type; 37922 | typedef typename vocovov_t::sf4_type sf4_type; 37923 | typedef typename node_type::T0 T0; 37924 | typedef typename node_type::T1 T1; 37925 | typedef typename node_type::T2 T2; 37926 | typedef typename node_type::T3 T3; 37927 | 37928 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37929 | const details::operator_type& operation, 37930 | expression_node_ptr (&branch)[2]) 37931 | { 37932 | // (v0 o0 c) o1 (v1 o2 v2) 37933 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]); 37934 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]); 37935 | const Type c = voc->c (); 37936 | const Type& v0 = voc->v (); 37937 | const Type& v1 = vov->v0(); 37938 | const Type& v2 = vov->v1(); 37939 | const details::operator_type o0 = voc->operation(); 37940 | const details::operator_type o1 = operation; 37941 | const details::operator_type o2 = vov->operation(); 37942 | 37943 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37944 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37945 | 37946 | expression_node_ptr result = error_node(); 37947 | 37948 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37949 | { 37950 | // (v0 / c) * (v1 / v2) --> (vovocov) (v0 * v1) / (c * v2) 37951 | if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 37952 | { 37953 | const bool synthesis_result = 37954 | synthesize_sf4ext_expression:: 37955 | template compile<vtype, vtype, ctype, vtype>(expr_gen, "(t*t)/(t*t)", v0, v1, c, v2, result); 37956 | 37957 | exprtk_debug(("(v0 / c) * (v1 / v2) --> (vovocov) (v0 * v1) / (c * v2)\n")); 37958 | 37959 | return (synthesis_result) ? result : error_node(); 37960 | } 37961 | // (v0 / c) / (v1 / v2) --> (vovocov) (v0 * v2) / (c * v1) 37962 | if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 37963 | { 37964 | const bool synthesis_result = 37965 | synthesize_sf4ext_expression:: 37966 | template compile<vtype, vtype, ctype, vtype>(expr_gen, "(t*t)/(t*t)", v0, v2, c, v1, result); 37967 | 37968 | exprtk_debug(("(v0 / c) / (v1 / v2) --> (vovocov) (v0 * v2) / (c * v1)\n")); 37969 | 37970 | return (synthesis_result) ? result : error_node(); 37971 | } 37972 | } 37973 | 37974 | const bool synthesis_result = 37975 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 37976 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result); 37977 | 37978 | if (synthesis_result) 37979 | return result; 37980 | 37981 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37982 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37983 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 37984 | 37985 | if (!expr_gen.valid_operator(o0,f0)) 37986 | return error_node(); 37987 | else if (!expr_gen.valid_operator(o1,f1)) 37988 | return error_node(); 37989 | else if (!expr_gen.valid_operator(o2,f2)) 37990 | return error_node(); 37991 | else 37992 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2); 37993 | } 37994 | 37995 | static inline std::string id(expression_generator<Type>& expr_gen, 37996 | const details::operator_type o0, 37997 | const details::operator_type o1, 37998 | const details::operator_type o2) 37999 | { 38000 | return details::build_string() 38001 | << "(t" << expr_gen.to_str(o0) 38002 | << "t)" << expr_gen.to_str(o1) 38003 | << "(t" << expr_gen.to_str(o2) 38004 | << "t)" 38005 | } 38006 | }; 38007 | 38008 | struct synthesize_covovov_expression0 38009 | { 38010 | typedef typename covovov_t::type0 node_type; 38011 | typedef typename covovov_t::sf4_type sf4_type; 38012 | typedef typename node_type::T0 T0; 38013 | typedef typename node_type::T1 T1; 38014 | typedef typename node_type::T2 T2; 38015 | typedef typename node_type::T3 T3; 38016 | 38017 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38018 | const details::operator_type& operation, 38019 | expression_node_ptr (&branch)[2]) 38020 | { 38021 | // (c o0 v0) o1 (v1 o2 v2) 38022 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]); 38023 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]); 38024 | const Type c = cov->c (); 38025 | const Type& v0 = cov->v (); 38026 | const Type& v1 = vov->v0(); 38027 | const Type& v2 = vov->v1(); 38028 | const details::operator_type o0 = cov->operation(); 38029 | const details::operator_type o1 = operation; 38030 | const details::operator_type o2 = vov->operation(); 38031 | 38032 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 38033 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38034 | 38035 | expression_node_ptr result = error_node(); 38036 | 38037 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 38038 | { 38039 | // (c / v0) * (v1 / v2) --> (covovov) (c * v1) / (v0 * v2) 38040 | if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 38041 | { 38042 | const bool synthesis_result = 38043 | synthesize_sf4ext_expression:: 38044 | template compile<ctype, vtype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", c, v1, v0, v2, result); 38045 | 38046 | exprtk_debug(("(c / v0) * (v1 / v2) --> (covovov) (c * v1) / (v0 * v2)\n")); 38047 | 38048 | return (synthesis_result) ? result : error_node(); 38049 | } 38050 | // (c / v0) / (v1 / v2) --> (covovov) (c * v2) / (v0 * v1) 38051 | if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 38052 | { 38053 | const bool synthesis_result = 38054 | synthesize_sf4ext_expression:: 38055 | template compile<ctype, vtype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", c, v2, v0, v1, result); 38056 | 38057 | exprtk_debug(("(c / v0) / (v1 / v2) --> (covovov) (c * v2) / (v0 * v1)\n")); 38058 | 38059 | return (synthesis_result) ? result : error_node(); 38060 | } 38061 | } 38062 | 38063 | const bool synthesis_result = 38064 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38065 | (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result); 38066 | 38067 | if (synthesis_result) 38068 | return result; 38069 | 38070 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38071 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 38072 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 38073 | 38074 | if (!expr_gen.valid_operator(o0,f0)) 38075 | return error_node(); 38076 | else if (!expr_gen.valid_operator(o1,f1)) 38077 | return error_node(); 38078 | else if (!expr_gen.valid_operator(o2,f2)) 38079 | return error_node(); 38080 | else 38081 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2); 38082 | } 38083 | 38084 | static inline std::string id(expression_generator<Type>& expr_gen, 38085 | const details::operator_type o0, 38086 | const details::operator_type o1, 38087 | const details::operator_type o2) 38088 | { 38089 | return details::build_string() 38090 | << "(t" << expr_gen.to_str(o0) 38091 | << "t)" << expr_gen.to_str(o1) 38092 | << "(t" << expr_gen.to_str(o2) 38093 | << "t)" 38094 | } 38095 | }; 38096 | 38097 | struct synthesize_covocov_expression0 38098 | { 38099 | typedef typename covocov_t::type0 node_type; 38100 | typedef typename covocov_t::sf4_type sf4_type; 38101 | typedef typename node_type::T0 T0; 38102 | typedef typename node_type::T1 T1; 38103 | typedef typename node_type::T2 T2; 38104 | typedef typename node_type::T3 T3; 38105 | 38106 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38107 | const details::operator_type& operation, 38108 | expression_node_ptr (&branch)[2]) 38109 | { 38110 | // (c0 o0 v0) o1 (c1 o2 v1) 38111 | const details::cov_base_node<Type>* cov0 = static_cast<details::cov_base_node<Type>*>(branch[0]); 38112 | const details::cov_base_node<Type>* cov1 = static_cast<details::cov_base_node<Type>*>(branch[1]); 38113 | const Type c0 = cov0->c(); 38114 | const Type& v0 = cov0->v(); 38115 | const Type c1 = cov1->c(); 38116 | const Type& v1 = cov1->v(); 38117 | const details::operator_type o0 = cov0->operation(); 38118 | const details::operator_type o1 = operation; 38119 | const details::operator_type o2 = cov1->operation(); 38120 | 38121 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 38122 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38123 | 38124 | expression_node_ptr result = error_node(); 38125 | 38126 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 38127 | { 38128 | // (c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1 38129 | if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2)) 38130 | { 38131 | const bool synthesis_result = 38132 | synthesize_sf3ext_expression:: 38133 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result); 38134 | 38135 | exprtk_debug(("(c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n")); 38136 | 38137 | return (synthesis_result) ? result : error_node(); 38138 | } 38139 | // (c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1 38140 | else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2)) 38141 | { 38142 | const bool synthesis_result = 38143 | synthesize_sf3ext_expression:: 38144 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result); 38145 | 38146 | exprtk_debug(("(c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n")); 38147 | 38148 | return (synthesis_result) ? result : error_node(); 38149 | } 38150 | // (c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1 38151 | else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2)) 38152 | { 38153 | const bool synthesis_result = 38154 | synthesize_sf3ext_expression:: 38155 | template compile<ctype, vtype, vtype>(expr_gen, "(t-t)+t", (c0 - c1), v0, v1, result); 38156 | 38157 | exprtk_debug(("(c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1\n")); 38158 | 38159 | return (synthesis_result) ? result : error_node(); 38160 | } 38161 | // (c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1 38162 | else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2)) 38163 | { 38164 | const bool synthesis_result = 38165 | synthesize_sf3ext_expression:: 38166 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result); 38167 | 38168 | exprtk_debug(("(c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n")); 38169 | 38170 | return (synthesis_result) ? result : error_node(); 38171 | } 38172 | // (c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1) 38173 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38174 | { 38175 | const bool synthesis_result = 38176 | synthesize_sf3ext_expression:: 38177 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result); 38178 | 38179 | exprtk_debug(("(c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1)\n")); 38180 | 38181 | return (synthesis_result) ? result : error_node(); 38182 | } 38183 | // (c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1) 38184 | else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 38185 | { 38186 | const bool synthesis_result = 38187 | synthesize_sf3ext_expression:: 38188 | template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", (c0 * c1), v0, v1, result); 38189 | 38190 | exprtk_debug(("(c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1)\n")); 38191 | 38192 | return (synthesis_result) ? result : error_node(); 38193 | } 38194 | // (c0 / v0) / (c1 / v1) --> (covov) ((c0 / c1) * v1) / v0 38195 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 38196 | { 38197 | const bool synthesis_result = 38198 | synthesize_sf3ext_expression:: 38199 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v1, v0, result); 38200 | 38201 | exprtk_debug(("(c0 / v0) / (c1 / v1) --> (covov) ((c0 / c1) * v1) / v0\n")); 38202 | 38203 | return (synthesis_result) ? result : error_node(); 38204 | } 38205 | // (c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1) 38206 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) 38207 | { 38208 | const bool synthesis_result = 38209 | synthesize_sf3ext_expression:: 38210 | template compile<ctype, vtype, vtype>(expr_gen, "t*(t*t)", (c0 / c1), v0, v1, result); 38211 | 38212 | exprtk_debug(("(c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n")); 38213 | 38214 | return (synthesis_result) ? result : error_node(); 38215 | } 38216 | // (c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1) 38217 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38218 | { 38219 | const bool synthesis_result = 38220 | synthesize_sf3ext_expression:: 38221 | template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", (c0 / c1), v0, v1, result); 38222 | 38223 | exprtk_debug(("(c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1)\n")); 38224 | 38225 | return (synthesis_result) ? result : error_node(); 38226 | } 38227 | // (c * v0) +/- (c * v1) --> (covov) c * (v0 +/- v1) 38228 | else if ( 38229 | (std::equal_to<T>()(c0,c1)) && 38230 | (details::e_mul == o0) && 38231 | (details::e_mul == o2) && 38232 | ( 38233 | (details::e_add == o1) || 38234 | (details::e_sub == o1) 38235 | ) 38236 | ) 38237 | { 38238 | std::string specfunc; 38239 | 38240 | switch (o1) 38241 | { 38242 | case details::e_add : specfunc = "t*(t+t)" break; 38243 | case details::e_sub : specfunc = "t*(t-t)" break; 38244 | default : return error_node(); 38245 | } 38246 | 38247 | const bool synthesis_result = 38248 | synthesize_sf3ext_expression:: 38249 | template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result); 38250 | 38251 | exprtk_debug(("(c * v0) +/- (c * v1) --> (covov) c * (v0 +/- v1)\n")); 38252 | 38253 | return (synthesis_result) ? result : error_node(); 38254 | } 38255 | } 38256 | 38257 | const bool synthesis_result = 38258 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38259 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result); 38260 | 38261 | if (synthesis_result) 38262 | return result; 38263 | 38264 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38265 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 38266 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 38267 | 38268 | if (!expr_gen.valid_operator(o0,f0)) 38269 | return error_node(); 38270 | else if (!expr_gen.valid_operator(o1,f1)) 38271 | return error_node(); 38272 | else if (!expr_gen.valid_operator(o2,f2)) 38273 | return error_node(); 38274 | else 38275 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2); 38276 | } 38277 | 38278 | static inline std::string id(expression_generator<Type>& expr_gen, 38279 | const details::operator_type o0, 38280 | const details::operator_type o1, 38281 | const details::operator_type o2) 38282 | { 38283 | return details::build_string() 38284 | << "(t" << expr_gen.to_str(o0) 38285 | << "t)" << expr_gen.to_str(o1) 38286 | << "(t" << expr_gen.to_str(o2) 38287 | << "t)" 38288 | } 38289 | }; 38290 | 38291 | struct synthesize_vocovoc_expression0 38292 | { 38293 | typedef typename vocovoc_t::type0 node_type; 38294 | typedef typename vocovoc_t::sf4_type sf4_type; 38295 | typedef typename node_type::T0 T0; 38296 | typedef typename node_type::T1 T1; 38297 | typedef typename node_type::T2 T2; 38298 | typedef typename node_type::T3 T3; 38299 | 38300 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38301 | const details::operator_type& operation, 38302 | expression_node_ptr (&branch)[2]) 38303 | { 38304 | // (v0 o0 c0) o1 (v1 o2 c1) 38305 | const details::voc_base_node<Type>* voc0 = static_cast<details::voc_base_node<Type>*>(branch[0]); 38306 | const details::voc_base_node<Type>* voc1 = static_cast<details::voc_base_node<Type>*>(branch[1]); 38307 | const Type c0 = voc0->c(); 38308 | const Type& v0 = voc0->v(); 38309 | const Type c1 = voc1->c(); 38310 | const Type& v1 = voc1->v(); 38311 | const details::operator_type o0 = voc0->operation(); 38312 | const details::operator_type o1 = operation; 38313 | const details::operator_type o2 = voc1->operation(); 38314 | 38315 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 38316 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38317 | 38318 | expression_node_ptr result = error_node(); 38319 | 38320 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 38321 | { 38322 | // (v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1 38323 | if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2)) 38324 | { 38325 | const bool synthesis_result = 38326 | synthesize_sf3ext_expression:: 38327 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result); 38328 | 38329 | exprtk_debug(("(v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n")); 38330 | 38331 | return (synthesis_result) ? result : error_node(); 38332 | } 38333 | // (v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1 38334 | else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2)) 38335 | { 38336 | const bool synthesis_result = 38337 | synthesize_sf3ext_expression:: 38338 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result); 38339 | 38340 | exprtk_debug(("(v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n")); 38341 | 38342 | return (synthesis_result) ? result : error_node(); 38343 | } 38344 | // (v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1 38345 | else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2)) 38346 | { 38347 | const bool synthesis_result = 38348 | synthesize_sf3ext_expression:: 38349 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c1 - c0), v0, v1, result); 38350 | 38351 | exprtk_debug(("(v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1\n")); 38352 | 38353 | return (synthesis_result) ? result : error_node(); 38354 | } 38355 | // (v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1 38356 | else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2)) 38357 | { 38358 | const bool synthesis_result = 38359 | synthesize_sf3ext_expression:: 38360 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result); 38361 | 38362 | exprtk_debug(("(v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n")); 38363 | 38364 | return (synthesis_result) ? result : error_node(); 38365 | } 38366 | // (v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1) 38367 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38368 | { 38369 | const bool synthesis_result = 38370 | synthesize_sf3ext_expression:: 38371 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result); 38372 | 38373 | exprtk_debug(("(v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n")); 38374 | 38375 | return (synthesis_result) ? result : error_node(); 38376 | } 38377 | // (v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1 38378 | else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 38379 | { 38380 | const bool synthesis_result = 38381 | synthesize_sf3ext_expression:: 38382 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", Type(1) / (c0 * c1), v0, v1, result); 38383 | 38384 | exprtk_debug(("(v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1\n")); 38385 | 38386 | return (synthesis_result) ? result : error_node(); 38387 | } 38388 | // (v0 / c0) / (v1 / c1) --> (covov) ((c1 / c0) * v0) / v1 38389 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 38390 | { 38391 | const bool synthesis_result = 38392 | synthesize_sf3ext_expression:: 38393 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c1 / c0), v0, v1, result); 38394 | 38395 | exprtk_debug(("(v0 / c0) / (v1 / c1) --> (covov) ((c1 / c0) * v0) / v1\n")); 38396 | 38397 | return (synthesis_result) ? result : error_node(); 38398 | } 38399 | // (v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1) 38400 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) 38401 | { 38402 | const bool synthesis_result = 38403 | synthesize_sf3ext_expression:: 38404 | template compile<ctype, vtype, vtype>(expr_gen, "t*(t/t)", (c0 * c1), v0, v1, result); 38405 | 38406 | exprtk_debug(("(v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n")); 38407 | 38408 | return (synthesis_result) ? result : error_node(); 38409 | } 38410 | // (v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1 38411 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38412 | { 38413 | const bool synthesis_result = 38414 | synthesize_sf3ext_expression:: 38415 | template compile<ctype, vtype, vtype>(expr_gen, "t*(t/t)", Type(1) / (c0 * c1), v0, v1, result); 38416 | 38417 | exprtk_debug(("(v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1\n")); 38418 | 38419 | return (synthesis_result) ? result : error_node(); 38420 | } 38421 | // (v0 / c0) * (v1 + c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 + c1) 38422 | else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_add == o2)) 38423 | { 38424 | const bool synthesis_result = 38425 | synthesize_sf4ext_expression:: 38426 | template compile<vtype, ctype, vtype, ctype>(expr_gen, "(t*t)*(t+t)", v0, T(1) / c0, v1, c1, result); 38427 | 38428 | exprtk_debug(("(v0 / c0) * (v1 + c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 + c1)\n")); 38429 | 38430 | return (synthesis_result) ? result : error_node(); 38431 | } 38432 | // (v0 / c0) * (v1 - c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 - c1) 38433 | else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_sub == o2)) 38434 | { 38435 | const bool synthesis_result = 38436 | synthesize_sf4ext_expression:: 38437 | template compile<vtype, ctype, vtype, ctype>(expr_gen, "(t*t)*(t-t)", v0, T(1) / c0, v1, c1, result); 38438 | 38439 | exprtk_debug(("(v0 / c0) * (v1 - c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 - c1)\n")); 38440 | 38441 | return (synthesis_result) ? result : error_node(); 38442 | } 38443 | // (v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1) 38444 | else if ( 38445 | (std::equal_to<T>()(c0,c1)) && 38446 | (details::e_mul == o0) && 38447 | (details::e_mul == o2) && 38448 | ( 38449 | (details::e_add == o1) || 38450 | (details::e_sub == o1) 38451 | ) 38452 | ) 38453 | { 38454 | std::string specfunc; 38455 | 38456 | switch (o1) 38457 | { 38458 | case details::e_add : specfunc = "t*(t+t)" break; 38459 | case details::e_sub : specfunc = "t*(t-t)" break; 38460 | default : return error_node(); 38461 | } 38462 | 38463 | const bool synthesis_result = 38464 | synthesize_sf3ext_expression:: 38465 | template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result); 38466 | 38467 | exprtk_debug(("(v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n")); 38468 | 38469 | return (synthesis_result) ? result : error_node(); 38470 | } 38471 | // (v0 / c) +/- (v1 / c) --> (vovoc) (v0 +/- v1) / c 38472 | else if ( 38473 | (std::equal_to<T>()(c0,c1)) && 38474 | (details::e_div == o0) && 38475 | (details::e_div == o2) && 38476 | ( 38477 | (details::e_add == o1) || 38478 | (details::e_sub == o1) 38479 | ) 38480 | ) 38481 | { 38482 | std::string specfunc; 38483 | 38484 | switch (o1) 38485 | { 38486 | case details::e_add : specfunc = "(t+t)/t" break; 38487 | case details::e_sub : specfunc = "(t-t)/t" break; 38488 | default : return error_node(); 38489 | } 38490 | 38491 | const bool synthesis_result = 38492 | synthesize_sf3ext_expression:: 38493 | template compile<vtype, vtype, ctype>(expr_gen, specfunc, v0, v1, c0, result); 38494 | 38495 | exprtk_debug(("(v0 / c) +/- (v1 / c) --> (vovoc) (v0 +/- v1) / c\n")); 38496 | 38497 | return (synthesis_result) ? result : error_node(); 38498 | } 38499 | } 38500 | 38501 | const bool synthesis_result = 38502 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38503 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result); 38504 | 38505 | if (synthesis_result) 38506 | return result; 38507 | 38508 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38509 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 38510 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 38511 | 38512 | if (!expr_gen.valid_operator(o0,f0)) 38513 | return error_node(); 38514 | else if (!expr_gen.valid_operator(o1,f1)) 38515 | return error_node(); 38516 | else if (!expr_gen.valid_operator(o2,f2)) 38517 | return error_node(); 38518 | else 38519 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2); 38520 | } 38521 | 38522 | static inline std::string id(expression_generator<Type>& expr_gen, 38523 | const details::operator_type o0, 38524 | const details::operator_type o1, 38525 | const details::operator_type o2) 38526 | { 38527 | return details::build_string() 38528 | << "(t" << expr_gen.to_str(o0) 38529 | << "t)" << expr_gen.to_str(o1) 38530 | << "(t" << expr_gen.to_str(o2) 38531 | << "t)" 38532 | } 38533 | }; 38534 | 38535 | struct synthesize_covovoc_expression0 38536 | { 38537 | typedef typename covovoc_t::type0 node_type; 38538 | typedef typename covovoc_t::sf4_type sf4_type; 38539 | typedef typename node_type::T0 T0; 38540 | typedef typename node_type::T1 T1; 38541 | typedef typename node_type::T2 T2; 38542 | typedef typename node_type::T3 T3; 38543 | 38544 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38545 | const details::operator_type& operation, 38546 | expression_node_ptr (&branch)[2]) 38547 | { 38548 | // (c0 o0 v0) o1 (v1 o2 c1) 38549 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]); 38550 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]); 38551 | const Type c0 = cov->c(); 38552 | const Type& v0 = cov->v(); 38553 | const Type c1 = voc->c(); 38554 | const Type& v1 = voc->v(); 38555 | const details::operator_type o0 = cov->operation(); 38556 | const details::operator_type o1 = operation; 38557 | const details::operator_type o2 = voc->operation(); 38558 | 38559 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 38560 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38561 | 38562 | expression_node_ptr result = error_node(); 38563 | 38564 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 38565 | { 38566 | // (c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1 38567 | if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2)) 38568 | { 38569 | const bool synthesis_result = 38570 | synthesize_sf3ext_expression:: 38571 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result); 38572 | 38573 | exprtk_debug(("(c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n")); 38574 | 38575 | return (synthesis_result) ? result : error_node(); 38576 | } 38577 | // (c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1 38578 | else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2)) 38579 | { 38580 | const bool synthesis_result = 38581 | synthesize_sf3ext_expression:: 38582 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result); 38583 | 38584 | exprtk_debug(("(c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n")); 38585 | 38586 | return (synthesis_result) ? result : error_node(); 38587 | } 38588 | // (c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1 38589 | else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2)) 38590 | { 38591 | const bool synthesis_result = 38592 | synthesize_sf3ext_expression:: 38593 | template compile<ctype, vtype, vtype>(expr_gen, "t-(t+t)", (c0 + c1), v0, v1, result); 38594 | 38595 | exprtk_debug(("(c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1\n")); 38596 | 38597 | return (synthesis_result) ? result : error_node(); 38598 | } 38599 | // (c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1 38600 | else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2)) 38601 | { 38602 | const bool synthesis_result = 38603 | synthesize_sf3ext_expression:: 38604 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result); 38605 | 38606 | exprtk_debug(("(c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n")); 38607 | 38608 | return (synthesis_result) ? result : error_node(); 38609 | } 38610 | // (c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1) 38611 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38612 | { 38613 | const bool synthesis_result = 38614 | synthesize_sf3ext_expression:: 38615 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result); 38616 | 38617 | exprtk_debug(("(c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n")); 38618 | 38619 | return (synthesis_result) ? result : error_node(); 38620 | } 38621 | // (c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0) 38622 | else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 38623 | { 38624 | const bool synthesis_result = 38625 | synthesize_sf3ext_expression:: 38626 | template compile<ctype, vtype, vtype>(expr_gen, "t*(t/t)", (c0 / c1), v1, v0, result); 38627 | 38628 | exprtk_debug(("(c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0)\n")); 38629 | 38630 | return (synthesis_result) ? result : error_node(); 38631 | } 38632 | // (c0 / v0) / (v1 / c1) --> (covov) (c0 * c1) / (v0 * v1) 38633 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 38634 | { 38635 | const bool synthesis_result = 38636 | synthesize_sf3ext_expression:: 38637 | template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", (c0 * c1), v0, v1, result); 38638 | 38639 | exprtk_debug(("(c0 / v0) / (v1 / c1) --> (covov) (c0 * c1) / (v0 * v1)\n")); 38640 | 38641 | return (synthesis_result) ? result : error_node(); 38642 | } 38643 | // (c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1) 38644 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) 38645 | { 38646 | const bool synthesis_result = 38647 | synthesize_sf3ext_expression:: 38648 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 * c1), v0, v1, result); 38649 | 38650 | exprtk_debug(("(c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n")); 38651 | 38652 | return (synthesis_result) ? result : error_node(); 38653 | } 38654 | // (c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1) 38655 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38656 | { 38657 | const bool synthesis_result = 38658 | synthesize_sf3ext_expression:: 38659 | template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", (c0 / c1), v0, v1, result); 38660 | 38661 | exprtk_debug(("(c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1)\n")); 38662 | 38663 | return (synthesis_result) ? result : error_node(); 38664 | } 38665 | // (c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1) 38666 | else if ( 38667 | (std::equal_to<T>()(c0,c1)) && 38668 | (details::e_mul == o0) && 38669 | (details::e_mul == o2) && 38670 | ( 38671 | (details::e_add == o1) || 38672 | (details::e_sub == o1) 38673 | ) 38674 | ) 38675 | { 38676 | std::string specfunc; 38677 | 38678 | switch (o1) 38679 | { 38680 | case details::e_add : specfunc = "t*(t+t)" break; 38681 | case details::e_sub : specfunc = "t*(t-t)" break; 38682 | default : return error_node(); 38683 | } 38684 | 38685 | const bool synthesis_result = 38686 | synthesize_sf3ext_expression:: 38687 | template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result); 38688 | 38689 | exprtk_debug(("(c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n")); 38690 | 38691 | return (synthesis_result) ? result : error_node(); 38692 | } 38693 | } 38694 | 38695 | const bool synthesis_result = 38696 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38697 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result); 38698 | 38699 | if (synthesis_result) 38700 | return result; 38701 | 38702 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38703 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 38704 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 38705 | 38706 | if (!expr_gen.valid_operator(o0,f0)) 38707 | return error_node(); 38708 | else if (!expr_gen.valid_operator(o1,f1)) 38709 | return error_node(); 38710 | else if (!expr_gen.valid_operator(o2,f2)) 38711 | return error_node(); 38712 | else 38713 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2); 38714 | } 38715 | 38716 | static inline std::string id(expression_generator<Type>& expr_gen, 38717 | const details::operator_type o0, 38718 | const details::operator_type o1, 38719 | const details::operator_type o2) 38720 | { 38721 | return details::build_string() 38722 | << "(t" << expr_gen.to_str(o0) 38723 | << "t)" << expr_gen.to_str(o1) 38724 | << "(t" << expr_gen.to_str(o2) 38725 | << "t)" 38726 | } 38727 | }; 38728 | 38729 | struct synthesize_vococov_expression0 38730 | { 38731 | typedef typename vococov_t::type0 node_type; 38732 | typedef typename vococov_t::sf4_type sf4_type; 38733 | typedef typename node_type::T0 T0; 38734 | typedef typename node_type::T1 T1; 38735 | typedef typename node_type::T2 T2; 38736 | typedef typename node_type::T3 T3; 38737 | 38738 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38739 | const details::operator_type& operation, 38740 | expression_node_ptr (&branch)[2]) 38741 | { 38742 | // (v0 o0 c0) o1 (c1 o2 v1) 38743 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]); 38744 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]); 38745 | const Type c0 = voc->c(); 38746 | const Type& v0 = voc->v(); 38747 | const Type c1 = cov->c(); 38748 | const Type& v1 = cov->v(); 38749 | const details::operator_type o0 = voc->operation(); 38750 | const details::operator_type o1 = operation; 38751 | const details::operator_type o2 = cov->operation(); 38752 | 38753 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 38754 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38755 | 38756 | expression_node_ptr result = error_node(); 38757 | 38758 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 38759 | { 38760 | // (v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1 38761 | if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2)) 38762 | { 38763 | const bool synthesis_result = 38764 | synthesize_sf3ext_expression:: 38765 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result); 38766 | 38767 | exprtk_debug(("(v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n")); 38768 | 38769 | return (synthesis_result) ? result : error_node(); 38770 | } 38771 | // (v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1 38772 | else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2)) 38773 | { 38774 | const bool synthesis_result = 38775 | synthesize_sf3ext_expression:: 38776 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result); 38777 | 38778 | exprtk_debug(("(v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n")); 38779 | 38780 | return (synthesis_result) ? result : error_node(); 38781 | } 38782 | // (v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0) 38783 | else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2)) 38784 | { 38785 | const bool synthesis_result = 38786 | synthesize_sf3ext_expression:: 38787 | template compile<vtype, vtype, ctype>(expr_gen, "(t+t)-t", v0, v1, (c1 + c0), result); 38788 | 38789 | exprtk_debug(("(v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0)\n")); 38790 | 38791 | return (synthesis_result) ? result : error_node(); 38792 | } 38793 | // (v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1 38794 | else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2)) 38795 | { 38796 | const bool synthesis_result = 38797 | synthesize_sf3ext_expression:: 38798 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result); 38799 | 38800 | exprtk_debug(("(v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n")); 38801 | 38802 | return (synthesis_result) ? result : error_node(); 38803 | } 38804 | // (v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1) 38805 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38806 | { 38807 | const bool synthesis_result = 38808 | synthesize_sf3ext_expression:: 38809 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result); 38810 | 38811 | exprtk_debug(("(v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1)\n")); 38812 | 38813 | return (synthesis_result) ? result : error_node(); 38814 | } 38815 | // (v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1) 38816 | else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 38817 | { 38818 | const bool synthesis_result = 38819 | synthesize_sf3ext_expression:: 38820 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c1 / c0), v0, v1, result); 38821 | 38822 | exprtk_debug(("(v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1)\n")); 38823 | 38824 | return (synthesis_result) ? result : error_node(); 38825 | } 38826 | // (v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1) 38827 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) 38828 | { 38829 | const bool synthesis_result = 38830 | synthesize_sf3ext_expression:: 38831 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 / c1), v0, v1, result); 38832 | 38833 | exprtk_debug(("(v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n")); 38834 | 38835 | return (synthesis_result) ? result : error_node(); 38836 | } 38837 | // (v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1) 38838 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38839 | { 38840 | const bool synthesis_result = 38841 | synthesize_sf3ext_expression:: 38842 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", Type(1) / (c0 * c1), v0, v1, result); 38843 | 38844 | exprtk_debug(("(v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1)\n")); 38845 | 38846 | return (synthesis_result) ? result : error_node(); 38847 | } 38848 | // (v0 / c0) / (c1 / v1) --> (vovoc) (v0 * v1) * (1 / (c0 * c1)) 38849 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 38850 | { 38851 | const bool synthesis_result = 38852 | synthesize_sf3ext_expression:: 38853 | template compile<vtype, vtype, ctype>(expr_gen, "(t*t)*t", v0, v1, Type(1) / (c0 * c1), result); 38854 | 38855 | exprtk_debug(("(v0 / c0) / (c1 / v1) --> (vovoc) (v0 * v1) * (1 / (c0 * c1))\n")); 38856 | 38857 | return (synthesis_result) ? result : error_node(); 38858 | } 38859 | // (v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1) 38860 | else if ( 38861 | (std::equal_to<T>()(c0,c1)) && 38862 | (details::e_mul == o0) && 38863 | (details::e_mul == o2) && 38864 | ( 38865 | (details::e_add == o1) || (details::e_sub == o1) 38866 | ) 38867 | ) 38868 | { 38869 | std::string specfunc; 38870 | 38871 | switch (o1) 38872 | { 38873 | case details::e_add : specfunc = "t*(t+t)" break; 38874 | case details::e_sub : specfunc = "t*(t-t)" break; 38875 | default : return error_node(); 38876 | } 38877 | 38878 | const bool synthesis_result = 38879 | synthesize_sf3ext_expression:: 38880 | template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result); 38881 | 38882 | exprtk_debug(("(v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1)\n")); 38883 | 38884 | return (synthesis_result) ? result : error_node(); 38885 | } 38886 | } 38887 | 38888 | const bool synthesis_result = 38889 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38890 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result); 38891 | 38892 | if (synthesis_result) 38893 | return result; 38894 | 38895 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38896 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 38897 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 38898 | 38899 | if (!expr_gen.valid_operator(o0,f0)) 38900 | return error_node(); 38901 | else if (!expr_gen.valid_operator(o1,f1)) 38902 | return error_node(); 38903 | else if (!expr_gen.valid_operator(o2,f2)) 38904 | return error_node(); 38905 | else 38906 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2); 38907 | } 38908 | 38909 | static inline std::string id(expression_generator<Type>& expr_gen, 38910 | const details::operator_type o0, 38911 | const details::operator_type o1, 38912 | const details::operator_type o2) 38913 | { 38914 | return details::build_string() 38915 | << "(t" << expr_gen.to_str(o0) 38916 | << "t)" << expr_gen.to_str(o1) 38917 | << "(t" << expr_gen.to_str(o2) 38918 | << "t)" 38919 | } 38920 | }; 38921 | 38922 | struct synthesize_vovovov_expression1 38923 | { 38924 | typedef typename vovovov_t::type1 node_type; 38925 | typedef typename vovovov_t::sf4_type sf4_type; 38926 | typedef typename node_type::T0 T0; 38927 | typedef typename node_type::T1 T1; 38928 | typedef typename node_type::T2 T2; 38929 | typedef typename node_type::T3 T3; 38930 | 38931 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38932 | const details::operator_type& operation, 38933 | expression_node_ptr (&branch)[2]) 38934 | { 38935 | // v0 o0 (v1 o1 (v2 o2 v3)) 38936 | typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t; 38937 | 38938 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]); 38939 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 38940 | const Type& v1 = vovov->t0(); 38941 | const Type& v2 = vovov->t1(); 38942 | const Type& v3 = vovov->t2(); 38943 | const details::operator_type o0 = operation; 38944 | const details::operator_type o1 = expr_gen.get_operator(vovov->f0()); 38945 | const details::operator_type o2 = expr_gen.get_operator(vovov->f1()); 38946 | 38947 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38948 | binary_functor_t f1 = vovov->f0(); 38949 | binary_functor_t f2 = vovov->f1(); 38950 | 38951 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38952 | 38953 | expression_node_ptr result = error_node(); 38954 | 38955 | const bool synthesis_result = 38956 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38957 | (expr_gen,id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result); 38958 | 38959 | if (synthesis_result) 38960 | return result; 38961 | else if (!expr_gen.valid_operator(o0,f0)) 38962 | return error_node(); 38963 | 38964 | exprtk_debug(("v0 o0 (v1 o1 (v2 o2 v3))\n")); 38965 | 38966 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2); 38967 | } 38968 | 38969 | static inline std::string id(expression_generator<Type>& expr_gen, 38970 | const details::operator_type o0, 38971 | const details::operator_type o1, 38972 | const details::operator_type o2) 38973 | { 38974 | return details::build_string() 38975 | << "t" << expr_gen.to_str(o0) 38976 | << "(t" << expr_gen.to_str(o1) 38977 | << "(t" << expr_gen.to_str(o2) 38978 | << "t))" 38979 | } 38980 | }; 38981 | 38982 | struct synthesize_vovovoc_expression1 38983 | { 38984 | typedef typename vovovoc_t::type1 node_type; 38985 | typedef typename vovovoc_t::sf4_type sf4_type; 38986 | typedef typename node_type::T0 T0; 38987 | typedef typename node_type::T1 T1; 38988 | typedef typename node_type::T2 T2; 38989 | typedef typename node_type::T3 T3; 38990 | 38991 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38992 | const details::operator_type& operation, 38993 | expression_node_ptr (&branch)[2]) 38994 | { 38995 | // v0 o0 (v1 o1 (v2 o2 c)) 38996 | typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t; 38997 | 38998 | const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]); 38999 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39000 | const Type& v1 = vovoc->t0(); 39001 | const Type& v2 = vovoc->t1(); 39002 | const Type c = vovoc->t2(); 39003 | const details::operator_type o0 = operation; 39004 | const details::operator_type o1 = expr_gen.get_operator(vovoc->f0()); 39005 | const details::operator_type o2 = expr_gen.get_operator(vovoc->f1()); 39006 | 39007 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39008 | binary_functor_t f1 = vovoc->f0(); 39009 | binary_functor_t f2 = vovoc->f1(); 39010 | 39011 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39012 | 39013 | expression_node_ptr result = error_node(); 39014 | 39015 | const bool synthesis_result = 39016 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39017 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result); 39018 | 39019 | if (synthesis_result) 39020 | return result; 39021 | else if (!expr_gen.valid_operator(o0,f0)) 39022 | return error_node(); 39023 | 39024 | exprtk_debug(("v0 o0 (v1 o1 (v2 o2 c))\n")); 39025 | 39026 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2); 39027 | } 39028 | 39029 | static inline std::string id(expression_generator<Type>& expr_gen, 39030 | const details::operator_type o0, 39031 | const details::operator_type o1, 39032 | const details::operator_type o2) 39033 | { 39034 | return details::build_string() 39035 | << "t" << expr_gen.to_str(o0) 39036 | << "(t" << expr_gen.to_str(o1) 39037 | << "(t" << expr_gen.to_str(o2) 39038 | << "t))" 39039 | } 39040 | }; 39041 | 39042 | struct synthesize_vovocov_expression1 39043 | { 39044 | typedef typename vovocov_t::type1 node_type; 39045 | typedef typename vovocov_t::sf4_type sf4_type; 39046 | typedef typename node_type::T0 T0; 39047 | typedef typename node_type::T1 T1; 39048 | typedef typename node_type::T2 T2; 39049 | typedef typename node_type::T3 T3; 39050 | 39051 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39052 | const details::operator_type& operation, 39053 | expression_node_ptr (&branch)[2]) 39054 | { 39055 | // v0 o0 (v1 o1 (c o2 v2)) 39056 | typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t; 39057 | 39058 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]); 39059 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39060 | const Type& v1 = vocov->t0(); 39061 | const Type c = vocov->t1(); 39062 | const Type& v2 = vocov->t2(); 39063 | const details::operator_type o0 = operation; 39064 | const details::operator_type o1 = expr_gen.get_operator(vocov->f0()); 39065 | const details::operator_type o2 = expr_gen.get_operator(vocov->f1()); 39066 | 39067 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39068 | binary_functor_t f1 = vocov->f0(); 39069 | binary_functor_t f2 = vocov->f1(); 39070 | 39071 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39072 | 39073 | expression_node_ptr result = error_node(); 39074 | 39075 | const bool synthesis_result = 39076 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39077 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result); 39078 | 39079 | if (synthesis_result) 39080 | return result; 39081 | if (!expr_gen.valid_operator(o0,f0)) 39082 | return error_node(); 39083 | 39084 | exprtk_debug(("v0 o0 (v1 o1 (c o2 v2))\n")); 39085 | 39086 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2); 39087 | } 39088 | 39089 | static inline std::string id(expression_generator<Type>& expr_gen, 39090 | const details::operator_type o0, 39091 | const details::operator_type o1, 39092 | const details::operator_type o2) 39093 | { 39094 | return details::build_string() 39095 | << "t" << expr_gen.to_str(o0) 39096 | << "(t" << expr_gen.to_str(o1) 39097 | << "(t" << expr_gen.to_str(o2) 39098 | << "t))" 39099 | } 39100 | }; 39101 | 39102 | struct synthesize_vocovov_expression1 39103 | { 39104 | typedef typename vocovov_t::type1 node_type; 39105 | typedef typename vocovov_t::sf4_type sf4_type; 39106 | typedef typename node_type::T0 T0; 39107 | typedef typename node_type::T1 T1; 39108 | typedef typename node_type::T2 T2; 39109 | typedef typename node_type::T3 T3; 39110 | 39111 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39112 | const details::operator_type& operation, 39113 | expression_node_ptr (&branch)[2]) 39114 | { 39115 | // v0 o0 (c o1 (v1 o2 v2)) 39116 | typedef typename synthesize_covov_expression1::node_type lcl_covov_t; 39117 | 39118 | const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[1]); 39119 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39120 | const Type c = covov->t0(); 39121 | const Type& v1 = covov->t1(); 39122 | const Type& v2 = covov->t2(); 39123 | const details::operator_type o0 = operation; 39124 | const details::operator_type o1 = expr_gen.get_operator(covov->f0()); 39125 | const details::operator_type o2 = expr_gen.get_operator(covov->f1()); 39126 | 39127 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39128 | binary_functor_t f1 = covov->f0(); 39129 | binary_functor_t f2 = covov->f1(); 39130 | 39131 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39132 | 39133 | expression_node_ptr result = error_node(); 39134 | 39135 | const bool synthesis_result = 39136 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39137 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result); 39138 | 39139 | if (synthesis_result) 39140 | return result; 39141 | else if (!expr_gen.valid_operator(o0,f0)) 39142 | return error_node(); 39143 | 39144 | exprtk_debug(("v0 o0 (c o1 (v1 o2 v2))\n")); 39145 | 39146 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2); 39147 | } 39148 | 39149 | static inline std::string id(expression_generator<Type>& expr_gen, 39150 | const details::operator_type o0, 39151 | const details::operator_type o1, 39152 | const details::operator_type o2) 39153 | { 39154 | return details::build_string() 39155 | << "t" << expr_gen.to_str(o0) 39156 | << "(t" << expr_gen.to_str(o1) 39157 | << "(t" << expr_gen.to_str(o2) 39158 | << "t))" 39159 | } 39160 | }; 39161 | 39162 | struct synthesize_covovov_expression1 39163 | { 39164 | typedef typename covovov_t::type1 node_type; 39165 | typedef typename covovov_t::sf4_type sf4_type; 39166 | typedef typename node_type::T0 T0; 39167 | typedef typename node_type::T1 T1; 39168 | typedef typename node_type::T2 T2; 39169 | typedef typename node_type::T3 T3; 39170 | 39171 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39172 | const details::operator_type& operation, 39173 | expression_node_ptr (&branch)[2]) 39174 | { 39175 | // c o0 (v0 o1 (v1 o2 v2)) 39176 | typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t; 39177 | 39178 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]); 39179 | const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); 39180 | const Type& v0 = vovov->t0(); 39181 | const Type& v1 = vovov->t1(); 39182 | const Type& v2 = vovov->t2(); 39183 | const details::operator_type o0 = operation; 39184 | const details::operator_type o1 = expr_gen.get_operator(vovov->f0()); 39185 | const details::operator_type o2 = expr_gen.get_operator(vovov->f1()); 39186 | 39187 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39188 | binary_functor_t f1 = vovov->f0(); 39189 | binary_functor_t f2 = vovov->f1(); 39190 | 39191 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39192 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39193 | 39194 | expression_node_ptr result = error_node(); 39195 | 39196 | const bool synthesis_result = 39197 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39198 | (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result); 39199 | 39200 | if (synthesis_result) 39201 | return result; 39202 | if (!expr_gen.valid_operator(o0,f0)) 39203 | return error_node(); 39204 | 39205 | exprtk_debug(("c o0 (v0 o1 (v1 o2 v2))\n")); 39206 | 39207 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2); 39208 | } 39209 | 39210 | static inline std::string id(expression_generator<Type>& expr_gen, 39211 | const details::operator_type o0, 39212 | const details::operator_type o1, 39213 | const details::operator_type o2) 39214 | { 39215 | return details::build_string() 39216 | << "t" << expr_gen.to_str(o0) 39217 | << "(t" << expr_gen.to_str(o1) 39218 | << "(t" << expr_gen.to_str(o2) 39219 | << "t))" 39220 | } 39221 | }; 39222 | 39223 | struct synthesize_covocov_expression1 39224 | { 39225 | typedef typename covocov_t::type1 node_type; 39226 | typedef typename covocov_t::sf4_type sf4_type; 39227 | typedef typename node_type::T0 T0; 39228 | typedef typename node_type::T1 T1; 39229 | typedef typename node_type::T2 T2; 39230 | typedef typename node_type::T3 T3; 39231 | 39232 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39233 | const details::operator_type& operation, 39234 | expression_node_ptr (&branch)[2]) 39235 | { 39236 | // c0 o0 (v0 o1 (c1 o2 v1)) 39237 | typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t; 39238 | 39239 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]); 39240 | const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); 39241 | const Type& v0 = vocov->t0(); 39242 | const Type c1 = vocov->t1(); 39243 | const Type& v1 = vocov->t2(); 39244 | const details::operator_type o0 = operation; 39245 | const details::operator_type o1 = expr_gen.get_operator(vocov->f0()); 39246 | const details::operator_type o2 = expr_gen.get_operator(vocov->f1()); 39247 | 39248 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39249 | binary_functor_t f1 = vocov->f0(); 39250 | binary_functor_t f2 = vocov->f1(); 39251 | 39252 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39253 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39254 | 39255 | expression_node_ptr result = error_node(); 39256 | 39257 | const bool synthesis_result = 39258 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39259 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result); 39260 | 39261 | if (synthesis_result) 39262 | return result; 39263 | else if (!expr_gen.valid_operator(o0,f0)) 39264 | return error_node(); 39265 | 39266 | exprtk_debug(("c0 o0 (v0 o1 (c1 o2 v1))\n")); 39267 | 39268 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2); 39269 | } 39270 | 39271 | static inline std::string id(expression_generator<Type>& expr_gen, 39272 | const details::operator_type o0, 39273 | const details::operator_type o1, 39274 | const details::operator_type o2) 39275 | { 39276 | return details::build_string() 39277 | << "t" << expr_gen.to_str(o0) 39278 | << "(t" << expr_gen.to_str(o1) 39279 | << "(t" << expr_gen.to_str(o2) 39280 | << "t))" 39281 | } 39282 | }; 39283 | 39284 | struct synthesize_vocovoc_expression1 39285 | { 39286 | typedef typename vocovoc_t::type1 node_type; 39287 | typedef typename vocovoc_t::sf4_type sf4_type; 39288 | typedef typename node_type::T0 T0; 39289 | typedef typename node_type::T1 T1; 39290 | typedef typename node_type::T2 T2; 39291 | typedef typename node_type::T3 T3; 39292 | 39293 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39294 | const details::operator_type& operation, 39295 | expression_node_ptr (&branch)[2]) 39296 | { 39297 | // v0 o0 (c0 o1 (v1 o2 c2)) 39298 | typedef typename synthesize_covoc_expression1::node_type lcl_covoc_t; 39299 | 39300 | const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[1]); 39301 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39302 | const Type c0 = covoc->t0(); 39303 | const Type& v1 = covoc->t1(); 39304 | const Type c1 = covoc->t2(); 39305 | const details::operator_type o0 = operation; 39306 | const details::operator_type o1 = expr_gen.get_operator(covoc->f0()); 39307 | const details::operator_type o2 = expr_gen.get_operator(covoc->f1()); 39308 | 39309 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39310 | binary_functor_t f1 = covoc->f0(); 39311 | binary_functor_t f2 = covoc->f1(); 39312 | 39313 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39314 | 39315 | expression_node_ptr result = error_node(); 39316 | 39317 | const bool synthesis_result = 39318 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39319 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result); 39320 | 39321 | if (synthesis_result) 39322 | return result; 39323 | else if (!expr_gen.valid_operator(o0,f0)) 39324 | return error_node(); 39325 | 39326 | exprtk_debug(("v0 o0 (c0 o1 (v1 o2 c2))\n")); 39327 | 39328 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2); 39329 | } 39330 | 39331 | static inline std::string id(expression_generator<Type>& expr_gen, 39332 | const details::operator_type o0, 39333 | const details::operator_type o1, 39334 | const details::operator_type o2) 39335 | { 39336 | return details::build_string() 39337 | << "t" << expr_gen.to_str(o0) 39338 | << "(t" << expr_gen.to_str(o1) 39339 | << "(t" << expr_gen.to_str(o2) 39340 | << "t))" 39341 | } 39342 | }; 39343 | 39344 | struct synthesize_covovoc_expression1 39345 | { 39346 | typedef typename covovoc_t::type1 node_type; 39347 | typedef typename covovoc_t::sf4_type sf4_type; 39348 | typedef typename node_type::T0 T0; 39349 | typedef typename node_type::T1 T1; 39350 | typedef typename node_type::T2 T2; 39351 | typedef typename node_type::T3 T3; 39352 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39353 | const details::operator_type& operation, 39354 | expression_node_ptr (&branch)[2]) 39355 | { 39356 | // c0 o0 (v0 o1 (v1 o2 c1)) 39357 | typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t; 39358 | 39359 | const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]); 39360 | const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); 39361 | const Type& v0 = vovoc->t0(); 39362 | const Type& v1 = vovoc->t1(); 39363 | const Type c1 = vovoc->t2(); 39364 | const details::operator_type o0 = operation; 39365 | const details::operator_type o1 = expr_gen.get_operator(vovoc->f0()); 39366 | const details::operator_type o2 = expr_gen.get_operator(vovoc->f1()); 39367 | 39368 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39369 | binary_functor_t f1 = vovoc->f0(); 39370 | binary_functor_t f2 = vovoc->f1(); 39371 | 39372 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39373 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39374 | 39375 | expression_node_ptr result = error_node(); 39376 | 39377 | const bool synthesis_result = 39378 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39379 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result); 39380 | 39381 | if (synthesis_result) 39382 | return result; 39383 | else if (!expr_gen.valid_operator(o0,f0)) 39384 | return error_node(); 39385 | 39386 | exprtk_debug(("c0 o0 (v0 o1 (v1 o2 c1))\n")); 39387 | 39388 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2); 39389 | } 39390 | 39391 | static inline std::string id(expression_generator<Type>& expr_gen, 39392 | const details::operator_type o0, 39393 | const details::operator_type o1, 39394 | const details::operator_type o2) 39395 | { 39396 | return details::build_string() 39397 | << "t" << expr_gen.to_str(o0) 39398 | << "(t" << expr_gen.to_str(o1) 39399 | << "(t" << expr_gen.to_str(o2) 39400 | << "t))" 39401 | } 39402 | }; 39403 | 39404 | struct synthesize_vococov_expression1 39405 | { 39406 | typedef typename vococov_t::type1 node_type; 39407 | typedef typename vococov_t::sf4_type sf4_type; 39408 | typedef typename node_type::T0 T0; 39409 | typedef typename node_type::T1 T1; 39410 | typedef typename node_type::T2 T2; 39411 | typedef typename node_type::T3 T3; 39412 | 39413 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39414 | const details::operator_type& operation, 39415 | expression_node_ptr (&branch)[2]) 39416 | { 39417 | // v0 o0 (c0 o1 (c1 o2 v1)) 39418 | typedef typename synthesize_cocov_expression1::node_type lcl_cocov_t; 39419 | 39420 | const lcl_cocov_t* cocov = static_cast<const lcl_cocov_t*>(branch[1]); 39421 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39422 | const Type c0 = cocov->t0(); 39423 | const Type c1 = cocov->t1(); 39424 | const Type& v1 = cocov->t2(); 39425 | const details::operator_type o0 = operation; 39426 | const details::operator_type o1 = expr_gen.get_operator(cocov->f0()); 39427 | const details::operator_type o2 = expr_gen.get_operator(cocov->f1()); 39428 | 39429 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39430 | binary_functor_t f1 = cocov->f0(); 39431 | binary_functor_t f2 = cocov->f1(); 39432 | 39433 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39434 | 39435 | expression_node_ptr result = error_node(); 39436 | 39437 | const bool synthesis_result = 39438 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39439 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result); 39440 | 39441 | if (synthesis_result) 39442 | return result; 39443 | else if (!expr_gen.valid_operator(o0,f0)) 39444 | return error_node(); 39445 | 39446 | exprtk_debug(("v0 o0 (c0 o1 (c1 o2 v1))\n")); 39447 | 39448 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2); 39449 | } 39450 | 39451 | static inline std::string id(expression_generator<Type>& expr_gen, 39452 | const details::operator_type o0, 39453 | const details::operator_type o1, 39454 | const details::operator_type o2) 39455 | { 39456 | return details::build_string() 39457 | << "t" << expr_gen.to_str(o0) 39458 | << "(t" << expr_gen.to_str(o1) 39459 | << "(t" << expr_gen.to_str(o2) 39460 | << "t))" 39461 | } 39462 | }; 39463 | 39464 | struct synthesize_vovovov_expression2 39465 | { 39466 | typedef typename vovovov_t::type2 node_type; 39467 | typedef typename vovovov_t::sf4_type sf4_type; 39468 | typedef typename node_type::T0 T0; 39469 | typedef typename node_type::T1 T1; 39470 | typedef typename node_type::T2 T2; 39471 | typedef typename node_type::T3 T3; 39472 | 39473 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39474 | const details::operator_type& operation, 39475 | expression_node_ptr (&branch)[2]) 39476 | { 39477 | // v0 o0 ((v1 o1 v2) o2 v3) 39478 | typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t; 39479 | 39480 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]); 39481 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39482 | const Type& v1 = vovov->t0(); 39483 | const Type& v2 = vovov->t1(); 39484 | const Type& v3 = vovov->t2(); 39485 | const details::operator_type o0 = operation; 39486 | const details::operator_type o1 = expr_gen.get_operator(vovov->f0()); 39487 | const details::operator_type o2 = expr_gen.get_operator(vovov->f1()); 39488 | 39489 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39490 | binary_functor_t f1 = vovov->f0(); 39491 | binary_functor_t f2 = vovov->f1(); 39492 | 39493 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39494 | 39495 | expression_node_ptr result = error_node(); 39496 | 39497 | const bool synthesis_result = 39498 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39499 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result); 39500 | 39501 | if (synthesis_result) 39502 | return result; 39503 | else if (!expr_gen.valid_operator(o0,f0)) 39504 | return error_node(); 39505 | 39506 | exprtk_debug(("v0 o0 ((v1 o1 v2) o2 v3)\n")); 39507 | 39508 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2); 39509 | } 39510 | 39511 | static inline std::string id(expression_generator<Type>& expr_gen, 39512 | const details::operator_type o0, 39513 | const details::operator_type o1, 39514 | const details::operator_type o2) 39515 | { 39516 | return details::build_string() 39517 | << "t" << expr_gen.to_str(o0) 39518 | << "((t" << expr_gen.to_str(o1) 39519 | << "t)" << expr_gen.to_str(o2) 39520 | << "t)" 39521 | } 39522 | }; 39523 | 39524 | struct synthesize_vovovoc_expression2 39525 | { 39526 | typedef typename vovovoc_t::type2 node_type; 39527 | typedef typename vovovoc_t::sf4_type sf4_type; 39528 | typedef typename node_type::T0 T0; 39529 | typedef typename node_type::T1 T1; 39530 | typedef typename node_type::T2 T2; 39531 | typedef typename node_type::T3 T3; 39532 | 39533 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39534 | const details::operator_type& operation, 39535 | expression_node_ptr (&branch)[2]) 39536 | { 39537 | // v0 o0 ((v1 o1 v2) o2 c) 39538 | typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t; 39539 | 39540 | const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]); 39541 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39542 | const Type& v1 = vovoc->t0(); 39543 | const Type& v2 = vovoc->t1(); 39544 | const Type c = vovoc->t2(); 39545 | const details::operator_type o0 = operation; 39546 | const details::operator_type o1 = expr_gen.get_operator(vovoc->f0()); 39547 | const details::operator_type o2 = expr_gen.get_operator(vovoc->f1()); 39548 | 39549 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39550 | binary_functor_t f1 = vovoc->f0(); 39551 | binary_functor_t f2 = vovoc->f1(); 39552 | 39553 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39554 | 39555 | expression_node_ptr result = error_node(); 39556 | 39557 | const bool synthesis_result = 39558 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39559 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result); 39560 | 39561 | if (synthesis_result) 39562 | return result; 39563 | else if (!expr_gen.valid_operator(o0,f0)) 39564 | return error_node(); 39565 | 39566 | exprtk_debug(("v0 o0 ((v1 o1 v2) o2 c)\n")); 39567 | 39568 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2); 39569 | } 39570 | 39571 | static inline std::string id(expression_generator<Type>& expr_gen, 39572 | const details::operator_type o0, 39573 | const details::operator_type o1, 39574 | const details::operator_type o2) 39575 | { 39576 | return details::build_string() 39577 | << "t" << expr_gen.to_str(o0) 39578 | << "((t" << expr_gen.to_str(o1) 39579 | << "t)" << expr_gen.to_str(o2) 39580 | << "t)" 39581 | } 39582 | }; 39583 | 39584 | struct synthesize_vovocov_expression2 39585 | { 39586 | typedef typename vovocov_t::type2 node_type; 39587 | typedef typename vovocov_t::sf4_type sf4_type; 39588 | typedef typename node_type::T0 T0; 39589 | typedef typename node_type::T1 T1; 39590 | typedef typename node_type::T2 T2; 39591 | typedef typename node_type::T3 T3; 39592 | 39593 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39594 | const details::operator_type& operation, 39595 | expression_node_ptr (&branch)[2]) 39596 | { 39597 | // v0 o0 ((v1 o1 c) o2 v2) 39598 | typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t; 39599 | 39600 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]); 39601 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39602 | const Type& v1 = vocov->t0(); 39603 | const Type c = vocov->t1(); 39604 | const Type& v2 = vocov->t2(); 39605 | const details::operator_type o0 = operation; 39606 | const details::operator_type o1 = expr_gen.get_operator(vocov->f0()); 39607 | const details::operator_type o2 = expr_gen.get_operator(vocov->f1()); 39608 | 39609 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39610 | binary_functor_t f1 = vocov->f0(); 39611 | binary_functor_t f2 = vocov->f1(); 39612 | 39613 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39614 | 39615 | expression_node_ptr result = error_node(); 39616 | 39617 | const bool synthesis_result = 39618 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39619 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result); 39620 | 39621 | if (synthesis_result) 39622 | return result; 39623 | else if (!expr_gen.valid_operator(o0,f0)) 39624 | return error_node(); 39625 | 39626 | exprtk_debug(("v0 o0 ((v1 o1 c) o2 v2)\n")); 39627 | 39628 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2); 39629 | } 39630 | 39631 | static inline std::string id(expression_generator<Type>& expr_gen, 39632 | const details::operator_type o0, 39633 | const details::operator_type o1, 39634 | const details::operator_type o2) 39635 | { 39636 | return details::build_string() 39637 | << "t" << expr_gen.to_str(o0) 39638 | << "((t" << expr_gen.to_str(o1) 39639 | << "t)" << expr_gen.to_str(o2) 39640 | << "t)" 39641 | } 39642 | }; 39643 | 39644 | struct synthesize_vocovov_expression2 39645 | { 39646 | typedef typename vocovov_t::type2 node_type; 39647 | typedef typename vocovov_t::sf4_type sf4_type; 39648 | typedef typename node_type::T0 T0; 39649 | typedef typename node_type::T1 T1; 39650 | typedef typename node_type::T2 T2; 39651 | typedef typename node_type::T3 T3; 39652 | 39653 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39654 | const details::operator_type& operation, 39655 | expression_node_ptr (&branch)[2]) 39656 | { 39657 | // v0 o0 ((c o1 v1) o2 v2) 39658 | typedef typename synthesize_covov_expression0::node_type lcl_covov_t; 39659 | 39660 | const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[1]); 39661 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39662 | const Type c = covov->t0(); 39663 | const Type& v1 = covov->t1(); 39664 | const Type& v2 = covov->t2(); 39665 | const details::operator_type o0 = operation; 39666 | const details::operator_type o1 = expr_gen.get_operator(covov->f0()); 39667 | const details::operator_type o2 = expr_gen.get_operator(covov->f1()); 39668 | 39669 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39670 | binary_functor_t f1 = covov->f0(); 39671 | binary_functor_t f2 = covov->f1(); 39672 | 39673 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39674 | 39675 | expression_node_ptr result = error_node(); 39676 | 39677 | const bool synthesis_result = 39678 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39679 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result); 39680 | 39681 | if (synthesis_result) 39682 | return result; 39683 | else if (!expr_gen.valid_operator(o0,f0)) 39684 | return error_node(); 39685 | 39686 | exprtk_debug(("v0 o0 ((c o1 v1) o2 v2)\n")); 39687 | 39688 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2); 39689 | } 39690 | 39691 | static inline std::string id(expression_generator<Type>& expr_gen, 39692 | const details::operator_type o0, 39693 | const details::operator_type o1, 39694 | const details::operator_type o2) 39695 | { 39696 | return details::build_string() 39697 | << "t" << expr_gen.to_str(o0) 39698 | << "((t" << expr_gen.to_str(o1) 39699 | << "t)" << expr_gen.to_str(o2) 39700 | << "t)" 39701 | } 39702 | }; 39703 | 39704 | struct synthesize_covovov_expression2 39705 | { 39706 | typedef typename covovov_t::type2 node_type; 39707 | typedef typename covovov_t::sf4_type sf4_type; 39708 | typedef typename node_type::T0 T0; 39709 | typedef typename node_type::T1 T1; 39710 | typedef typename node_type::T2 T2; 39711 | typedef typename node_type::T3 T3; 39712 | 39713 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39714 | const details::operator_type& operation, 39715 | expression_node_ptr (&branch)[2]) 39716 | { 39717 | // c o0 ((v1 o1 v2) o2 v3) 39718 | typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t; 39719 | 39720 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]); 39721 | const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); 39722 | const Type& v0 = vovov->t0(); 39723 | const Type& v1 = vovov->t1(); 39724 | const Type& v2 = vovov->t2(); 39725 | const details::operator_type o0 = operation; 39726 | const details::operator_type o1 = expr_gen.get_operator(vovov->f0()); 39727 | const details::operator_type o2 = expr_gen.get_operator(vovov->f1()); 39728 | 39729 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39730 | binary_functor_t f1 = vovov->f0(); 39731 | binary_functor_t f2 = vovov->f1(); 39732 | 39733 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39734 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39735 | 39736 | expression_node_ptr result = error_node(); 39737 | 39738 | const bool synthesis_result = 39739 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39740 | (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result); 39741 | 39742 | if (synthesis_result) 39743 | return result; 39744 | else if (!expr_gen.valid_operator(o0,f0)) 39745 | return error_node(); 39746 | 39747 | exprtk_debug(("c o0 ((v1 o1 v2) o2 v3)\n")); 39748 | 39749 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2); 39750 | } 39751 | 39752 | static inline std::string id(expression_generator<Type>& expr_gen, 39753 | const details::operator_type o0, 39754 | const details::operator_type o1, 39755 | const details::operator_type o2) 39756 | { 39757 | return details::build_string() 39758 | << "t" << expr_gen.to_str(o0) 39759 | << "((t" << expr_gen.to_str(o1) 39760 | << "t)" << expr_gen.to_str(o2) 39761 | << "t)" 39762 | } 39763 | }; 39764 | 39765 | struct synthesize_covocov_expression2 39766 | { 39767 | typedef typename covocov_t::type2 node_type; 39768 | typedef typename covocov_t::sf4_type sf4_type; 39769 | typedef typename node_type::T0 T0; 39770 | typedef typename node_type::T1 T1; 39771 | typedef typename node_type::T2 T2; 39772 | typedef typename node_type::T3 T3; 39773 | 39774 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39775 | const details::operator_type& operation, 39776 | expression_node_ptr (&branch)[2]) 39777 | { 39778 | // c0 o0 ((v0 o1 c1) o2 v1) 39779 | typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t; 39780 | 39781 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]); 39782 | const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); 39783 | const Type& v0 = vocov->t0(); 39784 | const Type c1 = vocov->t1(); 39785 | const Type& v1 = vocov->t2(); 39786 | const details::operator_type o0 = operation; 39787 | const details::operator_type o1 = expr_gen.get_operator(vocov->f0()); 39788 | const details::operator_type o2 = expr_gen.get_operator(vocov->f1()); 39789 | 39790 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39791 | binary_functor_t f1 = vocov->f0(); 39792 | binary_functor_t f2 = vocov->f1(); 39793 | 39794 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39795 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39796 | 39797 | expression_node_ptr result = error_node(); 39798 | 39799 | const bool synthesis_result = 39800 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39801 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result); 39802 | 39803 | if (synthesis_result) 39804 | return result; 39805 | else if (!expr_gen.valid_operator(o0,f0)) 39806 | return error_node(); 39807 | 39808 | exprtk_debug(("c0 o0 ((v0 o1 c1) o2 v1)\n")); 39809 | 39810 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2); 39811 | } 39812 | 39813 | static inline std::string id(expression_generator<Type>& expr_gen, 39814 | const details::operator_type o0, 39815 | const details::operator_type o1, 39816 | const details::operator_type o2) 39817 | { 39818 | return details::build_string() 39819 | << "t" << expr_gen.to_str(o0) 39820 | << "((t" << expr_gen.to_str(o1) 39821 | << "t)" << expr_gen.to_str(o2) 39822 | << "t)" 39823 | } 39824 | }; 39825 | 39826 | struct synthesize_vocovoc_expression2 39827 | { 39828 | typedef typename vocovoc_t::type2 node_type; 39829 | typedef typename vocovoc_t::sf4_type sf4_type; 39830 | typedef typename node_type::T0 T0; 39831 | typedef typename node_type::T1 T1; 39832 | typedef typename node_type::T2 T2; 39833 | typedef typename node_type::T3 T3; 39834 | 39835 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39836 | const details::operator_type& operation, 39837 | expression_node_ptr (&branch)[2]) 39838 | { 39839 | // v0 o0 ((c0 o1 v1) o2 c1) 39840 | typedef typename synthesize_covoc_expression0::node_type lcl_covoc_t; 39841 | 39842 | const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[1]); 39843 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39844 | const Type c0 = covoc->t0(); 39845 | const Type& v1 = covoc->t1(); 39846 | const Type c1 = covoc->t2(); 39847 | const details::operator_type o0 = operation; 39848 | const details::operator_type o1 = expr_gen.get_operator(covoc->f0()); 39849 | const details::operator_type o2 = expr_gen.get_operator(covoc->f1()); 39850 | 39851 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39852 | binary_functor_t f1 = covoc->f0(); 39853 | binary_functor_t f2 = covoc->f1(); 39854 | 39855 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39856 | 39857 | expression_node_ptr result = error_node(); 39858 | 39859 | const bool synthesis_result = 39860 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39861 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result); 39862 | 39863 | if (synthesis_result) 39864 | return result; 39865 | else if (!expr_gen.valid_operator(o0,f0)) 39866 | return error_node(); 39867 | 39868 | exprtk_debug(("v0 o0 ((c0 o1 v1) o2 c1)\n")); 39869 | 39870 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2); 39871 | } 39872 | 39873 | static inline std::string id(expression_generator<Type>& expr_gen, 39874 | const details::operator_type o0, 39875 | const details::operator_type o1, 39876 | const details::operator_type o2) 39877 | { 39878 | return details::build_string() 39879 | << "t" << expr_gen.to_str(o0) 39880 | << "((t" << expr_gen.to_str(o1) 39881 | << "t)" << expr_gen.to_str(o2) 39882 | << "t)" 39883 | } 39884 | }; 39885 | 39886 | struct synthesize_covovoc_expression2 39887 | { 39888 | typedef typename covovoc_t::type2 node_type; 39889 | typedef typename covovoc_t::sf4_type sf4_type; 39890 | typedef typename node_type::T0 T0; 39891 | typedef typename node_type::T1 T1; 39892 | typedef typename node_type::T2 T2; 39893 | typedef typename node_type::T3 T3; 39894 | 39895 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39896 | const details::operator_type& operation, 39897 | expression_node_ptr (&branch)[2]) 39898 | { 39899 | // c0 o0 ((v0 o1 v1) o2 c1) 39900 | typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t; 39901 | 39902 | const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]); 39903 | const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); 39904 | const Type& v0 = vovoc->t0(); 39905 | const Type& v1 = vovoc->t1(); 39906 | const Type c1 = vovoc->t2(); 39907 | const details::operator_type o0 = operation; 39908 | const details::operator_type o1 = expr_gen.get_operator(vovoc->f0()); 39909 | const details::operator_type o2 = expr_gen.get_operator(vovoc->f1()); 39910 | 39911 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39912 | binary_functor_t f1 = vovoc->f0(); 39913 | binary_functor_t f2 = vovoc->f1(); 39914 | 39915 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39916 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39917 | 39918 | expression_node_ptr result = error_node(); 39919 | 39920 | const bool synthesis_result = 39921 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39922 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result); 39923 | 39924 | if (synthesis_result) 39925 | return result; 39926 | else if (!expr_gen.valid_operator(o0,f0)) 39927 | return error_node(); 39928 | 39929 | exprtk_debug(("c0 o0 ((v0 o1 v1) o2 c1)\n")); 39930 | 39931 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2); 39932 | } 39933 | 39934 | static inline std::string id(expression_generator<Type>& expr_gen, 39935 | const details::operator_type o0, 39936 | const details::operator_type o1, 39937 | const details::operator_type o2) 39938 | { 39939 | return details::build_string() 39940 | << "t" << expr_gen.to_str(o0) 39941 | << "((t" << expr_gen.to_str(o1) 39942 | << "t)" << expr_gen.to_str(o2) 39943 | << "t)" 39944 | } 39945 | }; 39946 | 39947 | struct synthesize_vococov_expression2 39948 | { 39949 | typedef typename vococov_t::type2 node_type; 39950 | static inline expression_node_ptr process(expression_generator<Type>&, 39951 | const details::operator_type&, 39952 | expression_node_ptr (&)[2]) 39953 | { 39954 | // v0 o0 ((c0 o1 c1) o2 v1) - Not possible 39955 | exprtk_debug(("v0 o0 ((c0 o1 c1) o2 v1) - Not possible\n")); 39956 | return error_node(); 39957 | } 39958 | 39959 | static inline std::string id(expression_generator<Type>&, 39960 | const details::operator_type, 39961 | const details::operator_type, 39962 | const details::operator_type) 39963 | { 39964 | return "INVALID" 39965 | } 39966 | }; 39967 | 39968 | struct synthesize_vovovov_expression3 39969 | { 39970 | typedef typename vovovov_t::type3 node_type; 39971 | typedef typename vovovov_t::sf4_type sf4_type; 39972 | typedef typename node_type::T0 T0; 39973 | typedef typename node_type::T1 T1; 39974 | typedef typename node_type::T2 T2; 39975 | typedef typename node_type::T3 T3; 39976 | 39977 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39978 | const details::operator_type& operation, 39979 | expression_node_ptr (&branch)[2]) 39980 | { 39981 | // ((v0 o0 v1) o1 v2) o2 v3 39982 | typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t; 39983 | 39984 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]); 39985 | const Type& v0 = vovov->t0(); 39986 | const Type& v1 = vovov->t1(); 39987 | const Type& v2 = vovov->t2(); 39988 | const Type& v3 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 39989 | const details::operator_type o0 = expr_gen.get_operator(vovov->f0()); 39990 | const details::operator_type o1 = expr_gen.get_operator(vovov->f1()); 39991 | const details::operator_type o2 = operation; 39992 | 39993 | binary_functor_t f0 = vovov->f0(); 39994 | binary_functor_t f1 = vovov->f1(); 39995 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 39996 | 39997 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39998 | 39999 | expression_node_ptr result = error_node(); 40000 | 40001 | const bool synthesis_result = 40002 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40003 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result); 40004 | 40005 | if (synthesis_result) 40006 | return result; 40007 | else if (!expr_gen.valid_operator(o2,f2)) 40008 | return error_node(); 40009 | 40010 | exprtk_debug(("((v0 o0 v1) o1 v2) o2 v3\n")); 40011 | 40012 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2); 40013 | } 40014 | 40015 | static inline std::string id(expression_generator<Type>& expr_gen, 40016 | const details::operator_type o0, 40017 | const details::operator_type o1, 40018 | const details::operator_type o2) 40019 | { 40020 | return details::build_string() 40021 | << "((t" << expr_gen.to_str(o0) 40022 | << "t)" << expr_gen.to_str(o1) 40023 | << "t)" << expr_gen.to_str(o2) 40024 | << "t" 40025 | } 40026 | }; 40027 | 40028 | struct synthesize_vovovoc_expression3 40029 | { 40030 | typedef typename vovovoc_t::type3 node_type; 40031 | typedef typename vovovoc_t::sf4_type sf4_type; 40032 | typedef typename node_type::T0 T0; 40033 | typedef typename node_type::T1 T1; 40034 | typedef typename node_type::T2 T2; 40035 | typedef typename node_type::T3 T3; 40036 | 40037 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40038 | const details::operator_type& operation, 40039 | expression_node_ptr (&branch)[2]) 40040 | { 40041 | // ((v0 o0 v1) o1 v2) o2 c 40042 | typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t; 40043 | 40044 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]); 40045 | const Type& v0 = vovov->t0(); 40046 | const Type& v1 = vovov->t1(); 40047 | const Type& v2 = vovov->t2(); 40048 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 40049 | const details::operator_type o0 = expr_gen.get_operator(vovov->f0()); 40050 | const details::operator_type o1 = expr_gen.get_operator(vovov->f1()); 40051 | const details::operator_type o2 = operation; 40052 | 40053 | binary_functor_t f0 = vovov->f0(); 40054 | binary_functor_t f1 = vovov->f1(); 40055 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40056 | 40057 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40058 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 40059 | 40060 | expression_node_ptr result = error_node(); 40061 | 40062 | const bool synthesis_result = 40063 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40064 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result); 40065 | 40066 | if (synthesis_result) 40067 | return result; 40068 | else if (!expr_gen.valid_operator(o2,f2)) 40069 | return error_node(); 40070 | 40071 | exprtk_debug(("((v0 o0 v1) o1 v2) o2 c\n")); 40072 | 40073 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2); 40074 | } 40075 | 40076 | static inline std::string id(expression_generator<Type>& expr_gen, 40077 | const details::operator_type o0, 40078 | const details::operator_type o1, 40079 | const details::operator_type o2) 40080 | { 40081 | return details::build_string() 40082 | << "((t" << expr_gen.to_str(o0) 40083 | << "t)" << expr_gen.to_str(o1) 40084 | << "t)" << expr_gen.to_str(o2) 40085 | << "t" 40086 | } 40087 | }; 40088 | 40089 | struct synthesize_vovocov_expression3 40090 | { 40091 | typedef typename vovocov_t::type3 node_type; 40092 | typedef typename vovocov_t::sf4_type sf4_type; 40093 | typedef typename node_type::T0 T0; 40094 | typedef typename node_type::T1 T1; 40095 | typedef typename node_type::T2 T2; 40096 | typedef typename node_type::T3 T3; 40097 | 40098 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40099 | const details::operator_type& operation, 40100 | expression_node_ptr (&branch)[2]) 40101 | { 40102 | // ((v0 o0 v1) o1 c) o2 v2 40103 | typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t; 40104 | 40105 | const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[0]); 40106 | const Type& v0 = vovoc->t0(); 40107 | const Type& v1 = vovoc->t1(); 40108 | const Type c = vovoc->t2(); 40109 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40110 | const details::operator_type o0 = expr_gen.get_operator(vovoc->f0()); 40111 | const details::operator_type o1 = expr_gen.get_operator(vovoc->f1()); 40112 | const details::operator_type o2 = operation; 40113 | 40114 | binary_functor_t f0 = vovoc->f0(); 40115 | binary_functor_t f1 = vovoc->f1(); 40116 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40117 | 40118 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40119 | 40120 | expression_node_ptr result = error_node(); 40121 | 40122 | const bool synthesis_result = 40123 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40124 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result); 40125 | 40126 | if (synthesis_result) 40127 | return result; 40128 | else if (!expr_gen.valid_operator(o2,f2)) 40129 | return error_node(); 40130 | 40131 | exprtk_debug(("((v0 o0 v1) o1 c) o2 v2\n")); 40132 | 40133 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2); 40134 | } 40135 | 40136 | static inline std::string id(expression_generator<Type>& expr_gen, 40137 | const details::operator_type o0, 40138 | const details::operator_type o1, 40139 | const details::operator_type o2) 40140 | { 40141 | return details::build_string() 40142 | << "((t" << expr_gen.to_str(o0) 40143 | << "t)" << expr_gen.to_str(o1) 40144 | << "t)" << expr_gen.to_str(o2) 40145 | << "t" 40146 | } 40147 | }; 40148 | 40149 | struct synthesize_vocovov_expression3 40150 | { 40151 | typedef typename vocovov_t::type3 node_type; 40152 | typedef typename vocovov_t::sf4_type sf4_type; 40153 | typedef typename node_type::T0 T0; 40154 | typedef typename node_type::T1 T1; 40155 | typedef typename node_type::T2 T2; 40156 | typedef typename node_type::T3 T3; 40157 | 40158 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40159 | const details::operator_type& operation, 40160 | expression_node_ptr (&branch)[2]) 40161 | { 40162 | // ((v0 o0 c) o1 v1) o2 v2 40163 | typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t; 40164 | 40165 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]); 40166 | const Type& v0 = vocov->t0(); 40167 | const Type c = vocov->t1(); 40168 | const Type& v1 = vocov->t2(); 40169 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40170 | const details::operator_type o0 = expr_gen.get_operator(vocov->f0()); 40171 | const details::operator_type o1 = expr_gen.get_operator(vocov->f1()); 40172 | const details::operator_type o2 = operation; 40173 | 40174 | binary_functor_t f0 = vocov->f0(); 40175 | binary_functor_t f1 = vocov->f1(); 40176 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40177 | 40178 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40179 | 40180 | expression_node_ptr result = error_node(); 40181 | 40182 | const bool synthesis_result = 40183 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40184 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result); 40185 | 40186 | if (synthesis_result) 40187 | return result; 40188 | else if (!expr_gen.valid_operator(o2,f2)) 40189 | return error_node(); 40190 | 40191 | exprtk_debug(("((v0 o0 c) o1 v1) o2 v2\n")); 40192 | 40193 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2); 40194 | } 40195 | 40196 | static inline std::string id(expression_generator<Type>& expr_gen, 40197 | const details::operator_type o0, 40198 | const details::operator_type o1, 40199 | const details::operator_type o2) 40200 | { 40201 | return details::build_string() 40202 | << "((t" << expr_gen.to_str(o0) 40203 | << "t)" << expr_gen.to_str(o1) 40204 | << "t)" << expr_gen.to_str(o2) 40205 | << "t" 40206 | } 40207 | }; 40208 | 40209 | struct synthesize_covovov_expression3 40210 | { 40211 | typedef typename covovov_t::type3 node_type; 40212 | typedef typename covovov_t::sf4_type sf4_type; 40213 | typedef typename node_type::T0 T0; 40214 | typedef typename node_type::T1 T1; 40215 | typedef typename node_type::T2 T2; 40216 | typedef typename node_type::T3 T3; 40217 | 40218 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40219 | const details::operator_type& operation, 40220 | expression_node_ptr (&branch)[2]) 40221 | { 40222 | // ((c o0 v0) o1 v1) o2 v2 40223 | typedef typename synthesize_covov_expression0::node_type lcl_covov_t; 40224 | 40225 | const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]); 40226 | const Type c = covov->t0(); 40227 | const Type& v0 = covov->t1(); 40228 | const Type& v1 = covov->t2(); 40229 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40230 | const details::operator_type o0 = expr_gen.get_operator(covov->f0()); 40231 | const details::operator_type o1 = expr_gen.get_operator(covov->f1()); 40232 | const details::operator_type o2 = operation; 40233 | 40234 | binary_functor_t f0 = covov->f0(); 40235 | binary_functor_t f1 = covov->f1(); 40236 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40237 | 40238 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40239 | 40240 | expression_node_ptr result = error_node(); 40241 | 40242 | const bool synthesis_result = 40243 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40244 | (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result); 40245 | 40246 | if (synthesis_result) 40247 | return result; 40248 | else if (!expr_gen.valid_operator(o2,f2)) 40249 | return error_node(); 40250 | 40251 | exprtk_debug(("((c o0 v0) o1 v1) o2 v2\n")); 40252 | 40253 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2); 40254 | } 40255 | 40256 | static inline std::string id(expression_generator<Type>& expr_gen, 40257 | const details::operator_type o0, 40258 | const details::operator_type o1, 40259 | const details::operator_type o2) 40260 | { 40261 | return details::build_string() 40262 | << "((t" << expr_gen.to_str(o0) 40263 | << "t)" << expr_gen.to_str(o1) 40264 | << "t)" << expr_gen.to_str(o2) 40265 | << "t" 40266 | } 40267 | }; 40268 | 40269 | struct synthesize_covocov_expression3 40270 | { 40271 | typedef typename covocov_t::type3 node_type; 40272 | typedef typename covocov_t::sf4_type sf4_type; 40273 | typedef typename node_type::T0 T0; 40274 | typedef typename node_type::T1 T1; 40275 | typedef typename node_type::T2 T2; 40276 | typedef typename node_type::T3 T3; 40277 | 40278 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40279 | const details::operator_type& operation, 40280 | expression_node_ptr (&branch)[2]) 40281 | { 40282 | // ((c0 o0 v0) o1 c1) o2 v1 40283 | typedef typename synthesize_covoc_expression0::node_type lcl_covoc_t; 40284 | 40285 | const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[0]); 40286 | const Type c0 = covoc->t0(); 40287 | const Type& v0 = covoc->t1(); 40288 | const Type c1 = covoc->t2(); 40289 | const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40290 | const details::operator_type o0 = expr_gen.get_operator(covoc->f0()); 40291 | const details::operator_type o1 = expr_gen.get_operator(covoc->f1()); 40292 | const details::operator_type o2 = operation; 40293 | 40294 | binary_functor_t f0 = covoc->f0(); 40295 | binary_functor_t f1 = covoc->f1(); 40296 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40297 | 40298 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40299 | 40300 | expression_node_ptr result = error_node(); 40301 | 40302 | const bool synthesis_result = 40303 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40304 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result); 40305 | 40306 | if (synthesis_result) 40307 | return result; 40308 | else if (!expr_gen.valid_operator(o2,f2)) 40309 | return error_node(); 40310 | 40311 | exprtk_debug(("((c0 o0 v0) o1 c1) o2 v1\n")); 40312 | 40313 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2); 40314 | } 40315 | 40316 | static inline std::string id(expression_generator<Type>& expr_gen, 40317 | const details::operator_type o0, 40318 | const details::operator_type o1, 40319 | const details::operator_type o2) 40320 | { 40321 | return details::build_string() 40322 | << "((t" << expr_gen.to_str(o0) 40323 | << "t)" << expr_gen.to_str(o1) 40324 | << "t)" << expr_gen.to_str(o2) 40325 | << "t" 40326 | } 40327 | }; 40328 | 40329 | struct synthesize_vocovoc_expression3 40330 | { 40331 | typedef typename vocovoc_t::type3 node_type; 40332 | typedef typename vocovoc_t::sf4_type sf4_type; 40333 | typedef typename node_type::T0 T0; 40334 | typedef typename node_type::T1 T1; 40335 | typedef typename node_type::T2 T2; 40336 | typedef typename node_type::T3 T3; 40337 | 40338 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40339 | const details::operator_type& operation, 40340 | expression_node_ptr (&branch)[2]) 40341 | { 40342 | // ((v0 o0 c0) o1 v1) o2 c1 40343 | typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t; 40344 | 40345 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]); 40346 | const Type& v0 = vocov->t0(); 40347 | const Type c0 = vocov->t1(); 40348 | const Type& v1 = vocov->t2(); 40349 | const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); 40350 | const details::operator_type o0 = expr_gen.get_operator(vocov->f0()); 40351 | const details::operator_type o1 = expr_gen.get_operator(vocov->f1()); 40352 | const details::operator_type o2 = operation; 40353 | 40354 | binary_functor_t f0 = vocov->f0(); 40355 | binary_functor_t f1 = vocov->f1(); 40356 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40357 | 40358 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40359 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 40360 | 40361 | expression_node_ptr result = error_node(); 40362 | 40363 | const bool synthesis_result = 40364 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40365 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result); 40366 | 40367 | if (synthesis_result) 40368 | return result; 40369 | else if (!expr_gen.valid_operator(o2,f2)) 40370 | return error_node(); 40371 | 40372 | exprtk_debug(("((v0 o0 c0) o1 v1) o2 c1\n")); 40373 | 40374 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2); 40375 | } 40376 | 40377 | static inline std::string id(expression_generator<Type>& expr_gen, 40378 | const details::operator_type o0, 40379 | const details::operator_type o1, 40380 | const details::operator_type o2) 40381 | { 40382 | return details::build_string() 40383 | << "((t" << expr_gen.to_str(o0) 40384 | << "t)" << expr_gen.to_str(o1) 40385 | << "t)" << expr_gen.to_str(o2) 40386 | << "t" 40387 | } 40388 | }; 40389 | 40390 | struct synthesize_covovoc_expression3 40391 | { 40392 | typedef typename covovoc_t::type3 node_type; 40393 | typedef typename covovoc_t::sf4_type sf4_type; 40394 | typedef typename node_type::T0 T0; 40395 | typedef typename node_type::T1 T1; 40396 | typedef typename node_type::T2 T2; 40397 | typedef typename node_type::T3 T3; 40398 | 40399 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40400 | const details::operator_type& operation, 40401 | expression_node_ptr (&branch)[2]) 40402 | { 40403 | // ((c0 o0 v0) o1 v1) o2 c1 40404 | typedef typename synthesize_covov_expression0::node_type lcl_covov_t; 40405 | 40406 | const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]); 40407 | const Type c0 = covov->t0(); 40408 | const Type& v0 = covov->t1(); 40409 | const Type& v1 = covov->t2(); 40410 | const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); 40411 | const details::operator_type o0 = expr_gen.get_operator(covov->f0()); 40412 | const details::operator_type o1 = expr_gen.get_operator(covov->f1()); 40413 | const details::operator_type o2 = operation; 40414 | 40415 | binary_functor_t f0 = covov->f0(); 40416 | binary_functor_t f1 = covov->f1(); 40417 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40418 | 40419 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40420 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 40421 | 40422 | expression_node_ptr result = error_node(); 40423 | 40424 | const bool synthesis_result = 40425 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40426 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result); 40427 | 40428 | if (synthesis_result) 40429 | return result; 40430 | else if (!expr_gen.valid_operator(o2,f2)) 40431 | return error_node(); 40432 | 40433 | exprtk_debug(("((c0 o0 v0) o1 v1) o2 c1\n")); 40434 | 40435 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2); 40436 | } 40437 | 40438 | static inline std::string id(expression_generator<Type>& expr_gen, 40439 | const details::operator_type o0, 40440 | const details::operator_type o1, 40441 | const details::operator_type o2) 40442 | { 40443 | return details::build_string() 40444 | << "((t" << expr_gen.to_str(o0) 40445 | << "t)" << expr_gen.to_str(o1) 40446 | << "t)" << expr_gen.to_str(o2) 40447 | << "t" 40448 | } 40449 | }; 40450 | 40451 | struct synthesize_vococov_expression3 40452 | { 40453 | typedef typename vococov_t::type3 node_type; 40454 | typedef typename vococov_t::sf4_type sf4_type; 40455 | typedef typename node_type::T0 T0; 40456 | typedef typename node_type::T1 T1; 40457 | typedef typename node_type::T2 T2; 40458 | typedef typename node_type::T3 T3; 40459 | 40460 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40461 | const details::operator_type& operation, 40462 | expression_node_ptr (&branch)[2]) 40463 | { 40464 | // ((v0 o0 c0) o1 c1) o2 v1 40465 | typedef typename synthesize_vococ_expression0::node_type lcl_vococ_t; 40466 | 40467 | const lcl_vococ_t* vococ = static_cast<const lcl_vococ_t*>(branch[0]); 40468 | const Type& v0 = vococ->t0(); 40469 | const Type c0 = vococ->t1(); 40470 | const Type c1 = vococ->t2(); 40471 | const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40472 | const details::operator_type o0 = expr_gen.get_operator(vococ->f0()); 40473 | const details::operator_type o1 = expr_gen.get_operator(vococ->f1()); 40474 | const details::operator_type o2 = operation; 40475 | 40476 | binary_functor_t f0 = vococ->f0(); 40477 | binary_functor_t f1 = vococ->f1(); 40478 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40479 | 40480 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40481 | 40482 | expression_node_ptr result = error_node(); 40483 | 40484 | const bool synthesis_result = 40485 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40486 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result); 40487 | 40488 | if (synthesis_result) 40489 | return result; 40490 | else if (!expr_gen.valid_operator(o2,f2)) 40491 | return error_node(); 40492 | 40493 | exprtk_debug(("((v0 o0 c0) o1 c1) o2 v1\n")); 40494 | 40495 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2); 40496 | } 40497 | 40498 | static inline std::string id(expression_generator<Type>& expr_gen, 40499 | const details::operator_type o0, 40500 | const details::operator_type o1, 40501 | const details::operator_type o2) 40502 | { 40503 | return details::build_string() 40504 | << "((t" << expr_gen.to_str(o0) 40505 | << "t)" << expr_gen.to_str(o1) 40506 | << "t)" << expr_gen.to_str(o2) 40507 | << "t" 40508 | } 40509 | }; 40510 | 40511 | struct synthesize_vovovov_expression4 40512 | { 40513 | typedef typename vovovov_t::type4 node_type; 40514 | typedef typename vovovov_t::sf4_type sf4_type; 40515 | typedef typename node_type::T0 T0; 40516 | typedef typename node_type::T1 T1; 40517 | typedef typename node_type::T2 T2; 40518 | typedef typename node_type::T3 T3; 40519 | 40520 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40521 | const details::operator_type& operation, 40522 | expression_node_ptr (&branch)[2]) 40523 | { 40524 | // (v0 o0 (v1 o1 v2)) o2 v3 40525 | typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t; 40526 | 40527 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]); 40528 | const Type& v0 = vovov->t0(); 40529 | const Type& v1 = vovov->t1(); 40530 | const Type& v2 = vovov->t2(); 40531 | const Type& v3 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40532 | const details::operator_type o0 = expr_gen.get_operator(vovov->f0()); 40533 | const details::operator_type o1 = expr_gen.get_operator(vovov->f1()); 40534 | const details::operator_type o2 = operation; 40535 | 40536 | binary_functor_t f0 = vovov->f0(); 40537 | binary_functor_t f1 = vovov->f1(); 40538 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40539 | 40540 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40541 | 40542 | expression_node_ptr result = error_node(); 40543 | 40544 | const bool synthesis_result = 40545 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40546 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result); 40547 | 40548 | if (synthesis_result) 40549 | return result; 40550 | else if (!expr_gen.valid_operator(o2,f2)) 40551 | return error_node(); 40552 | 40553 | exprtk_debug(("(v0 o0 (v1 o1 v2)) o2 v3\n")); 40554 | 40555 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2); 40556 | } 40557 | 40558 | static inline std::string id(expression_generator<Type>& expr_gen, 40559 | const details::operator_type o0, 40560 | const details::operator_type o1, 40561 | const details::operator_type o2) 40562 | { 40563 | return details::build_string() 40564 | << "(t" << expr_gen.to_str(o0) 40565 | << "(t" << expr_gen.to_str(o1) 40566 | << "t)" << expr_gen.to_str(o2) 40567 | << "t" 40568 | } 40569 | }; 40570 | 40571 | struct synthesize_vovovoc_expression4 40572 | { 40573 | typedef typename vovovoc_t::type4 node_type; 40574 | typedef typename vovovoc_t::sf4_type sf4_type; 40575 | typedef typename node_type::T0 T0; 40576 | typedef typename node_type::T1 T1; 40577 | typedef typename node_type::T2 T2; 40578 | typedef typename node_type::T3 T3; 40579 | 40580 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40581 | const details::operator_type& operation, 40582 | expression_node_ptr (&branch)[2]) 40583 | { 40584 | // ((v0 o0 (v1 o1 v2)) o2 c) 40585 | typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t; 40586 | 40587 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]); 40588 | const Type& v0 = vovov->t0(); 40589 | const Type& v1 = vovov->t1(); 40590 | const Type& v2 = vovov->t2(); 40591 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 40592 | const details::operator_type o0 = expr_gen.get_operator(vovov->f0()); 40593 | const details::operator_type o1 = expr_gen.get_operator(vovov->f1()); 40594 | const details::operator_type o2 = operation; 40595 | 40596 | binary_functor_t f0 = vovov->f0(); 40597 | binary_functor_t f1 = vovov->f1(); 40598 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40599 | 40600 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40601 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 40602 | 40603 | expression_node_ptr result = error_node(); 40604 | 40605 | const bool synthesis_result = 40606 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40607 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result); 40608 | 40609 | if (synthesis_result) 40610 | return result; 40611 | else if (!expr_gen.valid_operator(o2,f2)) 40612 | return error_node(); 40613 | 40614 | exprtk_debug(("((v0 o0 (v1 o1 v2)) o2 c)\n")); 40615 | 40616 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2); 40617 | } 40618 | 40619 | static inline std::string id(expression_generator<Type>& expr_gen, 40620 | const details::operator_type o0, 40621 | const details::operator_type o1, 40622 | const details::operator_type o2) 40623 | { 40624 | return details::build_string() 40625 | << "(t" << expr_gen.to_str(o0) 40626 | << "(t" << expr_gen.to_str(o1) 40627 | << "t)" << expr_gen.to_str(o2) 40628 | << "t" 40629 | } 40630 | }; 40631 | 40632 | struct synthesize_vovocov_expression4 40633 | { 40634 | typedef typename vovocov_t::type4 node_type; 40635 | typedef typename vovocov_t::sf4_type sf4_type; 40636 | typedef typename node_type::T0 T0; 40637 | typedef typename node_type::T1 T1; 40638 | typedef typename node_type::T2 T2; 40639 | typedef typename node_type::T3 T3; 40640 | 40641 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40642 | const details::operator_type& operation, 40643 | expression_node_ptr (&branch)[2]) 40644 | { 40645 | // ((v0 o0 (v1 o1 c)) o2 v1) 40646 | typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t; 40647 | 40648 | const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[0]); 40649 | const Type& v0 = vovoc->t0(); 40650 | const Type& v1 = vovoc->t1(); 40651 | const Type c = vovoc->t2(); 40652 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40653 | const details::operator_type o0 = expr_gen.get_operator(vovoc->f0()); 40654 | const details::operator_type o1 = expr_gen.get_operator(vovoc->f1()); 40655 | const details::operator_type o2 = operation; 40656 | 40657 | binary_functor_t f0 = vovoc->f0(); 40658 | binary_functor_t f1 = vovoc->f1(); 40659 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40660 | 40661 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40662 | 40663 | expression_node_ptr result = error_node(); 40664 | 40665 | const bool synthesis_result = 40666 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40667 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result); 40668 | 40669 | if (synthesis_result) 40670 | return result; 40671 | else if (!expr_gen.valid_operator(o2,f2)) 40672 | return error_node(); 40673 | 40674 | exprtk_debug(("((v0 o0 (v1 o1 c)) o2 v1)\n")); 40675 | 40676 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2); 40677 | } 40678 | 40679 | static inline std::string id(expression_generator<Type>& expr_gen, 40680 | const details::operator_type o0, 40681 | const details::operator_type o1, 40682 | const details::operator_type o2) 40683 | { 40684 | return details::build_string() 40685 | << "(t" << expr_gen.to_str(o0) 40686 | << "(t" << expr_gen.to_str(o1) 40687 | << "t)" << expr_gen.to_str(o2) 40688 | << "t" 40689 | } 40690 | }; 40691 | 40692 | struct synthesize_vocovov_expression4 40693 | { 40694 | typedef typename vocovov_t::type4 node_type; 40695 | typedef typename vocovov_t::sf4_type sf4_type; 40696 | typedef typename node_type::T0 T0; 40697 | typedef typename node_type::T1 T1; 40698 | typedef typename node_type::T2 T2; 40699 | typedef typename node_type::T3 T3; 40700 | 40701 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40702 | const details::operator_type& operation, 40703 | expression_node_ptr (&branch)[2]) 40704 | { 40705 | // ((v0 o0 (c o1 v1)) o2 v2) 40706 | typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t; 40707 | 40708 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]); 40709 | const Type& v0 = vocov->t0(); 40710 | const Type c = vocov->t1(); 40711 | const Type& v1 = vocov->t2(); 40712 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40713 | const details::operator_type o0 = expr_gen.get_operator(vocov->f0()); 40714 | const details::operator_type o1 = expr_gen.get_operator(vocov->f1()); 40715 | const details::operator_type o2 = operation; 40716 | 40717 | binary_functor_t f0 = vocov->f0(); 40718 | binary_functor_t f1 = vocov->f1(); 40719 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40720 | 40721 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40722 | expression_node_ptr result = error_node(); 40723 | 40724 | const bool synthesis_result = 40725 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40726 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result); 40727 | 40728 | if (synthesis_result) 40729 | return result; 40730 | else if (!expr_gen.valid_operator(o2,f2)) 40731 | return error_node(); 40732 | 40733 | exprtk_debug(("((v0 o0 (c o1 v1)) o2 v2)\n")); 40734 | 40735 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2); 40736 | } 40737 | 40738 | static inline std::string id(expression_generator<Type>& expr_gen, 40739 | const details::operator_type o0, 40740 | const details::operator_type o1, 40741 | const details::operator_type o2) 40742 | { 40743 | return details::build_string() 40744 | << "(t" << expr_gen.to_str(o0) 40745 | << "(t" << expr_gen.to_str(o1) 40746 | << "t)" << expr_gen.to_str(o2) 40747 | << "t" 40748 | } 40749 | }; 40750 | 40751 | struct synthesize_covovov_expression4 40752 | { 40753 | typedef typename covovov_t::type4 node_type; 40754 | typedef typename covovov_t::sf4_type sf4_type; 40755 | typedef typename node_type::T0 T0; 40756 | typedef typename node_type::T1 T1; 40757 | typedef typename node_type::T2 T2; 40758 | typedef typename node_type::T3 T3; 40759 | 40760 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40761 | const details::operator_type& operation, 40762 | expression_node_ptr (&branch)[2]) 40763 | { 40764 | // ((c o0 (v0 o1 v1)) o2 v2) 40765 | typedef typename synthesize_covov_expression1::node_type lcl_covov_t; 40766 | 40767 | const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]); 40768 | const Type c = covov->t0(); 40769 | const Type& v0 = covov->t1(); 40770 | const Type& v1 = covov->t2(); 40771 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40772 | const details::operator_type o0 = expr_gen.get_operator(covov->f0()); 40773 | const details::operator_type o1 = expr_gen.get_operator(covov->f1()); 40774 | const details::operator_type o2 = operation; 40775 | 40776 | binary_functor_t f0 = covov->f0(); 40777 | binary_functor_t f1 = covov->f1(); 40778 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40779 | 40780 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40781 | 40782 | expression_node_ptr result = error_node(); 40783 | 40784 | const bool synthesis_result = 40785 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40786 | (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result); 40787 | 40788 | if (synthesis_result) 40789 | return result; 40790 | else if (!expr_gen.valid_operator(o2,f2)) 40791 | return error_node(); 40792 | 40793 | exprtk_debug(("((c o0 (v0 o1 v1)) o2 v2)\n")); 40794 | 40795 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2); 40796 | } 40797 | 40798 | static inline std::string id(expression_generator<Type>& expr_gen, 40799 | const details::operator_type o0, 40800 | const details::operator_type o1, 40801 | const details::operator_type o2) 40802 | { 40803 | return details::build_string() 40804 | << "(t" << expr_gen.to_str(o0) 40805 | << "(t" << expr_gen.to_str(o1) 40806 | << "t)" << expr_gen.to_str(o2) 40807 | << "t" 40808 | } 40809 | }; 40810 | 40811 | struct synthesize_covocov_expression4 40812 | { 40813 | typedef typename covocov_t::type4 node_type; 40814 | typedef typename covocov_t::sf4_type sf4_type; 40815 | typedef typename node_type::T0 T0; 40816 | typedef typename node_type::T1 T1; 40817 | typedef typename node_type::T2 T2; 40818 | typedef typename node_type::T3 T3; 40819 | 40820 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40821 | const details::operator_type& operation, 40822 | expression_node_ptr (&branch)[2]) 40823 | { 40824 | // ((c0 o0 (v0 o1 c1)) o2 v1) 40825 | typedef typename synthesize_covoc_expression1::node_type lcl_covoc_t; 40826 | 40827 | const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[0]); 40828 | const Type c0 = covoc->t0(); 40829 | const Type& v0 = covoc->t1(); 40830 | const Type c1 = covoc->t2(); 40831 | const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40832 | const details::operator_type o0 = expr_gen.get_operator(covoc->f0()); 40833 | const details::operator_type o1 = expr_gen.get_operator(covoc->f1()); 40834 | const details::operator_type o2 = operation; 40835 | 40836 | binary_functor_t f0 = covoc->f0(); 40837 | binary_functor_t f1 = covoc->f1(); 40838 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40839 | 40840 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40841 | 40842 | expression_node_ptr result = error_node(); 40843 | 40844 | const bool synthesis_result = 40845 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40846 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result); 40847 | 40848 | if (synthesis_result) 40849 | return result; 40850 | else if (!expr_gen.valid_operator(o2,f2)) 40851 | return error_node(); 40852 | 40853 | exprtk_debug(("((c0 o0 (v0 o1 c1)) o2 v1)\n")); 40854 | 40855 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2); 40856 | } 40857 | 40858 | static inline std::string id(expression_generator<Type>& expr_gen, 40859 | const details::operator_type o0, 40860 | const details::operator_type o1, 40861 | const details::operator_type o2) 40862 | { 40863 | return details::build_string() 40864 | << "(t" << expr_gen.to_str(o0) 40865 | << "(t" << expr_gen.to_str(o1) 40866 | << "t)" << expr_gen.to_str(o2) 40867 | << "t" 40868 | } 40869 | }; 40870 | 40871 | struct synthesize_vocovoc_expression4 40872 | { 40873 | typedef typename vocovoc_t::type4 node_type; 40874 | typedef typename vocovoc_t::sf4_type sf4_type; 40875 | typedef typename node_type::T0 T0; 40876 | typedef typename node_type::T1 T1; 40877 | typedef typename node_type::T2 T2; 40878 | typedef typename node_type::T3 T3; 40879 | 40880 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40881 | const details::operator_type& operation, 40882 | expression_node_ptr (&branch)[2]) 40883 | { 40884 | // ((v0 o0 (c0 o1 v1)) o2 c1) 40885 | typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t; 40886 | 40887 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]); 40888 | const Type& v0 = vocov->t0(); 40889 | const Type c0 = vocov->t1(); 40890 | const Type& v1 = vocov->t2(); 40891 | const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); 40892 | const details::operator_type o0 = expr_gen.get_operator(vocov->f0()); 40893 | const details::operator_type o1 = expr_gen.get_operator(vocov->f1()); 40894 | const details::operator_type o2 = operation; 40895 | 40896 | binary_functor_t f0 = vocov->f0(); 40897 | binary_functor_t f1 = vocov->f1(); 40898 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40899 | 40900 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40901 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 40902 | 40903 | expression_node_ptr result = error_node(); 40904 | 40905 | const bool synthesis_result = 40906 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40907 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result); 40908 | 40909 | if (synthesis_result) 40910 | return result; 40911 | else if (!expr_gen.valid_operator(o2,f2)) 40912 | return error_node(); 40913 | 40914 | exprtk_debug(("((v0 o0 (c0 o1 v1)) o2 c1)\n")); 40915 | 40916 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2); 40917 | } 40918 | 40919 | static inline std::string id(expression_generator<Type>& expr_gen, 40920 | const details::operator_type o0, 40921 | const details::operator_type o1, 40922 | const details::operator_type o2) 40923 | { 40924 | return details::build_string() 40925 | << "(t" << expr_gen.to_str(o0) 40926 | << "(t" << expr_gen.to_str(o1) 40927 | << "t)" << expr_gen.to_str(o2) 40928 | << "t" 40929 | } 40930 | }; 40931 | 40932 | struct synthesize_covovoc_expression4 40933 | { 40934 | typedef typename covovoc_t::type4 node_type; 40935 | typedef typename covovoc_t::sf4_type sf4_type; 40936 | typedef typename node_type::T0 T0; 40937 | typedef typename node_type::T1 T1; 40938 | typedef typename node_type::T2 T2; 40939 | typedef typename node_type::T3 T3; 40940 | 40941 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40942 | const details::operator_type& operation, 40943 | expression_node_ptr (&branch)[2]) 40944 | { 40945 | // ((c0 o0 (v0 o1 v1)) o2 c1) 40946 | typedef typename synthesize_covov_expression1::node_type lcl_covov_t; 40947 | 40948 | const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]); 40949 | const Type c0 = covov->t0(); 40950 | const Type& v0 = covov->t1(); 40951 | const Type& v1 = covov->t2(); 40952 | const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); 40953 | const details::operator_type o0 = expr_gen.get_operator(covov->f0()); 40954 | const details::operator_type o1 = expr_gen.get_operator(covov->f1()); 40955 | const details::operator_type o2 = operation; 40956 | 40957 | binary_functor_t f0 = covov->f0(); 40958 | binary_functor_t f1 = covov->f1(); 40959 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40960 | 40961 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40962 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 40963 | 40964 | expression_node_ptr result = error_node(); 40965 | 40966 | const bool synthesis_result = 40967 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40968 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result); 40969 | 40970 | if (synthesis_result) 40971 | return result; 40972 | else if (!expr_gen.valid_operator(o2,f2)) 40973 | return error_node(); 40974 | 40975 | exprtk_debug(("((c0 o0 (v0 o1 v1)) o2 c1)\n")); 40976 | 40977 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2); 40978 | } 40979 | 40980 | static inline std::string id(expression_generator<Type>& expr_gen, 40981 | const details::operator_type o0, 40982 | const details::operator_type o1, 40983 | const details::operator_type o2) 40984 | { 40985 | return details::build_string() 40986 | << "(t" << expr_gen.to_str(o0) 40987 | << "(t" << expr_gen.to_str(o1) 40988 | << "t)" << expr_gen.to_str(o2) 40989 | << "t" 40990 | } 40991 | }; 40992 | 40993 | struct synthesize_vococov_expression4 40994 | { 40995 | typedef typename vococov_t::type4 node_type; 40996 | static inline expression_node_ptr process(expression_generator<Type>&, 40997 | const details::operator_type&, 40998 | expression_node_ptr (&)[2]) 40999 | { 41000 | // ((v0 o0 (c0 o1 c1)) o2 v1) - Not possible 41001 | exprtk_debug(("((v0 o0 (c0 o1 c1)) o2 v1) - Not possible\n")); 41002 | return error_node(); 41003 | } 41004 | 41005 | static inline std::string id(expression_generator<Type>&, 41006 | const details::operator_type, 41007 | const details::operator_type, 41008 | const details::operator_type) 41009 | { 41010 | return "INVALID" 41011 | } 41012 | }; 41013 | #endif 41014 | 41015 | inline expression_node_ptr synthesize_uvouv_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2]) 41016 | { 41017 | // Definition: uv o uv 41018 | details::operator_type o0 = static_cast<details::uv_base_node<Type>*>(branch[0])->operation(); 41019 | details::operator_type o1 = static_cast<details::uv_base_node<Type>*>(branch[1])->operation(); 41020 | const Type& v0 = static_cast<details::uv_base_node<Type>*>(branch[0])->v(); 41021 | const Type& v1 = static_cast<details::uv_base_node<Type>*>(branch[1])->v(); 41022 | unary_functor_t u0 = reinterpret_cast<unary_functor_t> (0); 41023 | unary_functor_t u1 = reinterpret_cast<unary_functor_t> (0); 41024 | binary_functor_t f = reinterpret_cast<binary_functor_t>(0); 41025 | 41026 | if (!valid_operator(o0,u0)) 41027 | return error_node(); 41028 | else if (!valid_operator(o1,u1)) 41029 | return error_node(); 41030 | else if (!valid_operator(operation,f)) 41031 | return error_node(); 41032 | 41033 | expression_node_ptr result = error_node(); 41034 | 41035 | if ( 41036 | (details::e_neg == o0) && 41037 | (details::e_neg == o1) 41038 | ) 41039 | { 41040 | switch (operation) 41041 | { 41042 | // (-v0 + -v1) --> -(v0 + v1) 41043 | case details::e_add : result = (*this)(details::e_neg, 41044 | node_allocator_-> 41045 | allocate_rr<typename details:: 41046 | vov_node<Type,details::add_op<Type> > >(v0, v1)); 41047 | exprtk_debug(("(-v0 + -v1) --> -(v0 + v1)\n")); 41048 | break; 41049 | 41050 | // (-v0 - -v1) --> (v1 - v0) 41051 | case details::e_sub : result = node_allocator_-> 41052 | allocate_rr<typename details:: 41053 | vov_node<Type,details::sub_op<Type> > >(v1, v0); 41054 | exprtk_debug(("(-v0 - -v1) --> (v1 - v0)\n")); 41055 | break; 41056 | 41057 | // (-v0 * -v1) --> (v0 * v1) 41058 | case details::e_mul : result = node_allocator_-> 41059 | allocate_rr<typename details:: 41060 | vov_node<Type,details::mul_op<Type> > >(v0, v1); 41061 | exprtk_debug(("(-v0 * -v1) --> (v0 * v1)\n")); 41062 | break; 41063 | 41064 | // (-v0 / -v1) --> (v0 / v1) 41065 | case details::e_div : result = node_allocator_-> 41066 | allocate_rr<typename details:: 41067 | vov_node<Type,details::div_op<Type> > >(v0, v1); 41068 | exprtk_debug(("(-v0 / -v1) --> (v0 / v1)\n")); 41069 | break; 41070 | 41071 | default : break; 41072 | } 41073 | } 41074 | 41075 | if (0 == result) 41076 | { 41077 | result = node_allocator_-> 41078 | allocate_rrrrr<typename details::uvouv_node<Type> >(v0, v1, u0, u1, f); 41079 | } 41080 | 41081 | details::free_all_nodes(*node_allocator_,branch); 41082 | return result; 41083 | } 41084 | 41085 | #undef basic_opr_switch_statements 41086 | #undef extended_opr_switch_statements 41087 | #undef unary_opr_switch_statements 41088 | 41089 | #ifndef exprtk_disable_string_capabilities 41090 | 41091 | #define string_opr_switch_statements \ 41092 | case_stmt(details::e_lt , details::lt_op ) \ 41093 | case_stmt(details::e_lte , details::lte_op ) \ 41094 | case_stmt(details::e_gt , details::gt_op ) \ 41095 | case_stmt(details::e_gte , details::gte_op ) \ 41096 | case_stmt(details::e_eq , details::eq_op ) \ 41097 | case_stmt(details::e_ne , details::ne_op ) \ 41098 | case_stmt(details::e_in , details::in_op ) \ 41099 | case_stmt(details::e_like , details::like_op ) \ 41100 | case_stmt(details::e_ilike , details::ilike_op) \ 41101 | 41102 | template <typename T0, typename T1> 41103 | inline expression_node_ptr synthesize_str_xrox_expression_impl(const details::operator_type& opr, 41104 | T0 s0, T1 s1, 41105 | range_t rp0) 41106 | { 41107 | switch (opr) 41108 | { 41109 | #define case_stmt(op0, op1) \ 41110 | case op0 : return node_allocator_-> \ 41111 | allocate_ttt<typename details::str_xrox_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \ 41112 | (s0, s1, rp0); \ 41113 | 41114 | string_opr_switch_statements 41115 | #undef case_stmt 41116 | default : return error_node(); 41117 | } 41118 | } 41119 | 41120 | template <typename T0, typename T1> 41121 | inline expression_node_ptr synthesize_str_xoxr_expression_impl(const details::operator_type& opr, 41122 | T0 s0, T1 s1, 41123 | range_t rp1) 41124 | { 41125 | switch (opr) 41126 | { 41127 | #define case_stmt(op0, op1) \ 41128 | case op0 : return node_allocator_-> \ 41129 | allocate_ttt<typename details::str_xoxr_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \ 41130 | (s0, s1, rp1); \ 41131 | 41132 | string_opr_switch_statements 41133 | #undef case_stmt 41134 | default : return error_node(); 41135 | } 41136 | } 41137 | 41138 | template <typename T0, typename T1> 41139 | inline expression_node_ptr synthesize_str_xroxr_expression_impl(const details::operator_type& opr, 41140 | T0 s0, T1 s1, 41141 | range_t rp0, range_t rp1) 41142 | { 41143 | switch (opr) 41144 | { 41145 | #define case_stmt(op0, op1) \ 41146 | case op0 : return node_allocator_-> \ 41147 | allocate_tttt<typename details::str_xroxr_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \ 41148 | (s0, s1, rp0, rp1); \ 41149 | 41150 | string_opr_switch_statements 41151 | #undef case_stmt 41152 | default : return error_node(); 41153 | } 41154 | } 41155 | 41156 | template <typename T0, typename T1> 41157 | inline expression_node_ptr synthesize_sos_expression_impl(const details::operator_type& opr, T0 s0, T1 s1) 41158 | { 41159 | switch (opr) 41160 | { 41161 | #define case_stmt(op0, op1) \ 41162 | case op0 : return node_allocator_-> \ 41163 | allocate_tt<typename details::sos_node<Type,T0,T1,op1<Type> >,T0,T1>(s0, s1); \ 41164 | 41165 | string_opr_switch_statements 41166 | #undef case_stmt 41167 | default : return error_node(); 41168 | } 41169 | } 41170 | 41171 | inline expression_node_ptr synthesize_sos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41172 | { 41173 | std::string& s0 = static_cast<details::stringvar_node<Type>*>(branch[0])->ref(); 41174 | std::string& s1 = static_cast<details::stringvar_node<Type>*>(branch[1])->ref(); 41175 | 41176 | return synthesize_sos_expression_impl<std::string&,std::string&>(opr, s0, s1); 41177 | } 41178 | 41179 | inline expression_node_ptr synthesize_sros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41180 | { 41181 | std::string& s0 = static_cast<details::string_range_node<Type>*>(branch[0])->ref (); 41182 | std::string& s1 = static_cast<details::stringvar_node<Type>*> (branch[1])->ref (); 41183 | range_t rp0 = static_cast<details::string_range_node<Type>*>(branch[0])->range(); 41184 | 41185 | static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear(); 41186 | 41187 | details::free_node(*node_allocator_,branch[0]); 41188 | 41189 | return synthesize_str_xrox_expression_impl<std::string&,std::string&>(opr, s0, s1, rp0); 41190 | } 41191 | 41192 | inline expression_node_ptr synthesize_sosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41193 | { 41194 | std::string& s0 = static_cast<details::stringvar_node<Type>*> (branch[0])->ref (); 41195 | std::string& s1 = static_cast<details::string_range_node<Type>*>(branch[1])->ref (); 41196 | range_t rp1 = static_cast<details::string_range_node<Type>*>(branch[1])->range(); 41197 | 41198 | static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear(); 41199 | 41200 | details::free_node(*node_allocator_,branch[1]); 41201 | 41202 | return synthesize_str_xoxr_expression_impl<std::string&,std::string&>(opr, s0, s1, rp1); 41203 | } 41204 | 41205 | inline expression_node_ptr synthesize_socsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41206 | { 41207 | std::string& s0 = static_cast<details::stringvar_node<Type>*> (branch[0])->ref (); 41208 | std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str (); 41209 | range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range(); 41210 | 41211 | static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear(); 41212 | 41213 | details::free_node(*node_allocator_,branch[1]); 41214 | 41215 | return synthesize_str_xoxr_expression_impl<std::string&, const std::string>(opr, s0, s1, rp1); 41216 | } 41217 | 41218 | inline expression_node_ptr synthesize_srosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41219 | { 41220 | std::string& s0 = static_cast<details::string_range_node<Type>*>(branch[0])->ref (); 41221 | std::string& s1 = static_cast<details::string_range_node<Type>*>(branch[1])->ref (); 41222 | range_t rp0 = static_cast<details::string_range_node<Type>*>(branch[0])->range(); 41223 | range_t rp1 = static_cast<details::string_range_node<Type>*>(branch[1])->range(); 41224 | 41225 | static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear(); 41226 | static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear(); 41227 | 41228 | details::free_node(*node_allocator_,branch[0]); 41229 | details::free_node(*node_allocator_,branch[1]); 41230 | 41231 | return synthesize_str_xroxr_expression_impl<std::string&,std::string&>(opr, s0, s1, rp0, rp1); 41232 | } 41233 | 41234 | inline expression_node_ptr synthesize_socs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41235 | { 41236 | std::string& s0 = static_cast< details::stringvar_node<Type>*>(branch[0])->ref(); 41237 | std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str(); 41238 | 41239 | details::free_node(*node_allocator_,branch[1]); 41240 | 41241 | return synthesize_sos_expression_impl<std::string&, const std::string>(opr, s0, s1); 41242 | } 41243 | 41244 | inline expression_node_ptr synthesize_csos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41245 | { 41246 | std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str(); 41247 | std::string& s1 = static_cast<details::stringvar_node<Type>* >(branch[1])->ref(); 41248 | 41249 | details::free_node(*node_allocator_,branch[0]); 41250 | 41251 | return synthesize_sos_expression_impl<const std::string,std::string&>(opr, s0, s1); 41252 | } 41253 | 41254 | inline expression_node_ptr synthesize_csosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41255 | { 41256 | std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str (); 41257 | std::string& s1 = static_cast<details::string_range_node<Type>* >(branch[1])->ref (); 41258 | range_t rp1 = static_cast<details::string_range_node<Type>* >(branch[1])->range(); 41259 | 41260 | static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear(); 41261 | 41262 | details::free_node(*node_allocator_,branch[0]); 41263 | details::free_node(*node_allocator_,branch[1]); 41264 | 41265 | return synthesize_str_xoxr_expression_impl<const std::string,std::string&>(opr, s0, s1, rp1); 41266 | } 41267 | 41268 | inline expression_node_ptr synthesize_srocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41269 | { 41270 | std::string& s0 = static_cast<details::string_range_node<Type>* >(branch[0])->ref (); 41271 | std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str (); 41272 | range_t rp0 = static_cast<details::string_range_node<Type>* >(branch[0])->range(); 41273 | 41274 | static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear(); 41275 | 41276 | details::free_node(*node_allocator_,branch[0]); 41277 | details::free_node(*node_allocator_,branch[1]); 41278 | 41279 | return synthesize_str_xrox_expression_impl<std::string&, const std::string>(opr, s0, s1, rp0); 41280 | } 41281 | 41282 | inline expression_node_ptr synthesize_srocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41283 | { 41284 | std::string& s0 = static_cast<details::string_range_node<Type>* >(branch[0])->ref (); 41285 | std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str (); 41286 | range_t rp0 = static_cast<details::string_range_node<Type>* >(branch[0])->range(); 41287 | range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range(); 41288 | 41289 | static_cast<details::string_range_node<Type>*> (branch[0])->range_ref().clear(); 41290 | static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear(); 41291 | 41292 | details::free_node(*node_allocator_,branch[0]); 41293 | details::free_node(*node_allocator_,branch[1]); 41294 | 41295 | return synthesize_str_xroxr_expression_impl<std::string&, const std::string>(opr, s0, s1, rp0, rp1); 41296 | } 41297 | 41298 | inline expression_node_ptr synthesize_csocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41299 | { 41300 | const std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str(); 41301 | const std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str(); 41302 | 41303 | expression_node_ptr result = error_node(); 41304 | 41305 | if (details::e_add == opr) 41306 | result = node_allocator_->allocate_c<details::string_literal_node<Type> >(s0 + s1); 41307 | else if (details::e_in == opr) 41308 | result = node_allocator_->allocate_c<details::literal_node<Type> >(details::in_op <Type>::process(s0,s1)); 41309 | else if (details::e_like == opr) 41310 | result = node_allocator_->allocate_c<details::literal_node<Type> >(details::like_op <Type>::process(s0,s1)); 41311 | else if (details::e_ilike == opr) 41312 | result = node_allocator_->allocate_c<details::literal_node<Type> >(details::ilike_op<Type>::process(s0,s1)); 41313 | else 41314 | { 41315 | expression_node_ptr temp = synthesize_sos_expression_impl<const std::string, const std::string>(opr, s0, s1); 41316 | 41317 | const Type v = temp->value(); 41318 | 41319 | details::free_node(*node_allocator_,temp); 41320 | 41321 | result = node_allocator_->allocate<literal_node_t>(v); 41322 | } 41323 | 41324 | details::free_all_nodes(*node_allocator_,branch); 41325 | 41326 | return result; 41327 | } 41328 | 41329 | inline expression_node_ptr synthesize_csocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41330 | { 41331 | const std::string s0 = static_cast<details::string_literal_node<Type>* >(branch[0])->str (); 41332 | std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str (); 41333 | range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range(); 41334 | 41335 | static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear(); 41336 | 41337 | details::free_node(*node_allocator_,branch[0]); 41338 | details::free_node(*node_allocator_,branch[1]); 41339 | 41340 | return synthesize_str_xoxr_expression_impl<const std::string, const std::string>(opr, s0, s1, rp1); 41341 | } 41342 | 41343 | inline expression_node_ptr synthesize_csros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41344 | { 41345 | std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str (); 41346 | std::string& s1 = static_cast<details::stringvar_node<Type>* >(branch[1])->ref (); 41347 | range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range(); 41348 | 41349 | static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear(); 41350 | 41351 | details::free_node(*node_allocator_,branch[0]); 41352 | 41353 | return synthesize_str_xrox_expression_impl<const std::string,std::string&>(opr, s0, s1, rp0); 41354 | } 41355 | 41356 | inline expression_node_ptr synthesize_csrosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41357 | { 41358 | const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str (); 41359 | std::string& s1 = static_cast<details::string_range_node<Type>* >(branch[1])->ref (); 41360 | const range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range(); 41361 | const range_t rp1 = static_cast<details::string_range_node<Type>* >(branch[1])->range(); 41362 | 41363 | static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear(); 41364 | static_cast<details::string_range_node<Type>*> (branch[1])->range_ref().clear(); 41365 | 41366 | details::free_node(*node_allocator_,branch[0]); 41367 | details::free_node(*node_allocator_,branch[1]); 41368 | 41369 | return synthesize_str_xroxr_expression_impl<const std::string,std::string&>(opr, s0, s1, rp0, rp1); 41370 | } 41371 | 41372 | inline expression_node_ptr synthesize_csrocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41373 | { 41374 | const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str (); 41375 | const std::string s1 = static_cast<details::string_literal_node<Type>* >(branch[1])->str (); 41376 | const range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range(); 41377 | 41378 | static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear(); 41379 | 41380 | details::free_all_nodes(*node_allocator_,branch); 41381 | 41382 | return synthesize_str_xrox_expression_impl<const std::string,std::string>(opr, s0, s1, rp0); 41383 | } 41384 | 41385 | inline expression_node_ptr synthesize_csrocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41386 | { 41387 | const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str (); 41388 | const std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str (); 41389 | const range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range(); 41390 | const range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range(); 41391 | 41392 | static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear(); 41393 | static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear(); 41394 | 41395 | details::free_all_nodes(*node_allocator_,branch); 41396 | 41397 | return synthesize_str_xroxr_expression_impl<const std::string, const std::string>(opr, s0, s1, rp0, rp1); 41398 | } 41399 | 41400 | inline expression_node_ptr synthesize_strogen_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41401 | { 41402 | switch (opr) 41403 | { 41404 | #define case_stmt(op0, op1) \ 41405 | case op0 : return node_allocator_-> \ 41406 | allocate_ttt<typename details::str_sogens_node<Type,op1<Type> > > \ 41407 | (opr, branch[0], branch[1]); \ 41408 | 41409 | string_opr_switch_statements 41410 | #undef case_stmt 41411 | default : return error_node(); 41412 | } 41413 | } 41414 | 41415 | #undef string_opr_switch_statements 41416 | #endif 41417 | 41418 | #ifndef exprtk_disable_string_capabilities 41419 | inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41420 | { 41421 | if ((0 == branch[0]) || (0 == branch[1])) 41422 | { 41423 | details::free_all_nodes(*node_allocator_,branch); 41424 | 41425 | return error_node(); 41426 | } 41427 | 41428 | const bool b0_is_s = details::is_string_node (branch[0]); 41429 | const bool b0_is_cs = details::is_const_string_node (branch[0]); 41430 | const bool b0_is_sr = details::is_string_range_node (branch[0]); 41431 | const bool b0_is_csr = details::is_const_string_range_node(branch[0]); 41432 | 41433 | const bool b1_is_s = details::is_string_node (branch[1]); 41434 | const bool b1_is_cs = details::is_const_string_node (branch[1]); 41435 | const bool b1_is_sr = details::is_string_range_node (branch[1]); 41436 | const bool b1_is_csr = details::is_const_string_range_node(branch[1]); 41437 | 41438 | const bool b0_is_gen = details::is_string_assignment_node (branch[0]) || 41439 | details::is_genricstring_range_node(branch[0]) || 41440 | details::is_string_concat_node (branch[0]) || 41441 | details::is_string_function_node (branch[0]) || 41442 | details::is_string_condition_node (branch[0]) || 41443 | details::is_string_ccondition_node (branch[0]) || 41444 | details::is_string_vararg_node (branch[0]) ; 41445 | 41446 | const bool b1_is_gen = details::is_string_assignment_node (branch[1]) || 41447 | details::is_genricstring_range_node(branch[1]) || 41448 | details::is_string_concat_node (branch[1]) || 41449 | details::is_string_function_node (branch[1]) || 41450 | details::is_string_condition_node (branch[1]) || 41451 | details::is_string_ccondition_node (branch[1]) || 41452 | details::is_string_vararg_node (branch[1]) ; 41453 | 41454 | if (details::e_add == opr) 41455 | { 41456 | if (!b0_is_cs || !b1_is_cs) 41457 | { 41458 | return synthesize_expression<string_concat_node_t,2>(opr,branch); 41459 | } 41460 | } 41461 | 41462 | if (b0_is_gen || b1_is_gen) 41463 | { 41464 | return synthesize_strogen_expression(opr,branch); 41465 | } 41466 | else if (b0_is_s) 41467 | { 41468 | if (b1_is_s ) return synthesize_sos_expression (opr,branch); 41469 | else if (b1_is_cs ) return synthesize_socs_expression (opr,branch); 41470 | else if (b1_is_sr ) return synthesize_sosr_expression (opr,branch); 41471 | else if (b1_is_csr) return synthesize_socsr_expression (opr,branch); 41472 | } 41473 | else if (b0_is_cs) 41474 | { 41475 | if (b1_is_s ) return synthesize_csos_expression (opr,branch); 41476 | else if (b1_is_cs ) return synthesize_csocs_expression (opr,branch); 41477 | else if (b1_is_sr ) return synthesize_csosr_expression (opr,branch); 41478 | else if (b1_is_csr) return synthesize_csocsr_expression(opr,branch); 41479 | } 41480 | else if (b0_is_sr) 41481 | { 41482 | if (b1_is_s ) return synthesize_sros_expression (opr,branch); 41483 | else if (b1_is_sr ) return synthesize_srosr_expression (opr,branch); 41484 | else if (b1_is_cs ) return synthesize_srocs_expression (opr,branch); 41485 | else if (b1_is_csr) return synthesize_srocsr_expression(opr,branch); 41486 | } 41487 | else if (b0_is_csr) 41488 | { 41489 | if (b1_is_s ) return synthesize_csros_expression (opr,branch); 41490 | else if (b1_is_sr ) return synthesize_csrosr_expression (opr,branch); 41491 | else if (b1_is_cs ) return synthesize_csrocs_expression (opr,branch); 41492 | else if (b1_is_csr) return synthesize_csrocsr_expression(opr,branch); 41493 | } 41494 | 41495 | return error_node(); 41496 | } 41497 | #else 41498 | inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&branch)[2]) 41499 | { 41500 | details::free_all_nodes(*node_allocator_,branch); 41501 | return error_node(); 41502 | } 41503 | #endif 41504 | 41505 | #ifndef exprtk_disable_string_capabilities 41506 | inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[3]) 41507 | { 41508 | if (details::e_inrange != opr) 41509 | return error_node(); 41510 | else if ((0 == branch[0]) || (0 == branch[1]) || (0 == branch[2])) 41511 | { 41512 | details::free_all_nodes(*node_allocator_,branch); 41513 | 41514 | return error_node(); 41515 | } 41516 | else if ( 41517 | details::is_const_string_node(branch[0]) && 41518 | details::is_const_string_node(branch[1]) && 41519 | details::is_const_string_node(branch[2]) 41520 | ) 41521 | { 41522 | const std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str(); 41523 | const std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str(); 41524 | const std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str(); 41525 | 41526 | const Type v = (((s0 <= s1) && (s1 <= s2)) ? Type(1) : Type(0)); 41527 | 41528 | details::free_all_nodes(*node_allocator_,branch); 41529 | 41530 | return node_allocator_->allocate_c<details::literal_node<Type> >(v); 41531 | } 41532 | else if ( 41533 | details::is_string_node(branch[0]) && 41534 | details::is_string_node(branch[1]) && 41535 | details::is_string_node(branch[2]) 41536 | ) 41537 | { 41538 | std::string& s0 = static_cast<details::stringvar_node<Type>*>(branch[0])->ref(); 41539 | std::string& s1 = static_cast<details::stringvar_node<Type>*>(branch[1])->ref(); 41540 | std::string& s2 = static_cast<details::stringvar_node<Type>*>(branch[2])->ref(); 41541 | 41542 | typedef typename details::sosos_node<Type, std::string&, std::string&, std::string&, details::inrange_op<Type> > inrange_t; 41543 | 41544 | return node_allocator_->allocate_type<inrange_t, std::string&, std::string&, std::string&>(s0, s1, s2); 41545 | } 41546 | else if ( 41547 | details::is_const_string_node(branch[0]) && 41548 | details::is_string_node(branch[1]) && 41549 | details::is_const_string_node(branch[2]) 41550 | ) 41551 | { 41552 | std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str(); 41553 | std::string& s1 = static_cast<details::stringvar_node<Type>* >(branch[1])->ref(); 41554 | std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str(); 41555 | 41556 | typedef typename details::sosos_node<Type, std::string, std::string&, std::string, details::inrange_op<Type> > inrange_t; 41557 | 41558 | details::free_node(*node_allocator_,branch[0]); 41559 | details::free_node(*node_allocator_,branch[2]); 41560 | 41561 | return node_allocator_->allocate_type<inrange_t, std::string, std::string&, std::string>(s0, s1, s2); 41562 | } 41563 | else if ( 41564 | details::is_string_node(branch[0]) && 41565 | details::is_const_string_node(branch[1]) && 41566 | details::is_string_node(branch[2]) 41567 | ) 41568 | { 41569 | std::string& s0 = static_cast<details::stringvar_node<Type>* >(branch[0])->ref(); 41570 | std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str(); 41571 | std::string& s2 = static_cast<details::stringvar_node<Type>* >(branch[2])->ref(); 41572 | 41573 | typedef typename details::sosos_node<Type, std::string&, std::string, std::string&, details::inrange_op<Type> > inrange_t; 41574 | 41575 | details::free_node(*node_allocator_,branch[1]); 41576 | 41577 | return node_allocator_->allocate_type<inrange_t, std::string&, std::string, std::string&>(s0, s1, s2); 41578 | } 41579 | else if ( 41580 | details::is_string_node(branch[0]) && 41581 | details::is_string_node(branch[1]) && 41582 | details::is_const_string_node(branch[2]) 41583 | ) 41584 | { 41585 | std::string& s0 = static_cast<details::stringvar_node<Type>* >(branch[0])->ref(); 41586 | std::string& s1 = static_cast<details::stringvar_node<Type>* >(branch[1])->ref(); 41587 | std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str(); 41588 | 41589 | typedef typename details::sosos_node<Type, std::string&, std::string&, std::string, details::inrange_op<Type> > inrange_t; 41590 | 41591 | details::free_node(*node_allocator_,branch[2]); 41592 | 41593 | return node_allocator_->allocate_type<inrange_t, std::string&, std::string&, std::string>(s0, s1, s2); 41594 | } 41595 | else if ( 41596 | details::is_const_string_node(branch[0]) && 41597 | details:: is_string_node(branch[1]) && 41598 | details:: is_string_node(branch[2]) 41599 | ) 41600 | { 41601 | std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str(); 41602 | std::string& s1 = static_cast<details::stringvar_node<Type>* >(branch[1])->ref(); 41603 | std::string& s2 = static_cast<details::stringvar_node<Type>* >(branch[2])->ref(); 41604 | 41605 | typedef typename details::sosos_node<Type, std::string, std::string&, std::string&, details::inrange_op<Type> > inrange_t; 41606 | 41607 | details::free_node(*node_allocator_,branch[0]); 41608 | 41609 | return node_allocator_->allocate_type<inrange_t, std::string, std::string&, std::string&>(s0, s1, s2); 41610 | } 41611 | else 41612 | return error_node(); 41613 | } 41614 | #else 41615 | inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&branch)[3]) 41616 | { 41617 | details::free_all_nodes(*node_allocator_,branch); 41618 | return error_node(); 41619 | } 41620 | #endif 41621 | 41622 | inline expression_node_ptr synthesize_null_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2]) 41623 | { 41624 | /* 41625 | Note: The following are the type promotion rules 41626 | that relate to operations that include 'null': 41627 | 0. null ==/!= null --> true false 41628 | 1. null operation null --> null 41629 | 2. x ==/!= null --> true/false 41630 | 3. null ==/!= x --> true/false 41631 | 4. x operation null --> x 41632 | 5. null operation x --> x 41633 | */ 41634 | 41635 | typedef typename details::null_eq_node<T> nulleq_node_t; 41636 | 41637 | const bool b0_null = details::is_null_node(branch[0]); 41638 | const bool b1_null = details::is_null_node(branch[1]); 41639 | 41640 | if (b0_null && b1_null) 41641 | { 41642 | expression_node_ptr result = error_node(); 41643 | 41644 | if (details::e_eq == operation) 41645 | result = node_allocator_->allocate_c<literal_node_t>(T(1)); 41646 | else if (details::e_ne == operation) 41647 | result = node_allocator_->allocate_c<literal_node_t>(T(0)); 41648 | 41649 | if (result) 41650 | { 41651 | details::free_node(*node_allocator_,branch[0]); 41652 | details::free_node(*node_allocator_,branch[1]); 41653 | 41654 | return result; 41655 | } 41656 | 41657 | details::free_node(*node_allocator_,branch[1]); 41658 | 41659 | return branch[0]; 41660 | } 41661 | else if (details::e_eq == operation) 41662 | { 41663 | expression_node_ptr result = node_allocator_-> 41664 | allocate_rc<nulleq_node_t>(branch[b0_null ? 0 : 1],true); 41665 | 41666 | details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]); 41667 | 41668 | return result; 41669 | } 41670 | else if (details::e_ne == operation) 41671 | { 41672 | expression_node_ptr result = node_allocator_-> 41673 | allocate_rc<nulleq_node_t>(branch[b0_null ? 0 : 1],false); 41674 | 41675 | details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]); 41676 | 41677 | return result; 41678 | } 41679 | else if (b0_null) 41680 | { 41681 | details::free_node(*node_allocator_,branch[0]); 41682 | branch[0] = branch[1]; 41683 | branch[1] = error_node(); 41684 | } 41685 | else if (b1_null) 41686 | { 41687 | details::free_node(*node_allocator_,branch[1]); 41688 | branch[1] = error_node(); 41689 | } 41690 | 41691 | if ( 41692 | (details::e_add == operation) || (details::e_sub == operation) || 41693 | (details::e_mul == operation) || (details::e_div == operation) || 41694 | (details::e_mod == operation) || (details::e_pow == operation) 41695 | ) 41696 | { 41697 | return branch[0]; 41698 | } 41699 | 41700 | details::free_node(*node_allocator_, branch[0]); 41701 | 41702 | if ( 41703 | (details::e_lt == operation) || (details::e_lte == operation) || 41704 | (details::e_gt == operation) || (details::e_gte == operation) || 41705 | (details::e_and == operation) || (details::e_nand == operation) || 41706 | (details::e_or == operation) || (details::e_nor == operation) || 41707 | (details::e_xor == operation) || (details::e_xnor == operation) || 41708 | (details::e_in == operation) || (details::e_like == operation) || 41709 | (details::e_ilike == operation) 41710 | ) 41711 | { 41712 | return node_allocator_->allocate_c<literal_node_t>(T(0)); 41713 | } 41714 | 41715 | return node_allocator_->allocate<details::null_node<Type> >(); 41716 | } 41717 | 41718 | template <typename NodeType, std::size_t N> 41719 | inline expression_node_ptr synthesize_expression(const details::operator_type& operation, expression_node_ptr (&branch)[N]) 41720 | { 41721 | if ( 41722 | (details::e_in == operation) || 41723 | (details::e_like == operation) || 41724 | (details::e_ilike == operation) 41725 | ) 41726 | { 41727 | free_all_nodes(*node_allocator_,branch); 41728 | 41729 | return error_node(); 41730 | } 41731 | else if (!details::all_nodes_valid<N>(branch)) 41732 | { 41733 | free_all_nodes(*node_allocator_,branch); 41734 | 41735 | return error_node(); 41736 | } 41737 | else if ((details::e_default != operation)) 41738 | { 41739 | // Attempt simple constant folding optimisation. 41740 | expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(operation,branch); 41741 | 41742 | if (is_constant_foldable<N>(branch)) 41743 | { 41744 | const Type v = expression_point->value(); 41745 | details::free_node(*node_allocator_,expression_point); 41746 | 41747 | return node_allocator_->allocate<literal_node_t>(v); 41748 | } 41749 | 41750 | if (expression_point && expression_point->valid()) 41751 | { 41752 | return expression_point; 41753 | } 41754 | 41755 | parser_->set_error(parser_error::make_error( 41756 | parser_error::e_parser, 41757 | token_t(), 41758 | "ERR281 - Failed to synthesize node: NodeType", 41759 | exprtk_error_location)); 41760 | 41761 | details::free_node(*node_allocator_, expression_point); 41762 | } 41763 | 41764 | return error_node(); 41765 | } 41766 | 41767 | template <typename NodeType, std::size_t N> 41768 | inline expression_node_ptr synthesize_expression(F* f, expression_node_ptr (&branch)[N]) 41769 | { 41770 | if (!details::all_nodes_valid<N>(branch)) 41771 | { 41772 | free_all_nodes(*node_allocator_,branch); 41773 | 41774 | return error_node(); 41775 | } 41776 | 41777 | typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t; 41778 | 41779 | // Attempt simple constant folding optimisation. 41780 | 41781 | expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(f); 41782 | function_N_node_t* func_node_ptr = dynamic_cast<function_N_node_t*>(expression_point); 41783 | 41784 | if (0 == func_node_ptr) 41785 | { 41786 | free_all_nodes(*node_allocator_,branch); 41787 | 41788 | return error_node(); 41789 | } 41790 | else 41791 | func_node_ptr->init_branches(branch); 41792 | 41793 | if (is_constant_foldable<N>(branch) && !f->has_side_effects()) 41794 | { 41795 | Type v = expression_point->value(); 41796 | details::free_node(*node_allocator_,expression_point); 41797 | 41798 | return node_allocator_->allocate<literal_node_t>(v); 41799 | } 41800 | 41801 | parser_->state_.activate_side_effect("synthesize_expression(function<NT,N>)"); 41802 | 41803 | return expression_point; 41804 | } 41805 | 41806 | bool strength_reduction_enabled_; 41807 | details::node_allocator* node_allocator_; 41808 | synthesize_map_t synthesize_map_; 41809 | unary_op_map_t* unary_op_map_; 41810 | binary_op_map_t* binary_op_map_; 41811 | inv_binary_op_map_t* inv_binary_op_map_; 41812 | sf3_map_t* sf3_map_; 41813 | sf4_map_t* sf4_map_; 41814 | parser_t* parser_; 41815 | }; // class expression_generator 41816 | 41817 | inline void set_error(const parser_error::type& error_type) 41818 | { 41819 | error_list_.push_back(error_type); 41820 | } 41821 | 41822 | inline void remove_last_error() 41823 | { 41824 | if (!error_list_.empty()) 41825 | { 41826 | error_list_.pop_back(); 41827 | } 41828 | } 41829 | 41830 | inline void set_synthesis_error(const std::string& synthesis_error_message) 41831 | { 41832 | if (synthesis_error_.empty()) 41833 | { 41834 | synthesis_error_ = synthesis_error_message; 41835 | } 41836 | } 41837 | 41838 | inline void register_local_vars(expression<T>& e) 41839 | { 41840 | for (std::size_t i = 0; i < sem_.size(); ++i) 41841 | { 41842 | scope_element& se = sem_.get_element(i); 41843 | 41844 | exprtk_debug(("register_local_vars() - se[%s]\n", se.name.c_str())); 41845 | 41846 | if ( 41847 | (scope_element::e_variable == se.type) || 41848 | (scope_element::e_literal == se.type) || 41849 | (scope_element::e_vecelem == se.type) 41850 | ) 41851 | { 41852 | if (se.var_node) 41853 | { 41854 | e.register_local_var(se.var_node); 41855 | } 41856 | 41857 | if (se.data) 41858 | { 41859 | e.register_local_data(se.data, 1, 0); 41860 | } 41861 | } 41862 | else if (scope_element::e_vector == se.type) 41863 | { 41864 | if (se.vec_node) 41865 | { 41866 | e.register_local_var(se.vec_node); 41867 | } 41868 | 41869 | if (se.data) 41870 | { 41871 | e.register_local_data(se.data, se.size, 1); 41872 | } 41873 | } 41874 | #ifndef exprtk_disable_string_capabilities 41875 | else if (scope_element::e_string == se.type) 41876 | { 41877 | if (se.str_node) 41878 | { 41879 | e.register_local_var(se.str_node); 41880 | } 41881 | 41882 | if (se.data) 41883 | { 41884 | e.register_local_data(se.data, se.size, 2); 41885 | } 41886 | } 41887 | #endif 41888 | 41889 | se.var_node = 0; 41890 | se.vec_node = 0; 41891 | #ifndef exprtk_disable_string_capabilities 41892 | se.str_node = 0; 41893 | #endif 41894 | se.data = 0; 41895 | se.ref_count = 0; 41896 | se.active = false; 41897 | } 41898 | } 41899 | 41900 | inline void register_return_results(expression<T>& e) 41901 | { 41902 | e.register_return_results(results_context_); 41903 | results_context_ = 0; 41904 | } 41905 | 41906 | inline void load_unary_operations_map(unary_op_map_t& m) 41907 | { 41908 | #define register_unary_op(Op, UnaryFunctor) \ 41909 | m.insert(std::make_pair(Op,UnaryFunctor<T>::process)); \ 41910 | 41911 | register_unary_op(details::e_abs , details::abs_op ) 41912 | register_unary_op(details::e_acos , details::acos_op ) 41913 | register_unary_op(details::e_acosh , details::acosh_op) 41914 | register_unary_op(details::e_asin , details::asin_op ) 41915 | register_unary_op(details::e_asinh , details::asinh_op) 41916 | register_unary_op(details::e_atanh , details::atanh_op) 41917 | register_unary_op(details::e_ceil , details::ceil_op ) 41918 | register_unary_op(details::e_cos , details::cos_op ) 41919 | register_unary_op(details::e_cosh , details::cosh_op ) 41920 | register_unary_op(details::e_exp , details::exp_op ) 41921 | register_unary_op(details::e_expm1 , details::expm1_op) 41922 | register_unary_op(details::e_floor , details::floor_op) 41923 | register_unary_op(details::e_log , details::log_op ) 41924 | register_unary_op(details::e_log10 , details::log10_op) 41925 | register_unary_op(details::e_log2 , details::log2_op ) 41926 | register_unary_op(details::e_log1p , details::log1p_op) 41927 | register_unary_op(details::e_neg , details::neg_op ) 41928 | register_unary_op(details::e_pos , details::pos_op ) 41929 | register_unary_op(details::e_round , details::round_op) 41930 | register_unary_op(details::e_sin , details::sin_op ) 41931 | register_unary_op(details::e_sinc , details::sinc_op ) 41932 | register_unary_op(details::e_sinh , details::sinh_op ) 41933 | register_unary_op(details::e_sqrt , details::sqrt_op ) 41934 | register_unary_op(details::e_tan , details::tan_op ) 41935 | register_unary_op(details::e_tanh , details::tanh_op ) 41936 | register_unary_op(details::e_cot , details::cot_op ) 41937 | register_unary_op(details::e_sec , details::sec_op ) 41938 | register_unary_op(details::e_csc , details::csc_op ) 41939 | register_unary_op(details::e_r2d , details::r2d_op ) 41940 | register_unary_op(details::e_d2r , details::d2r_op ) 41941 | register_unary_op(details::e_d2g , details::d2g_op ) 41942 | register_unary_op(details::e_g2d , details::g2d_op ) 41943 | register_unary_op(details::e_notl , details::notl_op ) 41944 | register_unary_op(details::e_sgn , details::sgn_op ) 41945 | register_unary_op(details::e_erf , details::erf_op ) 41946 | register_unary_op(details::e_erfc , details::erfc_op ) 41947 | register_unary_op(details::e_ncdf , details::ncdf_op ) 41948 | register_unary_op(details::e_frac , details::frac_op ) 41949 | register_unary_op(details::e_trunc , details::trunc_op) 41950 | #undef register_unary_op 41951 | } 41952 | 41953 | inline void load_binary_operations_map(binary_op_map_t& m) 41954 | { 41955 | typedef typename binary_op_map_t::value_type value_type; 41956 | 41957 | #define register_binary_op(Op, BinaryFunctor) \ 41958 | m.insert(value_type(Op,BinaryFunctor<T>::process)); \ 41959 | 41960 | register_binary_op(details::e_add , details::add_op ) 41961 | register_binary_op(details::e_sub , details::sub_op ) 41962 | register_binary_op(details::e_mul , details::mul_op ) 41963 | register_binary_op(details::e_div , details::div_op ) 41964 | register_binary_op(details::e_mod , details::mod_op ) 41965 | register_binary_op(details::e_pow , details::pow_op ) 41966 | register_binary_op(details::e_lt , details::lt_op ) 41967 | register_binary_op(details::e_lte , details::lte_op ) 41968 | register_binary_op(details::e_gt , details::gt_op ) 41969 | register_binary_op(details::e_gte , details::gte_op ) 41970 | register_binary_op(details::e_eq , details::eq_op ) 41971 | register_binary_op(details::e_ne , details::ne_op ) 41972 | register_binary_op(details::e_and , details::and_op ) 41973 | register_binary_op(details::e_nand , details::nand_op) 41974 | register_binary_op(details::e_or , details::or_op ) 41975 | register_binary_op(details::e_nor , details::nor_op ) 41976 | register_binary_op(details::e_xor , details::xor_op ) 41977 | register_binary_op(details::e_xnor , details::xnor_op) 41978 | #undef register_binary_op 41979 | } 41980 | 41981 | inline void load_inv_binary_operations_map(inv_binary_op_map_t& m) 41982 | { 41983 | typedef typename inv_binary_op_map_t::value_type value_type; 41984 | 41985 | #define register_binary_op(Op, BinaryFunctor) \ 41986 | m.insert(value_type(BinaryFunctor<T>::process,Op)); \ 41987 | 41988 | register_binary_op(details::e_add , details::add_op ) 41989 | register_binary_op(details::e_sub , details::sub_op ) 41990 | register_binary_op(details::e_mul , details::mul_op ) 41991 | register_binary_op(details::e_div , details::div_op ) 41992 | register_binary_op(details::e_mod , details::mod_op ) 41993 | register_binary_op(details::e_pow , details::pow_op ) 41994 | register_binary_op(details::e_lt , details::lt_op ) 41995 | register_binary_op(details::e_lte , details::lte_op ) 41996 | register_binary_op(details::e_gt , details::gt_op ) 41997 | register_binary_op(details::e_gte , details::gte_op ) 41998 | register_binary_op(details::e_eq , details::eq_op ) 41999 | register_binary_op(details::e_ne , details::ne_op ) 42000 | register_binary_op(details::e_and , details::and_op ) 42001 | register_binary_op(details::e_nand , details::nand_op) 42002 | register_binary_op(details::e_or , details::or_op ) 42003 | register_binary_op(details::e_nor , details::nor_op ) 42004 | register_binary_op(details::e_xor , details::xor_op ) 42005 | register_binary_op(details::e_xnor , details::xnor_op) 42006 | #undef register_binary_op 42007 | } 42008 | 42009 | inline void load_sf3_map(sf3_map_t& sf3_map) 42010 | { 42011 | typedef std::pair<trinary_functor_t,details::operator_type> pair_t; 42012 | 42013 | #define register_sf3(Op) \ 42014 | sf3_map[details::sf##Op##_op<T>::id()] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \ 42015 | 42016 | register_sf3(00) register_sf3(01) register_sf3(02) register_sf3(03) 42017 | register_sf3(04) register_sf3(05) register_sf3(06) register_sf3(07) 42018 | register_sf3(08) register_sf3(09) register_sf3(10) register_sf3(11) 42019 | register_sf3(12) register_sf3(13) register_sf3(14) register_sf3(15) 42020 | register_sf3(16) register_sf3(17) register_sf3(18) register_sf3(19) 42021 | register_sf3(20) register_sf3(21) register_sf3(22) register_sf3(23) 42022 | register_sf3(24) register_sf3(25) register_sf3(26) register_sf3(27) 42023 | register_sf3(28) register_sf3(29) register_sf3(30) 42024 | #undef register_sf3 42025 | 42026 | #define register_sf3_extid(Id, Op) \ 42027 | sf3_map[Id] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \ 42028 | 42029 | register_sf3_extid("(t-t)-t",23) // (t-t)-t --> t-(t+t) 42030 | #undef register_sf3_extid 42031 | } 42032 | 42033 | inline void load_sf4_map(sf4_map_t& sf4_map) 42034 | { 42035 | typedef std::pair<quaternary_functor_t,details::operator_type> pair_t; 42036 | 42037 | #define register_sf4(Op) \ 42038 | sf4_map[details::sf##Op##_op<T>::id()] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \ 42039 | 42040 | register_sf4(48) register_sf4(49) register_sf4(50) register_sf4(51) 42041 | register_sf4(52) register_sf4(53) register_sf4(54) register_sf4(55) 42042 | register_sf4(56) register_sf4(57) register_sf4(58) register_sf4(59) 42043 | register_sf4(60) register_sf4(61) register_sf4(62) register_sf4(63) 42044 | register_sf4(64) register_sf4(65) register_sf4(66) register_sf4(67) 42045 | register_sf4(68) register_sf4(69) register_sf4(70) register_sf4(71) 42046 | register_sf4(72) register_sf4(73) register_sf4(74) register_sf4(75) 42047 | register_sf4(76) register_sf4(77) register_sf4(78) register_sf4(79) 42048 | register_sf4(80) register_sf4(81) register_sf4(82) register_sf4(83) 42049 | #undef register_sf4 42050 | 42051 | #define register_sf4ext(Op) \ 42052 | sf4_map[details::sfext##Op##_op<T>::id()] = pair_t(details::sfext##Op##_op<T>::process,details::e_sf4ext##Op); \ 42053 | 42054 | register_sf4ext(00) register_sf4ext(01) register_sf4ext(02) register_sf4ext(03) 42055 | register_sf4ext(04) register_sf4ext(05) register_sf4ext(06) register_sf4ext(07) 42056 | register_sf4ext(08) register_sf4ext(09) register_sf4ext(10) register_sf4ext(11) 42057 | register_sf4ext(12) register_sf4ext(13) register_sf4ext(14) register_sf4ext(15) 42058 | register_sf4ext(16) register_sf4ext(17) register_sf4ext(18) register_sf4ext(19) 42059 | register_sf4ext(20) register_sf4ext(21) register_sf4ext(22) register_sf4ext(23) 42060 | register_sf4ext(24) register_sf4ext(25) register_sf4ext(26) register_sf4ext(27) 42061 | register_sf4ext(28) register_sf4ext(29) register_sf4ext(30) register_sf4ext(31) 42062 | register_sf4ext(32) register_sf4ext(33) register_sf4ext(34) register_sf4ext(35) 42063 | register_sf4ext(36) register_sf4ext(36) register_sf4ext(38) register_sf4ext(39) 42064 | register_sf4ext(40) register_sf4ext(41) register_sf4ext(42) register_sf4ext(43) 42065 | register_sf4ext(44) register_sf4ext(45) register_sf4ext(46) register_sf4ext(47) 42066 | register_sf4ext(48) register_sf4ext(49) register_sf4ext(50) register_sf4ext(51) 42067 | register_sf4ext(52) register_sf4ext(53) register_sf4ext(54) register_sf4ext(55) 42068 | register_sf4ext(56) register_sf4ext(57) register_sf4ext(58) register_sf4ext(59) 42069 | register_sf4ext(60) register_sf4ext(61) 42070 | #undef register_sf4ext 42071 | } 42072 | 42073 | inline results_context_t& results_ctx() 42074 | { 42075 | if (0 == results_context_) 42076 | { 42077 | results_context_ = new results_context_t(); 42078 | } 42079 | 42080 | return (*results_context_); 42081 | } 42082 | 42083 | inline void return_cleanup() 42084 | { 42085 | #ifndef exprtk_disable_return_statement 42086 | if (results_context_) 42087 | { 42088 | delete results_context_; 42089 | results_context_ = 0; 42090 | } 42091 | 42092 | state_.return_stmt_present = false; 42093 | #endif 42094 | } 42095 | 42096 | inline bool valid_settings() 42097 | { 42098 | const std::size_t max_local_vector_size_bytes = sizeof(T) * settings_.max_local_vector_size(); 42099 | 42100 | if (max_local_vector_size_bytes > settings_.max_total_local_symbol_size_bytes()) 42101 | { 42102 | set_error(make_error( 42103 | parser_error::e_parser, 42104 | "ERR282 - Max local vector size of " + details::to_str(max_local_vector_size_bytes) + " bytes " 42105 | "is larger than max total local symbol size of " + details::to_str(settings_.max_total_local_symbol_size_bytes()) + " bytes", 42106 | exprtk_error_location)); 42107 | 42108 | return false; 42109 | } 42110 | 42111 | return true; 42112 | } 42113 | 42114 | private: 42115 | 42116 | parser(const parser<T>&) exprtk_delete; 42117 | parser<T>& operator=(const parser<T>&) exprtk_delete; 42118 | 42119 | settings_store settings_; 42120 | expression_generator<T> expression_generator_; 42121 | details::node_allocator node_allocator_; 42122 | symtab_store symtab_store_; 42123 | dependent_entity_collector dec_; 42124 | std::deque<parser_error::type> error_list_; 42125 | std::deque<bool> brkcnt_list_; 42126 | parser_state state_; 42127 | bool resolve_unknown_symbol_; 42128 | results_context_t* results_context_; 42129 | unknown_symbol_resolver* unknown_symbol_resolver_; 42130 | unknown_symbol_resolver default_usr_; 42131 | base_ops_map_t base_ops_map_; 42132 | unary_op_map_t unary_op_map_; 42133 | binary_op_map_t binary_op_map_; 42134 | inv_binary_op_map_t inv_binary_op_map_; 42135 | sf3_map_t sf3_map_; 42136 | sf4_map_t sf4_map_; 42137 | std::string synthesis_error_; 42138 | scope_element_manager sem_; 42139 | std::vector<state_t> current_state_stack_; 42140 | 42141 | immutable_memory_map_t immutable_memory_map_; 42142 | immutable_symtok_map_t immutable_symtok_map_; 42143 | 42144 | lexer::helper::helper_assembly helper_assembly_; 42145 | 42146 | lexer::helper::commutative_inserter commutative_inserter_; 42147 | lexer::helper::operator_joiner operator_joiner_2_; 42148 | lexer::helper::operator_joiner operator_joiner_3_; 42149 | lexer::helper::symbol_replacer symbol_replacer_; 42150 | lexer::helper::bracket_checker bracket_checker_; 42151 | lexer::helper::numeric_checker<T> numeric_checker_; 42152 | lexer::helper::sequence_validator sequence_validator_; 42153 | lexer::helper::sequence_validator_3tokens sequence_validator_3tkns_; 42154 | 42155 | loop_runtime_check_ptr loop_runtime_check_; 42156 | vector_access_runtime_check_ptr vector_access_runtime_check_; 42157 | compilation_check_ptr compilation_check_ptr_; 42158 | assert_check_ptr assert_check_; 42159 | std::set<std::string> assert_ids_; 42160 | 42161 | template <typename ParserType> 42162 | friend void details::disable_type_checking(ParserType& p); 42163 | }; // class parser 42164 | 42165 | namespace details 42166 | { 42167 | template <typename T> 42168 | struct collector_helper 42169 | { 42170 | typedef exprtk::symbol_table<T> symbol_table_t; 42171 | typedef exprtk::expression<T> expression_t; 42172 | typedef exprtk::parser<T> parser_t; 42173 | typedef typename parser_t::dependent_entity_collector::symbol_t symbol_t; 42174 | typedef typename parser_t::unknown_symbol_resolver usr_t; 42175 | 42176 | struct resolve_as_vector : public usr_t 42177 | { 42178 | typedef exprtk::parser<T> parser_t; 42179 | 42180 | using usr_t::process; 42181 | 42182 | resolve_as_vector() 42183 | : usr_t(usr_t::e_usrmode_extended) 42184 | {} 42185 | 42186 | virtual bool process(const std::string& unknown_symbol, 42187 | symbol_table_t& symbol_table, 42188 | std::string&) exprtk_override 42189 | { 42190 | static T v[1]; 42191 | symbol_table.add_vector(unknown_symbol,v); 42192 | return true; 42193 | } 42194 | }; 42195 | 42196 | static inline bool collection_pass(const std::string& expression_string, 42197 | std::set<std::string>& symbol_set, 42198 | const bool collect_variables, 42199 | const bool collect_functions, 42200 | const bool vector_pass, 42201 | symbol_table_t& ext_symbol_table) 42202 | { 42203 | symbol_table_t symbol_table; 42204 | expression_t expression; 42205 | parser_t parser; 42206 | 42207 | resolve_as_vector vect_resolver; 42208 | 42209 | expression.register_symbol_table(symbol_table ); 42210 | expression.register_symbol_table(ext_symbol_table); 42211 | 42212 | if (vector_pass) 42213 | parser.enable_unknown_symbol_resolver(&vect_resolver); 42214 | else 42215 | parser.enable_unknown_symbol_resolver(); 42216 | 42217 | if (collect_variables) 42218 | parser.dec().collect_variables() = true; 42219 | 42220 | if (collect_functions) 42221 | parser.dec().collect_functions() = true; 42222 | 42223 | bool pass_result = false; 42224 | 42225 | details::disable_type_checking(parser); 42226 | 42227 | if (parser.compile(expression_string, expression)) 42228 | { 42229 | pass_result = true; 42230 | 42231 | std::deque<symbol_t> symb_list; 42232 | parser.dec().symbols(symb_list); 42233 | 42234 | for (std::size_t i = 0; i < symb_list.size(); ++i) 42235 | { 42236 | symbol_set.insert(symb_list[i].first); 42237 | } 42238 | } 42239 | 42240 | return pass_result; 42241 | } 42242 | }; 42243 | } 42244 | 42245 | template <typename Allocator, 42246 | template <typename, typename> class Sequence> 42247 | inline bool collect_variables(const std::string& expression, 42248 | Sequence<std::string, Allocator>& symbol_list) 42249 | { 42250 | typedef double T; 42251 | typedef details::collector_helper<T> collect_t; 42252 | 42253 | collect_t::symbol_table_t null_symbol_table; 42254 | 42255 | std::set<std::string> symbol_set; 42256 | 42257 | const bool variable_pass = collect_t::collection_pass 42258 | (expression, symbol_set, true, false, false, null_symbol_table); 42259 | const bool vector_pass = collect_t::collection_pass 42260 | (expression, symbol_set, true, false, true, null_symbol_table); 42261 | 42262 | if (!variable_pass && !vector_pass) 42263 | return false; 42264 | 42265 | std::set<std::string>::iterator itr = symbol_set.begin(); 42266 | 42267 | while (symbol_set.end() != itr) 42268 | { 42269 | symbol_list.push_back(*itr); 42270 | ++itr; 42271 | } 42272 | 42273 | return true; 42274 | } 42275 | 42276 | template <typename T, 42277 | typename Allocator, 42278 | template <typename, typename> class Sequence> 42279 | inline bool collect_variables(const std::string& expression, 42280 | exprtk::symbol_table<T>& extrnl_symbol_table, 42281 | Sequence<std::string, Allocator>& symbol_list) 42282 | { 42283 | typedef details::collector_helper<T> collect_t; 42284 | 42285 | std::set<std::string> symbol_set; 42286 | 42287 | const bool variable_pass = collect_t::collection_pass 42288 | (expression, symbol_set, true, false, false, extrnl_symbol_table); 42289 | const bool vector_pass = collect_t::collection_pass 42290 | (expression, symbol_set, true, false, true, extrnl_symbol_table); 42291 | 42292 | if (!variable_pass && !vector_pass) 42293 | return false; 42294 | 42295 | std::set<std::string>::iterator itr = symbol_set.begin(); 42296 | 42297 | while (symbol_set.end() != itr) 42298 | { 42299 | symbol_list.push_back(*itr); 42300 | ++itr; 42301 | } 42302 | 42303 | return true; 42304 | } 42305 | 42306 | template <typename Allocator, 42307 | template <typename, typename> class Sequence> 42308 | inline bool collect_functions(const std::string& expression, 42309 | Sequence<std::string, Allocator>& symbol_list) 42310 | { 42311 | typedef double T; 42312 | typedef details::collector_helper<T> collect_t; 42313 | 42314 | collect_t::symbol_table_t null_symbol_table; 42315 | 42316 | std::set<std::string> symbol_set; 42317 | 42318 | const bool variable_pass = collect_t::collection_pass 42319 | (expression, symbol_set, false, true, false, null_symbol_table); 42320 | const bool vector_pass = collect_t::collection_pass 42321 | (expression, symbol_set, false, true, true, null_symbol_table); 42322 | 42323 | if (!variable_pass && !vector_pass) 42324 | return false; 42325 | 42326 | std::set<std::string>::iterator itr = symbol_set.begin(); 42327 | 42328 | while (symbol_set.end() != itr) 42329 | { 42330 | symbol_list.push_back(*itr); 42331 | ++itr; 42332 | } 42333 | 42334 | return true; 42335 | } 42336 | 42337 | template <typename T, 42338 | typename Allocator, 42339 | template <typename, typename> class Sequence> 42340 | inline bool collect_functions(const std::string& expression, 42341 | exprtk::symbol_table<T>& extrnl_symbol_table, 42342 | Sequence<std::string, Allocator>& symbol_list) 42343 | { 42344 | typedef details::collector_helper<T> collect_t; 42345 | 42346 | std::set<std::string> symbol_set; 42347 | 42348 | const bool variable_pass = collect_t::collection_pass 42349 | (expression, symbol_set, false, true, false, extrnl_symbol_table); 42350 | const bool vector_pass = collect_t::collection_pass 42351 | (expression, symbol_set, false, true, true, extrnl_symbol_table); 42352 | 42353 | if (!variable_pass && !vector_pass) 42354 | return false; 42355 | 42356 | std::set<std::string>::iterator itr = symbol_set.begin(); 42357 | 42358 | while (symbol_set.end() != itr) 42359 | { 42360 | symbol_list.push_back(*itr); 42361 | ++itr; 42362 | } 42363 | 42364 | return true; 42365 | } 42366 | 42367 | template <typename T> 42368 | inline T integrate(const expression<T>& e, 42369 | T& x, 42370 | const T& r0, const T& r1, 42371 | const std::size_t number_of_intervals = 1000000) 42372 | { 42373 | if (r0 > r1) 42374 | return T(0); 42375 | 42376 | const T h = (r1 - r0) / (T(2) * number_of_intervals); 42377 | T total_area = T(0); 42378 | 42379 | for (std::size_t i = 0; i < number_of_intervals; ++i) 42380 | { 42381 | x = r0 + T(2) * i * h; 42382 | const T y0 = e.value(); x += h; 42383 | const T y1 = e.value(); x += h; 42384 | const T y2 = e.value(); x += h; 42385 | total_area += h * (y0 + T(4) * y1 + y2) / T(3); 42386 | } 42387 | 42388 | return total_area; 42389 | } 42390 | 42391 | template <typename T> 42392 | inline T integrate(const expression<T>& e, 42393 | const std::string& variable_name, 42394 | const T& r0, const T& r1, 42395 | const std::size_t number_of_intervals = 1000000) 42396 | { 42397 | const symbol_table<T>& sym_table = e.get_symbol_table(); 42398 | 42399 | if (!sym_table.valid()) 42400 | { 42401 | return std::numeric_limits<T>::quiet_NaN(); 42402 | } 42403 | 42404 | details::variable_node<T>* var = sym_table.get_variable(variable_name); 42405 | 42406 | if (var) 42407 | { 42408 | T& x = var->ref(); 42409 | const T x_original = x; 42410 | const T result = integrate(e, x, r0, r1, number_of_intervals); 42411 | x = x_original; 42412 | 42413 | return result; 42414 | } 42415 | 42416 | return std::numeric_limits<T>::quiet_NaN(); 42417 | } 42418 | 42419 | template <typename T> 42420 | inline T derivative(const expression<T>& e, 42421 | T& x, 42422 | const T& h = T(0.00000001)) 42423 | { 42424 | const T x_init = x; 42425 | const T _2h = T(2) * h; 42426 | 42427 | x = x_init + _2h; 42428 | const T y0 = e.value(); 42429 | x = x_init + h; 42430 | const T y1 = e.value(); 42431 | x = x_init - h; 42432 | const T y2 = e.value(); 42433 | x = x_init - _2h; 42434 | const T y3 = e.value(); 42435 | x = x_init; 42436 | 42437 | return (-y0 + T(8) * (y1 - y2) + y3) / (T(12) * h); 42438 | } 42439 | 42440 | template <typename T> 42441 | inline T second_derivative(const expression<T>& e, 42442 | T& x, 42443 | const T& h = T(0.00001)) 42444 | { 42445 | const T x_init = x; 42446 | const T _2h = T(2) * h; 42447 | 42448 | const T y = e.value(); 42449 | x = x_init + _2h; 42450 | const T y0 = e.value(); 42451 | x = x_init + h; 42452 | const T y1 = e.value(); 42453 | x = x_init - h; 42454 | const T y2 = e.value(); 42455 | x = x_init - _2h; 42456 | const T y3 = e.value(); 42457 | x = x_init; 42458 | 42459 | return (-y0 + T(16) * (y1 + y2) - T(30) * y - y3) / (T(12) * h * h); 42460 | } 42461 | 42462 | template <typename T> 42463 | inline T third_derivative(const expression<T>& e, 42464 | T& x, 42465 | const T& h = T(0.0001)) 42466 | { 42467 | const T x_init = x; 42468 | const T _2h = T(2) * h; 42469 | 42470 | x = x_init + _2h; 42471 | const T y0 = e.value(); 42472 | x = x_init + h; 42473 | const T y1 = e.value(); 42474 | x = x_init - h; 42475 | const T y2 = e.value(); 42476 | x = x_init - _2h; 42477 | const T y3 = e.value(); 42478 | x = x_init; 42479 | 42480 | return (y0 + T(2) * (y2 - y1) - y3) / (T(2) * h * h * h); 42481 | } 42482 | 42483 | template <typename T> 42484 | inline T derivative(const expression<T>& e, 42485 | const std::string& variable_name, 42486 | const T& h = T(0.00000001)) 42487 | { 42488 | const symbol_table<T>& sym_table = e.get_symbol_table(); 42489 | 42490 | if (!sym_table.valid()) 42491 | { 42492 | return std::numeric_limits<T>::quiet_NaN(); 42493 | } 42494 | 42495 | details::variable_node<T>* var = sym_table.get_variable(variable_name); 42496 | 42497 | if (var) 42498 | { 42499 | T& x = var->ref(); 42500 | const T x_original = x; 42501 | const T result = derivative(e, x, h); 42502 | x = x_original; 42503 | 42504 | return result; 42505 | } 42506 | 42507 | return std::numeric_limits<T>::quiet_NaN(); 42508 | } 42509 | 42510 | template <typename T> 42511 | inline T second_derivative(const expression<T>& e, 42512 | const std::string& variable_name, 42513 | const T& h = T(0.00001)) 42514 | { 42515 | const symbol_table<T>& sym_table = e.get_symbol_table(); 42516 | 42517 | if (!sym_table.valid()) 42518 | { 42519 | return std::numeric_limits<T>::quiet_NaN(); 42520 | } 42521 | 42522 | details::variable_node<T>* var = sym_table.get_variable(variable_name); 42523 | 42524 | if (var) 42525 | { 42526 | T& x = var->ref(); 42527 | const T x_original = x; 42528 | const T result = second_derivative(e, x, h); 42529 | x = x_original; 42530 | 42531 | return result; 42532 | } 42533 | 42534 | return std::numeric_limits<T>::quiet_NaN(); 42535 | } 42536 | 42537 | template <typename T> 42538 | inline T third_derivative(const expression<T>& e, 42539 | const std::string& variable_name, 42540 | const T& h = T(0.0001)) 42541 | { 42542 | const symbol_table<T>& sym_table = e.get_symbol_table(); 42543 | 42544 | if (!sym_table.valid()) 42545 | { 42546 | return std::numeric_limits<T>::quiet_NaN(); 42547 | } 42548 | 42549 | details::variable_node<T>* var = sym_table.get_variable(variable_name); 42550 | 42551 | if (var) 42552 | { 42553 | T& x = var->ref(); 42554 | const T x_original = x; 42555 | const T result = third_derivative(e, x, h); 42556 | x = x_original; 42557 | 42558 | return result; 42559 | } 42560 | 42561 | return std::numeric_limits<T>::quiet_NaN(); 42562 | } 42563 | 42564 | /* 42565 | Note: The following 'compute' routines are simple helpers, 42566 | for quickly setting up the required pieces of code in order 42567 | to evaluate an expression. By virtue of how they operate 42568 | there will be an overhead with regards to their setup and 42569 | teardown and hence should not be used in time critical 42570 | sections of code. 42571 | Furthermore they only assume a small sub set of variables, 42572 | no string variables or user defined functions. 42573 | */ 42574 | template <typename T> 42575 | inline bool compute(const std::string& expression_string, T& result) 42576 | { 42577 | // No variables 42578 | symbol_table<T> symbol_table; 42579 | symbol_table.add_constants(); 42580 | 42581 | expression<T> expression; 42582 | expression.register_symbol_table(symbol_table); 42583 | 42584 | parser<T> parser; 42585 | 42586 | if (parser.compile(expression_string,expression)) 42587 | { 42588 | result = expression.value(); 42589 | 42590 | return true; 42591 | } 42592 | else 42593 | return false; 42594 | } 42595 | 42596 | template <typename T> 42597 | inline bool compute(const std::string& expression_string, 42598 | const T& x, 42599 | T& result) 42600 | { 42601 | // Only 'x' 42602 | static const std::string x_var("x"); 42603 | 42604 | symbol_table<T> symbol_table; 42605 | symbol_table.add_constants(); 42606 | symbol_table.add_constant(x_var,x); 42607 | 42608 | expression<T> expression; 42609 | expression.register_symbol_table(symbol_table); 42610 | 42611 | parser<T> parser; 42612 | 42613 | if (parser.compile(expression_string,expression)) 42614 | { 42615 | result = expression.value(); 42616 | 42617 | return true; 42618 | } 42619 | else 42620 | return false; 42621 | } 42622 | 42623 | template <typename T> 42624 | inline bool compute(const std::string& expression_string, 42625 | const T&x, const T& y, 42626 | T& result) 42627 | { 42628 | // Only 'x' and 'y' 42629 | static const std::string x_var("x"); 42630 | static const std::string y_var("y"); 42631 | 42632 | symbol_table<T> symbol_table; 42633 | symbol_table.add_constants(); 42634 | symbol_table.add_constant(x_var,x); 42635 | symbol_table.add_constant(y_var,y); 42636 | 42637 | expression<T> expression; 42638 | expression.register_symbol_table(symbol_table); 42639 | 42640 | parser<T> parser; 42641 | 42642 | if (parser.compile(expression_string,expression)) 42643 | { 42644 | result = expression.value(); 42645 | 42646 | return true; 42647 | } 42648 | else 42649 | return false; 42650 | } 42651 | 42652 | template <typename T> 42653 | inline bool compute(const std::string& expression_string, 42654 | const T& x, const T& y, const T& z, 42655 | T& result) 42656 | { 42657 | // Only 'x', 'y' or 'z' 42658 | static const std::string x_var("x"); 42659 | static const std::string y_var("y"); 42660 | static const std::string z_var("z"); 42661 | 42662 | symbol_table<T> symbol_table; 42663 | symbol_table.add_constants(); 42664 | symbol_table.add_constant(x_var,x); 42665 | symbol_table.add_constant(y_var,y); 42666 | symbol_table.add_constant(z_var,z); 42667 | 42668 | expression<T> expression; 42669 | expression.register_symbol_table(symbol_table); 42670 | 42671 | parser<T> parser; 42672 | 42673 | if (parser.compile(expression_string,expression)) 42674 | { 42675 | result = expression.value(); 42676 | 42677 | return true; 42678 | } 42679 | else 42680 | return false; 42681 | } 42682 | 42683 | template <typename T, std::size_t N> 42684 | class polynomial : public ifunction<T> 42685 | { 42686 | private: 42687 | 42688 | template <typename Type, std::size_t NumberOfCoefficients> 42689 | struct poly_impl { }; 42690 | 42691 | template <typename Type> 42692 | struct poly_impl <Type,12> 42693 | { 42694 | static inline T evaluate(const Type x, 42695 | const Type c12, const Type c11, const Type c10, const Type c9, const Type c8, 42696 | const Type c7, const Type c6, const Type c5, const Type c4, const Type c3, 42697 | const Type c2, const Type c1, const Type c0) 42698 | { 42699 | // p(x) = c_12x^12 + c_11x^11 + c_10x^10 + c_9x^9 + c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 42700 | return ((((((((((((c12 * x + c11) * x + c10) * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42701 | } 42702 | }; 42703 | 42704 | template <typename Type> 42705 | struct poly_impl <Type,11> 42706 | { 42707 | static inline T evaluate(const Type x, 42708 | const Type c11, const Type c10, const Type c9, const Type c8, const Type c7, 42709 | const Type c6, const Type c5, const Type c4, const Type c3, const Type c2, 42710 | const Type c1, const Type c0) 42711 | { 42712 | // p(x) = c_11x^11 + c_10x^10 + c_9x^9 + c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 42713 | return (((((((((((c11 * x + c10) * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42714 | } 42715 | }; 42716 | 42717 | template <typename Type> 42718 | struct poly_impl <Type,10> 42719 | { 42720 | static inline T evaluate(const Type x, 42721 | const Type c10, const Type c9, const Type c8, const Type c7, const Type c6, 42722 | const Type c5, const Type c4, const Type c3, const Type c2, const Type c1, 42723 | const Type c0) 42724 | { 42725 | // p(x) = c_10x^10 + c_9x^9 + c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 42726 | return ((((((((((c10 * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42727 | } 42728 | }; 42729 | 42730 | template <typename Type> 42731 | struct poly_impl <Type,9> 42732 | { 42733 | static inline T evaluate(const Type x, 42734 | const Type c9, const Type c8, const Type c7, const Type c6, const Type c5, 42735 | const Type c4, const Type c3, const Type c2, const Type c1, const Type c0) 42736 | { 42737 | // p(x) = c_9x^9 + c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 42738 | return (((((((((c9 * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42739 | } 42740 | }; 42741 | 42742 | template <typename Type> 42743 | struct poly_impl <Type,8> 42744 | { 42745 | static inline T evaluate(const Type x, 42746 | const Type c8, const Type c7, const Type c6, const Type c5, const Type c4, 42747 | const Type c3, const Type c2, const Type c1, const Type c0) 42748 | { 42749 | // p(x) = c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 42750 | return ((((((((c8 * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42751 | } 42752 | }; 42753 | 42754 | template <typename Type> 42755 | struct poly_impl <Type,7> 42756 | { 42757 | static inline T evaluate(const Type x, 42758 | const Type c7, const Type c6, const Type c5, const Type c4, const Type c3, 42759 | const Type c2, const Type c1, const Type c0) 42760 | { 42761 | // p(x) = c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 42762 | return (((((((c7 * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42763 | } 42764 | }; 42765 | 42766 | template <typename Type> 42767 | struct poly_impl <Type,6> 42768 | { 42769 | static inline T evaluate(const Type x, 42770 | const Type c6, const Type c5, const Type c4, const Type c3, const Type c2, 42771 | const Type c1, const Type c0) 42772 | { 42773 | // p(x) = c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 42774 | return ((((((c6 * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42775 | } 42776 | }; 42777 | 42778 | template <typename Type> 42779 | struct poly_impl <Type,5> 42780 | { 42781 | static inline T evaluate(const Type x, 42782 | const Type c5, const Type c4, const Type c3, const Type c2, 42783 | const Type c1, const Type c0) 42784 | { 42785 | // p(x) = c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 42786 | return (((((c5 * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42787 | } 42788 | }; 42789 | 42790 | template <typename Type> 42791 | struct poly_impl <Type,4> 42792 | { 42793 | static inline T evaluate(const Type x, const Type c4, const Type c3, const Type c2, const Type c1, const Type c0) 42794 | { 42795 | // p(x) = c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 42796 | return ((((c4 * x + c3) * x + c2) * x + c1) * x + c0); 42797 | } 42798 | }; 42799 | 42800 | template <typename Type> 42801 | struct poly_impl <Type,3> 42802 | { 42803 | static inline T evaluate(const Type x, const Type c3, const Type c2, const Type c1, const Type c0) 42804 | { 42805 | // p(x) = c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 42806 | return (((c3 * x + c2) * x + c1) * x + c0); 42807 | } 42808 | }; 42809 | 42810 | template <typename Type> 42811 | struct poly_impl <Type,2> 42812 | { 42813 | static inline T evaluate(const Type x, const Type c2, const Type c1, const Type c0) 42814 | { 42815 | // p(x) = c_2x^2 + c_1x^1 + c_0x^0 42816 | return ((c2 * x + c1) * x + c0); 42817 | } 42818 | }; 42819 | 42820 | template <typename Type> 42821 | struct poly_impl <Type,1> 42822 | { 42823 | static inline T evaluate(const Type x, const Type c1, const Type c0) 42824 | { 42825 | // p(x) = c_1x^1 + c_0x^0 42826 | return (c1 * x + c0); 42827 | } 42828 | }; 42829 | 42830 | public: 42831 | 42832 | using ifunction<T>::operator(); 42833 | 42834 | polynomial() 42835 | : ifunction<T>((N+2 <= 20) ? (N + 2) : std::numeric_limits<std::size_t>::max()) 42836 | { 42837 | disable_has_side_effects(*this); 42838 | } 42839 | 42840 | virtual ~polynomial() exprtk_override 42841 | {} 42842 | 42843 | #define poly_rtrn(NN) \ 42844 | return (NN != N) ? std::numeric_limits<T>::quiet_NaN() : 42845 | 42846 | inline virtual T operator() (const T& x, const T& c1, const T& c0) exprtk_override 42847 | { 42848 | poly_rtrn(1) (poly_impl<T,1>::evaluate(x, c1, c0)); 42849 | } 42850 | 42851 | inline virtual T operator() (const T& x, const T& c2, const T& c1, const T& c0) exprtk_override 42852 | { 42853 | poly_rtrn(2) (poly_impl<T,2>::evaluate(x, c2, c1, c0)); 42854 | } 42855 | 42856 | inline virtual T operator() (const T& x, const T& c3, const T& c2, const T& c1, const T& c0) exprtk_override 42857 | { 42858 | poly_rtrn(3) (poly_impl<T,3>::evaluate(x, c3, c2, c1, c0)); 42859 | } 42860 | 42861 | inline virtual T operator() (const T& x, const T& c4, const T& c3, const T& c2, const T& c1, 42862 | const T& c0) exprtk_override 42863 | { 42864 | poly_rtrn(4) (poly_impl<T,4>::evaluate(x, c4, c3, c2, c1, c0)); 42865 | } 42866 | 42867 | inline virtual T operator() (const T& x, const T& c5, const T& c4, const T& c3, const T& c2, 42868 | const T& c1, const T& c0) exprtk_override 42869 | { 42870 | poly_rtrn(5) (poly_impl<T,5>::evaluate(x, c5, c4, c3, c2, c1, c0)); 42871 | } 42872 | 42873 | inline virtual T operator() (const T& x, const T& c6, const T& c5, const T& c4, const T& c3, 42874 | const T& c2, const T& c1, const T& c0) exprtk_override 42875 | { 42876 | poly_rtrn(6) (poly_impl<T,6>::evaluate(x, c6, c5, c4, c3, c2, c1, c0)); 42877 | } 42878 | 42879 | inline virtual T operator() (const T& x, const T& c7, const T& c6, const T& c5, const T& c4, 42880 | const T& c3, const T& c2, const T& c1, const T& c0) exprtk_override 42881 | { 42882 | poly_rtrn(7) (poly_impl<T,7>::evaluate(x, c7, c6, c5, c4, c3, c2, c1, c0)); 42883 | } 42884 | 42885 | inline virtual T operator() (const T& x, const T& c8, const T& c7, const T& c6, const T& c5, 42886 | const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) exprtk_override 42887 | { 42888 | poly_rtrn(8) (poly_impl<T,8>::evaluate(x, c8, c7, c6, c5, c4, c3, c2, c1, c0)); 42889 | } 42890 | 42891 | inline virtual T operator() (const T& x, const T& c9, const T& c8, const T& c7, const T& c6, 42892 | const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, 42893 | const T& c0) exprtk_override 42894 | { 42895 | poly_rtrn(9) (poly_impl<T,9>::evaluate(x, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0)); 42896 | } 42897 | 42898 | inline virtual T operator() (const T& x, const T& c10, const T& c9, const T& c8, const T& c7, 42899 | const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, 42900 | const T& c1, const T& c0) exprtk_override 42901 | { 42902 | poly_rtrn(10) (poly_impl<T,10>::evaluate(x, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0)); 42903 | } 42904 | 42905 | inline virtual T operator() (const T& x, const T& c11, const T& c10, const T& c9, const T& c8, 42906 | const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, 42907 | const T& c2, const T& c1, const T& c0) exprtk_override 42908 | { 42909 | poly_rtrn(11) (poly_impl<T,11>::evaluate(x, c11, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0)); 42910 | } 42911 | 42912 | inline virtual T operator() (const T& x, const T& c12, const T& c11, const T& c10, const T& c9, 42913 | const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, 42914 | const T& c3, const T& c2, const T& c1, const T& c0) exprtk_override 42915 | { 42916 | poly_rtrn(12) (poly_impl<T,12>::evaluate(x, c12, c11, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0)); 42917 | } 42918 | 42919 | #undef poly_rtrn 42920 | 42921 | inline virtual T operator() () exprtk_override 42922 | { 42923 | return std::numeric_limits<T>::quiet_NaN(); 42924 | } 42925 | 42926 | inline virtual T operator() (const T&) exprtk_override 42927 | { 42928 | return std::numeric_limits<T>::quiet_NaN(); 42929 | } 42930 | 42931 | inline virtual T operator() (const T&, const T&) exprtk_override 42932 | { 42933 | return std::numeric_limits<T>::quiet_NaN(); 42934 | } 42935 | }; 42936 | 42937 | template <typename T> 42938 | class function_compositor 42939 | { 42940 | public: 42941 | 42942 | typedef exprtk::expression<T> expression_t; 42943 | typedef exprtk::symbol_table<T> symbol_table_t; 42944 | typedef exprtk::parser<T> parser_t; 42945 | typedef typename parser_t::settings_store settings_t; 42946 | 42947 | struct function 42948 | { 42949 | function() 42950 | {} 42951 | 42952 | explicit function(const std::string& n) 42953 | : name_(n) 42954 | {} 42955 | 42956 | function(const std::string& name, 42957 | const std::string& expression) 42958 | : name_(name) 42959 | , expression_(expression) 42960 | {} 42961 | 42962 | function(const std::string& name, 42963 | const std::string& expression, 42964 | const std::string& v0) 42965 | : name_(name) 42966 | , expression_(expression) 42967 | { 42968 | v_.push_back(v0); 42969 | } 42970 | 42971 | function(const std::string& name, 42972 | const std::string& expression, 42973 | const std::string& v0, const std::string& v1) 42974 | : name_(name) 42975 | , expression_(expression) 42976 | { 42977 | v_.push_back(v0); v_.push_back(v1); 42978 | } 42979 | 42980 | function(const std::string& name, 42981 | const std::string& expression, 42982 | const std::string& v0, const std::string& v1, 42983 | const std::string& v2) 42984 | : name_(name) 42985 | , expression_(expression) 42986 | { 42987 | v_.push_back(v0); v_.push_back(v1); 42988 | v_.push_back(v2); 42989 | } 42990 | 42991 | function(const std::string& name, 42992 | const std::string& expression, 42993 | const std::string& v0, const std::string& v1, 42994 | const std::string& v2, const std::string& v3) 42995 | : name_(name) 42996 | , expression_(expression) 42997 | { 42998 | v_.push_back(v0); v_.push_back(v1); 42999 | v_.push_back(v2); v_.push_back(v3); 43000 | } 43001 | 43002 | function(const std::string& name, 43003 | const std::string& expression, 43004 | const std::string& v0, const std::string& v1, 43005 | const std::string& v2, const std::string& v3, 43006 | const std::string& v4) 43007 | : name_(name) 43008 | , expression_(expression) 43009 | { 43010 | v_.push_back(v0); v_.push_back(v1); 43011 | v_.push_back(v2); v_.push_back(v3); 43012 | v_.push_back(v4); 43013 | } 43014 | 43015 | inline function& name(const std::string& n) 43016 | { 43017 | name_ = n; 43018 | return (*this); 43019 | } 43020 | 43021 | inline function& expression(const std::string& e) 43022 | { 43023 | expression_ = e; 43024 | return (*this); 43025 | } 43026 | 43027 | inline function& var(const std::string& v) 43028 | { 43029 | v_.push_back(v); 43030 | return (*this); 43031 | } 43032 | 43033 | inline function& vars(const std::string& v0, 43034 | const std::string& v1) 43035 | { 43036 | v_.push_back(v0); 43037 | v_.push_back(v1); 43038 | return (*this); 43039 | } 43040 | 43041 | inline function& vars(const std::string& v0, 43042 | const std::string& v1, 43043 | const std::string& v2) 43044 | { 43045 | v_.push_back(v0); 43046 | v_.push_back(v1); 43047 | v_.push_back(v2); 43048 | return (*this); 43049 | } 43050 | 43051 | inline function& vars(const std::string& v0, 43052 | const std::string& v1, 43053 | const std::string& v2, 43054 | const std::string& v3) 43055 | { 43056 | v_.push_back(v0); 43057 | v_.push_back(v1); 43058 | v_.push_back(v2); 43059 | v_.push_back(v3); 43060 | return (*this); 43061 | } 43062 | 43063 | inline function& vars(const std::string& v0, 43064 | const std::string& v1, 43065 | const std::string& v2, 43066 | const std::string& v3, 43067 | const std::string& v4) 43068 | { 43069 | v_.push_back(v0); 43070 | v_.push_back(v1); 43071 | v_.push_back(v2); 43072 | v_.push_back(v3); 43073 | v_.push_back(v4); 43074 | return (*this); 43075 | } 43076 | 43077 | std::string name_; 43078 | std::string expression_; 43079 | std::deque<std::string> v_; 43080 | }; 43081 | 43082 | private: 43083 | 43084 | struct base_func : public exprtk::ifunction<T> 43085 | { 43086 | typedef const T& type; 43087 | typedef exprtk::ifunction<T> function_t; 43088 | typedef std::vector<T*> varref_t; 43089 | typedef std::vector<T> var_t; 43090 | typedef std::vector<std::string> str_t; 43091 | typedef std::pair<T*,std::size_t> lvarref_t; 43092 | typedef std::vector<lvarref_t> lvr_vec_t; 43093 | typedef std::vector<std::string*> lstr_vec_t; 43094 | 43095 | using exprtk::ifunction<T>::operator(); 43096 | 43097 | explicit base_func(const std::size_t& pc = 0) 43098 | : exprtk::ifunction<T>(pc) 43099 | , local_var_stack_size(0) 43100 | , stack_depth(0) 43101 | { 43102 | v.resize(pc); 43103 | } 43104 | 43105 | virtual ~base_func() 43106 | {} 43107 | 43108 | #define exprtk_assign(Index) \ 43109 | (*v[Index]) = v##Index; \ 43110 | 43111 | inline void update(const T& v0) 43112 | { 43113 | exprtk_assign(0) 43114 | } 43115 | 43116 | inline void update(const T& v0, const T& v1) 43117 | { 43118 | exprtk_assign(0) exprtk_assign(1) 43119 | } 43120 | 43121 | inline void update(const T& v0, const T& v1, const T& v2) 43122 | { 43123 | exprtk_assign(0) exprtk_assign(1) 43124 | exprtk_assign(2) 43125 | } 43126 | 43127 | inline void update(const T& v0, const T& v1, const T& v2, const T& v3) 43128 | { 43129 | exprtk_assign(0) exprtk_assign(1) 43130 | exprtk_assign(2) exprtk_assign(3) 43131 | } 43132 | 43133 | inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4) 43134 | { 43135 | exprtk_assign(0) exprtk_assign(1) 43136 | exprtk_assign(2) exprtk_assign(3) 43137 | exprtk_assign(4) 43138 | } 43139 | 43140 | inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5) 43141 | { 43142 | exprtk_assign(0) exprtk_assign(1) 43143 | exprtk_assign(2) exprtk_assign(3) 43144 | exprtk_assign(4) exprtk_assign(5) 43145 | } 43146 | 43147 | #ifdef exprtk_assign 43148 | #undef exprtk_assign 43149 | #endif 43150 | 43151 | inline function_t& setup(expression_t& expr) 43152 | { 43153 | expression = expr; 43154 | 43155 | typedef typename expression_t::control_block ctrlblk_t; 43156 | typedef typename ctrlblk_t::local_data_list_t ldl_t; 43157 | typedef typename ctrlblk_t::data_type data_t; 43158 | typedef typename ldl_t::value_type ldl_value_type; 43159 | 43160 | const ldl_t ldl = expr.local_data_list(); 43161 | 43162 | std::vector<std::pair<std::size_t,data_t> > index_list; 43163 | 43164 | for (std::size_t i = 0; i < ldl.size(); ++i) 43165 | { 43166 | exprtk_debug(("base_func::setup() - element[%02d] type: %s size: %d\n", 43167 | static_cast<int>(i), 43168 | expression_t::control_block::to_str(ldl[i].type).c_str(), 43169 | static_cast<int>(ldl[i].size))); 43170 | 43171 | switch (ldl[i].type) 43172 | { 43173 | case ctrlblk_t::e_unknown : continue; 43174 | case ctrlblk_t::e_expr : continue; 43175 | case ctrlblk_t::e_vecholder : continue; 43176 | default : break; 43177 | } 43178 | 43179 | if (ldl[i].size) 43180 | { 43181 | index_list.push_back(std::make_pair(i,ldl[i].type)); 43182 | } 43183 | } 43184 | 43185 | std::size_t input_param_count = 0; 43186 | 43187 | for (std::size_t i = 0; i < index_list.size(); ++i) 43188 | { 43189 | const std::size_t index = index_list[i].first; 43190 | const ldl_value_type& local_var = ldl[index]; 43191 | 43192 | assert(local_var.pointer); 43193 | 43194 | if (i < (index_list.size() - v.size())) 43195 | { 43196 | if (local_var.type == ctrlblk_t::e_string) 43197 | { 43198 | local_str_vars.push_back( 43199 | reinterpret_cast<std::string*>(local_var.pointer)); 43200 | } 43201 | else if ( 43202 | (local_var.type == ctrlblk_t::e_data ) || 43203 | (local_var.type == ctrlblk_t::e_vecdata) 43204 | ) 43205 | { 43206 | local_vars.push_back(std::make_pair( 43207 | reinterpret_cast<T*>(local_var.pointer), 43208 | local_var.size)); 43209 | 43210 | local_var_stack_size += local_var.size; 43211 | } 43212 | } 43213 | else 43214 | { 43215 | v[input_param_count++] = reinterpret_cast<T*>(local_var.pointer); 43216 | } 43217 | } 43218 | 43219 | clear_stack(); 43220 | 43221 | return (*this); 43222 | } 43223 | 43224 | inline void pre() 43225 | { 43226 | if (stack_depth++) 43227 | { 43228 | if (!v.empty()) 43229 | { 43230 | var_t var_stack(v.size(),T(0)); 43231 | copy(v,var_stack); 43232 | input_params_stack.push_back(var_stack); 43233 | } 43234 | 43235 | if (!local_vars.empty()) 43236 | { 43237 | var_t local_vec_frame(local_var_stack_size,T(0)); 43238 | copy(local_vars,local_vec_frame); 43239 | local_var_stack.push_back(local_vec_frame); 43240 | } 43241 | 43242 | if (!local_str_vars.empty()) 43243 | { 43244 | str_t local_str_frame(local_str_vars.size()); 43245 | copy(local_str_vars,local_str_frame); 43246 | local_str_stack.push_back(local_str_frame); 43247 | } 43248 | } 43249 | } 43250 | 43251 | inline void post() 43252 | { 43253 | if (--stack_depth) 43254 | { 43255 | if (!v.empty()) 43256 | { 43257 | copy(input_params_stack.back(), v); 43258 | input_params_stack.pop_back(); 43259 | } 43260 | 43261 | if (!local_vars.empty()) 43262 | { 43263 | copy(local_var_stack.back(), local_vars); 43264 | local_var_stack.pop_back(); 43265 | } 43266 | 43267 | if (!local_str_vars.empty()) 43268 | { 43269 | copy(local_str_stack.back(), local_str_vars); 43270 | local_str_stack.pop_back(); 43271 | } 43272 | } 43273 | } 43274 | 43275 | void copy(const varref_t& src_v, var_t& dest_v) 43276 | { 43277 | for (std::size_t i = 0; i < src_v.size(); ++i) 43278 | { 43279 | dest_v[i] = (*src_v[i]); 43280 | } 43281 | } 43282 | 43283 | void copy(const lstr_vec_t& src_v, str_t& dest_v) 43284 | { 43285 | for (std::size_t i = 0; i < src_v.size(); ++i) 43286 | { 43287 | dest_v[i] = (*src_v[i]); 43288 | } 43289 | } 43290 | 43291 | void copy(const var_t& src_v, varref_t& dest_v) 43292 | { 43293 | for (std::size_t i = 0; i < src_v.size(); ++i) 43294 | { 43295 | (*dest_v[i]) = src_v[i]; 43296 | } 43297 | } 43298 | 43299 | void copy(const lvr_vec_t& src_v, var_t& dest_v) 43300 | { 43301 | typename var_t::iterator itr = dest_v.begin(); 43302 | typedef typename std::iterator_traits<typename var_t::iterator>::difference_type diff_t; 43303 | 43304 | for (std::size_t i = 0; i < src_v.size(); ++i) 43305 | { 43306 | lvarref_t vr = src_v[i]; 43307 | 43308 | if (1 == vr.second) 43309 | *itr++ = (*vr.first); 43310 | else 43311 | { 43312 | std::copy(vr.first, vr.first + vr.second, itr); 43313 | itr += static_cast<diff_t>(vr.second); 43314 | } 43315 | } 43316 | } 43317 | 43318 | void copy(const var_t& src_v, lvr_vec_t& dest_v) 43319 | { 43320 | typename var_t::const_iterator itr = src_v.begin(); 43321 | typedef typename std::iterator_traits<typename var_t::iterator>::difference_type diff_t; 43322 | 43323 | for (std::size_t i = 0; i < dest_v.size(); ++i) 43324 | { 43325 | lvarref_t& vr = dest_v[i]; 43326 | 43327 | assert(vr.first != 0); 43328 | assert(vr.second > 0); 43329 | 43330 | if (1 == vr.second) 43331 | (*vr.first) = *itr++; 43332 | else 43333 | { 43334 | std::copy(itr, itr + static_cast<diff_t>(vr.second), vr.first); 43335 | itr += static_cast<diff_t>(vr.second); 43336 | } 43337 | } 43338 | } 43339 | 43340 | void copy(const str_t& src_str, lstr_vec_t& dest_str) 43341 | { 43342 | assert(src_str.size() == dest_str.size()); 43343 | 43344 | for (std::size_t i = 0; i < dest_str.size(); ++i) 43345 | { 43346 | *dest_str[i] = src_str[i]; 43347 | } 43348 | } 43349 | 43350 | inline void clear_stack() 43351 | { 43352 | for (std::size_t i = 0; i < v.size(); ++i) 43353 | { 43354 | (*v[i]) = 0; 43355 | } 43356 | } 43357 | 43358 | inline virtual T value(expression_t& e) 43359 | { 43360 | return e.value(); 43361 | } 43362 | 43363 | expression_t expression; 43364 | varref_t v; 43365 | lvr_vec_t local_vars; 43366 | lstr_vec_t local_str_vars; 43367 | std::size_t local_var_stack_size; 43368 | std::size_t stack_depth; 43369 | std::deque<var_t> input_params_stack; 43370 | std::deque<var_t> local_var_stack; 43371 | std::deque<str_t> local_str_stack; 43372 | }; 43373 | 43374 | typedef std::map<std::string,base_func*> funcparam_t; 43375 | 43376 | typedef const T& type; 43377 | 43378 | template <typename BaseFuncType> 43379 | struct scoped_bft 43380 | { 43381 | explicit scoped_bft(BaseFuncType& bft) 43382 | : bft_(bft) 43383 | { 43384 | bft_.pre (); 43385 | } 43386 | 43387 | ~scoped_bft() 43388 | { 43389 | bft_.post(); 43390 | } 43391 | 43392 | BaseFuncType& bft_; 43393 | 43394 | private: 43395 | 43396 | scoped_bft(const scoped_bft&) exprtk_delete; 43397 | scoped_bft& operator=(const scoped_bft&) exprtk_delete; 43398 | }; 43399 | 43400 | struct func_0param : public base_func 43401 | { 43402 | using exprtk::ifunction<T>::operator(); 43403 | 43404 | func_0param() : base_func(0) {} 43405 | 43406 | inline T operator() () exprtk_override 43407 | { 43408 | scoped_bft<func_0param> sb(*this); 43409 | return this->value(base_func::expression); 43410 | } 43411 | }; 43412 | 43413 | struct func_1param : public base_func 43414 | { 43415 | using exprtk::ifunction<T>::operator(); 43416 | 43417 | func_1param() : base_func(1) {} 43418 | 43419 | inline T operator() (type v0) exprtk_override 43420 | { 43421 | scoped_bft<func_1param> sb(*this); 43422 | base_func::update(v0); 43423 | return this->value(base_func::expression); 43424 | } 43425 | }; 43426 | 43427 | struct func_2param : public base_func 43428 | { 43429 | using exprtk::ifunction<T>::operator(); 43430 | 43431 | func_2param() : base_func(2) {} 43432 | 43433 | inline T operator() (type v0, type v1) exprtk_override 43434 | { 43435 | scoped_bft<func_2param> sb(*this); 43436 | base_func::update(v0, v1); 43437 | return this->value(base_func::expression); 43438 | } 43439 | }; 43440 | 43441 | struct func_3param : public base_func 43442 | { 43443 | using exprtk::ifunction<T>::operator(); 43444 | 43445 | func_3param() : base_func(3) {} 43446 | 43447 | inline T operator() (type v0, type v1, type v2) exprtk_override 43448 | { 43449 | scoped_bft<func_3param> sb(*this); 43450 | base_func::update(v0, v1, v2); 43451 | return this->value(base_func::expression); 43452 | } 43453 | }; 43454 | 43455 | struct func_4param : public base_func 43456 | { 43457 | using exprtk::ifunction<T>::operator(); 43458 | 43459 | func_4param() : base_func(4) {} 43460 | 43461 | inline T operator() (type v0, type v1, type v2, type v3) exprtk_override 43462 | { 43463 | scoped_bft<func_4param> sb(*this); 43464 | base_func::update(v0, v1, v2, v3); 43465 | return this->value(base_func::expression); 43466 | } 43467 | }; 43468 | 43469 | struct func_5param : public base_func 43470 | { 43471 | using exprtk::ifunction<T>::operator(); 43472 | 43473 | func_5param() : base_func(5) {} 43474 | 43475 | inline T operator() (type v0, type v1, type v2, type v3, type v4) exprtk_override 43476 | { 43477 | scoped_bft<func_5param> sb(*this); 43478 | base_func::update(v0, v1, v2, v3, v4); 43479 | return this->value(base_func::expression); 43480 | } 43481 | }; 43482 | 43483 | struct func_6param : public base_func 43484 | { 43485 | using exprtk::ifunction<T>::operator(); 43486 | 43487 | func_6param() : base_func(6) {} 43488 | 43489 | inline T operator() (type v0, type v1, type v2, type v3, type v4, type v5) exprtk_override 43490 | { 43491 | scoped_bft<func_6param> sb(*this); 43492 | base_func::update(v0, v1, v2, v3, v4, v5); 43493 | return this->value(base_func::expression); 43494 | } 43495 | }; 43496 | 43497 | static T return_value(expression_t& e) 43498 | { 43499 | typedef exprtk::results_context<T> results_context_t; 43500 | typedef typename results_context_t::type_store_t type_t; 43501 | typedef typename type_t::scalar_view scalar_t; 43502 | 43503 | const T result = e.value(); 43504 | 43505 | if (e.return_invoked()) 43506 | { 43507 | // Due to the post compilation checks, it can be safely 43508 | // assumed that there will be at least one parameter 43509 | // and that the first parameter will always be scalar. 43510 | return scalar_t(e.results()[0])(); 43511 | } 43512 | 43513 | return result; 43514 | } 43515 | 43516 | #define def_fp_retval(N) \ 43517 | struct func_##N##param_retval exprtk_final : public func_##N##param \ 43518 | { \ 43519 | inline T value(expression_t& e) exprtk_override \ 43520 | { \ 43521 | return return_value(e); \ 43522 | } \ 43523 | }; \ 43524 | 43525 | def_fp_retval(0) 43526 | def_fp_retval(1) 43527 | def_fp_retval(2) 43528 | def_fp_retval(3) 43529 | def_fp_retval(4) 43530 | def_fp_retval(5) 43531 | def_fp_retval(6) 43532 | 43533 | #undef def_fp_retval 43534 | 43535 | template <typename Allocator, 43536 | template <typename, typename> class Sequence> 43537 | inline bool add(const std::string& name, 43538 | const std::string& expression, 43539 | const Sequence<std::string,Allocator>& var_list, 43540 | const bool override = false) 43541 | { 43542 | const typename std::map<std::string,expression_t>::iterator itr = expr_map_.find(name); 43543 | 43544 | if (expr_map_.end() != itr) 43545 | { 43546 | if (!override) 43547 | { 43548 | exprtk_debug(("Compositor error(add): function '%s' already defined\n", 43549 | name.c_str())); 43550 | 43551 | return false; 43552 | } 43553 | 43554 | remove(name, var_list.size()); 43555 | } 43556 | 43557 | if (compile_expression(name, expression, var_list)) 43558 | { 43559 | const std::size_t n = var_list.size(); 43560 | 43561 | fp_map_[n][name]->setup(expr_map_[name]); 43562 | 43563 | return true; 43564 | } 43565 | else 43566 | { 43567 | exprtk_debug(("Compositor error(add): Failed to compile function '%s'\n", 43568 | name.c_str())); 43569 | 43570 | return false; 43571 | } 43572 | } 43573 | 43574 | public: 43575 | 43576 | function_compositor() 43577 | : parser_(settings_t::default_compile_all_opts + 43578 | settings_t::e_disable_zero_return) 43579 | , fp_map_(7) 43580 | , load_variables_(false) 43581 | , load_vectors_(false) 43582 | {} 43583 | 43584 | explicit function_compositor(const symbol_table_t& st) 43585 | : symbol_table_(st) 43586 | , parser_(settings_t::default_compile_all_opts + 43587 | settings_t::e_disable_zero_return) 43588 | , fp_map_(7) 43589 | , load_variables_(false) 43590 | , load_vectors_(false) 43591 | {} 43592 | 43593 | ~function_compositor() 43594 | { 43595 | clear(); 43596 | } 43597 | 43598 | inline symbol_table_t& symbol_table() 43599 | { 43600 | return symbol_table_; 43601 | } 43602 | 43603 | inline const symbol_table_t& symbol_table() const 43604 | { 43605 | return symbol_table_; 43606 | } 43607 | 43608 | inline void add_auxiliary_symtab(symbol_table_t& symtab) 43609 | { 43610 | auxiliary_symtab_list_.push_back(&symtab); 43611 | } 43612 | 43613 | void load_variables(const bool load = true) 43614 | { 43615 | load_variables_ = load; 43616 | } 43617 | 43618 | void load_vectors(const bool load = true) 43619 | { 43620 | load_vectors_ = load; 43621 | } 43622 | 43623 | inline void register_loop_runtime_check(loop_runtime_check& lrtchk) 43624 | { 43625 | parser_.register_loop_runtime_check(lrtchk); 43626 | } 43627 | 43628 | inline void register_vector_access_runtime_check(vector_access_runtime_check& vartchk) 43629 | { 43630 | parser_.register_vector_access_runtime_check(vartchk); 43631 | } 43632 | 43633 | inline void register_compilation_timeout_check(compilation_check& compchk) 43634 | { 43635 | parser_.register_compilation_timeout_check(compchk); 43636 | } 43637 | 43638 | inline void clear_loop_runtime_check() 43639 | { 43640 | parser_.clear_loop_runtime_check(); 43641 | } 43642 | 43643 | inline void clear_vector_access_runtime_check() 43644 | { 43645 | parser_.clear_vector_access_runtime_check(); 43646 | } 43647 | 43648 | inline void clear_compilation_timeout_check() 43649 | { 43650 | parser_.clear_compilation_timeout_check(); 43651 | } 43652 | 43653 | void clear() 43654 | { 43655 | symbol_table_.clear(); 43656 | expr_map_ .clear(); 43657 | 43658 | for (std::size_t i = 0; i < fp_map_.size(); ++i) 43659 | { 43660 | typename funcparam_t::iterator itr = fp_map_[i].begin(); 43661 | typename funcparam_t::iterator end = fp_map_[i].end (); 43662 | 43663 | while (itr != end) 43664 | { 43665 | delete itr->second; 43666 | ++itr; 43667 | } 43668 | 43669 | fp_map_[i].clear(); 43670 | } 43671 | 43672 | clear_loop_runtime_check (); 43673 | clear_vector_access_runtime_check(); 43674 | clear_compilation_timeout_check (); 43675 | } 43676 | 43677 | inline bool add(const function& f, const bool override = false) 43678 | { 43679 | return add(f.name_, f.expression_, f.v_,override); 43680 | } 43681 | 43682 | inline std::string error() const 43683 | { 43684 | if (!error_list_.empty()) 43685 | { 43686 | return error_list_[0].diagnostic; 43687 | } 43688 | else 43689 | return std::string("No Error"); 43690 | } 43691 | 43692 | inline std::size_t error_count() const 43693 | { 43694 | return error_list_.size(); 43695 | } 43696 | 43697 | inline parser_error::type get_error(const std::size_t& index) const 43698 | { 43699 | if (index < error_list_.size()) 43700 | { 43701 | return error_list_[index]; 43702 | } 43703 | 43704 | throw std::invalid_argument("compositor::get_error() - Invalid error index specified"); 43705 | } 43706 | 43707 | private: 43708 | 43709 | template <typename Allocator, 43710 | template <typename, typename> class Sequence> 43711 | bool compile_expression(const std::string& name, 43712 | const std::string& expression, 43713 | const Sequence<std::string,Allocator>& input_var_list, 43714 | bool return_present = false) 43715 | { 43716 | expression_t compiled_expression; 43717 | symbol_table_t local_symbol_table; 43718 | 43719 | local_symbol_table.load_from(symbol_table_); 43720 | local_symbol_table.add_constants(); 43721 | 43722 | if (load_variables_) 43723 | { 43724 | local_symbol_table.load_variables_from(symbol_table_); 43725 | } 43726 | 43727 | if (load_vectors_) 43728 | { 43729 | local_symbol_table.load_vectors_from(symbol_table_); 43730 | } 43731 | 43732 | error_list_.clear(); 43733 | 43734 | if (!valid(name,input_var_list.size())) 43735 | { 43736 | parser_error::type error = 43737 | parser_error::make_error( 43738 | parser_error::e_parser, 43739 | lexer::token(), 43740 | "ERR283 - Function '" + name + "' is an invalid overload", 43741 | exprtk_error_location); 43742 | 43743 | error_list_.push_back(error); 43744 | return false; 43745 | } 43746 | 43747 | if (!forward(name, 43748 | input_var_list.size(), 43749 | local_symbol_table, 43750 | return_present)) 43751 | return false; 43752 | 43753 | compiled_expression.register_symbol_table(local_symbol_table); 43754 | 43755 | for (std::size_t i = 0; i < auxiliary_symtab_list_.size(); ++i) 43756 | { 43757 | compiled_expression.register_symbol_table((*auxiliary_symtab_list_[i])); 43758 | } 43759 | 43760 | std::string mod_expression; 43761 | 43762 | for (std::size_t i = 0; i < input_var_list.size(); ++i) 43763 | { 43764 | mod_expression += " var " + input_var_list[i] + "{};\n" 43765 | } 43766 | 43767 | if ( 43768 | ('{' == details::front(expression)) && 43769 | ('}' == details::back (expression)) 43770 | ) 43771 | mod_expression += "~" + expression + "" 43772 | else 43773 | mod_expression += "~{" + expression + "};" 43774 | 43775 | if (!parser_.compile(mod_expression,compiled_expression)) 43776 | { 43777 | exprtk_debug(("Compositor Error: %s\n", parser_.error().c_str())); 43778 | exprtk_debug(("Compositor modified expression: \n%s\n", mod_expression.c_str())); 43779 | 43780 | remove(name,input_var_list.size()); 43781 | 43782 | for (std::size_t err_index = 0; err_index < parser_.error_count(); ++err_index) 43783 | { 43784 | error_list_.push_back(parser_.get_error(err_index)); 43785 | } 43786 | 43787 | return false; 43788 | } 43789 | 43790 | if (!return_present && parser_.dec().return_present()) 43791 | { 43792 | remove(name,input_var_list.size()); 43793 | return compile_expression(name, expression, input_var_list, true); 43794 | } 43795 | 43796 | // Make sure every return point has a scalar as its first parameter 43797 | if (parser_.dec().return_present()) 43798 | { 43799 | typedef std::vector<std::string> str_list_t; 43800 | 43801 | str_list_t ret_param_list = parser_.dec().return_param_type_list(); 43802 | 43803 | for (std::size_t i = 0; i < ret_param_list.size(); ++i) 43804 | { 43805 | const std::string& params = ret_param_list[i]; 43806 | 43807 | if (params.empty() || ('T' != params[0])) 43808 | { 43809 | exprtk_debug(("Compositor Error: Return statement in function '%s' is invalid\n", 43810 | name.c_str())); 43811 | 43812 | remove(name,input_var_list.size()); 43813 | 43814 | return false; 43815 | } 43816 | } 43817 | } 43818 | 43819 | expr_map_[name] = compiled_expression; 43820 | 43821 | exprtk::ifunction<T>& ifunc = (*(fp_map_[input_var_list.size()])[name]); 43822 | 43823 | if (symbol_table_.add_function(name,ifunc)) 43824 | return true; 43825 | else 43826 | { 43827 | exprtk_debug(("Compositor Error: Failed to add function '%s' to symbol table\n", 43828 | name.c_str())); 43829 | return false; 43830 | } 43831 | } 43832 | 43833 | inline bool symbol_used(const std::string& symbol) const 43834 | { 43835 | return ( 43836 | symbol_table_.is_variable (symbol) || 43837 | symbol_table_.is_stringvar (symbol) || 43838 | symbol_table_.is_function (symbol) || 43839 | symbol_table_.is_vector (symbol) || 43840 | symbol_table_.is_vararg_function(symbol) 43841 | ); 43842 | } 43843 | 43844 | inline bool valid(const std::string& name, 43845 | const std::size_t& arg_count) const 43846 | { 43847 | if (arg_count > 6) 43848 | return false; 43849 | else if (symbol_used(name)) 43850 | return false; 43851 | else if (fp_map_[arg_count].end() != fp_map_[arg_count].find(name)) 43852 | return false; 43853 | else 43854 | return true; 43855 | } 43856 | 43857 | inline bool forward(const std::string& name, 43858 | const std::size_t& arg_count, 43859 | symbol_table_t& sym_table, 43860 | const bool ret_present = false) 43861 | { 43862 | switch (arg_count) 43863 | { 43864 | #define case_stmt(N) \ 43865 | case N : (fp_map_[arg_count])[name] = \ 43866 | (!ret_present) ? static_cast<base_func*> \ 43867 | (new func_##N##param) : \ 43868 | static_cast<base_func*> \ 43869 | (new func_##N##param_retval) ; \ 43870 | break; \ 43871 | 43872 | case_stmt(0) case_stmt(1) case_stmt(2) 43873 | case_stmt(3) case_stmt(4) case_stmt(5) 43874 | case_stmt(6) 43875 | #undef case_stmt 43876 | } 43877 | 43878 | exprtk::ifunction<T>& ifunc = (*(fp_map_[arg_count])[name]); 43879 | 43880 | return sym_table.add_function(name,ifunc); 43881 | } 43882 | 43883 | inline void remove(const std::string& name, const std::size_t& arg_count) 43884 | { 43885 | if (arg_count > 6) 43886 | return; 43887 | 43888 | const typename std::map<std::string,expression_t>::iterator em_itr = expr_map_.find(name); 43889 | 43890 | if (expr_map_.end() != em_itr) 43891 | { 43892 | expr_map_.erase(em_itr); 43893 | } 43894 | 43895 | const typename funcparam_t::iterator fp_itr = fp_map_[arg_count].find(name); 43896 | 43897 | if (fp_map_[arg_count].end() != fp_itr) 43898 | { 43899 | delete fp_itr->second; 43900 | fp_map_[arg_count].erase(fp_itr); 43901 | } 43902 | 43903 | symbol_table_.remove_function(name); 43904 | } 43905 | 43906 | private: 43907 | 43908 | symbol_table_t symbol_table_; 43909 | parser_t parser_; 43910 | std::map<std::string,expression_t> expr_map_; 43911 | std::vector<funcparam_t> fp_map_; 43912 | std::vector<symbol_table_t*> auxiliary_symtab_list_; 43913 | std::deque<parser_error::type> error_list_; 43914 | bool load_variables_; 43915 | bool load_vectors_; 43916 | }; // class function_compositor 43917 | 43918 | } // namespace exprtk 43919 | 43920 | #if defined(_MSC_VER) || defined(_WIN32) || defined(__WIN32__) || defined(WIN32) 43921 | # ifndef NOMINMAX 43922 | # define NOMINMAX 43923 | # endif 43924 | # ifndef WIN32_LEAN_AND_MEAN 43925 | # define WIN32_LEAN_AND_MEAN 43926 | # endif 43927 | # include 43928 | # include 43929 | #else 43930 | # include 43931 | # include 43932 | # include 43933 | #endif 43934 | 43935 | namespace exprtk 43936 | { 43937 | class timer 43938 | { 43939 | public: 43940 | 43941 | #if defined(_MSC_VER) || defined(_WIN32) || defined(__WIN32__) || defined(WIN32) 43942 | timer() 43943 | : in_use_(false) 43944 | , start_time_{ {0, 0} } 43945 | , stop_time_ { {0, 0} } 43946 | { 43947 | QueryPerformanceFrequency(&clock_frequency_); 43948 | } 43949 | 43950 | inline void start() 43951 | { 43952 | in_use_ = true; 43953 | QueryPerformanceCounter(&start_time_); 43954 | } 43955 | 43956 | inline void stop() 43957 | { 43958 | QueryPerformanceCounter(&stop_time_); 43959 | in_use_ = false; 43960 | } 43961 | 43962 | inline double time() const 43963 | { 43964 | return (1.0 * (stop_time_.QuadPart - start_time_.QuadPart)) / (1.0 * clock_frequency_.QuadPart); 43965 | } 43966 | 43967 | #else 43968 | 43969 | timer() 43970 | : in_use_(false) 43971 | { 43972 | start_time_.tv_sec = 0; 43973 | start_time_.tv_usec = 0; 43974 | 43975 | stop_time_.tv_sec = 0; 43976 | stop_time_.tv_usec = 0; 43977 | } 43978 | 43979 | inline void start() 43980 | { 43981 | in_use_ = true; 43982 | gettimeofday(&start_time_,0); 43983 | } 43984 | 43985 | inline void stop() 43986 | { 43987 | gettimeofday(&stop_time_, 0); 43988 | in_use_ = false; 43989 | } 43990 | 43991 | inline unsigned long long int usec_time() const 43992 | { 43993 | if (!in_use_) 43994 | { 43995 | if (stop_time_.tv_sec >= start_time_.tv_sec) 43996 | { 43997 | return 1000000LLU * static_cast<details::_uint64_t>(stop_time_.tv_sec - start_time_.tv_sec ) + 43998 | static_cast<details::_uint64_t>(stop_time_.tv_usec - start_time_.tv_usec) ; 43999 | } 44000 | else 44001 | return std::numeric_limits<details::_uint64_t>::max(); 44002 | } 44003 | else 44004 | return std::numeric_limits<details::_uint64_t>::max(); 44005 | } 44006 | 44007 | inline double time() const 44008 | { 44009 | return usec_time() * 0.000001; 44010 | } 44011 | 44012 | #endif 44013 | 44014 | inline bool in_use() const 44015 | { 44016 | return in_use_; 44017 | } 44018 | 44019 | private: 44020 | 44021 | bool in_use_; 44022 | 44023 | #if defined(_MSC_VER) || defined(_WIN32) || defined(__WIN32__) || defined(WIN32) 44024 | LARGE_INTEGER start_time_; 44025 | LARGE_INTEGER stop_time_; 44026 | LARGE_INTEGER clock_frequency_; 44027 | #else 44028 | struct timeval start_time_; 44029 | struct timeval stop_time_; 44030 | #endif 44031 | }; 44032 | 44033 | template <typename T> 44034 | struct type_defs 44035 | { 44036 | typedef symbol_table<T> symbol_table_t; 44037 | typedef expression<T> expression_t; 44038 | typedef parser<T> parser_t; 44039 | typedef parser_error::type error_t; 44040 | typedef function_compositor<T> compositor_t; 44041 | typedef typename compositor_t::function function_t; 44042 | }; 44043 | 44044 | } // namespace exprtk 44045 | 44046 | #ifndef exprtk_disable_rtl_io 44047 | namespace exprtk 44048 | { 44049 | namespace rtl { namespace io { namespace details 44050 | { 44051 | template <typename T> 44052 | inline void print_type(const std::string& fmt, 44053 | const T v, 44054 | exprtk::details::numeric::details::real_type_tag) 44055 | { 44056 | #if defined(__clang__) 44057 | #pragma clang diagnostic push 44058 | #pragma clang diagnostic ignored "-Wformat-nonliteral" 44059 | #elif defined(__GNUC__) || defined(__GNUG__) 44060 | #pragma GCC diagnostic push 44061 | #pragma GCC diagnostic ignored "-Wformat-nonliteral" 44062 | #elif defined(_MSC_VER) 44063 | #endif 44064 | 44065 | printf(fmt.c_str(), v); 44066 | 44067 | #if defined(__clang__) 44068 | #pragma clang diagnostic pop 44069 | #elif defined(__GNUC__) || defined(__GNUG__) 44070 | #pragma GCC diagnostic pop 44071 | #elif defined(_MSC_VER) 44072 | #endif 44073 | } 44074 | 44075 | template <typename T> 44076 | struct print_impl 44077 | { 44078 | typedef typename igeneric_function<T>::generic_type generic_type; 44079 | typedef typename igeneric_function<T>::parameter_list_t parameter_list_t; 44080 | typedef typename generic_type::scalar_view scalar_t; 44081 | typedef typename generic_type::vector_view vector_t; 44082 | typedef typename generic_type::string_view string_t; 44083 | typedef typename exprtk::details::numeric::details::number_type<T>::type num_type; 44084 | 44085 | static void process(const std::string& scalar_format, parameter_list_t parameters) 44086 | { 44087 | for (std::size_t i = 0; i < parameters.size(); ++i) 44088 | { 44089 | generic_type& gt = parameters[i]; 44090 | 44091 | switch (gt.type) 44092 | { 44093 | case generic_type::e_scalar : print(scalar_format,scalar_t(gt)); 44094 | break; 44095 | 44096 | case generic_type::e_vector : print(scalar_format,vector_t(gt)); 44097 | break; 44098 | 44099 | case generic_type::e_string : print(string_t(gt)); 44100 | break; 44101 | 44102 | default : continue; 44103 | } 44104 | } 44105 | } 44106 | 44107 | static inline void print(const std::string& scalar_format, const scalar_t& s) 44108 | { 44109 | print_type(scalar_format,s(),num_type()); 44110 | } 44111 | 44112 | static inline void print(const std::string& scalar_format, const vector_t& v) 44113 | { 44114 | for (std::size_t i = 0; i < v.size(); ++i) 44115 | { 44116 | print_type(scalar_format,v[i],num_type()); 44117 | 44118 | if ((i + 1) < v.size()) 44119 | printf(" "); 44120 | } 44121 | } 44122 | 44123 | static inline void print(const string_t& s) 44124 | { 44125 | printf("%s",to_str(s).c_str()); 44126 | } 44127 | }; 44128 | 44129 | } // namespace exprtk::rtl::io::details 44130 | 44131 | template <typename T> 44132 | struct print exprtk_final : public exprtk::igeneric_function<T> 44133 | { 44134 | typedef typename igeneric_function<T>::parameter_list_t parameter_list_t; 44135 | 44136 | using exprtk::igeneric_function<T>::operator(); 44137 | 44138 | explicit print(const std::string& scalar_format = "%10.5f") 44139 | : scalar_format_(scalar_format) 44140 | { 44141 | exprtk::enable_zero_parameters(*this); 44142 | } 44143 | 44144 | inline T operator() (parameter_list_t parameters) exprtk_override 44145 | { 44146 | details::print_impl<T>::process(scalar_format_,parameters); 44147 | return T(0); 44148 | } 44149 | 44150 | std::string scalar_format_; 44151 | }; 44152 | 44153 | template <typename T> 44154 | struct println exprtk_final : public exprtk::igeneric_function<T> 44155 | { 44156 | typedef typename igeneric_function<T>::parameter_list_t parameter_list_t; 44157 | 44158 | using exprtk::igeneric_function<T>::operator(); 44159 | 44160 | explicit println(const std::string& scalar_format = "%10.5f") 44161 | : scalar_format_(scalar_format) 44162 | { 44163 | exprtk::enable_zero_parameters(*this); 44164 | } 44165 | 44166 | inline T operator() (parameter_list_t parameters) exprtk_override 44167 | { 44168 | details::print_impl<T>::process(scalar_format_,parameters); 44169 | printf("\n"); 44170 | return T(0); 44171 | } 44172 | 44173 | std::string scalar_format_; 44174 | }; 44175 | 44176 | template <typename T> 44177 | struct package 44178 | { 44179 | print <T> p; 44180 | println<T> pl; 44181 | 44182 | bool register_package(exprtk::symbol_table<T>& symtab) 44183 | { 44184 | #define exprtk_register_function(FunctionName, FunctionType) \ 44185 | if (!symtab.add_function(FunctionName,FunctionType)) \ 44186 | { \ 44187 | exprtk_debug(( \ 44188 | "exprtk::rtl::io::register_package - Failed to add function: %s\n", \ 44189 | FunctionName)); \ 44190 | return false; \ 44191 | } \ 44192 | 44193 | exprtk_register_function("print" , p ) 44194 | exprtk_register_function("println", pl) 44195 | #undef exprtk_register_function 44196 | 44197 | return true; 44198 | } 44199 | }; 44200 | 44201 | } // namespace exprtk::rtl::io 44202 | } // namespace exprtk::rtl 44203 | } // namespace exprtk 44204 | #endif 44205 | 44206 | #ifndef exprtk_disable_rtl_io_file 44207 | #include 44208 | namespace exprtk 44209 | { 44210 | namespace rtl { namespace io { namespace file { namespace details 44211 | { 44212 | using ::exprtk::details::char_ptr; 44213 | using ::exprtk::details::char_cptr; 44214 | 44215 | enum file_mode 44216 | { 44217 | e_error = 0, 44218 | e_read = 1, 44219 | e_write = 2, 44220 | e_rdwrt = 4 44221 | }; 44222 | 44223 | struct file_descriptor 44224 | { 44225 | file_descriptor(const std::string& fname, const std::string& access) 44226 | : stream_ptr(0) 44227 | , mode(get_file_mode(access)) 44228 | , file_name(fname) 44229 | {} 44230 | 44231 | void* stream_ptr; 44232 | file_mode mode; 44233 | std::string file_name; 44234 | 44235 | bool open() 44236 | { 44237 | if (e_read == mode) 44238 | { 44239 | std::ifstream* stream = new std::ifstream(file_name.c_str(),std::ios::binary); 44240 | 44241 | if (!(*stream)) 44242 | { 44243 | file_name.clear(); 44244 | delete stream; 44245 | 44246 | return false; 44247 | } 44248 | 44249 | stream_ptr = stream; 44250 | 44251 | return true; 44252 | } 44253 | else if (e_write == mode) 44254 | { 44255 | std::ofstream* stream = new std::ofstream(file_name.c_str(),std::ios::binary); 44256 | 44257 | if (!(*stream)) 44258 | { 44259 | file_name.clear(); 44260 | delete stream; 44261 | 44262 | return false; 44263 | } 44264 | 44265 | stream_ptr = stream; 44266 | 44267 | return true; 44268 | } 44269 | else if (e_rdwrt == mode) 44270 | { 44271 | std::fstream* stream = new std::fstream(file_name.c_str(),std::ios::binary); 44272 | 44273 | if (!(*stream)) 44274 | { 44275 | file_name.clear(); 44276 | delete stream; 44277 | 44278 | return false; 44279 | } 44280 | 44281 | stream_ptr = stream; 44282 | 44283 | return true; 44284 | } 44285 | 44286 | return false; 44287 | } 44288 | 44289 | template <typename Stream, typename Ptr> 44290 | void close(Ptr& p) 44291 | { 44292 | Stream* stream = reinterpret_cast<Stream*>(p); 44293 | stream->close(); 44294 | delete stream; 44295 | p = reinterpret_cast<Ptr>(0); 44296 | } 44297 | 44298 | bool close() 44299 | { 44300 | switch (mode) 44301 | { 44302 | case e_read : close<std::ifstream>(stream_ptr); 44303 | break; 44304 | 44305 | case e_write : close<std::ofstream>(stream_ptr); 44306 | break; 44307 | 44308 | case e_rdwrt : close<std::fstream> (stream_ptr); 44309 | break; 44310 | 44311 | default : return false; 44312 | } 44313 | 44314 | return true; 44315 | } 44316 | 44317 | template <typename View> 44318 | bool write(const View& view, const std::size_t amount, const std::size_t offset = 0) 44319 | { 44320 | switch (mode) 44321 | { 44322 | case e_write : reinterpret_cast<std::ofstream*>(stream_ptr)-> 44323 | write(reinterpret_cast<char_cptr>(view.begin() + offset), amount * sizeof(typename View::value_t)); 44324 | break; 44325 | 44326 | case e_rdwrt : reinterpret_cast<std::fstream*>(stream_ptr)-> 44327 | write(reinterpret_cast<char_cptr>(view.begin() + offset) , amount * sizeof(typename View::value_t)); 44328 | break; 44329 | 44330 | default : return false; 44331 | } 44332 | 44333 | return true; 44334 | } 44335 | 44336 | template <typename View> 44337 | bool read(View& view, const std::size_t amount, const std::size_t offset = 0) 44338 | { 44339 | switch (mode) 44340 | { 44341 | case e_read : reinterpret_cast<std::ifstream*>(stream_ptr)-> 44342 | read(reinterpret_cast<char_ptr>(view.begin() + offset), amount * sizeof(typename View::value_t)); 44343 | break; 44344 | 44345 | case e_rdwrt : reinterpret_cast<std::fstream*>(stream_ptr)-> 44346 | read(reinterpret_cast<char_ptr>(view.begin() + offset) , amount * sizeof(typename View::value_t)); 44347 | break; 44348 | 44349 | default : return false; 44350 | } 44351 | 44352 | return true; 44353 | } 44354 | 44355 | bool getline(std::string& s) 44356 | { 44357 | switch (mode) 44358 | { 44359 | case e_read : return (!!std::getline(*reinterpret_cast<std::ifstream*>(stream_ptr),s)); 44360 | case e_rdwrt : return (!!std::getline(*reinterpret_cast<std::fstream* >(stream_ptr),s)); 44361 | default : return false; 44362 | } 44363 | } 44364 | 44365 | bool eof() const 44366 | { 44367 | switch (mode) 44368 | { 44369 | case e_read : return reinterpret_cast<std::ifstream*>(stream_ptr)->eof(); 44370 | case e_write : return reinterpret_cast<std::ofstream*>(stream_ptr)->eof(); 44371 | case e_rdwrt : return reinterpret_cast<std::fstream* >(stream_ptr)->eof(); 44372 | default : return true; 44373 | } 44374 | } 44375 | 44376 | file_mode get_file_mode(const std::string& access) const 44377 | { 44378 | if (access.empty() || access.size() > 2) 44379 | return e_error; 44380 | 44381 | std::size_t w_cnt = 0; 44382 | std::size_t r_cnt = 0; 44383 | 44384 | for (std::size_t i = 0; i < access.size(); ++i) 44385 | { 44386 | switch (std::tolower(access[i])) 44387 | { 44388 | case 'r' : r_cnt++; break; 44389 | case 'w' : w_cnt++; break; 44390 | default : return e_error; 44391 | } 44392 | } 44393 | 44394 | if ((0 == r_cnt) && (0 == w_cnt)) 44395 | return e_error; 44396 | else if ((r_cnt > 1) || (w_cnt > 1)) 44397 | return e_error; 44398 | else if ((1 == r_cnt) && (1 == w_cnt)) 44399 | return e_rdwrt; 44400 | else if (1 == r_cnt) 44401 | return e_read; 44402 | else 44403 | return e_write; 44404 | } 44405 | }; 44406 | 44407 | template <typename T> 44408 | file_descriptor* make_handle(T v) 44409 | { 44410 | const std::size_t fd_size = sizeof(details::file_descriptor*); 44411 | details::file_descriptor* fd = reinterpret_cast<file_descriptor*>(0); 44412 | 44413 | std::memcpy(reinterpret_cast<char_ptr >(&fd), 44414 | reinterpret_cast<char_cptr>(&v ), 44415 | fd_size); 44416 | return fd; 44417 | } 44418 | 44419 | template <typename T> 44420 | void perform_check() 44421 | { 44422 | #ifdef _MSC_VER 44423 | #pragma warning(push) 44424 | #pragma warning(disable: 4127) 44425 | #endif 44426 | if (sizeof(T) < sizeof(void*)) 44427 | { 44428 | throw std::runtime_error("exprtk::rtl::io::file - Error - pointer size larger than holder."); 44429 | } 44430 | #ifdef _MSC_VER 44431 | #pragma warning(pop) 44432 | #endif 44433 | assert(sizeof(T) <= sizeof(void*)); 44434 | } 44435 | 44436 | } // namespace exprtk::rtl::io::file::details 44437 | 44438 | template <typename T> 44439 | class open exprtk_final : public exprtk::igeneric_function<T> 44440 | { 44441 | public: 44442 | 44443 | typedef typename exprtk::igeneric_function<T> igfun_t; 44444 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44445 | typedef typename igfun_t::generic_type generic_type; 44446 | typedef typename generic_type::string_view string_t; 44447 | 44448 | using igfun_t::operator(); 44449 | 44450 | open() 44451 | : exprtk::igeneric_function<T>("S|SS") 44452 | { details::perform_check<T>(); } 44453 | 44454 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44455 | { 44456 | const std::string file_name = to_str(string_t(parameters[0])); 44457 | 44458 | if (file_name.empty()) 44459 | { 44460 | return T(0); 44461 | } 44462 | 44463 | if ((1 == ps_index) && (0 == string_t(parameters[1]).size())) 44464 | { 44465 | return T(0); 44466 | } 44467 | 44468 | const std::string access = 44469 | (0 == ps_index) ? "r" : to_str(string_t(parameters[1])); 44470 | 44471 | details::file_descriptor* fd = new details::file_descriptor(file_name,access); 44472 | 44473 | if (fd->open()) 44474 | { 44475 | T t = T(0); 44476 | 44477 | const std::size_t fd_size = sizeof(details::file_descriptor*); 44478 | 44479 | std::memcpy(reinterpret_cast<char*>(&t ), 44480 | reinterpret_cast<char*>(&fd), 44481 | fd_size); 44482 | return t; 44483 | } 44484 | else 44485 | { 44486 | delete fd; 44487 | return T(0); 44488 | } 44489 | } 44490 | }; 44491 | 44492 | template <typename T> 44493 | struct close exprtk_final : public exprtk::ifunction<T> 44494 | { 44495 | using exprtk::ifunction<T>::operator(); 44496 | 44497 | close() 44498 | : exprtk::ifunction<T>(1) 44499 | { details::perform_check<T>(); } 44500 | 44501 | inline T operator() (const T& v) exprtk_override 44502 | { 44503 | details::file_descriptor* fd = details::make_handle(v); 44504 | 44505 | if (!fd->close()) 44506 | return T(0); 44507 | 44508 | delete fd; 44509 | 44510 | return T(1); 44511 | } 44512 | }; 44513 | 44514 | template <typename T> 44515 | class write exprtk_final : public exprtk::igeneric_function<T> 44516 | { 44517 | public: 44518 | 44519 | typedef typename exprtk::igeneric_function<T> igfun_t; 44520 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44521 | typedef typename igfun_t::generic_type generic_type; 44522 | typedef typename generic_type::string_view string_t; 44523 | typedef typename generic_type::scalar_view scalar_t; 44524 | typedef typename generic_type::vector_view vector_t; 44525 | 44526 | using igfun_t::operator(); 44527 | 44528 | write() 44529 | : igfun_t("TS|TST|TV|TVT") 44530 | { details::perform_check<T>(); } 44531 | 44532 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44533 | { 44534 | details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])()); 44535 | 44536 | switch (ps_index) 44537 | { 44538 | case 0 : { 44539 | const string_t buffer(parameters[1]); 44540 | const std::size_t amount = buffer.size(); 44541 | return T(fd->write(buffer, amount) ? 1 : 0); 44542 | } 44543 | 44544 | case 1 : { 44545 | const string_t buffer(parameters[1]); 44546 | const std::size_t amount = 44547 | std::min(buffer.size(), 44548 | static_cast<std::size_t>(scalar_t(parameters[2])())); 44549 | return T(fd->write(buffer, amount) ? 1 : 0); 44550 | } 44551 | 44552 | case 2 : { 44553 | const vector_t vec(parameters[1]); 44554 | const std::size_t amount = vec.size(); 44555 | return T(fd->write(vec, amount) ? 1 : 0); 44556 | } 44557 | 44558 | case 3 : { 44559 | const vector_t vec(parameters[1]); 44560 | const std::size_t amount = 44561 | std::min(vec.size(), 44562 | static_cast<std::size_t>(scalar_t(parameters[2])())); 44563 | return T(fd->write(vec, amount) ? 1 : 0); 44564 | } 44565 | } 44566 | 44567 | return T(0); 44568 | } 44569 | }; 44570 | 44571 | template <typename T> 44572 | class read exprtk_final : public exprtk::igeneric_function<T> 44573 | { 44574 | public: 44575 | 44576 | typedef typename exprtk::igeneric_function<T> igfun_t; 44577 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44578 | typedef typename igfun_t::generic_type generic_type; 44579 | typedef typename generic_type::string_view string_t; 44580 | typedef typename generic_type::scalar_view scalar_t; 44581 | typedef typename generic_type::vector_view vector_t; 44582 | 44583 | using igfun_t::operator(); 44584 | 44585 | read() 44586 | : igfun_t("TS|TST|TV|TVT") 44587 | { details::perform_check<T>(); } 44588 | 44589 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44590 | { 44591 | details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])()); 44592 | 44593 | switch (ps_index) 44594 | { 44595 | case 0 : { 44596 | string_t buffer(parameters[1]); 44597 | const std::size_t amount = buffer.size(); 44598 | return T(fd->read(buffer,amount) ? 1 : 0); 44599 | } 44600 | 44601 | case 1 : { 44602 | string_t buffer(parameters[1]); 44603 | const std::size_t amount = 44604 | std::min(buffer.size(), 44605 | static_cast<std::size_t>(scalar_t(parameters[2])())); 44606 | return T(fd->read(buffer,amount) ? 1 : 0); 44607 | } 44608 | 44609 | case 2 : { 44610 | vector_t vec(parameters[1]); 44611 | const std::size_t amount = vec.size(); 44612 | return T(fd->read(vec,amount) ? 1 : 0); 44613 | } 44614 | 44615 | case 3 : { 44616 | vector_t vec(parameters[1]); 44617 | const std::size_t amount = 44618 | std::min(vec.size(), 44619 | static_cast<std::size_t>(scalar_t(parameters[2])())); 44620 | return T(fd->read(vec,amount) ? 1 : 0); 44621 | } 44622 | } 44623 | 44624 | return T(0); 44625 | } 44626 | }; 44627 | 44628 | template <typename T> 44629 | class getline exprtk_final : public exprtk::igeneric_function<T> 44630 | { 44631 | public: 44632 | 44633 | typedef typename exprtk::igeneric_function<T> igfun_t; 44634 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44635 | typedef typename igfun_t::generic_type generic_type; 44636 | typedef typename generic_type::string_view string_t; 44637 | typedef typename generic_type::scalar_view scalar_t; 44638 | 44639 | using igfun_t::operator(); 44640 | 44641 | getline() 44642 | : igfun_t("T",igfun_t::e_rtrn_string) 44643 | { details::perform_check<T>(); } 44644 | 44645 | inline T operator() (std::string& result, parameter_list_t parameters) exprtk_override 44646 | { 44647 | details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])()); 44648 | return T(fd->getline(result) ? 1 : 0); 44649 | } 44650 | }; 44651 | 44652 | template <typename T> 44653 | struct eof exprtk_final : public exprtk::ifunction<T> 44654 | { 44655 | using exprtk::ifunction<T>::operator(); 44656 | 44657 | eof() 44658 | : exprtk::ifunction<T>(1) 44659 | { details::perform_check<T>(); } 44660 | 44661 | inline T operator() (const T& v) exprtk_override 44662 | { 44663 | details::file_descriptor* fd = details::make_handle(v); 44664 | return (fd->eof() ? T(1) : T(0)); 44665 | } 44666 | }; 44667 | 44668 | template <typename T> 44669 | struct package 44670 | { 44671 | open <T> o; 44672 | close <T> c; 44673 | write <T> w; 44674 | read <T> r; 44675 | getline<T> g; 44676 | eof <T> e; 44677 | 44678 | bool register_package(exprtk::symbol_table<T>& symtab) 44679 | { 44680 | #define exprtk_register_function(FunctionName, FunctionType) \ 44681 | if (!symtab.add_function(FunctionName,FunctionType)) \ 44682 | { \ 44683 | exprtk_debug(( \ 44684 | "exprtk::rtl::io::file::register_package - Failed to add function: %s\n", \ 44685 | FunctionName)); \ 44686 | return false; \ 44687 | } \ 44688 | 44689 | exprtk_register_function("open" , o) 44690 | exprtk_register_function("close" , c) 44691 | exprtk_register_function("write" , w) 44692 | exprtk_register_function("read" , r) 44693 | exprtk_register_function("getline" , g) 44694 | exprtk_register_function("eof" , e) 44695 | #undef exprtk_register_function 44696 | 44697 | return true; 44698 | } 44699 | }; 44700 | 44701 | } // namespace exprtk::rtl::io::file 44702 | } // namespace exprtk::rtl::io 44703 | } // namespace exprtk::rtl 44704 | } // namespace exprtk 44705 | #endif 44706 | 44707 | #ifndef exprtk_disable_rtl_vecops 44708 | namespace exprtk 44709 | { 44710 | namespace rtl { namespace vecops { 44711 | 44712 | namespace helper 44713 | { 44714 | template <typename Vector> 44715 | inline bool invalid_range(const Vector& v, const std::size_t r0, const std::size_t r1) 44716 | { 44717 | if (r0 > (v.size() - 1)) 44718 | return true; 44719 | else if (r1 > (v.size() - 1)) 44720 | return true; 44721 | else if (r1 < r0) 44722 | return true; 44723 | else 44724 | return false; 44725 | } 44726 | 44727 | template <typename T> 44728 | struct load_vector_range 44729 | { 44730 | typedef typename exprtk::igeneric_function<T> igfun_t; 44731 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44732 | typedef typename igfun_t::generic_type generic_type; 44733 | typedef typename generic_type::scalar_view scalar_t; 44734 | typedef typename generic_type::vector_view vector_t; 44735 | 44736 | static inline bool process(parameter_list_t& parameters, 44737 | std::size_t& r0, std::size_t& r1, 44738 | const std::size_t& r0_prmidx, 44739 | const std::size_t& r1_prmidx, 44740 | const std::size_t vec_idx = 0) 44741 | { 44742 | if (r0_prmidx >= parameters.size()) 44743 | return false; 44744 | 44745 | if (r1_prmidx >= parameters.size()) 44746 | return false; 44747 | 44748 | if (!scalar_t(parameters[r0_prmidx]).to_uint(r0)) 44749 | return false; 44750 | 44751 | if (!scalar_t(parameters[r1_prmidx]).to_uint(r1)) 44752 | return false; 44753 | 44754 | return !invalid_range(vector_t(parameters[vec_idx]), r0, r1); 44755 | } 44756 | }; 44757 | } 44758 | 44759 | namespace details 44760 | { 44761 | template <typename T> 44762 | inline void kahan_sum(T& sum, T& error, const T v) 44763 | { 44764 | const T x = v - error; 44765 | const T y = sum + x; 44766 | error = (y - sum) - x; 44767 | sum = y; 44768 | } 44769 | 44770 | } // namespace exprtk::rtl::details 44771 | 44772 | template <typename T> 44773 | class all_true exprtk_final : public exprtk::igeneric_function<T> 44774 | { 44775 | public: 44776 | 44777 | typedef typename exprtk::igeneric_function<T> igfun_t; 44778 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44779 | typedef typename igfun_t::generic_type generic_type; 44780 | typedef typename generic_type::scalar_view scalar_t; 44781 | typedef typename generic_type::vector_view vector_t; 44782 | 44783 | using igfun_t::operator(); 44784 | 44785 | all_true() 44786 | : exprtk::igeneric_function<T>("V|VTT|T*") 44787 | /* 44788 | Overloads: 44789 | 0. V - vector 44790 | 1. VTT - vector, r0, r1 44791 | 2. T* - T....T 44792 | */ 44793 | {} 44794 | 44795 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44796 | { 44797 | if (2 == ps_index) 44798 | { 44799 | for (std::size_t i = 0; i < parameters.size(); ++i) 44800 | { 44801 | if (scalar_t(parameters[i])() == T(0)) 44802 | { 44803 | return T(0); 44804 | } 44805 | } 44806 | } 44807 | else 44808 | { 44809 | const vector_t vec(parameters[0]); 44810 | 44811 | std::size_t r0 = 0; 44812 | std::size_t r1 = vec.size() - 1; 44813 | 44814 | if ( 44815 | (1 == ps_index) && 44816 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 44817 | ) 44818 | { 44819 | return std::numeric_limits<T>::quiet_NaN(); 44820 | } 44821 | 44822 | for (std::size_t i = r0; i <= r1; ++i) 44823 | { 44824 | if (vec[i] == T(0)) 44825 | { 44826 | return T(0); 44827 | } 44828 | } 44829 | } 44830 | 44831 | return T(1); 44832 | } 44833 | }; 44834 | 44835 | template <typename T> 44836 | class all_false exprtk_final : public exprtk::igeneric_function<T> 44837 | { 44838 | public: 44839 | 44840 | typedef typename exprtk::igeneric_function<T> igfun_t; 44841 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44842 | typedef typename igfun_t::generic_type generic_type; 44843 | typedef typename generic_type::scalar_view scalar_t; 44844 | typedef typename generic_type::vector_view vector_t; 44845 | 44846 | using igfun_t::operator(); 44847 | 44848 | all_false() 44849 | : exprtk::igeneric_function<T>("V|VTT|T*") 44850 | /* 44851 | Overloads: 44852 | 0. V - vector 44853 | 1. VTT - vector, r0, r1 44854 | 2. T* - T....T 44855 | */ 44856 | {} 44857 | 44858 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44859 | { 44860 | if (2 == ps_index) 44861 | { 44862 | for (std::size_t i = 0; i < parameters.size(); ++i) 44863 | { 44864 | if (scalar_t(parameters[i])() != T(0)) 44865 | { 44866 | return T(0); 44867 | } 44868 | } 44869 | } 44870 | else 44871 | { 44872 | const vector_t vec(parameters[0]); 44873 | 44874 | std::size_t r0 = 0; 44875 | std::size_t r1 = vec.size() - 1; 44876 | 44877 | if ( 44878 | (1 == ps_index) && 44879 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 44880 | ) 44881 | { 44882 | return std::numeric_limits<T>::quiet_NaN(); 44883 | } 44884 | 44885 | for (std::size_t i = r0; i <= r1; ++i) 44886 | { 44887 | if (vec[i] != T(0)) 44888 | { 44889 | return T(0); 44890 | } 44891 | } 44892 | } 44893 | 44894 | return T(1); 44895 | } 44896 | }; 44897 | 44898 | template <typename T> 44899 | class any_true exprtk_final : public exprtk::igeneric_function<T> 44900 | { 44901 | public: 44902 | 44903 | typedef typename exprtk::igeneric_function<T> igfun_t; 44904 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44905 | typedef typename igfun_t::generic_type generic_type; 44906 | typedef typename generic_type::scalar_view scalar_t; 44907 | typedef typename generic_type::vector_view vector_t; 44908 | 44909 | using igfun_t::operator(); 44910 | 44911 | any_true() 44912 | : exprtk::igeneric_function<T>("V|VTT|T*") 44913 | /* 44914 | Overloads: 44915 | 0. V - vector 44916 | 1. VTT - vector, r0, r1 44917 | 2. T* - T....T 44918 | */ 44919 | {} 44920 | 44921 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44922 | { 44923 | if (2 == ps_index) 44924 | { 44925 | for (std::size_t i = 0; i < parameters.size(); ++i) 44926 | { 44927 | if (scalar_t(parameters[i])() != T(0)) 44928 | { 44929 | return T(1); 44930 | } 44931 | } 44932 | } 44933 | else 44934 | { 44935 | const vector_t vec(parameters[0]); 44936 | 44937 | std::size_t r0 = 0; 44938 | std::size_t r1 = vec.size() - 1; 44939 | 44940 | if ( 44941 | (1 == ps_index) && 44942 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 44943 | ) 44944 | { 44945 | return std::numeric_limits<T>::quiet_NaN(); 44946 | } 44947 | 44948 | for (std::size_t i = r0; i <= r1; ++i) 44949 | { 44950 | if (vec[i] != T(0)) 44951 | { 44952 | return T(1); 44953 | } 44954 | } 44955 | } 44956 | 44957 | return T(0); 44958 | } 44959 | }; 44960 | 44961 | template <typename T> 44962 | class any_false exprtk_final : public exprtk::igeneric_function<T> 44963 | { 44964 | public: 44965 | 44966 | typedef typename exprtk::igeneric_function<T> igfun_t; 44967 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44968 | typedef typename igfun_t::generic_type generic_type; 44969 | typedef typename generic_type::scalar_view scalar_t; 44970 | typedef typename generic_type::vector_view vector_t; 44971 | 44972 | using igfun_t::operator(); 44973 | 44974 | any_false() 44975 | : exprtk::igeneric_function<T>("V|VTT|T*") 44976 | /* 44977 | Overloads: 44978 | 0. V - vector 44979 | 1. VTT - vector, r0, r1 44980 | 2. T* - T....T 44981 | */ 44982 | {} 44983 | 44984 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44985 | { 44986 | if (2 == ps_index) 44987 | { 44988 | for (std::size_t i = 0; i < parameters.size(); ++i) 44989 | { 44990 | if (scalar_t(parameters[i])() == T(0)) 44991 | { 44992 | return T(1); 44993 | } 44994 | } 44995 | } 44996 | else 44997 | { 44998 | const vector_t vec(parameters[0]); 44999 | 45000 | std::size_t r0 = 0; 45001 | std::size_t r1 = vec.size() - 1; 45002 | 45003 | if ( 45004 | (1 == ps_index) && 45005 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 45006 | ) 45007 | { 45008 | return std::numeric_limits<T>::quiet_NaN(); 45009 | } 45010 | 45011 | for (std::size_t i = r0; i <= r1; ++i) 45012 | { 45013 | if (vec[i] == T(0)) 45014 | { 45015 | return T(1); 45016 | } 45017 | } 45018 | } 45019 | 45020 | return T(0); 45021 | } 45022 | }; 45023 | 45024 | template <typename T> 45025 | class count exprtk_final : public exprtk::igeneric_function<T> 45026 | { 45027 | public: 45028 | 45029 | typedef typename exprtk::igeneric_function<T> igfun_t; 45030 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45031 | typedef typename igfun_t::generic_type generic_type; 45032 | typedef typename generic_type::scalar_view scalar_t; 45033 | typedef typename generic_type::vector_view vector_t; 45034 | 45035 | using igfun_t::operator(); 45036 | 45037 | count() 45038 | : exprtk::igeneric_function<T>("V|VTT|T*") 45039 | /* 45040 | Overloads: 45041 | 0. V - vector 45042 | 1. VTT - vector, r0, r1 45043 | 2. T* - T....T 45044 | */ 45045 | {} 45046 | 45047 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45048 | { 45049 | std::size_t cnt = 0; 45050 | 45051 | if (2 == ps_index) 45052 | { 45053 | for (std::size_t i = 0; i < parameters.size(); ++i) 45054 | { 45055 | if (scalar_t(parameters[i])() != T(0)) ++cnt; 45056 | } 45057 | } 45058 | else 45059 | { 45060 | const vector_t vec(parameters[0]); 45061 | 45062 | std::size_t r0 = 0; 45063 | std::size_t r1 = vec.size() - 1; 45064 | 45065 | if ( 45066 | (1 == ps_index) && 45067 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 45068 | ) 45069 | { 45070 | return std::numeric_limits<T>::quiet_NaN(); 45071 | } 45072 | 45073 | for (std::size_t i = r0; i <= r1; ++i) 45074 | { 45075 | if (vec[i] != T(0)) ++cnt; 45076 | } 45077 | } 45078 | 45079 | return T(cnt); 45080 | } 45081 | }; 45082 | 45083 | template <typename T> 45084 | class copy exprtk_final : public exprtk::igeneric_function<T> 45085 | { 45086 | public: 45087 | 45088 | typedef typename exprtk::igeneric_function<T> igfun_t; 45089 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45090 | typedef typename igfun_t::generic_type generic_type; 45091 | typedef typename generic_type::scalar_view scalar_t; 45092 | typedef typename generic_type::vector_view vector_t; 45093 | 45094 | using igfun_t::operator(); 45095 | 45096 | copy() 45097 | : exprtk::igeneric_function<T>("VV|VTTVTT") 45098 | /* 45099 | Overloads: 45100 | 0. VV - x(vector), y(vector) 45101 | 1. VTTVTT - x(vector), xr0, xr1, y(vector), yr0, yr1, 45102 | */ 45103 | {} 45104 | 45105 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45106 | { 45107 | const vector_t x(parameters[0]); 45108 | vector_t y(parameters[(0 == ps_index) ? 1 : 3]); 45109 | 45110 | std::size_t xr0 = 0; 45111 | std::size_t xr1 = x.size() - 1; 45112 | 45113 | std::size_t yr0 = 0; 45114 | std::size_t yr1 = y.size() - 1; 45115 | 45116 | if (1 == ps_index) 45117 | { 45118 | if ( 45119 | !helper::load_vector_range<T>::process(parameters, xr0, xr1, 1, 2, 0) || 45120 | !helper::load_vector_range<T>::process(parameters, yr0, yr1, 4, 5, 3) 45121 | ) 45122 | return T(0); 45123 | } 45124 | 45125 | const std::size_t n = std::min(xr1 - xr0 + 1, yr1 - yr0 + 1); 45126 | 45127 | std::copy( 45128 | x.begin() + xr0, 45129 | x.begin() + xr0 + n, 45130 | y.begin() + yr0); 45131 | 45132 | return T(n); 45133 | } 45134 | }; 45135 | 45136 | template <typename T> 45137 | class rol exprtk_final : public exprtk::igeneric_function<T> 45138 | { 45139 | public: 45140 | 45141 | typedef typename exprtk::igeneric_function<T> igfun_t; 45142 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45143 | typedef typename igfun_t::generic_type generic_type; 45144 | typedef typename generic_type::scalar_view scalar_t; 45145 | typedef typename generic_type::vector_view vector_t; 45146 | 45147 | using igfun_t::operator(); 45148 | 45149 | rol() 45150 | : exprtk::igeneric_function<T>("VT|VTTT") 45151 | /* 45152 | Overloads: 45153 | 0. VT - vector, N 45154 | 1. VTTT - vector, N, r0, r1 45155 | */ 45156 | {} 45157 | 45158 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45159 | { 45160 | vector_t vec(parameters[0]); 45161 | 45162 | std::size_t n = 0; 45163 | std::size_t r0 = 0; 45164 | std::size_t r1 = vec.size() - 1; 45165 | 45166 | if (!scalar_t(parameters[1]).to_uint(n)) 45167 | return T(0); 45168 | 45169 | if ( 45170 | (1 == ps_index) && 45171 | !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0) 45172 | ) 45173 | return T(0); 45174 | 45175 | const std::size_t dist = r1 - r0 + 1; 45176 | const std::size_t shift = n % dist; 45177 | 45178 | std::rotate( 45179 | vec.begin() + r0, 45180 | vec.begin() + r0 + shift, 45181 | vec.begin() + r1 + 1); 45182 | 45183 | return T(1); 45184 | } 45185 | }; 45186 | 45187 | template <typename T> 45188 | class ror exprtk_final : public exprtk::igeneric_function<T> 45189 | { 45190 | public: 45191 | 45192 | typedef typename exprtk::igeneric_function<T> igfun_t; 45193 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45194 | typedef typename igfun_t::generic_type generic_type; 45195 | typedef typename generic_type::scalar_view scalar_t; 45196 | typedef typename generic_type::vector_view vector_t; 45197 | 45198 | using igfun_t::operator(); 45199 | 45200 | ror() 45201 | : exprtk::igeneric_function<T>("VT|VTTT") 45202 | /* 45203 | Overloads: 45204 | 0. VT - vector, N 45205 | 1. VTTT - vector, N, r0, r1 45206 | */ 45207 | {} 45208 | 45209 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45210 | { 45211 | vector_t vec(parameters[0]); 45212 | 45213 | std::size_t n = 0; 45214 | std::size_t r0 = 0; 45215 | std::size_t r1 = vec.size() - 1; 45216 | 45217 | if (!scalar_t(parameters[1]).to_uint(n)) 45218 | return T(0); 45219 | 45220 | if ( 45221 | (1 == ps_index) && 45222 | !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0) 45223 | ) 45224 | return T(0); 45225 | 45226 | const std::size_t dist = r1 - r0 + 1; 45227 | const std::size_t shift = (dist - (n % dist)) % dist; 45228 | 45229 | std::rotate( 45230 | vec.begin() + r0, 45231 | vec.begin() + r0 + shift, 45232 | vec.begin() + r1 + 1); 45233 | 45234 | return T(1); 45235 | } 45236 | }; 45237 | 45238 | template <typename T> 45239 | class reverse exprtk_final : public exprtk::igeneric_function<T> 45240 | { 45241 | public: 45242 | 45243 | typedef typename exprtk::igeneric_function<T> igfun_t; 45244 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45245 | typedef typename igfun_t::generic_type generic_type; 45246 | typedef typename generic_type::scalar_view scalar_t; 45247 | typedef typename generic_type::vector_view vector_t; 45248 | 45249 | using igfun_t::operator(); 45250 | 45251 | reverse() 45252 | : exprtk::igeneric_function<T>("V|VTT") 45253 | /* 45254 | Overloads: 45255 | 0. V - vector 45256 | 1. VTT - vector, r0, r1 45257 | */ 45258 | {} 45259 | 45260 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45261 | { 45262 | vector_t vec(parameters[0]); 45263 | 45264 | std::size_t r0 = 0; 45265 | std::size_t r1 = vec.size() - 1; 45266 | 45267 | if ( 45268 | (1 == ps_index) && 45269 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 45270 | ) 45271 | return T(0); 45272 | 45273 | std::reverse(vec.begin() + r0, vec.begin() + r1 + 1); 45274 | 45275 | return T(1); 45276 | } 45277 | }; 45278 | 45279 | template <typename T> 45280 | class shift_left exprtk_final : public exprtk::igeneric_function<T> 45281 | { 45282 | public: 45283 | 45284 | typedef typename exprtk::igeneric_function<T> igfun_t; 45285 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45286 | typedef typename igfun_t::generic_type generic_type; 45287 | typedef typename generic_type::scalar_view scalar_t; 45288 | typedef typename generic_type::vector_view vector_t; 45289 | 45290 | using igfun_t::operator(); 45291 | 45292 | shift_left() 45293 | : exprtk::igeneric_function<T>("VT|VTTT") 45294 | /* 45295 | Overloads: 45296 | 0. VT - vector, N 45297 | 1. VTTT - vector, N, r0, r1 45298 | */ 45299 | {} 45300 | 45301 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45302 | { 45303 | vector_t vec(parameters[0]); 45304 | 45305 | std::size_t n = 0; 45306 | std::size_t r0 = 0; 45307 | std::size_t r1 = vec.size() - 1; 45308 | 45309 | if (!scalar_t(parameters[1]).to_uint(n)) 45310 | return T(0); 45311 | 45312 | if ( 45313 | (1 == ps_index) && 45314 | !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0) 45315 | ) 45316 | return T(0); 45317 | 45318 | const std::size_t dist = r1 - r0 + 1; 45319 | 45320 | if (n > dist) 45321 | return T(0); 45322 | 45323 | std::rotate( 45324 | vec.begin() + r0, 45325 | vec.begin() + r0 + n, 45326 | vec.begin() + r1 + 1); 45327 | 45328 | for (std::size_t i = r1 - n + 1ULL; i <= r1; ++i) 45329 | { 45330 | vec[i] = T(0); 45331 | } 45332 | 45333 | return T(1); 45334 | } 45335 | }; 45336 | 45337 | template <typename T> 45338 | class shift_right exprtk_final : public exprtk::igeneric_function<T> 45339 | { 45340 | public: 45341 | 45342 | typedef typename exprtk::igeneric_function<T> igfun_t; 45343 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45344 | typedef typename igfun_t::generic_type generic_type; 45345 | typedef typename generic_type::scalar_view scalar_t; 45346 | typedef typename generic_type::vector_view vector_t; 45347 | 45348 | using igfun_t::operator(); 45349 | 45350 | shift_right() 45351 | : exprtk::igeneric_function<T>("VT|VTTT") 45352 | /* 45353 | Overloads: 45354 | 0. VT - vector, N 45355 | 1. VTTT - vector, N, r0, r1 45356 | */ 45357 | {} 45358 | 45359 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45360 | { 45361 | vector_t vec(parameters[0]); 45362 | 45363 | std::size_t n = 0; 45364 | std::size_t r0 = 0; 45365 | std::size_t r1 = vec.size() - 1; 45366 | 45367 | if (!scalar_t(parameters[1]).to_uint(n)) 45368 | return T(0); 45369 | 45370 | if ( 45371 | (1 == ps_index) && 45372 | !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0) 45373 | ) 45374 | return T(0); 45375 | 45376 | const std::size_t dist = r1 - r0 + 1; 45377 | 45378 | if (n > dist) 45379 | return T(0); 45380 | 45381 | const std::size_t shift = (dist - (n % dist)) % dist; 45382 | 45383 | std::rotate( 45384 | vec.begin() + r0, 45385 | vec.begin() + r0 + shift, 45386 | vec.begin() + r1 + 1); 45387 | 45388 | for (std::size_t i = r0; i < r0 + n; ++i) 45389 | { 45390 | vec[i] = T(0); 45391 | } 45392 | 45393 | return T(1); 45394 | } 45395 | }; 45396 | 45397 | template <typename T> 45398 | class sort exprtk_final : public exprtk::igeneric_function<T> 45399 | { 45400 | public: 45401 | 45402 | typedef typename exprtk::igeneric_function<T> igfun_t; 45403 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45404 | typedef typename igfun_t::generic_type generic_type; 45405 | typedef typename generic_type::string_view string_t; 45406 | typedef typename generic_type::vector_view vector_t; 45407 | 45408 | using igfun_t::operator(); 45409 | 45410 | sort() 45411 | : exprtk::igeneric_function<T>("V|VTT|VS|VSTT") 45412 | /* 45413 | Overloads: 45414 | 0. V - vector 45415 | 1. VTT - vector, r0, r1 45416 | 2. VS - vector, string 45417 | 3. VSTT - vector, string, r0, r1 45418 | */ 45419 | {} 45420 | 45421 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45422 | { 45423 | vector_t vec(parameters[0]); 45424 | 45425 | std::size_t r0 = 0; 45426 | std::size_t r1 = vec.size() - 1; 45427 | 45428 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)) 45429 | return T(0); 45430 | if ((3 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)) 45431 | return T(0); 45432 | 45433 | bool ascending = true; 45434 | 45435 | if ((2 == ps_index) || (3 == ps_index)) 45436 | { 45437 | if (exprtk::details::imatch(to_str(string_t(parameters[1])),"ascending")) 45438 | ascending = true; 45439 | else if (exprtk::details::imatch(to_str(string_t(parameters[1])),"descending")) 45440 | ascending = false; 45441 | else 45442 | return T(0); 45443 | } 45444 | 45445 | if (ascending) 45446 | std::sort( 45447 | vec.begin() + r0, 45448 | vec.begin() + r1 + 1, 45449 | std::less<T>()); 45450 | else 45451 | std::sort( 45452 | vec.begin() + r0, 45453 | vec.begin() + r1 + 1, 45454 | std::greater<T>()); 45455 | 45456 | return T(1); 45457 | } 45458 | }; 45459 | 45460 | template <typename T> 45461 | class nthelement exprtk_final : public exprtk::igeneric_function<T> 45462 | { 45463 | public: 45464 | 45465 | typedef typename exprtk::igeneric_function<T> igfun_t; 45466 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45467 | typedef typename igfun_t::generic_type generic_type; 45468 | typedef typename generic_type::scalar_view scalar_t; 45469 | typedef typename generic_type::vector_view vector_t; 45470 | 45471 | using igfun_t::operator(); 45472 | 45473 | nthelement() 45474 | : exprtk::igeneric_function<T>("VT|VTTT") 45475 | /* 45476 | Overloads: 45477 | 0. VT - vector, nth-element 45478 | 1. VTTT - vector, nth-element, r0, r1 45479 | */ 45480 | {} 45481 | 45482 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45483 | { 45484 | vector_t vec(parameters[0]); 45485 | 45486 | std::size_t n = 0; 45487 | std::size_t r0 = 0; 45488 | std::size_t r1 = vec.size() - 1; 45489 | 45490 | if (!scalar_t(parameters[1]).to_uint(n)) 45491 | return T(0); 45492 | 45493 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)) 45494 | { 45495 | return std::numeric_limits<T>::quiet_NaN(); 45496 | } 45497 | 45498 | std::nth_element( 45499 | vec.begin() + r0, 45500 | vec.begin() + r0 + n , 45501 | vec.begin() + r1 + 1); 45502 | 45503 | return T(1); 45504 | } 45505 | }; 45506 | 45507 | template <typename T> 45508 | class assign exprtk_final : public exprtk::igeneric_function<T> 45509 | { 45510 | public: 45511 | 45512 | typedef typename exprtk::igeneric_function<T> igfun_t; 45513 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45514 | typedef typename igfun_t::generic_type generic_type; 45515 | typedef typename generic_type::scalar_view scalar_t; 45516 | typedef typename generic_type::vector_view vector_t; 45517 | 45518 | using igfun_t::operator(); 45519 | 45520 | assign() 45521 | : exprtk::igeneric_function<T>("VT|VTTT|VTTTT") 45522 | /* 45523 | Overloads: 45524 | 0. VT - vector, V 45525 | 1. VTTT - vector, V, r0, r1 45526 | 2. VTTTT - vector, V, r0, r1, SS 45527 | */ 45528 | {} 45529 | 45530 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45531 | { 45532 | vector_t vec(parameters[0]); 45533 | 45534 | const T assign_value = scalar_t(parameters[1]); 45535 | 45536 | const std::size_t step_size = (2 != ps_index) ? 1 : 45537 | static_cast<std::size_t>(scalar_t(parameters.back())()); 45538 | 45539 | std::size_t r0 = 0; 45540 | std::size_t r1 = vec.size() - 1; 45541 | 45542 | if ( 45543 | ((ps_index == 1) || (ps_index == 2)) && 45544 | !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0) 45545 | ) 45546 | { 45547 | return T(0); 45548 | } 45549 | 45550 | for (std::size_t i = r0; i <= r1; i += step_size) 45551 | { 45552 | vec[i] = assign_value; 45553 | } 45554 | 45555 | return T(1); 45556 | } 45557 | }; 45558 | 45559 | template <typename T> 45560 | class iota exprtk_final : public exprtk::igeneric_function<T> 45561 | { 45562 | public: 45563 | 45564 | typedef typename exprtk::igeneric_function<T> igfun_t; 45565 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45566 | typedef typename igfun_t::generic_type generic_type; 45567 | typedef typename generic_type::scalar_view scalar_t; 45568 | typedef typename generic_type::vector_view vector_t; 45569 | 45570 | using igfun_t::operator(); 45571 | 45572 | iota() 45573 | : exprtk::igeneric_function<T>("VTT|VT|VTTTT|VTTT") 45574 | /* 45575 | Overloads: 45576 | 0. VTT - vector, SV, SS 45577 | 1. VT - vector, SV, SS (+1) 45578 | 2. VTTT - vector, r0, r1, SV, SS 45579 | 3. VTT - vector, r0, r1, SV, SS (+1) 45580 | 45581 | Where: 45582 | 1. SV - Start value 45583 | 2. SS - Step size 45584 | */ 45585 | {} 45586 | 45587 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45588 | { 45589 | vector_t vec(parameters[0]); 45590 | 45591 | const T start_value = (ps_index <= 1) ? 45592 | scalar_t(parameters[1]) : 45593 | scalar_t(parameters[3]) ; 45594 | 45595 | const T step_size = ((0 == ps_index) || (2 == ps_index)) ? 45596 | scalar_t(parameters.back())() : 45597 | T(1) ; 45598 | 45599 | std::size_t r0 = 0; 45600 | std::size_t r1 = vec.size() - 1; 45601 | 45602 | if ( 45603 | ((ps_index == 2) || (ps_index == 3)) && 45604 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 45605 | ) 45606 | { 45607 | return T(0); 45608 | } 45609 | 45610 | for (std::size_t i = r0; i <= r1; ++i) 45611 | { 45612 | vec[i] = start_value + ((i - r0) * step_size); 45613 | } 45614 | 45615 | return T(1); 45616 | } 45617 | }; 45618 | 45619 | template <typename T> 45620 | class sumk exprtk_final : public exprtk::igeneric_function<T> 45621 | { 45622 | public: 45623 | 45624 | typedef typename exprtk::igeneric_function<T> igfun_t; 45625 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45626 | typedef typename igfun_t::generic_type generic_type; 45627 | typedef typename generic_type::scalar_view scalar_t; 45628 | typedef typename generic_type::vector_view vector_t; 45629 | 45630 | using igfun_t::operator(); 45631 | 45632 | sumk() 45633 | : exprtk::igeneric_function<T>("V|VTT|VTTT") 45634 | /* 45635 | Overloads: 45636 | 0. V - vector 45637 | 1. VTT - vector, r0, r1 45638 | 2. VTTT - vector, r0, r1, stride 45639 | */ 45640 | {} 45641 | 45642 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45643 | { 45644 | const vector_t vec(parameters[0]); 45645 | 45646 | const std::size_t stride = (2 != ps_index) ? 1 : 45647 | static_cast<std::size_t>(scalar_t(parameters[3])()); 45648 | 45649 | std::size_t r0 = 0; 45650 | std::size_t r1 = vec.size() - 1; 45651 | 45652 | if ( 45653 | ((1 == ps_index) || (2 == ps_index)) && 45654 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 45655 | ) 45656 | { 45657 | return std::numeric_limits<T>::quiet_NaN(); 45658 | } 45659 | 45660 | T result = T(0); 45661 | T error = T(0); 45662 | 45663 | for (std::size_t i = r0; i <= r1; i += stride) 45664 | { 45665 | details::kahan_sum(result, error, vec[i]); 45666 | } 45667 | 45668 | return result; 45669 | } 45670 | }; 45671 | 45672 | template <typename T> 45673 | class axpy exprtk_final : public exprtk::igeneric_function<T> 45674 | { 45675 | public: 45676 | 45677 | typedef typename exprtk::igeneric_function<T> igfun_t; 45678 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45679 | typedef typename igfun_t::generic_type generic_type; 45680 | typedef typename generic_type::scalar_view scalar_t; 45681 | typedef typename generic_type::vector_view vector_t; 45682 | 45683 | using igfun_t::operator(); 45684 | 45685 | axpy() 45686 | : exprtk::igeneric_function<T>("TVV|TVVTT") 45687 | /* 45688 | y <- ax + y 45689 | Overloads: 45690 | 0. TVV - a, x(vector), y(vector) 45691 | 1. TVVTT - a, x(vector), y(vector), r0, r1 45692 | */ 45693 | {} 45694 | 45695 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45696 | { 45697 | const vector_t x(parameters[1]); 45698 | vector_t y(parameters[2]); 45699 | 45700 | std::size_t r0 = 0; 45701 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 45702 | 45703 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 3, 4, 1)) 45704 | return std::numeric_limits<T>::quiet_NaN(); 45705 | else if (helper::invalid_range(y, r0, r1)) 45706 | return std::numeric_limits<T>::quiet_NaN(); 45707 | 45708 | const T a = scalar_t(parameters[0])(); 45709 | 45710 | for (std::size_t i = r0; i <= r1; ++i) 45711 | { 45712 | y[i] = (a * x[i]) + y[i]; 45713 | } 45714 | 45715 | return T(1); 45716 | } 45717 | }; 45718 | 45719 | template <typename T> 45720 | class axpby exprtk_final : public exprtk::igeneric_function<T> 45721 | { 45722 | public: 45723 | 45724 | typedef typename exprtk::igeneric_function<T> igfun_t; 45725 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45726 | typedef typename igfun_t::generic_type generic_type; 45727 | typedef typename generic_type::scalar_view scalar_t; 45728 | typedef typename generic_type::vector_view vector_t; 45729 | 45730 | using igfun_t::operator(); 45731 | 45732 | axpby() 45733 | : exprtk::igeneric_function<T>("TVTV|TVTVTT") 45734 | /* 45735 | y <- ax + by 45736 | Overloads: 45737 | 0. TVTV - a, x(vector), b, y(vector) 45738 | 1. TVTVTT - a, x(vector), b, y(vector), r0, r1 45739 | */ 45740 | {} 45741 | 45742 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45743 | { 45744 | const vector_t x(parameters[1]); 45745 | vector_t y(parameters[3]); 45746 | 45747 | std::size_t r0 = 0; 45748 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 45749 | 45750 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1)) 45751 | return std::numeric_limits<T>::quiet_NaN(); 45752 | else if (helper::invalid_range(y, r0, r1)) 45753 | return std::numeric_limits<T>::quiet_NaN(); 45754 | 45755 | const T a = scalar_t(parameters[0])(); 45756 | const T b = scalar_t(parameters[2])(); 45757 | 45758 | for (std::size_t i = r0; i <= r1; ++i) 45759 | { 45760 | y[i] = (a * x[i]) + (b * y[i]); 45761 | } 45762 | 45763 | return T(1); 45764 | } 45765 | }; 45766 | 45767 | template <typename T> 45768 | class axpyz exprtk_final : public exprtk::igeneric_function<T> 45769 | { 45770 | public: 45771 | 45772 | typedef typename exprtk::igeneric_function<T> igfun_t; 45773 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45774 | typedef typename igfun_t::generic_type generic_type; 45775 | typedef typename generic_type::scalar_view scalar_t; 45776 | typedef typename generic_type::vector_view vector_t; 45777 | 45778 | using igfun_t::operator(); 45779 | 45780 | axpyz() 45781 | : exprtk::igeneric_function<T>("TVVV|TVVVTT") 45782 | /* 45783 | z <- ax + y 45784 | Overloads: 45785 | 0. TVVV - a, x(vector), y(vector), z(vector) 45786 | 1. TVVVTT - a, x(vector), y(vector), z(vector), r0, r1 45787 | */ 45788 | {} 45789 | 45790 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45791 | { 45792 | const vector_t x(parameters[1]); 45793 | const vector_t y(parameters[2]); 45794 | vector_t z(parameters[3]); 45795 | 45796 | std::size_t r0 = 0; 45797 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 45798 | 45799 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1)) 45800 | return std::numeric_limits<T>::quiet_NaN(); 45801 | else if (helper::invalid_range(y, r0, r1)) 45802 | return std::numeric_limits<T>::quiet_NaN(); 45803 | else if (helper::invalid_range(z, r0, r1)) 45804 | return std::numeric_limits<T>::quiet_NaN(); 45805 | 45806 | const T a = scalar_t(parameters[0])(); 45807 | 45808 | for (std::size_t i = r0; i <= r1; ++i) 45809 | { 45810 | z[i] = (a * x[i]) + y[i]; 45811 | } 45812 | 45813 | return T(1); 45814 | } 45815 | }; 45816 | 45817 | template <typename T> 45818 | class axpbyz exprtk_final : public exprtk::igeneric_function<T> 45819 | { 45820 | public: 45821 | 45822 | typedef typename exprtk::igeneric_function<T> igfun_t; 45823 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45824 | typedef typename igfun_t::generic_type generic_type; 45825 | typedef typename generic_type::scalar_view scalar_t; 45826 | typedef typename generic_type::vector_view vector_t; 45827 | 45828 | using igfun_t::operator(); 45829 | 45830 | axpbyz() 45831 | : exprtk::igeneric_function<T>("TVTVV|TVTVVTT") 45832 | /* 45833 | z <- ax + by 45834 | Overloads: 45835 | 0. TVTVV - a, x(vector), b, y(vector), z(vector) 45836 | 1. TVTVVTT - a, x(vector), b, y(vector), z(vector), r0, r1 45837 | */ 45838 | {} 45839 | 45840 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45841 | { 45842 | const vector_t x(parameters[1]); 45843 | const vector_t y(parameters[3]); 45844 | vector_t z(parameters[4]); 45845 | 45846 | std::size_t r0 = 0; 45847 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 45848 | 45849 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 5, 6, 1)) 45850 | return std::numeric_limits<T>::quiet_NaN(); 45851 | else if (helper::invalid_range(y, r0, r1)) 45852 | return std::numeric_limits<T>::quiet_NaN(); 45853 | else if (helper::invalid_range(z, r0, r1)) 45854 | return std::numeric_limits<T>::quiet_NaN(); 45855 | 45856 | const T a = scalar_t(parameters[0])(); 45857 | const T b = scalar_t(parameters[2])(); 45858 | 45859 | for (std::size_t i = r0; i <= r1; ++i) 45860 | { 45861 | z[i] = (a * x[i]) + (b * y[i]); 45862 | } 45863 | 45864 | return T(1); 45865 | } 45866 | }; 45867 | 45868 | template <typename T> 45869 | class axpbsy exprtk_final : public exprtk::igeneric_function<T> 45870 | { 45871 | public: 45872 | 45873 | typedef typename exprtk::igeneric_function<T> igfun_t; 45874 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45875 | typedef typename igfun_t::generic_type generic_type; 45876 | typedef typename generic_type::scalar_view scalar_t; 45877 | typedef typename generic_type::vector_view vector_t; 45878 | 45879 | using igfun_t::operator(); 45880 | 45881 | axpbsy() 45882 | : exprtk::igeneric_function<T>("TVTTV|TVTTVTT") 45883 | /* 45884 | y <- ax + by 45885 | Overloads: 45886 | 0. TVTVV - a, x(vector), b, shift, y(vector), z(vector) 45887 | 1. TVTVVTT - a, x(vector), b, shift, y(vector), z(vector), r0, r1 45888 | */ 45889 | {} 45890 | 45891 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45892 | { 45893 | const vector_t x(parameters[1]); 45894 | vector_t y(parameters[4]); 45895 | 45896 | std::size_t r0 = 0; 45897 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 45898 | 45899 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 5, 6, 1)) 45900 | return std::numeric_limits<T>::quiet_NaN(); 45901 | else if (helper::invalid_range(y, r0, r1)) 45902 | return std::numeric_limits<T>::quiet_NaN(); 45903 | 45904 | const T a = scalar_t(parameters[0])(); 45905 | const T b = scalar_t(parameters[2])(); 45906 | 45907 | const std::size_t s = static_cast<std::size_t>(scalar_t(parameters[3])()); 45908 | 45909 | for (std::size_t i = r0; i <= r1; ++i) 45910 | { 45911 | y[i] = (a * x[i]) + (b * y[i + s]); 45912 | } 45913 | 45914 | return T(1); 45915 | } 45916 | }; 45917 | 45918 | template <typename T> 45919 | class axpbsyz exprtk_final : public exprtk::igeneric_function<T> 45920 | { 45921 | public: 45922 | 45923 | typedef typename exprtk::igeneric_function<T> igfun_t; 45924 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45925 | typedef typename igfun_t::generic_type generic_type; 45926 | typedef typename generic_type::scalar_view scalar_t; 45927 | typedef typename generic_type::vector_view vector_t; 45928 | 45929 | using igfun_t::operator(); 45930 | 45931 | axpbsyz() 45932 | : exprtk::igeneric_function<T>("TVTTVV|TVTTVVTT") 45933 | /* 45934 | z <- ax + by 45935 | Overloads: 45936 | 0. TVTVV - a, x(vector), b, shift, y(vector), z(vector) 45937 | 1. TVTVVTT - a, x(vector), b, shift, y(vector), z(vector), r0, r1 45938 | */ 45939 | {} 45940 | 45941 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45942 | { 45943 | const vector_t x(parameters[1]); 45944 | const vector_t y(parameters[4]); 45945 | vector_t z(parameters[5]); 45946 | 45947 | std::size_t r0 = 0; 45948 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 45949 | 45950 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 6, 7, 1)) 45951 | return std::numeric_limits<T>::quiet_NaN(); 45952 | else if (helper::invalid_range(y, r0, r1)) 45953 | return std::numeric_limits<T>::quiet_NaN(); 45954 | else if (helper::invalid_range(z, r0, r1)) 45955 | return std::numeric_limits<T>::quiet_NaN(); 45956 | 45957 | const T a = scalar_t(parameters[0])(); 45958 | const T b = scalar_t(parameters[2])(); 45959 | 45960 | const std::size_t s = static_cast<std::size_t>(scalar_t(parameters[3])()); 45961 | 45962 | for (std::size_t i = r0; i <= r1; ++i) 45963 | { 45964 | z[i] = (a * x[i]) + (b * y[i + s]); 45965 | } 45966 | 45967 | return T(1); 45968 | } 45969 | }; 45970 | 45971 | template <typename T> 45972 | class axpbz exprtk_final : public exprtk::igeneric_function<T> 45973 | { 45974 | public: 45975 | 45976 | typedef typename exprtk::igeneric_function<T> igfun_t; 45977 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45978 | typedef typename igfun_t::generic_type generic_type; 45979 | typedef typename generic_type::scalar_view scalar_t; 45980 | typedef typename generic_type::vector_view vector_t; 45981 | 45982 | using igfun_t::operator(); 45983 | 45984 | axpbz() 45985 | : exprtk::igeneric_function<T>("TVTV|TVTVTT") 45986 | /* 45987 | z <- ax + b 45988 | Overloads: 45989 | 0. TVTV - a, x(vector), b, z(vector) 45990 | 1. TVTVTT - a, x(vector), b, z(vector), r0, r1 45991 | */ 45992 | {} 45993 | 45994 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45995 | { 45996 | const vector_t x(parameters[1]); 45997 | vector_t z(parameters[3]); 45998 | 45999 | std::size_t r0 = 0; 46000 | std::size_t r1 = x.size() - 1; 46001 | 46002 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1)) 46003 | return std::numeric_limits<T>::quiet_NaN(); 46004 | else if (helper::invalid_range(z, r0, r1)) 46005 | return std::numeric_limits<T>::quiet_NaN(); 46006 | 46007 | const T a = scalar_t(parameters[0])(); 46008 | const T b = scalar_t(parameters[2])(); 46009 | 46010 | for (std::size_t i = r0; i <= r1; ++i) 46011 | { 46012 | z[i] = (a * x[i]) + b; 46013 | } 46014 | 46015 | return T(1); 46016 | } 46017 | }; 46018 | 46019 | template <typename T> 46020 | class diff exprtk_final : public exprtk::igeneric_function<T> 46021 | { 46022 | public: 46023 | 46024 | typedef typename exprtk::igeneric_function<T> igfun_t; 46025 | typedef typename igfun_t::parameter_list_t parameter_list_t; 46026 | typedef typename igfun_t::generic_type generic_type; 46027 | typedef typename generic_type::scalar_view scalar_t; 46028 | typedef typename generic_type::vector_view vector_t; 46029 | 46030 | using igfun_t::operator(); 46031 | 46032 | diff() 46033 | : exprtk::igeneric_function<T>("VV|VVT") 46034 | /* 46035 | x_(i - stride) - x_i 46036 | Overloads: 46037 | 0. VV - x(vector), y(vector) 46038 | 1. VVT - x(vector), y(vector), stride 46039 | */ 46040 | {} 46041 | 46042 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 46043 | { 46044 | const vector_t x(parameters[0]); 46045 | vector_t y(parameters[1]); 46046 | 46047 | const std::size_t r0 = 0; 46048 | const std::size_t r1 = std::min(x.size(),y.size()) - 1; 46049 | 46050 | const std::size_t stride = (1 != ps_index) ? 1 : 46051 | std::min(r1,static_cast<std::size_t>(scalar_t(parameters[2])())); 46052 | 46053 | for (std::size_t i = 0; i < stride; ++i) 46054 | { 46055 | y[i] = std::numeric_limits<T>::quiet_NaN(); 46056 | } 46057 | 46058 | for (std::size_t i = (r0 + stride); i <= r1; ++i) 46059 | { 46060 | y[i] = x[i] - x[i - stride]; 46061 | } 46062 | 46063 | return T(1); 46064 | } 46065 | }; 46066 | 46067 | template <typename T> 46068 | class dot exprtk_final : public exprtk::igeneric_function<T> 46069 | { 46070 | public: 46071 | 46072 | typedef typename exprtk::igeneric_function<T> igfun_t; 46073 | typedef typename igfun_t::parameter_list_t parameter_list_t; 46074 | typedef typename igfun_t::generic_type generic_type; 46075 | typedef typename generic_type::scalar_view scalar_t; 46076 | typedef typename generic_type::vector_view vector_t; 46077 | 46078 | using igfun_t::operator(); 46079 | 46080 | dot() 46081 | : exprtk::igeneric_function<T>("VV|VVTT") 46082 | /* 46083 | Overloads: 46084 | 0. VV - x(vector), y(vector) 46085 | 1. VVTT - x(vector), y(vector), r0, r1 46086 | */ 46087 | {} 46088 | 46089 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 46090 | { 46091 | const vector_t x(parameters[0]); 46092 | const vector_t y(parameters[1]); 46093 | 46094 | std::size_t r0 = 0; 46095 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 46096 | 46097 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)) 46098 | return std::numeric_limits<T>::quiet_NaN(); 46099 | else if (helper::invalid_range(y, r0, r1)) 46100 | return std::numeric_limits<T>::quiet_NaN(); 46101 | 46102 | T result = T(0); 46103 | 46104 | for (std::size_t i = r0; i <= r1; ++i) 46105 | { 46106 | result += (x[i] * y[i]); 46107 | } 46108 | 46109 | return result; 46110 | } 46111 | }; 46112 | 46113 | template <typename T> 46114 | class dotk exprtk_final : public exprtk::igeneric_function<T> 46115 | { 46116 | public: 46117 | 46118 | typedef typename exprtk::igeneric_function<T> igfun_t; 46119 | typedef typename igfun_t::parameter_list_t parameter_list_t; 46120 | typedef typename igfun_t::generic_type generic_type; 46121 | typedef typename generic_type::scalar_view scalar_t; 46122 | typedef typename generic_type::vector_view vector_t; 46123 | 46124 | using igfun_t::operator(); 46125 | 46126 | dotk() 46127 | : exprtk::igeneric_function<T>("VV|VVTT") 46128 | /* 46129 | Overloads: 46130 | 0. VV - x(vector), y(vector) 46131 | 1. VVTT - x(vector), y(vector), r0, r1 46132 | */ 46133 | {} 46134 | 46135 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 46136 | { 46137 | const vector_t x(parameters[0]); 46138 | const vector_t y(parameters[1]); 46139 | 46140 | std::size_t r0 = 0; 46141 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 46142 | 46143 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)) 46144 | return std::numeric_limits<T>::quiet_NaN(); 46145 | else if (helper::invalid_range(y, r0, r1)) 46146 | return std::numeric_limits<T>::quiet_NaN(); 46147 | 46148 | T result = T(0); 46149 | T error = T(0); 46150 | 46151 | for (std::size_t i = r0; i <= r1; ++i) 46152 | { 46153 | details::kahan_sum(result, error, (x[i] * y[i])); 46154 | } 46155 | 46156 | return result; 46157 | } 46158 | }; 46159 | 46160 | template <typename T> 46161 | class threshold_below exprtk_final : public exprtk::igeneric_function<T> 46162 | { 46163 | public: 46164 | 46165 | typedef typename exprtk::igeneric_function<T> igfun_t; 46166 | typedef typename igfun_t::parameter_list_t parameter_list_t; 46167 | typedef typename igfun_t::generic_type generic_type; 46168 | typedef typename generic_type::scalar_view scalar_t; 46169 | typedef typename generic_type::vector_view vector_t; 46170 | 46171 | using igfun_t::operator(); 46172 | 46173 | threshold_below() 46174 | : exprtk::igeneric_function<T>("VTT|VTTTT") 46175 | /* 46176 | Overloads: 46177 | 0. VTT - vector, TV, SV 46178 | 1. VTTTT - vector, r0, r1, TV, SV 46179 | 46180 | Where: 46181 | TV - Threshold value 46182 | SV - Snap-to value 46183 | */ 46184 | {} 46185 | 46186 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 46187 | { 46188 | vector_t vec(parameters[0]); 46189 | 46190 | const T threshold_value = (0 == ps_index) ? 46191 | scalar_t(parameters[1]) : 46192 | scalar_t(parameters[3]) ; 46193 | 46194 | const T snap_value = scalar_t(parameters.back()); 46195 | 46196 | std::size_t r0 = 0; 46197 | std::size_t r1 = vec.size() - 1; 46198 | 46199 | if ( 46200 | (1 == ps_index) && 46201 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 46202 | ) 46203 | { 46204 | return T(0); 46205 | } 46206 | 46207 | for (std::size_t i = r0; i <= r1; ++i) 46208 | { 46209 | if (vec[i] < threshold_value) 46210 | { 46211 | vec[i] = snap_value; 46212 | } 46213 | } 46214 | 46215 | return T(1); 46216 | } 46217 | }; 46218 | 46219 | template <typename T> 46220 | class threshold_above exprtk_final : public exprtk::igeneric_function<T> 46221 | { 46222 | public: 46223 | 46224 | typedef typename exprtk::igeneric_function<T> igfun_t; 46225 | typedef typename igfun_t::parameter_list_t parameter_list_t; 46226 | typedef typename igfun_t::generic_type generic_type; 46227 | typedef typename generic_type::scalar_view scalar_t; 46228 | typedef typename generic_type::vector_view vector_t; 46229 | 46230 | using igfun_t::operator(); 46231 | 46232 | threshold_above() 46233 | : exprtk::igeneric_function<T>("VTT|VTTTT") 46234 | /* 46235 | Overloads: 46236 | 0. VTT - vector, TV, SV 46237 | 1. VTTTT - vector, r0, r1, TV, SV 46238 | 46239 | Where: 46240 | TV - Threshold value 46241 | SV - Snap-to value 46242 | */ 46243 | {} 46244 | 46245 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 46246 | { 46247 | vector_t vec(parameters[0]); 46248 | 46249 | const T threshold_value = (0 == ps_index) ? 46250 | scalar_t(parameters[1]) : 46251 | scalar_t(parameters[3]) ; 46252 | 46253 | const T snap_value = scalar_t(parameters.back()); 46254 | 46255 | std::size_t r0 = 0; 46256 | std::size_t r1 = vec.size() - 1; 46257 | 46258 | if ( 46259 | (1 == ps_index) && 46260 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 46261 | ) 46262 | { 46263 | return T(0); 46264 | } 46265 | 46266 | for (std::size_t i = r0; i <= r1; ++i) 46267 | { 46268 | if (vec[i] > threshold_value) 46269 | { 46270 | vec[i] = snap_value; 46271 | } 46272 | } 46273 | 46274 | return T(1); 46275 | } 46276 | }; 46277 | 46278 | template <typename T> 46279 | class min_elemwise exprtk_final : public exprtk::igeneric_function<T> 46280 | { 46281 | public: 46282 | 46283 | typedef typename exprtk::igeneric_function<T> igfun_t; 46284 | typedef typename igfun_t::parameter_list_t parameter_list_t; 46285 | typedef typename igfun_t::generic_type generic_type; 46286 | typedef typename generic_type::scalar_view scalar_t; 46287 | typedef typename generic_type::vector_view vector_t; 46288 | 46289 | using igfun_t::operator(); 46290 | 46291 | min_elemwise() 46292 | : exprtk::igeneric_function<T>("VT|VVT|VTTT|VVTTT") 46293 | /* 46294 | Overloads: 46295 | 0. VT - vector, T 46296 | 0. VVT - vector, vector, T 46297 | 0. VTTT - vector, r0, r1, T 46298 | 0. VVTTT - vector, vector, r0, r1, T 46299 | */ 46300 | {} 46301 | 46302 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 46303 | { 46304 | std::size_t out_vec_index = 0; 46305 | std::size_t in_vec_index = (ps_index & 1) ? 1 : 0; 46306 | std::size_t scalar_index = parameters.size() - 1; 46307 | 46308 | vector_t out_vec(parameters[out_vec_index]); 46309 | vector_t in_vec (parameters[in_vec_index ]); 46310 | 46311 | const T s = scalar_t(parameters[scalar_index ])(); 46312 | 46313 | std::size_t r0 = 0; 46314 | std::size_t r1 = in_vec.size() - 1; 46315 | 46316 | if ((2 == ps_index) || (3 == ps_index)) 46317 | { 46318 | std::size_t rng_idx0 = 0; 46319 | std::size_t rng_idx1 = 0; 46320 | 46321 | switch (ps_index) 46322 | { 46323 | case 2 : { rng_idx0 = 1; rng_idx1 = 2; }; break; 46324 | case 3 : { rng_idx0 = 2; rng_idx1 = 3; }; break; 46325 | } 46326 | 46327 | if (!helper::load_vector_range<T>::process(parameters, r0, r1, rng_idx0, rng_idx1, 0)) 46328 | { 46329 | return T(0); 46330 | } 46331 | } 46332 | 46333 | for (std::size_t i = r0; i <= r1; ++i) 46334 | { 46335 | out_vec[i] = exprtk::details::numeric::min(in_vec[i], s); 46336 | } 46337 | 46338 | return T(1); 46339 | } 46340 | }; 46341 | 46342 | template <typename T> 46343 | class max_elemwise exprtk_final : public exprtk::igeneric_function<T> 46344 | { 46345 | public: 46346 | 46347 | typedef typename exprtk::igeneric_function<T> igfun_t; 46348 | typedef typename igfun_t::parameter_list_t parameter_list_t; 46349 | typedef typename igfun_t::generic_type generic_type; 46350 | typedef typename generic_type::scalar_view scalar_t; 46351 | typedef typename generic_type::vector_view vector_t; 46352 | 46353 | using igfun_t::operator(); 46354 | 46355 | max_elemwise() 46356 | : exprtk::igeneric_function<T>("VT|VVT|VTTT|VVTTT") 46357 | /* 46358 | Overloads: 46359 | 0. VT - vector, T 46360 | 1. VVT - vector, vector, T 46361 | 2. VTTT - vector, r0, r1, T 46362 | 3. VVTTT - vector, vector, r0, r1, T 46363 | */ 46364 | {} 46365 | 46366 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 46367 | { 46368 | std::size_t out_vec_index = 0; 46369 | std::size_t in_vec_index = (ps_index & 1) ? 1 : 0; 46370 | std::size_t scalar_index = parameters.size() - 1; 46371 | 46372 | vector_t out_vec(parameters[out_vec_index]); 46373 | vector_t in_vec (parameters[in_vec_index ]); 46374 | 46375 | const T s = scalar_t(parameters[scalar_index ])(); 46376 | 46377 | std::size_t r0 = 0; 46378 | std::size_t r1 = in_vec.size() - 1; 46379 | 46380 | if ((2 == ps_index) || (3 == ps_index)) 46381 | { 46382 | std::size_t rng_idx0 = 0; 46383 | std::size_t rng_idx1 = 0; 46384 | 46385 | switch (ps_index) 46386 | { 46387 | case 2 : { rng_idx0 = 1; rng_idx1 = 2; }; break; 46388 | case 3 : { rng_idx0 = 2; rng_idx1 = 3; }; break; 46389 | } 46390 | 46391 | if (!helper::load_vector_range<T>::process(parameters, r0, r1, rng_idx0, rng_idx1, 0)) 46392 | { 46393 | return T(0); 46394 | } 46395 | } 46396 | 46397 | for (std::size_t i = r0; i <= r1; ++i) 46398 | { 46399 | out_vec[i] = exprtk::details::numeric::max(in_vec[i], s); 46400 | } 46401 | 46402 | return T(1); 46403 | } 46404 | }; 46405 | 46406 | template <typename T> 46407 | class select exprtk_final : public exprtk::igeneric_function<T> 46408 | { 46409 | public: 46410 | 46411 | typedef typename exprtk::igeneric_function<T> igfun_t; 46412 | typedef typename igfun_t::parameter_list_t parameter_list_t; 46413 | typedef typename igfun_t::generic_type generic_type; 46414 | typedef typename generic_type::vector_view vector_t; 46415 | 46416 | using igfun_t::operator(); 46417 | 46418 | select() 46419 | : exprtk::igeneric_function<T>("VVVV|VVVVTT") 46420 | /* 46421 | Overloads: 46422 | 0. VVVV - out vector, mask, vector 0, vector 1 46423 | 1. VVVV - out vector, mask, vector 0, vector 1, r0, r1 46424 | */ 46425 | {} 46426 | 46427 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 46428 | { 46429 | vector_t out (parameters[0]); 46430 | const vector_t mask(parameters[1]); 46431 | const vector_t vec0(parameters[2]); 46432 | const vector_t vec1(parameters[3]); 46433 | 46434 | std::size_t r0 = 0; 46435 | std::size_t r1 = out.size() - 1; 46436 | 46437 | if (1 == ps_index) 46438 | { 46439 | std::size_t rng_idx0 = 4; 46440 | std::size_t rng_idx1 = 5; 46441 | 46442 | if (!helper::load_vector_range<T>::process(parameters, r0, r1, rng_idx0, rng_idx1, 0)) 46443 | { 46444 | return T(0); 46445 | } 46446 | 46447 | if (helper::invalid_range(out , r0, r1)) return T(0); 46448 | if (helper::invalid_range(mask, r0, r1)) return T(0); 46449 | if (helper::invalid_range(vec0, r0, r1)) return T(0); 46450 | if (helper::invalid_range(vec1, r0, r1)) return T(0); 46451 | } 46452 | 46453 | for (std::size_t i = r0; i <= r1; ++i) 46454 | { 46455 | out[i] = (mask[i] != T(0)) ? vec0[i] : vec1[i]; 46456 | } 46457 | 46458 | return T(1); 46459 | } 46460 | }; 46461 | 46462 | template <typename T> 46463 | struct package 46464 | { 46465 | all_true <T> at; 46466 | all_false <T> af; 46467 | any_true <T> nt; 46468 | any_false <T> nf; 46469 | count <T> c; 46470 | copy <T> cp; 46471 | rol <T> rl; 46472 | ror <T> rr; 46473 | reverse <T> rev; 46474 | shift_left <T> sl; 46475 | shift_right <T> sr; 46476 | sort <T> st; 46477 | nthelement <T> ne; 46478 | assign <T> an; 46479 | iota <T> ia; 46480 | sumk <T> sk; 46481 | axpy <T> b1_axpy; 46482 | axpby <T> b1_axpby; 46483 | axpyz <T> b1_axpyz; 46484 | axpbyz <T> b1_axpbyz; 46485 | axpbsy <T> b1_axpbsy; 46486 | axpbsyz <T> b1_axpbsyz; 46487 | axpbz <T> b1_axpbz; 46488 | diff <T> df; 46489 | dot <T> dt; 46490 | dotk <T> dtk; 46491 | threshold_above<T> ta; 46492 | threshold_below<T> tb; 46493 | min_elemwise<T> miew; 46494 | max_elemwise<T> maew; 46495 | select<T> slct; 46496 | 46497 | bool register_package(exprtk::symbol_table<T>& symtab) 46498 | { 46499 | #define exprtk_register_function(FunctionName, FunctionType) \ 46500 | if (!symtab.add_function(FunctionName,FunctionType)) \ 46501 | { \ 46502 | exprtk_debug(( \ 46503 | "exprtk::rtl::vecops::register_package - Failed to add function: %s\n", \ 46504 | FunctionName)); \ 46505 | return false; \ 46506 | } \ 46507 | 46508 | exprtk_register_function("all_true" , at ) 46509 | exprtk_register_function("all_false" , af ) 46510 | exprtk_register_function("any_true" , nt ) 46511 | exprtk_register_function("any_false" , nf ) 46512 | exprtk_register_function("count" , c ) 46513 | exprtk_register_function("copy" , cp ) 46514 | exprtk_register_function("rotate_left" , rl ) 46515 | exprtk_register_function("rol" , rl ) 46516 | exprtk_register_function("rotate_right" , rr ) 46517 | exprtk_register_function("ror" , rr ) 46518 | exprtk_register_function("reverse" , rev ) 46519 | exprtk_register_function("shftl" , sl ) 46520 | exprtk_register_function("shftr" , sr ) 46521 | exprtk_register_function("sort" , st ) 46522 | exprtk_register_function("nth_element" , ne ) 46523 | exprtk_register_function("assign" , an ) 46524 | exprtk_register_function("iota" , ia ) 46525 | exprtk_register_function("sumk" , sk ) 46526 | exprtk_register_function("axpy" , b1_axpy ) 46527 | exprtk_register_function("axpby" , b1_axpby ) 46528 | exprtk_register_function("axpyz" , b1_axpyz ) 46529 | exprtk_register_function("axpbyz" , b1_axpbyz ) 46530 | exprtk_register_function("axpbsy" , b1_axpbsy ) 46531 | exprtk_register_function("axpbsyz" , b1_axpbsyz) 46532 | exprtk_register_function("axpbz" , b1_axpbz ) 46533 | exprtk_register_function("diff" , df ) 46534 | exprtk_register_function("dot" , dt ) 46535 | exprtk_register_function("dotk" , dtk ) 46536 | exprtk_register_function("threshold_above" , ta ) 46537 | exprtk_register_function("threshold_below" , tb ) 46538 | exprtk_register_function("min_elemwise" , miew ) 46539 | exprtk_register_function("max_elemwise" , maew ) 46540 | exprtk_register_function("select" , slct ) 46541 | 46542 | #undef exprtk_register_function 46543 | 46544 | return true; 46545 | } 46546 | }; 46547 | 46548 | } // namespace exprtk::rtl::vecops 46549 | } // namespace exprtk::rtl 46550 | } // namespace exprtk 46551 | #endif 46552 | 46553 | namespace exprtk 46554 | { 46555 | namespace information 46556 | { 46557 | using ::exprtk::details::char_cptr; 46558 | 46559 | static char_cptr library = "Mathematical Expression Toolkit" 46560 | static char_cptr version = "2.71828182845904523536028747135266249775724" 46561 | "7093699959574966967627724076630353547594571" 46562 | "3821785251664274274663919320030599218174135" 46563 | "9662904357290033429526059563073813232862794" 46564 | static char_cptr date = "20250101" 46565 | static char_cptr min_cpp = "199711L" 46566 | 46567 | static inline std::string data() 46568 | { 46569 | static const std::string info_str = std::string(library) + 46570 | std::string(" v") + std::string(version) + 46571 | std::string(" (") + date + std::string(")") + 46572 | std::string(" (") + min_cpp + std::string(")"); 46573 | return info_str; 46574 | } 46575 | 46576 | } // namespace information 46577 | 46578 | #ifdef exprtk_debug 46579 | #undef exprtk_debug 46580 | #endif 46581 | 46582 | #ifdef exprtk_error_location 46583 | #undef exprtk_error_location 46584 | #endif 46585 | 46586 | #ifdef exprtk_fallthrough 46587 | #undef exprtk_fallthrough 46588 | #endif 46589 | 46590 | #ifdef exprtk_override 46591 | #undef exprtk_override 46592 | #endif 46593 | 46594 | #ifdef exprtk_final 46595 | #undef exprtk_final 46596 | #endif 46597 | 46598 | #ifdef exprtk_delete 46599 | #undef exprtk_delete 46600 | #endif 46601 | 46602 | } // namespace exprtk 46603 | 46604 | #endif