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 | assert(data); 04660 | 04661 | data_ = data; 04662 | 04663 | if (!data_ref_.empty()) 04664 | { 04665 | for (std::size_t i = 0; i < data_ref_.size(); ++i) 04666 | { 04667 | (*data_ref_[i]) = data; 04668 | } 04669 | } 04670 | } 04671 | 04672 | inline bool rebase(data_ptr_t data, const std::size_t new_size) 04673 | { 04674 | if (set_size(new_size)) 04675 | { 04676 | rebase(data); 04677 | return true; 04678 | } 04679 | 04680 | return false; 04681 | } 04682 | 04683 | inline data_ptr_t data() const 04684 | { 04685 | return data_; 04686 | } 04687 | 04688 | inline std::size_t base_size() const 04689 | { 04690 | return base_size_; 04691 | } 04692 | 04693 | inline std::size_t size() const 04694 | { 04695 | return size_; 04696 | } 04697 | 04698 | inline const T& operator[](const std::size_t index) const 04699 | { 04700 | assert(index < size_); 04701 | return data_[index]; 04702 | } 04703 | 04704 | inline T& operator[](const std::size_t index) 04705 | { 04706 | assert(index < size_); 04707 | return data_[index]; 04708 | } 04709 | 04710 | void set_ref(data_ptr_t* data_ref) 04711 | { 04712 | data_ref_.push_back(data_ref); 04713 | exprtk_debug(("vector_view::set_ref() - data_ref: %p data_ref_.size(): %d\n", 04714 | reinterpret_cast<void*>(data_ref), 04715 | static_cast<int>(data_ref_.size()))); 04716 | } 04717 | 04718 | void set_size_ref(std::size_t* size_ref) 04719 | { 04720 | size_ref_.push_back(size_ref); 04721 | exprtk_debug(("vector_view::set_size_ref() - size_ref: %p size_ref_.size(): %d\n", 04722 | reinterpret_cast<void*>(size_ref), 04723 | static_cast<int>(size_ref_.size()))); 04724 | } 04725 | 04726 | void remove_ref(data_ptr_t* data_ref) 04727 | { 04728 | data_ref_.erase( 04729 | std::remove(data_ref_.begin(), data_ref_.end(), data_ref), 04730 | data_ref_.end()); 04731 | exprtk_debug(("vector_view::remove_ref() - data_ref: %p data_ref_.size(): %d\n", 04732 | reinterpret_cast<void*>(data_ref), 04733 | static_cast<int>(data_ref_.size()))); 04734 | } 04735 | 04736 | void remove_size_ref(std::size_t* size_ref) 04737 | { 04738 | size_ref_.erase( 04739 | std::remove(size_ref_.begin(), size_ref_.end(), size_ref), 04740 | size_ref_.end()); 04741 | exprtk_debug(("vector_view::remove_size_ref() - size_ref: %p size_ref_.size(): %d\n", 04742 | reinterpret_cast<void*>(size_ref), 04743 | static_cast<int>(size_ref_.size()))); 04744 | } 04745 | 04746 | bool set_size(const std::size_t new_size) 04747 | { 04748 | if ((new_size > 0) && (new_size <= base_size_)) 04749 | { 04750 | size_ = new_size; 04751 | exprtk_debug(("vector_view::set_size() - data_: %p size: %lu\n", 04752 | reinterpret_cast<void*>(data_), 04753 | size_)); 04754 | 04755 | if (!size_ref_.empty()) 04756 | { 04757 | for (std::size_t i = 0; i < size_ref_.size(); ++i) 04758 | { 04759 | (*size_ref_[i]) = new_size; 04760 | } 04761 | } 04762 | 04763 | return true; 04764 | } 04765 | 04766 | exprtk_debug(("vector_view::set_size() - error invalid new_size: %lu base_size: %lu\n", 04767 | new_size, 04768 | base_size_)); 04769 | return false; 04770 | } 04771 | 04772 | private: 04773 | 04774 | const std::size_t base_size_; 04775 | std::size_t size_; 04776 | data_ptr_t data_; 04777 | std::vector<data_ptr_t*> data_ref_; 04778 | std::vector<std::size_t*> size_ref_; 04779 | }; 04780 | 04781 | template <typename T> 04782 | inline vector_view<T> make_vector_view(T* data, 04783 | const std::size_t size, const std::size_t offset = 0) 04784 | { 04785 | return vector_view<T>(data + offset, size); 04786 | } 04787 | 04788 | template <typename T> 04789 | inline vector_view<T> make_vector_view(std::vector<T>& v, 04790 | const std::size_t size, const std::size_t offset = 0) 04791 | { 04792 | return vector_view<T>(v.data() + offset, size); 04793 | } 04794 | 04795 | template <typename T> class results_context; 04796 | namespace details { template <typename T> class vector_interface; } 04797 | 04798 | template <typename T> 04799 | struct type_store 04800 | { 04801 | enum store_type 04802 | { 04803 | e_unknown, 04804 | e_scalar , 04805 | e_vector , 04806 | e_string 04807 | }; 04808 | 04809 | type_store() 04810 | : data(0) 04811 | , size(0) 04812 | , type(e_unknown) 04813 | , ivec(0) 04814 | {} 04815 | 04816 | union 04817 | { 04818 | void* data; 04819 | T* vec_data; 04820 | }; 04821 | 04822 | typedef details::vector_interface<T>* ivec_t; 04823 | 04824 | std::size_t size; 04825 | store_type type; 04826 | ivec_t ivec; 04827 | 04828 | class parameter_list 04829 | { 04830 | public: 04831 | 04832 | explicit parameter_list(std::vector<type_store>& pl) 04833 | : parameter_list_(pl) 04834 | {} 04835 | 04836 | inline bool empty() const 04837 | { 04838 | return parameter_list_.empty(); 04839 | } 04840 | 04841 | inline std::size_t size() const 04842 | { 04843 | return parameter_list_.size(); 04844 | } 04845 | 04846 | inline type_store& operator[](const std::size_t& index) 04847 | { 04848 | return parameter_list_[index]; 04849 | } 04850 | 04851 | inline const type_store& operator[](const std::size_t& index) const 04852 | { 04853 | return parameter_list_[index]; 04854 | } 04855 | 04856 | inline type_store& front() 04857 | { 04858 | return parameter_list_[0]; 04859 | } 04860 | 04861 | inline const type_store& front() const 04862 | { 04863 | return parameter_list_[0]; 04864 | } 04865 | 04866 | inline type_store& back() 04867 | { 04868 | return parameter_list_.back(); 04869 | } 04870 | 04871 | inline const type_store& back() const 04872 | { 04873 | return parameter_list_.back(); 04874 | } 04875 | 04876 | inline typename std::vector<type_store>::const_iterator begin() const 04877 | { 04878 | return parameter_list_.begin(); 04879 | } 04880 | 04881 | inline typename std::vector<type_store>::const_iterator end() const 04882 | { 04883 | return parameter_list_.end(); 04884 | } 04885 | 04886 | inline typename std::vector<type_store>::iterator begin() 04887 | { 04888 | return parameter_list_.begin(); 04889 | } 04890 | 04891 | inline typename std::vector<type_store>::iterator end() 04892 | { 04893 | return parameter_list_.end(); 04894 | } 04895 | 04896 | private: 04897 | 04898 | std::vector<type_store>& parameter_list_; 04899 | 04900 | friend class results_context<T>; 04901 | }; 04902 | 04903 | template <typename ViewType> 04904 | struct type_view 04905 | { 04906 | typedef type_store<T> type_store_t; 04907 | typedef ViewType value_t; 04908 | 04909 | explicit type_view(type_store_t& ts) 04910 | : ts_(ts) 04911 | , data_(reinterpret_cast<value_t*>(ts_.data)) 04912 | {} 04913 | 04914 | explicit type_view(const type_store_t& ts) 04915 | : ts_(const_cast<type_store_t&>(ts)) 04916 | , data_(reinterpret_cast<value_t*>(ts_.data)) 04917 | {} 04918 | 04919 | inline std::size_t size() const 04920 | { 04921 | return ts_.size; 04922 | } 04923 | 04924 | inline value_t& operator[](const std::size_t& i) 04925 | { 04926 | return data_[i]; 04927 | } 04928 | 04929 | inline const value_t& operator[](const std::size_t& i) const 04930 | { 04931 | return data_[i]; 04932 | } 04933 | 04934 | inline const value_t* begin() const { return data_; } 04935 | inline value_t* begin() { return data_; } 04936 | 04937 | inline const value_t* end() const 04938 | { 04939 | return static_cast<value_t*>(data_ + ts_.size); 04940 | } 04941 | 04942 | inline value_t* end() 04943 | { 04944 | return static_cast<value_t*>(data_ + ts_.size); 04945 | } 04946 | 04947 | type_store_t& ts_; 04948 | value_t* data_; 04949 | }; 04950 | 04951 | typedef type_view<T> vector_view; 04952 | typedef type_view<char> string_view; 04953 | 04954 | struct scalar_view 04955 | { 04956 | typedef type_store<T> type_store_t; 04957 | typedef T value_t; 04958 | 04959 | explicit scalar_view(type_store_t& ts) 04960 | : v_(*reinterpret_cast<value_t*>(ts.data)) 04961 | {} 04962 | 04963 | explicit scalar_view(const type_store_t& ts) 04964 | : v_(*reinterpret_cast<value_t*>(const_cast<type_store_t&>(ts).data)) 04965 | {} 04966 | 04967 | inline value_t& operator() () 04968 | { 04969 | return v_; 04970 | } 04971 | 04972 | inline const value_t& operator() () const 04973 | { 04974 | return v_; 04975 | } 04976 | 04977 | inline operator value_t() const 04978 | { 04979 | return v_; 04980 | } 04981 | 04982 | inline operator value_t() 04983 | { 04984 | return v_; 04985 | } 04986 | 04987 | template <typename IntType> 04988 | inline bool to_int(IntType& i) const 04989 | { 04990 | if (!exprtk::details::numeric::is_integer(v_)) 04991 | return false; 04992 | 04993 | i = static_cast<IntType>(v_); 04994 | 04995 | return true; 04996 | } 04997 | 04998 | template <typename UIntType> 04999 | inline bool to_uint(UIntType& u) const 05000 | { 05001 | if (v_ < T(0)) 05002 | return false; 05003 | else if (!exprtk::details::numeric::is_integer(v_)) 05004 | return false; 05005 | 05006 | u = static_cast<UIntType>(v_); 05007 | 05008 | return true; 05009 | } 05010 | 05011 | T& v_; 05012 | }; 05013 | }; 05014 | 05015 | template <typename StringView> 05016 | inline std::string to_str(const StringView& view) 05017 | { 05018 | return std::string(view.begin(),view.size()); 05019 | } 05020 | 05021 | #ifndef exprtk_disable_return_statement 05022 | namespace details 05023 | { 05024 | template <typename T> class return_node; 05025 | template <typename T> class return_envelope_node; 05026 | } 05027 | #endif 05028 | 05029 | template <typename T> 05030 | class results_context 05031 | { 05032 | public: 05033 | 05034 | typedef type_store<T> type_store_t; 05035 | typedef typename type_store_t::scalar_view scalar_t; 05036 | typedef typename type_store_t::vector_view vector_t; 05037 | typedef typename type_store_t::string_view string_t; 05038 | 05039 | results_context() 05040 | : results_available_(false) 05041 | {} 05042 | 05043 | inline std::size_t count() const 05044 | { 05045 | if (results_available_) 05046 | return parameter_list_.size(); 05047 | else 05048 | return 0; 05049 | } 05050 | 05051 | inline type_store_t& operator[](const std::size_t& index) 05052 | { 05053 | return parameter_list_[index]; 05054 | } 05055 | 05056 | inline const type_store_t& operator[](const std::size_t& index) const 05057 | { 05058 | return parameter_list_[index]; 05059 | } 05060 | 05061 | inline bool get_scalar(const std::size_t& index, T& out) const 05062 | { 05063 | if ( 05064 | (index < parameter_list_.size()) && 05065 | (parameter_list_[index].type == type_store_t::e_scalar) 05066 | ) 05067 | { 05068 | const scalar_t scalar(parameter_list_[index]); 05069 | out = scalar(); 05070 | return true; 05071 | } 05072 | 05073 | return false; 05074 | } 05075 | 05076 | template <typename OutputIterator> 05077 | inline bool get_vector(const std::size_t& index, OutputIterator out_itr) const 05078 | { 05079 | if ( 05080 | (index < parameter_list_.size()) && 05081 | (parameter_list_[index].type == type_store_t::e_vector) 05082 | ) 05083 | { 05084 | const vector_t vector(parameter_list_[index]); 05085 | for (std::size_t i = 0; i < vector.size(); ++i) 05086 | { 05087 | *(out_itr++) = vector[i]; 05088 | } 05089 | 05090 | return true; 05091 | } 05092 | 05093 | return false; 05094 | } 05095 | 05096 | inline bool get_vector(const std::size_t& index, std::vector<T>& out) const 05097 | { 05098 | return get_vector(index,std::back_inserter(out)); 05099 | } 05100 | 05101 | inline bool get_string(const std::size_t& index, std::string& out) const 05102 | { 05103 | if ( 05104 | (index < parameter_list_.size()) && 05105 | (parameter_list_[index].type == type_store_t::e_string) 05106 | ) 05107 | { 05108 | const string_t str(parameter_list_[index]); 05109 | out.assign(str.begin(),str.size()); 05110 | return true; 05111 | } 05112 | 05113 | return false; 05114 | } 05115 | 05116 | private: 05117 | 05118 | inline void clear() 05119 | { 05120 | results_available_ = false; 05121 | } 05122 | 05123 | typedef std::vector<type_store_t> ts_list_t; 05124 | typedef typename type_store_t::parameter_list parameter_list_t; 05125 | 05126 | inline void assign(const parameter_list_t& pl) 05127 | { 05128 | parameter_list_ = pl.parameter_list_; 05129 | results_available_ = true; 05130 | } 05131 | 05132 | bool results_available_; 05133 | ts_list_t parameter_list_; 05134 | 05135 | #ifndef exprtk_disable_return_statement 05136 | friend class details::return_node<T>; 05137 | friend class details::return_envelope_node<T>; 05138 | #endif 05139 | }; 05140 | 05141 | namespace details 05142 | { 05143 | enum operator_type 05144 | { 05145 | e_default , e_null , e_add , e_sub , 05146 | e_mul , e_div , e_mod , e_pow , 05147 | e_atan2 , e_min , e_max , e_avg , 05148 | e_sum , e_prod , e_lt , e_lte , 05149 | e_eq , e_equal , e_ne , e_nequal , 05150 | e_gte , e_gt , e_and , e_nand , 05151 | e_or , e_nor , e_xor , e_xnor , 05152 | e_mand , e_mor , e_scand , e_scor , 05153 | e_shr , e_shl , e_abs , e_acos , 05154 | e_acosh , e_asin , e_asinh , e_atan , 05155 | e_atanh , e_ceil , e_cos , e_cosh , 05156 | e_exp , e_expm1 , e_floor , e_log , 05157 | e_log10 , e_log2 , e_log1p , e_logn , 05158 | e_neg , e_pos , e_round , e_roundn , 05159 | e_root , e_sqrt , e_sin , e_sinc , 05160 | e_sinh , e_sec , e_csc , e_tan , 05161 | e_tanh , e_cot , e_clamp , e_iclamp , 05162 | e_inrange , e_sgn , e_r2d , e_d2r , 05163 | e_d2g , e_g2d , e_hypot , e_notl , 05164 | e_erf , e_erfc , e_ncdf , e_frac , 05165 | e_trunc , e_assign , e_addass , e_subass , 05166 | e_mulass , e_divass , e_modass , e_in , 05167 | e_like , e_ilike , e_multi , e_smulti , 05168 | e_swap , 05169 | 05170 | // Do not add new functions/operators after this point. 05171 | e_sf00 = 1000, e_sf01 = 1001, e_sf02 = 1002, e_sf03 = 1003, 05172 | e_sf04 = 1004, e_sf05 = 1005, e_sf06 = 1006, e_sf07 = 1007, 05173 | e_sf08 = 1008, e_sf09 = 1009, e_sf10 = 1010, e_sf11 = 1011, 05174 | e_sf12 = 1012, e_sf13 = 1013, e_sf14 = 1014, e_sf15 = 1015, 05175 | e_sf16 = 1016, e_sf17 = 1017, e_sf18 = 1018, e_sf19 = 1019, 05176 | e_sf20 = 1020, e_sf21 = 1021, e_sf22 = 1022, e_sf23 = 1023, 05177 | e_sf24 = 1024, e_sf25 = 1025, e_sf26 = 1026, e_sf27 = 1027, 05178 | e_sf28 = 1028, e_sf29 = 1029, e_sf30 = 1030, e_sf31 = 1031, 05179 | e_sf32 = 1032, e_sf33 = 1033, e_sf34 = 1034, e_sf35 = 1035, 05180 | e_sf36 = 1036, e_sf37 = 1037, e_sf38 = 1038, e_sf39 = 1039, 05181 | e_sf40 = 1040, e_sf41 = 1041, e_sf42 = 1042, e_sf43 = 1043, 05182 | e_sf44 = 1044, e_sf45 = 1045, e_sf46 = 1046, e_sf47 = 1047, 05183 | e_sf48 = 1048, e_sf49 = 1049, e_sf50 = 1050, e_sf51 = 1051, 05184 | e_sf52 = 1052, e_sf53 = 1053, e_sf54 = 1054, e_sf55 = 1055, 05185 | e_sf56 = 1056, e_sf57 = 1057, e_sf58 = 1058, e_sf59 = 1059, 05186 | e_sf60 = 1060, e_sf61 = 1061, e_sf62 = 1062, e_sf63 = 1063, 05187 | e_sf64 = 1064, e_sf65 = 1065, e_sf66 = 1066, e_sf67 = 1067, 05188 | e_sf68 = 1068, e_sf69 = 1069, e_sf70 = 1070, e_sf71 = 1071, 05189 | e_sf72 = 1072, e_sf73 = 1073, e_sf74 = 1074, e_sf75 = 1075, 05190 | e_sf76 = 1076, e_sf77 = 1077, e_sf78 = 1078, e_sf79 = 1079, 05191 | e_sf80 = 1080, e_sf81 = 1081, e_sf82 = 1082, e_sf83 = 1083, 05192 | e_sf84 = 1084, e_sf85 = 1085, e_sf86 = 1086, e_sf87 = 1087, 05193 | e_sf88 = 1088, e_sf89 = 1089, e_sf90 = 1090, e_sf91 = 1091, 05194 | e_sf92 = 1092, e_sf93 = 1093, e_sf94 = 1094, e_sf95 = 1095, 05195 | e_sf96 = 1096, e_sf97 = 1097, e_sf98 = 1098, e_sf99 = 1099, 05196 | e_sffinal = 1100, 05197 | e_sf4ext00 = 2000, e_sf4ext01 = 2001, e_sf4ext02 = 2002, e_sf4ext03 = 2003, 05198 | e_sf4ext04 = 2004, e_sf4ext05 = 2005, e_sf4ext06 = 2006, e_sf4ext07 = 2007, 05199 | e_sf4ext08 = 2008, e_sf4ext09 = 2009, e_sf4ext10 = 2010, e_sf4ext11 = 2011, 05200 | e_sf4ext12 = 2012, e_sf4ext13 = 2013, e_sf4ext14 = 2014, e_sf4ext15 = 2015, 05201 | e_sf4ext16 = 2016, e_sf4ext17 = 2017, e_sf4ext18 = 2018, e_sf4ext19 = 2019, 05202 | e_sf4ext20 = 2020, e_sf4ext21 = 2021, e_sf4ext22 = 2022, e_sf4ext23 = 2023, 05203 | e_sf4ext24 = 2024, e_sf4ext25 = 2025, e_sf4ext26 = 2026, e_sf4ext27 = 2027, 05204 | e_sf4ext28 = 2028, e_sf4ext29 = 2029, e_sf4ext30 = 2030, e_sf4ext31 = 2031, 05205 | e_sf4ext32 = 2032, e_sf4ext33 = 2033, e_sf4ext34 = 2034, e_sf4ext35 = 2035, 05206 | e_sf4ext36 = 2036, e_sf4ext37 = 2037, e_sf4ext38 = 2038, e_sf4ext39 = 2039, 05207 | e_sf4ext40 = 2040, e_sf4ext41 = 2041, e_sf4ext42 = 2042, e_sf4ext43 = 2043, 05208 | e_sf4ext44 = 2044, e_sf4ext45 = 2045, e_sf4ext46 = 2046, e_sf4ext47 = 2047, 05209 | e_sf4ext48 = 2048, e_sf4ext49 = 2049, e_sf4ext50 = 2050, e_sf4ext51 = 2051, 05210 | e_sf4ext52 = 2052, e_sf4ext53 = 2053, e_sf4ext54 = 2054, e_sf4ext55 = 2055, 05211 | e_sf4ext56 = 2056, e_sf4ext57 = 2057, e_sf4ext58 = 2058, e_sf4ext59 = 2059, 05212 | e_sf4ext60 = 2060, e_sf4ext61 = 2061 05213 | }; 05214 | 05215 | inline std::string to_str(const operator_type opr) 05216 | { 05217 | switch (opr) 05218 | { 05219 | case e_add : return "+" ; 05220 | case e_sub : return "-" ; 05221 | case e_mul : return "*" ; 05222 | case e_div : return "/" ; 05223 | case e_mod : return "%" ; 05224 | case e_pow : return "^" ; 05225 | case e_assign : return ":=" ; 05226 | case e_addass : return "+=" ; 05227 | case e_subass : return "-=" ; 05228 | case e_mulass : return "*=" ; 05229 | case e_divass : return "/=" ; 05230 | case e_modass : return "%=" ; 05231 | case e_lt : return "<" ; 05232 | case e_lte : return "<=" ; 05233 | case e_eq : return "==" ; 05234 | case e_equal : return "=" ; 05235 | case e_ne : return "!=" ; 05236 | case e_nequal : return "<>" ; 05237 | case e_gte : return ">=" ; 05238 | case e_gt : return ">" ; 05239 | case e_and : return "and" ; 05240 | case e_or : return "or" ; 05241 | case e_xor : return "xor" ; 05242 | case e_nand : return "nand" 05243 | case e_nor : return "nor" ; 05244 | case e_xnor : return "xnor" 05245 | default : return "N/A" ; 05246 | } 05247 | } 05248 | 05249 | struct base_operation_t 05250 | { 05251 | base_operation_t(const operator_type t, const unsigned int& np) 05252 | : type(t) 05253 | , num_params(np) 05254 | {} 05255 | 05256 | operator_type type; 05257 | unsigned int num_params; 05258 | }; 05259 | 05260 | namespace loop_unroll 05261 | { 05262 | const unsigned int global_loop_batch_size = 05263 | #ifndef exprtk_disable_superscalar_unroll 05264 | 16; 05265 | #else 05266 | 4; 05267 | #endif 05268 | 05269 | struct details 05270 | { 05271 | explicit details(const std::size_t& vsize, 05272 | const unsigned int loop_batch_size = global_loop_batch_size) 05273 | : batch_size(loop_batch_size ) 05274 | , remainder (vsize % batch_size) 05275 | , upper_bound(static_cast<int>(vsize - (remainder ? loop_batch_size : 0))) 05276 | {} 05277 | 05278 | unsigned int batch_size; 05279 | int remainder; 05280 | int upper_bound; 05281 | }; 05282 | } 05283 | 05284 | #ifdef exprtk_enable_debugging 05285 | inline void dump_ptr(const std::string& s, const void* ptr, const std::size_t size = 0) 05286 | { 05287 | if (size) 05288 | exprtk_debug(("%s - addr: %p size: %d\n", 05289 | s.c_str(), 05290 | ptr, 05291 | static_cast<unsigned int>(size))); 05292 | else 05293 | exprtk_debug(("%s - addr: %p\n", s.c_str(), ptr)); 05294 | } 05295 | 05296 | template <typename T> 05297 | inline void dump_vector(const std::string& vec_name, const T* data, const std::size_t size) 05298 | { 05299 | printf("----- %s (%p) -----\n", 05300 | vec_name.c_str(), 05301 | static_cast<const void*>(data)); 05302 | printf("[ "); 05303 | for (std::size_t i = 0; i < size; ++i) 05304 | { 05305 | printf("%8.3f\t", data[i]); 05306 | } 05307 | printf(" ]\n"); 05308 | printf("---------------------\n"); 05309 | } 05310 | #else 05311 | inline void dump_ptr(const std::string&, const void*) {} 05312 | inline void dump_ptr(const std::string&, const void*, const std::size_t) {} 05313 | template <typename T> 05314 | inline void dump_vector(const std::string&, const T*, const std::size_t) {} 05315 | #endif 05316 | 05317 | template <typename T> 05318 | class vec_data_store 05319 | { 05320 | public: 05321 | 05322 | typedef vec_data_store<T> type; 05323 | typedef T* data_t; 05324 | 05325 | private: 05326 | 05327 | struct control_block 05328 | { 05329 | control_block() 05330 | : ref_count(1) 05331 | , size (0) 05332 | , data (0) 05333 | , destruct (true) 05334 | {} 05335 | 05336 | explicit control_block(const std::size_t& dsize) 05337 | : ref_count(1 ) 05338 | , size (dsize) 05339 | , data (0 ) 05340 | , destruct (true ) 05341 | { create_data(); } 05342 | 05343 | control_block(const std::size_t& dsize, data_t dptr, bool dstrct = false) 05344 | : ref_count(1 ) 05345 | , size (dsize ) 05346 | , data (dptr ) 05347 | , destruct (dstrct) 05348 | {} 05349 | 05350 | ~control_block() 05351 | { 05352 | if (data && destruct && (0 == ref_count)) 05353 | { 05354 | dump_ptr("~vec_data_store::control_block() data",data); 05355 | delete[] data; 05356 | data = reinterpret_cast<data_t>(0); 05357 | } 05358 | } 05359 | 05360 | static inline control_block* create(const std::size_t& dsize, data_t data_ptr = data_t(0), bool dstrct = false) 05361 | { 05362 | if (dsize) 05363 | { 05364 | if (0 == data_ptr) 05365 | return (new control_block(dsize)); 05366 | else 05367 | return (new control_block(dsize, data_ptr, dstrct)); 05368 | } 05369 | else 05370 | return (new control_block); 05371 | } 05372 | 05373 | static inline void destroy(control_block*& cntrl_blck) 05374 | { 05375 | if (cntrl_blck) 05376 | { 05377 | if ( 05378 | (0 != cntrl_blck->ref_count) && 05379 | (0 == --cntrl_blck->ref_count) 05380 | ) 05381 | { 05382 | delete cntrl_blck; 05383 | } 05384 | 05385 | cntrl_blck = 0; 05386 | } 05387 | } 05388 | 05389 | std::size_t ref_count; 05390 | std::size_t size; 05391 | data_t data; 05392 | bool destruct; 05393 | 05394 | private: 05395 | 05396 | control_block(const control_block&) exprtk_delete; 05397 | control_block& operator=(const control_block&) exprtk_delete; 05398 | 05399 | inline void create_data() 05400 | { 05401 | destruct = true; 05402 | data = new T[size]; 05403 | std::fill_n(data, size, T(0)); 05404 | dump_ptr("control_block::create_data() - data", data, size); 05405 | } 05406 | }; 05407 | 05408 | public: 05409 | 05410 | vec_data_store() 05411 | : control_block_(control_block::create(0)) 05412 | {} 05413 | 05414 | explicit vec_data_store(const std::size_t& size) 05415 | : control_block_(control_block::create(size,reinterpret_cast<data_t>(0),true)) 05416 | {} 05417 | 05418 | vec_data_store(const std::size_t& size, data_t data, bool dstrct = false) 05419 | : control_block_(control_block::create(size, data, dstrct)) 05420 | {} 05421 | 05422 | vec_data_store(const type& vds) 05423 | { 05424 | control_block_ = vds.control_block_; 05425 | control_block_->ref_count++; 05426 | } 05427 | 05428 | ~vec_data_store() 05429 | { 05430 | control_block::destroy(control_block_); 05431 | } 05432 | 05433 | type& operator=(const type& vds) 05434 | { 05435 | if (this != &vds) 05436 | { 05437 | const std::size_t final_size = min_size(control_block_, vds.control_block_); 05438 | 05439 | vds.control_block_->size = final_size; 05440 | control_block_->size = final_size; 05441 | 05442 | if (control_block_->destruct || (0 == control_block_->data)) 05443 | { 05444 | control_block::destroy(control_block_); 05445 | 05446 | control_block_ = vds.control_block_; 05447 | control_block_->ref_count++; 05448 | } 05449 | } 05450 | 05451 | return (*this); 05452 | } 05453 | 05454 | inline data_t data() 05455 | { 05456 | return control_block_->data; 05457 | } 05458 | 05459 | inline data_t data() const 05460 | { 05461 | return control_block_->data; 05462 | } 05463 | 05464 | inline std::size_t size() const 05465 | { 05466 | return control_block_->size; 05467 | } 05468 | 05469 | inline data_t& ref() 05470 | { 05471 | return control_block_->data; 05472 | } 05473 | 05474 | inline void dump() const 05475 | { 05476 | #ifdef exprtk_enable_debugging 05477 | exprtk_debug(("size: %d\taddress:%p\tdestruct:%c\n", 05478 | size(), 05479 | data(), 05480 | (control_block_->destruct ? 'T' : 'F'))); 05481 | 05482 | for (std::size_t i = 0; i < size(); ++i) 05483 | { 05484 | if (5 == i) 05485 | exprtk_debug(("\n")); 05486 | 05487 | exprtk_debug(("%15.10f ", data()[i])); 05488 | } 05489 | exprtk_debug(("\n")); 05490 | #endif 05491 | } 05492 | 05493 | static inline void match_sizes(type& vds0, type& vds1) 05494 | { 05495 | const std::size_t size = min_size(vds0.control_block_,vds1.control_block_); 05496 | vds0.control_block_->size = size; 05497 | vds1.control_block_->size = size; 05498 | } 05499 | 05500 | private: 05501 | 05502 | static inline std::size_t min_size(const control_block* cb0, const control_block* cb1) 05503 | { 05504 | const std::size_t size0 = cb0->size; 05505 | const std::size_t size1 = cb1->size; 05506 | 05507 | if (size0 && size1) 05508 | return std::min(size0,size1); 05509 | else 05510 | return (size0) ? size0 : size1; 05511 | } 05512 | 05513 | control_block* control_block_; 05514 | }; 05515 | 05516 | namespace numeric 05517 | { 05518 | namespace details 05519 | { 05520 | template <typename T> 05521 | inline T process_impl(const operator_type operation, const T arg) 05522 | { 05523 | switch (operation) 05524 | { 05525 | case e_abs : return numeric::abs (arg); 05526 | case e_acos : return numeric::acos (arg); 05527 | case e_acosh : return numeric::acosh(arg); 05528 | case e_asin : return numeric::asin (arg); 05529 | case e_asinh : return numeric::asinh(arg); 05530 | case e_atan : return numeric::atan (arg); 05531 | case e_atanh : return numeric::atanh(arg); 05532 | case e_ceil : return numeric::ceil (arg); 05533 | case e_cos : return numeric::cos (arg); 05534 | case e_cosh : return numeric::cosh (arg); 05535 | case e_exp : return numeric::exp (arg); 05536 | case e_expm1 : return numeric::expm1(arg); 05537 | case e_floor : return numeric::floor(arg); 05538 | case e_log : return numeric::log (arg); 05539 | case e_log10 : return numeric::log10(arg); 05540 | case e_log2 : return numeric::log2 (arg); 05541 | case e_log1p : return numeric::log1p(arg); 05542 | case e_neg : return numeric::neg (arg); 05543 | case e_pos : return numeric::pos (arg); 05544 | case e_round : return numeric::round(arg); 05545 | case e_sin : return numeric::sin (arg); 05546 | case e_sinc : return numeric::sinc (arg); 05547 | case e_sinh : return numeric::sinh (arg); 05548 | case e_sqrt : return numeric::sqrt (arg); 05549 | case e_tan : return numeric::tan (arg); 05550 | case e_tanh : return numeric::tanh (arg); 05551 | case e_cot : return numeric::cot (arg); 05552 | case e_sec : return numeric::sec (arg); 05553 | case e_csc : return numeric::csc (arg); 05554 | case e_r2d : return numeric::r2d (arg); 05555 | case e_d2r : return numeric::d2r (arg); 05556 | case e_d2g : return numeric::d2g (arg); 05557 | case e_g2d : return numeric::g2d (arg); 05558 | case e_notl : return numeric::notl (arg); 05559 | case e_sgn : return numeric::sgn (arg); 05560 | case e_erf : return numeric::erf (arg); 05561 | case e_erfc : return numeric::erfc (arg); 05562 | case e_ncdf : return numeric::ncdf (arg); 05563 | case e_frac : return numeric::frac (arg); 05564 | case e_trunc : return numeric::trunc(arg); 05565 | 05566 | default : exprtk_debug(("numeric::details::process_impl<T> - Invalid unary operation.\n")); 05567 | return std::numeric_limits<T>::quiet_NaN(); 05568 | } 05569 | } 05570 | 05571 | template <typename T> 05572 | inline T process_impl(const operator_type operation, const T arg0, const T arg1) 05573 | { 05574 | switch (operation) 05575 | { 05576 | case e_add : return (arg0 + arg1); 05577 | case e_sub : return (arg0 - arg1); 05578 | case e_mul : return (arg0 * arg1); 05579 | case e_div : return (arg0 / arg1); 05580 | case e_mod : return modulus<T>(arg0,arg1); 05581 | case e_pow : return pow<T>(arg0,arg1); 05582 | case e_atan2 : return atan2<T>(arg0,arg1); 05583 | case e_min : return std::min<T>(arg0,arg1); 05584 | case e_max : return std::max<T>(arg0,arg1); 05585 | case e_logn : return logn<T>(arg0,arg1); 05586 | case e_lt : return (arg0 < arg1) ? T(1) : T(0); 05587 | case e_lte : return (arg0 <= arg1) ? T(1) : T(0); 05588 | case e_eq : return std::equal_to<T>()(arg0,arg1) ? T(1) : T(0); 05589 | case e_ne : return std::not_equal_to<T>()(arg0,arg1) ? T(1) : T(0); 05590 | case e_gte : return (arg0 >= arg1) ? T(1) : T(0); 05591 | case e_gt : return (arg0 > arg1) ? T(1) : T(0); 05592 | case e_and : return and_opr <T>(arg0,arg1); 05593 | case e_nand : return nand_opr<T>(arg0,arg1); 05594 | case e_or : return or_opr <T>(arg0,arg1); 05595 | case e_nor : return nor_opr <T>(arg0,arg1); 05596 | case e_xor : return xor_opr <T>(arg0,arg1); 05597 | case e_xnor : return xnor_opr<T>(arg0,arg1); 05598 | case e_root : return root <T>(arg0,arg1); 05599 | case e_roundn : return roundn <T>(arg0,arg1); 05600 | case e_equal : return equal <T>(arg0,arg1); 05601 | case e_nequal : return nequal <T>(arg0,arg1); 05602 | case e_hypot : return hypot <T>(arg0,arg1); 05603 | case e_shr : return shr <T>(arg0,arg1); 05604 | case e_shl : return shl <T>(arg0,arg1); 05605 | 05606 | default : exprtk_debug(("numeric::details::process_impl<T> - Invalid binary operation.\n")); 05607 | return std::numeric_limits<T>::quiet_NaN(); 05608 | } 05609 | } 05610 | 05611 | template <typename T> 05612 | inline T process_impl(const operator_type operation, const T arg0, const T arg1, int_type_tag) 05613 | { 05614 | switch (operation) 05615 | { 05616 | case e_add : return (arg0 + arg1); 05617 | case e_sub : return (arg0 - arg1); 05618 | case e_mul : return (arg0 * arg1); 05619 | case e_div : return (arg0 / arg1); 05620 | case e_mod : return arg0 % arg1; 05621 | case e_pow : return pow<T>(arg0,arg1); 05622 | case e_min : return std::min<T>(arg0,arg1); 05623 | case e_max : return std::max<T>(arg0,arg1); 05624 | case e_logn : return logn<T>(arg0,arg1); 05625 | case e_lt : return (arg0 < arg1) ? T(1) : T(0); 05626 | case e_lte : return (arg0 <= arg1) ? T(1) : T(0); 05627 | case e_eq : return (arg0 == arg1) ? T(1) : T(0); 05628 | case e_ne : return (arg0 != arg1) ? T(1) : T(0); 05629 | case e_gte : return (arg0 >= arg1) ? T(1) : T(0); 05630 | case e_gt : return (arg0 > arg1) ? T(1) : T(0); 05631 | case e_and : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(1) : T(0); 05632 | case e_nand : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(0) : T(1); 05633 | case e_or : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(1) : T(0); 05634 | case e_nor : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(0) : T(1); 05635 | case e_xor : return arg0 ^ arg1; 05636 | case e_xnor : return !(arg0 ^ arg1); 05637 | case e_root : return root<T>(arg0,arg1); 05638 | case e_equal : return arg0 == arg1; 05639 | case e_nequal : return arg0 != arg1; 05640 | case e_hypot : return hypot<T>(arg0,arg1); 05641 | case e_shr : return arg0 >> arg1; 05642 | case e_shl : return arg0 << arg1; 05643 | 05644 | default : exprtk_debug(("numeric::details::process_impl<IntType> - Invalid binary operation.\n")); 05645 | return std::numeric_limits<T>::quiet_NaN(); 05646 | } 05647 | } 05648 | } 05649 | 05650 | template <typename T> 05651 | inline T process(const operator_type operation, const T arg) 05652 | { 05653 | return exprtk::details::numeric::details::process_impl(operation,arg); 05654 | } 05655 | 05656 | template <typename T> 05657 | inline T process(const operator_type operation, const T arg0, const T arg1) 05658 | { 05659 | return exprtk::details::numeric::details::process_impl(operation, arg0, arg1); 05660 | } 05661 | } 05662 | 05663 | template <typename Node> 05664 | struct node_collector_interface 05665 | { 05666 | typedef Node* node_ptr_t; 05667 | typedef Node** node_pp_t; 05668 | typedef std::vector<node_pp_t> noderef_list_t; 05669 | 05670 | virtual ~node_collector_interface() 05671 | {} 05672 | 05673 | virtual void collect_nodes(noderef_list_t&) 05674 | {} 05675 | }; 05676 | 05677 | template <typename Node> 05678 | struct node_depth_base; 05679 | 05680 | template <typename T> 05681 | class expression_node : public node_collector_interface<expression_node<T> > 05682 | , public node_depth_base<expression_node<T> > 05683 | { 05684 | public: 05685 | 05686 | enum node_type 05687 | { 05688 | e_none , e_null , e_constant , e_unary , 05689 | e_binary , e_binary_ext , e_trinary , e_quaternary , 05690 | e_vararg , e_conditional , e_while , e_repeat , 05691 | e_for , e_switch , e_mswitch , e_return , 05692 | e_retenv , e_variable , e_stringvar , e_stringconst , 05693 | e_stringvarrng , e_cstringvarrng , e_strgenrange , e_strconcat , 05694 | e_stringvarsize , e_strswap , e_stringsize , e_stringvararg , 05695 | e_function , e_vafunction , e_genfunction , e_strfunction , 05696 | e_strcondition , e_strccondition , e_add , e_sub , 05697 | e_mul , e_div , e_mod , e_pow , 05698 | e_lt , e_lte , e_gt , e_gte , 05699 | e_eq , e_ne , e_and , e_nand , 05700 | e_or , e_nor , e_xor , e_xnor , 05701 | e_in , e_like , e_ilike , e_inranges , 05702 | e_ipow , e_ipowinv , e_abs , e_acos , 05703 | e_acosh , e_asin , e_asinh , e_atan , 05704 | e_atanh , e_ceil , e_cos , e_cosh , 05705 | e_exp , e_expm1 , e_floor , e_log , 05706 | e_log10 , e_log2 , e_log1p , e_neg , 05707 | e_pos , e_round , e_sin , e_sinc , 05708 | e_sinh , e_sqrt , e_tan , e_tanh , 05709 | e_cot , e_sec , e_csc , e_r2d , 05710 | e_d2r , e_d2g , e_g2d , e_notl , 05711 | e_sgn , e_erf , e_erfc , e_ncdf , 05712 | e_frac , e_trunc , e_uvouv , e_vov , 05713 | e_cov , e_voc , e_vob , e_bov , 05714 | e_cob , e_boc , e_vovov , e_vovoc , 05715 | e_vocov , e_covov , e_covoc , e_vovovov , 05716 | e_vovovoc , e_vovocov , e_vocovov , e_covovov , 05717 | e_covocov , e_vocovoc , e_covovoc , e_vococov , 05718 | e_sf3ext , e_sf4ext , e_nulleq , e_strass , 05719 | e_vector , e_vecsize , e_vecelem , e_veccelem , 05720 | e_vecelemrtc , e_veccelemrtc , e_rbvecelem , e_rbvecelemrtc , 05721 | e_rbveccelem , e_rbveccelemrtc , e_vecinit , e_vecvalass , 05722 | e_vecvecass , e_vecopvalass , e_vecopvecass , e_vecfunc , 05723 | e_vecvecswap , e_vecvecineq , e_vecvalineq , e_valvecineq , 05724 | e_vecvecarith , e_vecvalarith , e_valvecarith , e_vecunaryop , 05725 | e_vecondition , e_break , e_continue , e_swap , 05726 | e_assert 05727 | }; 05728 | 05729 | typedef T value_type; 05730 | typedef expression_node<T>* expression_ptr; 05731 | typedef node_collector_interface<expression_node<T> > nci_t; 05732 | typedef typename nci_t::noderef_list_t noderef_list_t; 05733 | typedef node_depth_base<expression_node<T> > ndb_t; 05734 | 05735 | virtual ~expression_node() 05736 | {} 05737 | 05738 | inline virtual T value() const 05739 | { 05740 | return std::numeric_limits<T>::quiet_NaN(); 05741 | } 05742 | 05743 | inline virtual expression_node<T>* branch(const std::size_t& index = 0) const 05744 | { 05745 | return reinterpret_cast<expression_ptr>(index * 0); 05746 | } 05747 | 05748 | inline virtual node_type type() const 05749 | { 05750 | return e_none; 05751 | } 05752 | 05753 | inline virtual bool valid() const 05754 | { 05755 | return true; 05756 | } 05757 | }; // class expression_node 05758 | 05759 | template <typename T> 05760 | inline bool is_generally_string_node(const expression_node<T>* node); 05761 | 05762 | inline bool is_true(const double v) 05763 | { 05764 | return std::not_equal_to<double>()(0.0,v); 05765 | } 05766 | 05767 | inline bool is_true(const long double v) 05768 | { 05769 | return std::not_equal_to<long double>()(0.0L,v); 05770 | } 05771 | 05772 | inline bool is_true(const float v) 05773 | { 05774 | return std::not_equal_to<float>()(0.0f,v); 05775 | } 05776 | 05777 | template <typename T> 05778 | inline bool is_true(const expression_node<T>* node) 05779 | { 05780 | return std::not_equal_to<T>()(T(0),node->value()); 05781 | } 05782 | 05783 | template <typename T> 05784 | inline bool is_true(const std::pair<expression_node<T>*,bool>& node) 05785 | { 05786 | return std::not_equal_to<T>()(T(0),node.first->value()); 05787 | } 05788 | 05789 | template <typename T> 05790 | inline bool is_false(const expression_node<T>* node) 05791 | { 05792 | return std::equal_to<T>()(T(0),node->value()); 05793 | } 05794 | 05795 | template <typename T> 05796 | inline bool is_false(const std::pair<expression_node<T>*,bool>& node) 05797 | { 05798 | return std::equal_to<T>()(T(0),node.first->value()); 05799 | } 05800 | 05801 | template <typename T> 05802 | inline bool is_literal_node(const expression_node<T>* node) 05803 | { 05804 | return node && (details::expression_node<T>::e_constant == node->type()); 05805 | } 05806 | 05807 | template <typename T> 05808 | inline bool is_unary_node(const expression_node<T>* node) 05809 | { 05810 | return node && (details::expression_node<T>::e_unary == node->type()); 05811 | } 05812 | 05813 | template <typename T> 05814 | inline bool is_neg_unary_node(const expression_node<T>* node) 05815 | { 05816 | return node && (details::expression_node<T>::e_neg == node->type()); 05817 | } 05818 | 05819 | template <typename T> 05820 | inline bool is_binary_node(const expression_node<T>* node) 05821 | { 05822 | return node && (details::expression_node<T>::e_binary == node->type()); 05823 | } 05824 | 05825 | template <typename T> 05826 | inline bool is_variable_node(const expression_node<T>* node) 05827 | { 05828 | return node && (details::expression_node<T>::e_variable == node->type()); 05829 | } 05830 | 05831 | template <typename T> 05832 | inline bool is_ivariable_node(const expression_node<T>* node) 05833 | { 05834 | return node && 05835 | ( 05836 | details::expression_node<T>::e_variable == node->type() || 05837 | details::expression_node<T>::e_vecelem == node->type() || 05838 | details::expression_node<T>::e_veccelem == node->type() || 05839 | details::expression_node<T>::e_vecelemrtc == node->type() || 05840 | details::expression_node<T>::e_veccelemrtc == node->type() || 05841 | details::expression_node<T>::e_rbvecelem == node->type() || 05842 | details::expression_node<T>::e_rbveccelem == node->type() || 05843 | details::expression_node<T>::e_rbvecelemrtc == node->type() || 05844 | details::expression_node<T>::e_rbveccelemrtc == node->type() 05845 | ); 05846 | } 05847 | 05848 | template <typename T> 05849 | inline bool is_vector_elem_node(const expression_node<T>* node) 05850 | { 05851 | return node && (details::expression_node<T>::e_vecelem == node->type()); 05852 | } 05853 | 05854 | template <typename T> 05855 | inline bool is_vector_celem_node(const expression_node<T>* node) 05856 | { 05857 | return node && (details::expression_node<T>::e_veccelem == node->type()); 05858 | } 05859 | 05860 | template <typename T> 05861 | inline bool is_vector_elem_rtc_node(const expression_node<T>* node) 05862 | { 05863 | return node && (details::expression_node<T>::e_vecelemrtc == node->type()); 05864 | } 05865 | 05866 | template <typename T> 05867 | inline bool is_vector_celem_rtc_node(const expression_node<T>* node) 05868 | { 05869 | return node && (details::expression_node<T>::e_veccelemrtc == node->type()); 05870 | } 05871 | 05872 | template <typename T> 05873 | inline bool is_rebasevector_elem_node(const expression_node<T>* node) 05874 | { 05875 | return node && (details::expression_node<T>::e_rbvecelem == node->type()); 05876 | } 05877 | 05878 | template <typename T> 05879 | inline bool is_rebasevector_elem_rtc_node(const expression_node<T>* node) 05880 | { 05881 | return node && (details::expression_node<T>::e_rbvecelemrtc == node->type()); 05882 | } 05883 | 05884 | template <typename T> 05885 | inline bool is_rebasevector_celem_rtc_node(const expression_node<T>* node) 05886 | { 05887 | return node && (details::expression_node<T>::e_rbveccelemrtc == node->type()); 05888 | } 05889 | 05890 | template <typename T> 05891 | inline bool is_rebasevector_celem_node(const expression_node<T>* node) 05892 | { 05893 | return node && (details::expression_node<T>::e_rbveccelem == node->type()); 05894 | } 05895 | 05896 | template <typename T> 05897 | inline bool is_vector_node(const expression_node<T>* node) 05898 | { 05899 | return node && (details::expression_node<T>::e_vector == node->type()); 05900 | } 05901 | 05902 | template <typename T> 05903 | inline bool is_ivector_node(const expression_node<T>* node) 05904 | { 05905 | if (node) 05906 | { 05907 | switch (node->type()) 05908 | { 05909 | case details::expression_node<T>::e_vector : 05910 | case details::expression_node<T>::e_vecvalass : 05911 | case details::expression_node<T>::e_vecvecass : 05912 | case details::expression_node<T>::e_vecopvalass : 05913 | case details::expression_node<T>::e_vecopvecass : 05914 | case details::expression_node<T>::e_vecvecswap : 05915 | case details::expression_node<T>::e_vecvecarith : 05916 | case details::expression_node<T>::e_vecvalarith : 05917 | case details::expression_node<T>::e_valvecarith : 05918 | case details::expression_node<T>::e_vecunaryop : 05919 | case details::expression_node<T>::e_vecondition : return true; 05920 | default : return false; 05921 | } 05922 | } 05923 | else 05924 | return false; 05925 | } 05926 | 05927 | template <typename T> 05928 | inline bool amalgamated_vecop(const expression_node<T>* node) 05929 | { 05930 | if (node) 05931 | { 05932 | switch (node->type()) 05933 | { 05934 | case details::expression_node<T>::e_vecvecarith : 05935 | case details::expression_node<T>::e_vecvalarith : 05936 | case details::expression_node<T>::e_valvecarith : 05937 | case details::expression_node<T>::e_vecunaryop : return true; 05938 | default : return false; 05939 | } 05940 | } 05941 | else 05942 | return false; 05943 | } 05944 | 05945 | template <typename T> 05946 | inline bool is_constant_node(const expression_node<T>* node) 05947 | { 05948 | return node && 05949 | ( 05950 | details::expression_node<T>::e_constant == node->type() || 05951 | details::expression_node<T>::e_stringconst == node->type() 05952 | ); 05953 | } 05954 | 05955 | template <typename T> 05956 | inline bool is_null_node(const expression_node<T>* node) 05957 | { 05958 | return node && (details::expression_node<T>::e_null == node->type()); 05959 | } 05960 | 05961 | template <typename T> 05962 | inline bool is_break_node(const expression_node<T>* node) 05963 | { 05964 | return node && (details::expression_node<T>::e_break == node->type()); 05965 | } 05966 | 05967 | template <typename T> 05968 | inline bool is_continue_node(const expression_node<T>* node) 05969 | { 05970 | return node && (details::expression_node<T>::e_continue == node->type()); 05971 | } 05972 | 05973 | template <typename T> 05974 | inline bool is_swap_node(const expression_node<T>* node) 05975 | { 05976 | return node && (details::expression_node<T>::e_swap == node->type()); 05977 | } 05978 | 05979 | template <typename T> 05980 | inline bool is_function(const expression_node<T>* node) 05981 | { 05982 | return node && (details::expression_node<T>::e_function == node->type()); 05983 | } 05984 | 05985 | template <typename T> 05986 | inline bool is_vararg_node(const expression_node<T>* node) 05987 | { 05988 | return node && (details::expression_node<T>::e_vararg == node->type()); 05989 | } 05990 | 05991 | template <typename T> 05992 | inline bool is_return_node(const expression_node<T>* node) 05993 | { 05994 | return node && (details::expression_node<T>::e_return == node->type()); 05995 | } 05996 | 05997 | template <typename T> class unary_node; 05998 | 05999 | template <typename T> 06000 | inline bool is_negate_node(const expression_node<T>* node) 06001 | { 06002 | if (node && is_unary_node(node)) 06003 | { 06004 | return (details::e_neg == static_cast<const unary_node<T>*>(node)->operation()); 06005 | } 06006 | else 06007 | return false; 06008 | } 06009 | 06010 | template <typename T> 06011 | inline bool is_assert_node(const expression_node<T>* node) 06012 | { 06013 | return node && (details::expression_node<T>::e_assert == node->type()); 06014 | } 06015 | 06016 | template <typename T> 06017 | inline bool branch_deletable(const expression_node<T>* node) 06018 | { 06019 | return (0 != node) && 06020 | !is_variable_node(node) && 06021 | !is_string_node (node) ; 06022 | } 06023 | 06024 | template <std::size_t N, typename T> 06025 | inline bool all_nodes_valid(expression_node<T>* const (&b)[N]) 06026 | { 06027 | for (std::size_t i = 0; i < N; ++i) 06028 | { 06029 | if (0 == b[i]) return false; 06030 | } 06031 | 06032 | return true; 06033 | } 06034 | 06035 | template <typename T, 06036 | typename Allocator, 06037 | template <typename, typename> class Sequence> 06038 | inline bool all_nodes_valid(const Sequence<expression_node<T>*,Allocator>& b) 06039 | { 06040 | for (std::size_t i = 0; i < b.size(); ++i) 06041 | { 06042 | if (0 == b[i]) return false; 06043 | } 06044 | 06045 | return true; 06046 | } 06047 | 06048 | template <std::size_t N, typename T> 06049 | inline bool all_nodes_variables(expression_node<T>* const (&b)[N]) 06050 | { 06051 | for (std::size_t i = 0; i < N; ++i) 06052 | { 06053 | if (0 == b[i]) 06054 | return false; 06055 | else if (!is_variable_node(b[i])) 06056 | return false; 06057 | } 06058 | 06059 | return true; 06060 | } 06061 | 06062 | template <typename T, 06063 | typename Allocator, 06064 | template <typename, typename> class Sequence> 06065 | inline bool all_nodes_variables(const Sequence<expression_node<T>*,Allocator>& b) 06066 | { 06067 | for (std::size_t i = 0; i < b.size(); ++i) 06068 | { 06069 | if (0 == b[i]) 06070 | return false; 06071 | else if (!is_variable_node(b[i])) 06072 | return false; 06073 | } 06074 | 06075 | return true; 06076 | } 06077 | 06078 | template <typename Node> 06079 | class node_collection_destructor 06080 | { 06081 | public: 06082 | 06083 | typedef node_collector_interface<Node> nci_t; 06084 | 06085 | typedef typename nci_t::node_ptr_t node_ptr_t; 06086 | typedef typename nci_t::node_pp_t node_pp_t; 06087 | typedef typename nci_t::noderef_list_t noderef_list_t; 06088 | 06089 | static void delete_nodes(node_ptr_t& root) 06090 | { 06091 | std::vector<node_pp_t> node_delete_list; 06092 | node_delete_list.reserve(1000); 06093 | 06094 | collect_nodes(root, node_delete_list); 06095 | 06096 | for (std::size_t i = 0; i < node_delete_list.size(); ++i) 06097 | { 06098 | node_ptr_t& node = *node_delete_list[i]; 06099 | exprtk_debug(("ncd::delete_nodes() - deleting: %p\n", reinterpret_cast<void*>(node))); 06100 | delete node; 06101 | node = reinterpret_cast<node_ptr_t>(0); 06102 | } 06103 | } 06104 | 06105 | private: 06106 | 06107 | static void collect_nodes(node_ptr_t& root, noderef_list_t& node_delete_list) 06108 | { 06109 | std::deque<node_ptr_t> node_list; 06110 | node_list.push_back(root); 06111 | node_delete_list.push_back(&root); 06112 | 06113 | noderef_list_t child_node_delete_list; 06114 | child_node_delete_list.reserve(1000); 06115 | 06116 | while (!node_list.empty()) 06117 | { 06118 | node_list.front()->collect_nodes(child_node_delete_list); 06119 | 06120 | if (!child_node_delete_list.empty()) 06121 | { 06122 | for (std::size_t i = 0; i < child_node_delete_list.size(); ++i) 06123 | { 06124 | node_pp_t& node = child_node_delete_list[i]; 06125 | 06126 | if (0 == (*node)) 06127 | { 06128 | exprtk_debug(("ncd::collect_nodes() - null node encountered.\n")); 06129 | } 06130 | 06131 | node_list.push_back(*node); 06132 | } 06133 | 06134 | node_delete_list.insert( 06135 | node_delete_list.end(), 06136 | child_node_delete_list.begin(), child_node_delete_list.end()); 06137 | 06138 | child_node_delete_list.clear(); 06139 | } 06140 | 06141 | node_list.pop_front(); 06142 | } 06143 | 06144 | std::reverse(node_delete_list.begin(), node_delete_list.end()); 06145 | } 06146 | }; 06147 | 06148 | template <typename NodeAllocator, typename T, std::size_t N> 06149 | inline void free_all_nodes(NodeAllocator& node_allocator, expression_node<T>* (&b)[N]) 06150 | { 06151 | for (std::size_t i = 0; i < N; ++i) 06152 | { 06153 | free_node(node_allocator,b[i]); 06154 | } 06155 | } 06156 | 06157 | template <typename NodeAllocator, 06158 | typename T, 06159 | typename Allocator, 06160 | template <typename, typename> class Sequence> 06161 | inline void free_all_nodes(NodeAllocator& node_allocator, Sequence<expression_node<T>*,Allocator>& b) 06162 | { 06163 | for (std::size_t i = 0; i < b.size(); ++i) 06164 | { 06165 | free_node(node_allocator,b[i]); 06166 | } 06167 | 06168 | b.clear(); 06169 | } 06170 | 06171 | template <typename NodeAllocator, typename T> 06172 | inline void free_node(NodeAllocator&, expression_node<T>*& node) 06173 | { 06174 | if ((0 == node) || is_variable_node(node) || is_string_node(node)) 06175 | { 06176 | return; 06177 | } 06178 | 06179 | node_collection_destructor<expression_node<T> > 06180 | ::delete_nodes(node); 06181 | } 06182 | 06183 | template <typename T> 06184 | inline void destroy_node(expression_node<T>*& node) 06185 | { 06186 | if (0 != node) 06187 | { 06188 | node_collection_destructor<expression_node<T> > 06189 | ::delete_nodes(node); 06190 | } 06191 | } 06192 | 06193 | template <typename Node> 06194 | struct node_depth_base 06195 | { 06196 | typedef Node* node_ptr_t; 06197 | typedef std::pair<node_ptr_t,bool> nb_pair_t; 06198 | 06199 | node_depth_base() 06200 | : depth_set(false) 06201 | , depth(0) 06202 | {} 06203 | 06204 | virtual ~node_depth_base() 06205 | {} 06206 | 06207 | virtual std::size_t node_depth() const { return 1; } 06208 | 06209 | std::size_t compute_node_depth(const Node* const& node) const 06210 | { 06211 | if (!depth_set) 06212 | { 06213 | depth = 1 + (node ? node->node_depth() : 0); 06214 | depth_set = true; 06215 | } 06216 | 06217 | return depth; 06218 | } 06219 | 06220 | std::size_t compute_node_depth(const nb_pair_t& branch) const 06221 | { 06222 | if (!depth_set) 06223 | { 06224 | depth = 1 + (branch.first ? branch.first->node_depth() : 0); 06225 | depth_set = true; 06226 | } 06227 | 06228 | return depth; 06229 | } 06230 | 06231 | template <std::size_t N> 06232 | std::size_t compute_node_depth(const nb_pair_t (&branch)[N]) const 06233 | { 06234 | if (!depth_set) 06235 | { 06236 | depth = 0; 06237 | 06238 | for (std::size_t i = 0; i < N; ++i) 06239 | { 06240 | if (branch[i].first) 06241 | { 06242 | depth = std::max(depth,branch[i].first->node_depth()); 06243 | } 06244 | } 06245 | 06246 | depth += 1; 06247 | depth_set = true; 06248 | } 06249 | 06250 | return depth; 06251 | } 06252 | 06253 | template <typename BranchType> 06254 | std::size_t max_node_depth(const BranchType& n0, const BranchType& n1) const 06255 | { 06256 | return std::max(compute_node_depth(n0), compute_node_depth(n1)); 06257 | } 06258 | 06259 | template <typename BranchType> 06260 | std::size_t max_node_depth(const BranchType& n0, const BranchType& n1, const BranchType& n2) const 06261 | { 06262 | return std::max(compute_node_depth(n0), 06263 | std::max(compute_node_depth(n1), compute_node_depth(n2))); 06264 | } 06265 | 06266 | template <typename BranchType> 06267 | std::size_t max_node_depth(const BranchType& n0, const BranchType& n1, 06268 | const BranchType& n2, const BranchType& n3) const 06269 | { 06270 | return std::max( 06271 | std::max(compute_node_depth(n0), compute_node_depth(n1)), 06272 | std::max(compute_node_depth(n2), compute_node_depth(n3))); 06273 | } 06274 | 06275 | template <typename BranchType> 06276 | std::size_t compute_node_depth(const BranchType& n0, const BranchType& n1) const 06277 | { 06278 | if (!depth_set) 06279 | { 06280 | depth = 1 + max_node_depth(n0, n1); 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 06290 | { 06291 | if (!depth_set) 06292 | { 06293 | depth = 1 + max_node_depth(n0, n1, n2); 06294 | depth_set = true; 06295 | } 06296 | 06297 | return depth; 06298 | } 06299 | 06300 | template <typename BranchType> 06301 | std::size_t compute_node_depth(const BranchType& n0, const BranchType& n1, 06302 | const BranchType& n2, const BranchType& n3) const 06303 | { 06304 | if (!depth_set) 06305 | { 06306 | depth = 1 + max_node_depth(n0, n1, n2, n3); 06307 | depth_set = true; 06308 | } 06309 | 06310 | return depth; 06311 | } 06312 | 06313 | template <typename Allocator, 06314 | template <typename, typename> class Sequence> 06315 | std::size_t compute_node_depth(const Sequence<node_ptr_t, Allocator>& branch_list) const 06316 | { 06317 | if (!depth_set) 06318 | { 06319 | for (std::size_t i = 0; i < branch_list.size(); ++i) 06320 | { 06321 | if (branch_list[i]) 06322 | { 06323 | depth = std::max(depth, compute_node_depth(branch_list[i])); 06324 | } 06325 | } 06326 | 06327 | depth_set = true; 06328 | } 06329 | 06330 | return depth; 06331 | } 06332 | 06333 | template <typename Allocator, 06334 | template <typename, typename> class Sequence> 06335 | std::size_t compute_node_depth(const Sequence<nb_pair_t,Allocator>& branch_list) const 06336 | { 06337 | if (!depth_set) 06338 | { 06339 | for (std::size_t i = 0; i < branch_list.size(); ++i) 06340 | { 06341 | if (branch_list[i].first) 06342 | { 06343 | depth = std::max(depth, compute_node_depth(branch_list[i].first)); 06344 | } 06345 | } 06346 | 06347 | depth_set = true; 06348 | } 06349 | 06350 | return depth; 06351 | } 06352 | 06353 | mutable bool depth_set; 06354 | mutable std::size_t depth; 06355 | 06356 | template <typename NodeSequence> 06357 | void collect(node_ptr_t const& node, 06358 | const bool deletable, 06359 | NodeSequence& delete_node_list) const 06360 | { 06361 | if ((0 != node) && deletable) 06362 | { 06363 | delete_node_list.push_back(const_cast<node_ptr_t*>(&node)); 06364 | } 06365 | } 06366 | 06367 | template <typename NodeSequence> 06368 | void collect(const nb_pair_t& branch, 06369 | NodeSequence& delete_node_list) const 06370 | { 06371 | collect(branch.first, branch.second, delete_node_list); 06372 | } 06373 | 06374 | template <typename NodeSequence> 06375 | void collect(Node*& node, 06376 | NodeSequence& delete_node_list) const 06377 | { 06378 | collect(node, branch_deletable(node), delete_node_list); 06379 | } 06380 | 06381 | template <std::size_t N, typename NodeSequence> 06382 | void collect(const nb_pair_t(&branch)[N], 06383 | NodeSequence& delete_node_list) const 06384 | { 06385 | for (std::size_t i = 0; i < N; ++i) 06386 | { 06387 | collect(branch[i].first, branch[i].second, delete_node_list); 06388 | } 06389 | } 06390 | 06391 | template <typename Allocator, 06392 | template <typename, typename> class Sequence, 06393 | typename NodeSequence> 06394 | void collect(const Sequence<nb_pair_t, Allocator>& branch, 06395 | NodeSequence& delete_node_list) const 06396 | { 06397 | for (std::size_t i = 0; i < branch.size(); ++i) 06398 | { 06399 | collect(branch[i].first, branch[i].second, delete_node_list); 06400 | } 06401 | } 06402 | 06403 | template <typename Allocator, 06404 | template <typename, typename> class Sequence, 06405 | typename NodeSequence> 06406 | void collect(const Sequence<node_ptr_t, Allocator>& branch_list, 06407 | NodeSequence& delete_node_list) const 06408 | { 06409 | for (std::size_t i = 0; i < branch_list.size(); ++i) 06410 | { 06411 | collect(branch_list[i], branch_deletable(branch_list[i]), delete_node_list); 06412 | } 06413 | } 06414 | 06415 | template <typename Boolean, 06416 | typename AllocatorT, 06417 | typename AllocatorB, 06418 | template <typename, typename> class Sequence, 06419 | typename NodeSequence> 06420 | void collect(const Sequence<node_ptr_t, AllocatorT>& branch_list, 06421 | const Sequence<Boolean, AllocatorB>& branch_deletable_list, 06422 | NodeSequence& delete_node_list) const 06423 | { 06424 | for (std::size_t i = 0; i < branch_list.size(); ++i) 06425 | { 06426 | collect(branch_list[i], branch_deletable_list[i], delete_node_list); 06427 | } 06428 | } 06429 | }; 06430 | 06431 | template <typename Type> 06432 | class vector_holder 06433 | { 06434 | private: 06435 | 06436 | typedef Type value_type; 06437 | typedef value_type* value_ptr; 06438 | typedef const value_ptr const_value_ptr; 06439 | typedef vector_holder<Type> vector_holder_t; 06440 | 06441 | class vector_holder_base 06442 | { 06443 | public: 06444 | 06445 | virtual ~vector_holder_base() 06446 | {} 06447 | 06448 | inline value_ptr operator[](const std::size_t& index) const 06449 | { 06450 | return value_at(index); 06451 | } 06452 | 06453 | inline std::size_t size() const 06454 | { 06455 | return vector_size(); 06456 | } 06457 | 06458 | inline std::size_t base_size() const 06459 | { 06460 | return vector_base_size(); 06461 | } 06462 | 06463 | inline value_ptr data() const 06464 | { 06465 | return value_at(0); 06466 | } 06467 | 06468 | virtual inline bool rebaseable() const 06469 | { 06470 | return false; 06471 | } 06472 | 06473 | virtual void set_ref(value_ptr*) 06474 | {} 06475 | 06476 | virtual void remove_ref(value_ptr*) 06477 | {} 06478 | 06479 | virtual void set_size_ref(std::size_t*) 06480 | {} 06481 | 06482 | virtual void remove_size_ref(std::size_t*) 06483 | {} 06484 | 06485 | virtual vector_view<Type>* rebaseable_instance() 06486 | { 06487 | return reinterpret_cast<vector_view<Type>*>(0); 06488 | } 06489 | 06490 | protected: 06491 | 06492 | virtual value_ptr value_at(const std::size_t&) const = 0; 06493 | virtual std::size_t vector_size() const = 0; 06494 | virtual std::size_t vector_base_size() const = 0; 06495 | }; 06496 | 06497 | class array_vector_impl exprtk_final : public vector_holder_base 06498 | { 06499 | public: 06500 | 06501 | array_vector_impl(const Type* vec, const std::size_t& vec_size) 06502 | : vec_(vec) 06503 | , size_(vec_size) 06504 | {} 06505 | 06506 | protected: 06507 | 06508 | value_ptr value_at(const std::size_t& index) const exprtk_override 06509 | { 06510 | assert(index < size_); 06511 | return const_cast<const_value_ptr>(vec_ + index); 06512 | } 06513 | 06514 | std::size_t vector_size() const exprtk_override 06515 | { 06516 | return size_; 06517 | } 06518 | 06519 | std::size_t vector_base_size() const exprtk_override 06520 | { 06521 | return vector_size(); 06522 | } 06523 | 06524 | private: 06525 | 06526 | array_vector_impl(const array_vector_impl&) exprtk_delete; 06527 | array_vector_impl& operator=(const array_vector_impl&) exprtk_delete; 06528 | 06529 | const Type* vec_; 06530 | const std::size_t size_; 06531 | }; 06532 | 06533 | template <typename Allocator, 06534 | template <typename, typename> class Sequence> 06535 | class sequence_vector_impl exprtk_final : public vector_holder_base 06536 | { 06537 | public: 06538 | 06539 | typedef Sequence<Type,Allocator> sequence_t; 06540 | 06541 | explicit sequence_vector_impl(sequence_t& seq) 06542 | : sequence_(seq) 06543 | {} 06544 | 06545 | protected: 06546 | 06547 | value_ptr value_at(const std::size_t& index) const exprtk_override 06548 | { 06549 | assert(index < sequence_.size()); 06550 | return (&sequence_[index]); 06551 | } 06552 | 06553 | std::size_t vector_size() const exprtk_override 06554 | { 06555 | return sequence_.size(); 06556 | } 06557 | 06558 | std::size_t vector_base_size() const exprtk_override 06559 | { 06560 | return vector_size(); 06561 | } 06562 | 06563 | private: 06564 | 06565 | sequence_vector_impl(const sequence_vector_impl&) exprtk_delete; 06566 | sequence_vector_impl& operator=(const sequence_vector_impl&) exprtk_delete; 06567 | 06568 | sequence_t& sequence_; 06569 | }; 06570 | 06571 | class vector_view_impl exprtk_final : public vector_holder_base 06572 | { 06573 | public: 06574 | 06575 | typedef exprtk::vector_view<Type> vector_view_t; 06576 | 06577 | explicit vector_view_impl(vector_view_t& vec_view) 06578 | : vec_view_(vec_view) 06579 | { 06580 | assert(vec_view_.size() > 0); 06581 | } 06582 | 06583 | void set_ref(value_ptr* ref) exprtk_override 06584 | { 06585 | vec_view_.set_ref(ref); 06586 | } 06587 | 06588 | void remove_ref(value_ptr* ref) exprtk_override 06589 | { 06590 | vec_view_.remove_ref(ref); 06591 | } 06592 | 06593 | bool rebaseable() const exprtk_override 06594 | { 06595 | return true; 06596 | } 06597 | 06598 | vector_view<Type>* rebaseable_instance() exprtk_override 06599 | { 06600 | return &vec_view_; 06601 | } 06602 | 06603 | protected: 06604 | 06605 | value_ptr value_at(const std::size_t& index) const exprtk_override 06606 | { 06607 | assert(index < vec_view_.size()); 06608 | return (&vec_view_[index]); 06609 | } 06610 | 06611 | std::size_t vector_size() const exprtk_override 06612 | { 06613 | return vec_view_.size(); 06614 | } 06615 | 06616 | std::size_t vector_base_size() const exprtk_override 06617 | { 06618 | return vec_view_.base_size(); 06619 | } 06620 | 06621 | private: 06622 | 06623 | vector_view_impl(const vector_view_impl&) exprtk_delete; 06624 | vector_view_impl& operator=(const vector_view_impl&) exprtk_delete; 06625 | 06626 | vector_view_t& vec_view_; 06627 | }; 06628 | 06629 | class resizable_vector_impl exprtk_final : public vector_holder_base 06630 | { 06631 | public: 06632 | 06633 | resizable_vector_impl(vector_holder& vec_view_holder, 06634 | const Type* vec, 06635 | const std::size_t& vec_size) 06636 | : vec_(vec) 06637 | , size_(vec_size) 06638 | , vec_view_holder_(*vec_view_holder.rebaseable_instance()) 06639 | { 06640 | assert(vec_view_holder.rebaseable_instance()); 06641 | assert(size_ <= vector_base_size()); 06642 | } 06643 | 06644 | virtual ~resizable_vector_impl() exprtk_override 06645 | {} 06646 | 06647 | protected: 06648 | 06649 | value_ptr value_at(const std::size_t& index) const exprtk_override 06650 | { 06651 | assert(index < vector_size()); 06652 | return const_cast<const_value_ptr>(vec_ + index); 06653 | } 06654 | 06655 | std::size_t vector_size() const exprtk_override 06656 | { 06657 | return vec_view_holder_.size(); 06658 | } 06659 | 06660 | std::size_t vector_base_size() const exprtk_override 06661 | { 06662 | return vec_view_holder_.base_size(); 06663 | } 06664 | 06665 | bool rebaseable() const exprtk_override 06666 | { 06667 | return true; 06668 | } 06669 | 06670 | virtual vector_view<Type>* rebaseable_instance() exprtk_override 06671 | { 06672 | return &vec_view_holder_; 06673 | } 06674 | 06675 | private: 06676 | 06677 | resizable_vector_impl(const resizable_vector_impl&) exprtk_delete; 06678 | resizable_vector_impl& operator=(const resizable_vector_impl&) exprtk_delete; 06679 | 06680 | const Type* vec_; 06681 | const std::size_t size_; 06682 | vector_view<Type>& vec_view_holder_; 06683 | }; 06684 | 06685 | public: 06686 | 06687 | typedef typename details::vec_data_store<Type> vds_t; 06688 | 06689 | vector_holder(Type* vec, const std::size_t& vec_size) 06690 | : vector_holder_base_(new(buffer)array_vector_impl(vec,vec_size)) 06691 | {} 06692 | 06693 | explicit vector_holder(const vds_t& vds) 06694 | : vector_holder_base_(new(buffer)array_vector_impl(vds.data(),vds.size())) 06695 | {} 06696 | 06697 | template <typename Allocator> 06698 | explicit vector_holder(std::vector<Type,Allocator>& vec) 06699 | : vector_holder_base_(new(buffer)sequence_vector_impl<Allocator,std::vector>(vec)) 06700 | {} 06701 | 06702 | explicit vector_holder(exprtk::vector_view<Type>& vec) 06703 | : vector_holder_base_(new(buffer)vector_view_impl(vec)) 06704 | {} 06705 | 06706 | explicit vector_holder(vector_holder_t& vec_holder, const vds_t& vds) 06707 | : vector_holder_base_(new(buffer)resizable_vector_impl(vec_holder, vds.data(), vds.size())) 06708 | {} 06709 | 06710 | inline value_ptr operator[](const std::size_t& index) const 06711 | { 06712 | return (*vector_holder_base_)[index]; 06713 | } 06714 | 06715 | inline std::size_t size() const 06716 | { 06717 | return vector_holder_base_->size(); 06718 | } 06719 | 06720 | inline std::size_t base_size() const 06721 | { 06722 | return vector_holder_base_->base_size(); 06723 | } 06724 | 06725 | inline value_ptr data() const 06726 | { 06727 | return vector_holder_base_->data(); 06728 | } 06729 | 06730 | void set_ref(value_ptr* ref) 06731 | { 06732 | if (rebaseable()) 06733 | { 06734 | vector_holder_base_->set_ref(ref); 06735 | } 06736 | } 06737 | 06738 | void set_size_ref(std::size_t* ref) 06739 | { 06740 | if (rebaseable()) 06741 | { 06742 | vector_holder_base_->set_size_ref(ref); 06743 | } 06744 | } 06745 | 06746 | void remove_ref(value_ptr* ref) 06747 | { 06748 | if (rebaseable()) 06749 | { 06750 | vector_holder_base_->remove_ref(ref); 06751 | } 06752 | } 06753 | 06754 | void remove_size_ref(std::size_t* ref) 06755 | { 06756 | if (rebaseable()) 06757 | { 06758 | vector_holder_base_->remove_size_ref(ref); 06759 | } 06760 | } 06761 | 06762 | bool rebaseable() const 06763 | { 06764 | return vector_holder_base_->rebaseable(); 06765 | } 06766 | 06767 | vector_view<Type>* rebaseable_instance() 06768 | { 06769 | return vector_holder_base_->rebaseable_instance(); 06770 | } 06771 | 06772 | private: 06773 | 06774 | vector_holder(const vector_holder<Type>&) exprtk_delete; 06775 | vector_holder<Type>& operator=(const vector_holder<Type>&) exprtk_delete; 06776 | 06777 | mutable vector_holder_base* vector_holder_base_; 06778 | uchar_t buffer[64]; 06779 | }; 06780 | 06781 | template <typename T> 06782 | class null_node exprtk_final : public expression_node<T> 06783 | { 06784 | public: 06785 | 06786 | inline T value() const exprtk_override 06787 | { 06788 | return std::numeric_limits<T>::quiet_NaN(); 06789 | } 06790 | 06791 | inline typename expression_node<T>::node_type type() const exprtk_override 06792 | { 06793 | return expression_node<T>::e_null; 06794 | } 06795 | }; 06796 | 06797 | template <typename T, std::size_t N> 06798 | inline void construct_branch_pair(std::pair<expression_node<T>*,bool> (&branch)[N], 06799 | expression_node<T>* b, 06800 | const std::size_t& index) 06801 | { 06802 | if (b && (index < N)) 06803 | { 06804 | branch[index] = std::make_pair(b,branch_deletable(b)); 06805 | } 06806 | } 06807 | 06808 | template <typename T> 06809 | inline void construct_branch_pair(std::pair<expression_node<T>*,bool>& branch, expression_node<T>* b) 06810 | { 06811 | if (b) 06812 | { 06813 | branch = std::make_pair(b,branch_deletable(b)); 06814 | } 06815 | } 06816 | 06817 | template <std::size_t N, typename T> 06818 | inline void init_branches(std::pair<expression_node<T>*,bool> (&branch)[N], 06819 | expression_node<T>* b0, 06820 | expression_node<T>* b1 = reinterpret_cast<expression_node<T>*>(0), 06821 | expression_node<T>* b2 = reinterpret_cast<expression_node<T>*>(0), 06822 | expression_node<T>* b3 = reinterpret_cast<expression_node<T>*>(0), 06823 | expression_node<T>* b4 = reinterpret_cast<expression_node<T>*>(0), 06824 | expression_node<T>* b5 = reinterpret_cast<expression_node<T>*>(0), 06825 | expression_node<T>* b6 = reinterpret_cast<expression_node<T>*>(0), 06826 | expression_node<T>* b7 = reinterpret_cast<expression_node<T>*>(0), 06827 | expression_node<T>* b8 = reinterpret_cast<expression_node<T>*>(0), 06828 | expression_node<T>* b9 = reinterpret_cast<expression_node<T>*>(0)) 06829 | { 06830 | construct_branch_pair(branch, b0, 0); 06831 | construct_branch_pair(branch, b1, 1); 06832 | construct_branch_pair(branch, b2, 2); 06833 | construct_branch_pair(branch, b3, 3); 06834 | construct_branch_pair(branch, b4, 4); 06835 | construct_branch_pair(branch, b5, 5); 06836 | construct_branch_pair(branch, b6, 6); 06837 | construct_branch_pair(branch, b7, 7); 06838 | construct_branch_pair(branch, b8, 8); 06839 | construct_branch_pair(branch, b9, 9); 06840 | } 06841 | 06842 | template <typename T> 06843 | class null_eq_node exprtk_final : public expression_node<T> 06844 | { 06845 | public: 06846 | 06847 | typedef expression_node<T>* expression_ptr; 06848 | typedef std::pair<expression_ptr,bool> branch_t; 06849 | 06850 | explicit null_eq_node(expression_ptr branch, const bool equality = true) 06851 | : equality_(equality) 06852 | { 06853 | construct_branch_pair(branch_, branch); 06854 | assert(valid()); 06855 | } 06856 | 06857 | inline T value() const exprtk_override 06858 | { 06859 | const T v = branch_.first->value(); 06860 | const bool result = details::numeric::is_nan(v); 06861 | 06862 | if (result) 06863 | return equality_ ? T(1) : T(0); 06864 | else 06865 | return equality_ ? T(0) : T(1); 06866 | } 06867 | 06868 | inline typename expression_node<T>::node_type type() const exprtk_override 06869 | { 06870 | return expression_node<T>::e_nulleq; 06871 | } 06872 | 06873 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 06874 | { 06875 | return branch_.first; 06876 | } 06877 | 06878 | inline bool valid() const exprtk_override 06879 | { 06880 | return branch_.first; 06881 | } 06882 | 06883 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 06884 | { 06885 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 06886 | } 06887 | 06888 | std::size_t node_depth() const exprtk_override 06889 | { 06890 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 06891 | } 06892 | 06893 | private: 06894 | 06895 | bool equality_; 06896 | branch_t branch_; 06897 | }; 06898 | 06899 | template <typename T> 06900 | class literal_node exprtk_final : public expression_node<T> 06901 | { 06902 | public: 06903 | 06904 | explicit literal_node(const T& v) 06905 | : value_(v) 06906 | {} 06907 | 06908 | inline T value() const exprtk_override 06909 | { 06910 | return value_; 06911 | } 06912 | 06913 | inline typename expression_node<T>::node_type type() const exprtk_override 06914 | { 06915 | return expression_node<T>::e_constant; 06916 | } 06917 | 06918 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 06919 | { 06920 | return reinterpret_cast<expression_node<T>*>(0); 06921 | } 06922 | 06923 | private: 06924 | 06925 | literal_node(const literal_node<T>&) exprtk_delete; 06926 | literal_node<T>& operator=(const literal_node<T>&) exprtk_delete; 06927 | 06928 | const T value_; 06929 | }; 06930 | 06931 | template <typename T> 06932 | struct range_pack; 06933 | 06934 | template <typename T> 06935 | struct range_data_type; 06936 | 06937 | template <typename T> 06938 | class range_interface 06939 | { 06940 | public: 06941 | 06942 | typedef range_pack<T> range_t; 06943 | 06944 | virtual ~range_interface() 06945 | {} 06946 | 06947 | virtual range_t& range_ref() = 0; 06948 | 06949 | virtual const range_t& range_ref() const = 0; 06950 | }; 06951 | 06952 | #ifndef exprtk_disable_string_capabilities 06953 | template <typename T> 06954 | class string_base_node 06955 | { 06956 | public: 06957 | 06958 | typedef range_data_type<T> range_data_type_t; 06959 | 06960 | virtual ~string_base_node() 06961 | {} 06962 | 06963 | virtual std::string str () const = 0; 06964 | 06965 | virtual char_cptr base() const = 0; 06966 | 06967 | virtual std::size_t size() const = 0; 06968 | }; 06969 | 06970 | template <typename T> 06971 | class string_literal_node exprtk_final 06972 | : public expression_node <T> 06973 | , public string_base_node<T> 06974 | , public range_interface <T> 06975 | { 06976 | public: 06977 | 06978 | typedef range_pack<T> range_t; 06979 | 06980 | explicit string_literal_node(const std::string& v) 06981 | : value_(v) 06982 | { 06983 | rp_.n0_c = std::make_pair<bool,std::size_t>(true, 0); 06984 | rp_.n1_c = std::make_pair<bool,std::size_t>(true, v.size()); 06985 | rp_.cache.first = rp_.n0_c.second; 06986 | rp_.cache.second = rp_.n1_c.second; 06987 | } 06988 | 06989 | inline T value() const exprtk_override 06990 | { 06991 | return std::numeric_limits<T>::quiet_NaN(); 06992 | } 06993 | 06994 | inline typename expression_node<T>::node_type type() const exprtk_override 06995 | { 06996 | return expression_node<T>::e_stringconst; 06997 | } 06998 | 06999 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 07000 | { 07001 | return reinterpret_cast<expression_node<T>*>(0); 07002 | } 07003 | 07004 | std::string str() const exprtk_override 07005 | { 07006 | return value_; 07007 | } 07008 | 07009 | char_cptr base() const exprtk_override 07010 | { 07011 | return value_.data(); 07012 | } 07013 | 07014 | std::size_t size() const exprtk_override 07015 | { 07016 | return value_.size(); 07017 | } 07018 | 07019 | range_t& range_ref() exprtk_override 07020 | { 07021 | return rp_; 07022 | } 07023 | 07024 | const range_t& range_ref() const exprtk_override 07025 | { 07026 | return rp_; 07027 | } 07028 | 07029 | private: 07030 | 07031 | string_literal_node(const string_literal_node<T>&) exprtk_delete; 07032 | string_literal_node<T>& operator=(const string_literal_node<T>&) exprtk_delete; 07033 | 07034 | const std::string value_; 07035 | range_t rp_; 07036 | }; 07037 | #endif 07038 | 07039 | template <typename T> 07040 | class unary_node : public expression_node<T> 07041 | { 07042 | public: 07043 | 07044 | typedef expression_node<T>* expression_ptr; 07045 | typedef std::pair<expression_ptr,bool> branch_t; 07046 | 07047 | unary_node(const operator_type& opr, expression_ptr branch) 07048 | : operation_(opr) 07049 | { 07050 | construct_branch_pair(branch_,branch); 07051 | assert(valid()); 07052 | } 07053 | 07054 | inline T value() const exprtk_override 07055 | { 07056 | return numeric::process<T> 07057 | (operation_,branch_.first->value()); 07058 | } 07059 | 07060 | inline typename expression_node<T>::node_type type() const exprtk_override 07061 | { 07062 | return expression_node<T>::e_unary; 07063 | } 07064 | 07065 | inline operator_type operation() 07066 | { 07067 | return operation_; 07068 | } 07069 | 07070 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 07071 | { 07072 | return branch_.first; 07073 | } 07074 | 07075 | inline bool valid() const exprtk_override 07076 | { 07077 | return branch_.first && branch_.first->valid(); 07078 | } 07079 | 07080 | inline void release() 07081 | { 07082 | branch_.second = false; 07083 | } 07084 | 07085 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07086 | { 07087 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 07088 | } 07089 | 07090 | std::size_t node_depth() const exprtk_final 07091 | { 07092 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 07093 | } 07094 | 07095 | private: 07096 | 07097 | operator_type operation_; 07098 | branch_t branch_; 07099 | }; 07100 | 07101 | template <typename T> 07102 | class binary_node : public expression_node<T> 07103 | { 07104 | public: 07105 | 07106 | typedef expression_node<T>* expression_ptr; 07107 | typedef std::pair<expression_ptr,bool> branch_t; 07108 | 07109 | binary_node(const operator_type& opr, 07110 | expression_ptr branch0, 07111 | expression_ptr branch1) 07112 | : operation_(opr) 07113 | { 07114 | init_branches<2>(branch_, branch0, branch1); 07115 | assert(valid()); 07116 | } 07117 | 07118 | inline T value() const exprtk_override 07119 | { 07120 | return numeric::process<T> 07121 | ( 07122 | operation_, 07123 | branch_[0].first->value(), 07124 | branch_[1].first->value() 07125 | ); 07126 | } 07127 | 07128 | inline typename expression_node<T>::node_type type() const exprtk_override 07129 | { 07130 | return expression_node<T>::e_binary; 07131 | } 07132 | 07133 | inline operator_type operation() 07134 | { 07135 | return operation_; 07136 | } 07137 | 07138 | inline expression_node<T>* branch(const std::size_t& index = 0) const exprtk_override 07139 | { 07140 | assert(index < 2); 07141 | return branch_[index].first; 07142 | } 07143 | 07144 | inline bool valid() const exprtk_override 07145 | { 07146 | return 07147 | branch_[0].first && branch_[0].first->valid() && 07148 | branch_[1].first && branch_[1].first->valid() ; 07149 | } 07150 | 07151 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07152 | { 07153 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 07154 | } 07155 | 07156 | std::size_t node_depth() const exprtk_final 07157 | { 07158 | return expression_node<T>::ndb_t::template compute_node_depth<2>(branch_); 07159 | } 07160 | 07161 | private: 07162 | 07163 | operator_type operation_; 07164 | branch_t branch_[2]; 07165 | }; 07166 | 07167 | template <typename T, typename Operation> 07168 | class binary_ext_node exprtk_final : public expression_node<T> 07169 | { 07170 | public: 07171 | 07172 | typedef expression_node<T>* expression_ptr; 07173 | typedef std::pair<expression_ptr,bool> branch_t; 07174 | 07175 | binary_ext_node(expression_ptr branch0, expression_ptr branch1) 07176 | { 07177 | init_branches<2>(branch_, branch0, branch1); 07178 | assert(valid()); 07179 | } 07180 | 07181 | inline T value() const exprtk_override 07182 | { 07183 | const T arg0 = branch_[0].first->value(); 07184 | const T arg1 = branch_[1].first->value(); 07185 | return Operation::process(arg0,arg1); 07186 | } 07187 | 07188 | inline typename expression_node<T>::node_type type() const exprtk_override 07189 | { 07190 | return expression_node<T>::e_binary_ext; 07191 | } 07192 | 07193 | inline operator_type operation() 07194 | { 07195 | return Operation::operation(); 07196 | } 07197 | 07198 | inline expression_node<T>* branch(const std::size_t& index = 0) const exprtk_override 07199 | { 07200 | assert(index < 2); 07201 | return branch_[index].first; 07202 | } 07203 | 07204 | inline bool valid() const exprtk_override 07205 | { 07206 | return 07207 | branch_[0].first && branch_[0].first->valid() && 07208 | branch_[1].first && branch_[1].first->valid() ; 07209 | } 07210 | 07211 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07212 | { 07213 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 07214 | } 07215 | 07216 | std::size_t node_depth() const exprtk_override 07217 | { 07218 | return expression_node<T>::ndb_t::template compute_node_depth<2>(branch_); 07219 | } 07220 | 07221 | protected: 07222 | 07223 | branch_t branch_[2]; 07224 | }; 07225 | 07226 | template <typename T> 07227 | class trinary_node : public expression_node<T> 07228 | { 07229 | public: 07230 | 07231 | typedef expression_node<T>* expression_ptr; 07232 | typedef std::pair<expression_ptr,bool> branch_t; 07233 | 07234 | trinary_node(const operator_type& opr, 07235 | expression_ptr branch0, 07236 | expression_ptr branch1, 07237 | expression_ptr branch2) 07238 | : operation_(opr) 07239 | { 07240 | init_branches<3>(branch_, branch0, branch1, branch2); 07241 | assert(valid()); 07242 | } 07243 | 07244 | inline T value() const exprtk_override 07245 | { 07246 | const T arg0 = branch_[0].first->value(); 07247 | const T arg1 = branch_[1].first->value(); 07248 | const T arg2 = branch_[2].first->value(); 07249 | 07250 | switch (operation_) 07251 | { 07252 | case e_inrange : return (arg1 < arg0) ? T(0) : ((arg1 > arg2) ? T(0) : T(1)); 07253 | 07254 | case e_clamp : return (arg1 < arg0) ? arg0 : (arg1 > arg2 ? arg2 : arg1); 07255 | 07256 | case e_iclamp : if ((arg1 <= arg0) || (arg1 >= arg2)) 07257 | return arg1; 07258 | else 07259 | return ((T(2) * arg1 <= (arg2 + arg0)) ? arg0 : arg2); 07260 | 07261 | default : exprtk_debug(("trinary_node::value() - Error: Invalid operation\n")); 07262 | return std::numeric_limits<T>::quiet_NaN(); 07263 | } 07264 | } 07265 | 07266 | inline typename expression_node<T>::node_type type() const exprtk_override 07267 | { 07268 | return expression_node<T>::e_trinary; 07269 | } 07270 | 07271 | inline bool valid() const exprtk_override 07272 | { 07273 | return 07274 | branch_[0].first && branch_[0].first->valid() && 07275 | branch_[1].first && branch_[1].first->valid() && 07276 | branch_[2].first && branch_[2].first->valid() ; 07277 | } 07278 | 07279 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07280 | { 07281 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 07282 | } 07283 | 07284 | std::size_t node_depth() const exprtk_override exprtk_final 07285 | { 07286 | return expression_node<T>::ndb_t::template compute_node_depth<3>(branch_); 07287 | } 07288 | 07289 | protected: 07290 | 07291 | operator_type operation_; 07292 | branch_t branch_[3]; 07293 | }; 07294 | 07295 | template <typename T> 07296 | class quaternary_node : public expression_node<T> 07297 | { 07298 | public: 07299 | 07300 | typedef expression_node<T>* expression_ptr; 07301 | typedef std::pair<expression_ptr,bool> branch_t; 07302 | 07303 | quaternary_node(const operator_type& opr, 07304 | expression_ptr branch0, 07305 | expression_ptr branch1, 07306 | expression_ptr branch2, 07307 | expression_ptr branch3) 07308 | : operation_(opr) 07309 | { 07310 | init_branches<4>(branch_, branch0, branch1, branch2, branch3); 07311 | } 07312 | 07313 | inline T value() const exprtk_override 07314 | { 07315 | return std::numeric_limits<T>::quiet_NaN(); 07316 | } 07317 | 07318 | inline typename expression_node<T>::node_type type() const exprtk_override 07319 | { 07320 | return expression_node<T>::e_quaternary; 07321 | } 07322 | 07323 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07324 | { 07325 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 07326 | } 07327 | 07328 | std::size_t node_depth() const exprtk_override exprtk_final 07329 | { 07330 | return expression_node<T>::ndb_t::template compute_node_depth<4>(branch_); 07331 | } 07332 | 07333 | inline bool valid() const exprtk_override 07334 | { 07335 | return 07336 | branch_[0].first && branch_[0].first->valid() && 07337 | branch_[1].first && branch_[1].first->valid() && 07338 | branch_[2].first && branch_[2].first->valid() && 07339 | branch_[3].first && branch_[3].first->valid() ; 07340 | } 07341 | 07342 | protected: 07343 | 07344 | operator_type operation_; 07345 | branch_t branch_[4]; 07346 | }; 07347 | 07348 | template <typename T> 07349 | class conditional_node exprtk_final : public expression_node<T> 07350 | { 07351 | public: 07352 | 07353 | typedef expression_node<T>* expression_ptr; 07354 | typedef std::pair<expression_ptr,bool> branch_t; 07355 | 07356 | conditional_node(expression_ptr condition, 07357 | expression_ptr consequent, 07358 | expression_ptr alternative) 07359 | { 07360 | construct_branch_pair(condition_ , condition ); 07361 | construct_branch_pair(consequent_ , consequent ); 07362 | construct_branch_pair(alternative_, alternative); 07363 | assert(valid()); 07364 | } 07365 | 07366 | inline T value() const exprtk_override 07367 | { 07368 | if (is_true(condition_)) 07369 | return consequent_.first->value(); 07370 | else 07371 | return alternative_.first->value(); 07372 | } 07373 | 07374 | inline typename expression_node<T>::node_type type() const exprtk_override 07375 | { 07376 | return expression_node<T>::e_conditional; 07377 | } 07378 | 07379 | inline bool valid() const exprtk_override 07380 | { 07381 | return 07382 | condition_ .first && condition_ .first->valid() && 07383 | consequent_ .first && consequent_ .first->valid() && 07384 | alternative_.first && alternative_.first->valid() ; 07385 | } 07386 | 07387 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07388 | { 07389 | expression_node<T>::ndb_t::collect(condition_ , node_delete_list); 07390 | expression_node<T>::ndb_t::collect(consequent_ , node_delete_list); 07391 | expression_node<T>::ndb_t::collect(alternative_ , node_delete_list); 07392 | } 07393 | 07394 | std::size_t node_depth() const exprtk_override 07395 | { 07396 | return expression_node<T>::ndb_t::compute_node_depth 07397 | (condition_, consequent_, alternative_); 07398 | } 07399 | 07400 | private: 07401 | 07402 | branch_t condition_; 07403 | branch_t consequent_; 07404 | branch_t alternative_; 07405 | }; 07406 | 07407 | template <typename T> 07408 | class cons_conditional_node exprtk_final : public expression_node<T> 07409 | { 07410 | public: 07411 | 07412 | // Consequent only conditional statement node 07413 | typedef expression_node<T>* expression_ptr; 07414 | typedef std::pair<expression_ptr,bool> branch_t; 07415 | 07416 | cons_conditional_node(expression_ptr condition, 07417 | expression_ptr consequent) 07418 | { 07419 | construct_branch_pair(condition_ , condition ); 07420 | construct_branch_pair(consequent_, consequent); 07421 | assert(valid()); 07422 | } 07423 | 07424 | inline T value() const exprtk_override 07425 | { 07426 | if (is_true(condition_)) 07427 | return consequent_.first->value(); 07428 | else 07429 | return std::numeric_limits<T>::quiet_NaN(); 07430 | } 07431 | 07432 | inline typename expression_node<T>::node_type type() const exprtk_override 07433 | { 07434 | return expression_node<T>::e_conditional; 07435 | } 07436 | 07437 | inline bool valid() const exprtk_override 07438 | { 07439 | return 07440 | condition_ .first && condition_ .first->valid() && 07441 | consequent_.first && consequent_.first->valid() ; 07442 | } 07443 | 07444 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07445 | { 07446 | expression_node<T>::ndb_t::collect(condition_ , node_delete_list); 07447 | expression_node<T>::ndb_t::collect(consequent_ , node_delete_list); 07448 | } 07449 | 07450 | std::size_t node_depth() const exprtk_override 07451 | { 07452 | return expression_node<T>::ndb_t:: 07453 | compute_node_depth(condition_, consequent_); 07454 | } 07455 | 07456 | private: 07457 | 07458 | branch_t condition_; 07459 | branch_t consequent_; 07460 | }; 07461 | 07462 | #ifndef exprtk_disable_break_continue 07463 | template <typename T> 07464 | class break_exception 07465 | { 07466 | public: 07467 | 07468 | explicit break_exception(const T& v) 07469 | : value(v) 07470 | {} 07471 | 07472 | T value; 07473 | }; 07474 | 07475 | class continue_exception {}; 07476 | 07477 | template <typename T> 07478 | class break_node exprtk_final : public expression_node<T> 07479 | { 07480 | public: 07481 | 07482 | typedef expression_node<T>* expression_ptr; 07483 | typedef std::pair<expression_ptr,bool> branch_t; 07484 | 07485 | explicit break_node(expression_ptr ret = expression_ptr(0)) 07486 | { 07487 | construct_branch_pair(return_, ret); 07488 | } 07489 | 07490 | inline T value() const exprtk_override 07491 | { 07492 | const T result = return_.first ? 07493 | return_.first->value() : 07494 | std::numeric_limits<T>::quiet_NaN(); 07495 | 07496 | throw break_exception<T>(result); 07497 | 07498 | #if !defined(_MSC_VER) && !defined(__NVCOMPILER) 07499 | return std::numeric_limits<T>::quiet_NaN(); 07500 | #endif 07501 | } 07502 | 07503 | inline typename expression_node<T>::node_type type() const exprtk_override 07504 | { 07505 | return expression_node<T>::e_break; 07506 | } 07507 | 07508 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07509 | { 07510 | expression_node<T>::ndb_t::collect(return_, node_delete_list); 07511 | } 07512 | 07513 | std::size_t node_depth() const exprtk_override 07514 | { 07515 | return expression_node<T>::ndb_t::compute_node_depth(return_); 07516 | } 07517 | 07518 | private: 07519 | 07520 | branch_t return_; 07521 | }; 07522 | 07523 | template <typename T> 07524 | class continue_node exprtk_final : public expression_node<T> 07525 | { 07526 | public: 07527 | 07528 | inline T value() const exprtk_override 07529 | { 07530 | throw continue_exception(); 07531 | #if !defined(_MSC_VER) && !defined(__NVCOMPILER) 07532 | return std::numeric_limits<T>::quiet_NaN(); 07533 | #endif 07534 | } 07535 | 07536 | inline typename expression_node<T>::node_type type() const exprtk_override 07537 | { 07538 | return expression_node<T>::e_break; 07539 | } 07540 | }; 07541 | #endif 07542 | 07543 | struct loop_runtime_checker 07544 | { 07545 | loop_runtime_checker(loop_runtime_check_ptr loop_runtime_check, 07546 | loop_runtime_check::loop_types lp_typ = loop_runtime_check::e_invalid) 07547 | : iteration_count_(0) 07548 | , loop_runtime_check_(loop_runtime_check) 07549 | , max_loop_iterations_(loop_runtime_check_->max_loop_iterations) 07550 | , loop_type_(lp_typ) 07551 | { 07552 | assert(loop_runtime_check_); 07553 | } 07554 | 07555 | inline void reset(const _uint64_t initial_value = 0) const 07556 | { 07557 | iteration_count_ = initial_value; 07558 | } 07559 | 07560 | inline bool check() const 07561 | { 07562 | assert(loop_runtime_check_); 07563 | 07564 | if ( 07565 | (++iteration_count_ <= max_loop_iterations_) && 07566 | loop_runtime_check_->check() 07567 | ) 07568 | { 07569 | return true; 07570 | } 07571 | 07572 | loop_runtime_check::violation_context ctxt; 07573 | ctxt.loop = loop_type_; 07574 | ctxt.violation = loop_runtime_check::e_iteration_count; 07575 | ctxt.iteration_count = iteration_count_; 07576 | 07577 | loop_runtime_check_->handle_runtime_violation(ctxt); 07578 | 07579 | return false; 07580 | } 07581 | 07582 | bool valid() const 07583 | { 07584 | return 0 != loop_runtime_check_; 07585 | } 07586 | 07587 | mutable _uint64_t iteration_count_; 07588 | mutable loop_runtime_check_ptr loop_runtime_check_; 07589 | const details::_uint64_t& max_loop_iterations_; 07590 | loop_runtime_check::loop_types loop_type_; 07591 | }; 07592 | 07593 | template <typename T> 07594 | class while_loop_node : public expression_node<T> 07595 | { 07596 | public: 07597 | 07598 | typedef expression_node<T>* expression_ptr; 07599 | typedef std::pair<expression_ptr,bool> branch_t; 07600 | 07601 | while_loop_node(expression_ptr condition, 07602 | expression_ptr loop_body) 07603 | { 07604 | construct_branch_pair(condition_, condition); 07605 | construct_branch_pair(loop_body_, loop_body); 07606 | assert(valid()); 07607 | } 07608 | 07609 | inline T value() const exprtk_override 07610 | { 07611 | T result = T(0); 07612 | 07613 | while (is_true(condition_)) 07614 | { 07615 | result = loop_body_.first->value(); 07616 | } 07617 | 07618 | return result; 07619 | } 07620 | 07621 | inline typename expression_node<T>::node_type type() const exprtk_override 07622 | { 07623 | return expression_node<T>::e_while; 07624 | } 07625 | 07626 | inline bool valid() const exprtk_override 07627 | { 07628 | return 07629 | condition_.first && condition_.first->valid() && 07630 | loop_body_.first && loop_body_.first->valid() ; 07631 | } 07632 | 07633 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07634 | { 07635 | expression_node<T>::ndb_t::collect(condition_ , node_delete_list); 07636 | expression_node<T>::ndb_t::collect(loop_body_ , node_delete_list); 07637 | } 07638 | 07639 | std::size_t node_depth() const exprtk_override 07640 | { 07641 | return expression_node<T>::ndb_t::compute_node_depth(condition_, loop_body_); 07642 | } 07643 | 07644 | protected: 07645 | 07646 | branch_t condition_; 07647 | branch_t loop_body_; 07648 | }; 07649 | 07650 | template <typename T> 07651 | class while_loop_rtc_node exprtk_final 07652 | : public while_loop_node<T> 07653 | , public loop_runtime_checker 07654 | { 07655 | public: 07656 | 07657 | typedef while_loop_node<T> parent_t; 07658 | typedef expression_node<T>* expression_ptr; 07659 | 07660 | while_loop_rtc_node(expression_ptr condition, 07661 | expression_ptr loop_body, 07662 | loop_runtime_check_ptr loop_rt_chk) 07663 | : parent_t(condition, loop_body) 07664 | , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_while_loop) 07665 | { 07666 | assert(valid()); 07667 | } 07668 | 07669 | inline T value() const exprtk_override 07670 | { 07671 | 07672 | T result = T(0); 07673 | 07674 | loop_runtime_checker::reset(); 07675 | 07676 | while (is_true(parent_t::condition_) && loop_runtime_checker::check()) 07677 | { 07678 | result = parent_t::loop_body_.first->value(); 07679 | } 07680 | 07681 | return result; 07682 | } 07683 | 07684 | using parent_t::valid; 07685 | 07686 | bool valid() const exprtk_override exprtk_final 07687 | { 07688 | return parent_t::valid() && 07689 | loop_runtime_checker::valid(); 07690 | } 07691 | }; 07692 | 07693 | template <typename T> 07694 | class repeat_until_loop_node : public expression_node<T> 07695 | { 07696 | public: 07697 | 07698 | typedef expression_node<T>* expression_ptr; 07699 | typedef std::pair<expression_ptr,bool> branch_t; 07700 | 07701 | repeat_until_loop_node(expression_ptr condition, 07702 | expression_ptr loop_body) 07703 | { 07704 | construct_branch_pair(condition_, condition); 07705 | construct_branch_pair(loop_body_, loop_body); 07706 | assert(valid()); 07707 | } 07708 | 07709 | inline T value() const exprtk_override 07710 | { 07711 | T result = T(0); 07712 | 07713 | do 07714 | { 07715 | result = loop_body_.first->value(); 07716 | } 07717 | while (is_false(condition_.first)); 07718 | 07719 | return result; 07720 | } 07721 | 07722 | inline typename expression_node<T>::node_type type() const exprtk_override 07723 | { 07724 | return expression_node<T>::e_repeat; 07725 | } 07726 | 07727 | inline bool valid() const exprtk_override 07728 | { 07729 | return 07730 | condition_.first && condition_.first->valid() && 07731 | loop_body_.first && loop_body_.first->valid() ; 07732 | } 07733 | 07734 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07735 | { 07736 | expression_node<T>::ndb_t::collect(condition_ , node_delete_list); 07737 | expression_node<T>::ndb_t::collect(loop_body_ , node_delete_list); 07738 | } 07739 | 07740 | std::size_t node_depth() const exprtk_override 07741 | { 07742 | return expression_node<T>::ndb_t::compute_node_depth(condition_, loop_body_); 07743 | } 07744 | 07745 | protected: 07746 | 07747 | branch_t condition_; 07748 | branch_t loop_body_; 07749 | }; 07750 | 07751 | template <typename T> 07752 | class repeat_until_loop_rtc_node exprtk_final 07753 | : public repeat_until_loop_node<T> 07754 | , public loop_runtime_checker 07755 | { 07756 | public: 07757 | 07758 | typedef repeat_until_loop_node<T> parent_t; 07759 | typedef expression_node<T>* expression_ptr; 07760 | 07761 | repeat_until_loop_rtc_node(expression_ptr condition, 07762 | expression_ptr loop_body, 07763 | loop_runtime_check_ptr loop_rt_chk) 07764 | : parent_t(condition, loop_body) 07765 | , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_repeat_until_loop) 07766 | { 07767 | assert(valid()); 07768 | } 07769 | 07770 | inline T value() const exprtk_override 07771 | { 07772 | T result = T(0); 07773 | 07774 | loop_runtime_checker::reset(1); 07775 | 07776 | do 07777 | { 07778 | result = parent_t::loop_body_.first->value(); 07779 | } 07780 | while (is_false(parent_t::condition_.first) && loop_runtime_checker::check()); 07781 | 07782 | return result; 07783 | } 07784 | 07785 | using parent_t::valid; 07786 | 07787 | inline bool valid() const exprtk_override exprtk_final 07788 | { 07789 | return parent_t::valid() && 07790 | loop_runtime_checker::valid(); 07791 | } 07792 | }; 07793 | 07794 | template <typename T> 07795 | class for_loop_node : public expression_node<T> 07796 | { 07797 | public: 07798 | 07799 | typedef expression_node<T>* expression_ptr; 07800 | typedef std::pair<expression_ptr,bool> branch_t; 07801 | 07802 | for_loop_node(expression_ptr initialiser, 07803 | expression_ptr condition, 07804 | expression_ptr incrementor, 07805 | expression_ptr loop_body) 07806 | { 07807 | construct_branch_pair(initialiser_, initialiser); 07808 | construct_branch_pair(condition_ , condition ); 07809 | construct_branch_pair(incrementor_, incrementor); 07810 | construct_branch_pair(loop_body_ , loop_body ); 07811 | assert(valid()); 07812 | } 07813 | 07814 | inline T value() const exprtk_override 07815 | { 07816 | T result = T(0); 07817 | 07818 | if (initialiser_.first) 07819 | initialiser_.first->value(); 07820 | 07821 | if (incrementor_.first) 07822 | { 07823 | while (is_true(condition_)) 07824 | { 07825 | result = loop_body_.first->value(); 07826 | incrementor_.first->value(); 07827 | } 07828 | } 07829 | else 07830 | { 07831 | while (is_true(condition_)) 07832 | { 07833 | result = loop_body_.first->value(); 07834 | } 07835 | } 07836 | 07837 | return result; 07838 | } 07839 | 07840 | inline typename expression_node<T>::node_type type() const exprtk_override 07841 | { 07842 | return expression_node<T>::e_for; 07843 | } 07844 | 07845 | inline bool valid() const exprtk_override 07846 | { 07847 | return condition_.first && loop_body_.first; 07848 | } 07849 | 07850 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07851 | { 07852 | expression_node<T>::ndb_t::collect(initialiser_ , node_delete_list); 07853 | expression_node<T>::ndb_t::collect(condition_ , node_delete_list); 07854 | expression_node<T>::ndb_t::collect(incrementor_ , node_delete_list); 07855 | expression_node<T>::ndb_t::collect(loop_body_ , node_delete_list); 07856 | } 07857 | 07858 | std::size_t node_depth() const exprtk_override 07859 | { 07860 | return expression_node<T>::ndb_t::compute_node_depth 07861 | (initialiser_, condition_, incrementor_, loop_body_); 07862 | } 07863 | 07864 | protected: 07865 | 07866 | branch_t initialiser_; 07867 | branch_t condition_ ; 07868 | branch_t incrementor_; 07869 | branch_t loop_body_ ; 07870 | }; 07871 | 07872 | template <typename T> 07873 | class for_loop_rtc_node exprtk_final 07874 | : public for_loop_node<T> 07875 | , public loop_runtime_checker 07876 | { 07877 | public: 07878 | 07879 | typedef for_loop_node<T> parent_t; 07880 | typedef expression_node<T>* expression_ptr; 07881 | 07882 | for_loop_rtc_node(expression_ptr initialiser, 07883 | expression_ptr condition, 07884 | expression_ptr incrementor, 07885 | expression_ptr loop_body, 07886 | loop_runtime_check_ptr loop_rt_chk) 07887 | : parent_t(initialiser, condition, incrementor, loop_body) 07888 | , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_for_loop) 07889 | { 07890 | assert(valid()); 07891 | } 07892 | 07893 | inline T value() const exprtk_override 07894 | { 07895 | T result = T(0); 07896 | 07897 | loop_runtime_checker::reset(); 07898 | 07899 | if (parent_t::initialiser_.first) 07900 | parent_t::initialiser_.first->value(); 07901 | 07902 | if (parent_t::incrementor_.first) 07903 | { 07904 | while (is_true(parent_t::condition_) && loop_runtime_checker::check()) 07905 | { 07906 | result = parent_t::loop_body_.first->value(); 07907 | parent_t::incrementor_.first->value(); 07908 | } 07909 | } 07910 | else 07911 | { 07912 | while (is_true(parent_t::condition_) && loop_runtime_checker::check()) 07913 | { 07914 | result = parent_t::loop_body_.first->value(); 07915 | } 07916 | } 07917 | 07918 | return result; 07919 | } 07920 | 07921 | using parent_t::valid; 07922 | 07923 | inline bool valid() const exprtk_override exprtk_final 07924 | { 07925 | return parent_t::valid() && 07926 | loop_runtime_checker::valid(); 07927 | } 07928 | }; 07929 | 07930 | #ifndef exprtk_disable_break_continue 07931 | template <typename T> 07932 | class while_loop_bc_node : public while_loop_node<T> 07933 | { 07934 | public: 07935 | 07936 | typedef while_loop_node<T> parent_t; 07937 | typedef expression_node<T>* expression_ptr; 07938 | 07939 | while_loop_bc_node(expression_ptr condition, 07940 | expression_ptr loop_body) 07941 | : parent_t(condition, loop_body) 07942 | { 07943 | assert(parent_t::valid()); 07944 | } 07945 | 07946 | inline T value() const exprtk_override 07947 | { 07948 | T result = T(0); 07949 | 07950 | while (is_true(parent_t::condition_)) 07951 | { 07952 | try 07953 | { 07954 | result = parent_t::loop_body_.first->value(); 07955 | } 07956 | catch(const break_exception<T>& e) 07957 | { 07958 | return e.value; 07959 | } 07960 | catch(const continue_exception&) 07961 | {} 07962 | } 07963 | 07964 | return result; 07965 | } 07966 | }; 07967 | 07968 | template <typename T> 07969 | class while_loop_bc_rtc_node exprtk_final 07970 | : public while_loop_bc_node<T> 07971 | , public loop_runtime_checker 07972 | { 07973 | public: 07974 | 07975 | typedef while_loop_bc_node<T> parent_t; 07976 | typedef expression_node<T>* expression_ptr; 07977 | 07978 | while_loop_bc_rtc_node(expression_ptr condition, 07979 | expression_ptr loop_body, 07980 | loop_runtime_check_ptr loop_rt_chk) 07981 | : parent_t(condition, loop_body) 07982 | , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_while_loop) 07983 | { 07984 | assert(valid()); 07985 | } 07986 | 07987 | inline T value() const exprtk_override 07988 | { 07989 | T result = T(0); 07990 | 07991 | loop_runtime_checker::reset(); 07992 | 07993 | while (is_true(parent_t::condition_) && loop_runtime_checker::check()) 07994 | { 07995 | try 07996 | { 07997 | result = parent_t::loop_body_.first->value(); 07998 | } 07999 | catch(const break_exception<T>& e) 08000 | { 08001 | return e.value; 08002 | } 08003 | catch(const continue_exception&) 08004 | {} 08005 | } 08006 | 08007 | return result; 08008 | } 08009 | 08010 | using parent_t::valid; 08011 | 08012 | inline bool valid() const exprtk_override exprtk_final 08013 | { 08014 | return parent_t::valid() && 08015 | loop_runtime_checker::valid(); 08016 | } 08017 | }; 08018 | 08019 | template <typename T> 08020 | class repeat_until_loop_bc_node : public repeat_until_loop_node<T> 08021 | { 08022 | public: 08023 | 08024 | typedef repeat_until_loop_node<T> parent_t; 08025 | typedef expression_node<T>* expression_ptr; 08026 | 08027 | repeat_until_loop_bc_node(expression_ptr condition, 08028 | expression_ptr loop_body) 08029 | : parent_t(condition, loop_body) 08030 | { 08031 | assert(parent_t::valid()); 08032 | } 08033 | 08034 | inline T value() const exprtk_override 08035 | { 08036 | T result = T(0); 08037 | 08038 | do 08039 | { 08040 | try 08041 | { 08042 | result = parent_t::loop_body_.first->value(); 08043 | } 08044 | catch(const break_exception<T>& e) 08045 | { 08046 | return e.value; 08047 | } 08048 | catch(const continue_exception&) 08049 | {} 08050 | } 08051 | while (is_false(parent_t::condition_.first)); 08052 | 08053 | return result; 08054 | } 08055 | }; 08056 | 08057 | template <typename T> 08058 | class repeat_until_loop_bc_rtc_node exprtk_final 08059 | : public repeat_until_loop_bc_node<T> 08060 | , public loop_runtime_checker 08061 | { 08062 | public: 08063 | 08064 | typedef repeat_until_loop_bc_node<T> parent_t; 08065 | typedef expression_node<T>* expression_ptr; 08066 | 08067 | repeat_until_loop_bc_rtc_node(expression_ptr condition, 08068 | expression_ptr loop_body, 08069 | loop_runtime_check_ptr loop_rt_chk) 08070 | : parent_t(condition, loop_body) 08071 | , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_repeat_until_loop) 08072 | { 08073 | assert(valid()); 08074 | } 08075 | 08076 | inline T value() const exprtk_override 08077 | { 08078 | T result = T(0); 08079 | 08080 | loop_runtime_checker::reset(); 08081 | 08082 | do 08083 | { 08084 | try 08085 | { 08086 | result = parent_t::loop_body_.first->value(); 08087 | } 08088 | catch(const break_exception<T>& e) 08089 | { 08090 | return e.value; 08091 | } 08092 | catch(const continue_exception&) 08093 | {} 08094 | } 08095 | while (is_false(parent_t::condition_.first) && loop_runtime_checker::check()); 08096 | 08097 | return result; 08098 | } 08099 | 08100 | using parent_t::valid; 08101 | 08102 | inline bool valid() const exprtk_override exprtk_final 08103 | { 08104 | return parent_t::valid() && 08105 | loop_runtime_checker::valid(); 08106 | } 08107 | }; 08108 | 08109 | template <typename T> 08110 | class for_loop_bc_node : public for_loop_node<T> 08111 | { 08112 | public: 08113 | 08114 | typedef for_loop_node<T> parent_t; 08115 | typedef expression_node<T>* expression_ptr; 08116 | 08117 | for_loop_bc_node(expression_ptr initialiser, 08118 | expression_ptr condition, 08119 | expression_ptr incrementor, 08120 | expression_ptr loop_body) 08121 | : parent_t(initialiser, condition, incrementor, loop_body) 08122 | { 08123 | assert(parent_t::valid()); 08124 | } 08125 | 08126 | inline T value() const exprtk_override 08127 | { 08128 | T result = T(0); 08129 | 08130 | if (parent_t::initialiser_.first) 08131 | parent_t::initialiser_.first->value(); 08132 | 08133 | if (parent_t::incrementor_.first) 08134 | { 08135 | while (is_true(parent_t::condition_)) 08136 | { 08137 | try 08138 | { 08139 | result = parent_t::loop_body_.first->value(); 08140 | } 08141 | catch(const break_exception<T>& e) 08142 | { 08143 | return e.value; 08144 | } 08145 | catch(const continue_exception&) 08146 | {} 08147 | 08148 | parent_t::incrementor_.first->value(); 08149 | } 08150 | } 08151 | else 08152 | { 08153 | while (is_true(parent_t::condition_)) 08154 | { 08155 | try 08156 | { 08157 | result = parent_t::loop_body_.first->value(); 08158 | } 08159 | catch(const break_exception<T>& e) 08160 | { 08161 | return e.value; 08162 | } 08163 | catch(const continue_exception&) 08164 | {} 08165 | } 08166 | } 08167 | 08168 | return result; 08169 | } 08170 | }; 08171 | 08172 | template <typename T> 08173 | class for_loop_bc_rtc_node exprtk_final 08174 | : public for_loop_bc_node<T> 08175 | , public loop_runtime_checker 08176 | { 08177 | public: 08178 | 08179 | typedef for_loop_bc_node<T> parent_t; 08180 | typedef expression_node<T>* expression_ptr; 08181 | 08182 | for_loop_bc_rtc_node(expression_ptr initialiser, 08183 | expression_ptr condition, 08184 | expression_ptr incrementor, 08185 | expression_ptr loop_body, 08186 | loop_runtime_check_ptr loop_rt_chk) 08187 | : parent_t(initialiser, condition, incrementor, loop_body) 08188 | , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_for_loop) 08189 | { 08190 | assert(valid()); 08191 | } 08192 | 08193 | inline T value() const exprtk_override 08194 | { 08195 | T result = T(0); 08196 | 08197 | loop_runtime_checker::reset(); 08198 | 08199 | if (parent_t::initialiser_.first) 08200 | parent_t::initialiser_.first->value(); 08201 | 08202 | if (parent_t::incrementor_.first) 08203 | { 08204 | while (is_true(parent_t::condition_) && loop_runtime_checker::check()) 08205 | { 08206 | try 08207 | { 08208 | result = parent_t::loop_body_.first->value(); 08209 | } 08210 | catch(const break_exception<T>& e) 08211 | { 08212 | return e.value; 08213 | } 08214 | catch(const continue_exception&) 08215 | {} 08216 | 08217 | parent_t::incrementor_.first->value(); 08218 | } 08219 | } 08220 | else 08221 | { 08222 | while (is_true(parent_t::condition_) && loop_runtime_checker::check()) 08223 | { 08224 | try 08225 | { 08226 | result = parent_t::loop_body_.first->value(); 08227 | } 08228 | catch(const break_exception<T>& e) 08229 | { 08230 | return e.value; 08231 | } 08232 | catch(const continue_exception&) 08233 | {} 08234 | } 08235 | } 08236 | 08237 | return result; 08238 | } 08239 | 08240 | using parent_t::valid; 08241 | 08242 | inline bool valid() const exprtk_override exprtk_final 08243 | { 08244 | return parent_t::valid() && 08245 | loop_runtime_checker::valid(); 08246 | } 08247 | }; 08248 | #endif 08249 | 08250 | template <typename T> 08251 | class switch_node : public expression_node<T> 08252 | { 08253 | public: 08254 | 08255 | typedef expression_node<T>* expression_ptr; 08256 | typedef std::pair<expression_ptr,bool> branch_t; 08257 | 08258 | template <typename Allocator, 08259 | template <typename, typename> class Sequence> 08260 | explicit switch_node(const Sequence<expression_ptr,Allocator>& arg_list) 08261 | { 08262 | if (1 != (arg_list.size() & 1)) 08263 | return; 08264 | 08265 | arg_list_.resize(arg_list.size()); 08266 | 08267 | for (std::size_t i = 0; i < arg_list.size(); ++i) 08268 | { 08269 | if (arg_list[i] && arg_list[i]->valid()) 08270 | { 08271 | construct_branch_pair(arg_list_[i], arg_list[i]); 08272 | } 08273 | else 08274 | { 08275 | arg_list_.clear(); 08276 | return; 08277 | } 08278 | } 08279 | 08280 | assert(valid()); 08281 | } 08282 | 08283 | inline T value() const exprtk_override 08284 | { 08285 | const std::size_t upper_bound = (arg_list_.size() - 1); 08286 | 08287 | for (std::size_t i = 0; i < upper_bound; i += 2) 08288 | { 08289 | expression_ptr condition = arg_list_[i ].first; 08290 | expression_ptr consequent = arg_list_[i + 1].first; 08291 | 08292 | if (is_true(condition)) 08293 | { 08294 | return consequent->value(); 08295 | } 08296 | } 08297 | 08298 | return arg_list_[upper_bound].first->value(); 08299 | } 08300 | 08301 | inline typename expression_node<T>::node_type type() const exprtk_override exprtk_final 08302 | { 08303 | return expression_node<T>::e_switch; 08304 | } 08305 | 08306 | inline bool valid() const exprtk_override 08307 | { 08308 | return !arg_list_.empty(); 08309 | } 08310 | 08311 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 08312 | { 08313 | expression_node<T>::ndb_t::collect(arg_list_, node_delete_list); 08314 | } 08315 | 08316 | std::size_t node_depth() const exprtk_override exprtk_final 08317 | { 08318 | return expression_node<T>::ndb_t::compute_node_depth(arg_list_); 08319 | } 08320 | 08321 | protected: 08322 | 08323 | std::vector<branch_t> arg_list_; 08324 | }; 08325 | 08326 | template <typename T, typename Switch_N> 08327 | class switch_n_node exprtk_final : public switch_node<T> 08328 | { 08329 | public: 08330 | 08331 | typedef expression_node<T>* expression_ptr; 08332 | 08333 | template <typename Allocator, 08334 | template <typename, typename> class Sequence> 08335 | explicit switch_n_node(const Sequence<expression_ptr,Allocator>& arg_list) 08336 | : switch_node<T>(arg_list) 08337 | {} 08338 | 08339 | inline T value() const exprtk_override 08340 | { 08341 | return Switch_N::process(switch_node<T>::arg_list_); 08342 | } 08343 | }; 08344 | 08345 | template <typename T> 08346 | class multi_switch_node exprtk_final : public expression_node<T> 08347 | { 08348 | public: 08349 | 08350 | typedef expression_node<T>* expression_ptr; 08351 | typedef std::pair<expression_ptr,bool> branch_t; 08352 | 08353 | template <typename Allocator, 08354 | template <typename, typename> class Sequence> 08355 | explicit multi_switch_node(const Sequence<expression_ptr,Allocator>& arg_list) 08356 | { 08357 | if (0 != (arg_list.size() & 1)) 08358 | return; 08359 | 08360 | arg_list_.resize(arg_list.size()); 08361 | 08362 | for (std::size_t i = 0; i < arg_list.size(); ++i) 08363 | { 08364 | if (arg_list[i] && arg_list[i]->valid()) 08365 | { 08366 | construct_branch_pair(arg_list_[i], arg_list[i]); 08367 | } 08368 | else 08369 | { 08370 | arg_list_.clear(); 08371 | return; 08372 | } 08373 | } 08374 | 08375 | assert(valid()); 08376 | } 08377 | 08378 | inline T value() const exprtk_override 08379 | { 08380 | const std::size_t upper_bound = (arg_list_.size() - 1); 08381 | 08382 | T result = T(0); 08383 | 08384 | for (std::size_t i = 0; i < upper_bound; i += 2) 08385 | { 08386 | expression_ptr condition = arg_list_[i ].first; 08387 | expression_ptr consequent = arg_list_[i + 1].first; 08388 | 08389 | if (is_true(condition)) 08390 | { 08391 | result = consequent->value(); 08392 | } 08393 | } 08394 | 08395 | return result; 08396 | } 08397 | 08398 | inline typename expression_node<T>::node_type type() const exprtk_override 08399 | { 08400 | return expression_node<T>::e_mswitch; 08401 | } 08402 | 08403 | inline bool valid() const exprtk_override 08404 | { 08405 | return !arg_list_.empty() && (0 == (arg_list_.size() % 2)); 08406 | } 08407 | 08408 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 08409 | { 08410 | expression_node<T>::ndb_t::collect(arg_list_, node_delete_list); 08411 | } 08412 | 08413 | std::size_t node_depth() const exprtk_override exprtk_final 08414 | { 08415 | return expression_node<T>::ndb_t::compute_node_depth(arg_list_); 08416 | } 08417 | 08418 | private: 08419 | 08420 | std::vector<branch_t> arg_list_; 08421 | }; 08422 | 08423 | template <typename T> 08424 | class ivariable 08425 | { 08426 | public: 08427 | 08428 | virtual ~ivariable() 08429 | {} 08430 | 08431 | virtual T& ref() = 0; 08432 | virtual const T& ref() const = 0; 08433 | }; 08434 | 08435 | template <typename T> 08436 | class variable_node exprtk_final 08437 | : public expression_node<T> 08438 | , public ivariable <T> 08439 | { 08440 | public: 08441 | 08442 | static T null_value; 08443 | 08444 | explicit variable_node() 08445 | : value_(&null_value) 08446 | {} 08447 | 08448 | explicit variable_node(T& v) 08449 | : value_(&v) 08450 | {} 08451 | 08452 | inline bool operator <(const variable_node<T>& v) const 08453 | { 08454 | return this < (&v); 08455 | } 08456 | 08457 | inline T value() const exprtk_override 08458 | { 08459 | return (*value_); 08460 | } 08461 | 08462 | inline T& ref() exprtk_override 08463 | { 08464 | return (*value_); 08465 | } 08466 | 08467 | inline const T& ref() const exprtk_override 08468 | { 08469 | return (*value_); 08470 | } 08471 | 08472 | inline typename expression_node<T>::node_type type() const exprtk_override 08473 | { 08474 | return expression_node<T>::e_variable; 08475 | } 08476 | 08477 | private: 08478 | 08479 | T* value_; 08480 | }; 08481 | 08482 | template <typename T> 08483 | T variable_node<T>::null_value = T(std::numeric_limits<T>::quiet_NaN()); 08484 | 08485 | template <typename T> 08486 | struct range_pack 08487 | { 08488 | typedef expression_node<T>* expression_node_ptr; 08489 | typedef std::pair<std::size_t,std::size_t> cached_range_t; 08490 | 08491 | struct size_holder_t 08492 | { 08493 | std::size_t size_; 08494 | 08495 | size_holder_t(const std::size_t sz = std::numeric_limits<std::size_t>::max()) 08496 | : size_(sz) 08497 | {} 08498 | 08499 | std::size_t size() const 08500 | { 08501 | return size_; 08502 | } 08503 | }; 08504 | 08505 | range_pack() 08506 | : n0_e (std::make_pair(false,expression_node_ptr(0))) 08507 | , n1_e (std::make_pair(false,expression_node_ptr(0))) 08508 | , n0_c (std::make_pair(false,0)) 08509 | , n1_c (std::make_pair(false,0)) 08510 | , cache(std::make_pair(0,0)) 08511 | {} 08512 | 08513 | void clear() 08514 | { 08515 | n0_e = std::make_pair(false,expression_node_ptr(0)); 08516 | n1_e = std::make_pair(false,expression_node_ptr(0)); 08517 | n0_c = std::make_pair(false,0); 08518 | n1_c = std::make_pair(false,0); 08519 | cache = std::make_pair(0,0); 08520 | } 08521 | 08522 | void free() 08523 | { 08524 | if (n0_e.first && n0_e.second) 08525 | { 08526 | n0_e.first = false; 08527 | 08528 | if ( 08529 | !is_variable_node(n0_e.second) && 08530 | !is_string_node (n0_e.second) 08531 | ) 08532 | { 08533 | destroy_node(n0_e.second); 08534 | } 08535 | } 08536 | 08537 | if (n1_e.first && n1_e.second) 08538 | { 08539 | n1_e.first = false; 08540 | 08541 | if ( 08542 | !is_variable_node(n1_e.second) && 08543 | !is_string_node (n1_e.second) 08544 | ) 08545 | { 08546 | destroy_node(n1_e.second); 08547 | } 08548 | } 08549 | } 08550 | 08551 | bool const_range() const 08552 | { 08553 | return ( n0_c.first && n1_c.first) && 08554 | (!n0_e.first && !n1_e.first); 08555 | } 08556 | 08557 | bool var_range() const 08558 | { 08559 | return ( n0_e.first && n1_e.first) && 08560 | (!n0_c.first && !n1_c.first); 08561 | } 08562 | 08563 | template <typename StrBaseType> 08564 | bool operator() (std::size_t& r0, std::size_t& r1, const StrBaseType& str_base) const 08565 | { 08566 | if (n0_c.first) 08567 | r0 = n0_c.second; 08568 | else if (n0_e.first) 08569 | { 08570 | r0 = static_cast<std::size_t>(details::numeric::to_int64(n0_e.second->value())); 08571 | } 08572 | else 08573 | return false; 08574 | 08575 | if (n1_c.first) 08576 | r1 = n1_c.second; 08577 | else if (n1_e.first) 08578 | { 08579 | r1 = static_cast<std::size_t>(details::numeric::to_int64(n1_e.second->value())); 08580 | } 08581 | else 08582 | return false; 08583 | 08584 | const std::size_t size = str_base.size(); 08585 | 08586 | if ( 08587 | (std::numeric_limits<std::size_t>::max() != size) && 08588 | (std::numeric_limits<std::size_t>::max() == r1 ) 08589 | ) 08590 | { 08591 | r1 = size; 08592 | } 08593 | 08594 | cache.first = r0; 08595 | cache.second = r1; 08596 | 08597 | #ifdef exprtk_enable_range_runtime_checks 08598 | return range_runtime_check(r0, r1, size); 08599 | #else 08600 | return (r0 <= r1) && (r1 <= size); 08601 | #endif 08602 | } 08603 | 08604 | inline std::size_t const_size() const 08605 | { 08606 | return (n1_c.second - n0_c.second); 08607 | } 08608 | 08609 | inline std::size_t cache_size() const 08610 | { 08611 | return (cache.second - cache.first); 08612 | } 08613 | 08614 | std::pair<bool,expression_node_ptr> n0_e; 08615 | std::pair<bool,expression_node_ptr> n1_e; 08616 | std::pair<bool,std::size_t > n0_c; 08617 | std::pair<bool,std::size_t > n1_c; 08618 | mutable cached_range_t cache; 08619 | 08620 | #ifdef exprtk_enable_range_runtime_checks 08621 | bool range_runtime_check(const std::size_t r0, 08622 | const std::size_t r1, 08623 | const std::size_t size) const 08624 | { 08625 | if (r0 > size) 08626 | { 08627 | throw std::runtime_error("range error: (r0 < 0) || (r0 > size)"); 08628 | #if !defined(_MSC_VER) && !defined(__NVCOMPILER) 08629 | return false; 08630 | #endif 08631 | } 08632 | 08633 | if (r1 > size) 08634 | { 08635 | throw std::runtime_error("range error: (r1 < 0) || (r1 > size)"); 08636 | #if !defined(_MSC_VER) && !defined(__NVCOMPILER) 08637 | return false; 08638 | #endif 08639 | } 08640 | 08641 | return (r0 <= r1); 08642 | } 08643 | #endif 08644 | }; 08645 | 08646 | template <typename T> 08647 | class string_base_node; 08648 | 08649 | template <typename T> 08650 | struct range_data_type 08651 | { 08652 | typedef range_pack<T> range_t; 08653 | typedef string_base_node<T>* strbase_ptr_t; 08654 | 08655 | range_data_type() 08656 | : range(0) 08657 | , data (0) 08658 | , size (0) 08659 | , type_size(0) 08660 | , str_node (0) 08661 | {} 08662 | 08663 | range_t* range; 08664 | void* data; 08665 | std::size_t size; 08666 | std::size_t type_size; 08667 | strbase_ptr_t str_node; 08668 | }; 08669 | 08670 | template <typename T> class vector_node; 08671 | 08672 | template <typename T> 08673 | class vector_interface 08674 | { 08675 | public: 08676 | 08677 | typedef vector_node<T>* vector_node_ptr; 08678 | typedef vec_data_store<T> vds_t; 08679 | 08680 | virtual ~vector_interface() 08681 | {} 08682 | 08683 | virtual std::size_t size () const = 0; 08684 | 08685 | virtual std::size_t base_size() const = 0; 08686 | 08687 | virtual vector_node_ptr vec () const = 0; 08688 | 08689 | virtual vector_node_ptr vec () = 0; 08690 | 08691 | virtual vds_t& vds () = 0; 08692 | 08693 | virtual const vds_t& vds () const = 0; 08694 | 08695 | virtual bool side_effect () const { return false; } 08696 | }; 08697 | 08698 | template <typename T> 08699 | class vector_node exprtk_final 08700 | : public expression_node <T> 08701 | , public vector_interface<T> 08702 | { 08703 | public: 08704 | 08705 | typedef expression_node<T>* expression_ptr; 08706 | typedef vector_holder<T> vector_holder_t; 08707 | typedef vector_node<T>* vector_node_ptr; 08708 | typedef vec_data_store<T> vds_t; 08709 | 08710 | explicit vector_node(vector_holder_t* vh) 08711 | : vector_holder_(vh) 08712 | , vds_((*vector_holder_).size(),(*vector_holder_)[0]) 08713 | { 08714 | vector_holder_->set_ref(&vds_.ref()); 08715 | } 08716 | 08717 | vector_node(const vds_t& vds, vector_holder_t* vh) 08718 | : vector_holder_(vh) 08719 | , vds_(vds) 08720 | {} 08721 | 08722 | ~vector_node() exprtk_override 08723 | { 08724 | assert(valid()); 08725 | vector_holder_->remove_ref(&vds_.ref()); 08726 | } 08727 | 08728 | inline T value() const exprtk_override 08729 | { 08730 | return vds().data()[0]; 08731 | } 08732 | 08733 | vector_node_ptr vec() const exprtk_override 08734 | { 08735 | return const_cast<vector_node_ptr>(this); 08736 | } 08737 | 08738 | vector_node_ptr vec() exprtk_override 08739 | { 08740 | return this; 08741 | } 08742 | 08743 | inline typename expression_node<T>::node_type type() const exprtk_override 08744 | { 08745 | return expression_node<T>::e_vector; 08746 | } 08747 | 08748 | inline bool valid() const exprtk_override 08749 | { 08750 | return vector_holder_; 08751 | } 08752 | 08753 | std::size_t size() const exprtk_override 08754 | { 08755 | return vec_holder().size(); 08756 | } 08757 | 08758 | std::size_t base_size() const exprtk_override 08759 | { 08760 | return vec_holder().base_size(); 08761 | } 08762 | 08763 | vds_t& vds() exprtk_override 08764 | { 08765 | return vds_; 08766 | } 08767 | 08768 | const vds_t& vds() const exprtk_override 08769 | { 08770 | return vds_; 08771 | } 08772 | 08773 | inline vector_holder_t& vec_holder() 08774 | { 08775 | return (*vector_holder_); 08776 | } 08777 | 08778 | inline vector_holder_t& vec_holder() const 08779 | { 08780 | return (*vector_holder_); 08781 | } 08782 | 08783 | private: 08784 | 08785 | vector_holder_t* vector_holder_; 08786 | vds_t vds_; 08787 | }; 08788 | 08789 | template <typename T> 08790 | class vector_size_node exprtk_final 08791 | : public expression_node <T> 08792 | { 08793 | public: 08794 | 08795 | typedef expression_node<T>* expression_ptr; 08796 | typedef vector_holder<T> vector_holder_t; 08797 | 08798 | explicit vector_size_node(vector_holder_t* vh) 08799 | : vector_holder_(vh) 08800 | {} 08801 | 08802 | ~vector_size_node() exprtk_override 08803 | { 08804 | assert(valid()); 08805 | } 08806 | 08807 | inline T value() const exprtk_override 08808 | { 08809 | assert(vector_holder_); 08810 | return static_cast<T>(vector_holder_->size()); 08811 | } 08812 | 08813 | inline typename expression_node<T>::node_type type() const exprtk_override 08814 | { 08815 | return expression_node<T>::e_vecsize; 08816 | } 08817 | 08818 | inline bool valid() const exprtk_override 08819 | { 08820 | return vector_holder_ && vector_holder_->size(); 08821 | } 08822 | 08823 | inline vector_holder_t* vec_holder() 08824 | { 08825 | return vector_holder_; 08826 | } 08827 | 08828 | private: 08829 | 08830 | vector_holder_t* vector_holder_; 08831 | }; 08832 | 08833 | template <typename T> 08834 | class vector_elem_node exprtk_final 08835 | : public expression_node<T> 08836 | , public ivariable <T> 08837 | { 08838 | public: 08839 | 08840 | typedef expression_node<T>* expression_ptr; 08841 | typedef vector_holder<T> vector_holder_t; 08842 | typedef vector_holder_t* vector_holder_ptr; 08843 | typedef std::pair<expression_ptr,bool> branch_t; 08844 | 08845 | vector_elem_node(expression_ptr vec_node, 08846 | expression_ptr index, 08847 | vector_holder_ptr vec_holder) 08848 | : vector_holder_(vec_holder) 08849 | , vector_base_((*vec_holder)[0]) 08850 | { 08851 | construct_branch_pair(vector_node_, vec_node); 08852 | construct_branch_pair(index_ , index ); 08853 | assert(valid()); 08854 | } 08855 | 08856 | inline T value() const exprtk_override 08857 | { 08858 | return *access_vector(); 08859 | } 08860 | 08861 | inline T& ref() exprtk_override 08862 | { 08863 | return *access_vector(); 08864 | } 08865 | 08866 | inline const T& ref() const exprtk_override 08867 | { 08868 | return *access_vector(); 08869 | } 08870 | 08871 | inline typename expression_node<T>::node_type type() const exprtk_override 08872 | { 08873 | return expression_node<T>::e_vecelem; 08874 | } 08875 | 08876 | inline bool valid() const exprtk_override 08877 | { 08878 | return 08879 | vector_holder_ && 08880 | index_.first && 08881 | vector_node_.first && 08882 | index_.first->valid() && 08883 | vector_node_.first->valid(); 08884 | } 08885 | 08886 | inline vector_holder_t& vec_holder() 08887 | { 08888 | return (*vector_holder_); 08889 | } 08890 | 08891 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 08892 | { 08893 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 08894 | expression_node<T>::ndb_t::collect(index_ , node_delete_list); 08895 | } 08896 | 08897 | std::size_t node_depth() const exprtk_override 08898 | { 08899 | return expression_node<T>::ndb_t::compute_node_depth 08900 | (vector_node_, index_); 08901 | } 08902 | 08903 | private: 08904 | 08905 | inline T* access_vector() const 08906 | { 08907 | vector_node_.first->value(); 08908 | return (vector_base_ + details::numeric::to_uint64(index_.first->value())); 08909 | } 08910 | 08911 | vector_holder_ptr vector_holder_; 08912 | T* vector_base_; 08913 | branch_t vector_node_; 08914 | branch_t index_; 08915 | }; 08916 | 08917 | template <typename T> 08918 | class vector_celem_node exprtk_final 08919 | : public expression_node<T> 08920 | , public ivariable <T> 08921 | { 08922 | public: 08923 | 08924 | typedef expression_node<T>* expression_ptr; 08925 | typedef vector_holder<T> vector_holder_t; 08926 | typedef vector_holder_t* vector_holder_ptr; 08927 | typedef std::pair<expression_ptr,bool> branch_t; 08928 | 08929 | vector_celem_node(expression_ptr vec_node, 08930 | const std::size_t index, 08931 | vector_holder_ptr vec_holder) 08932 | : index_(index) 08933 | , vector_holder_(vec_holder) 08934 | , vector_base_((*vec_holder)[0]) 08935 | { 08936 | construct_branch_pair(vector_node_, vec_node); 08937 | assert(valid()); 08938 | } 08939 | 08940 | inline T value() const exprtk_override 08941 | { 08942 | return *access_vector(); 08943 | } 08944 | 08945 | inline T& ref() exprtk_override 08946 | { 08947 | return *access_vector(); 08948 | } 08949 | 08950 | inline const T& ref() const exprtk_override 08951 | { 08952 | return *access_vector(); 08953 | } 08954 | 08955 | inline typename expression_node<T>::node_type type() const exprtk_override 08956 | { 08957 | return expression_node<T>::e_veccelem; 08958 | } 08959 | 08960 | inline bool valid() const exprtk_override 08961 | { 08962 | return 08963 | vector_holder_ && 08964 | vector_node_.first && 08965 | vector_node_.first->valid(); 08966 | } 08967 | 08968 | inline vector_holder_t& vec_holder() 08969 | { 08970 | return (*vector_holder_); 08971 | } 08972 | 08973 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 08974 | { 08975 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 08976 | } 08977 | 08978 | std::size_t node_depth() const exprtk_override 08979 | { 08980 | return expression_node<T>::ndb_t::compute_node_depth(vector_node_); 08981 | } 08982 | 08983 | private: 08984 | 08985 | inline T* access_vector() const 08986 | { 08987 | vector_node_.first->value(); 08988 | return (vector_base_ + index_); 08989 | } 08990 | 08991 | const std::size_t index_; 08992 | vector_holder_ptr vector_holder_; 08993 | T* vector_base_; 08994 | branch_t vector_node_; 08995 | }; 08996 | 08997 | template <typename T> 08998 | class vector_elem_rtc_node exprtk_final 08999 | : public expression_node<T> 09000 | , public ivariable <T> 09001 | { 09002 | public: 09003 | 09004 | typedef expression_node<T>* expression_ptr; 09005 | typedef vector_holder<T> vector_holder_t; 09006 | typedef vector_holder_t* vector_holder_ptr; 09007 | typedef std::pair<expression_ptr,bool> branch_t; 09008 | 09009 | vector_elem_rtc_node(expression_ptr vec_node, 09010 | expression_ptr index, 09011 | vector_holder_ptr vec_holder, 09012 | vector_access_runtime_check_ptr vec_rt_chk) 09013 | : vector_holder_(vec_holder) 09014 | , vector_base_((*vec_holder)[0]) 09015 | , vec_rt_chk_(vec_rt_chk) 09016 | , max_vector_index_(vector_holder_->size() - 1) 09017 | { 09018 | construct_branch_pair(vector_node_, vec_node); 09019 | construct_branch_pair(index_ , index ); 09020 | assert(valid()); 09021 | } 09022 | 09023 | inline T value() const exprtk_override 09024 | { 09025 | return *access_vector(); 09026 | } 09027 | 09028 | inline T& ref() exprtk_override 09029 | { 09030 | return *access_vector(); 09031 | } 09032 | 09033 | inline const T& ref() const exprtk_override 09034 | { 09035 | return *access_vector(); 09036 | } 09037 | 09038 | inline typename expression_node<T>::node_type type() const exprtk_override 09039 | { 09040 | return expression_node<T>::e_vecelemrtc; 09041 | } 09042 | 09043 | inline bool valid() const exprtk_override 09044 | { 09045 | return 09046 | vector_holder_ && 09047 | index_.first && 09048 | vector_node_.first && 09049 | index_.first->valid() && 09050 | vector_node_.first->valid(); 09051 | } 09052 | 09053 | inline vector_holder_t& vec_holder() 09054 | { 09055 | return (*vector_holder_); 09056 | } 09057 | 09058 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09059 | { 09060 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 09061 | expression_node<T>::ndb_t::collect(index_, node_delete_list); 09062 | } 09063 | 09064 | std::size_t node_depth() const exprtk_override 09065 | { 09066 | return expression_node<T>::ndb_t::compute_node_depth 09067 | (vector_node_, index_); 09068 | } 09069 | 09070 | private: 09071 | 09072 | inline T* access_vector() const 09073 | { 09074 | const _uint64_t index = details::numeric::to_uint64(index_.first->value()); 09075 | vector_node_.first->value(); 09076 | 09077 | if (index <= max_vector_index_) 09078 | { 09079 | return (vector_holder_->data() + index); 09080 | } 09081 | 09082 | assert(vec_rt_chk_); 09083 | 09084 | const _uint64_t base_address = reinterpret_cast<_uint64_t>(vector_base_); 09085 | 09086 | vector_access_runtime_check::violation_context context; 09087 | context.base_ptr = reinterpret_cast<void*>(base_address); 09088 | context.end_ptr = reinterpret_cast<void*>(base_address + vector_holder_->size() * sizeof(T)); 09089 | context.access_ptr = reinterpret_cast<void*>(base_address + index * sizeof(T)); 09090 | context.type_size = sizeof(T); 09091 | 09092 | return vec_rt_chk_->handle_runtime_violation(context) ? 09093 | reinterpret_cast<T*>(context.access_ptr) : 09094 | vector_base_ ; 09095 | } 09096 | 09097 | vector_holder_ptr vector_holder_; 09098 | T* vector_base_; 09099 | branch_t vector_node_; 09100 | branch_t index_; 09101 | vector_access_runtime_check_ptr vec_rt_chk_; 09102 | const std::size_t max_vector_index_; 09103 | }; 09104 | 09105 | template <typename T> 09106 | class vector_celem_rtc_node exprtk_final 09107 | : public expression_node<T> 09108 | , public ivariable <T> 09109 | { 09110 | public: 09111 | 09112 | typedef expression_node<T>* expression_ptr; 09113 | typedef vector_holder<T> vector_holder_t; 09114 | typedef vector_holder_t* vector_holder_ptr; 09115 | typedef std::pair<expression_ptr,bool> branch_t; 09116 | 09117 | vector_celem_rtc_node(expression_ptr vec_node, 09118 | const std::size_t index, 09119 | vector_holder_ptr vec_holder, 09120 | vector_access_runtime_check_ptr vec_rt_chk) 09121 | : index_(index) 09122 | , max_vector_index_(vec_holder->size() - 1) 09123 | , vector_holder_(vec_holder) 09124 | , vector_base_((*vec_holder)[0]) 09125 | , vec_rt_chk_(vec_rt_chk) 09126 | { 09127 | construct_branch_pair(vector_node_, vec_node); 09128 | assert(valid()); 09129 | } 09130 | 09131 | inline T value() const exprtk_override 09132 | { 09133 | return *access_vector(); 09134 | } 09135 | 09136 | inline T& ref() exprtk_override 09137 | { 09138 | return *access_vector(); 09139 | } 09140 | 09141 | inline const T& ref() const exprtk_override 09142 | { 09143 | return *access_vector(); 09144 | } 09145 | 09146 | inline typename expression_node<T>::node_type type() const exprtk_override 09147 | { 09148 | return expression_node<T>::e_veccelemrtc; 09149 | } 09150 | 09151 | inline bool valid() const exprtk_override 09152 | { 09153 | return 09154 | vector_holder_ && 09155 | vector_node_.first && 09156 | vector_node_.first->valid(); 09157 | } 09158 | 09159 | inline vector_holder_t& vec_holder() 09160 | { 09161 | return (*vector_holder_); 09162 | } 09163 | 09164 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09165 | { 09166 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 09167 | } 09168 | 09169 | std::size_t node_depth() const exprtk_override 09170 | { 09171 | return expression_node<T>::ndb_t::compute_node_depth(vector_node_); 09172 | } 09173 | 09174 | private: 09175 | 09176 | inline T* access_vector() const 09177 | { 09178 | vector_node_.first->value(); 09179 | 09180 | if (index_ <= max_vector_index_) 09181 | { 09182 | return (vector_holder_->data() + index_); 09183 | } 09184 | 09185 | assert(vec_rt_chk_); 09186 | 09187 | const _uint64_t base_address = reinterpret_cast<_uint64_t>(vector_base_); 09188 | 09189 | vector_access_runtime_check::violation_context context; 09190 | context.base_ptr = reinterpret_cast<void*>(base_address); 09191 | context.end_ptr = reinterpret_cast<void*>(base_address + vector_holder_->size() * sizeof(T)); 09192 | context.access_ptr = reinterpret_cast<void*>(base_address + index_ * sizeof(T)); 09193 | context.type_size = sizeof(T); 09194 | 09195 | return vec_rt_chk_->handle_runtime_violation(context) ? 09196 | reinterpret_cast<T*>(context.access_ptr) : 09197 | vector_base_ ; 09198 | } 09199 | 09200 | const std::size_t index_; 09201 | const std::size_t max_vector_index_; 09202 | vector_holder_ptr vector_holder_; 09203 | T* vector_base_; 09204 | branch_t vector_node_; 09205 | vector_access_runtime_check_ptr vec_rt_chk_; 09206 | }; 09207 | 09208 | template <typename T> 09209 | class rebasevector_elem_node exprtk_final 09210 | : public expression_node<T> 09211 | , public ivariable <T> 09212 | { 09213 | public: 09214 | 09215 | typedef expression_node<T>* expression_ptr; 09216 | typedef vector_holder<T> vector_holder_t; 09217 | typedef vector_holder_t* vector_holder_ptr; 09218 | typedef vec_data_store<T> vds_t; 09219 | typedef std::pair<expression_ptr,bool> branch_t; 09220 | 09221 | rebasevector_elem_node(expression_ptr vec_node, 09222 | expression_ptr index, 09223 | vector_holder_ptr vec_holder) 09224 | : vector_holder_(vec_holder) 09225 | { 09226 | construct_branch_pair(vector_node_, vec_node); 09227 | construct_branch_pair(index_ , index ); 09228 | assert(valid()); 09229 | } 09230 | 09231 | inline T value() const exprtk_override 09232 | { 09233 | return *access_vector(); 09234 | } 09235 | 09236 | inline T& ref() exprtk_override 09237 | { 09238 | return *access_vector(); 09239 | } 09240 | 09241 | inline const T& ref() const exprtk_override 09242 | { 09243 | return *access_vector(); 09244 | } 09245 | 09246 | inline typename expression_node<T>::node_type type() const exprtk_override 09247 | { 09248 | return expression_node<T>::e_rbvecelem; 09249 | } 09250 | 09251 | inline bool valid() const exprtk_override 09252 | { 09253 | return 09254 | vector_holder_ && 09255 | index_.first && 09256 | vector_node_.first && 09257 | index_.first->valid() && 09258 | vector_node_.first->valid(); 09259 | } 09260 | 09261 | inline vector_holder_t& vec_holder() 09262 | { 09263 | return (*vector_holder_); 09264 | } 09265 | 09266 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09267 | { 09268 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 09269 | expression_node<T>::ndb_t::collect(index_, node_delete_list); 09270 | } 09271 | 09272 | std::size_t node_depth() const exprtk_override 09273 | { 09274 | return expression_node<T>::ndb_t::compute_node_depth 09275 | (vector_node_, index_); 09276 | } 09277 | 09278 | private: 09279 | 09280 | inline T* access_vector() const 09281 | { 09282 | vector_node_.first->value(); 09283 | return (vector_holder_->data() + details::numeric::to_uint64(index_.first->value())); 09284 | } 09285 | 09286 | vector_holder_ptr vector_holder_; 09287 | branch_t vector_node_; 09288 | branch_t index_; 09289 | }; 09290 | 09291 | template <typename T> 09292 | class rebasevector_celem_node exprtk_final 09293 | : public expression_node<T> 09294 | , public ivariable <T> 09295 | { 09296 | public: 09297 | 09298 | typedef expression_node<T>* expression_ptr; 09299 | typedef vector_holder<T> vector_holder_t; 09300 | typedef vector_holder_t* vector_holder_ptr; 09301 | typedef std::pair<expression_ptr,bool> branch_t; 09302 | 09303 | rebasevector_celem_node(expression_ptr vec_node, 09304 | const std::size_t index, 09305 | vector_holder_ptr vec_holder) 09306 | : index_(index) 09307 | , vector_holder_(vec_holder) 09308 | { 09309 | construct_branch_pair(vector_node_, vec_node); 09310 | assert(valid()); 09311 | } 09312 | 09313 | inline T value() const exprtk_override 09314 | { 09315 | vector_node_.first->value(); 09316 | return ref(); 09317 | } 09318 | 09319 | inline T& ref() exprtk_override 09320 | { 09321 | return *(vector_holder_->data() + index_); 09322 | } 09323 | 09324 | inline const T& ref() const exprtk_override 09325 | { 09326 | return *(vector_holder_->data() + index_); 09327 | } 09328 | 09329 | inline typename expression_node<T>::node_type type() const exprtk_override 09330 | { 09331 | return expression_node<T>::e_rbveccelem; 09332 | } 09333 | 09334 | inline bool valid() const exprtk_override 09335 | { 09336 | return 09337 | vector_holder_ && 09338 | vector_node_.first && 09339 | vector_node_.first->valid(); 09340 | } 09341 | 09342 | inline vector_holder_t& vec_holder() 09343 | { 09344 | return (*vector_holder_); 09345 | } 09346 | 09347 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09348 | { 09349 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 09350 | } 09351 | 09352 | std::size_t node_depth() const exprtk_override 09353 | { 09354 | return expression_node<T>::ndb_t::compute_node_depth(vector_node_); 09355 | } 09356 | 09357 | private: 09358 | 09359 | const std::size_t index_; 09360 | vector_holder_ptr vector_holder_; 09361 | branch_t vector_node_; 09362 | }; 09363 | 09364 | template <typename T> 09365 | class rebasevector_elem_rtc_node exprtk_final 09366 | : public expression_node<T> 09367 | , public ivariable <T> 09368 | { 09369 | public: 09370 | 09371 | typedef expression_node<T>* expression_ptr; 09372 | typedef vector_holder<T> vector_holder_t; 09373 | typedef vector_holder_t* vector_holder_ptr; 09374 | typedef std::pair<expression_ptr,bool> branch_t; 09375 | 09376 | rebasevector_elem_rtc_node(expression_ptr vec_node, 09377 | expression_ptr index, 09378 | vector_holder_ptr vec_holder, 09379 | vector_access_runtime_check_ptr vec_rt_chk) 09380 | : vector_holder_(vec_holder) 09381 | , vec_rt_chk_(vec_rt_chk) 09382 | { 09383 | construct_branch_pair(vector_node_, vec_node); 09384 | construct_branch_pair(index_ , index ); 09385 | assert(valid()); 09386 | } 09387 | 09388 | inline T value() const exprtk_override 09389 | { 09390 | return *access_vector(); 09391 | } 09392 | 09393 | inline T& ref() exprtk_override 09394 | { 09395 | return *access_vector(); 09396 | } 09397 | 09398 | inline const T& ref() const exprtk_override 09399 | { 09400 | return *access_vector(); 09401 | } 09402 | 09403 | inline typename expression_node<T>::node_type type() const exprtk_override 09404 | { 09405 | return expression_node<T>::e_rbvecelemrtc; 09406 | } 09407 | 09408 | inline bool valid() const exprtk_override 09409 | { 09410 | return 09411 | vector_holder_ && 09412 | index_.first && 09413 | vector_node_.first && 09414 | index_.first->valid() && 09415 | vector_node_.first->valid(); 09416 | } 09417 | 09418 | inline vector_holder_t& vec_holder() 09419 | { 09420 | return (*vector_holder_); 09421 | } 09422 | 09423 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09424 | { 09425 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 09426 | expression_node<T>::ndb_t::collect(index_ , node_delete_list); 09427 | } 09428 | 09429 | std::size_t node_depth() const exprtk_override 09430 | { 09431 | return expression_node<T>::ndb_t::compute_node_depth 09432 | (vector_node_, index_); 09433 | } 09434 | 09435 | private: 09436 | 09437 | inline T* access_vector() const 09438 | { 09439 | vector_node_.first->value(); 09440 | const _uint64_t index = details::numeric::to_uint64(index_.first->value()); 09441 | 09442 | if (index <= (vector_holder_->size() - 1)) 09443 | { 09444 | return (vector_holder_->data() + index); 09445 | } 09446 | 09447 | assert(vec_rt_chk_); 09448 | 09449 | const _uint64_t base_address = reinterpret_cast<_uint64_t>(vector_holder_->data()); 09450 | 09451 | vector_access_runtime_check::violation_context context; 09452 | context.base_ptr = reinterpret_cast<void*>(base_address); 09453 | context.end_ptr = reinterpret_cast<void*>(base_address + vector_holder_->size() * sizeof(T)); 09454 | context.access_ptr = reinterpret_cast<void*>(base_address + index * sizeof(T)); 09455 | context.type_size = sizeof(T); 09456 | 09457 | return vec_rt_chk_->handle_runtime_violation(context) ? 09458 | reinterpret_cast<T*>(context.access_ptr) : 09459 | vector_holder_->data() ; 09460 | } 09461 | 09462 | vector_holder_ptr vector_holder_; 09463 | branch_t vector_node_; 09464 | branch_t index_; 09465 | vector_access_runtime_check_ptr vec_rt_chk_; 09466 | }; 09467 | 09468 | template <typename T> 09469 | class rebasevector_celem_rtc_node exprtk_final 09470 | : public expression_node<T> 09471 | , public ivariable <T> 09472 | { 09473 | public: 09474 | 09475 | typedef expression_node<T>* expression_ptr; 09476 | typedef vector_holder<T> vector_holder_t; 09477 | typedef vector_holder_t* vector_holder_ptr; 09478 | typedef std::pair<expression_ptr,bool> branch_t; 09479 | 09480 | rebasevector_celem_rtc_node(expression_ptr vec_node, 09481 | const std::size_t index, 09482 | vector_holder_ptr vec_holder, 09483 | vector_access_runtime_check_ptr vec_rt_chk) 09484 | : index_(index) 09485 | , vector_holder_(vec_holder) 09486 | , vector_base_((*vec_holder)[0]) 09487 | , vec_rt_chk_(vec_rt_chk) 09488 | { 09489 | construct_branch_pair(vector_node_, vec_node); 09490 | assert(valid()); 09491 | } 09492 | 09493 | inline T value() const exprtk_override 09494 | { 09495 | return *access_vector(); 09496 | } 09497 | 09498 | inline T& ref() exprtk_override 09499 | { 09500 | return *access_vector(); 09501 | } 09502 | 09503 | inline const T& ref() const exprtk_override 09504 | { 09505 | return *access_vector(); 09506 | } 09507 | 09508 | inline typename expression_node<T>::node_type type() const exprtk_override 09509 | { 09510 | return expression_node<T>::e_rbveccelemrtc; 09511 | } 09512 | 09513 | inline bool valid() const exprtk_override 09514 | { 09515 | return 09516 | vector_holder_ && 09517 | vector_node_.first && 09518 | vector_node_.first->valid(); 09519 | } 09520 | 09521 | inline vector_holder_t& vec_holder() 09522 | { 09523 | return (*vector_holder_); 09524 | } 09525 | 09526 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09527 | { 09528 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 09529 | } 09530 | 09531 | std::size_t node_depth() const exprtk_override 09532 | { 09533 | return expression_node<T>::ndb_t::compute_node_depth(vector_node_); 09534 | } 09535 | 09536 | private: 09537 | 09538 | inline T* access_vector() const 09539 | { 09540 | vector_node_.first->value(); 09541 | 09542 | if (index_ <= vector_holder_->size() - 1) 09543 | { 09544 | return (vector_holder_->data() + index_); 09545 | } 09546 | 09547 | assert(vec_rt_chk_); 09548 | 09549 | const _uint64_t base_address = reinterpret_cast<_uint64_t>(vector_base_); 09550 | 09551 | vector_access_runtime_check::violation_context context; 09552 | context.base_ptr = reinterpret_cast<void*>(base_address); 09553 | context.end_ptr = reinterpret_cast<void*>(base_address + vector_holder_->size() * sizeof(T)); 09554 | context.access_ptr = reinterpret_cast<void*>(base_address + index_ * sizeof(T)); 09555 | context.type_size = sizeof(T); 09556 | 09557 | return vec_rt_chk_->handle_runtime_violation(context) ? 09558 | reinterpret_cast<T*>(context.access_ptr) : 09559 | vector_base_ ; 09560 | } 09561 | 09562 | const std::size_t index_; 09563 | vector_holder_ptr vector_holder_; 09564 | T* vector_base_; 09565 | branch_t vector_node_; 09566 | vector_access_runtime_check_ptr vec_rt_chk_; 09567 | }; 09568 | 09569 | template <typename T> 09570 | class vector_initialisation_node exprtk_final : public expression_node<T> 09571 | { 09572 | public: 09573 | 09574 | typedef expression_node<T>* expression_ptr; 09575 | 09576 | vector_initialisation_node(T* vector_base, 09577 | const std::size_t& size, 09578 | const std::vector<expression_ptr>& initialiser_list, 09579 | const bool single_value_initialse) 09580 | : vector_base_(vector_base) 09581 | , initialiser_list_(initialiser_list) 09582 | , size_(size) 09583 | , single_value_initialse_(single_value_initialse) 09584 | , zero_value_initialse_(false) 09585 | , const_nonzero_literal_value_initialse_(false) 09586 | , single_initialiser_value_(T(0)) 09587 | { 09588 | if (single_value_initialse_) 09589 | { 09590 | if (initialiser_list_.empty()) 09591 | zero_value_initialse_ = true; 09592 | else if ( 09593 | (initialiser_list_.size() == 1) && 09594 | details::is_constant_node(initialiser_list_[0]) && 09595 | (T(0) == initialiser_list_[0]->value()) 09596 | ) 09597 | { 09598 | zero_value_initialse_ = true; 09599 | } 09600 | else 09601 | { 09602 | assert(initialiser_list_.size() == 1); 09603 | 09604 | if (details::is_constant_node(initialiser_list_[0])) 09605 | { 09606 | const_nonzero_literal_value_initialse_ = true; 09607 | single_initialiser_value_ = initialiser_list_[0]->value(); 09608 | assert(T(0) != single_initialiser_value_); 09609 | } 09610 | } 09611 | } 09612 | } 09613 | 09614 | inline T value() const exprtk_override 09615 | { 09616 | if (single_value_initialse_) 09617 | { 09618 | if (zero_value_initialse_) 09619 | { 09620 | details::set_zero_value(vector_base_, size_); 09621 | } 09622 | else if (const_nonzero_literal_value_initialse_) 09623 | { 09624 | for (std::size_t i = 0; i < size_; ++i) 09625 | { 09626 | *(vector_base_ + i) = single_initialiser_value_; 09627 | } 09628 | } 09629 | else 09630 | { 09631 | for (std::size_t i = 0; i < size_; ++i) 09632 | { 09633 | *(vector_base_ + i) = initialiser_list_[0]->value(); 09634 | } 09635 | } 09636 | } 09637 | else 09638 | { 09639 | const std::size_t initialiser_list_size = initialiser_list_.size(); 09640 | 09641 | for (std::size_t i = 0; i < initialiser_list_size; ++i) 09642 | { 09643 | *(vector_base_ + i) = initialiser_list_[i]->value(); 09644 | } 09645 | 09646 | if (initialiser_list_size < size_) 09647 | { 09648 | details::set_zero_value( 09649 | vector_base_ + initialiser_list_size, 09650 | (size_ - initialiser_list_size)); 09651 | } 09652 | } 09653 | 09654 | return *(vector_base_); 09655 | } 09656 | 09657 | inline typename expression_node<T>::node_type type() const exprtk_override 09658 | { 09659 | return expression_node<T>::e_vecinit; 09660 | } 09661 | 09662 | inline bool valid() const exprtk_override 09663 | { 09664 | return vector_base_; 09665 | } 09666 | 09667 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09668 | { 09669 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09670 | } 09671 | 09672 | std::size_t node_depth() const exprtk_override 09673 | { 09674 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09675 | } 09676 | 09677 | private: 09678 | 09679 | vector_initialisation_node(const vector_initialisation_node<T>&) exprtk_delete; 09680 | vector_initialisation_node<T>& operator=(const vector_initialisation_node<T>&) exprtk_delete; 09681 | 09682 | mutable T* vector_base_; 09683 | std::vector<expression_ptr> initialiser_list_; 09684 | const std::size_t size_; 09685 | const bool single_value_initialse_; 09686 | bool zero_value_initialse_; 09687 | bool const_nonzero_literal_value_initialse_; 09688 | T single_initialiser_value_; 09689 | }; 09690 | 09691 | template <typename T> 09692 | class vector_init_zero_value_node exprtk_final : public expression_node<T> 09693 | { 09694 | public: 09695 | 09696 | typedef expression_node<T>* expression_ptr; 09697 | 09698 | vector_init_zero_value_node(T* vector_base, 09699 | const std::size_t& size, 09700 | const std::vector<expression_ptr>& initialiser_list) 09701 | : vector_base_(vector_base) 09702 | , size_(size) 09703 | , initialiser_list_(initialiser_list) 09704 | {} 09705 | 09706 | inline T value() const exprtk_override 09707 | { 09708 | details::set_zero_value(vector_base_, size_); 09709 | return *(vector_base_); 09710 | } 09711 | 09712 | inline typename expression_node<T>::node_type type() const exprtk_override 09713 | { 09714 | return expression_node<T>::e_vecinit; 09715 | } 09716 | 09717 | inline bool valid() const exprtk_override 09718 | { 09719 | return vector_base_; 09720 | } 09721 | 09722 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09723 | { 09724 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09725 | } 09726 | 09727 | std::size_t node_depth() const exprtk_override 09728 | { 09729 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09730 | } 09731 | 09732 | private: 09733 | 09734 | vector_init_zero_value_node(const vector_init_zero_value_node<T>&) exprtk_delete; 09735 | vector_init_zero_value_node<T>& operator=(const vector_init_zero_value_node<T>&) exprtk_delete; 09736 | 09737 | mutable T* vector_base_; 09738 | const std::size_t size_; 09739 | std::vector<expression_ptr> initialiser_list_; 09740 | }; 09741 | 09742 | template <typename T> 09743 | class vector_init_single_constvalue_node exprtk_final : public expression_node<T> 09744 | { 09745 | public: 09746 | 09747 | typedef expression_node<T>* expression_ptr; 09748 | 09749 | vector_init_single_constvalue_node(T* vector_base, 09750 | const std::size_t& size, 09751 | const std::vector<expression_ptr>& initialiser_list) 09752 | : vector_base_(vector_base) 09753 | , size_(size) 09754 | , initialiser_list_(initialiser_list) 09755 | { 09756 | single_initialiser_value_ = initialiser_list_[0]->value(); 09757 | assert(valid()); 09758 | } 09759 | 09760 | inline T value() const exprtk_override 09761 | { 09762 | for (std::size_t i = 0; i < size_; ++i) 09763 | { 09764 | *(vector_base_ + i) = single_initialiser_value_; 09765 | } 09766 | 09767 | return *(vector_base_); 09768 | } 09769 | 09770 | inline typename expression_node<T>::node_type type() const exprtk_override 09771 | { 09772 | return expression_node<T>::e_vecinit; 09773 | } 09774 | 09775 | inline bool valid() const exprtk_override 09776 | { 09777 | return vector_base_ && 09778 | (initialiser_list_.size() == 1) && 09779 | (details::is_constant_node(initialiser_list_[0])) && 09780 | (single_initialiser_value_ != T(0)); 09781 | } 09782 | 09783 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09784 | { 09785 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09786 | } 09787 | 09788 | std::size_t node_depth() const exprtk_override 09789 | { 09790 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09791 | } 09792 | 09793 | private: 09794 | 09795 | vector_init_single_constvalue_node(const vector_init_single_constvalue_node<T>&) exprtk_delete; 09796 | vector_init_single_constvalue_node<T>& operator=(const vector_init_single_constvalue_node<T>&) exprtk_delete; 09797 | 09798 | mutable T* vector_base_; 09799 | const std::size_t size_; 09800 | std::vector<expression_ptr> initialiser_list_; 09801 | T single_initialiser_value_; 09802 | }; 09803 | 09804 | template <typename T> 09805 | class vector_init_single_value_node exprtk_final : public expression_node<T> 09806 | { 09807 | public: 09808 | 09809 | typedef expression_node<T>* expression_ptr; 09810 | 09811 | vector_init_single_value_node(T* vector_base, 09812 | const std::size_t& size, 09813 | const std::vector<expression_ptr>& initialiser_list) 09814 | : vector_base_(vector_base) 09815 | , size_(size) 09816 | , initialiser_list_(initialiser_list) 09817 | { 09818 | assert(valid()); 09819 | } 09820 | 09821 | inline T value() const exprtk_override 09822 | { 09823 | expression_node<T>& node = *initialiser_list_[0]; 09824 | 09825 | for (std::size_t i = 0; i < size_; ++i) 09826 | { 09827 | *(vector_base_ + i) = node.value(); 09828 | } 09829 | 09830 | return *(vector_base_); 09831 | } 09832 | 09833 | inline typename expression_node<T>::node_type type() const exprtk_override 09834 | { 09835 | return expression_node<T>::e_vecinit; 09836 | } 09837 | 09838 | inline bool valid() const exprtk_override 09839 | { 09840 | return vector_base_ && 09841 | (initialiser_list_.size() == 1) && 09842 | !details::is_constant_node(initialiser_list_[0]); 09843 | } 09844 | 09845 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09846 | { 09847 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09848 | } 09849 | 09850 | std::size_t node_depth() const exprtk_override 09851 | { 09852 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09853 | } 09854 | 09855 | private: 09856 | 09857 | vector_init_single_value_node(const vector_init_single_value_node<T>&) exprtk_delete; 09858 | vector_init_single_value_node<T>& operator=(const vector_init_single_value_node<T>&) exprtk_delete; 09859 | 09860 | mutable T* vector_base_; 09861 | const std::size_t size_; 09862 | std::vector<expression_ptr> initialiser_list_; 09863 | }; 09864 | 09865 | template <typename T> 09866 | class vector_init_iota_constconst_node exprtk_final : public expression_node<T> 09867 | { 09868 | public: 09869 | 09870 | typedef expression_node<T>* expression_ptr; 09871 | 09872 | vector_init_iota_constconst_node(T* vector_base, 09873 | const std::size_t& size, 09874 | const std::vector<expression_ptr>& initialiser_list) 09875 | : vector_base_(vector_base) 09876 | , size_(size) 09877 | , initialiser_list_(initialiser_list) 09878 | { 09879 | base_value_ = initialiser_list_[0]->value(); 09880 | increment_value_ = initialiser_list_[1]->value(); 09881 | 09882 | assert(valid()); 09883 | } 09884 | 09885 | inline T value() const exprtk_override 09886 | { 09887 | T value = base_value_; 09888 | 09889 | for (std::size_t i = 0; i < size_; ++i, value += increment_value_) 09890 | { 09891 | *(vector_base_ + i) = value; 09892 | } 09893 | 09894 | return *(vector_base_); 09895 | } 09896 | 09897 | inline typename expression_node<T>::node_type type() const exprtk_override 09898 | { 09899 | return expression_node<T>::e_vecinit; 09900 | } 09901 | 09902 | inline bool valid() const exprtk_override 09903 | { 09904 | return vector_base_ && 09905 | (initialiser_list_.size() == 2) && 09906 | (details::is_constant_node(initialiser_list_[0])) && 09907 | (details::is_constant_node(initialiser_list_[1])) ; 09908 | } 09909 | 09910 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09911 | { 09912 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09913 | } 09914 | 09915 | std::size_t node_depth() const exprtk_override 09916 | { 09917 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09918 | } 09919 | 09920 | private: 09921 | 09922 | vector_init_iota_constconst_node(const vector_init_iota_constconst_node<T>&) exprtk_delete; 09923 | vector_init_iota_constconst_node<T>& operator=(const vector_init_iota_constconst_node<T>&) exprtk_delete; 09924 | 09925 | mutable T* vector_base_; 09926 | const std::size_t size_; 09927 | std::vector<expression_ptr> initialiser_list_; 09928 | T base_value_; 09929 | T increment_value_; 09930 | }; 09931 | 09932 | template <typename T> 09933 | class vector_init_iota_constnconst_node exprtk_final : public expression_node<T> 09934 | { 09935 | public: 09936 | 09937 | typedef expression_node<T>* expression_ptr; 09938 | 09939 | vector_init_iota_constnconst_node(T* vector_base, 09940 | const std::size_t& size, 09941 | const std::vector<expression_ptr>& initialiser_list) 09942 | : vector_base_(vector_base) 09943 | , size_(size) 09944 | , initialiser_list_(initialiser_list) 09945 | { 09946 | assert(valid()); 09947 | base_value_ = initialiser_list_[0]->value(); 09948 | } 09949 | 09950 | inline T value() const exprtk_override 09951 | { 09952 | T value = base_value_; 09953 | expression_node<T>& increment = *initialiser_list_[1]; 09954 | 09955 | for (std::size_t i = 0; i < size_; ++i, value += increment.value()) 09956 | { 09957 | *(vector_base_ + i) = value; 09958 | } 09959 | 09960 | return *(vector_base_); 09961 | } 09962 | 09963 | inline typename expression_node<T>::node_type type() const exprtk_override 09964 | { 09965 | return expression_node<T>::e_vecinit; 09966 | } 09967 | 09968 | inline bool valid() const exprtk_override 09969 | { 09970 | return vector_base_ && 09971 | (initialiser_list_.size() == 2) && 09972 | ( details::is_constant_node(initialiser_list_[0])) && 09973 | (!details::is_constant_node(initialiser_list_[1])); 09974 | } 09975 | 09976 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09977 | { 09978 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09979 | } 09980 | 09981 | std::size_t node_depth() const exprtk_override 09982 | { 09983 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09984 | } 09985 | 09986 | private: 09987 | 09988 | vector_init_iota_constnconst_node(const vector_init_iota_constnconst_node<T>&) exprtk_delete; 09989 | vector_init_iota_constnconst_node<T>& operator=(const vector_init_iota_constnconst_node<T>&) exprtk_delete; 09990 | 09991 | mutable T* vector_base_; 09992 | const std::size_t size_; 09993 | std::vector<expression_ptr> initialiser_list_; 09994 | T base_value_; 09995 | }; 09996 | 09997 | template <typename T> 09998 | class vector_init_iota_nconstconst_node exprtk_final : public expression_node<T> 09999 | { 10000 | public: 10001 | 10002 | typedef expression_node<T>* expression_ptr; 10003 | 10004 | vector_init_iota_nconstconst_node(T* vector_base, 10005 | const std::size_t& size, 10006 | const std::vector<expression_ptr>& initialiser_list) 10007 | : vector_base_(vector_base) 10008 | , size_(size) 10009 | , initialiser_list_(initialiser_list) 10010 | { 10011 | assert(valid()); 10012 | } 10013 | 10014 | inline T value() const exprtk_override 10015 | { 10016 | T value = initialiser_list_[0]->value(); 10017 | const T increment = initialiser_list_[1]->value(); 10018 | 10019 | for (std::size_t i = 0; i < size_; ++i, value += increment) 10020 | { 10021 | *(vector_base_ + i) = value; 10022 | } 10023 | 10024 | return *(vector_base_); 10025 | } 10026 | 10027 | inline typename expression_node<T>::node_type type() const exprtk_override 10028 | { 10029 | return expression_node<T>::e_vecinit; 10030 | } 10031 | 10032 | inline bool valid() const exprtk_override 10033 | { 10034 | return vector_base_ && 10035 | (initialiser_list_.size() == 2) && 10036 | (!details::is_constant_node(initialiser_list_[0])) && 10037 | (details::is_constant_node(initialiser_list_[1])); 10038 | } 10039 | 10040 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 10041 | { 10042 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 10043 | } 10044 | 10045 | std::size_t node_depth() const exprtk_override 10046 | { 10047 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 10048 | } 10049 | 10050 | private: 10051 | 10052 | vector_init_iota_nconstconst_node(const vector_init_iota_nconstconst_node<T>&) exprtk_delete; 10053 | vector_init_iota_nconstconst_node<T>& operator=(const vector_init_iota_nconstconst_node<T>&) exprtk_delete; 10054 | 10055 | mutable T* vector_base_; 10056 | const std::size_t size_; 10057 | std::vector<expression_ptr> initialiser_list_; 10058 | }; 10059 | 10060 | template <typename T> 10061 | class vector_init_iota_nconstnconst_node exprtk_final : public expression_node<T> 10062 | { 10063 | public: 10064 | 10065 | typedef expression_node<T>* expression_ptr; 10066 | 10067 | vector_init_iota_nconstnconst_node(T* vector_base, 10068 | const std::size_t& size, 10069 | const std::vector<expression_ptr>& initialiser_list) 10070 | : vector_base_(vector_base) 10071 | , size_(size) 10072 | , initialiser_list_(initialiser_list) 10073 | { 10074 | assert(valid()); 10075 | } 10076 | 10077 | inline T value() const exprtk_override 10078 | { 10079 | T value = initialiser_list_[0]->value(); 10080 | expression_node<T>& increment = *initialiser_list_[1]; 10081 | 10082 | for (std::size_t i = 0; i < size_; ++i, value += increment.value()) 10083 | { 10084 | *(vector_base_ + i) = value; 10085 | } 10086 | 10087 | return *(vector_base_); 10088 | } 10089 | 10090 | inline typename expression_node<T>::node_type type() const exprtk_override 10091 | { 10092 | return expression_node<T>::e_vecinit; 10093 | } 10094 | 10095 | inline bool valid() const exprtk_override 10096 | { 10097 | return vector_base_ && 10098 | (initialiser_list_.size() == 2) && 10099 | (!details::is_constant_node(initialiser_list_[0])) && 10100 | (!details::is_constant_node(initialiser_list_[1])); 10101 | } 10102 | 10103 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 10104 | { 10105 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 10106 | } 10107 | 10108 | std::size_t node_depth() const exprtk_override 10109 | { 10110 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 10111 | } 10112 | 10113 | private: 10114 | 10115 | vector_init_iota_nconstnconst_node(const vector_init_iota_nconstnconst_node<T>&) exprtk_delete; 10116 | vector_init_iota_nconstnconst_node<T>& operator=(const vector_init_iota_nconstnconst_node<T>&) exprtk_delete; 10117 | 10118 | mutable T* vector_base_; 10119 | const std::size_t size_; 10120 | std::vector<expression_ptr> initialiser_list_; 10121 | }; 10122 | 10123 | template <typename T> 10124 | class swap_node exprtk_final : public expression_node<T> 10125 | { 10126 | public: 10127 | 10128 | typedef expression_node<T>* expression_ptr; 10129 | typedef variable_node<T>* variable_node_ptr; 10130 | 10131 | swap_node(variable_node_ptr var0, variable_node_ptr var1) 10132 | : var0_(var0) 10133 | , var1_(var1) 10134 | {} 10135 | 10136 | inline T value() const exprtk_override 10137 | { 10138 | std::swap(var0_->ref(),var1_->ref()); 10139 | return var1_->ref(); 10140 | } 10141 | 10142 | inline typename expression_node<T>::node_type type() const exprtk_override 10143 | { 10144 | return expression_node<T>::e_swap; 10145 | } 10146 | 10147 | private: 10148 | 10149 | variable_node_ptr var0_; 10150 | variable_node_ptr var1_; 10151 | }; 10152 | 10153 | template <typename T> 10154 | class swap_generic_node exprtk_final : public binary_node<T> 10155 | { 10156 | public: 10157 | 10158 | typedef expression_node<T>* expression_ptr; 10159 | typedef ivariable<T>* ivariable_ptr; 10160 | 10161 | swap_generic_node(expression_ptr var0, expression_ptr var1) 10162 | : binary_node<T>(details::e_swap, var0, var1) 10163 | , var0_(0) 10164 | , var1_(0) 10165 | , initialised_(false) 10166 | { 10167 | var0_ = dynamic_cast<ivariable_ptr>(var0); 10168 | var1_ = dynamic_cast<ivariable_ptr>(var1); 10169 | 10170 | initialised_ = (var0_ && var1_); 10171 | 10172 | assert(valid()); 10173 | } 10174 | 10175 | inline T value() const exprtk_override 10176 | { 10177 | std::swap(var0_->ref(),var1_->ref()); 10178 | return var1_->ref(); 10179 | } 10180 | 10181 | inline typename expression_node<T>::node_type type() const exprtk_override 10182 | { 10183 | return expression_node<T>::e_swap; 10184 | } 10185 | 10186 | inline bool valid() const exprtk_override 10187 | { 10188 | return initialised_ && binary_node<T>::valid(); 10189 | } 10190 | 10191 | private: 10192 | 10193 | ivariable_ptr var0_; 10194 | ivariable_ptr var1_; 10195 | bool initialised_; 10196 | }; 10197 | 10198 | template <typename T> 10199 | class swap_vecvec_node exprtk_final 10200 | : public binary_node <T> 10201 | , public vector_interface<T> 10202 | { 10203 | public: 10204 | 10205 | typedef expression_node<T>* expression_ptr; 10206 | typedef vector_node <T>* vector_node_ptr; 10207 | typedef vec_data_store <T> vds_t; 10208 | 10209 | using binary_node<T>::branch; 10210 | 10211 | swap_vecvec_node(expression_ptr branch0, 10212 | expression_ptr branch1) 10213 | : binary_node<T>(details::e_swap, branch0, branch1) 10214 | , vec0_node_ptr_(0) 10215 | , vec1_node_ptr_(0) 10216 | , initialised_ (false) 10217 | { 10218 | if (is_ivector_node(branch(0))) 10219 | { 10220 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 10221 | 10222 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(0)))) 10223 | { 10224 | vec0_node_ptr_ = vi->vec(); 10225 | vds() = vi->vds(); 10226 | } 10227 | } 10228 | 10229 | if (is_ivector_node(branch(1))) 10230 | { 10231 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 10232 | 10233 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1)))) 10234 | { 10235 | vec1_node_ptr_ = vi->vec(); 10236 | } 10237 | } 10238 | 10239 | if (vec0_node_ptr_ && vec1_node_ptr_) 10240 | { 10241 | initialised_ = size() <= base_size(); 10242 | } 10243 | 10244 | assert(valid()); 10245 | } 10246 | 10247 | inline T value() const exprtk_override 10248 | { 10249 | binary_node<T>::branch(0)->value(); 10250 | binary_node<T>::branch(1)->value(); 10251 | 10252 | T* vec0 = vec0_node_ptr_->vds().data(); 10253 | T* vec1 = vec1_node_ptr_->vds().data(); 10254 | 10255 | assert(size() <= base_size()); 10256 | const std::size_t n = size(); 10257 | 10258 | for (std::size_t i = 0; i < n; ++i) 10259 | { 10260 | std::swap(vec0[i],vec1[i]); 10261 | } 10262 | 10263 | return vec1_node_ptr_->value(); 10264 | } 10265 | 10266 | vector_node_ptr vec() const exprtk_override 10267 | { 10268 | return vec0_node_ptr_; 10269 | } 10270 | 10271 | vector_node_ptr vec() exprtk_override 10272 | { 10273 | return vec0_node_ptr_; 10274 | } 10275 | 10276 | inline typename expression_node<T>::node_type type() const exprtk_override 10277 | { 10278 | return expression_node<T>::e_vecvecswap; 10279 | } 10280 | 10281 | inline bool valid() const exprtk_override 10282 | { 10283 | return initialised_ && binary_node<T>::valid(); 10284 | } 10285 | 10286 | std::size_t size() const exprtk_override 10287 | { 10288 | return std::min( 10289 | vec0_node_ptr_->vec_holder().size(), 10290 | vec1_node_ptr_->vec_holder().size()); 10291 | } 10292 | 10293 | std::size_t base_size() const exprtk_override 10294 | { 10295 | return std::min( 10296 | vec0_node_ptr_->vec_holder().base_size(), 10297 | vec1_node_ptr_->vec_holder().base_size()); 10298 | } 10299 | 10300 | vds_t& vds() exprtk_override 10301 | { 10302 | return vds_; 10303 | } 10304 | 10305 | const vds_t& vds() const exprtk_override 10306 | { 10307 | return vds_; 10308 | } 10309 | 10310 | private: 10311 | 10312 | vector_node<T>* vec0_node_ptr_; 10313 | vector_node<T>* vec1_node_ptr_; 10314 | bool initialised_; 10315 | vds_t vds_; 10316 | }; 10317 | 10318 | #ifndef exprtk_disable_string_capabilities 10319 | template <typename T> 10320 | class stringvar_node exprtk_final 10321 | : public expression_node <T> 10322 | , public string_base_node<T> 10323 | , public range_interface <T> 10324 | { 10325 | public: 10326 | 10327 | typedef typename range_interface<T>::range_t range_t; 10328 | 10329 | static std::string null_value; 10330 | 10331 | explicit stringvar_node() 10332 | : value_(&null_value) 10333 | {} 10334 | 10335 | explicit stringvar_node(std::string& v) 10336 | : value_(&v) 10337 | { 10338 | rp_.n0_c = std::make_pair<bool,std::size_t>(true,0); 10339 | rp_.n1_c = std::make_pair<bool,std::size_t>(true,v.size()); 10340 | rp_.cache.first = rp_.n0_c.second; 10341 | rp_.cache.second = rp_.n1_c.second; 10342 | } 10343 | 10344 | inline bool operator <(const stringvar_node<T>& v) const 10345 | { 10346 | return this < (&v); 10347 | } 10348 | 10349 | inline T value() const exprtk_override 10350 | { 10351 | rp_.n1_c.second = (*value_).size(); 10352 | rp_.cache.second = rp_.n1_c.second; 10353 | 10354 | return std::numeric_limits<T>::quiet_NaN(); 10355 | } 10356 | 10357 | std::string str() const exprtk_override 10358 | { 10359 | return ref(); 10360 | } 10361 | 10362 | char_cptr base() const exprtk_override 10363 | { 10364 | return &(*value_)[0]; 10365 | } 10366 | 10367 | std::size_t size() const exprtk_override 10368 | { 10369 | return ref().size(); 10370 | } 10371 | 10372 | std::string& ref() 10373 | { 10374 | return (*value_); 10375 | } 10376 | 10377 | const std::string& ref() const 10378 | { 10379 | return (*value_); 10380 | } 10381 | 10382 | range_t& range_ref() exprtk_override 10383 | { 10384 | return rp_; 10385 | } 10386 | 10387 | const range_t& range_ref() const exprtk_override 10388 | { 10389 | return rp_; 10390 | } 10391 | 10392 | inline typename expression_node<T>::node_type type() const exprtk_override 10393 | { 10394 | return expression_node<T>::e_stringvar; 10395 | } 10396 | 10397 | void rebase(std::string& s) 10398 | { 10399 | value_ = &s; 10400 | rp_.n0_c = std::make_pair<bool,std::size_t>(true,0); 10401 | rp_.n1_c = std::make_pair<bool,std::size_t>(true,value_->size() - 1); 10402 | rp_.cache.first = rp_.n0_c.second; 10403 | rp_.cache.second = rp_.n1_c.second; 10404 | } 10405 | 10406 | private: 10407 | 10408 | std::string* value_; 10409 | mutable range_t rp_; 10410 | }; 10411 | 10412 | template <typename T> 10413 | std::string stringvar_node<T>::null_value = std::string(""); 10414 | 10415 | template <typename T> 10416 | class string_range_node exprtk_final 10417 | : public expression_node <T> 10418 | , public string_base_node<T> 10419 | , public range_interface <T> 10420 | { 10421 | public: 10422 | 10423 | typedef typename range_interface<T>::range_t range_t; 10424 | 10425 | static std::string null_value; 10426 | 10427 | explicit string_range_node(std::string& v, const range_t& rp) 10428 | : value_(&v) 10429 | , rp_(rp) 10430 | {} 10431 | 10432 | virtual ~string_range_node() 10433 | { 10434 | rp_.free(); 10435 | } 10436 | 10437 | inline bool operator <(const string_range_node<T>& v) const 10438 | { 10439 | return this < (&v); 10440 | } 10441 | 10442 | inline T value() const exprtk_override 10443 | { 10444 | return std::numeric_limits<T>::quiet_NaN(); 10445 | } 10446 | 10447 | std::string str() const exprtk_override 10448 | { 10449 | return (*value_); 10450 | } 10451 | 10452 | char_cptr base() const exprtk_override 10453 | { 10454 | return &(*value_)[0]; 10455 | } 10456 | 10457 | std::size_t size() const exprtk_override 10458 | { 10459 | return ref().size(); 10460 | } 10461 | 10462 | inline range_t range() const 10463 | { 10464 | return rp_; 10465 | } 10466 | 10467 | inline std::string& ref() 10468 | { 10469 | return (*value_); 10470 | } 10471 | 10472 | inline const std::string& ref() const 10473 | { 10474 | return (*value_); 10475 | } 10476 | 10477 | inline range_t& range_ref() exprtk_override 10478 | { 10479 | return rp_; 10480 | } 10481 | 10482 | inline const range_t& range_ref() const exprtk_override 10483 | { 10484 | return rp_; 10485 | } 10486 | 10487 | inline typename expression_node<T>::node_type type() const exprtk_override 10488 | { 10489 | return expression_node<T>::e_stringvarrng; 10490 | } 10491 | 10492 | private: 10493 | 10494 | std::string* value_; 10495 | range_t rp_; 10496 | }; 10497 | 10498 | template <typename T> 10499 | std::string string_range_node<T>::null_value = std::string(""); 10500 | 10501 | template <typename T> 10502 | class const_string_range_node exprtk_final 10503 | : public expression_node <T> 10504 | , public string_base_node<T> 10505 | , public range_interface <T> 10506 | { 10507 | public: 10508 | 10509 | typedef typename range_interface<T>::range_t range_t; 10510 | 10511 | explicit const_string_range_node(const std::string& v, const range_t& rp) 10512 | : value_(v) 10513 | , rp_(rp) 10514 | {} 10515 | 10516 | ~const_string_range_node() exprtk_override 10517 | { 10518 | rp_.free(); 10519 | } 10520 | 10521 | inline T value() const exprtk_override 10522 | { 10523 | return std::numeric_limits<T>::quiet_NaN(); 10524 | } 10525 | 10526 | std::string str() const exprtk_override 10527 | { 10528 | return value_; 10529 | } 10530 | 10531 | char_cptr base() const exprtk_override 10532 | { 10533 | return value_.data(); 10534 | } 10535 | 10536 | std::size_t size() const exprtk_override 10537 | { 10538 | return value_.size(); 10539 | } 10540 | 10541 | range_t range() const 10542 | { 10543 | return rp_; 10544 | } 10545 | 10546 | range_t& range_ref() exprtk_override 10547 | { 10548 | return rp_; 10549 | } 10550 | 10551 | const range_t& range_ref() const exprtk_override 10552 | { 10553 | return rp_; 10554 | } 10555 | 10556 | inline typename expression_node<T>::node_type type() const exprtk_override 10557 | { 10558 | return expression_node<T>::e_cstringvarrng; 10559 | } 10560 | 10561 | private: 10562 | 10563 | const_string_range_node(const const_string_range_node<T>&) exprtk_delete; 10564 | const_string_range_node<T>& operator=(const const_string_range_node<T>&) exprtk_delete; 10565 | 10566 | const std::string value_; 10567 | range_t rp_; 10568 | }; 10569 | 10570 | template <typename T> 10571 | class generic_string_range_node exprtk_final 10572 | : public expression_node <T> 10573 | , public string_base_node<T> 10574 | , public range_interface <T> 10575 | { 10576 | public: 10577 | 10578 | typedef expression_node <T>* expression_ptr; 10579 | typedef stringvar_node <T>* strvar_node_ptr; 10580 | typedef string_base_node<T>* str_base_ptr; 10581 | typedef typename range_interface<T>::range_t range_t; 10582 | typedef range_t* range_ptr; 10583 | typedef range_interface<T> irange_t; 10584 | typedef irange_t* irange_ptr; 10585 | typedef std::pair<expression_ptr,bool> branch_t; 10586 | typedef typename range_t::size_holder_t size_holder_t; 10587 | 10588 | generic_string_range_node(expression_ptr str_branch, const range_t& brange) 10589 | : initialised_(false) 10590 | , str_base_ptr_ (0) 10591 | , str_range_ptr_(0) 10592 | , base_range_(brange) 10593 | { 10594 | range_.n0_c = std::make_pair<bool,std::size_t>(true,0); 10595 | range_.n1_c = std::make_pair<bool,std::size_t>(true,0); 10596 | range_.cache.first = range_.n0_c.second; 10597 | range_.cache.second = range_.n1_c.second; 10598 | 10599 | construct_branch_pair(branch_, str_branch); 10600 | 10601 | if (is_generally_string_node(branch_.first)) 10602 | { 10603 | str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_.first); 10604 | 10605 | if (0 == str_base_ptr_) 10606 | return; 10607 | 10608 | str_range_ptr_ = dynamic_cast<irange_ptr>(branch_.first); 10609 | 10610 | if (0 == str_range_ptr_) 10611 | return; 10612 | } 10613 | 10614 | initialised_ = (str_base_ptr_ && str_range_ptr_); 10615 | assert(valid()); 10616 | } 10617 | 10618 | ~generic_string_range_node() exprtk_override 10619 | { 10620 | base_range_.free(); 10621 | } 10622 | 10623 | inline T value() const exprtk_override 10624 | { 10625 | branch_.first->value(); 10626 | 10627 | std::size_t str_r0 = 0; 10628 | std::size_t str_r1 = 0; 10629 | 10630 | std::size_t r0 = 0; 10631 | std::size_t r1 = 0; 10632 | 10633 | const range_t& range = str_range_ptr_->range_ref(); 10634 | 10635 | const std::size_t base_str_size = str_base_ptr_->size(); 10636 | 10637 | if ( 10638 | range (str_r0, str_r1, size_holder_t(base_str_size )) && 10639 | base_range_(r0 , r1 , size_holder_t(base_str_size - str_r0)) 10640 | ) 10641 | { 10642 | const std::size_t size = r1 - r0; 10643 | 10644 | range_.n1_c.second = size; 10645 | range_.cache.second = range_.n1_c.second; 10646 | 10647 | value_.assign(str_base_ptr_->base() + str_r0 + r0, size); 10648 | } 10649 | 10650 | return std::numeric_limits<T>::quiet_NaN(); 10651 | } 10652 | 10653 | std::string str() const exprtk_override 10654 | { 10655 | return value_; 10656 | } 10657 | 10658 | char_cptr base() const exprtk_override 10659 | { 10660 | return &value_[0]; 10661 | } 10662 | 10663 | std::size_t size() const exprtk_override 10664 | { 10665 | return value_.size(); 10666 | } 10667 | 10668 | range_t& range_ref() exprtk_override 10669 | { 10670 | return range_; 10671 | } 10672 | 10673 | const range_t& range_ref() const exprtk_override 10674 | { 10675 | return range_; 10676 | } 10677 | 10678 | inline typename expression_node<T>::node_type type() const exprtk_override 10679 | { 10680 | return expression_node<T>::e_strgenrange; 10681 | } 10682 | 10683 | inline bool valid() const exprtk_override 10684 | { 10685 | return initialised_ && branch_.first; 10686 | } 10687 | 10688 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 10689 | { 10690 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 10691 | } 10692 | 10693 | std::size_t node_depth() const exprtk_override 10694 | { 10695 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 10696 | } 10697 | 10698 | private: 10699 | 10700 | bool initialised_; 10701 | branch_t branch_; 10702 | str_base_ptr str_base_ptr_; 10703 | irange_ptr str_range_ptr_; 10704 | mutable range_t base_range_; 10705 | mutable range_t range_; 10706 | mutable std::string value_; 10707 | }; 10708 | 10709 | template <typename T> 10710 | class string_concat_node exprtk_final 10711 | : public binary_node <T> 10712 | , public string_base_node<T> 10713 | , public range_interface <T> 10714 | { 10715 | public: 10716 | 10717 | typedef typename range_interface<T>::range_t range_t; 10718 | typedef range_interface<T> irange_t; 10719 | typedef irange_t* irange_ptr; 10720 | typedef range_t* range_ptr; 10721 | typedef expression_node <T>* expression_ptr; 10722 | typedef string_base_node<T>* str_base_ptr; 10723 | 10724 | using binary_node<T>::branch; 10725 | 10726 | string_concat_node(const operator_type& opr, 10727 | expression_ptr branch0, 10728 | expression_ptr branch1) 10729 | : binary_node<T>(opr, branch0, branch1) 10730 | , initialised_(false) 10731 | , str0_base_ptr_ (0) 10732 | , str1_base_ptr_ (0) 10733 | , str0_range_ptr_(0) 10734 | , str1_range_ptr_(0) 10735 | { 10736 | range_.n0_c = std::make_pair<bool,std::size_t>(true,0); 10737 | range_.n1_c = std::make_pair<bool,std::size_t>(true,0); 10738 | 10739 | range_.cache.first = range_.n0_c.second; 10740 | range_.cache.second = range_.n1_c.second; 10741 | 10742 | if (is_generally_string_node(branch(0))) 10743 | { 10744 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0)); 10745 | 10746 | if (0 == str0_base_ptr_) 10747 | return; 10748 | 10749 | str0_range_ptr_ = dynamic_cast<irange_ptr>(branch(0)); 10750 | 10751 | if (0 == str0_range_ptr_) 10752 | return; 10753 | } 10754 | 10755 | if (is_generally_string_node(branch(1))) 10756 | { 10757 | str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1)); 10758 | 10759 | if (0 == str1_base_ptr_) 10760 | return; 10761 | 10762 | str1_range_ptr_ = dynamic_cast<irange_ptr>(branch(1)); 10763 | 10764 | if (0 == str1_range_ptr_) 10765 | return; 10766 | } 10767 | 10768 | initialised_ = str0_base_ptr_ && 10769 | str1_base_ptr_ && 10770 | str0_range_ptr_ && 10771 | str1_range_ptr_ ; 10772 | 10773 | assert(valid()); 10774 | } 10775 | 10776 | inline T value() const exprtk_override 10777 | { 10778 | branch(0)->value(); 10779 | branch(1)->value(); 10780 | 10781 | std::size_t str0_r0 = 0; 10782 | std::size_t str0_r1 = 0; 10783 | 10784 | std::size_t str1_r0 = 0; 10785 | std::size_t str1_r1 = 0; 10786 | 10787 | const range_t& range0 = str0_range_ptr_->range_ref(); 10788 | const range_t& range1 = str1_range_ptr_->range_ref(); 10789 | 10790 | if ( 10791 | range0(str0_r0, str0_r1, *str0_base_ptr_) && 10792 | range1(str1_r0, str1_r1, *str1_base_ptr_) 10793 | ) 10794 | { 10795 | const std::size_t size0 = (str0_r1 - str0_r0); 10796 | const std::size_t size1 = (str1_r1 - str1_r0); 10797 | 10798 | value_.assign(str0_base_ptr_->base() + str0_r0, size0); 10799 | value_.append(str1_base_ptr_->base() + str1_r0, size1); 10800 | 10801 | range_.n1_c.second = value_.size(); 10802 | range_.cache.second = range_.n1_c.second; 10803 | } 10804 | 10805 | return std::numeric_limits<T>::quiet_NaN(); 10806 | } 10807 | 10808 | std::string str() const exprtk_override 10809 | { 10810 | return value_; 10811 | } 10812 | 10813 | char_cptr base() const exprtk_override 10814 | { 10815 | return &value_[0]; 10816 | } 10817 | 10818 | std::size_t size() const exprtk_override 10819 | { 10820 | return value_.size(); 10821 | } 10822 | 10823 | range_t& range_ref() exprtk_override 10824 | { 10825 | return range_; 10826 | } 10827 | 10828 | const range_t& range_ref() const exprtk_override 10829 | { 10830 | return range_; 10831 | } 10832 | 10833 | inline typename expression_node<T>::node_type type() const exprtk_override 10834 | { 10835 | return expression_node<T>::e_strconcat; 10836 | } 10837 | 10838 | inline bool valid() const exprtk_override 10839 | { 10840 | return initialised_ && binary_node<T>::valid(); 10841 | } 10842 | 10843 | private: 10844 | 10845 | bool initialised_; 10846 | str_base_ptr str0_base_ptr_; 10847 | str_base_ptr str1_base_ptr_; 10848 | irange_ptr str0_range_ptr_; 10849 | irange_ptr str1_range_ptr_; 10850 | mutable range_t range_; 10851 | mutable std::string value_; 10852 | }; 10853 | 10854 | template <typename T> 10855 | class swap_string_node exprtk_final 10856 | : public binary_node <T> 10857 | , public string_base_node<T> 10858 | , public range_interface <T> 10859 | { 10860 | public: 10861 | 10862 | typedef typename range_interface<T>::range_t range_t; 10863 | typedef range_t* range_ptr; 10864 | typedef range_interface<T> irange_t; 10865 | typedef irange_t* irange_ptr; 10866 | typedef expression_node <T>* expression_ptr; 10867 | typedef stringvar_node <T>* strvar_node_ptr; 10868 | typedef string_base_node<T>* str_base_ptr; 10869 | 10870 | using binary_node<T>::branch; 10871 | 10872 | swap_string_node(expression_ptr branch0, expression_ptr branch1) 10873 | : binary_node<T>(details::e_swap, branch0, branch1) 10874 | , initialised_(false) 10875 | , str0_node_ptr_(0) 10876 | , str1_node_ptr_(0) 10877 | { 10878 | if (is_string_node(branch(0))) 10879 | { 10880 | str0_node_ptr_ = static_cast<strvar_node_ptr>(branch(0)); 10881 | } 10882 | 10883 | if (is_string_node(branch(1))) 10884 | { 10885 | str1_node_ptr_ = static_cast<strvar_node_ptr>(branch(1)); 10886 | } 10887 | 10888 | initialised_ = (str0_node_ptr_ && str1_node_ptr_); 10889 | assert(valid()); 10890 | } 10891 | 10892 | inline T value() const exprtk_override 10893 | { 10894 | branch(0)->value(); 10895 | branch(1)->value(); 10896 | 10897 | std::swap(str0_node_ptr_->ref(), str1_node_ptr_->ref()); 10898 | 10899 | return std::numeric_limits<T>::quiet_NaN(); 10900 | } 10901 | 10902 | std::string str() const exprtk_override 10903 | { 10904 | return str0_node_ptr_->str(); 10905 | } 10906 | 10907 | char_cptr base() const exprtk_override 10908 | { 10909 | return str0_node_ptr_->base(); 10910 | } 10911 | 10912 | std::size_t size() const exprtk_override 10913 | { 10914 | return str0_node_ptr_->size(); 10915 | } 10916 | 10917 | range_t& range_ref() exprtk_override 10918 | { 10919 | return str0_node_ptr_->range_ref(); 10920 | } 10921 | 10922 | const range_t& range_ref() const exprtk_override 10923 | { 10924 | return str0_node_ptr_->range_ref(); 10925 | } 10926 | 10927 | inline typename expression_node<T>::node_type type() const exprtk_override 10928 | { 10929 | return expression_node<T>::e_strswap; 10930 | } 10931 | 10932 | inline bool valid() const exprtk_override 10933 | { 10934 | return initialised_ && binary_node<T>::valid(); 10935 | } 10936 | 10937 | private: 10938 | 10939 | bool initialised_; 10940 | strvar_node_ptr str0_node_ptr_; 10941 | strvar_node_ptr str1_node_ptr_; 10942 | }; 10943 | 10944 | template <typename T> 10945 | class swap_genstrings_node exprtk_final : public binary_node<T> 10946 | { 10947 | public: 10948 | 10949 | typedef typename range_interface<T>::range_t range_t; 10950 | typedef range_t* range_ptr; 10951 | typedef range_interface<T> irange_t; 10952 | typedef irange_t* irange_ptr; 10953 | typedef expression_node <T>* expression_ptr; 10954 | typedef string_base_node<T>* str_base_ptr; 10955 | 10956 | using binary_node<T>::branch; 10957 | 10958 | swap_genstrings_node(expression_ptr branch0, 10959 | expression_ptr branch1) 10960 | : binary_node<T>(details::e_default, branch0, branch1) 10961 | , str0_base_ptr_ (0) 10962 | , str1_base_ptr_ (0) 10963 | , str0_range_ptr_(0) 10964 | , str1_range_ptr_(0) 10965 | , initialised_(false) 10966 | { 10967 | if (is_generally_string_node(branch(0))) 10968 | { 10969 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0)); 10970 | 10971 | if (0 == str0_base_ptr_) 10972 | return; 10973 | 10974 | irange_ptr range = dynamic_cast<irange_ptr>(branch(0)); 10975 | 10976 | if (0 == range) 10977 | return; 10978 | 10979 | str0_range_ptr_ = &(range->range_ref()); 10980 | } 10981 | 10982 | if (is_generally_string_node(branch(1))) 10983 | { 10984 | str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1)); 10985 | 10986 | if (0 == str1_base_ptr_) 10987 | return; 10988 | 10989 | irange_ptr range = dynamic_cast<irange_ptr>(branch(1)); 10990 | 10991 | if (0 == range) 10992 | return; 10993 | 10994 | str1_range_ptr_ = &(range->range_ref()); 10995 | } 10996 | 10997 | initialised_ = str0_base_ptr_ && 10998 | str1_base_ptr_ && 10999 | str0_range_ptr_ && 11000 | str1_range_ptr_ ; 11001 | 11002 | assert(valid()); 11003 | } 11004 | 11005 | inline T value() const exprtk_override 11006 | { 11007 | branch(0)->value(); 11008 | branch(1)->value(); 11009 | 11010 | std::size_t str0_r0 = 0; 11011 | std::size_t str0_r1 = 0; 11012 | 11013 | std::size_t str1_r0 = 0; 11014 | std::size_t str1_r1 = 0; 11015 | 11016 | const range_t& range0 = (*str0_range_ptr_); 11017 | const range_t& range1 = (*str1_range_ptr_); 11018 | 11019 | if ( 11020 | range0(str0_r0, str0_r1, *str0_base_ptr_) && 11021 | range1(str1_r0, str1_r1, *str1_base_ptr_) 11022 | ) 11023 | { 11024 | const std::size_t size0 = range0.cache_size(); 11025 | const std::size_t size1 = range1.cache_size(); 11026 | const std::size_t max_size = std::min(size0,size1); 11027 | 11028 | char_ptr s0 = const_cast<char_ptr>(str0_base_ptr_->base() + str0_r0); 11029 | char_ptr s1 = const_cast<char_ptr>(str1_base_ptr_->base() + str1_r0); 11030 | 11031 | loop_unroll::details lud(max_size); 11032 | char_cptr upper_bound = s0 + lud.upper_bound; 11033 | 11034 | while (s0 < upper_bound) 11035 | { 11036 | #define exprtk_loop(N) \ 11037 | std::swap(s0[N], s1[N]); \ 11038 | 11039 | exprtk_loop( 0) exprtk_loop( 1) 11040 | exprtk_loop( 2) exprtk_loop( 3) 11041 | #ifndef exprtk_disable_superscalar_unroll 11042 | exprtk_loop( 4) exprtk_loop( 5) 11043 | exprtk_loop( 6) exprtk_loop( 7) 11044 | exprtk_loop( 8) exprtk_loop( 9) 11045 | exprtk_loop(10) exprtk_loop(11) 11046 | exprtk_loop(12) exprtk_loop(13) 11047 | exprtk_loop(14) exprtk_loop(15) 11048 | #endif 11049 | 11050 | s0 += lud.batch_size; 11051 | s1 += lud.batch_size; 11052 | } 11053 | 11054 | int i = 0; 11055 | 11056 | switch (lud.remainder) 11057 | { 11058 | #define case_stmt(N) \ 11059 | case N : { std::swap(s0[i], s1[i]); ++i; } \ 11060 | exprtk_fallthrough \ 11061 | 11062 | #ifndef exprtk_disable_superscalar_unroll 11063 | case_stmt(15) case_stmt(14) 11064 | case_stmt(13) case_stmt(12) 11065 | case_stmt(11) case_stmt(10) 11066 | case_stmt( 9) case_stmt( 8) 11067 | case_stmt( 7) case_stmt( 6) 11068 | case_stmt( 5) case_stmt( 4) 11069 | #endif 11070 | case_stmt( 3) case_stmt( 2) 11071 | case_stmt( 1) 11072 | default: break; 11073 | } 11074 | 11075 | #undef exprtk_loop 11076 | #undef case_stmt 11077 | } 11078 | 11079 | return std::numeric_limits<T>::quiet_NaN(); 11080 | } 11081 | 11082 | inline typename expression_node<T>::node_type type() const exprtk_override 11083 | { 11084 | return expression_node<T>::e_strswap; 11085 | } 11086 | 11087 | inline bool valid() const exprtk_override 11088 | { 11089 | return initialised_ && binary_node<T>::valid(); 11090 | } 11091 | 11092 | private: 11093 | 11094 | swap_genstrings_node(const swap_genstrings_node<T>&) exprtk_delete; 11095 | swap_genstrings_node<T>& operator=(const swap_genstrings_node<T>&) exprtk_delete; 11096 | 11097 | str_base_ptr str0_base_ptr_; 11098 | str_base_ptr str1_base_ptr_; 11099 | range_ptr str0_range_ptr_; 11100 | range_ptr str1_range_ptr_; 11101 | bool initialised_; 11102 | }; 11103 | 11104 | template <typename T> 11105 | class stringvar_size_node exprtk_final : public expression_node<T> 11106 | { 11107 | public: 11108 | 11109 | static const std::string null_value; 11110 | 11111 | explicit stringvar_size_node() 11112 | : value_(&null_value) 11113 | {} 11114 | 11115 | explicit stringvar_size_node(std::string& v) 11116 | : value_(&v) 11117 | {} 11118 | 11119 | inline T value() const exprtk_override 11120 | { 11121 | return T((*value_).size()); 11122 | } 11123 | 11124 | inline typename expression_node<T>::node_type type() const exprtk_override 11125 | { 11126 | return expression_node<T>::e_stringvarsize; 11127 | } 11128 | 11129 | private: 11130 | 11131 | const std::string* value_; 11132 | }; 11133 | 11134 | template <typename T> 11135 | const std::string stringvar_size_node<T>::null_value = std::string(""); 11136 | 11137 | template <typename T> 11138 | class string_size_node exprtk_final : public expression_node<T> 11139 | { 11140 | public: 11141 | 11142 | typedef expression_node <T>* expression_ptr; 11143 | typedef string_base_node<T>* str_base_ptr; 11144 | typedef std::pair<expression_ptr,bool> branch_t; 11145 | 11146 | explicit string_size_node(expression_ptr branch) 11147 | : str_base_ptr_(0) 11148 | { 11149 | construct_branch_pair(branch_, branch); 11150 | 11151 | if (is_generally_string_node(branch_.first)) 11152 | { 11153 | str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_.first); 11154 | } 11155 | 11156 | assert(valid()); 11157 | } 11158 | 11159 | inline T value() const exprtk_override 11160 | { 11161 | branch_.first->value(); 11162 | return T(str_base_ptr_->size()); 11163 | } 11164 | 11165 | inline typename expression_node<T>::node_type type() const exprtk_override 11166 | { 11167 | return expression_node<T>::e_stringsize; 11168 | } 11169 | 11170 | inline bool valid() const exprtk_override 11171 | { 11172 | return str_base_ptr_; 11173 | } 11174 | 11175 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 11176 | { 11177 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 11178 | } 11179 | 11180 | std::size_t node_depth() const exprtk_override 11181 | { 11182 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 11183 | } 11184 | 11185 | private: 11186 | 11187 | branch_t branch_; 11188 | str_base_ptr str_base_ptr_; 11189 | }; 11190 | 11191 | struct asn_assignment 11192 | { 11193 | static inline void execute(std::string& s, char_cptr data, const std::size_t size) 11194 | { s.assign(data,size); } 11195 | }; 11196 | 11197 | struct asn_addassignment 11198 | { 11199 | static inline void execute(std::string& s, char_cptr data, const std::size_t size) 11200 | { s.append(data,size); } 11201 | }; 11202 | 11203 | template <typename T, typename AssignmentProcess = asn_assignment> 11204 | class assignment_string_node exprtk_final 11205 | : public binary_node <T> 11206 | , public string_base_node<T> 11207 | , public range_interface <T> 11208 | { 11209 | public: 11210 | 11211 | typedef typename range_interface<T>::range_t range_t; 11212 | typedef range_t* range_ptr; 11213 | typedef range_interface <T> irange_t; 11214 | typedef irange_t* irange_ptr; 11215 | typedef expression_node <T>* expression_ptr; 11216 | typedef stringvar_node <T>* strvar_node_ptr; 11217 | typedef string_base_node<T>* str_base_ptr; 11218 | 11219 | using binary_node<T>::branch; 11220 | 11221 | assignment_string_node(const operator_type& opr, 11222 | expression_ptr branch0, 11223 | expression_ptr branch1) 11224 | : binary_node<T>(opr, branch0, branch1) 11225 | , initialised_(false) 11226 | , str0_base_ptr_ (0) 11227 | , str1_base_ptr_ (0) 11228 | , str0_node_ptr_ (0) 11229 | , str1_range_ptr_(0) 11230 | { 11231 | if (is_string_node(branch(0))) 11232 | { 11233 | str0_node_ptr_ = static_cast<strvar_node_ptr>(branch(0)); 11234 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0)); 11235 | } 11236 | 11237 | if (is_generally_string_node(branch(1))) 11238 | { 11239 | str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1)); 11240 | 11241 | if (0 == str1_base_ptr_) 11242 | return; 11243 | 11244 | irange_ptr range = dynamic_cast<irange_ptr>(branch(1)); 11245 | 11246 | if (0 == range) 11247 | return; 11248 | 11249 | str1_range_ptr_ = &(range->range_ref()); 11250 | } 11251 | 11252 | initialised_ = str0_base_ptr_ && 11253 | str1_base_ptr_ && 11254 | str0_node_ptr_ && 11255 | str1_range_ptr_ ; 11256 | 11257 | assert(valid()); 11258 | } 11259 | 11260 | inline T value() const exprtk_override 11261 | { 11262 | branch(1)->value(); 11263 | 11264 | std::size_t r0 = 0; 11265 | std::size_t r1 = 0; 11266 | 11267 | const range_t& range = (*str1_range_ptr_); 11268 | 11269 | if (range(r0, r1, *str1_base_ptr_)) 11270 | { 11271 | AssignmentProcess::execute( 11272 | str0_node_ptr_->ref(), 11273 | str1_base_ptr_->base() + r0, (r1 - r0)); 11274 | 11275 | branch(0)->value(); 11276 | } 11277 | 11278 | return std::numeric_limits<T>::quiet_NaN(); 11279 | } 11280 | 11281 | std::string str() const exprtk_override 11282 | { 11283 | return str0_node_ptr_->str(); 11284 | } 11285 | 11286 | char_cptr base() const exprtk_override 11287 | { 11288 | return str0_node_ptr_->base(); 11289 | } 11290 | 11291 | std::size_t size() const exprtk_override 11292 | { 11293 | return str0_node_ptr_->size(); 11294 | } 11295 | 11296 | range_t& range_ref() exprtk_override 11297 | { 11298 | return str0_node_ptr_->range_ref(); 11299 | } 11300 | 11301 | const range_t& range_ref() const exprtk_override 11302 | { 11303 | return str0_node_ptr_->range_ref(); 11304 | } 11305 | 11306 | inline typename expression_node<T>::node_type type() const exprtk_override 11307 | { 11308 | return expression_node<T>::e_strass; 11309 | } 11310 | 11311 | inline bool valid() const exprtk_override 11312 | { 11313 | return initialised_ && binary_node<T>::valid(); 11314 | } 11315 | 11316 | private: 11317 | 11318 | bool initialised_; 11319 | str_base_ptr str0_base_ptr_; 11320 | str_base_ptr str1_base_ptr_; 11321 | strvar_node_ptr str0_node_ptr_; 11322 | range_ptr str1_range_ptr_; 11323 | }; 11324 | 11325 | template <typename T, typename AssignmentProcess = asn_assignment> 11326 | class assignment_string_range_node exprtk_final 11327 | : public binary_node <T> 11328 | , public string_base_node<T> 11329 | , public range_interface <T> 11330 | { 11331 | public: 11332 | 11333 | typedef typename range_interface<T>::range_t range_t; 11334 | typedef range_t* range_ptr; 11335 | typedef range_interface <T> irange_t; 11336 | typedef irange_t* irange_ptr; 11337 | typedef expression_node <T>* expression_ptr; 11338 | typedef stringvar_node <T>* strvar_node_ptr; 11339 | typedef string_range_node<T>* str_rng_node_ptr; 11340 | typedef string_base_node <T>* str_base_ptr; 11341 | 11342 | using binary_node<T>::branch; 11343 | 11344 | assignment_string_range_node(const operator_type& opr, 11345 | expression_ptr branch0, 11346 | expression_ptr branch1) 11347 | : binary_node<T>(opr, branch0, branch1) 11348 | , initialised_(false) 11349 | , str0_base_ptr_ (0) 11350 | , str1_base_ptr_ (0) 11351 | , str0_rng_node_ptr_(0) 11352 | , str0_range_ptr_ (0) 11353 | , str1_range_ptr_ (0) 11354 | { 11355 | if (is_string_range_node(branch(0))) 11356 | { 11357 | str0_rng_node_ptr_ = static_cast<str_rng_node_ptr>(branch(0)); 11358 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0)); 11359 | irange_ptr range = dynamic_cast<irange_ptr>(branch(0)); 11360 | 11361 | if (0 == range) 11362 | return; 11363 | 11364 | str0_range_ptr_ = &(range->range_ref()); 11365 | } 11366 | 11367 | if (is_generally_string_node(branch(1))) 11368 | { 11369 | str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1)); 11370 | 11371 | if (0 == str1_base_ptr_) 11372 | return; 11373 | 11374 | irange_ptr range = dynamic_cast<irange_ptr>(branch(1)); 11375 | 11376 | if (0 == range) 11377 | return; 11378 | 11379 | str1_range_ptr_ = &(range->range_ref()); 11380 | } 11381 | 11382 | initialised_ = str0_base_ptr_ && 11383 | str1_base_ptr_ && 11384 | str0_rng_node_ptr_ && 11385 | str0_range_ptr_ && 11386 | str1_range_ptr_ ; 11387 | 11388 | assert(valid()); 11389 | } 11390 | 11391 | inline T value() const exprtk_override 11392 | { 11393 | branch(0)->value(); 11394 | branch(1)->value(); 11395 | 11396 | std::size_t s0_r0 = 0; 11397 | std::size_t s0_r1 = 0; 11398 | 11399 | std::size_t s1_r0 = 0; 11400 | std::size_t s1_r1 = 0; 11401 | 11402 | const range_t& range0 = (*str0_range_ptr_); 11403 | const range_t& range1 = (*str1_range_ptr_); 11404 | 11405 | if ( 11406 | range0(s0_r0, s0_r1, *str0_base_ptr_) && 11407 | range1(s1_r0, s1_r1, *str1_base_ptr_) 11408 | ) 11409 | { 11410 | const std::size_t size = std::min((s0_r1 - s0_r0), (s1_r1 - s1_r0)); 11411 | 11412 | std::copy( 11413 | str1_base_ptr_->base() + s1_r0, 11414 | str1_base_ptr_->base() + s1_r0 + size, 11415 | const_cast<char_ptr>(base() + s0_r0)); 11416 | } 11417 | 11418 | return std::numeric_limits<T>::quiet_NaN(); 11419 | } 11420 | 11421 | std::string str() const exprtk_override 11422 | { 11423 | return str0_base_ptr_->str(); 11424 | } 11425 | 11426 | char_cptr base() const exprtk_override 11427 | { 11428 | return str0_base_ptr_->base(); 11429 | } 11430 | 11431 | std::size_t size() const exprtk_override 11432 | { 11433 | return str0_base_ptr_->size(); 11434 | } 11435 | 11436 | range_t& range_ref() exprtk_override 11437 | { 11438 | return str0_rng_node_ptr_->range_ref(); 11439 | } 11440 | 11441 | const range_t& range_ref() const exprtk_override 11442 | { 11443 | return str0_rng_node_ptr_->range_ref(); 11444 | } 11445 | 11446 | inline typename expression_node<T>::node_type type() const exprtk_override 11447 | { 11448 | return expression_node<T>::e_strass; 11449 | } 11450 | 11451 | inline bool valid() const exprtk_override 11452 | { 11453 | return initialised_ && binary_node<T>::valid(); 11454 | } 11455 | 11456 | private: 11457 | 11458 | bool initialised_; 11459 | str_base_ptr str0_base_ptr_; 11460 | str_base_ptr str1_base_ptr_; 11461 | str_rng_node_ptr str0_rng_node_ptr_; 11462 | range_ptr str0_range_ptr_; 11463 | range_ptr str1_range_ptr_; 11464 | }; 11465 | 11466 | template <typename T> 11467 | class conditional_string_node exprtk_final 11468 | : public trinary_node <T> 11469 | , public string_base_node<T> 11470 | , public range_interface <T> 11471 | { 11472 | public: 11473 | 11474 | typedef typename range_interface<T>::range_t range_t; 11475 | typedef range_t* range_ptr; 11476 | typedef range_interface <T> irange_t; 11477 | typedef irange_t* irange_ptr; 11478 | typedef expression_node <T>* expression_ptr; 11479 | typedef string_base_node<T>* str_base_ptr; 11480 | 11481 | conditional_string_node(expression_ptr condition, 11482 | expression_ptr consequent, 11483 | expression_ptr alternative) 11484 | : trinary_node<T>(details::e_default, consequent, alternative, condition) 11485 | , initialised_(false) 11486 | , str0_base_ptr_ (0) 11487 | , str1_base_ptr_ (0) 11488 | , str0_range_ptr_(0) 11489 | , str1_range_ptr_(0) 11490 | , condition_ (condition ) 11491 | , consequent_ (consequent ) 11492 | , alternative_(alternative) 11493 | { 11494 | range_.n0_c = std::make_pair<bool,std::size_t>(true,0); 11495 | range_.n1_c = std::make_pair<bool,std::size_t>(true,0); 11496 | 11497 | range_.cache.first = range_.n0_c.second; 11498 | range_.cache.second = range_.n1_c.second; 11499 | 11500 | if (is_generally_string_node(trinary_node<T>::branch_[0].first)) 11501 | { 11502 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(trinary_node<T>::branch_[0].first); 11503 | 11504 | if (0 == str0_base_ptr_) 11505 | return; 11506 | 11507 | str0_range_ptr_ = dynamic_cast<irange_ptr>(trinary_node<T>::branch_[0].first); 11508 | 11509 | if (0 == str0_range_ptr_) 11510 | return; 11511 | } 11512 | 11513 | if (is_generally_string_node(trinary_node<T>::branch_[1].first)) 11514 | { 11515 | str1_base_ptr_ = dynamic_cast<str_base_ptr>(trinary_node<T>::branch_[1].first); 11516 | 11517 | if (0 == str1_base_ptr_) 11518 | return; 11519 | 11520 | str1_range_ptr_ = dynamic_cast<irange_ptr>(trinary_node<T>::branch_[1].first); 11521 | 11522 | if (0 == str1_range_ptr_) 11523 | return; 11524 | } 11525 | 11526 | initialised_ = str0_base_ptr_ && 11527 | str1_base_ptr_ && 11528 | str0_range_ptr_ && 11529 | str1_range_ptr_ ; 11530 | 11531 | assert(valid()); 11532 | } 11533 | 11534 | inline T value() const exprtk_override 11535 | { 11536 | std::size_t r0 = 0; 11537 | std::size_t r1 = 0; 11538 | 11539 | if (is_true(condition_)) 11540 | { 11541 | consequent_->value(); 11542 | 11543 | const range_t& range = str0_range_ptr_->range_ref(); 11544 | 11545 | if (range(r0, r1, *str0_base_ptr_)) 11546 | { 11547 | const std::size_t size = (r1 - r0); 11548 | 11549 | value_.assign(str0_base_ptr_->base() + r0, size); 11550 | 11551 | range_.n1_c.second = value_.size(); 11552 | range_.cache.second = range_.n1_c.second; 11553 | 11554 | return T(1); 11555 | } 11556 | } 11557 | else 11558 | { 11559 | alternative_->value(); 11560 | 11561 | const range_t& range = str1_range_ptr_->range_ref(); 11562 | 11563 | if (range(r0, r1, *str1_base_ptr_)) 11564 | { 11565 | const std::size_t size = (r1 - r0); 11566 | 11567 | value_.assign(str1_base_ptr_->base() + r0, size); 11568 | 11569 | range_.n1_c.second = value_.size(); 11570 | range_.cache.second = range_.n1_c.second; 11571 | 11572 | return T(0); 11573 | } 11574 | } 11575 | 11576 | return std::numeric_limits<T>::quiet_NaN(); 11577 | } 11578 | 11579 | std::string str() const exprtk_override 11580 | { 11581 | return value_; 11582 | } 11583 | 11584 | char_cptr base() const exprtk_override 11585 | { 11586 | return &value_[0]; 11587 | } 11588 | 11589 | std::size_t size() const exprtk_override 11590 | { 11591 | return value_.size(); 11592 | } 11593 | 11594 | range_t& range_ref() exprtk_override 11595 | { 11596 | return range_; 11597 | } 11598 | 11599 | const range_t& range_ref() const exprtk_override 11600 | { 11601 | return range_; 11602 | } 11603 | 11604 | inline typename expression_node<T>::node_type type() const exprtk_override 11605 | { 11606 | return expression_node<T>::e_strcondition; 11607 | } 11608 | 11609 | inline bool valid() const exprtk_override 11610 | { 11611 | return 11612 | initialised_ && 11613 | condition_ && condition_ ->valid() && 11614 | consequent_ && consequent_ ->valid() && 11615 | alternative_&& alternative_->valid() ; 11616 | } 11617 | 11618 | private: 11619 | 11620 | bool initialised_; 11621 | str_base_ptr str0_base_ptr_; 11622 | str_base_ptr str1_base_ptr_; 11623 | irange_ptr str0_range_ptr_; 11624 | irange_ptr str1_range_ptr_; 11625 | mutable range_t range_; 11626 | mutable std::string value_; 11627 | 11628 | expression_ptr condition_; 11629 | expression_ptr consequent_; 11630 | expression_ptr alternative_; 11631 | }; 11632 | 11633 | template <typename T> 11634 | class cons_conditional_str_node exprtk_final 11635 | : public binary_node <T> 11636 | , public string_base_node<T> 11637 | , public range_interface <T> 11638 | { 11639 | public: 11640 | 11641 | typedef typename range_interface<T>::range_t range_t; 11642 | typedef range_t* range_ptr; 11643 | typedef range_interface <T> irange_t; 11644 | typedef irange_t* irange_ptr; 11645 | typedef expression_node <T>* expression_ptr; 11646 | typedef string_base_node<T>* str_base_ptr; 11647 | 11648 | using binary_node<T>::branch; 11649 | 11650 | cons_conditional_str_node(expression_ptr condition, 11651 | expression_ptr consequent) 11652 | : binary_node<T>(details::e_default, consequent, condition) 11653 | , initialised_(false) 11654 | , str0_base_ptr_ (0) 11655 | , str0_range_ptr_(0) 11656 | , condition_ (condition ) 11657 | , consequent_(consequent) 11658 | { 11659 | range_.n0_c = std::make_pair<bool,std::size_t>(true,0); 11660 | range_.n1_c = std::make_pair<bool,std::size_t>(true,0); 11661 | 11662 | range_.cache.first = range_.n0_c.second; 11663 | range_.cache.second = range_.n1_c.second; 11664 | 11665 | if (is_generally_string_node(branch(0))) 11666 | { 11667 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0)); 11668 | 11669 | if (0 == str0_base_ptr_) 11670 | return; 11671 | 11672 | str0_range_ptr_ = dynamic_cast<irange_ptr>(branch(0)); 11673 | 11674 | if (0 == str0_range_ptr_) 11675 | return; 11676 | } 11677 | 11678 | initialised_ = str0_base_ptr_ && str0_range_ptr_ ; 11679 | assert(valid()); 11680 | } 11681 | 11682 | inline T value() const exprtk_override 11683 | { 11684 | if (is_true(condition_)) 11685 | { 11686 | consequent_->value(); 11687 | 11688 | const range_t& range = str0_range_ptr_->range_ref(); 11689 | 11690 | std::size_t r0 = 0; 11691 | std::size_t r1 = 0; 11692 | 11693 | if (range(r0, r1, str0_base_ptr_->size())) 11694 | { 11695 | const std::size_t size = (r1 - r0); 11696 | 11697 | value_.assign(str0_base_ptr_->base() + r0, size); 11698 | 11699 | range_.n1_c.second = value_.size(); 11700 | range_.cache.second = range_.n1_c.second; 11701 | 11702 | return T(1); 11703 | } 11704 | } 11705 | 11706 | return std::numeric_limits<T>::quiet_NaN(); 11707 | } 11708 | 11709 | std::string str() const exprtk_override 11710 | { 11711 | return value_; 11712 | } 11713 | 11714 | char_cptr base() const exprtk_override 11715 | { 11716 | return &value_[0]; 11717 | } 11718 | 11719 | std::size_t size() const exprtk_override 11720 | { 11721 | return value_.size(); 11722 | } 11723 | 11724 | range_t& range_ref() exprtk_override 11725 | { 11726 | return range_; 11727 | } 11728 | 11729 | const range_t& range_ref() const exprtk_override 11730 | { 11731 | return range_; 11732 | } 11733 | 11734 | inline typename expression_node<T>::node_type type() const exprtk_override 11735 | { 11736 | return expression_node<T>::e_strccondition; 11737 | } 11738 | 11739 | inline bool valid() const exprtk_override 11740 | { 11741 | return 11742 | initialised_ && 11743 | condition_ && condition_ ->valid() && 11744 | consequent_ && consequent_ ->valid() ; 11745 | } 11746 | 11747 | private: 11748 | 11749 | bool initialised_; 11750 | str_base_ptr str0_base_ptr_; 11751 | irange_ptr str0_range_ptr_; 11752 | mutable range_t range_; 11753 | mutable std::string value_; 11754 | 11755 | expression_ptr condition_; 11756 | expression_ptr consequent_; 11757 | }; 11758 | 11759 | template <typename T, typename VarArgFunction> 11760 | class str_vararg_node exprtk_final 11761 | : public expression_node <T> 11762 | , public string_base_node<T> 11763 | , public range_interface <T> 11764 | { 11765 | public: 11766 | 11767 | typedef typename range_interface<T>::range_t range_t; 11768 | typedef range_t* range_ptr; 11769 | typedef range_interface <T> irange_t; 11770 | typedef irange_t* irange_ptr; 11771 | typedef expression_node <T>* expression_ptr; 11772 | typedef string_base_node<T>* str_base_ptr; 11773 | typedef std::pair<expression_ptr,bool> branch_t; 11774 | 11775 | template <typename Allocator, 11776 | template <typename, typename> class Sequence> 11777 | explicit str_vararg_node(const Sequence<expression_ptr,Allocator>& arg_list) 11778 | : initialised_(false) 11779 | , str_base_ptr_ (0) 11780 | , str_range_ptr_(0) 11781 | { 11782 | construct_branch_pair(final_node_, const_cast<expression_ptr>(arg_list.back())); 11783 | 11784 | if (0 == final_node_.first) 11785 | return; 11786 | else if (!is_generally_string_node(final_node_.first)) 11787 | return; 11788 | 11789 | str_base_ptr_ = dynamic_cast<str_base_ptr>(final_node_.first); 11790 | 11791 | if (0 == str_base_ptr_) 11792 | return; 11793 | 11794 | str_range_ptr_ = dynamic_cast<irange_ptr>(final_node_.first); 11795 | 11796 | if (0 == str_range_ptr_) 11797 | return; 11798 | 11799 | if (arg_list.size() > 1) 11800 | { 11801 | const std::size_t arg_list_size = arg_list.size() - 1; 11802 | 11803 | arg_list_.resize(arg_list_size); 11804 | 11805 | for (std::size_t i = 0; i < arg_list_size; ++i) 11806 | { 11807 | if (arg_list[i] && arg_list[i]->valid()) 11808 | { 11809 | construct_branch_pair(arg_list_[i], arg_list[i]); 11810 | } 11811 | else 11812 | { 11813 | arg_list_.clear(); 11814 | return; 11815 | } 11816 | } 11817 | 11818 | initialised_ = true; 11819 | } 11820 | 11821 | initialised_ &= str_base_ptr_ && str_range_ptr_; 11822 | assert(valid()); 11823 | } 11824 | 11825 | inline T value() const exprtk_override 11826 | { 11827 | if (!arg_list_.empty()) 11828 | { 11829 | VarArgFunction::process(arg_list_); 11830 | } 11831 | 11832 | final_node_.first->value(); 11833 | 11834 | return std::numeric_limits<T>::quiet_NaN(); 11835 | } 11836 | 11837 | std::string str() const exprtk_override 11838 | { 11839 | return str_base_ptr_->str(); 11840 | } 11841 | 11842 | char_cptr base() const exprtk_override 11843 | { 11844 | return str_base_ptr_->base(); 11845 | } 11846 | 11847 | std::size_t size() const exprtk_override 11848 | { 11849 | return str_base_ptr_->size(); 11850 | } 11851 | 11852 | range_t& range_ref() exprtk_override 11853 | { 11854 | return str_range_ptr_->range_ref(); 11855 | } 11856 | 11857 | const range_t& range_ref() const exprtk_override 11858 | { 11859 | return str_range_ptr_->range_ref(); 11860 | } 11861 | 11862 | inline typename expression_node<T>::node_type type() const exprtk_override 11863 | { 11864 | return expression_node<T>::e_stringvararg; 11865 | } 11866 | 11867 | inline bool valid() const exprtk_override 11868 | { 11869 | return 11870 | initialised_ && 11871 | final_node_.first && final_node_.first->valid(); 11872 | } 11873 | 11874 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 11875 | { 11876 | expression_node<T>::ndb_t::collect(final_node_ , node_delete_list); 11877 | expression_node<T>::ndb_t::collect(arg_list_ , node_delete_list); 11878 | } 11879 | 11880 | std::size_t node_depth() const exprtk_override 11881 | { 11882 | return std::max( 11883 | expression_node<T>::ndb_t::compute_node_depth(final_node_), 11884 | expression_node<T>::ndb_t::compute_node_depth(arg_list_ )); 11885 | } 11886 | 11887 | private: 11888 | 11889 | bool initialised_; 11890 | branch_t final_node_; 11891 | str_base_ptr str_base_ptr_; 11892 | irange_ptr str_range_ptr_; 11893 | std::vector<branch_t> arg_list_; 11894 | }; 11895 | #endif 11896 | 11897 | template <typename T> 11898 | class assert_node exprtk_final : public expression_node<T> 11899 | { 11900 | public: 11901 | 11902 | typedef expression_node<T>* expression_ptr; 11903 | typedef std::pair<expression_ptr,bool> branch_t; 11904 | typedef string_base_node<T>* str_base_ptr; 11905 | typedef assert_check::assert_context assert_context_t; 11906 | 11907 | assert_node(expression_ptr assert_condition_node, 11908 | expression_ptr assert_message_node, 11909 | assert_check_ptr assert_check, 11910 | const assert_context_t& context) 11911 | : assert_message_str_base_(0) 11912 | , assert_check_(assert_check) 11913 | , context_(context) 11914 | { 11915 | construct_branch_pair(assert_condition_node_, assert_condition_node); 11916 | construct_branch_pair(assert_message_node_ , assert_message_node ); 11917 | 11918 | #ifndef exprtk_disable_string_capabilities 11919 | if ( 11920 | assert_message_node_.first && 11921 | details::is_generally_string_node(assert_message_node_.first) 11922 | ) 11923 | { 11924 | assert_message_str_base_ = dynamic_cast<str_base_ptr>(assert_message_node_.first); 11925 | } 11926 | #endif 11927 | 11928 | assert(valid()); 11929 | } 11930 | 11931 | inline T value() const exprtk_override 11932 | { 11933 | if (details::is_true(assert_condition_node_.first->value())) 11934 | { 11935 | return T(1); 11936 | } 11937 | 11938 | #ifndef exprtk_disable_string_capabilities 11939 | if (assert_message_node_.first) 11940 | { 11941 | assert_message_node_.first->value(); 11942 | assert(assert_message_str_base_); 11943 | context_.message = assert_message_str_base_->str(); 11944 | } 11945 | #endif 11946 | 11947 | assert_check_->handle_assert(context_); 11948 | return T(0); 11949 | } 11950 | 11951 | inline typename expression_node<T>::node_type type() const exprtk_override 11952 | { 11953 | return expression_node<T>::e_assert; 11954 | } 11955 | 11956 | inline bool valid() const exprtk_override 11957 | { 11958 | return ( 11959 | assert_check_ && 11960 | assert_condition_node_.first && 11961 | assert_condition_node_.first->valid() 11962 | ) && 11963 | ( 11964 | (0 == assert_message_node_.first) || 11965 | ( 11966 | assert_message_node_.first && 11967 | assert_message_str_base_ && 11968 | assert_message_node_.first->valid() && 11969 | details::is_generally_string_node(assert_message_node_.first) 11970 | ) 11971 | ); 11972 | } 11973 | 11974 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 11975 | { 11976 | expression_node<T>::ndb_t::collect(assert_condition_node_, node_delete_list); 11977 | expression_node<T>::ndb_t::collect(assert_message_node_ , node_delete_list); 11978 | } 11979 | 11980 | std::size_t node_depth() const exprtk_override 11981 | { 11982 | return expression_node<T>::ndb_t::compute_node_depth 11983 | (assert_condition_node_, assert_message_node_); 11984 | } 11985 | 11986 | private: 11987 | 11988 | branch_t assert_condition_node_; 11989 | branch_t assert_message_node_; 11990 | str_base_ptr assert_message_str_base_; 11991 | assert_check_ptr assert_check_; 11992 | mutable assert_context_t context_; 11993 | }; 11994 | 11995 | template <typename T, std::size_t N> 11996 | inline T axn(const T a, const T x) 11997 | { 11998 | // a*x^n 11999 | return a * exprtk::details::numeric::fast_exp<T,N>::result(x); 12000 | } 12001 | 12002 | template <typename T, std::size_t N> 12003 | inline T axnb(const T a, const T x, const T b) 12004 | { 12005 | // a*x^n+b 12006 | return a * exprtk::details::numeric::fast_exp<T,N>::result(x) + b; 12007 | } 12008 | 12009 | template <typename T> 12010 | struct sf_base 12011 | { 12012 | typedef typename details::functor_t<T>::Type Type; 12013 | typedef typename details::functor_t<T> functor_t; 12014 | typedef typename functor_t::qfunc_t quaternary_functor_t; 12015 | typedef typename functor_t::tfunc_t trinary_functor_t; 12016 | typedef typename functor_t::bfunc_t binary_functor_t; 12017 | typedef typename functor_t::ufunc_t unary_functor_t; 12018 | }; 12019 | 12020 | #define define_sfop3(NN, OP0, OP1) \ 12021 | template <typename T> \ 12022 | struct sf##NN##_op : public sf_base<T> \ 12023 | { \ 12024 | typedef typename sf_base<T>::Type const Type; \ 12025 | static inline T process(Type x, Type y, Type z) \ 12026 | { \ 12027 | return (OP0); \ 12028 | } \ 12029 | static inline std::string id() \ 12030 | { \ 12031 | return (OP1); \ 12032 | } \ 12033 | }; \ 12034 | 12035 | define_sfop3(00,(x + y) / z ,"(t+t)/t") 12036 | define_sfop3(01,(x + y) * z ,"(t+t)*t") 12037 | define_sfop3(02,(x + y) - z ,"(t+t)-t") 12038 | define_sfop3(03,(x + y) + z ,"(t+t)+t") 12039 | define_sfop3(04,(x - y) + z ,"(t-t)+t") 12040 | define_sfop3(05,(x - y) / z ,"(t-t)/t") 12041 | define_sfop3(06,(x - y) * z ,"(t-t)*t") 12042 | define_sfop3(07,(x * y) + z ,"(t*t)+t") 12043 | define_sfop3(08,(x * y) - z ,"(t*t)-t") 12044 | define_sfop3(09,(x * y) / z ,"(t*t)/t") 12045 | define_sfop3(10,(x * y) * z ,"(t*t)*t") 12046 | define_sfop3(11,(x / y) + z ,"(t/t)+t") 12047 | define_sfop3(12,(x / y) - z ,"(t/t)-t") 12048 | define_sfop3(13,(x / y) / z ,"(t/t)/t") 12049 | define_sfop3(14,(x / y) * z ,"(t/t)*t") 12050 | define_sfop3(15,x / (y + z) ,"t/(t+t)") 12051 | define_sfop3(16,x / (y - z) ,"t/(t-t)") 12052 | define_sfop3(17,x / (y * z) ,"t/(t*t)") 12053 | define_sfop3(18,x / (y / z) ,"t/(t/t)") 12054 | define_sfop3(19,x * (y + z) ,"t*(t+t)") 12055 | define_sfop3(20,x * (y - z) ,"t*(t-t)") 12056 | define_sfop3(21,x * (y * z) ,"t*(t*t)") 12057 | define_sfop3(22,x * (y / z) ,"t*(t/t)") 12058 | define_sfop3(23,x - (y + z) ,"t-(t+t)") 12059 | define_sfop3(24,x - (y - z) ,"t-(t-t)") 12060 | define_sfop3(25,x - (y / z) ,"t-(t/t)") 12061 | define_sfop3(26,x - (y * z) ,"t-(t*t)") 12062 | define_sfop3(27,x + (y * z) ,"t+(t*t)") 12063 | define_sfop3(28,x + (y / z) ,"t+(t/t)") 12064 | define_sfop3(29,x + (y + z) ,"t+(t+t)") 12065 | define_sfop3(30,x + (y - z) ,"t+(t-t)") 12066 | define_sfop3(31,(axnb<T,2>(x,y,z))," ") 12067 | define_sfop3(32,(axnb<T,3>(x,y,z))," ") 12068 | define_sfop3(33,(axnb<T,4>(x,y,z))," ") 12069 | define_sfop3(34,(axnb<T,5>(x,y,z))," ") 12070 | define_sfop3(35,(axnb<T,6>(x,y,z))," ") 12071 | define_sfop3(36,(axnb<T,7>(x,y,z))," ") 12072 | define_sfop3(37,(axnb<T,8>(x,y,z))," ") 12073 | define_sfop3(38,(axnb<T,9>(x,y,z))," ") 12074 | define_sfop3(39,x * numeric::log(y) + z,"") 12075 | define_sfop3(40,x * numeric::log(y) - z,"") 12076 | define_sfop3(41,x * numeric::log10(y) + z,"") 12077 | define_sfop3(42,x * numeric::log10(y) - z,"") 12078 | define_sfop3(43,x * numeric::sin(y) + z ,"") 12079 | define_sfop3(44,x * numeric::sin(y) - z ,"") 12080 | define_sfop3(45,x * numeric::cos(y) + z ,"") 12081 | define_sfop3(46,x * numeric::cos(y) - z ,"") 12082 | define_sfop3(47,details::is_true(x) ? y : z,"") 12083 | 12084 | #define define_sfop4(NN, OP0, OP1) \ 12085 | template <typename T> \ 12086 | struct sf##NN##_op : public sf_base<T> \ 12087 | { \ 12088 | typedef typename sf_base<T>::Type const Type; \ 12089 | static inline T process(Type x, Type y, Type z, Type w) \ 12090 | { \ 12091 | return (OP0); \ 12092 | } \ 12093 | static inline std::string id() \ 12094 | { \ 12095 | return (OP1); \ 12096 | } \ 12097 | }; \ 12098 | 12099 | define_sfop4(48,(x + ((y + z) / w)),"t+((t+t)/t)") 12100 | define_sfop4(49,(x + ((y + z) * w)),"t+((t+t)*t)") 12101 | define_sfop4(50,(x + ((y - z) / w)),"t+((t-t)/t)") 12102 | define_sfop4(51,(x + ((y - z) * w)),"t+((t-t)*t)") 12103 | define_sfop4(52,(x + ((y * z) / w)),"t+((t*t)/t)") 12104 | define_sfop4(53,(x + ((y * z) * w)),"t+((t*t)*t)") 12105 | define_sfop4(54,(x + ((y / z) + w)),"t+((t/t)+t)") 12106 | define_sfop4(55,(x + ((y / z) / w)),"t+((t/t)/t)") 12107 | define_sfop4(56,(x + ((y / z) * w)),"t+((t/t)*t)") 12108 | define_sfop4(57,(x - ((y + z) / w)),"t-((t+t)/t)") 12109 | define_sfop4(58,(x - ((y + z) * w)),"t-((t+t)*t)") 12110 | define_sfop4(59,(x - ((y - z) / w)),"t-((t-t)/t)") 12111 | define_sfop4(60,(x - ((y - z) * w)),"t-((t-t)*t)") 12112 | define_sfop4(61,(x - ((y * z) / w)),"t-((t*t)/t)") 12113 | define_sfop4(62,(x - ((y * z) * w)),"t-((t*t)*t)") 12114 | define_sfop4(63,(x - ((y / z) / w)),"t-((t/t)/t)") 12115 | define_sfop4(64,(x - ((y / z) * w)),"t-((t/t)*t)") 12116 | define_sfop4(65,(((x + y) * z) - w),"((t+t)*t)-t") 12117 | define_sfop4(66,(((x - y) * z) - w),"((t-t)*t)-t") 12118 | define_sfop4(67,(((x * y) * z) - w),"((t*t)*t)-t") 12119 | define_sfop4(68,(((x / y) * z) - w),"((t/t)*t)-t") 12120 | define_sfop4(69,(((x + y) / z) - w),"((t+t)/t)-t") 12121 | define_sfop4(70,(((x - y) / z) - w),"((t-t)/t)-t") 12122 | define_sfop4(71,(((x * y) / z) - w),"((t*t)/t)-t") 12123 | define_sfop4(72,(((x / y) / z) - w),"((t/t)/t)-t") 12124 | define_sfop4(73,((x * y) + (z * w)),"(t*t)+(t*t)") 12125 | define_sfop4(74,((x * y) - (z * w)),"(t*t)-(t*t)") 12126 | define_sfop4(75,((x * y) + (z / w)),"(t*t)+(t/t)") 12127 | define_sfop4(76,((x * y) - (z / w)),"(t*t)-(t/t)") 12128 | define_sfop4(77,((x / y) + (z / w)),"(t/t)+(t/t)") 12129 | define_sfop4(78,((x / y) - (z / w)),"(t/t)-(t/t)") 12130 | define_sfop4(79,((x / y) - (z * w)),"(t/t)-(t*t)") 12131 | define_sfop4(80,(x / (y + (z * w))),"t/(t+(t*t))") 12132 | define_sfop4(81,(x / (y - (z * w))),"t/(t-(t*t))") 12133 | define_sfop4(82,(x * (y + (z * w))),"t*(t+(t*t))") 12134 | define_sfop4(83,(x * (y - (z * w))),"t*(t-(t*t))") 12135 | 12136 | define_sfop4(84,(axn<T,2>(x,y) + axn<T,2>(z,w)),"") 12137 | define_sfop4(85,(axn<T,3>(x,y) + axn<T,3>(z,w)),"") 12138 | define_sfop4(86,(axn<T,4>(x,y) + axn<T,4>(z,w)),"") 12139 | define_sfop4(87,(axn<T,5>(x,y) + axn<T,5>(z,w)),"") 12140 | define_sfop4(88,(axn<T,6>(x,y) + axn<T,6>(z,w)),"") 12141 | define_sfop4(89,(axn<T,7>(x,y) + axn<T,7>(z,w)),"") 12142 | define_sfop4(90,(axn<T,8>(x,y) + axn<T,8>(z,w)),"") 12143 | define_sfop4(91,(axn<T,9>(x,y) + axn<T,9>(z,w)),"") 12144 | define_sfop4(92,((details::is_true(x) && details::is_true(y)) ? z : w),"") 12145 | define_sfop4(93,((details::is_true(x) || details::is_true(y)) ? z : w),"") 12146 | define_sfop4(94,((x < y) ? z : w),"") 12147 | define_sfop4(95,((x <= y) ? z : w),"") 12148 | define_sfop4(96,((x > y) ? z : w),"") 12149 | define_sfop4(97,((x >= y) ? z : w),"") 12150 | define_sfop4(98,(details::is_true(numeric::equal(x,y)) ? z : w),"") 12151 | define_sfop4(99,(x * numeric::sin(y) + z * numeric::cos(w)),"") 12152 | 12153 | define_sfop4(ext00,((x + y) - (z * w)),"(t+t)-(t*t)") 12154 | define_sfop4(ext01,((x + y) - (z / w)),"(t+t)-(t/t)") 12155 | define_sfop4(ext02,((x + y) + (z * w)),"(t+t)+(t*t)") 12156 | define_sfop4(ext03,((x + y) + (z / w)),"(t+t)+(t/t)") 12157 | define_sfop4(ext04,((x - y) + (z * w)),"(t-t)+(t*t)") 12158 | define_sfop4(ext05,((x - y) + (z / w)),"(t-t)+(t/t)") 12159 | define_sfop4(ext06,((x - y) - (z * w)),"(t-t)-(t*t)") 12160 | define_sfop4(ext07,((x - y) - (z / w)),"(t-t)-(t/t)") 12161 | define_sfop4(ext08,((x + y) - (z - w)),"(t+t)-(t-t)") 12162 | define_sfop4(ext09,((x + y) + (z - w)),"(t+t)+(t-t)") 12163 | define_sfop4(ext10,((x + y) + (z + w)),"(t+t)+(t+t)") 12164 | define_sfop4(ext11,((x + y) * (z - w)),"(t+t)*(t-t)") 12165 | define_sfop4(ext12,((x + y) / (z - w)),"(t+t)/(t-t)") 12166 | define_sfop4(ext13,((x - y) - (z + w)),"(t-t)-(t+t)") 12167 | define_sfop4(ext14,((x - y) + (z + w)),"(t-t)+(t+t)") 12168 | define_sfop4(ext15,((x - y) * (z + w)),"(t-t)*(t+t)") 12169 | define_sfop4(ext16,((x - y) / (z + w)),"(t-t)/(t+t)") 12170 | define_sfop4(ext17,((x * y) - (z + w)),"(t*t)-(t+t)") 12171 | define_sfop4(ext18,((x / y) - (z + w)),"(t/t)-(t+t)") 12172 | define_sfop4(ext19,((x * y) + (z + w)),"(t*t)+(t+t)") 12173 | define_sfop4(ext20,((x / y) + (z + w)),"(t/t)+(t+t)") 12174 | define_sfop4(ext21,((x * y) + (z - w)),"(t*t)+(t-t)") 12175 | define_sfop4(ext22,((x / y) + (z - w)),"(t/t)+(t-t)") 12176 | define_sfop4(ext23,((x * y) - (z - w)),"(t*t)-(t-t)") 12177 | define_sfop4(ext24,((x / y) - (z - w)),"(t/t)-(t-t)") 12178 | define_sfop4(ext25,((x + y) * (z * w)),"(t+t)*(t*t)") 12179 | define_sfop4(ext26,((x + y) * (z / w)),"(t+t)*(t/t)") 12180 | define_sfop4(ext27,((x + y) / (z * w)),"(t+t)/(t*t)") 12181 | define_sfop4(ext28,((x + y) / (z / w)),"(t+t)/(t/t)") 12182 | define_sfop4(ext29,((x - y) / (z * w)),"(t-t)/(t*t)") 12183 | define_sfop4(ext30,((x - y) / (z / w)),"(t-t)/(t/t)") 12184 | define_sfop4(ext31,((x - y) * (z * w)),"(t-t)*(t*t)") 12185 | define_sfop4(ext32,((x - y) * (z / w)),"(t-t)*(t/t)") 12186 | define_sfop4(ext33,((x * y) * (z + w)),"(t*t)*(t+t)") 12187 | define_sfop4(ext34,((x / y) * (z + w)),"(t/t)*(t+t)") 12188 | define_sfop4(ext35,((x * y) / (z + w)),"(t*t)/(t+t)") 12189 | define_sfop4(ext36,((x / y) / (z + w)),"(t/t)/(t+t)") 12190 | define_sfop4(ext37,((x * y) / (z - w)),"(t*t)/(t-t)") 12191 | define_sfop4(ext38,((x / y) / (z - w)),"(t/t)/(t-t)") 12192 | define_sfop4(ext39,((x * y) * (z - w)),"(t*t)*(t-t)") 12193 | define_sfop4(ext40,((x * y) / (z * w)),"(t*t)/(t*t)") 12194 | define_sfop4(ext41,((x / y) * (z / w)),"(t/t)*(t/t)") 12195 | define_sfop4(ext42,((x / y) * (z - w)),"(t/t)*(t-t)") 12196 | define_sfop4(ext43,((x * y) * (z * w)),"(t*t)*(t*t)") 12197 | define_sfop4(ext44,(x + (y * (z / w))),"t+(t*(t/t))") 12198 | define_sfop4(ext45,(x - (y * (z / w))),"t-(t*(t/t))") 12199 | define_sfop4(ext46,(x + (y / (z * w))),"t+(t/(t*t))") 12200 | define_sfop4(ext47,(x - (y / (z * w))),"t-(t/(t*t))") 12201 | define_sfop4(ext48,(((x - y) - z) * w),"((t-t)-t)*t") 12202 | define_sfop4(ext49,(((x - y) - z) / w),"((t-t)-t)/t") 12203 | define_sfop4(ext50,(((x - y) + z) * w),"((t-t)+t)*t") 12204 | define_sfop4(ext51,(((x - y) + z) / w),"((t-t)+t)/t") 12205 | define_sfop4(ext52,((x + (y - z)) * w),"(t+(t-t))*t") 12206 | define_sfop4(ext53,((x + (y - z)) / w),"(t+(t-t))/t") 12207 | define_sfop4(ext54,((x + y) / (z + w)),"(t+t)/(t+t)") 12208 | define_sfop4(ext55,((x - y) / (z - w)),"(t-t)/(t-t)") 12209 | define_sfop4(ext56,((x + y) * (z + w)),"(t+t)*(t+t)") 12210 | define_sfop4(ext57,((x - y) * (z - w)),"(t-t)*(t-t)") 12211 | define_sfop4(ext58,((x - y) + (z - w)),"(t-t)+(t-t)") 12212 | define_sfop4(ext59,((x - y) - (z - w)),"(t-t)-(t-t)") 12213 | define_sfop4(ext60,((x / y) + (z * w)),"(t/t)+(t*t)") 12214 | define_sfop4(ext61,(((x * y) * z) / w),"((t*t)*t)/t") 12215 | 12216 | #undef define_sfop3 12217 | #undef define_sfop4 12218 | 12219 | template <typename T, typename SpecialFunction> 12220 | class sf3_node exprtk_final : public trinary_node<T> 12221 | { 12222 | public: 12223 | 12224 | typedef expression_node<T>* expression_ptr; 12225 | 12226 | sf3_node(const operator_type& opr, 12227 | expression_ptr branch0, 12228 | expression_ptr branch1, 12229 | expression_ptr branch2) 12230 | : trinary_node<T>(opr, branch0, branch1, branch2) 12231 | {} 12232 | 12233 | inline T value() const exprtk_override 12234 | { 12235 | const T x = trinary_node<T>::branch_[0].first->value(); 12236 | const T y = trinary_node<T>::branch_[1].first->value(); 12237 | const T z = trinary_node<T>::branch_[2].first->value(); 12238 | 12239 | return SpecialFunction::process(x, y, z); 12240 | } 12241 | }; 12242 | 12243 | template <typename T, typename SpecialFunction> 12244 | class sf4_node exprtk_final : public quaternary_node<T> 12245 | { 12246 | public: 12247 | 12248 | typedef expression_node<T>* expression_ptr; 12249 | 12250 | sf4_node(const operator_type& opr, 12251 | expression_ptr branch0, 12252 | expression_ptr branch1, 12253 | expression_ptr branch2, 12254 | expression_ptr branch3) 12255 | : quaternary_node<T>(opr, branch0, branch1, branch2, branch3) 12256 | {} 12257 | 12258 | inline T value() const exprtk_override 12259 | { 12260 | const T x = quaternary_node<T>::branch_[0].first->value(); 12261 | const T y = quaternary_node<T>::branch_[1].first->value(); 12262 | const T z = quaternary_node<T>::branch_[2].first->value(); 12263 | const T w = quaternary_node<T>::branch_[3].first->value(); 12264 | 12265 | return SpecialFunction::process(x, y, z, w); 12266 | } 12267 | }; 12268 | 12269 | template <typename T, typename SpecialFunction> 12270 | class sf3_var_node exprtk_final : public expression_node<T> 12271 | { 12272 | public: 12273 | 12274 | typedef expression_node<T>* expression_ptr; 12275 | 12276 | sf3_var_node(const T& v0, const T& v1, const T& v2) 12277 | : v0_(v0) 12278 | , v1_(v1) 12279 | , v2_(v2) 12280 | {} 12281 | 12282 | inline T value() const exprtk_override 12283 | { 12284 | return SpecialFunction::process(v0_, v1_, v2_); 12285 | } 12286 | 12287 | inline typename expression_node<T>::node_type type() const exprtk_override 12288 | { 12289 | return expression_node<T>::e_trinary; 12290 | } 12291 | 12292 | private: 12293 | 12294 | sf3_var_node(const sf3_var_node<T,SpecialFunction>&) exprtk_delete; 12295 | sf3_var_node<T,SpecialFunction>& operator=(const sf3_var_node<T,SpecialFunction>&) exprtk_delete; 12296 | 12297 | const T& v0_; 12298 | const T& v1_; 12299 | const T& v2_; 12300 | }; 12301 | 12302 | template <typename T, typename SpecialFunction> 12303 | class sf4_var_node exprtk_final : public expression_node<T> 12304 | { 12305 | public: 12306 | 12307 | typedef expression_node<T>* expression_ptr; 12308 | 12309 | sf4_var_node(const T& v0, const T& v1, const T& v2, const T& v3) 12310 | : v0_(v0) 12311 | , v1_(v1) 12312 | , v2_(v2) 12313 | , v3_(v3) 12314 | {} 12315 | 12316 | inline T value() const exprtk_override 12317 | { 12318 | return SpecialFunction::process(v0_, v1_, v2_, v3_); 12319 | } 12320 | 12321 | inline typename expression_node<T>::node_type type() const exprtk_override 12322 | { 12323 | return expression_node<T>::e_trinary; 12324 | } 12325 | 12326 | private: 12327 | 12328 | sf4_var_node(const sf4_var_node<T,SpecialFunction>&) exprtk_delete; 12329 | sf4_var_node<T,SpecialFunction>& operator=(const sf4_var_node<T,SpecialFunction>&) exprtk_delete; 12330 | 12331 | const T& v0_; 12332 | const T& v1_; 12333 | const T& v2_; 12334 | const T& v3_; 12335 | }; 12336 | 12337 | template <typename T, typename VarArgFunction> 12338 | class vararg_node exprtk_final : public expression_node<T> 12339 | { 12340 | public: 12341 | 12342 | typedef expression_node<T>* expression_ptr; 12343 | typedef std::pair<expression_ptr,bool> branch_t; 12344 | 12345 | template <typename Allocator, 12346 | template <typename, typename> class Sequence> 12347 | explicit vararg_node(const Sequence<expression_ptr,Allocator>& arg_list) 12348 | : initialised_(false) 12349 | { 12350 | arg_list_.resize(arg_list.size()); 12351 | 12352 | for (std::size_t i = 0; i < arg_list.size(); ++i) 12353 | { 12354 | if (arg_list[i] && arg_list[i]->valid()) 12355 | { 12356 | construct_branch_pair(arg_list_[i],arg_list[i]); 12357 | } 12358 | else 12359 | { 12360 | arg_list_.clear(); 12361 | return; 12362 | } 12363 | } 12364 | 12365 | initialised_ = (arg_list_.size() == arg_list.size()); 12366 | assert(valid()); 12367 | } 12368 | 12369 | inline T value() const exprtk_override 12370 | { 12371 | return VarArgFunction::process(arg_list_); 12372 | } 12373 | 12374 | inline typename expression_node<T>::node_type type() const exprtk_override 12375 | { 12376 | return expression_node<T>::e_vararg; 12377 | } 12378 | 12379 | inline bool valid() const exprtk_override 12380 | { 12381 | return initialised_; 12382 | } 12383 | 12384 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 12385 | { 12386 | expression_node<T>::ndb_t::collect(arg_list_, node_delete_list); 12387 | } 12388 | 12389 | std::size_t node_depth() const exprtk_override 12390 | { 12391 | return expression_node<T>::ndb_t::compute_node_depth(arg_list_); 12392 | } 12393 | 12394 | std::size_t size() const 12395 | { 12396 | return arg_list_.size(); 12397 | } 12398 | 12399 | expression_ptr operator[](const std::size_t& index) const 12400 | { 12401 | return arg_list_[index].first; 12402 | } 12403 | 12404 | private: 12405 | 12406 | std::vector<branch_t> arg_list_; 12407 | bool initialised_; 12408 | }; 12409 | 12410 | template <typename T, typename VarArgFunction> 12411 | class vararg_varnode exprtk_final : public expression_node<T> 12412 | { 12413 | public: 12414 | 12415 | typedef expression_node<T>* expression_ptr; 12416 | 12417 | template <typename Allocator, 12418 | template <typename, typename> class Sequence> 12419 | explicit vararg_varnode(const Sequence<expression_ptr,Allocator>& arg_list) 12420 | : initialised_(false) 12421 | { 12422 | arg_list_.resize(arg_list.size()); 12423 | 12424 | for (std::size_t i = 0; i < arg_list.size(); ++i) 12425 | { 12426 | if (arg_list[i] && arg_list[i]->valid() && is_variable_node(arg_list[i])) 12427 | { 12428 | variable_node<T>* var_node_ptr = static_cast<variable_node<T>*>(arg_list[i]); 12429 | arg_list_[i] = (&var_node_ptr->ref()); 12430 | } 12431 | else 12432 | { 12433 | arg_list_.clear(); 12434 | return; 12435 | } 12436 | } 12437 | 12438 | initialised_ = (arg_list.size() == arg_list_.size()); 12439 | assert(valid()); 12440 | } 12441 | 12442 | inline T value() const exprtk_override 12443 | { 12444 | return VarArgFunction::process(arg_list_); 12445 | } 12446 | 12447 | inline typename expression_node<T>::node_type type() const exprtk_override 12448 | { 12449 | return expression_node<T>::e_vararg; 12450 | } 12451 | 12452 | inline bool valid() const exprtk_override 12453 | { 12454 | return initialised_; 12455 | } 12456 | 12457 | private: 12458 | 12459 | std::vector<const T*> arg_list_; 12460 | bool initialised_; 12461 | }; 12462 | 12463 | template <typename T, typename VecFunction> 12464 | class vectorize_node exprtk_final : public expression_node<T> 12465 | { 12466 | public: 12467 | 12468 | typedef expression_node<T>* expression_ptr; 12469 | typedef std::pair<expression_ptr,bool> branch_t; 12470 | 12471 | explicit vectorize_node(const expression_ptr v) 12472 | : ivec_ptr_(0) 12473 | { 12474 | construct_branch_pair(v_, v); 12475 | 12476 | if (is_ivector_node(v_.first)) 12477 | { 12478 | ivec_ptr_ = dynamic_cast<vector_interface<T>*>(v_.first); 12479 | } 12480 | } 12481 | 12482 | inline T value() const exprtk_override 12483 | { 12484 | v_.first->value(); 12485 | return VecFunction::process(ivec_ptr_); 12486 | } 12487 | 12488 | inline typename expression_node<T>::node_type type() const exprtk_override 12489 | { 12490 | return expression_node<T>::e_vecfunc; 12491 | } 12492 | 12493 | inline bool valid() const exprtk_override 12494 | { 12495 | return ivec_ptr_ && v_.first && v_.first->valid(); 12496 | } 12497 | 12498 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 12499 | { 12500 | expression_node<T>::ndb_t::collect(v_, node_delete_list); 12501 | } 12502 | 12503 | std::size_t node_depth() const exprtk_override 12504 | { 12505 | return expression_node<T>::ndb_t::compute_node_depth(v_); 12506 | } 12507 | 12508 | private: 12509 | 12510 | vector_interface<T>* ivec_ptr_; 12511 | branch_t v_; 12512 | }; 12513 | 12514 | template <typename T> 12515 | class assignment_node exprtk_final : public binary_node<T> 12516 | { 12517 | public: 12518 | 12519 | typedef expression_node<T>* expression_ptr; 12520 | using binary_node<T>::branch; 12521 | 12522 | assignment_node(const operator_type& opr, 12523 | expression_ptr branch0, 12524 | expression_ptr branch1) 12525 | : binary_node<T>(opr, branch0, branch1) 12526 | , var_node_ptr_(0) 12527 | { 12528 | if (is_variable_node(branch(0))) 12529 | { 12530 | var_node_ptr_ = static_cast<variable_node<T>*>(branch(0)); 12531 | } 12532 | } 12533 | 12534 | inline T value() const exprtk_override 12535 | { 12536 | T& result = var_node_ptr_->ref(); 12537 | result = branch(1)->value(); 12538 | 12539 | return result; 12540 | } 12541 | 12542 | inline bool valid() const exprtk_override 12543 | { 12544 | return var_node_ptr_ && binary_node<T>::valid(); 12545 | } 12546 | 12547 | private: 12548 | 12549 | variable_node<T>* var_node_ptr_; 12550 | }; 12551 | 12552 | template <typename T> 12553 | class assignment_vec_elem_node exprtk_final : public binary_node<T> 12554 | { 12555 | public: 12556 | 12557 | typedef expression_node<T>* expression_ptr; 12558 | using binary_node<T>::branch; 12559 | 12560 | assignment_vec_elem_node(const operator_type& opr, 12561 | expression_ptr branch0, 12562 | expression_ptr branch1) 12563 | : binary_node<T>(opr, branch0, branch1) 12564 | , vec_node_ptr_(0) 12565 | { 12566 | if (is_vector_elem_node(branch(0))) 12567 | { 12568 | vec_node_ptr_ = static_cast<vector_elem_node<T>*>(branch(0)); 12569 | } 12570 | 12571 | assert(valid()); 12572 | } 12573 | 12574 | inline T value() const exprtk_override 12575 | { 12576 | T& result = vec_node_ptr_->ref(); 12577 | result = branch(1)->value(); 12578 | 12579 | return result; 12580 | } 12581 | 12582 | inline bool valid() const exprtk_override 12583 | { 12584 | return vec_node_ptr_ && binary_node<T>::valid(); 12585 | } 12586 | 12587 | private: 12588 | 12589 | vector_elem_node<T>* vec_node_ptr_; 12590 | }; 12591 | 12592 | template <typename T> 12593 | class assignment_vec_elem_rtc_node exprtk_final : public binary_node<T> 12594 | { 12595 | public: 12596 | 12597 | typedef expression_node<T>* expression_ptr; 12598 | using binary_node<T>::branch; 12599 | 12600 | assignment_vec_elem_rtc_node(const operator_type& opr, 12601 | expression_ptr branch0, 12602 | expression_ptr branch1) 12603 | : binary_node<T>(opr, branch0, branch1) 12604 | , vec_node_ptr_(0) 12605 | { 12606 | if (is_vector_elem_rtc_node(branch(0))) 12607 | { 12608 | vec_node_ptr_ = static_cast<vector_elem_rtc_node<T>*>(branch(0)); 12609 | } 12610 | 12611 | assert(valid()); 12612 | } 12613 | 12614 | inline T value() const exprtk_override 12615 | { 12616 | T& result = vec_node_ptr_->ref(); 12617 | result = branch(1)->value(); 12618 | 12619 | return result; 12620 | } 12621 | 12622 | inline bool valid() const exprtk_override 12623 | { 12624 | return vec_node_ptr_ && binary_node<T>::valid(); 12625 | } 12626 | 12627 | private: 12628 | 12629 | vector_elem_rtc_node<T>* vec_node_ptr_; 12630 | }; 12631 | 12632 | template <typename T> 12633 | class assignment_rebasevec_elem_node exprtk_final : public binary_node<T> 12634 | { 12635 | public: 12636 | 12637 | typedef expression_node<T>* expression_ptr; 12638 | using expression_node<T>::branch; 12639 | 12640 | assignment_rebasevec_elem_node(const operator_type& opr, 12641 | expression_ptr branch0, 12642 | expression_ptr branch1) 12643 | : binary_node<T>(opr, branch0, branch1) 12644 | , rbvec_node_ptr_(0) 12645 | { 12646 | if (is_rebasevector_elem_node(branch(0))) 12647 | { 12648 | rbvec_node_ptr_ = static_cast<rebasevector_elem_node<T>*>(branch(0)); 12649 | } 12650 | 12651 | assert(valid()); 12652 | } 12653 | 12654 | inline T value() const exprtk_override 12655 | { 12656 | T& result = rbvec_node_ptr_->ref(); 12657 | result = branch(1)->value(); 12658 | 12659 | return result; 12660 | } 12661 | 12662 | inline bool valid() const exprtk_override 12663 | { 12664 | return rbvec_node_ptr_ && binary_node<T>::valid(); 12665 | } 12666 | 12667 | private: 12668 | 12669 | rebasevector_elem_node<T>* rbvec_node_ptr_; 12670 | }; 12671 | 12672 | template <typename T> 12673 | class assignment_rebasevec_elem_rtc_node exprtk_final : public binary_node<T> 12674 | { 12675 | public: 12676 | 12677 | typedef expression_node<T>* expression_ptr; 12678 | using expression_node<T>::branch; 12679 | 12680 | assignment_rebasevec_elem_rtc_node(const operator_type& opr, 12681 | expression_ptr branch0, 12682 | expression_ptr branch1) 12683 | : binary_node<T>(opr, branch0, branch1) 12684 | , rbvec_node_ptr_(0) 12685 | { 12686 | if (is_rebasevector_elem_rtc_node(branch(0))) 12687 | { 12688 | rbvec_node_ptr_ = static_cast<rebasevector_elem_rtc_node<T>*>(branch(0)); 12689 | } 12690 | 12691 | assert(valid()); 12692 | } 12693 | 12694 | inline T value() const exprtk_override 12695 | { 12696 | T& result = rbvec_node_ptr_->ref(); 12697 | result = branch(1)->value(); 12698 | 12699 | return result; 12700 | } 12701 | 12702 | inline bool valid() const exprtk_override 12703 | { 12704 | return rbvec_node_ptr_ && binary_node<T>::valid(); 12705 | } 12706 | 12707 | private: 12708 | 12709 | rebasevector_elem_rtc_node<T>* rbvec_node_ptr_; 12710 | }; 12711 | 12712 | template <typename T> 12713 | class assignment_rebasevec_celem_node exprtk_final : public binary_node<T> 12714 | { 12715 | public: 12716 | 12717 | typedef expression_node<T>* expression_ptr; 12718 | using binary_node<T>::branch; 12719 | 12720 | assignment_rebasevec_celem_node(const operator_type& opr, 12721 | expression_ptr branch0, 12722 | expression_ptr branch1) 12723 | : binary_node<T>(opr, branch0, branch1) 12724 | , rbvec_node_ptr_(0) 12725 | { 12726 | if (is_rebasevector_celem_node(branch(0))) 12727 | { 12728 | rbvec_node_ptr_ = static_cast<rebasevector_celem_node<T>*>(branch(0)); 12729 | } 12730 | 12731 | assert(valid()); 12732 | } 12733 | 12734 | inline T value() const exprtk_override 12735 | { 12736 | T& result = rbvec_node_ptr_->ref(); 12737 | result = branch(1)->value(); 12738 | 12739 | return result; 12740 | } 12741 | 12742 | inline bool valid() const exprtk_override 12743 | { 12744 | return rbvec_node_ptr_ && binary_node<T>::valid(); 12745 | } 12746 | 12747 | private: 12748 | 12749 | rebasevector_celem_node<T>* rbvec_node_ptr_; 12750 | }; 12751 | 12752 | template <typename T> 12753 | class assignment_vec_node exprtk_final 12754 | : public binary_node <T> 12755 | , public vector_interface<T> 12756 | { 12757 | public: 12758 | 12759 | typedef expression_node<T>* expression_ptr; 12760 | typedef vector_node<T>* vector_node_ptr; 12761 | typedef vec_data_store<T> vds_t; 12762 | 12763 | using binary_node<T>::branch; 12764 | 12765 | assignment_vec_node(const operator_type& opr, 12766 | expression_ptr branch0, 12767 | expression_ptr branch1) 12768 | : binary_node<T>(opr, branch0, branch1) 12769 | , vec_node_ptr_(0) 12770 | { 12771 | if (is_vector_node(branch(0))) 12772 | { 12773 | vec_node_ptr_ = static_cast<vector_node<T>*>(branch(0)); 12774 | vds() = vec_node_ptr_->vds(); 12775 | } 12776 | 12777 | assert(valid()); 12778 | } 12779 | 12780 | inline T value() const exprtk_override 12781 | { 12782 | const T v = branch(1)->value(); 12783 | 12784 | T* vec = vds().data(); 12785 | 12786 | loop_unroll::details lud(size()); 12787 | const T* upper_bound = vec + lud.upper_bound; 12788 | 12789 | while (vec < upper_bound) 12790 | { 12791 | #define exprtk_loop(N) \ 12792 | vec[N] = v; \ 12793 | 12794 | exprtk_loop( 0) exprtk_loop( 1) 12795 | exprtk_loop( 2) exprtk_loop( 3) 12796 | #ifndef exprtk_disable_superscalar_unroll 12797 | exprtk_loop( 4) exprtk_loop( 5) 12798 | exprtk_loop( 6) exprtk_loop( 7) 12799 | exprtk_loop( 8) exprtk_loop( 9) 12800 | exprtk_loop(10) exprtk_loop(11) 12801 | exprtk_loop(12) exprtk_loop(13) 12802 | exprtk_loop(14) exprtk_loop(15) 12803 | #endif 12804 | 12805 | vec += lud.batch_size; 12806 | } 12807 | 12808 | switch (lud.remainder) 12809 | { 12810 | #define case_stmt(N) \ 12811 | case N : *vec++ = v; \ 12812 | exprtk_fallthrough \ 12813 | 12814 | #ifndef exprtk_disable_superscalar_unroll 12815 | case_stmt(15) case_stmt(14) 12816 | case_stmt(13) case_stmt(12) 12817 | case_stmt(11) case_stmt(10) 12818 | case_stmt( 9) case_stmt( 8) 12819 | case_stmt( 7) case_stmt( 6) 12820 | case_stmt( 5) case_stmt( 4) 12821 | #endif 12822 | case_stmt( 3) case_stmt( 2) 12823 | case 1 : *vec++ = v; 12824 | } 12825 | 12826 | #undef exprtk_loop 12827 | #undef case_stmt 12828 | 12829 | return vec_node_ptr_->value(); 12830 | } 12831 | 12832 | vector_node_ptr vec() const exprtk_override 12833 | { 12834 | return vec_node_ptr_; 12835 | } 12836 | 12837 | vector_node_ptr vec() exprtk_override 12838 | { 12839 | return vec_node_ptr_; 12840 | } 12841 | 12842 | inline typename expression_node<T>::node_type type() const exprtk_override 12843 | { 12844 | return expression_node<T>::e_vecvalass; 12845 | } 12846 | 12847 | inline bool valid() const exprtk_override 12848 | { 12849 | return 12850 | vec_node_ptr_ && 12851 | (vds().size() <= vec_node_ptr_->vec_holder().base_size()) && 12852 | binary_node<T>::valid(); 12853 | } 12854 | 12855 | std::size_t size() const exprtk_override 12856 | { 12857 | return vec_node_ptr_->vec_holder().size(); 12858 | } 12859 | 12860 | std::size_t base_size() const exprtk_override 12861 | { 12862 | return vec_node_ptr_->vec_holder().base_size(); 12863 | } 12864 | 12865 | vds_t& vds() exprtk_override 12866 | { 12867 | return vds_; 12868 | } 12869 | 12870 | const vds_t& vds() const exprtk_override 12871 | { 12872 | return vds_; 12873 | } 12874 | 12875 | private: 12876 | 12877 | vector_node<T>* vec_node_ptr_; 12878 | vds_t vds_; 12879 | }; 12880 | 12881 | template <typename T> 12882 | class assignment_vecvec_node exprtk_final 12883 | : public binary_node <T> 12884 | , public vector_interface<T> 12885 | { 12886 | public: 12887 | 12888 | typedef expression_node<T>* expression_ptr; 12889 | typedef vector_node<T>* vector_node_ptr; 12890 | typedef vec_data_store<T> vds_t; 12891 | 12892 | using binary_node<T>::branch; 12893 | 12894 | assignment_vecvec_node(const operator_type& opr, 12895 | expression_ptr branch0, 12896 | expression_ptr branch1) 12897 | : binary_node<T>(opr, branch0, branch1) 12898 | , vec0_node_ptr_(0) 12899 | , vec1_node_ptr_(0) 12900 | , initialised_(false) 12901 | , src_is_ivec_(false) 12902 | { 12903 | if (is_vector_node(branch(0))) 12904 | { 12905 | vec0_node_ptr_ = static_cast<vector_node<T>*>(branch(0)); 12906 | vds() = vec0_node_ptr_->vds(); 12907 | } 12908 | 12909 | if (is_vector_node(branch(1))) 12910 | { 12911 | vec1_node_ptr_ = static_cast<vector_node<T>*>(branch(1)); 12912 | vds_t::match_sizes(vds(),vec1_node_ptr_->vds()); 12913 | } 12914 | else if (is_ivector_node(branch(1))) 12915 | { 12916 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 12917 | 12918 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1)))) 12919 | { 12920 | vec1_node_ptr_ = vi->vec(); 12921 | 12922 | if (!vi->side_effect()) 12923 | { 12924 | vi->vds() = vds(); 12925 | src_is_ivec_ = true; 12926 | } 12927 | else 12928 | vds_t::match_sizes(vds(),vi->vds()); 12929 | } 12930 | } 12931 | 12932 | initialised_ = 12933 | vec0_node_ptr_ && 12934 | vec1_node_ptr_ && 12935 | (size() <= base_size()) && 12936 | (vds_.size() <= base_size()) && 12937 | binary_node<T>::valid(); 12938 | 12939 | assert(valid()); 12940 | } 12941 | 12942 | inline T value() const exprtk_override 12943 | { 12944 | branch(1)->value(); 12945 | 12946 | if (src_is_ivec_) 12947 | return vec0_node_ptr_->value(); 12948 | 12949 | T* vec0 = vec0_node_ptr_->vds().data(); 12950 | T* vec1 = vec1_node_ptr_->vds().data(); 12951 | 12952 | loop_unroll::details lud(size()); 12953 | const T* upper_bound = vec0 + lud.upper_bound; 12954 | 12955 | while (vec0 < upper_bound) 12956 | { 12957 | #define exprtk_loop(N) \ 12958 | vec0[N] = vec1[N]; \ 12959 | 12960 | exprtk_loop( 0) exprtk_loop( 1) 12961 | exprtk_loop( 2) exprtk_loop( 3) 12962 | #ifndef exprtk_disable_superscalar_unroll 12963 | exprtk_loop( 4) exprtk_loop( 5) 12964 | exprtk_loop( 6) exprtk_loop( 7) 12965 | exprtk_loop( 8) exprtk_loop( 9) 12966 | exprtk_loop(10) exprtk_loop(11) 12967 | exprtk_loop(12) exprtk_loop(13) 12968 | exprtk_loop(14) exprtk_loop(15) 12969 | #endif 12970 | 12971 | vec0 += lud.batch_size; 12972 | vec1 += lud.batch_size; 12973 | } 12974 | 12975 | switch (lud.remainder) 12976 | { 12977 | #define case_stmt(N,fall_through) \ 12978 | case N : *vec0++ = *vec1++; \ 12979 | fall_through \ 12980 | 12981 | #ifndef exprtk_disable_superscalar_unroll 12982 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 12983 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 12984 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 12985 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 12986 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 12987 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 12988 | #endif 12989 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 12990 | case_stmt( 1, (void)0;) 12991 | } 12992 | 12993 | #undef exprtk_loop 12994 | #undef case_stmt 12995 | 12996 | return vec0_node_ptr_->value(); 12997 | } 12998 | 12999 | vector_node_ptr vec() exprtk_override 13000 | { 13001 | return vec0_node_ptr_; 13002 | } 13003 | 13004 | vector_node_ptr vec() const exprtk_override 13005 | { 13006 | return vec0_node_ptr_; 13007 | } 13008 | 13009 | inline typename expression_node<T>::node_type type() const exprtk_override 13010 | { 13011 | return expression_node<T>::e_vecvecass; 13012 | } 13013 | 13014 | inline bool valid() const exprtk_override 13015 | { 13016 | return initialised_; 13017 | } 13018 | 13019 | std::size_t size() const exprtk_override 13020 | { 13021 | return std::min( 13022 | vec0_node_ptr_->vec_holder().size(), 13023 | vec1_node_ptr_->vec_holder().size()); 13024 | } 13025 | 13026 | std::size_t base_size() const exprtk_override 13027 | { 13028 | return std::min( 13029 | vec0_node_ptr_->vec_holder().base_size(), 13030 | vec1_node_ptr_->vec_holder().base_size()); 13031 | } 13032 | 13033 | vds_t& vds() exprtk_override 13034 | { 13035 | return vds_; 13036 | } 13037 | 13038 | const vds_t& vds() const exprtk_override 13039 | { 13040 | return vds_; 13041 | } 13042 | 13043 | private: 13044 | 13045 | vector_node<T>* vec0_node_ptr_; 13046 | vector_node<T>* vec1_node_ptr_; 13047 | bool initialised_; 13048 | bool src_is_ivec_; 13049 | vds_t vds_; 13050 | }; 13051 | 13052 | template <typename T, typename Operation> 13053 | class assignment_op_node exprtk_final : public binary_node<T> 13054 | { 13055 | public: 13056 | 13057 | typedef expression_node<T>* expression_ptr; 13058 | using binary_node<T>::branch; 13059 | 13060 | assignment_op_node(const operator_type& opr, 13061 | expression_ptr branch0, 13062 | expression_ptr branch1) 13063 | : binary_node<T>(opr, branch0, branch1) 13064 | , var_node_ptr_(0) 13065 | { 13066 | if (is_variable_node(branch(0))) 13067 | { 13068 | var_node_ptr_ = static_cast<variable_node<T>*>(branch(0)); 13069 | } 13070 | 13071 | assert(valid()); 13072 | } 13073 | 13074 | inline T value() const exprtk_override 13075 | { 13076 | T& v = var_node_ptr_->ref(); 13077 | v = Operation::process(v,branch(1)->value()); 13078 | 13079 | return v; 13080 | } 13081 | 13082 | inline bool valid() const exprtk_override 13083 | { 13084 | return var_node_ptr_ && binary_node<T>::valid(); 13085 | } 13086 | 13087 | private: 13088 | 13089 | variable_node<T>* var_node_ptr_; 13090 | }; 13091 | 13092 | template <typename T, typename Operation> 13093 | class assignment_vec_elem_op_node exprtk_final : public binary_node<T> 13094 | { 13095 | public: 13096 | 13097 | typedef expression_node<T>* expression_ptr; 13098 | using binary_node<T>::branch; 13099 | 13100 | assignment_vec_elem_op_node(const operator_type& opr, 13101 | expression_ptr branch0, 13102 | expression_ptr branch1) 13103 | : binary_node<T>(opr, branch0, branch1) 13104 | , vec_node_ptr_(0) 13105 | { 13106 | if (is_vector_elem_node(branch(0))) 13107 | { 13108 | vec_node_ptr_ = static_cast<vector_elem_node<T>*>(branch(0)); 13109 | } 13110 | 13111 | assert(valid()); 13112 | } 13113 | 13114 | inline T value() const exprtk_override 13115 | { 13116 | T& v = vec_node_ptr_->ref(); 13117 | v = Operation::process(v,branch(1)->value()); 13118 | 13119 | return v; 13120 | } 13121 | 13122 | inline bool valid() const exprtk_override 13123 | { 13124 | return vec_node_ptr_ && binary_node<T>::valid(); 13125 | } 13126 | 13127 | private: 13128 | 13129 | vector_elem_node<T>* vec_node_ptr_; 13130 | }; 13131 | 13132 | template <typename T, typename Operation> 13133 | class assignment_vec_elem_op_rtc_node exprtk_final : public binary_node<T> 13134 | { 13135 | public: 13136 | 13137 | typedef expression_node<T>* expression_ptr; 13138 | using binary_node<T>::branch; 13139 | 13140 | assignment_vec_elem_op_rtc_node(const operator_type& opr, 13141 | expression_ptr branch0, 13142 | expression_ptr branch1) 13143 | : binary_node<T>(opr, branch0, branch1) 13144 | , vec_node_ptr_(0) 13145 | { 13146 | if (is_vector_elem_rtc_node(branch(0))) 13147 | { 13148 | vec_node_ptr_ = static_cast<vector_elem_rtc_node<T>*>(branch(0)); 13149 | } 13150 | 13151 | assert(valid()); 13152 | } 13153 | 13154 | inline T value() const exprtk_override 13155 | { 13156 | T& v = vec_node_ptr_->ref(); 13157 | v = Operation::process(v,branch(1)->value()); 13158 | 13159 | return v; 13160 | } 13161 | 13162 | inline bool valid() const exprtk_override 13163 | { 13164 | return vec_node_ptr_ && binary_node<T>::valid(); 13165 | } 13166 | 13167 | private: 13168 | 13169 | vector_elem_rtc_node<T>* vec_node_ptr_; 13170 | }; 13171 | 13172 | template <typename T, typename Operation> 13173 | class assignment_vec_celem_op_rtc_node exprtk_final : public binary_node<T> 13174 | { 13175 | public: 13176 | 13177 | typedef expression_node<T>* expression_ptr; 13178 | using binary_node<T>::branch; 13179 | 13180 | assignment_vec_celem_op_rtc_node(const operator_type& opr, 13181 | expression_ptr branch0, 13182 | expression_ptr branch1) 13183 | : binary_node<T>(opr, branch0, branch1) 13184 | , vec_node_ptr_(0) 13185 | { 13186 | if (is_vector_celem_rtc_node(branch(0))) 13187 | { 13188 | vec_node_ptr_ = static_cast<vector_celem_rtc_node<T>*>(branch(0)); 13189 | } 13190 | 13191 | assert(valid()); 13192 | } 13193 | 13194 | inline T value() const exprtk_override 13195 | { 13196 | T& v = vec_node_ptr_->ref(); 13197 | v = Operation::process(v,branch(1)->value()); 13198 | 13199 | return v; 13200 | } 13201 | 13202 | inline bool valid() const exprtk_override 13203 | { 13204 | return vec_node_ptr_ && binary_node<T>::valid(); 13205 | } 13206 | 13207 | private: 13208 | 13209 | vector_celem_rtc_node<T>* vec_node_ptr_; 13210 | }; 13211 | 13212 | template <typename T, typename Operation> 13213 | class assignment_rebasevec_elem_op_node exprtk_final : public binary_node<T> 13214 | { 13215 | public: 13216 | 13217 | typedef expression_node<T>* expression_ptr; 13218 | using binary_node<T>::branch; 13219 | 13220 | assignment_rebasevec_elem_op_node(const operator_type& opr, 13221 | expression_ptr branch0, 13222 | expression_ptr branch1) 13223 | : binary_node<T>(opr, branch0, branch1) 13224 | , rbvec_node_ptr_(0) 13225 | { 13226 | if (is_rebasevector_elem_node(branch(0))) 13227 | { 13228 | rbvec_node_ptr_ = static_cast<rebasevector_elem_node<T>*>(branch(0)); 13229 | } 13230 | 13231 | assert(valid()); 13232 | } 13233 | 13234 | inline T value() const exprtk_override 13235 | { 13236 | T& v = rbvec_node_ptr_->ref(); 13237 | v = Operation::process(v,branch(1)->value()); 13238 | 13239 | return v; 13240 | } 13241 | 13242 | inline bool valid() const exprtk_override 13243 | { 13244 | return rbvec_node_ptr_ && binary_node<T>::valid(); 13245 | } 13246 | 13247 | private: 13248 | 13249 | rebasevector_elem_node<T>* rbvec_node_ptr_; 13250 | }; 13251 | 13252 | template <typename T, typename Operation> 13253 | class assignment_rebasevec_celem_op_node exprtk_final : public binary_node<T> 13254 | { 13255 | public: 13256 | 13257 | typedef expression_node<T>* expression_ptr; 13258 | using binary_node<T>::branch; 13259 | 13260 | assignment_rebasevec_celem_op_node(const operator_type& opr, 13261 | expression_ptr branch0, 13262 | expression_ptr branch1) 13263 | : binary_node<T>(opr, branch0, branch1) 13264 | , rbvec_node_ptr_(0) 13265 | { 13266 | if (is_rebasevector_celem_node(branch(0))) 13267 | { 13268 | rbvec_node_ptr_ = static_cast<rebasevector_celem_node<T>*>(branch(0)); 13269 | } 13270 | 13271 | assert(valid()); 13272 | } 13273 | 13274 | inline T value() const exprtk_override 13275 | { 13276 | T& v = rbvec_node_ptr_->ref(); 13277 | v = Operation::process(v,branch(1)->value()); 13278 | 13279 | return v; 13280 | } 13281 | 13282 | inline bool valid() const exprtk_override 13283 | { 13284 | return rbvec_node_ptr_ && binary_node<T>::valid(); 13285 | } 13286 | 13287 | private: 13288 | 13289 | rebasevector_celem_node<T>* rbvec_node_ptr_; 13290 | }; 13291 | 13292 | template <typename T, typename Operation> 13293 | class assignment_rebasevec_elem_op_rtc_node exprtk_final : public binary_node<T> 13294 | { 13295 | public: 13296 | 13297 | typedef expression_node<T>* expression_ptr; 13298 | using binary_node<T>::branch; 13299 | 13300 | assignment_rebasevec_elem_op_rtc_node(const operator_type& opr, 13301 | expression_ptr branch0, 13302 | expression_ptr branch1) 13303 | : binary_node<T>(opr, branch0, branch1) 13304 | , rbvec_node_ptr_(0) 13305 | { 13306 | if (is_rebasevector_elem_rtc_node(branch(0))) 13307 | { 13308 | rbvec_node_ptr_ = static_cast<rebasevector_elem_rtc_node<T>*>(branch(0)); 13309 | } 13310 | 13311 | assert(valid()); 13312 | } 13313 | 13314 | inline T value() const exprtk_override 13315 | { 13316 | T& v = rbvec_node_ptr_->ref(); 13317 | v = Operation::process(v,branch(1)->value()); 13318 | 13319 | return v; 13320 | } 13321 | 13322 | inline bool valid() const exprtk_override 13323 | { 13324 | return rbvec_node_ptr_ && binary_node<T>::valid(); 13325 | } 13326 | 13327 | private: 13328 | 13329 | rebasevector_elem_rtc_node<T>* rbvec_node_ptr_; 13330 | }; 13331 | 13332 | template <typename T, typename Operation> 13333 | class assignment_rebasevec_celem_op_rtc_node exprtk_final : public binary_node<T> 13334 | { 13335 | public: 13336 | 13337 | typedef expression_node<T>* expression_ptr; 13338 | using binary_node<T>::branch; 13339 | 13340 | assignment_rebasevec_celem_op_rtc_node(const operator_type& opr, 13341 | expression_ptr branch0, 13342 | expression_ptr branch1) 13343 | : binary_node<T>(opr, branch0, branch1) 13344 | , rbvec_node_ptr_(0) 13345 | { 13346 | if (is_rebasevector_celem_rtc_node(branch(0))) 13347 | { 13348 | rbvec_node_ptr_ = static_cast<rebasevector_celem_rtc_node<T>*>(branch(0)); 13349 | } 13350 | 13351 | assert(valid()); 13352 | } 13353 | 13354 | inline T value() const exprtk_override 13355 | { 13356 | T& v = rbvec_node_ptr_->ref(); 13357 | v = Operation::process(v,branch(1)->value()); 13358 | 13359 | return v; 13360 | } 13361 | 13362 | inline bool valid() const exprtk_override 13363 | { 13364 | return rbvec_node_ptr_ && binary_node<T>::valid(); 13365 | } 13366 | 13367 | private: 13368 | 13369 | rebasevector_celem_rtc_node<T>* rbvec_node_ptr_; 13370 | }; 13371 | 13372 | template <typename T, typename Operation> 13373 | class assignment_vec_op_node exprtk_final 13374 | : public binary_node <T> 13375 | , public vector_interface<T> 13376 | { 13377 | public: 13378 | 13379 | typedef expression_node<T>* expression_ptr; 13380 | typedef vector_node<T>* vector_node_ptr; 13381 | typedef vec_data_store<T> vds_t; 13382 | 13383 | using binary_node<T>::branch; 13384 | 13385 | assignment_vec_op_node(const operator_type& opr, 13386 | expression_ptr branch0, 13387 | expression_ptr branch1) 13388 | : binary_node<T>(opr, branch0, branch1) 13389 | , vec_node_ptr_(0) 13390 | { 13391 | if (is_vector_node(branch(0))) 13392 | { 13393 | vec_node_ptr_ = static_cast<vector_node<T>*>(branch(0)); 13394 | vds() = vec_node_ptr_->vds(); 13395 | } 13396 | 13397 | assert(valid()); 13398 | } 13399 | 13400 | inline T value() const exprtk_override 13401 | { 13402 | const T v = branch(1)->value(); 13403 | 13404 | T* vec = vds().data(); 13405 | 13406 | loop_unroll::details lud(size()); 13407 | const T* upper_bound = vec + lud.upper_bound; 13408 | 13409 | while (vec < upper_bound) 13410 | { 13411 | #define exprtk_loop(N) \ 13412 | Operation::assign(vec[N],v); \ 13413 | 13414 | exprtk_loop( 0) exprtk_loop( 1) 13415 | exprtk_loop( 2) exprtk_loop( 3) 13416 | #ifndef exprtk_disable_superscalar_unroll 13417 | exprtk_loop( 4) exprtk_loop( 5) 13418 | exprtk_loop( 6) exprtk_loop( 7) 13419 | exprtk_loop( 8) exprtk_loop( 9) 13420 | exprtk_loop(10) exprtk_loop(11) 13421 | exprtk_loop(12) exprtk_loop(13) 13422 | exprtk_loop(14) exprtk_loop(15) 13423 | #endif 13424 | 13425 | vec += lud.batch_size; 13426 | } 13427 | 13428 | switch (lud.remainder) 13429 | { 13430 | #define case_stmt(N,fall_through) \ 13431 | case N : Operation::assign(*vec++,v); \ 13432 | fall_through \ 13433 | 13434 | #ifndef exprtk_disable_superscalar_unroll 13435 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 13436 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 13437 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 13438 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 13439 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 13440 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 13441 | #endif 13442 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 13443 | case_stmt( 1, (void)0;) 13444 | } 13445 | 13446 | #undef exprtk_loop 13447 | #undef case_stmt 13448 | 13449 | return vec_node_ptr_->value(); 13450 | } 13451 | 13452 | vector_node_ptr vec() const exprtk_override 13453 | { 13454 | return vec_node_ptr_; 13455 | } 13456 | 13457 | vector_node_ptr vec() exprtk_override 13458 | { 13459 | return vec_node_ptr_; 13460 | } 13461 | 13462 | inline typename expression_node<T>::node_type type() const exprtk_override 13463 | { 13464 | return expression_node<T>::e_vecopvalass; 13465 | } 13466 | 13467 | inline bool valid() const exprtk_override 13468 | { 13469 | return 13470 | vec_node_ptr_ && 13471 | (size() <= base_size()) && 13472 | binary_node<T>::valid() ; 13473 | } 13474 | 13475 | std::size_t size() const exprtk_override 13476 | { 13477 | return vec_node_ptr_->vec_holder().size(); 13478 | } 13479 | 13480 | std::size_t base_size() const exprtk_override 13481 | { 13482 | return vec_node_ptr_->vec_holder().base_size(); 13483 | } 13484 | 13485 | vds_t& vds() exprtk_override 13486 | { 13487 | return vds_; 13488 | } 13489 | 13490 | const vds_t& vds() const exprtk_override 13491 | { 13492 | return vds_; 13493 | } 13494 | 13495 | bool side_effect() const exprtk_override 13496 | { 13497 | return true; 13498 | } 13499 | 13500 | private: 13501 | 13502 | vector_node<T>* vec_node_ptr_; 13503 | vds_t vds_; 13504 | }; 13505 | 13506 | template <typename T, typename Operation> 13507 | class assignment_vecvec_op_node exprtk_final 13508 | : public binary_node <T> 13509 | , public vector_interface<T> 13510 | { 13511 | public: 13512 | 13513 | typedef expression_node<T>* expression_ptr; 13514 | typedef vector_node<T>* vector_node_ptr; 13515 | typedef vec_data_store<T> vds_t; 13516 | 13517 | using binary_node<T>::branch; 13518 | 13519 | assignment_vecvec_op_node(const operator_type& opr, 13520 | expression_ptr branch0, 13521 | expression_ptr branch1) 13522 | : binary_node<T>(opr, branch0, branch1) 13523 | , vec0_node_ptr_(0) 13524 | , vec1_node_ptr_(0) 13525 | , initialised_(false) 13526 | { 13527 | if (is_vector_node(branch(0))) 13528 | { 13529 | vec0_node_ptr_ = static_cast<vector_node<T>*>(branch(0)); 13530 | vds() = vec0_node_ptr_->vds(); 13531 | } 13532 | 13533 | if (is_vector_node(branch(1))) 13534 | { 13535 | vec1_node_ptr_ = static_cast<vector_node<T>*>(branch(1)); 13536 | vec1_node_ptr_->vds() = vds(); 13537 | } 13538 | else if (is_ivector_node(branch(1))) 13539 | { 13540 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 13541 | 13542 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1)))) 13543 | { 13544 | vec1_node_ptr_ = vi->vec(); 13545 | vec1_node_ptr_->vds() = vi->vds(); 13546 | } 13547 | else 13548 | vds_t::match_sizes(vds(),vec1_node_ptr_->vds()); 13549 | } 13550 | 13551 | initialised_ = 13552 | vec0_node_ptr_ && 13553 | vec1_node_ptr_ && 13554 | (size() <= base_size()) && 13555 | binary_node<T>::valid(); 13556 | 13557 | assert(valid()); 13558 | } 13559 | 13560 | inline T value() const exprtk_override 13561 | { 13562 | branch(0)->value(); 13563 | branch(1)->value(); 13564 | 13565 | T* vec0 = vec0_node_ptr_->vds().data(); 13566 | const T* vec1 = vec1_node_ptr_->vds().data(); 13567 | 13568 | loop_unroll::details lud(size()); 13569 | const T* upper_bound = vec0 + lud.upper_bound; 13570 | 13571 | while (vec0 < upper_bound) 13572 | { 13573 | #define exprtk_loop(N) \ 13574 | vec0[N] = Operation::process(vec0[N], vec1[N]); \ 13575 | 13576 | exprtk_loop( 0) exprtk_loop( 1) 13577 | exprtk_loop( 2) exprtk_loop( 3) 13578 | #ifndef exprtk_disable_superscalar_unroll 13579 | exprtk_loop( 4) exprtk_loop( 5) 13580 | exprtk_loop( 6) exprtk_loop( 7) 13581 | exprtk_loop( 8) exprtk_loop( 9) 13582 | exprtk_loop(10) exprtk_loop(11) 13583 | exprtk_loop(12) exprtk_loop(13) 13584 | exprtk_loop(14) exprtk_loop(15) 13585 | #endif 13586 | 13587 | vec0 += lud.batch_size; 13588 | vec1 += lud.batch_size; 13589 | } 13590 | 13591 | int i = 0; 13592 | 13593 | switch (lud.remainder) 13594 | { 13595 | #define case_stmt(N,fall_through) \ 13596 | case N : { vec0[i] = Operation::process(vec0[i], vec1[i]); ++i; } \ 13597 | fall_through \ 13598 | 13599 | #ifndef exprtk_disable_superscalar_unroll 13600 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 13601 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 13602 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 13603 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 13604 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 13605 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 13606 | #endif 13607 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 13608 | case_stmt( 1, (void)0;) 13609 | } 13610 | 13611 | #undef exprtk_loop 13612 | #undef case_stmt 13613 | 13614 | return vec0_node_ptr_->value(); 13615 | } 13616 | 13617 | vector_node_ptr vec() const exprtk_override 13618 | { 13619 | return vec0_node_ptr_; 13620 | } 13621 | 13622 | vector_node_ptr vec() exprtk_override 13623 | { 13624 | return vec0_node_ptr_; 13625 | } 13626 | 13627 | inline typename expression_node<T>::node_type type() const exprtk_override 13628 | { 13629 | return expression_node<T>::e_vecopvecass; 13630 | } 13631 | 13632 | inline bool valid() const exprtk_override 13633 | { 13634 | return initialised_; 13635 | } 13636 | 13637 | std::size_t size() const exprtk_override 13638 | { 13639 | return std::min( 13640 | vec0_node_ptr_->vec_holder().size(), 13641 | vec1_node_ptr_->vec_holder().size()); 13642 | } 13643 | 13644 | std::size_t base_size() const exprtk_override 13645 | { 13646 | return std::min( 13647 | vec0_node_ptr_->vec_holder().base_size(), 13648 | vec1_node_ptr_->vec_holder().base_size()); 13649 | } 13650 | 13651 | vds_t& vds() exprtk_override 13652 | { 13653 | return vds_; 13654 | } 13655 | 13656 | const vds_t& vds() const exprtk_override 13657 | { 13658 | return vds_; 13659 | } 13660 | 13661 | bool side_effect() const exprtk_override 13662 | { 13663 | return true; 13664 | } 13665 | 13666 | private: 13667 | 13668 | vector_node<T>* vec0_node_ptr_; 13669 | vector_node<T>* vec1_node_ptr_; 13670 | bool initialised_; 13671 | vds_t vds_; 13672 | }; 13673 | 13674 | template <typename T> 13675 | struct memory_context_t 13676 | { 13677 | typedef vector_node<T>* vector_node_ptr; 13678 | typedef vector_holder<T> vector_holder_t; 13679 | typedef vector_holder_t* vector_holder_ptr; 13680 | 13681 | memory_context_t() 13682 | : temp_(0) 13683 | , temp_vec_node_(0) 13684 | {} 13685 | 13686 | void clear() 13687 | { 13688 | delete temp_vec_node_; 13689 | delete temp_; 13690 | } 13691 | 13692 | vector_holder_ptr temp_; 13693 | vector_node_ptr temp_vec_node_; 13694 | }; 13695 | 13696 | template <typename T> 13697 | inline memory_context_t<T> make_memory_context(vector_holder<T>& vec_holder, 13698 | vec_data_store<T>& vds) 13699 | { 13700 | memory_context_t<T> result_ctxt; 13701 | 13702 | result_ctxt.temp_ = (vec_holder.rebaseable()) ? 13703 | new vector_holder<T>(vec_holder,vds) : 13704 | new vector_holder<T>(vds) ; 13705 | 13706 | result_ctxt.temp_vec_node_ = new vector_node<T>(vds,result_ctxt.temp_); 13707 | 13708 | return result_ctxt; 13709 | } 13710 | 13711 | template <typename T> 13712 | inline memory_context_t<T> make_memory_context(vector_holder<T>& vec_holder0, 13713 | vector_holder<T>& vec_holder1, 13714 | vec_data_store<T>& vds) 13715 | { 13716 | memory_context_t<T> result_ctxt; 13717 | 13718 | if (!vec_holder0.rebaseable() && !vec_holder1.rebaseable()) 13719 | result_ctxt.temp_ = new vector_holder<T>(vds); 13720 | else if (vec_holder0.rebaseable() && !vec_holder1.rebaseable()) 13721 | result_ctxt.temp_ = new vector_holder<T>(vec_holder0,vds); 13722 | else if (!vec_holder0.rebaseable() && vec_holder1.rebaseable()) 13723 | result_ctxt.temp_ = new vector_holder<T>(vec_holder1,vds); 13724 | else 13725 | { 13726 | result_ctxt.temp_ = (vec_holder0.base_size() >= vec_holder1.base_size()) ? 13727 | new vector_holder<T>(vec_holder0, vds) : 13728 | new vector_holder<T>(vec_holder1, vds) ; 13729 | } 13730 | 13731 | result_ctxt.temp_vec_node_ = new vector_node<T>(vds,result_ctxt.temp_); 13732 | 13733 | return result_ctxt; 13734 | } 13735 | 13736 | template <typename T, typename Operation> 13737 | class vec_binop_vecvec_node exprtk_final 13738 | : public binary_node <T> 13739 | , public vector_interface<T> 13740 | { 13741 | public: 13742 | 13743 | typedef expression_node<T>* expression_ptr; 13744 | typedef vector_node<T>* vector_node_ptr; 13745 | typedef vector_holder<T> vector_holder_t; 13746 | typedef vector_holder_t* vector_holder_ptr; 13747 | typedef vec_data_store<T> vds_t; 13748 | typedef memory_context_t<T> memory_context; 13749 | 13750 | using binary_node<T>::branch; 13751 | 13752 | vec_binop_vecvec_node(const operator_type& opr, 13753 | expression_ptr branch0, 13754 | expression_ptr branch1) 13755 | : binary_node<T>(opr, branch0, branch1) 13756 | , vec0_node_ptr_(0) 13757 | , vec1_node_ptr_(0) 13758 | , initialised_(false) 13759 | { 13760 | bool v0_is_ivec = false; 13761 | bool v1_is_ivec = false; 13762 | 13763 | if (is_vector_node(branch(0))) 13764 | { 13765 | vec0_node_ptr_ = static_cast<vector_node_ptr>(branch(0)); 13766 | } 13767 | else if (is_ivector_node(branch(0))) 13768 | { 13769 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 13770 | 13771 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(0)))) 13772 | { 13773 | vec0_node_ptr_ = vi->vec(); 13774 | v0_is_ivec = true; 13775 | } 13776 | } 13777 | 13778 | if (is_vector_node(branch(1))) 13779 | { 13780 | vec1_node_ptr_ = static_cast<vector_node_ptr>(branch(1)); 13781 | } 13782 | else if (is_ivector_node(branch(1))) 13783 | { 13784 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 13785 | 13786 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1)))) 13787 | { 13788 | vec1_node_ptr_ = vi->vec(); 13789 | v1_is_ivec = true; 13790 | } 13791 | } 13792 | 13793 | if (vec0_node_ptr_ && vec1_node_ptr_) 13794 | { 13795 | vector_holder<T>& vec0 = vec0_node_ptr_->vec_holder(); 13796 | vector_holder<T>& vec1 = vec1_node_ptr_->vec_holder(); 13797 | 13798 | if (v0_is_ivec && (vec0.base_size() <= vec1.base_size())) 13799 | { 13800 | vds_ = vds_t(vec0_node_ptr_->vds()); 13801 | } 13802 | else if (v1_is_ivec && (vec1.base_size() <= vec0.base_size())) 13803 | { 13804 | vds_ = vds_t(vec1_node_ptr_->vds()); 13805 | } 13806 | else 13807 | { 13808 | vds_ = vds_t(std::min(vec0.base_size(),vec1.base_size())); 13809 | } 13810 | 13811 | memory_context_ = make_memory_context(vec0, vec1, vds()); 13812 | 13813 | initialised_ = 13814 | (size() <= base_size()) && 13815 | binary_node<T>::valid(); 13816 | } 13817 | 13818 | assert(valid()); 13819 | } 13820 | 13821 | ~vec_binop_vecvec_node() 13822 | { 13823 | memory_context_.clear(); 13824 | } 13825 | 13826 | inline T value() const exprtk_override 13827 | { 13828 | branch(0)->value(); 13829 | branch(1)->value(); 13830 | 13831 | const T* vec0 = vec0_node_ptr_->vds().data(); 13832 | const T* vec1 = vec1_node_ptr_->vds().data(); 13833 | T* vec2 = vds().data(); 13834 | 13835 | loop_unroll::details lud(size()); 13836 | const T* upper_bound = vec2 + lud.upper_bound; 13837 | 13838 | while (vec2 < upper_bound) 13839 | { 13840 | #define exprtk_loop(N) \ 13841 | vec2[N] = Operation::process(vec0[N], vec1[N]); \ 13842 | 13843 | exprtk_loop( 0) exprtk_loop( 1) 13844 | exprtk_loop( 2) exprtk_loop( 3) 13845 | #ifndef exprtk_disable_superscalar_unroll 13846 | exprtk_loop( 4) exprtk_loop( 5) 13847 | exprtk_loop( 6) exprtk_loop( 7) 13848 | exprtk_loop( 8) exprtk_loop( 9) 13849 | exprtk_loop(10) exprtk_loop(11) 13850 | exprtk_loop(12) exprtk_loop(13) 13851 | exprtk_loop(14) exprtk_loop(15) 13852 | #endif 13853 | 13854 | vec0 += lud.batch_size; 13855 | vec1 += lud.batch_size; 13856 | vec2 += lud.batch_size; 13857 | } 13858 | 13859 | int i = 0; 13860 | 13861 | switch (lud.remainder) 13862 | { 13863 | #define case_stmt(N) \ 13864 | case N : { vec2[i] = Operation::process(vec0[i], vec1[i]); ++i; } \ 13865 | exprtk_fallthrough \ 13866 | 13867 | #ifndef exprtk_disable_superscalar_unroll 13868 | case_stmt(15) case_stmt(14) 13869 | case_stmt(13) case_stmt(12) 13870 | case_stmt(11) case_stmt(10) 13871 | case_stmt( 9) case_stmt( 8) 13872 | case_stmt( 7) case_stmt( 6) 13873 | case_stmt( 5) case_stmt( 4) 13874 | #endif 13875 | case_stmt( 3) case_stmt( 2) 13876 | case_stmt( 1) 13877 | default: break; 13878 | } 13879 | 13880 | #undef exprtk_loop 13881 | #undef case_stmt 13882 | 13883 | return (vds().data())[0]; 13884 | } 13885 | 13886 | vector_node_ptr vec() const exprtk_override 13887 | { 13888 | return memory_context_.temp_vec_node_; 13889 | } 13890 | 13891 | vector_node_ptr vec() exprtk_override 13892 | { 13893 | return memory_context_.temp_vec_node_; 13894 | } 13895 | 13896 | inline typename expression_node<T>::node_type type() const exprtk_override 13897 | { 13898 | return expression_node<T>::e_vecvecarith; 13899 | } 13900 | 13901 | inline bool valid() const exprtk_override 13902 | { 13903 | return initialised_; 13904 | } 13905 | 13906 | std::size_t size() const exprtk_override 13907 | { 13908 | return std::min(vds().size(), 13909 | std::min( 13910 | vec0_node_ptr_->vec_holder().size(), 13911 | vec1_node_ptr_->vec_holder().size())); 13912 | } 13913 | 13914 | std::size_t base_size() const exprtk_override 13915 | { 13916 | return std::min( 13917 | vec0_node_ptr_->vec_holder().base_size(), 13918 | vec1_node_ptr_->vec_holder().base_size()); 13919 | } 13920 | 13921 | vds_t& vds() exprtk_override 13922 | { 13923 | return vds_; 13924 | } 13925 | 13926 | const vds_t& vds() const exprtk_override 13927 | { 13928 | return vds_; 13929 | } 13930 | 13931 | private: 13932 | 13933 | vector_node_ptr vec0_node_ptr_; 13934 | vector_node_ptr vec1_node_ptr_; 13935 | bool initialised_; 13936 | vds_t vds_; 13937 | memory_context memory_context_; 13938 | }; 13939 | 13940 | template <typename T, typename Operation> 13941 | class vec_binop_vecval_node exprtk_final 13942 | : public binary_node <T> 13943 | , public vector_interface<T> 13944 | { 13945 | public: 13946 | 13947 | typedef expression_node<T>* expression_ptr; 13948 | typedef vector_node<T>* vector_node_ptr; 13949 | typedef vector_holder<T> vector_holder_t; 13950 | typedef vector_holder_t* vector_holder_ptr; 13951 | typedef vec_data_store<T> vds_t; 13952 | typedef memory_context_t<T> memory_context; 13953 | 13954 | using binary_node<T>::branch; 13955 | 13956 | vec_binop_vecval_node(const operator_type& opr, 13957 | expression_ptr branch0, 13958 | expression_ptr branch1) 13959 | : binary_node<T>(opr, branch0, branch1) 13960 | , vec0_node_ptr_(0) 13961 | { 13962 | bool v0_is_ivec = false; 13963 | 13964 | if (is_vector_node(branch(0))) 13965 | { 13966 | vec0_node_ptr_ = static_cast<vector_node_ptr>(branch(0)); 13967 | } 13968 | else if (is_ivector_node(branch(0))) 13969 | { 13970 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 13971 | 13972 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(0)))) 13973 | { 13974 | vec0_node_ptr_ = vi->vec(); 13975 | v0_is_ivec = true; 13976 | } 13977 | } 13978 | 13979 | if (vec0_node_ptr_) 13980 | { 13981 | if (v0_is_ivec) 13982 | vds() = vec0_node_ptr_->vds(); 13983 | else 13984 | vds() = vds_t(vec0_node_ptr_->base_size()); 13985 | 13986 | memory_context_ = make_memory_context(vec0_node_ptr_->vec_holder(), vds()); 13987 | } 13988 | 13989 | assert(valid()); 13990 | } 13991 | 13992 | ~vec_binop_vecval_node() 13993 | { 13994 | memory_context_.clear(); 13995 | } 13996 | 13997 | inline T value() const exprtk_override 13998 | { 13999 | branch(0)->value(); 14000 | const T v = branch(1)->value(); 14001 | 14002 | const T* vec0 = vec0_node_ptr_->vds().data(); 14003 | T* vec1 = vds().data(); 14004 | 14005 | loop_unroll::details lud(size()); 14006 | const T* upper_bound = vec0 + lud.upper_bound; 14007 | 14008 | while (vec0 < upper_bound) 14009 | { 14010 | #define exprtk_loop(N) \ 14011 | vec1[N] = Operation::process(vec0[N], v); \ 14012 | 14013 | exprtk_loop( 0) exprtk_loop( 1) 14014 | exprtk_loop( 2) exprtk_loop( 3) 14015 | #ifndef exprtk_disable_superscalar_unroll 14016 | exprtk_loop( 4) exprtk_loop( 5) 14017 | exprtk_loop( 6) exprtk_loop( 7) 14018 | exprtk_loop( 8) exprtk_loop( 9) 14019 | exprtk_loop(10) exprtk_loop(11) 14020 | exprtk_loop(12) exprtk_loop(13) 14021 | exprtk_loop(14) exprtk_loop(15) 14022 | #endif 14023 | 14024 | vec0 += lud.batch_size; 14025 | vec1 += lud.batch_size; 14026 | } 14027 | 14028 | int i = 0; 14029 | 14030 | switch (lud.remainder) 14031 | { 14032 | #define case_stmt(N,fall_through) \ 14033 | case N : { vec1[i] = Operation::process(vec0[i], v); ++i; } \ 14034 | fall_through \ 14035 | 14036 | #ifndef exprtk_disable_superscalar_unroll 14037 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 14038 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 14039 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 14040 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 14041 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 14042 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 14043 | #endif 14044 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 14045 | case_stmt( 1, (void)0;) 14046 | } 14047 | 14048 | #undef exprtk_loop 14049 | #undef case_stmt 14050 | 14051 | return (vds().data())[0]; 14052 | } 14053 | 14054 | vector_node_ptr vec() const exprtk_override 14055 | { 14056 | return memory_context_.temp_vec_node_; 14057 | } 14058 | 14059 | vector_node_ptr vec() exprtk_override 14060 | { 14061 | return memory_context_.temp_vec_node_; 14062 | } 14063 | 14064 | inline typename expression_node<T>::node_type type() const exprtk_override 14065 | { 14066 | return expression_node<T>::e_vecvalarith; 14067 | } 14068 | 14069 | inline bool valid() const exprtk_override 14070 | { 14071 | return 14072 | vec0_node_ptr_ && 14073 | (size() <= base_size()) && 14074 | binary_node<T>::valid(); 14075 | } 14076 | 14077 | std::size_t size() const exprtk_override 14078 | { 14079 | return std::min(vec0_node_ptr_->size(), vds().size()); 14080 | } 14081 | 14082 | std::size_t base_size() const exprtk_override 14083 | { 14084 | return vec0_node_ptr_->vec_holder().base_size(); 14085 | } 14086 | 14087 | vds_t& vds() exprtk_override 14088 | { 14089 | return vds_; 14090 | } 14091 | 14092 | const vds_t& vds() const exprtk_override 14093 | { 14094 | return vds_; 14095 | } 14096 | 14097 | private: 14098 | 14099 | vector_node_ptr vec0_node_ptr_; 14100 | vds_t vds_; 14101 | memory_context memory_context_; 14102 | }; 14103 | 14104 | template <typename T, typename Operation> 14105 | class vec_binop_valvec_node exprtk_final 14106 | : public binary_node <T> 14107 | , public vector_interface<T> 14108 | { 14109 | public: 14110 | 14111 | typedef expression_node<T>* expression_ptr; 14112 | typedef vector_node<T>* vector_node_ptr; 14113 | typedef vector_holder<T> vector_holder_t; 14114 | typedef vector_holder_t* vector_holder_ptr; 14115 | typedef vec_data_store<T> vds_t; 14116 | typedef memory_context_t<T> memory_context; 14117 | 14118 | using binary_node<T>::branch; 14119 | 14120 | vec_binop_valvec_node(const operator_type& opr, 14121 | expression_ptr branch0, 14122 | expression_ptr branch1) 14123 | : binary_node<T>(opr, branch0, branch1) 14124 | , vec1_node_ptr_(0) 14125 | { 14126 | bool v1_is_ivec = false; 14127 | 14128 | if (is_vector_node(branch(1))) 14129 | { 14130 | vec1_node_ptr_ = static_cast<vector_node_ptr>(branch(1)); 14131 | } 14132 | else if (is_ivector_node(branch(1))) 14133 | { 14134 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 14135 | 14136 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1)))) 14137 | { 14138 | vec1_node_ptr_ = vi->vec(); 14139 | v1_is_ivec = true; 14140 | } 14141 | } 14142 | 14143 | if (vec1_node_ptr_) 14144 | { 14145 | if (v1_is_ivec) 14146 | vds() = vec1_node_ptr_->vds(); 14147 | else 14148 | vds() = vds_t(vec1_node_ptr_->base_size()); 14149 | 14150 | memory_context_ = make_memory_context(vec1_node_ptr_->vec_holder(), vds()); 14151 | } 14152 | 14153 | assert(valid()); 14154 | } 14155 | 14156 | ~vec_binop_valvec_node() 14157 | { 14158 | memory_context_.clear(); 14159 | } 14160 | 14161 | inline T value() const exprtk_override 14162 | { 14163 | const T v = branch(0)->value(); 14164 | branch(1)->value(); 14165 | 14166 | T* vec0 = vds().data(); 14167 | const T* vec1 = vec1_node_ptr_->vds().data(); 14168 | 14169 | loop_unroll::details lud(size()); 14170 | const T* upper_bound = vec0 + lud.upper_bound; 14171 | 14172 | while (vec0 < upper_bound) 14173 | { 14174 | #define exprtk_loop(N) \ 14175 | vec0[N] = Operation::process(v, vec1[N]); \ 14176 | 14177 | exprtk_loop( 0) exprtk_loop( 1) 14178 | exprtk_loop( 2) exprtk_loop( 3) 14179 | #ifndef exprtk_disable_superscalar_unroll 14180 | exprtk_loop( 4) exprtk_loop( 5) 14181 | exprtk_loop( 6) exprtk_loop( 7) 14182 | exprtk_loop( 8) exprtk_loop( 9) 14183 | exprtk_loop(10) exprtk_loop(11) 14184 | exprtk_loop(12) exprtk_loop(13) 14185 | exprtk_loop(14) exprtk_loop(15) 14186 | #endif 14187 | 14188 | vec0 += lud.batch_size; 14189 | vec1 += lud.batch_size; 14190 | } 14191 | 14192 | int i = 0; 14193 | 14194 | switch (lud.remainder) 14195 | { 14196 | #define case_stmt(N,fall_through) \ 14197 | case N : { vec0[i] = Operation::process(v, vec1[i]); ++i; } \ 14198 | fall_through \ 14199 | 14200 | #ifndef exprtk_disable_superscalar_unroll 14201 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 14202 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 14203 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 14204 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 14205 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 14206 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 14207 | #endif 14208 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 14209 | case_stmt( 1, (void)0;) 14210 | } 14211 | 14212 | #undef exprtk_loop 14213 | #undef case_stmt 14214 | 14215 | return (vds().data())[0]; 14216 | } 14217 | 14218 | vector_node_ptr vec() const exprtk_override 14219 | { 14220 | return memory_context_.temp_vec_node_; 14221 | } 14222 | 14223 | vector_node_ptr vec() exprtk_override 14224 | { 14225 | return memory_context_.temp_vec_node_; 14226 | } 14227 | 14228 | inline typename expression_node<T>::node_type type() const exprtk_override 14229 | { 14230 | return expression_node<T>::e_vecvalarith; 14231 | } 14232 | 14233 | inline bool valid() const exprtk_override 14234 | { 14235 | return 14236 | vec1_node_ptr_ && 14237 | (size() <= base_size()) && 14238 | (vds_.size() <= base_size()) && 14239 | binary_node<T>::valid(); 14240 | } 14241 | 14242 | std::size_t size() const exprtk_override 14243 | { 14244 | return std::min(vec1_node_ptr_->size(), vds().size()); 14245 | } 14246 | 14247 | std::size_t base_size() const exprtk_override 14248 | { 14249 | return vec1_node_ptr_->vec_holder().base_size(); 14250 | } 14251 | 14252 | vds_t& vds() exprtk_override 14253 | { 14254 | return vds_; 14255 | } 14256 | 14257 | const vds_t& vds() const exprtk_override 14258 | { 14259 | return vds_; 14260 | } 14261 | 14262 | private: 14263 | 14264 | vector_node_ptr vec1_node_ptr_; 14265 | vds_t vds_; 14266 | memory_context memory_context_; 14267 | }; 14268 | 14269 | template <typename T, typename Operation> 14270 | class unary_vector_node exprtk_final 14271 | : public unary_node <T> 14272 | , public vector_interface<T> 14273 | { 14274 | public: 14275 | 14276 | typedef expression_node<T>* expression_ptr; 14277 | typedef vector_node<T>* vector_node_ptr; 14278 | typedef vector_holder<T> vector_holder_t; 14279 | typedef vector_holder_t* vector_holder_ptr; 14280 | typedef vec_data_store<T> vds_t; 14281 | typedef memory_context_t<T> memory_context; 14282 | 14283 | using expression_node<T>::branch; 14284 | 14285 | unary_vector_node(const operator_type& opr, expression_ptr branch0) 14286 | : unary_node<T>(opr, branch0) 14287 | , vec0_node_ptr_(0) 14288 | { 14289 | bool vec0_is_ivec = false; 14290 | 14291 | if (is_vector_node(branch(0))) 14292 | { 14293 | vec0_node_ptr_ = static_cast<vector_node_ptr>(branch(0)); 14294 | } 14295 | else if (is_ivector_node(branch(0))) 14296 | { 14297 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 14298 | 14299 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(0)))) 14300 | { 14301 | vec0_node_ptr_ = vi->vec(); 14302 | vec0_is_ivec = true; 14303 | } 14304 | } 14305 | 14306 | if (vec0_node_ptr_) 14307 | { 14308 | if (vec0_is_ivec) 14309 | vds_ = vec0_node_ptr_->vds(); 14310 | else 14311 | vds_ = vds_t(vec0_node_ptr_->base_size()); 14312 | 14313 | memory_context_ = make_memory_context(vec0_node_ptr_->vec_holder(), vds()); 14314 | } 14315 | 14316 | assert(valid()); 14317 | } 14318 | 14319 | ~unary_vector_node() 14320 | { 14321 | memory_context_.clear(); 14322 | } 14323 | 14324 | inline T value() const exprtk_override 14325 | { 14326 | branch()->value(); 14327 | 14328 | const T* vec0 = vec0_node_ptr_->vds().data(); 14329 | T* vec1 = vds().data(); 14330 | 14331 | loop_unroll::details lud(size()); 14332 | const T* upper_bound = vec0 + lud.upper_bound; 14333 | 14334 | while (vec0 < upper_bound) 14335 | { 14336 | #define exprtk_loop(N) \ 14337 | vec1[N] = Operation::process(vec0[N]); \ 14338 | 14339 | exprtk_loop( 0) exprtk_loop( 1) 14340 | exprtk_loop( 2) exprtk_loop( 3) 14341 | #ifndef exprtk_disable_superscalar_unroll 14342 | exprtk_loop( 4) exprtk_loop( 5) 14343 | exprtk_loop( 6) exprtk_loop( 7) 14344 | exprtk_loop( 8) exprtk_loop( 9) 14345 | exprtk_loop(10) exprtk_loop(11) 14346 | exprtk_loop(12) exprtk_loop(13) 14347 | exprtk_loop(14) exprtk_loop(15) 14348 | #endif 14349 | 14350 | vec0 += lud.batch_size; 14351 | vec1 += lud.batch_size; 14352 | } 14353 | 14354 | int i = 0; 14355 | 14356 | switch (lud.remainder) 14357 | { 14358 | #define case_stmt(N) \ 14359 | case N : { vec1[i] = Operation::process(vec0[i]); ++i; } \ 14360 | exprtk_fallthrough \ 14361 | 14362 | #ifndef exprtk_disable_superscalar_unroll 14363 | case_stmt(15) case_stmt(14) 14364 | case_stmt(13) case_stmt(12) 14365 | case_stmt(11) case_stmt(10) 14366 | case_stmt( 9) case_stmt( 8) 14367 | case_stmt( 7) case_stmt( 6) 14368 | case_stmt( 5) case_stmt( 4) 14369 | #endif 14370 | case_stmt( 3) case_stmt( 2) 14371 | case_stmt( 1) 14372 | default: break; 14373 | } 14374 | 14375 | #undef exprtk_loop 14376 | #undef case_stmt 14377 | 14378 | return (vds().data())[0]; 14379 | } 14380 | 14381 | vector_node_ptr vec() const exprtk_override 14382 | { 14383 | return memory_context_.temp_vec_node_; 14384 | } 14385 | 14386 | vector_node_ptr vec() exprtk_override 14387 | { 14388 | return memory_context_.temp_vec_node_; 14389 | } 14390 | 14391 | inline typename expression_node<T>::node_type type() const exprtk_override 14392 | { 14393 | return expression_node<T>::e_vecunaryop; 14394 | } 14395 | 14396 | inline bool valid() const exprtk_override 14397 | { 14398 | return vec0_node_ptr_ && unary_node<T>::valid(); 14399 | } 14400 | 14401 | std::size_t size() const exprtk_override 14402 | { 14403 | return std::min(vds().size(),vec0_node_ptr_->vec_holder().size()); 14404 | } 14405 | 14406 | std::size_t base_size() const exprtk_override 14407 | { 14408 | return vec0_node_ptr_->vec_holder().base_size(); 14409 | } 14410 | 14411 | vds_t& vds() exprtk_override 14412 | { 14413 | return vds_; 14414 | } 14415 | 14416 | const vds_t& vds() const exprtk_override 14417 | { 14418 | return vds_; 14419 | } 14420 | 14421 | private: 14422 | 14423 | vector_node_ptr vec0_node_ptr_; 14424 | vds_t vds_; 14425 | memory_context memory_context_; 14426 | }; 14427 | 14428 | template <typename T> 14429 | class conditional_vector_node exprtk_final 14430 | : public expression_node <T> 14431 | , public vector_interface<T> 14432 | { 14433 | public: 14434 | 14435 | typedef expression_node <T>* expression_ptr; 14436 | typedef vector_interface<T>* vec_interface_ptr; 14437 | typedef vector_node <T>* vector_node_ptr; 14438 | typedef vector_holder <T> vector_holder_t; 14439 | typedef vector_holder_t* vector_holder_ptr; 14440 | typedef vec_data_store <T> vds_t; 14441 | typedef memory_context_t<T> memory_context; 14442 | typedef std::pair<expression_ptr,bool> branch_t; 14443 | 14444 | conditional_vector_node(expression_ptr condition, 14445 | expression_ptr consequent, 14446 | expression_ptr alternative) 14447 | : consequent_node_ptr_ (0) 14448 | , alternative_node_ptr_(0) 14449 | , temp_vec_node_ (0) 14450 | , temp_ (0) 14451 | , result_vec_size_ (0) 14452 | , initialised_ (false) 14453 | { 14454 | construct_branch_pair(condition_ , condition ); 14455 | construct_branch_pair(consequent_ , consequent ); 14456 | construct_branch_pair(alternative_, alternative); 14457 | 14458 | if (details::is_ivector_node(consequent_.first)) 14459 | { 14460 | vec_interface_ptr ivec_ptr = dynamic_cast<vec_interface_ptr>(consequent_.first); 14461 | 14462 | if (0 != ivec_ptr) 14463 | { 14464 | consequent_node_ptr_ = ivec_ptr->vec(); 14465 | } 14466 | } 14467 | 14468 | if (details::is_ivector_node(alternative_.first)) 14469 | { 14470 | vec_interface_ptr ivec_ptr = dynamic_cast<vec_interface_ptr>(alternative_.first); 14471 | 14472 | if (0 != ivec_ptr) 14473 | { 14474 | alternative_node_ptr_ = ivec_ptr->vec(); 14475 | } 14476 | } 14477 | 14478 | if (consequent_node_ptr_ && alternative_node_ptr_) 14479 | { 14480 | const std::size_t vec_size = 14481 | std::max(consequent_node_ptr_ ->vec_holder().base_size(), 14482 | alternative_node_ptr_->vec_holder().base_size()); 14483 | 14484 | vds_ = vds_t(vec_size); 14485 | memory_context_ = make_memory_context( 14486 | consequent_node_ptr_ ->vec_holder(), 14487 | alternative_node_ptr_->vec_holder(), 14488 | vds()); 14489 | 14490 | initialised_ = (vec_size > 0); 14491 | } 14492 | 14493 | assert(initialised_); 14494 | } 14495 | 14496 | ~conditional_vector_node() 14497 | { 14498 | memory_context_.clear(); 14499 | } 14500 | 14501 | inline T value() const exprtk_override 14502 | { 14503 | T result = T(0); 14504 | T* source_vector = 0; 14505 | T* result_vector = vds().data(); 14506 | 14507 | if (is_true(condition_)) 14508 | { 14509 | result = consequent_.first->value(); 14510 | source_vector = consequent_node_ptr_->vds().data(); 14511 | result_vec_size_ = consequent_node_ptr_->size(); 14512 | } 14513 | else 14514 | { 14515 | result = alternative_.first->value(); 14516 | source_vector = alternative_node_ptr_->vds().data(); 14517 | result_vec_size_ = alternative_node_ptr_->size(); 14518 | } 14519 | 14520 | const std::size_t copy_size = std::min(result_vec_size_, vds().size()); 14521 | 14522 | for (std::size_t i = 0; i < copy_size; ++i) 14523 | { 14524 | result_vector[i] = source_vector[i]; 14525 | } 14526 | 14527 | return result; 14528 | } 14529 | 14530 | vector_node_ptr vec() const exprtk_override 14531 | { 14532 | return memory_context_.temp_vec_node_; 14533 | } 14534 | 14535 | vector_node_ptr vec() exprtk_override 14536 | { 14537 | return memory_context_.temp_vec_node_; 14538 | } 14539 | 14540 | inline typename expression_node<T>::node_type type() const exprtk_override 14541 | { 14542 | return expression_node<T>::e_vecondition; 14543 | } 14544 | 14545 | inline bool valid() const exprtk_override 14546 | { 14547 | return 14548 | initialised_ && 14549 | condition_ .first && condition_ .first->valid() && 14550 | consequent_ .first && consequent_ .first->valid() && 14551 | alternative_.first && alternative_.first->valid() && 14552 | size() <= base_size(); 14553 | } 14554 | 14555 | std::size_t size() const exprtk_override 14556 | { 14557 | return result_vec_size_; 14558 | } 14559 | 14560 | std::size_t base_size() const exprtk_override 14561 | { 14562 | return std::min( 14563 | consequent_node_ptr_ ->vec_holder().base_size(), 14564 | alternative_node_ptr_->vec_holder().base_size()); 14565 | } 14566 | 14567 | vds_t& vds() exprtk_override 14568 | { 14569 | return vds_; 14570 | } 14571 | 14572 | const vds_t& vds() const exprtk_override 14573 | { 14574 | return vds_; 14575 | } 14576 | 14577 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 14578 | { 14579 | expression_node<T>::ndb_t::collect(condition_ , node_delete_list); 14580 | expression_node<T>::ndb_t::collect(consequent_ , node_delete_list); 14581 | expression_node<T>::ndb_t::collect(alternative_ , node_delete_list); 14582 | } 14583 | 14584 | std::size_t node_depth() const exprtk_override 14585 | { 14586 | return expression_node<T>::ndb_t::compute_node_depth 14587 | (condition_, consequent_, alternative_); 14588 | } 14589 | 14590 | private: 14591 | 14592 | branch_t condition_; 14593 | branch_t consequent_; 14594 | branch_t alternative_; 14595 | vector_node_ptr consequent_node_ptr_; 14596 | vector_node_ptr alternative_node_ptr_; 14597 | vector_node_ptr temp_vec_node_; 14598 | vector_holder_ptr temp_; 14599 | vds_t vds_; 14600 | mutable std::size_t result_vec_size_; 14601 | bool initialised_; 14602 | memory_context memory_context_; 14603 | }; 14604 | 14605 | template <typename T> 14606 | class scand_node exprtk_final : public binary_node<T> 14607 | { 14608 | public: 14609 | 14610 | typedef expression_node<T>* expression_ptr; 14611 | using binary_node<T>::branch; 14612 | 14613 | scand_node(const operator_type& opr, 14614 | expression_ptr branch0, 14615 | expression_ptr branch1) 14616 | : binary_node<T>(opr, branch0, branch1) 14617 | { 14618 | assert(binary_node<T>::valid()); 14619 | } 14620 | 14621 | inline T value() const exprtk_override 14622 | { 14623 | return ( 14624 | std::not_equal_to<T>() 14625 | (T(0),branch(0)->value()) && 14626 | std::not_equal_to<T>() 14627 | (T(0),branch(1)->value()) 14628 | ) ? T(1) : T(0); 14629 | } 14630 | }; 14631 | 14632 | template <typename T> 14633 | class scor_node exprtk_final : public binary_node<T> 14634 | { 14635 | public: 14636 | 14637 | typedef expression_node<T>* expression_ptr; 14638 | using binary_node<T>::branch; 14639 | 14640 | scor_node(const operator_type& opr, 14641 | expression_ptr branch0, 14642 | expression_ptr branch1) 14643 | : binary_node<T>(opr, branch0, branch1) 14644 | { 14645 | assert(binary_node<T>::valid()); 14646 | } 14647 | 14648 | inline T value() const exprtk_override 14649 | { 14650 | return ( 14651 | std::not_equal_to<T>() 14652 | (T(0),branch(0)->value()) || 14653 | std::not_equal_to<T>() 14654 | (T(0),branch(1)->value()) 14655 | ) ? T(1) : T(0); 14656 | } 14657 | }; 14658 | 14659 | template <typename T, typename IFunction, std::size_t N> 14660 | class function_N_node exprtk_final : public expression_node<T> 14661 | { 14662 | public: 14663 | 14664 | // Function of N parameters. 14665 | typedef expression_node<T>* expression_ptr; 14666 | typedef std::pair<expression_ptr,bool> branch_t; 14667 | typedef IFunction ifunction; 14668 | 14669 | explicit function_N_node(ifunction* func) 14670 | : function_((N == func->param_count) ? func : reinterpret_cast<ifunction*>(0)) 14671 | , parameter_count_(func->param_count) 14672 | , initialised_(false) 14673 | {} 14674 | 14675 | template <std::size_t NumBranches> 14676 | bool init_branches(expression_ptr (&b)[NumBranches]) 14677 | { 14678 | // Needed for incompetent and broken msvc compiler versions 14679 | #ifdef _MSC_VER 14680 | #pragma warning(push) 14681 | #pragma warning(disable: 4127) 14682 | #endif 14683 | 14684 | if (N != NumBranches) 14685 | { 14686 | return false; 14687 | } 14688 | 14689 | for (std::size_t i = 0; i < NumBranches; ++i) 14690 | { 14691 | if (b[i] && b[i]->valid()) 14692 | branch_[i] = std::make_pair(b[i],branch_deletable(b[i])); 14693 | else 14694 | return false; 14695 | } 14696 | 14697 | initialised_ = function_; 14698 | assert(valid()); 14699 | return initialised_; 14700 | 14701 | #ifdef _MSC_VER 14702 | #pragma warning(pop) 14703 | #endif 14704 | } 14705 | 14706 | inline bool operator <(const function_N_node<T,IFunction,N>& fn) const 14707 | { 14708 | return this < (&fn); 14709 | } 14710 | 14711 | inline T value() const exprtk_override 14712 | { 14713 | // Needed for incompetent and broken msvc compiler versions 14714 | #ifdef _MSC_VER 14715 | #pragma warning(push) 14716 | #pragma warning(disable: 4127) 14717 | #endif 14718 | 14719 | T v[N]; 14720 | evaluate_branches<T,N>::execute(v,branch_); 14721 | return invoke<T,N>::execute(*function_,v); 14722 | 14723 | #ifdef _MSC_VER 14724 | #pragma warning(pop) 14725 | #endif 14726 | } 14727 | 14728 | inline typename expression_node<T>::node_type type() const exprtk_override 14729 | { 14730 | return expression_node<T>::e_function; 14731 | } 14732 | 14733 | inline bool valid() const exprtk_override 14734 | { 14735 | return initialised_; 14736 | } 14737 | 14738 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 14739 | { 14740 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 14741 | } 14742 | 14743 | std::size_t node_depth() const exprtk_override 14744 | { 14745 | return expression_node<T>::ndb_t::template compute_node_depth<N>(branch_); 14746 | } 14747 | 14748 | template <typename T_, std::size_t BranchCount> 14749 | struct evaluate_branches 14750 | { 14751 | static inline void execute(T_ (&v)[BranchCount], const branch_t (&b)[BranchCount]) 14752 | { 14753 | for (std::size_t i = 0; i < BranchCount; ++i) 14754 | { 14755 | v[i] = b[i].first->value(); 14756 | } 14757 | } 14758 | }; 14759 | 14760 | template <typename T_> 14761 | struct evaluate_branches <T_,6> 14762 | { 14763 | static inline void execute(T_ (&v)[6], const branch_t (&b)[6]) 14764 | { 14765 | v[0] = b[0].first->value(); 14766 | v[1] = b[1].first->value(); 14767 | v[2] = b[2].first->value(); 14768 | v[3] = b[3].first->value(); 14769 | v[4] = b[4].first->value(); 14770 | v[5] = b[5].first->value(); 14771 | } 14772 | }; 14773 | 14774 | template <typename T_> 14775 | struct evaluate_branches <T_,5> 14776 | { 14777 | static inline void execute(T_ (&v)[5], const branch_t (&b)[5]) 14778 | { 14779 | v[0] = b[0].first->value(); 14780 | v[1] = b[1].first->value(); 14781 | v[2] = b[2].first->value(); 14782 | v[3] = b[3].first->value(); 14783 | v[4] = b[4].first->value(); 14784 | } 14785 | }; 14786 | 14787 | template <typename T_> 14788 | struct evaluate_branches <T_,4> 14789 | { 14790 | static inline void execute(T_ (&v)[4], const branch_t (&b)[4]) 14791 | { 14792 | v[0] = b[0].first->value(); 14793 | v[1] = b[1].first->value(); 14794 | v[2] = b[2].first->value(); 14795 | v[3] = b[3].first->value(); 14796 | } 14797 | }; 14798 | 14799 | template <typename T_> 14800 | struct evaluate_branches <T_,3> 14801 | { 14802 | static inline void execute(T_ (&v)[3], const branch_t (&b)[3]) 14803 | { 14804 | v[0] = b[0].first->value(); 14805 | v[1] = b[1].first->value(); 14806 | v[2] = b[2].first->value(); 14807 | } 14808 | }; 14809 | 14810 | template <typename T_> 14811 | struct evaluate_branches <T_,2> 14812 | { 14813 | static inline void execute(T_ (&v)[2], const branch_t (&b)[2]) 14814 | { 14815 | v[0] = b[0].first->value(); 14816 | v[1] = b[1].first->value(); 14817 | } 14818 | }; 14819 | 14820 | template <typename T_> 14821 | struct evaluate_branches <T_,1> 14822 | { 14823 | static inline void execute(T_ (&v)[1], const branch_t (&b)[1]) 14824 | { 14825 | v[0] = b[0].first->value(); 14826 | } 14827 | }; 14828 | 14829 | template <typename T_, std::size_t ParamCount> 14830 | struct invoke { static inline T execute(ifunction&, branch_t (&)[ParamCount]) { return std::numeric_limits<T_>::quiet_NaN(); } }; 14831 | 14832 | template <typename T_> 14833 | struct invoke<T_,20> 14834 | { 14835 | static inline T_ execute(ifunction& f, T_ (&v)[20]) 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],v[12],v[13],v[14],v[15],v[16],v[17],v[18],v[19]); } 14837 | }; 14838 | 14839 | template <typename T_> 14840 | struct invoke<T_,19> 14841 | { 14842 | static inline T_ execute(ifunction& f, T_ (&v)[19]) 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],v[11],v[12],v[13],v[14],v[15],v[16],v[17],v[18]); } 14844 | }; 14845 | 14846 | template <typename T_> 14847 | struct invoke<T_,18> 14848 | { 14849 | static inline T_ execute(ifunction& f, T_ (&v)[18]) 14850 | { 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]); } 14851 | }; 14852 | 14853 | template <typename T_> 14854 | struct invoke<T_,17> 14855 | { 14856 | static inline T_ execute(ifunction& f, T_ (&v)[17]) 14857 | { 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]); } 14858 | }; 14859 | 14860 | template <typename T_> 14861 | struct invoke<T_,16> 14862 | { 14863 | static inline T_ execute(ifunction& f, T_ (&v)[16]) 14864 | { 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]); } 14865 | }; 14866 | 14867 | template <typename T_> 14868 | struct invoke<T_,15> 14869 | { 14870 | static inline T_ execute(ifunction& f, T_ (&v)[15]) 14871 | { 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]); } 14872 | }; 14873 | 14874 | template <typename T_> 14875 | struct invoke<T_,14> 14876 | { 14877 | static inline T_ execute(ifunction& f, T_ (&v)[14]) 14878 | { 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]); } 14879 | }; 14880 | 14881 | template <typename T_> 14882 | struct invoke<T_,13> 14883 | { 14884 | static inline T_ execute(ifunction& f, T_ (&v)[13]) 14885 | { 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]); } 14886 | }; 14887 | 14888 | template <typename T_> 14889 | struct invoke<T_,12> 14890 | { 14891 | static inline T_ execute(ifunction& f, T_ (&v)[12]) 14892 | { 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]); } 14893 | }; 14894 | 14895 | template <typename T_> 14896 | struct invoke<T_,11> 14897 | { 14898 | static inline T_ execute(ifunction& f, T_ (&v)[11]) 14899 | { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9], v[10]); } 14900 | }; 14901 | 14902 | template <typename T_> 14903 | struct invoke<T_,10> 14904 | { 14905 | static inline T_ execute(ifunction& f, T_ (&v)[10]) 14906 | { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9]); } 14907 | }; 14908 | 14909 | template <typename T_> 14910 | struct invoke<T_,9> 14911 | { 14912 | static inline T_ execute(ifunction& f, T_ (&v)[9]) 14913 | { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8]); } 14914 | }; 14915 | 14916 | template <typename T_> 14917 | struct invoke<T_,8> 14918 | { 14919 | static inline T_ execute(ifunction& f, T_ (&v)[8]) 14920 | { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]); } 14921 | }; 14922 | 14923 | template <typename T_> 14924 | struct invoke<T_,7> 14925 | { 14926 | static inline T_ execute(ifunction& f, T_ (&v)[7]) 14927 | { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6]); } 14928 | }; 14929 | 14930 | template <typename T_> 14931 | struct invoke<T_,6> 14932 | { 14933 | static inline T_ execute(ifunction& f, T_ (&v)[6]) 14934 | { return f(v[0], v[1], v[2], v[3], v[4], v[5]); } 14935 | }; 14936 | 14937 | template <typename T_> 14938 | struct invoke<T_,5> 14939 | { 14940 | static inline T_ execute(ifunction& f, T_ (&v)[5]) 14941 | { return f(v[0], v[1], v[2], v[3], v[4]); } 14942 | }; 14943 | 14944 | template <typename T_> 14945 | struct invoke<T_,4> 14946 | { 14947 | static inline T_ execute(ifunction& f, T_ (&v)[4]) 14948 | { return f(v[0], v[1], v[2], v[3]); } 14949 | }; 14950 | 14951 | template <typename T_> 14952 | struct invoke<T_,3> 14953 | { 14954 | static inline T_ execute(ifunction& f, T_ (&v)[3]) 14955 | { return f(v[0], v[1], v[2]); } 14956 | }; 14957 | 14958 | template <typename T_> 14959 | struct invoke<T_,2> 14960 | { 14961 | static inline T_ execute(ifunction& f, T_ (&v)[2]) 14962 | { return f(v[0], v[1]); } 14963 | }; 14964 | 14965 | template <typename T_> 14966 | struct invoke<T_,1> 14967 | { 14968 | static inline T_ execute(ifunction& f, T_ (&v)[1]) 14969 | { return f(v[0]); } 14970 | }; 14971 | 14972 | private: 14973 | 14974 | ifunction* function_; 14975 | std::size_t parameter_count_; 14976 | branch_t branch_[N]; 14977 | bool initialised_; 14978 | }; 14979 | 14980 | template <typename T, typename IFunction> 14981 | class function_N_node<T,IFunction,0> exprtk_final : public expression_node<T> 14982 | { 14983 | public: 14984 | 14985 | typedef expression_node<T>* expression_ptr; 14986 | typedef IFunction ifunction; 14987 | 14988 | explicit function_N_node(ifunction* func) 14989 | : function_((0 == func->param_count) ? func : reinterpret_cast<ifunction*>(0)) 14990 | { 14991 | assert(valid()); 14992 | } 14993 | 14994 | inline bool operator <(const function_N_node<T,IFunction,0>& fn) const 14995 | { 14996 | return this < (&fn); 14997 | } 14998 | 14999 | inline T value() const exprtk_override 15000 | { 15001 | return (*function_)(); 15002 | } 15003 | 15004 | inline typename expression_node<T>::node_type type() const exprtk_override 15005 | { 15006 | return expression_node<T>::e_function; 15007 | } 15008 | 15009 | inline bool valid() const exprtk_override 15010 | { 15011 | return function_; 15012 | } 15013 | 15014 | private: 15015 | 15016 | ifunction* function_; 15017 | }; 15018 | 15019 | template <typename T, typename VarArgFunction> 15020 | class vararg_function_node exprtk_final : public expression_node<T> 15021 | { 15022 | public: 15023 | 15024 | typedef expression_node<T>* expression_ptr; 15025 | 15026 | vararg_function_node(VarArgFunction* func, 15027 | const std::vector<expression_ptr>& arg_list) 15028 | : function_(func) 15029 | , arg_list_(arg_list) 15030 | { 15031 | value_list_.resize(arg_list.size(),std::numeric_limits<T>::quiet_NaN()); 15032 | assert(valid()); 15033 | } 15034 | 15035 | inline bool operator <(const vararg_function_node<T,VarArgFunction>& fn) const 15036 | { 15037 | return this < (&fn); 15038 | } 15039 | 15040 | inline T value() const exprtk_override 15041 | { 15042 | populate_value_list(); 15043 | return (*function_)(value_list_); 15044 | } 15045 | 15046 | inline typename expression_node<T>::node_type type() const exprtk_override 15047 | { 15048 | return expression_node<T>::e_vafunction; 15049 | } 15050 | 15051 | inline bool valid() const exprtk_override 15052 | { 15053 | return function_; 15054 | } 15055 | 15056 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 15057 | { 15058 | for (std::size_t i = 0; i < arg_list_.size(); ++i) 15059 | { 15060 | if (arg_list_[i] && !details::is_variable_node(arg_list_[i])) 15061 | { 15062 | node_delete_list.push_back(&arg_list_[i]); 15063 | } 15064 | } 15065 | } 15066 | 15067 | std::size_t node_depth() const exprtk_override 15068 | { 15069 | return expression_node<T>::ndb_t::compute_node_depth(arg_list_); 15070 | } 15071 | 15072 | private: 15073 | 15074 | inline void populate_value_list() const 15075 | { 15076 | for (std::size_t i = 0; i < arg_list_.size(); ++i) 15077 | { 15078 | value_list_[i] = arg_list_[i]->value(); 15079 | } 15080 | } 15081 | 15082 | VarArgFunction* function_; 15083 | std::vector<expression_ptr> arg_list_; 15084 | mutable std::vector<T> value_list_; 15085 | }; 15086 | 15087 | template <typename T, typename GenericFunction> 15088 | class generic_function_node : public expression_node<T> 15089 | { 15090 | public: 15091 | 15092 | typedef type_store<T> type_store_t; 15093 | typedef expression_node<T>* expression_ptr; 15094 | typedef variable_node<T> variable_node_t; 15095 | typedef vector_node<T> vector_node_t; 15096 | typedef variable_node_t* variable_node_ptr_t; 15097 | typedef vector_node_t* vector_node_ptr_t; 15098 | typedef range_interface<T> range_interface_t; 15099 | typedef range_data_type<T> range_data_type_t; 15100 | typedef typename range_interface<T>::range_t range_t; 15101 | 15102 | typedef std::pair<expression_ptr,bool> branch_t; 15103 | typedef vector_holder<T>* vh_t; 15104 | typedef vector_view<T>* vecview_t; 15105 | 15106 | typedef std::vector<T> tmp_vs_t; 15107 | typedef std::vector<type_store_t> typestore_list_t; 15108 | typedef std::vector<range_data_type_t> range_list_t; 15109 | 15110 | explicit generic_function_node(const std::vector<expression_ptr>& arg_list, 15111 | GenericFunction* func = reinterpret_cast<GenericFunction*>(0)) 15112 | : function_(func) 15113 | , arg_list_(arg_list) 15114 | {} 15115 | 15116 | virtual ~generic_function_node() 15117 | { 15118 | for (std::size_t i = 0; i < vv_list_.size(); ++i) 15119 | { 15120 | vecview_t& vv = vv_list_[i]; 15121 | if (vv) 15122 | { 15123 | if (typestore_list_[i].vec_data) 15124 | { 15125 | vv->remove_ref(&typestore_list_[i].vec_data); 15126 | } 15127 | 15128 | vv->remove_size_ref(&typestore_list_[i].size); 15129 | typestore_list_[i].vec_data = 0; 15130 | } 15131 | } 15132 | } 15133 | 15134 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 15135 | { 15136 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 15137 | } 15138 | 15139 | std::size_t node_depth() const exprtk_override exprtk_final 15140 | { 15141 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 15142 | } 15143 | 15144 | virtual bool init_branches() 15145 | { 15146 | expr_as_vec1_store_.resize(arg_list_.size(), T(0) ); 15147 | typestore_list_ .resize(arg_list_.size(), type_store_t() ); 15148 | range_list_ .resize(arg_list_.size(), range_data_type_t()); 15149 | branch_ .resize(arg_list_.size(), branch_t(reinterpret_cast<expression_ptr>(0),false)); 15150 | vv_list_ .resize(arg_list_.size(), vecview_t(0)); 15151 | 15152 | for (std::size_t i = 0; i < arg_list_.size(); ++i) 15153 | { 15154 | type_store_t& ts = typestore_list_[i]; 15155 | 15156 | if (0 == arg_list_[i]) 15157 | return false; 15158 | else if (is_ivector_node(arg_list_[i])) 15159 | { 15160 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 15161 | 15162 | if (0 == (vi = dynamic_cast<vector_interface<T>*>(arg_list_[i]))) 15163 | return false; 15164 | 15165 | ts.size = vi->size(); 15166 | ts.data = vi->vds().data(); 15167 | ts.type = type_store_t::e_vector; 15168 | ts.ivec = vi; 15169 | 15170 | if (expression_node<T>::e_vecondition == arg_list_[i]->type()) 15171 | { 15172 | vec_size_refresh_list_.push_back(i); 15173 | } 15174 | 15175 | if ( 15176 | vi->vec()->vec_holder().rebaseable() && 15177 | vi->vec()->vec_holder().rebaseable_instance() 15178 | ) 15179 | { 15180 | vv_list_[i] = vi->vec()->vec_holder().rebaseable_instance(); 15181 | vv_list_[i]->set_size_ref(&ts.size); 15182 | 15183 | if (!amalgamated_vecop(arg_list_[i])) 15184 | { 15185 | vv_list_[i]->set_ref(&ts.vec_data); 15186 | } 15187 | } 15188 | } 15189 | #ifndef exprtk_disable_string_capabilities 15190 | else if (is_generally_string_node(arg_list_[i])) 15191 | { 15192 | string_base_node<T>* sbn = reinterpret_cast<string_base_node<T>*>(0); 15193 | 15194 | if (0 == (sbn = dynamic_cast<string_base_node<T>*>(arg_list_[i]))) 15195 | return false; 15196 | 15197 | ts.size = sbn->size(); 15198 | ts.data = reinterpret_cast<void*>(const_cast<char_ptr>(sbn->base())); 15199 | ts.type = type_store_t::e_string; 15200 | 15201 | range_list_[i].data = ts.data; 15202 | range_list_[i].size = ts.size; 15203 | range_list_[i].type_size = sizeof(char); 15204 | range_list_[i].str_node = sbn; 15205 | 15206 | range_interface_t* ri = reinterpret_cast<range_interface_t*>(0); 15207 | 15208 | if (0 == (ri = dynamic_cast<range_interface_t*>(arg_list_[i]))) 15209 | return false; 15210 | 15211 | const range_t& rp = ri->range_ref(); 15212 | 15213 | if ( 15214 | rp.const_range() && 15215 | is_const_string_range_node(arg_list_[i]) 15216 | ) 15217 | { 15218 | ts.size = rp.const_size(); 15219 | ts.data = static_cast<char_ptr>(ts.data) + rp.n0_c.second; 15220 | range_list_[i].range = reinterpret_cast<range_t*>(0); 15221 | } 15222 | else 15223 | { 15224 | range_list_[i].range = &(ri->range_ref()); 15225 | range_param_list_.push_back(i); 15226 | } 15227 | } 15228 | #endif 15229 | else if (is_variable_node(arg_list_[i])) 15230 | { 15231 | variable_node_ptr_t var = variable_node_ptr_t(0); 15232 | 15233 | if (0 == (var = dynamic_cast<variable_node_ptr_t>(arg_list_[i]))) 15234 | return false; 15235 | 15236 | ts.size = 1; 15237 | ts.data = &var->ref(); 15238 | ts.type = type_store_t::e_scalar; 15239 | } 15240 | else 15241 | { 15242 | ts.size = 1; 15243 | ts.data = reinterpret_cast<void*>(&expr_as_vec1_store_[i]); 15244 | ts.type = type_store_t::e_scalar; 15245 | } 15246 | 15247 | branch_[i] = std::make_pair(arg_list_[i],branch_deletable(arg_list_[i])); 15248 | } 15249 | 15250 | return true; 15251 | } 15252 | 15253 | inline bool operator <(const generic_function_node<T,GenericFunction>& fn) const 15254 | { 15255 | return this < (&fn); 15256 | } 15257 | 15258 | inline T value() const exprtk_override 15259 | { 15260 | if (populate_value_list()) 15261 | { 15262 | typedef typename GenericFunction::parameter_list_t parameter_list_t; 15263 | 15264 | return (*function_)(parameter_list_t(typestore_list_)); 15265 | } 15266 | 15267 | return std::numeric_limits<T>::quiet_NaN(); 15268 | } 15269 | 15270 | inline typename expression_node<T>::node_type type() const exprtk_override 15271 | { 15272 | return expression_node<T>::e_genfunction; 15273 | } 15274 | 15275 | inline bool valid() const exprtk_override 15276 | { 15277 | return function_; 15278 | } 15279 | 15280 | protected: 15281 | 15282 | inline virtual bool populate_value_list() const 15283 | { 15284 | assert(branch_.size() == typestore_list_.size()); 15285 | 15286 | for (std::size_t i = 0; i < branch_.size(); ++i) 15287 | { 15288 | expr_as_vec1_store_[i] = branch_[i].first->value(); 15289 | } 15290 | 15291 | if (!vec_size_refresh_list_.empty()) 15292 | { 15293 | for (std::size_t i = 0; i < vec_size_refresh_list_.size(); ++i) 15294 | { 15295 | const std::size_t index = vec_size_refresh_list_[i]; 15296 | type_store_t& ts = typestore_list_[index]; 15297 | ts.size = ts.ivec->size(); 15298 | } 15299 | } 15300 | 15301 | if (!range_param_list_.empty()) 15302 | { 15303 | assert(range_param_list_.size() <= branch_.size()); 15304 | 15305 | for (std::size_t i = 0; i < range_param_list_.size(); ++i) 15306 | { 15307 | const std::size_t index = range_param_list_[i]; 15308 | range_data_type_t& rdt = range_list_[index]; 15309 | 15310 | const range_t& rp = (*rdt.range); 15311 | std::size_t r0 = 0; 15312 | std::size_t r1 = 0; 15313 | 15314 | const std::size_t data_size = 15315 | #ifndef exprtk_disable_string_capabilities 15316 | rdt.str_node ? rdt.str_node->size() : rdt.size; 15317 | #else 15318 | rdt.size; 15319 | #endif 15320 | 15321 | if (!rp(r0, r1, typename range_t::size_holder_t(data_size))) 15322 | { 15323 | return false; 15324 | } 15325 | 15326 | type_store_t& ts = typestore_list_[index]; 15327 | 15328 | ts.size = rp.cache_size(); 15329 | #ifndef exprtk_disable_string_capabilities 15330 | if (ts.type == type_store_t::e_string) 15331 | ts.data = const_cast<char_ptr>(rdt.str_node->base()) + rp.cache.first; 15332 | else 15333 | #endif 15334 | ts.data = static_cast<char_ptr>(rdt.data) + (rp.cache.first * rdt.type_size); 15335 | } 15336 | } 15337 | 15338 | return true; 15339 | } 15340 | 15341 | GenericFunction* function_; 15342 | mutable typestore_list_t typestore_list_; 15343 | 15344 | private: 15345 | 15346 | std::vector<expression_ptr> arg_list_; 15347 | std::vector<branch_t> branch_; 15348 | std::vector<vecview_t> vv_list_; 15349 | mutable tmp_vs_t expr_as_vec1_store_; 15350 | mutable range_list_t range_list_; 15351 | std::vector<std::size_t> range_param_list_; 15352 | std::vector<std::size_t> vec_size_refresh_list_; 15353 | }; 15354 | 15355 | #ifndef exprtk_disable_string_capabilities 15356 | template <typename T, typename StringFunction> 15357 | class string_function_node : public generic_function_node<T,StringFunction> 15358 | , public string_base_node<T> 15359 | , public range_interface <T> 15360 | { 15361 | public: 15362 | 15363 | typedef generic_function_node<T,StringFunction> gen_function_t; 15364 | typedef typename range_interface<T>::range_t range_t; 15365 | 15366 | string_function_node(StringFunction* func, 15367 | const std::vector<typename gen_function_t::expression_ptr>& arg_list) 15368 | : gen_function_t(arg_list,func) 15369 | { 15370 | range_.n0_c = std::make_pair<bool,std::size_t>(true,0); 15371 | range_.n1_c = std::make_pair<bool,std::size_t>(true,0); 15372 | range_.cache.first = range_.n0_c.second; 15373 | range_.cache.second = range_.n1_c.second; 15374 | assert(valid()); 15375 | } 15376 | 15377 | inline bool operator <(const string_function_node<T,StringFunction>& fn) const 15378 | { 15379 | return this < (&fn); 15380 | } 15381 | 15382 | inline T value() const exprtk_override 15383 | { 15384 | if (gen_function_t::populate_value_list()) 15385 | { 15386 | typedef typename StringFunction::parameter_list_t parameter_list_t; 15387 | 15388 | const T result = 15389 | (*gen_function_t::function_) 15390 | ( 15391 | ret_string_, 15392 | parameter_list_t(gen_function_t::typestore_list_) 15393 | ); 15394 | 15395 | range_.n1_c.second = ret_string_.size(); 15396 | range_.cache.second = range_.n1_c.second; 15397 | 15398 | return result; 15399 | } 15400 | 15401 | return std::numeric_limits<T>::quiet_NaN(); 15402 | } 15403 | 15404 | inline typename expression_node<T>::node_type type() const exprtk_override 15405 | { 15406 | return expression_node<T>::e_strfunction; 15407 | } 15408 | 15409 | inline bool valid() const exprtk_override 15410 | { 15411 | return gen_function_t::function_; 15412 | } 15413 | 15414 | std::string str() const exprtk_override 15415 | { 15416 | return ret_string_; 15417 | } 15418 | 15419 | char_cptr base() const exprtk_override 15420 | { 15421 | return &ret_string_[0]; 15422 | } 15423 | 15424 | std::size_t size() const exprtk_override 15425 | { 15426 | return ret_string_.size(); 15427 | } 15428 | 15429 | range_t& range_ref() exprtk_override 15430 | { 15431 | return range_; 15432 | } 15433 | 15434 | const range_t& range_ref() const exprtk_override 15435 | { 15436 | return range_; 15437 | } 15438 | 15439 | protected: 15440 | 15441 | mutable range_t range_; 15442 | mutable std::string ret_string_; 15443 | }; 15444 | #endif 15445 | 15446 | template <typename T, typename GenericFunction> 15447 | class multimode_genfunction_node : public generic_function_node<T,GenericFunction> 15448 | { 15449 | public: 15450 | 15451 | typedef generic_function_node<T,GenericFunction> gen_function_t; 15452 | typedef typename gen_function_t::range_t range_t; 15453 | 15454 | multimode_genfunction_node(GenericFunction* func, 15455 | const std::size_t& param_seq_index, 15456 | const std::vector<typename gen_function_t::expression_ptr>& arg_list) 15457 | : gen_function_t(arg_list,func) 15458 | , param_seq_index_(param_seq_index) 15459 | {} 15460 | 15461 | inline T value() const exprtk_override 15462 | { 15463 | assert(gen_function_t::valid()); 15464 | 15465 | if (gen_function_t::populate_value_list()) 15466 | { 15467 | typedef typename GenericFunction::parameter_list_t parameter_list_t; 15468 | 15469 | return 15470 | (*gen_function_t::function_) 15471 | ( 15472 | param_seq_index_, 15473 | parameter_list_t(gen_function_t::typestore_list_) 15474 | ); 15475 | } 15476 | 15477 | return std::numeric_limits<T>::quiet_NaN(); 15478 | } 15479 | 15480 | inline typename expression_node<T>::node_type type() const exprtk_override exprtk_final 15481 | { 15482 | return expression_node<T>::e_genfunction; 15483 | } 15484 | 15485 | private: 15486 | 15487 | std::size_t param_seq_index_; 15488 | }; 15489 | 15490 | #ifndef exprtk_disable_string_capabilities 15491 | template <typename T, typename StringFunction> 15492 | class multimode_strfunction_node exprtk_final : public string_function_node<T,StringFunction> 15493 | { 15494 | public: 15495 | 15496 | typedef string_function_node<T,StringFunction> str_function_t; 15497 | typedef typename str_function_t::range_t range_t; 15498 | 15499 | multimode_strfunction_node(StringFunction* func, 15500 | const std::size_t& param_seq_index, 15501 | const std::vector<typename str_function_t::expression_ptr>& arg_list) 15502 | : str_function_t(func,arg_list) 15503 | , param_seq_index_(param_seq_index) 15504 | {} 15505 | 15506 | inline T value() const exprtk_override 15507 | { 15508 | if (str_function_t::populate_value_list()) 15509 | { 15510 | typedef typename StringFunction::parameter_list_t parameter_list_t; 15511 | 15512 | const T result = 15513 | (*str_function_t::function_) 15514 | ( 15515 | param_seq_index_, 15516 | str_function_t::ret_string_, 15517 | parameter_list_t(str_function_t::typestore_list_) 15518 | ); 15519 | 15520 | str_function_t::range_.n1_c.second = str_function_t::ret_string_.size(); 15521 | str_function_t::range_.cache.second = str_function_t::range_.n1_c.second; 15522 | 15523 | return result; 15524 | } 15525 | 15526 | return std::numeric_limits<T>::quiet_NaN(); 15527 | } 15528 | 15529 | inline typename expression_node<T>::node_type type() const exprtk_override 15530 | { 15531 | return expression_node<T>::e_strfunction; 15532 | } 15533 | 15534 | private: 15535 | 15536 | const std::size_t param_seq_index_; 15537 | }; 15538 | #endif 15539 | 15540 | class return_exception {}; 15541 | 15542 | template <typename T> 15543 | class null_igenfunc 15544 | { 15545 | public: 15546 | 15547 | virtual ~null_igenfunc() 15548 | {} 15549 | 15550 | typedef type_store<T> generic_type; 15551 | typedef typename generic_type::parameter_list parameter_list_t; 15552 | 15553 | inline virtual T operator() (parameter_list_t) 15554 | { 15555 | return std::numeric_limits<T>::quiet_NaN(); 15556 | } 15557 | }; 15558 | 15559 | #ifndef exprtk_disable_return_statement 15560 | template <typename T> 15561 | class return_node exprtk_final : public generic_function_node<T,null_igenfunc<T> > 15562 | { 15563 | public: 15564 | 15565 | typedef results_context<T> results_context_t; 15566 | typedef null_igenfunc<T> igeneric_function_t; 15567 | typedef igeneric_function_t* igeneric_function_ptr; 15568 | typedef generic_function_node<T,igeneric_function_t> gen_function_t; 15569 | 15570 | return_node(const std::vector<typename gen_function_t::expression_ptr>& arg_list, 15571 | results_context_t& rc) 15572 | : gen_function_t (arg_list) 15573 | , results_context_(&rc) 15574 | { 15575 | assert(valid()); 15576 | } 15577 | 15578 | inline T value() const exprtk_override 15579 | { 15580 | if (gen_function_t::populate_value_list()) 15581 | { 15582 | prepare_typestore_list(); 15583 | 15584 | typedef typename type_store<T>::parameter_list parameter_list_t; 15585 | 15586 | results_context_-> 15587 | assign(parameter_list_t(gen_function_t::typestore_list_)); 15588 | 15589 | throw return_exception(); 15590 | } 15591 | 15592 | return std::numeric_limits<T>::quiet_NaN(); 15593 | } 15594 | 15595 | inline typename expression_node<T>::node_type type() const exprtk_override 15596 | { 15597 | return expression_node<T>::e_return; 15598 | } 15599 | 15600 | inline bool valid() const exprtk_override 15601 | { 15602 | return results_context_; 15603 | } 15604 | 15605 | private: 15606 | 15607 | void prepare_typestore_list() const 15608 | { 15609 | for (std::size_t i = 0; i < gen_function_t::typestore_list_.size(); ++i) 15610 | { 15611 | typename gen_function_t::type_store_t& ts = gen_function_t::typestore_list_[i]; 15612 | 15613 | if (ts.ivec) 15614 | { 15615 | ts.size = ts.ivec->size(); 15616 | } 15617 | } 15618 | } 15619 | 15620 | results_context_t* results_context_; 15621 | }; 15622 | 15623 | template <typename T> 15624 | class return_envelope_node exprtk_final : public expression_node<T> 15625 | { 15626 | public: 15627 | 15628 | typedef expression_node<T>* expression_ptr; 15629 | typedef results_context<T> results_context_t; 15630 | typedef std::pair<expression_ptr,bool> branch_t; 15631 | 15632 | return_envelope_node(expression_ptr body, results_context_t& rc) 15633 | : results_context_(&rc ) 15634 | , return_invoked_ (false) 15635 | { 15636 | construct_branch_pair(body_, body); 15637 | assert(valid()); 15638 | } 15639 | 15640 | inline T value() const exprtk_override 15641 | { 15642 | try 15643 | { 15644 | return_invoked_ = false; 15645 | results_context_->clear(); 15646 | 15647 | return body_.first->value(); 15648 | } 15649 | catch(const return_exception&) 15650 | { 15651 | return_invoked_ = true; 15652 | 15653 | return std::numeric_limits<T>::quiet_NaN(); 15654 | } 15655 | } 15656 | 15657 | inline typename expression_node<T>::node_type type() const exprtk_override 15658 | { 15659 | return expression_node<T>::e_retenv; 15660 | } 15661 | 15662 | inline bool valid() const exprtk_override 15663 | { 15664 | return results_context_ && body_.first; 15665 | } 15666 | 15667 | inline bool* retinvk_ptr() 15668 | { 15669 | return &return_invoked_; 15670 | } 15671 | 15672 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 15673 | { 15674 | expression_node<T>::ndb_t::collect(body_, node_delete_list); 15675 | } 15676 | 15677 | std::size_t node_depth() const exprtk_override 15678 | { 15679 | return expression_node<T>::ndb_t::compute_node_depth(body_); 15680 | } 15681 | 15682 | private: 15683 | 15684 | results_context_t* results_context_; 15685 | mutable bool return_invoked_; 15686 | branch_t body_; 15687 | }; 15688 | #endif 15689 | 15690 | #define exprtk_define_unary_op(OpName) \ 15691 | template <typename T> \ 15692 | struct OpName##_op \ 15693 | { \ 15694 | typedef typename functor_t<T>::Type Type; \ 15695 | typedef typename expression_node<T>::node_type node_t; \ 15696 | \ 15697 | static inline T process(Type v) \ 15698 | { \ 15699 | return numeric:: OpName (v); \ 15700 | } \ 15701 | \ 15702 | static inline node_t type() \ 15703 | { \ 15704 | return expression_node<T>::e_##OpName; \ 15705 | } \ 15706 | \ 15707 | static inline details::operator_type operation() \ 15708 | { \ 15709 | return details::e_##OpName; \ 15710 | } \ 15711 | }; \ 15712 | 15713 | exprtk_define_unary_op(abs ) 15714 | exprtk_define_unary_op(acos ) 15715 | exprtk_define_unary_op(acosh) 15716 | exprtk_define_unary_op(asin ) 15717 | exprtk_define_unary_op(asinh) 15718 | exprtk_define_unary_op(atan ) 15719 | exprtk_define_unary_op(atanh) 15720 | exprtk_define_unary_op(ceil ) 15721 | exprtk_define_unary_op(cos ) 15722 | exprtk_define_unary_op(cosh ) 15723 | exprtk_define_unary_op(cot ) 15724 | exprtk_define_unary_op(csc ) 15725 | exprtk_define_unary_op(d2g ) 15726 | exprtk_define_unary_op(d2r ) 15727 | exprtk_define_unary_op(erf ) 15728 | exprtk_define_unary_op(erfc ) 15729 | exprtk_define_unary_op(exp ) 15730 | exprtk_define_unary_op(expm1) 15731 | exprtk_define_unary_op(floor) 15732 | exprtk_define_unary_op(frac ) 15733 | exprtk_define_unary_op(g2d ) 15734 | exprtk_define_unary_op(log ) 15735 | exprtk_define_unary_op(log10) 15736 | exprtk_define_unary_op(log2 ) 15737 | exprtk_define_unary_op(log1p) 15738 | exprtk_define_unary_op(ncdf ) 15739 | exprtk_define_unary_op(neg ) 15740 | exprtk_define_unary_op(notl ) 15741 | exprtk_define_unary_op(pos ) 15742 | exprtk_define_unary_op(r2d ) 15743 | exprtk_define_unary_op(round) 15744 | exprtk_define_unary_op(sec ) 15745 | exprtk_define_unary_op(sgn ) 15746 | exprtk_define_unary_op(sin ) 15747 | exprtk_define_unary_op(sinc ) 15748 | exprtk_define_unary_op(sinh ) 15749 | exprtk_define_unary_op(sqrt ) 15750 | exprtk_define_unary_op(tan ) 15751 | exprtk_define_unary_op(tanh ) 15752 | exprtk_define_unary_op(trunc) 15753 | #undef exprtk_define_unary_op 15754 | 15755 | template <typename T> 15756 | struct opr_base 15757 | { 15758 | typedef typename details::functor_t<T>::Type Type; 15759 | typedef typename details::functor_t<T>::RefType RefType; 15760 | typedef typename details::functor_t<T> functor_t; 15761 | typedef typename functor_t::qfunc_t quaternary_functor_t; 15762 | typedef typename functor_t::tfunc_t trinary_functor_t; 15763 | typedef typename functor_t::bfunc_t binary_functor_t; 15764 | typedef typename functor_t::ufunc_t unary_functor_t; 15765 | }; 15766 | 15767 | template <typename T> 15768 | struct add_op : public opr_base<T> 15769 | { 15770 | typedef typename opr_base<T>::Type Type; 15771 | typedef typename opr_base<T>::RefType RefType; 15772 | 15773 | static inline T process(Type t1, Type t2) { return t1 + t2; } 15774 | static inline T process(Type t1, Type t2, Type t3) { return t1 + t2 + t3; } 15775 | static inline void assign(RefType t1, Type t2) { t1 += t2; } 15776 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_add; } 15777 | static inline details::operator_type operation() { return details::e_add; } 15778 | }; 15779 | 15780 | template <typename T> 15781 | struct mul_op : public opr_base<T> 15782 | { 15783 | typedef typename opr_base<T>::Type Type; 15784 | typedef typename opr_base<T>::RefType RefType; 15785 | 15786 | static inline T process(Type t1, Type t2) { return t1 * t2; } 15787 | static inline T process(Type t1, Type t2, Type t3) { return t1 * t2 * t3; } 15788 | static inline void assign(RefType t1, Type t2) { t1 *= t2; } 15789 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_mul; } 15790 | static inline details::operator_type operation() { return details::e_mul; } 15791 | }; 15792 | 15793 | template <typename T> 15794 | struct sub_op : public opr_base<T> 15795 | { 15796 | typedef typename opr_base<T>::Type Type; 15797 | typedef typename opr_base<T>::RefType RefType; 15798 | 15799 | static inline T process(Type t1, Type t2) { return t1 - t2; } 15800 | static inline T process(Type t1, Type t2, Type t3) { return t1 - t2 - t3; } 15801 | static inline void assign(RefType t1, Type t2) { t1 -= t2; } 15802 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_sub; } 15803 | static inline details::operator_type operation() { return details::e_sub; } 15804 | }; 15805 | 15806 | template <typename T> 15807 | struct div_op : public opr_base<T> 15808 | { 15809 | typedef typename opr_base<T>::Type Type; 15810 | typedef typename opr_base<T>::RefType RefType; 15811 | 15812 | static inline T process(Type t1, Type t2) { return t1 / t2; } 15813 | static inline T process(Type t1, Type t2, Type t3) { return t1 / t2 / t3; } 15814 | static inline void assign(RefType t1, Type t2) { t1 /= t2; } 15815 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_div; } 15816 | static inline details::operator_type operation() { return details::e_div; } 15817 | }; 15818 | 15819 | template <typename T> 15820 | struct mod_op : public opr_base<T> 15821 | { 15822 | typedef typename opr_base<T>::Type Type; 15823 | typedef typename opr_base<T>::RefType RefType; 15824 | 15825 | static inline T process(Type t1, Type t2) { return numeric::modulus<T>(t1,t2); } 15826 | static inline void assign(RefType t1, Type t2) { t1 = numeric::modulus<T>(t1,t2); } 15827 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_mod; } 15828 | static inline details::operator_type operation() { return details::e_mod; } 15829 | }; 15830 | 15831 | template <typename T> 15832 | struct pow_op : public opr_base<T> 15833 | { 15834 | typedef typename opr_base<T>::Type Type; 15835 | typedef typename opr_base<T>::RefType RefType; 15836 | 15837 | static inline T process(Type t1, Type t2) { return numeric::pow<T>(t1,t2); } 15838 | static inline void assign(RefType t1, Type t2) { t1 = numeric::pow<T>(t1,t2); } 15839 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_pow; } 15840 | static inline details::operator_type operation() { return details::e_pow; } 15841 | }; 15842 | 15843 | template <typename T> 15844 | struct lt_op : public opr_base<T> 15845 | { 15846 | typedef typename opr_base<T>::Type Type; 15847 | 15848 | static inline T process(Type t1, Type t2) { return ((t1 < t2) ? T(1) : T(0)); } 15849 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 < t2) ? T(1) : T(0)); } 15850 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_lt; } 15851 | static inline details::operator_type operation() { return details::e_lt; } 15852 | }; 15853 | 15854 | template <typename T> 15855 | struct lte_op : public opr_base<T> 15856 | { 15857 | typedef typename opr_base<T>::Type Type; 15858 | 15859 | static inline T process(Type t1, Type t2) { return ((t1 <= t2) ? T(1) : T(0)); } 15860 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 <= t2) ? T(1) : T(0)); } 15861 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_lte; } 15862 | static inline details::operator_type operation() { return details::e_lte; } 15863 | }; 15864 | 15865 | template <typename T> 15866 | struct gt_op : public opr_base<T> 15867 | { 15868 | typedef typename opr_base<T>::Type Type; 15869 | 15870 | static inline T process(Type t1, Type t2) { return ((t1 > t2) ? T(1) : T(0)); } 15871 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 > t2) ? T(1) : T(0)); } 15872 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_gt; } 15873 | static inline details::operator_type operation() { return details::e_gt; } 15874 | }; 15875 | 15876 | template <typename T> 15877 | struct gte_op : public opr_base<T> 15878 | { 15879 | typedef typename opr_base<T>::Type Type; 15880 | 15881 | static inline T process(Type t1, Type t2) { return ((t1 >= t2) ? T(1) : T(0)); } 15882 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 >= t2) ? T(1) : T(0)); } 15883 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_gte; } 15884 | static inline details::operator_type operation() { return details::e_gte; } 15885 | }; 15886 | 15887 | template <typename T> 15888 | struct eq_op : public opr_base<T> 15889 | { 15890 | typedef typename opr_base<T>::Type Type; 15891 | static inline T process(Type t1, Type t2) { return (std::equal_to<T>()(t1,t2) ? T(1) : T(0)); } 15892 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 == t2) ? T(1) : T(0)); } 15893 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_eq; } 15894 | static inline details::operator_type operation() { return details::e_eq; } 15895 | }; 15896 | 15897 | template <typename T> 15898 | struct equal_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::equal(t1,t2); } 15903 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 == t2) ? T(1) : T(0)); } 15904 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_eq; } 15905 | static inline details::operator_type operation() { return details::e_equal; } 15906 | }; 15907 | 15908 | template <typename T> 15909 | struct ne_op : public opr_base<T> 15910 | { 15911 | typedef typename opr_base<T>::Type Type; 15912 | 15913 | static inline T process(Type t1, Type t2) { return (std::not_equal_to<T>()(t1,t2) ? T(1) : T(0)); } 15914 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 != t2) ? T(1) : T(0)); } 15915 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_ne; } 15916 | static inline details::operator_type operation() { return details::e_ne; } 15917 | }; 15918 | 15919 | template <typename T> 15920 | struct and_op : public opr_base<T> 15921 | { 15922 | typedef typename opr_base<T>::Type Type; 15923 | 15924 | static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(1) : T(0); } 15925 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_and; } 15926 | static inline details::operator_type operation() { return details::e_and; } 15927 | }; 15928 | 15929 | template <typename T> 15930 | struct nand_op : public opr_base<T> 15931 | { 15932 | typedef typename opr_base<T>::Type Type; 15933 | 15934 | static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(0) : T(1); } 15935 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nand; } 15936 | static inline details::operator_type operation() { return details::e_nand; } 15937 | }; 15938 | 15939 | template <typename T> 15940 | struct or_op : public opr_base<T> 15941 | { 15942 | typedef typename opr_base<T>::Type Type; 15943 | 15944 | static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(1) : T(0); } 15945 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_or; } 15946 | static inline details::operator_type operation() { return details::e_or; } 15947 | }; 15948 | 15949 | template <typename T> 15950 | struct nor_op : public opr_base<T> 15951 | { 15952 | typedef typename opr_base<T>::Type Type; 15953 | 15954 | static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(0) : T(1); } 15955 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; } 15956 | static inline details::operator_type operation() { return details::e_nor; } 15957 | }; 15958 | 15959 | template <typename T> 15960 | struct xor_op : public opr_base<T> 15961 | { 15962 | typedef typename opr_base<T>::Type Type; 15963 | 15964 | static inline T process(Type t1, Type t2) { return numeric::xor_opr<T>(t1,t2); } 15965 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; } 15966 | static inline details::operator_type operation() { return details::e_xor; } 15967 | }; 15968 | 15969 | template <typename T> 15970 | struct xnor_op : public opr_base<T> 15971 | { 15972 | typedef typename opr_base<T>::Type Type; 15973 | 15974 | static inline T process(Type t1, Type t2) { return numeric::xnor_opr<T>(t1,t2); } 15975 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; } 15976 | static inline details::operator_type operation() { return details::e_xnor; } 15977 | }; 15978 | 15979 | template <typename T> 15980 | struct in_op : public opr_base<T> 15981 | { 15982 | typedef typename opr_base<T>::Type Type; 15983 | 15984 | static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); } 15985 | static inline T process(const std::string& t1, const std::string& t2) { return ((std::string::npos != t2.find(t1)) ? T(1) : T(0)); } 15986 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_in; } 15987 | static inline details::operator_type operation() { return details::e_in; } 15988 | }; 15989 | 15990 | template <typename T> 15991 | struct like_op : public opr_base<T> 15992 | { 15993 | typedef typename opr_base<T>::Type Type; 15994 | 15995 | static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); } 15996 | static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_match(t2,t1) ? T(1) : T(0)); } 15997 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_like; } 15998 | static inline details::operator_type operation() { return details::e_like; } 15999 | }; 16000 | 16001 | template <typename T> 16002 | struct ilike_op : public opr_base<T> 16003 | { 16004 | typedef typename opr_base<T>::Type Type; 16005 | 16006 | static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); } 16007 | static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_imatch(t2,t1) ? T(1) : T(0)); } 16008 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_ilike; } 16009 | static inline details::operator_type operation() { return details::e_ilike; } 16010 | }; 16011 | 16012 | template <typename T> 16013 | struct inrange_op : public opr_base<T> 16014 | { 16015 | typedef typename opr_base<T>::Type Type; 16016 | 16017 | static inline T process(const T& t0, const T& t1, const T& t2) { return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0); } 16018 | static inline T process(const std::string& t0, const std::string& t1, const std::string& t2) 16019 | { 16020 | return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0); 16021 | } 16022 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_inranges; } 16023 | static inline details::operator_type operation() { return details::e_inrange; } 16024 | }; 16025 | 16026 | template <typename T> 16027 | inline T value(details::expression_node<T>* n) 16028 | { 16029 | return n->value(); 16030 | } 16031 | 16032 | template <typename T> 16033 | inline T value(std::pair<details::expression_node<T>*,bool> n) 16034 | { 16035 | return n.first->value(); 16036 | } 16037 | 16038 | template <typename T> 16039 | inline T value(const T* t) 16040 | { 16041 | return (*t); 16042 | } 16043 | 16044 | template <typename T> 16045 | inline T value(const T& t) 16046 | { 16047 | return t; 16048 | } 16049 | 16050 | template <typename T> 16051 | struct vararg_add_op exprtk_final : public opr_base<T> 16052 | { 16053 | typedef typename opr_base<T>::Type Type; 16054 | 16055 | template <typename Type, 16056 | typename Allocator, 16057 | template <typename, typename> class Sequence> 16058 | static inline T process(const Sequence<Type,Allocator>& arg_list) 16059 | { 16060 | switch (arg_list.size()) 16061 | { 16062 | case 0 : return T(0); 16063 | case 1 : return process_1(arg_list); 16064 | case 2 : return process_2(arg_list); 16065 | case 3 : return process_3(arg_list); 16066 | case 4 : return process_4(arg_list); 16067 | case 5 : return process_5(arg_list); 16068 | default : 16069 | { 16070 | T result = T(0); 16071 | 16072 | for (std::size_t i = 0; i < arg_list.size(); ++i) 16073 | { 16074 | result += value(arg_list[i]); 16075 | } 16076 | 16077 | return result; 16078 | } 16079 | } 16080 | } 16081 | 16082 | template <typename Sequence> 16083 | static inline T process_1(const Sequence& arg_list) 16084 | { 16085 | return value(arg_list[0]); 16086 | } 16087 | 16088 | template <typename Sequence> 16089 | static inline T process_2(const Sequence& arg_list) 16090 | { 16091 | return value(arg_list[0]) + value(arg_list[1]); 16092 | } 16093 | 16094 | template <typename Sequence> 16095 | static inline T process_3(const Sequence& arg_list) 16096 | { 16097 | return value(arg_list[0]) + value(arg_list[1]) + 16098 | value(arg_list[2]) ; 16099 | } 16100 | 16101 | template <typename Sequence> 16102 | static inline T process_4(const Sequence& arg_list) 16103 | { 16104 | return value(arg_list[0]) + value(arg_list[1]) + 16105 | value(arg_list[2]) + value(arg_list[3]) ; 16106 | } 16107 | 16108 | template <typename Sequence> 16109 | static inline T process_5(const Sequence& arg_list) 16110 | { 16111 | return value(arg_list[0]) + value(arg_list[1]) + 16112 | value(arg_list[2]) + value(arg_list[3]) + 16113 | value(arg_list[4]) ; 16114 | } 16115 | }; 16116 | 16117 | template <typename T> 16118 | struct vararg_mul_op exprtk_final : public opr_base<T> 16119 | { 16120 | typedef typename opr_base<T>::Type Type; 16121 | 16122 | template <typename Type, 16123 | typename Allocator, 16124 | template <typename, typename> class Sequence> 16125 | static inline T process(const Sequence<Type,Allocator>& arg_list) 16126 | { 16127 | switch (arg_list.size()) 16128 | { 16129 | case 0 : return T(0); 16130 | case 1 : return process_1(arg_list); 16131 | case 2 : return process_2(arg_list); 16132 | case 3 : return process_3(arg_list); 16133 | case 4 : return process_4(arg_list); 16134 | case 5 : return process_5(arg_list); 16135 | default : 16136 | { 16137 | T result = T(value(arg_list[0])); 16138 | 16139 | for (std::size_t i = 1; i < arg_list.size(); ++i) 16140 | { 16141 | result *= value(arg_list[i]); 16142 | } 16143 | 16144 | return result; 16145 | } 16146 | } 16147 | } 16148 | 16149 | template <typename Sequence> 16150 | static inline T process_1(const Sequence& arg_list) 16151 | { 16152 | return value(arg_list[0]); 16153 | } 16154 | 16155 | template <typename Sequence> 16156 | static inline T process_2(const Sequence& arg_list) 16157 | { 16158 | return value(arg_list[0]) * value(arg_list[1]); 16159 | } 16160 | 16161 | template <typename Sequence> 16162 | static inline T process_3(const Sequence& arg_list) 16163 | { 16164 | return value(arg_list[0]) * value(arg_list[1]) * 16165 | value(arg_list[2]) ; 16166 | } 16167 | 16168 | template <typename Sequence> 16169 | static inline T process_4(const Sequence& arg_list) 16170 | { 16171 | return value(arg_list[0]) * value(arg_list[1]) * 16172 | value(arg_list[2]) * value(arg_list[3]) ; 16173 | } 16174 | 16175 | template <typename Sequence> 16176 | static inline T process_5(const Sequence& arg_list) 16177 | { 16178 | return value(arg_list[0]) * value(arg_list[1]) * 16179 | value(arg_list[2]) * value(arg_list[3]) * 16180 | value(arg_list[4]) ; 16181 | } 16182 | }; 16183 | 16184 | template <typename T> 16185 | struct vararg_avg_op exprtk_final : public opr_base<T> 16186 | { 16187 | typedef typename opr_base<T>::Type Type; 16188 | 16189 | template <typename Type, 16190 | typename Allocator, 16191 | template <typename, typename> class Sequence> 16192 | static inline T process(const Sequence<Type,Allocator>& arg_list) 16193 | { 16194 | switch (arg_list.size()) 16195 | { 16196 | case 0 : return T(0); 16197 | case 1 : return process_1(arg_list); 16198 | case 2 : return process_2(arg_list); 16199 | case 3 : return process_3(arg_list); 16200 | case 4 : return process_4(arg_list); 16201 | case 5 : return process_5(arg_list); 16202 | default : return vararg_add_op<T>::process(arg_list) / T(arg_list.size()); 16203 | } 16204 | } 16205 | 16206 | template <typename Sequence> 16207 | static inline T process_1(const Sequence& arg_list) 16208 | { 16209 | return value(arg_list[0]); 16210 | } 16211 | 16212 | template <typename Sequence> 16213 | static inline T process_2(const Sequence& arg_list) 16214 | { 16215 | return (value(arg_list[0]) + value(arg_list[1])) / T(2); 16216 | } 16217 | 16218 | template <typename Sequence> 16219 | static inline T process_3(const Sequence& arg_list) 16220 | { 16221 | return (value(arg_list[0]) + value(arg_list[1]) + value(arg_list[2])) / T(3); 16222 | } 16223 | 16224 | template <typename Sequence> 16225 | static inline T process_4(const Sequence& arg_list) 16226 | { 16227 | return (value(arg_list[0]) + value(arg_list[1]) + 16228 | value(arg_list[2]) + value(arg_list[3])) / T(4); 16229 | } 16230 | 16231 | template <typename Sequence> 16232 | static inline T process_5(const Sequence& arg_list) 16233 | { 16234 | return (value(arg_list[0]) + value(arg_list[1]) + 16235 | value(arg_list[2]) + value(arg_list[3]) + 16236 | value(arg_list[4])) / T(5); 16237 | } 16238 | }; 16239 | 16240 | template <typename T> 16241 | struct vararg_min_op exprtk_final : public opr_base<T> 16242 | { 16243 | typedef typename opr_base<T>::Type Type; 16244 | 16245 | template <typename Type, 16246 | typename Allocator, 16247 | template <typename, typename> class Sequence> 16248 | static inline T process(const Sequence<Type,Allocator>& arg_list) 16249 | { 16250 | switch (arg_list.size()) 16251 | { 16252 | case 0 : return T(0); 16253 | case 1 : return process_1(arg_list); 16254 | case 2 : return process_2(arg_list); 16255 | case 3 : return process_3(arg_list); 16256 | case 4 : return process_4(arg_list); 16257 | case 5 : return process_5(arg_list); 16258 | default : 16259 | { 16260 | T result = T(value(arg_list[0])); 16261 | 16262 | for (std::size_t i = 1; i < arg_list.size(); ++i) 16263 | { 16264 | const T v = value(arg_list[i]); 16265 | 16266 | if (v < result) 16267 | result = v; 16268 | } 16269 | 16270 | return result; 16271 | } 16272 | } 16273 | } 16274 | 16275 | template <typename Sequence> 16276 | static inline T process_1(const Sequence& arg_list) 16277 | { 16278 | return value(arg_list[0]); 16279 | } 16280 | 16281 | template <typename Sequence> 16282 | static inline T process_2(const Sequence& arg_list) 16283 | { 16284 | return std::min<T>(value(arg_list[0]),value(arg_list[1])); 16285 | } 16286 | 16287 | template <typename Sequence> 16288 | static inline T process_3(const Sequence& arg_list) 16289 | { 16290 | return std::min<T>(std::min<T>(value(arg_list[0]),value(arg_list[1])),value(arg_list[2])); 16291 | } 16292 | 16293 | template <typename Sequence> 16294 | static inline T process_4(const Sequence& arg_list) 16295 | { 16296 | return std::min<T>( 16297 | std::min<T>(value(arg_list[0]), value(arg_list[1])), 16298 | std::min<T>(value(arg_list[2]), value(arg_list[3]))); 16299 | } 16300 | 16301 | template <typename Sequence> 16302 | static inline T process_5(const Sequence& arg_list) 16303 | { 16304 | return std::min<T>( 16305 | std::min<T>(std::min<T>(value(arg_list[0]), value(arg_list[1])), 16306 | std::min<T>(value(arg_list[2]), value(arg_list[3]))), 16307 | value(arg_list[4])); 16308 | } 16309 | }; 16310 | 16311 | template <typename T> 16312 | struct vararg_max_op exprtk_final : public opr_base<T> 16313 | { 16314 | typedef typename opr_base<T>::Type Type; 16315 | 16316 | template <typename Type, 16317 | typename Allocator, 16318 | template <typename, typename> class Sequence> 16319 | static inline T process(const Sequence<Type,Allocator>& arg_list) 16320 | { 16321 | switch (arg_list.size()) 16322 | { 16323 | case 0 : return T(0); 16324 | case 1 : return process_1(arg_list); 16325 | case 2 : return process_2(arg_list); 16326 | case 3 : return process_3(arg_list); 16327 | case 4 : return process_4(arg_list); 16328 | case 5 : return process_5(arg_list); 16329 | default : 16330 | { 16331 | T result = T(value(arg_list[0])); 16332 | 16333 | for (std::size_t i = 1; i < arg_list.size(); ++i) 16334 | { 16335 | const T v = value(arg_list[i]); 16336 | 16337 | if (v > result) 16338 | result = v; 16339 | } 16340 | 16341 | return result; 16342 | } 16343 | } 16344 | } 16345 | 16346 | template <typename Sequence> 16347 | static inline T process_1(const Sequence& arg_list) 16348 | { 16349 | return value(arg_list[0]); 16350 | } 16351 | 16352 | template <typename Sequence> 16353 | static inline T process_2(const Sequence& arg_list) 16354 | { 16355 | return std::max<T>(value(arg_list[0]),value(arg_list[1])); 16356 | } 16357 | 16358 | template <typename Sequence> 16359 | static inline T process_3(const Sequence& arg_list) 16360 | { 16361 | return std::max<T>(std::max<T>(value(arg_list[0]),value(arg_list[1])),value(arg_list[2])); 16362 | } 16363 | 16364 | template <typename Sequence> 16365 | static inline T process_4(const Sequence& arg_list) 16366 | { 16367 | return std::max<T>( 16368 | std::max<T>(value(arg_list[0]), value(arg_list[1])), 16369 | std::max<T>(value(arg_list[2]), value(arg_list[3]))); 16370 | } 16371 | 16372 | template <typename Sequence> 16373 | static inline T process_5(const Sequence& arg_list) 16374 | { 16375 | return std::max<T>( 16376 | std::max<T>(std::max<T>(value(arg_list[0]), value(arg_list[1])), 16377 | std::max<T>(value(arg_list[2]), value(arg_list[3]))), 16378 | value(arg_list[4])); 16379 | } 16380 | }; 16381 | 16382 | template <typename T> 16383 | struct vararg_mand_op exprtk_final : public opr_base<T> 16384 | { 16385 | typedef typename opr_base<T>::Type Type; 16386 | 16387 | template <typename Type, 16388 | typename Allocator, 16389 | template <typename, typename> class Sequence> 16390 | static inline T process(const Sequence<Type,Allocator>& arg_list) 16391 | { 16392 | switch (arg_list.size()) 16393 | { 16394 | case 1 : return process_1(arg_list); 16395 | case 2 : return process_2(arg_list); 16396 | case 3 : return process_3(arg_list); 16397 | case 4 : return process_4(arg_list); 16398 | case 5 : return process_5(arg_list); 16399 | default : 16400 | { 16401 | for (std::size_t i = 0; i < arg_list.size(); ++i) 16402 | { 16403 | if (std::equal_to<T>()(T(0), value(arg_list[i]))) 16404 | return T(0); 16405 | } 16406 | 16407 | return T(1); 16408 | } 16409 | } 16410 | } 16411 | 16412 | template <typename Sequence> 16413 | static inline T process_1(const Sequence& arg_list) 16414 | { 16415 | return std::not_equal_to<T>() 16416 | (T(0), value(arg_list[0])) ? T(1) : T(0); 16417 | } 16418 | 16419 | template <typename Sequence> 16420 | static inline T process_2(const Sequence& arg_list) 16421 | { 16422 | return ( 16423 | std::not_equal_to<T>()(T(0), value(arg_list[0])) && 16424 | std::not_equal_to<T>()(T(0), value(arg_list[1])) 16425 | ) ? T(1) : T(0); 16426 | } 16427 | 16428 | template <typename Sequence> 16429 | static inline T process_3(const Sequence& arg_list) 16430 | { 16431 | return ( 16432 | std::not_equal_to<T>()(T(0), value(arg_list[0])) && 16433 | std::not_equal_to<T>()(T(0), value(arg_list[1])) && 16434 | std::not_equal_to<T>()(T(0), value(arg_list[2])) 16435 | ) ? T(1) : T(0); 16436 | } 16437 | 16438 | template <typename Sequence> 16439 | static inline T process_4(const Sequence& arg_list) 16440 | { 16441 | return ( 16442 | std::not_equal_to<T>()(T(0), value(arg_list[0])) && 16443 | std::not_equal_to<T>()(T(0), value(arg_list[1])) && 16444 | std::not_equal_to<T>()(T(0), value(arg_list[2])) && 16445 | std::not_equal_to<T>()(T(0), value(arg_list[3])) 16446 | ) ? T(1) : T(0); 16447 | } 16448 | 16449 | template <typename Sequence> 16450 | static inline T process_5(const Sequence& arg_list) 16451 | { 16452 | return ( 16453 | std::not_equal_to<T>()(T(0), value(arg_list[0])) && 16454 | std::not_equal_to<T>()(T(0), value(arg_list[1])) && 16455 | std::not_equal_to<T>()(T(0), value(arg_list[2])) && 16456 | std::not_equal_to<T>()(T(0), value(arg_list[3])) && 16457 | std::not_equal_to<T>()(T(0), value(arg_list[4])) 16458 | ) ? T(1) : T(0); 16459 | } 16460 | }; 16461 | 16462 | template <typename T> 16463 | struct vararg_mor_op exprtk_final : public opr_base<T> 16464 | { 16465 | typedef typename opr_base<T>::Type Type; 16466 | 16467 | template <typename Type, 16468 | typename Allocator, 16469 | template <typename, typename> class Sequence> 16470 | static inline T process(const Sequence<Type,Allocator>& arg_list) 16471 | { 16472 | switch (arg_list.size()) 16473 | { 16474 | case 1 : return process_1(arg_list); 16475 | case 2 : return process_2(arg_list); 16476 | case 3 : return process_3(arg_list); 16477 | case 4 : return process_4(arg_list); 16478 | case 5 : return process_5(arg_list); 16479 | default : 16480 | { 16481 | for (std::size_t i = 0; i < arg_list.size(); ++i) 16482 | { 16483 | if (std::not_equal_to<T>()(T(0), value(arg_list[i]))) 16484 | return T(1); 16485 | } 16486 | 16487 | return T(0); 16488 | } 16489 | } 16490 | } 16491 | 16492 | template <typename Sequence> 16493 | static inline T process_1(const Sequence& arg_list) 16494 | { 16495 | return std::not_equal_to<T>() 16496 | (T(0), value(arg_list[0])) ? T(1) : T(0); 16497 | } 16498 | 16499 | template <typename Sequence> 16500 | static inline T process_2(const Sequence& arg_list) 16501 | { 16502 | return ( 16503 | std::not_equal_to<T>()(T(0), value(arg_list[0])) || 16504 | std::not_equal_to<T>()(T(0), value(arg_list[1])) 16505 | ) ? T(1) : T(0); 16506 | } 16507 | 16508 | template <typename Sequence> 16509 | static inline T process_3(const Sequence& arg_list) 16510 | { 16511 | return ( 16512 | std::not_equal_to<T>()(T(0), value(arg_list[0])) || 16513 | std::not_equal_to<T>()(T(0), value(arg_list[1])) || 16514 | std::not_equal_to<T>()(T(0), value(arg_list[2])) 16515 | ) ? T(1) : T(0); 16516 | } 16517 | 16518 | template <typename Sequence> 16519 | static inline T process_4(const Sequence& arg_list) 16520 | { 16521 | return ( 16522 | std::not_equal_to<T>()(T(0), value(arg_list[0])) || 16523 | std::not_equal_to<T>()(T(0), value(arg_list[1])) || 16524 | std::not_equal_to<T>()(T(0), value(arg_list[2])) || 16525 | std::not_equal_to<T>()(T(0), value(arg_list[3])) 16526 | ) ? T(1) : T(0); 16527 | } 16528 | 16529 | template <typename Sequence> 16530 | static inline T process_5(const Sequence& arg_list) 16531 | { 16532 | return ( 16533 | std::not_equal_to<T>()(T(0), value(arg_list[0])) || 16534 | std::not_equal_to<T>()(T(0), value(arg_list[1])) || 16535 | std::not_equal_to<T>()(T(0), value(arg_list[2])) || 16536 | std::not_equal_to<T>()(T(0), value(arg_list[3])) || 16537 | std::not_equal_to<T>()(T(0), value(arg_list[4])) 16538 | ) ? T(1) : T(0); 16539 | } 16540 | }; 16541 | 16542 | template <typename T> 16543 | struct vararg_multi_op exprtk_final : public opr_base<T> 16544 | { 16545 | typedef typename opr_base<T>::Type Type; 16546 | 16547 | template <typename Type, 16548 | typename Allocator, 16549 | template <typename, typename> class Sequence> 16550 | static inline T process(const Sequence<Type,Allocator>& arg_list) 16551 | { 16552 | switch (arg_list.size()) 16553 | { 16554 | case 0 : return std::numeric_limits<T>::quiet_NaN(); 16555 | case 1 : return process_1(arg_list); 16556 | case 2 : return process_2(arg_list); 16557 | case 3 : return process_3(arg_list); 16558 | case 4 : return process_4(arg_list); 16559 | case 5 : return process_5(arg_list); 16560 | case 6 : return process_6(arg_list); 16561 | case 7 : return process_7(arg_list); 16562 | case 8 : return process_8(arg_list); 16563 | default : 16564 | { 16565 | for (std::size_t i = 0; i < (arg_list.size() - 1); ++i) 16566 | { 16567 | value(arg_list[i]); 16568 | } 16569 | return value(arg_list.back()); 16570 | } 16571 | } 16572 | } 16573 | 16574 | template <typename Sequence> 16575 | static inline T process_1(const Sequence& arg_list) 16576 | { 16577 | return value(arg_list[0]); 16578 | } 16579 | 16580 | template <typename Sequence> 16581 | static inline T process_2(const Sequence& arg_list) 16582 | { 16583 | value(arg_list[0]); 16584 | return value(arg_list[1]); 16585 | } 16586 | 16587 | template <typename Sequence> 16588 | static inline T process_3(const Sequence& arg_list) 16589 | { 16590 | value(arg_list[0]); 16591 | value(arg_list[1]); 16592 | return value(arg_list[2]); 16593 | } 16594 | 16595 | template <typename Sequence> 16596 | static inline T process_4(const Sequence& arg_list) 16597 | { 16598 | value(arg_list[0]); 16599 | value(arg_list[1]); 16600 | value(arg_list[2]); 16601 | return value(arg_list[3]); 16602 | } 16603 | 16604 | template <typename Sequence> 16605 | static inline T process_5(const Sequence& arg_list) 16606 | { 16607 | value(arg_list[0]); 16608 | value(arg_list[1]); 16609 | value(arg_list[2]); 16610 | value(arg_list[3]); 16611 | return value(arg_list[4]); 16612 | } 16613 | 16614 | template <typename Sequence> 16615 | static inline T process_6(const Sequence& arg_list) 16616 | { 16617 | value(arg_list[0]); 16618 | value(arg_list[1]); 16619 | value(arg_list[2]); 16620 | value(arg_list[3]); 16621 | value(arg_list[4]); 16622 | return value(arg_list[5]); 16623 | } 16624 | 16625 | template <typename Sequence> 16626 | static inline T process_7(const Sequence& arg_list) 16627 | { 16628 | value(arg_list[0]); 16629 | value(arg_list[1]); 16630 | value(arg_list[2]); 16631 | value(arg_list[3]); 16632 | value(arg_list[4]); 16633 | value(arg_list[5]); 16634 | return value(arg_list[6]); 16635 | } 16636 | 16637 | template <typename Sequence> 16638 | static inline T process_8(const Sequence& arg_list) 16639 | { 16640 | value(arg_list[0]); 16641 | value(arg_list[1]); 16642 | value(arg_list[2]); 16643 | value(arg_list[3]); 16644 | value(arg_list[4]); 16645 | value(arg_list[5]); 16646 | value(arg_list[6]); 16647 | return value(arg_list[7]); 16648 | } 16649 | }; 16650 | 16651 | template <typename T> 16652 | struct vec_add_op 16653 | { 16654 | typedef vector_interface<T>* ivector_ptr; 16655 | 16656 | static inline T process(const ivector_ptr v) 16657 | { 16658 | const T* vec = v->vec()->vds().data(); 16659 | const std::size_t vec_size = v->size(); 16660 | 16661 | loop_unroll::details lud(vec_size); 16662 | 16663 | if (vec_size <= static_cast<std::size_t>(lud.batch_size)) 16664 | { 16665 | T result = T(0); 16666 | int i = 0; 16667 | 16668 | switch (vec_size) 16669 | { 16670 | #define case_stmt(N,fall_through) \ 16671 | case N : result += vec[i++]; \ 16672 | fall_through \ 16673 | 16674 | #ifndef exprtk_disable_superscalar_unroll 16675 | case_stmt(16, exprtk_fallthrough) case_stmt(15, exprtk_fallthrough) 16676 | case_stmt(14, exprtk_fallthrough) case_stmt(13, exprtk_fallthrough) 16677 | case_stmt(12, exprtk_fallthrough) case_stmt(11, exprtk_fallthrough) 16678 | case_stmt(10, exprtk_fallthrough) case_stmt( 9, exprtk_fallthrough) 16679 | case_stmt( 8, exprtk_fallthrough) case_stmt( 7, exprtk_fallthrough) 16680 | case_stmt( 6, exprtk_fallthrough) case_stmt( 5, exprtk_fallthrough) 16681 | 16682 | #endif 16683 | case_stmt( 4, exprtk_fallthrough) case_stmt( 3, exprtk_fallthrough) 16684 | case_stmt( 2, exprtk_fallthrough) case_stmt( 1, (void)0;) 16685 | } 16686 | 16687 | #undef case_stmt 16688 | 16689 | return result; 16690 | } 16691 | 16692 | T r[] = { 16693 | T(0), T(0), T(0), T(0), T(0), T(0), T(0), T(0), 16694 | T(0), T(0), T(0), T(0), T(0), T(0), T(0), T(0) 16695 | }; 16696 | 16697 | const T* upper_bound = vec + lud.upper_bound; 16698 | 16699 | while (vec < upper_bound) 16700 | { 16701 | #define exprtk_loop(N) \ 16702 | r[N] += vec[N]; \ 16703 | 16704 | exprtk_loop( 0) exprtk_loop( 1) 16705 | exprtk_loop( 2) exprtk_loop( 3) 16706 | #ifndef exprtk_disable_superscalar_unroll 16707 | exprtk_loop( 4) exprtk_loop( 5) 16708 | exprtk_loop( 6) exprtk_loop( 7) 16709 | exprtk_loop( 8) exprtk_loop( 9) 16710 | exprtk_loop(10) exprtk_loop(11) 16711 | exprtk_loop(12) exprtk_loop(13) 16712 | exprtk_loop(14) exprtk_loop(15) 16713 | #endif 16714 | 16715 | vec += lud.batch_size; 16716 | } 16717 | 16718 | int i = 0; 16719 | 16720 | switch (lud.remainder) 16721 | { 16722 | #define case_stmt(N,fall_through) \ 16723 | case N : r[0] += vec[i++]; \ 16724 | fall_through \ 16725 | 16726 | #ifndef exprtk_disable_superscalar_unroll 16727 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 16728 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 16729 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 16730 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 16731 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 16732 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 16733 | #endif 16734 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 16735 | case_stmt( 1, (void)0;) 16736 | } 16737 | 16738 | #undef exprtk_loop 16739 | #undef case_stmt 16740 | 16741 | return (r[ 0] + r[ 1] + r[ 2] + r[ 3]) 16742 | #ifndef exprtk_disable_superscalar_unroll 16743 | + (r[ 4] + r[ 5] + r[ 6] + r[ 7]) 16744 | + (r[ 8] + r[ 9] + r[10] + r[11]) 16745 | + (r[12] + r[13] + r[14] + r[15]) 16746 | #endif 16747 | ; 16748 | } 16749 | }; 16750 | 16751 | template <typename T> 16752 | struct vec_mul_op 16753 | { 16754 | typedef vector_interface<T>* ivector_ptr; 16755 | 16756 | static inline T process(const ivector_ptr v) 16757 | { 16758 | const T* vec = v->vec()->vds().data(); 16759 | const std::size_t vec_size = v->vec()->size(); 16760 | 16761 | loop_unroll::details lud(vec_size); 16762 | 16763 | if (vec_size <= static_cast<std::size_t>(lud.batch_size)) 16764 | { 16765 | T result = T(1); 16766 | int i = 0; 16767 | 16768 | switch (vec_size) 16769 | { 16770 | #define case_stmt(N,fall_through) \ 16771 | case N : result *= vec[i++]; \ 16772 | fall_through \ 16773 | 16774 | #ifndef exprtk_disable_superscalar_unroll 16775 | case_stmt(16, exprtk_fallthrough) case_stmt(15, exprtk_fallthrough) 16776 | case_stmt(14, exprtk_fallthrough) case_stmt(13, exprtk_fallthrough) 16777 | case_stmt(12, exprtk_fallthrough) case_stmt(11, exprtk_fallthrough) 16778 | case_stmt(10, exprtk_fallthrough) case_stmt( 9, exprtk_fallthrough) 16779 | case_stmt( 8, exprtk_fallthrough) case_stmt( 7, exprtk_fallthrough) 16780 | case_stmt( 6, exprtk_fallthrough) case_stmt( 5, exprtk_fallthrough) 16781 | #endif 16782 | case_stmt( 4, exprtk_fallthrough) case_stmt( 3, exprtk_fallthrough) 16783 | case_stmt( 2, exprtk_fallthrough) case_stmt( 1, (void)0;) 16784 | } 16785 | 16786 | #undef case_stmt 16787 | 16788 | return result; 16789 | } 16790 | 16791 | T r[] = { 16792 | T(1), T(1), T(1), T(1), T(1), T(1), T(1), T(1), 16793 | T(1), T(1), T(1), T(1), T(1), T(1), T(1), T(1) 16794 | }; 16795 | 16796 | const T* upper_bound = vec + lud.upper_bound; 16797 | 16798 | while (vec < upper_bound) 16799 | { 16800 | #define exprtk_loop(N) \ 16801 | r[N] *= vec[N]; \ 16802 | 16803 | exprtk_loop( 0) exprtk_loop( 1) 16804 | exprtk_loop( 2) exprtk_loop( 3) 16805 | #ifndef exprtk_disable_superscalar_unroll 16806 | exprtk_loop( 4) exprtk_loop( 5) 16807 | exprtk_loop( 6) exprtk_loop( 7) 16808 | exprtk_loop( 8) exprtk_loop( 9) 16809 | exprtk_loop(10) exprtk_loop(11) 16810 | exprtk_loop(12) exprtk_loop(13) 16811 | exprtk_loop(14) exprtk_loop(15) 16812 | #endif 16813 | 16814 | vec += lud.batch_size; 16815 | } 16816 | 16817 | int i = 0; 16818 | 16819 | switch (lud.remainder) 16820 | { 16821 | #define case_stmt(N,fall_through) \ 16822 | case N : r[0] *= vec[i++]; \ 16823 | fall_through \ 16824 | 16825 | #ifndef exprtk_disable_superscalar_unroll 16826 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 16827 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 16828 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 16829 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 16830 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 16831 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 16832 | #endif 16833 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 16834 | case_stmt( 1, (void)0;) 16835 | } 16836 | 16837 | #undef exprtk_loop 16838 | #undef case_stmt 16839 | 16840 | return (r[ 0] * r[ 1] * r[ 2] * r[ 3]) 16841 | #ifndef exprtk_disable_superscalar_unroll 16842 | * (r[ 4] * r[ 5] * r[ 6] * r[ 7]) 16843 | * (r[ 8] * r[ 9] * r[10] * r[11]) 16844 | * (r[12] * r[13] * r[14] * r[15]) 16845 | #endif 16846 | ; 16847 | } 16848 | }; 16849 | 16850 | template <typename T> 16851 | struct vec_avg_op 16852 | { 16853 | typedef vector_interface<T>* ivector_ptr; 16854 | 16855 | static inline T process(const ivector_ptr v) 16856 | { 16857 | const T vec_size = T(v->vec()->size()); 16858 | return vec_add_op<T>::process(v) / vec_size; 16859 | } 16860 | }; 16861 | 16862 | template <typename T> 16863 | struct vec_min_op 16864 | { 16865 | typedef vector_interface<T>* ivector_ptr; 16866 | 16867 | static inline T process(const ivector_ptr v) 16868 | { 16869 | const T* vec = v->vec()->vds().data(); 16870 | const std::size_t vec_size = v->vec()->size(); 16871 | 16872 | T result = vec[0]; 16873 | 16874 | for (std::size_t i = 1; i < vec_size; ++i) 16875 | { 16876 | const T v_i = vec[i]; 16877 | 16878 | if (v_i < result) 16879 | result = v_i; 16880 | } 16881 | 16882 | return result; 16883 | } 16884 | }; 16885 | 16886 | template <typename T> 16887 | struct vec_max_op 16888 | { 16889 | typedef vector_interface<T>* ivector_ptr; 16890 | 16891 | static inline T process(const ivector_ptr v) 16892 | { 16893 | const T* vec = v->vec()->vds().data(); 16894 | const std::size_t vec_size = v->vec()->size(); 16895 | 16896 | T result = vec[0]; 16897 | 16898 | for (std::size_t i = 1; i < vec_size; ++i) 16899 | { 16900 | const T v_i = vec[i]; 16901 | 16902 | if (v_i > result) 16903 | result = v_i; 16904 | } 16905 | 16906 | return result; 16907 | } 16908 | }; 16909 | 16910 | template <typename T> 16911 | class vov_base_node : public expression_node<T> 16912 | { 16913 | public: 16914 | 16915 | virtual ~vov_base_node() 16916 | {} 16917 | 16918 | inline virtual operator_type operation() const 16919 | { 16920 | return details::e_default; 16921 | } 16922 | 16923 | virtual const T& v0() const = 0; 16924 | 16925 | virtual const T& v1() const = 0; 16926 | }; 16927 | 16928 | template <typename T> 16929 | class cov_base_node : public expression_node<T> 16930 | { 16931 | public: 16932 | 16933 | virtual ~cov_base_node() 16934 | {} 16935 | 16936 | inline virtual operator_type operation() const 16937 | { 16938 | return details::e_default; 16939 | } 16940 | 16941 | virtual const T c() const = 0; 16942 | 16943 | virtual const T& v() const = 0; 16944 | }; 16945 | 16946 | template <typename T> 16947 | class voc_base_node : public expression_node<T> 16948 | { 16949 | public: 16950 | 16951 | virtual ~voc_base_node() 16952 | {} 16953 | 16954 | inline virtual operator_type operation() const 16955 | { 16956 | return details::e_default; 16957 | } 16958 | 16959 | virtual const T c() const = 0; 16960 | 16961 | virtual const T& v() const = 0; 16962 | }; 16963 | 16964 | template <typename T> 16965 | class vob_base_node : public expression_node<T> 16966 | { 16967 | public: 16968 | 16969 | virtual ~vob_base_node() 16970 | {} 16971 | 16972 | virtual const T& v() const = 0; 16973 | }; 16974 | 16975 | template <typename T> 16976 | class bov_base_node : public expression_node<T> 16977 | { 16978 | public: 16979 | 16980 | virtual ~bov_base_node() 16981 | {} 16982 | 16983 | virtual const T& v() const = 0; 16984 | }; 16985 | 16986 | template <typename T> 16987 | class cob_base_node : public expression_node<T> 16988 | { 16989 | public: 16990 | 16991 | virtual ~cob_base_node() 16992 | {} 16993 | 16994 | inline virtual operator_type operation() const 16995 | { 16996 | return details::e_default; 16997 | } 16998 | 16999 | virtual const T c() const = 0; 17000 | 17001 | virtual void set_c(const T) = 0; 17002 | 17003 | virtual expression_node<T>* move_branch(const std::size_t& index) = 0; 17004 | }; 17005 | 17006 | template <typename T> 17007 | class boc_base_node : public expression_node<T> 17008 | { 17009 | public: 17010 | 17011 | virtual ~boc_base_node() 17012 | {} 17013 | 17014 | inline virtual operator_type operation() const 17015 | { 17016 | return details::e_default; 17017 | } 17018 | 17019 | virtual const T c() const = 0; 17020 | 17021 | virtual void set_c(const T) = 0; 17022 | 17023 | virtual expression_node<T>* move_branch(const std::size_t& index) = 0; 17024 | }; 17025 | 17026 | template <typename T> 17027 | class uv_base_node : public expression_node<T> 17028 | { 17029 | public: 17030 | 17031 | virtual ~uv_base_node() 17032 | {} 17033 | 17034 | inline virtual operator_type operation() const 17035 | { 17036 | return details::e_default; 17037 | } 17038 | 17039 | virtual const T& v() const = 0; 17040 | }; 17041 | 17042 | template <typename T> 17043 | class sos_base_node : public expression_node<T> 17044 | { 17045 | public: 17046 | 17047 | virtual ~sos_base_node() 17048 | {} 17049 | 17050 | inline virtual operator_type operation() const 17051 | { 17052 | return details::e_default; 17053 | } 17054 | }; 17055 | 17056 | template <typename T> 17057 | class sosos_base_node : public expression_node<T> 17058 | { 17059 | public: 17060 | 17061 | virtual ~sosos_base_node() 17062 | {} 17063 | 17064 | inline virtual operator_type operation() const 17065 | { 17066 | return details::e_default; 17067 | } 17068 | }; 17069 | 17070 | template <typename T> 17071 | class T0oT1oT2_base_node : public expression_node<T> 17072 | { 17073 | public: 17074 | 17075 | virtual ~T0oT1oT2_base_node() 17076 | {} 17077 | 17078 | virtual std::string type_id() const = 0; 17079 | }; 17080 | 17081 | template <typename T> 17082 | class T0oT1oT2oT3_base_node : public expression_node<T> 17083 | { 17084 | public: 17085 | 17086 | virtual ~T0oT1oT2oT3_base_node() 17087 | {} 17088 | 17089 | virtual std::string type_id() const = 0; 17090 | }; 17091 | 17092 | template <typename T, typename Operation> 17093 | class unary_variable_node exprtk_final : public uv_base_node<T> 17094 | { 17095 | public: 17096 | 17097 | typedef expression_node<T>* expression_ptr; 17098 | typedef Operation operation_t; 17099 | 17100 | explicit unary_variable_node(const T& var) 17101 | : v_(var) 17102 | {} 17103 | 17104 | inline T value() const exprtk_override 17105 | { 17106 | return Operation::process(v_); 17107 | } 17108 | 17109 | inline typename expression_node<T>::node_type type() const exprtk_override 17110 | { 17111 | return Operation::type(); 17112 | } 17113 | 17114 | inline operator_type operation() const exprtk_override 17115 | { 17116 | return Operation::operation(); 17117 | } 17118 | 17119 | inline const T& v() const exprtk_override 17120 | { 17121 | return v_; 17122 | } 17123 | 17124 | private: 17125 | 17126 | unary_variable_node(const unary_variable_node<T,Operation>&) exprtk_delete; 17127 | unary_variable_node<T,Operation>& operator=(const unary_variable_node<T,Operation>&) exprtk_delete; 17128 | 17129 | const T& v_; 17130 | }; 17131 | 17132 | template <typename T> 17133 | class uvouv_node exprtk_final : public expression_node<T> 17134 | { 17135 | public: 17136 | 17137 | // UOpr1(v0) Op UOpr2(v1) 17138 | typedef typename details::functor_t<T> functor_t; 17139 | typedef typename functor_t::bfunc_t bfunc_t; 17140 | typedef typename functor_t::ufunc_t ufunc_t; 17141 | typedef expression_node<T>* expression_ptr; 17142 | 17143 | explicit uvouv_node(const T& var0,const T& var1, 17144 | ufunc_t uf0, ufunc_t uf1, bfunc_t bf) 17145 | : v0_(var0) 17146 | , v1_(var1) 17147 | , u0_(uf0 ) 17148 | , u1_(uf1 ) 17149 | , f_ (bf ) 17150 | {} 17151 | 17152 | inline T value() const exprtk_override 17153 | { 17154 | return f_(u0_(v0_),u1_(v1_)); 17155 | } 17156 | 17157 | inline typename expression_node<T>::node_type type() const exprtk_override 17158 | { 17159 | return expression_node<T>::e_uvouv; 17160 | } 17161 | 17162 | inline const T& v0() 17163 | { 17164 | return v0_; 17165 | } 17166 | 17167 | inline const T& v1() 17168 | { 17169 | return v1_; 17170 | } 17171 | 17172 | inline ufunc_t u0() 17173 | { 17174 | return u0_; 17175 | } 17176 | 17177 | inline ufunc_t u1() 17178 | { 17179 | return u1_; 17180 | } 17181 | 17182 | inline ufunc_t f() 17183 | { 17184 | return f_; 17185 | } 17186 | 17187 | private: 17188 | 17189 | uvouv_node(const uvouv_node<T>&) exprtk_delete; 17190 | uvouv_node<T>& operator=(const uvouv_node<T>&) exprtk_delete; 17191 | 17192 | const T& v0_; 17193 | const T& v1_; 17194 | const ufunc_t u0_; 17195 | const ufunc_t u1_; 17196 | const bfunc_t f_; 17197 | }; 17198 | 17199 | template <typename T, typename Operation> 17200 | class unary_branch_node exprtk_final : public expression_node<T> 17201 | { 17202 | public: 17203 | 17204 | typedef Operation operation_t; 17205 | typedef expression_node<T>* expression_ptr; 17206 | typedef std::pair<expression_ptr,bool> branch_t; 17207 | 17208 | explicit unary_branch_node(expression_ptr branch) 17209 | { 17210 | construct_branch_pair(branch_, branch); 17211 | } 17212 | 17213 | inline T value() const exprtk_override 17214 | { 17215 | return Operation::process(branch_.first->value()); 17216 | } 17217 | 17218 | inline typename expression_node<T>::node_type type() const exprtk_override 17219 | { 17220 | return Operation::type(); 17221 | } 17222 | 17223 | inline bool valid() const exprtk_override 17224 | { 17225 | return branch_.first && branch_.first->valid(); 17226 | } 17227 | 17228 | inline operator_type operation() 17229 | { 17230 | return Operation::operation(); 17231 | } 17232 | 17233 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 17234 | { 17235 | return branch_.first; 17236 | } 17237 | 17238 | inline void release() 17239 | { 17240 | branch_.second = false; 17241 | } 17242 | 17243 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 17244 | { 17245 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 17246 | } 17247 | 17248 | std::size_t node_depth() const exprtk_override 17249 | { 17250 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 17251 | } 17252 | 17253 | private: 17254 | 17255 | unary_branch_node(const unary_branch_node<T,Operation>&) exprtk_delete; 17256 | unary_branch_node<T,Operation>& operator=(const unary_branch_node<T,Operation>&) exprtk_delete; 17257 | 17258 | branch_t branch_; 17259 | }; 17260 | 17261 | template <typename T> struct is_const { enum {result = 0}; }; 17262 | template <typename T> struct is_const <const T> { enum {result = 1}; }; 17263 | template <typename T> struct is_const_ref { enum {result = 0}; }; 17264 | template <typename T> struct is_const_ref <const T&> { enum {result = 1}; }; 17265 | template <typename T> struct is_ref { enum {result = 0}; }; 17266 | template <typename T> struct is_ref<T&> { enum {result = 1}; }; 17267 | template <typename T> struct is_ref<const T&> { enum {result = 0}; }; 17268 | 17269 | template <std::size_t State> 17270 | struct param_to_str { static std::string result() { static const std::string r("v"); return r; } }; 17271 | 17272 | template <> 17273 | struct param_to_str<0> { static std::string result() { static const std::string r("c"); return r; } }; 17274 | 17275 | #define exprtk_crtype(Type) \ 17276 | param_to_str<is_const_ref< Type >::result>::result() \ 17277 | 17278 | template <typename T> 17279 | struct T0oT1oT2process 17280 | { 17281 | typedef typename details::functor_t<T> functor_t; 17282 | typedef typename functor_t::bfunc_t bfunc_t; 17283 | 17284 | struct mode0 17285 | { 17286 | static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1) 17287 | { 17288 | // (T0 o0 T1) o1 T2 17289 | return bf1(bf0(t0,t1),t2); 17290 | } 17291 | 17292 | template <typename T0, typename T1, typename T2> 17293 | static inline std::string id() 17294 | { 17295 | static const std::string result = "(" + exprtk_crtype(T0) + "o" + 17296 | exprtk_crtype(T1) + ")o(" + 17297 | exprtk_crtype(T2) + ")" ; 17298 | return result; 17299 | } 17300 | }; 17301 | 17302 | struct mode1 17303 | { 17304 | static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1) 17305 | { 17306 | // T0 o0 (T1 o1 T2) 17307 | return bf0(t0,bf1(t1,t2)); 17308 | } 17309 | 17310 | template <typename T0, typename T1, typename T2> 17311 | static inline std::string id() 17312 | { 17313 | static const std::string result = "(" + exprtk_crtype(T0) + ")o(" + 17314 | exprtk_crtype(T1) + "o" + 17315 | exprtk_crtype(T2) + ")" ; 17316 | return result; 17317 | } 17318 | }; 17319 | }; 17320 | 17321 | template <typename T> 17322 | struct T0oT1oT20T3process 17323 | { 17324 | typedef typename details::functor_t<T> functor_t; 17325 | typedef typename functor_t::bfunc_t bfunc_t; 17326 | 17327 | struct mode0 17328 | { 17329 | static inline T process(const T& t0, const T& t1, 17330 | const T& t2, const T& t3, 17331 | const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) 17332 | { 17333 | // (T0 o0 T1) o1 (T2 o2 T3) 17334 | return bf1(bf0(t0,t1),bf2(t2,t3)); 17335 | } 17336 | 17337 | template <typename T0, typename T1, typename T2, typename T3> 17338 | static inline std::string id() 17339 | { 17340 | static const std::string result = "(" + exprtk_crtype(T0) + "o" + 17341 | exprtk_crtype(T1) + ")o" + 17342 | "(" + exprtk_crtype(T2) + "o" + 17343 | exprtk_crtype(T3) + ")" ; 17344 | return result; 17345 | } 17346 | }; 17347 | 17348 | struct mode1 17349 | { 17350 | static inline T process(const T& t0, const T& t1, 17351 | const T& t2, const T& t3, 17352 | const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) 17353 | { 17354 | // (T0 o0 (T1 o1 (T2 o2 T3)) 17355 | return bf0(t0,bf1(t1,bf2(t2,t3))); 17356 | } 17357 | template <typename T0, typename T1, typename T2, typename T3> 17358 | static inline std::string id() 17359 | { 17360 | static const std::string result = "(" + exprtk_crtype(T0) + ")o((" + 17361 | exprtk_crtype(T1) + ")o(" + 17362 | exprtk_crtype(T2) + "o" + 17363 | exprtk_crtype(T3) + "))" ; 17364 | return result; 17365 | } 17366 | }; 17367 | 17368 | struct mode2 17369 | { 17370 | static inline T process(const T& t0, const T& t1, 17371 | const T& t2, const T& t3, 17372 | const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) 17373 | { 17374 | // (T0 o0 ((T1 o1 T2) o2 T3) 17375 | return bf0(t0,bf2(bf1(t1,t2),t3)); 17376 | } 17377 | 17378 | template <typename T0, typename T1, typename T2, typename T3> 17379 | static inline std::string id() 17380 | { 17381 | static const std::string result = "(" + exprtk_crtype(T0) + ")o((" + 17382 | exprtk_crtype(T1) + "o" + 17383 | exprtk_crtype(T2) + ")o(" + 17384 | exprtk_crtype(T3) + "))" ; 17385 | return result; 17386 | } 17387 | }; 17388 | 17389 | struct mode3 17390 | { 17391 | static inline T process(const T& t0, const T& t1, 17392 | const T& t2, const T& t3, 17393 | const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) 17394 | { 17395 | // (((T0 o0 T1) o1 T2) o2 T3) 17396 | return bf2(bf1(bf0(t0,t1),t2),t3); 17397 | } 17398 | 17399 | template <typename T0, typename T1, typename T2, typename T3> 17400 | static inline std::string id() 17401 | { 17402 | static const std::string result = "((" + exprtk_crtype(T0) + "o" + 17403 | exprtk_crtype(T1) + ")o(" + 17404 | exprtk_crtype(T2) + "))o(" + 17405 | exprtk_crtype(T3) + ")" 17406 | return result; 17407 | } 17408 | }; 17409 | 17410 | struct mode4 17411 | { 17412 | static inline T process(const T& t0, const T& t1, 17413 | const T& t2, const T& t3, 17414 | const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) 17415 | { 17416 | // ((T0 o0 (T1 o1 T2)) o2 T3 17417 | return bf2(bf0(t0,bf1(t1,t2)),t3); 17418 | } 17419 | 17420 | template <typename T0, typename T1, typename T2, typename T3> 17421 | static inline std::string id() 17422 | { 17423 | static const std::string result = "((" + exprtk_crtype(T0) + ")o(" + 17424 | exprtk_crtype(T1) + "o" + 17425 | exprtk_crtype(T2) + "))o(" + 17426 | exprtk_crtype(T3) + ")" ; 17427 | return result; 17428 | } 17429 | }; 17430 | }; 17431 | 17432 | #undef exprtk_crtype 17433 | 17434 | template <typename T, typename T0, typename T1> 17435 | struct nodetype_T0oT1 { static const typename expression_node<T>::node_type result; }; 17436 | template <typename T, typename T0, typename T1> 17437 | const typename expression_node<T>::node_type nodetype_T0oT1<T,T0,T1>::result = expression_node<T>::e_none; 17438 | 17439 | #define synthesis_node_type_define(T0_, T1_, v_) \ 17440 | template <typename T, typename T0, typename T1> \ 17441 | struct nodetype_T0oT1<T,T0_,T1_> { static const typename expression_node<T>::node_type result; }; \ 17442 | template <typename T, typename T0, typename T1> \ 17443 | const typename expression_node<T>::node_type nodetype_T0oT1<T,T0_,T1_>::result = expression_node<T>:: v_; \ 17444 | 17445 | synthesis_node_type_define(const T0&, const T1&, e_vov) 17446 | synthesis_node_type_define(const T0&, const T1 , e_voc) 17447 | synthesis_node_type_define(const T0 , const T1&, e_cov) 17448 | synthesis_node_type_define( T0&, T1&, e_none) 17449 | synthesis_node_type_define(const T0 , const T1 , e_none) 17450 | synthesis_node_type_define( T0&, const T1 , e_none) 17451 | synthesis_node_type_define(const T0 , T1&, e_none) 17452 | synthesis_node_type_define(const T0&, T1&, e_none) 17453 | synthesis_node_type_define( T0&, const T1&, e_none) 17454 | #undef synthesis_node_type_define 17455 | 17456 | template <typename T, typename T0, typename T1, typename T2> 17457 | struct nodetype_T0oT1oT2 { static const typename expression_node<T>::node_type result; }; 17458 | template <typename T, typename T0, typename T1, typename T2> 17459 | const typename expression_node<T>::node_type nodetype_T0oT1oT2<T,T0,T1,T2>::result = expression_node<T>::e_none; 17460 | 17461 | #define synthesis_node_type_define(T0_, T1_, T2_, v_) \ 17462 | template <typename T, typename T0, typename T1, typename T2> \ 17463 | struct nodetype_T0oT1oT2<T,T0_,T1_,T2_> { static const typename expression_node<T>::node_type result; }; \ 17464 | template <typename T, typename T0, typename T1, typename T2> \ 17465 | const typename expression_node<T>::node_type nodetype_T0oT1oT2<T,T0_,T1_,T2_>::result = expression_node<T>:: v_; \ 17466 | 17467 | synthesis_node_type_define(const T0&, const T1&, const T2&, e_vovov) 17468 | synthesis_node_type_define(const T0&, const T1&, const T2 , e_vovoc) 17469 | synthesis_node_type_define(const T0&, const T1 , const T2&, e_vocov) 17470 | synthesis_node_type_define(const T0 , const T1&, const T2&, e_covov) 17471 | synthesis_node_type_define(const T0 , const T1&, const T2 , e_covoc) 17472 | synthesis_node_type_define(const T0 , const T1 , const T2 , e_none ) 17473 | synthesis_node_type_define(const T0 , const T1 , const T2&, e_none ) 17474 | synthesis_node_type_define(const T0&, const T1 , const T2 , e_none ) 17475 | synthesis_node_type_define( T0&, T1&, T2&, e_none ) 17476 | #undef synthesis_node_type_define 17477 | 17478 | template <typename T, typename T0, typename T1, typename T2, typename T3> 17479 | struct nodetype_T0oT1oT2oT3 { static const typename expression_node<T>::node_type result; }; 17480 | template <typename T, typename T0, typename T1, typename T2, typename T3> 17481 | const typename expression_node<T>::node_type nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result = expression_node<T>::e_none; 17482 | 17483 | #define synthesis_node_type_define(T0_, T1_, T2_, T3_, v_) \ 17484 | template <typename T, typename T0, typename T1, typename T2, typename T3> \ 17485 | struct nodetype_T0oT1oT2oT3<T,T0_,T1_,T2_,T3_> { static const typename expression_node<T>::node_type result; }; \ 17486 | template <typename T, typename T0, typename T1, typename T2, typename T3> \ 17487 | const typename expression_node<T>::node_type nodetype_T0oT1oT2oT3<T,T0_,T1_,T2_,T3_>::result = expression_node<T>:: v_; \ 17488 | 17489 | synthesis_node_type_define(const T0&, const T1&, const T2&, const T3&, e_vovovov) 17490 | synthesis_node_type_define(const T0&, const T1&, const T2&, const T3 , e_vovovoc) 17491 | synthesis_node_type_define(const T0&, const T1&, const T2 , const T3&, e_vovocov) 17492 | synthesis_node_type_define(const T0&, const T1 , const T2&, const T3&, e_vocovov) 17493 | synthesis_node_type_define(const T0 , const T1&, const T2&, const T3&, e_covovov) 17494 | synthesis_node_type_define(const T0 , const T1&, const T2 , const T3&, e_covocov) 17495 | synthesis_node_type_define(const T0&, const T1 , const T2&, const T3 , e_vocovoc) 17496 | synthesis_node_type_define(const T0 , const T1&, const T2&, const T3 , e_covovoc) 17497 | synthesis_node_type_define(const T0&, const T1 , const T2 , const T3&, e_vococov) 17498 | synthesis_node_type_define(const T0 , const T1 , const T2 , const T3 , e_none ) 17499 | synthesis_node_type_define(const T0 , const T1 , const T2 , const T3&, e_none ) 17500 | synthesis_node_type_define(const T0 , const T1 , const T2&, const T3 , e_none ) 17501 | synthesis_node_type_define(const T0 , const T1&, const T2 , const T3 , e_none ) 17502 | synthesis_node_type_define(const T0&, const T1 , const T2 , const T3 , e_none ) 17503 | synthesis_node_type_define(const T0 , const T1 , const T2&, const T3&, e_none ) 17504 | synthesis_node_type_define(const T0&, const T1&, const T2 , const T3 , e_none ) 17505 | #undef synthesis_node_type_define 17506 | 17507 | template <typename T, typename T0, typename T1> 17508 | class T0oT1 exprtk_final : public expression_node<T> 17509 | { 17510 | public: 17511 | 17512 | typedef typename details::functor_t<T> functor_t; 17513 | typedef typename functor_t::bfunc_t bfunc_t; 17514 | typedef T value_type; 17515 | typedef T0oT1<T,T0,T1> node_type; 17516 | 17517 | T0oT1(T0 p0, T1 p1, const bfunc_t p2) 17518 | : t0_(p0) 17519 | , t1_(p1) 17520 | , f_ (p2) 17521 | {} 17522 | 17523 | inline typename expression_node<T>::node_type type() const exprtk_override 17524 | { 17525 | static const typename expression_node<T>::node_type result = nodetype_T0oT1<T,T0,T1>::result; 17526 | return result; 17527 | } 17528 | 17529 | inline operator_type operation() const exprtk_override 17530 | { 17531 | return e_default; 17532 | } 17533 | 17534 | inline T value() const exprtk_override 17535 | { 17536 | return f_(t0_,t1_); 17537 | } 17538 | 17539 | inline T0 t0() const 17540 | { 17541 | return t0_; 17542 | } 17543 | 17544 | inline T1 t1() const 17545 | { 17546 | return t1_; 17547 | } 17548 | 17549 | inline bfunc_t f() const 17550 | { 17551 | return f_; 17552 | } 17553 | 17554 | template <typename Allocator> 17555 | static inline expression_node<T>* allocate(Allocator& allocator, 17556 | T0 p0, T1 p1, 17557 | bfunc_t p2) 17558 | { 17559 | return allocator 17560 | .template allocate_type<node_type, T0, T1, bfunc_t&> 17561 | (p0, p1, p2); 17562 | } 17563 | 17564 | private: 17565 | 17566 | T0oT1(const T0oT1<T,T0,T1>&) exprtk_delete; 17567 | T0oT1<T,T0,T1>& operator=(const T0oT1<T,T0,T1>&) { return (*this); } 17568 | 17569 | T0 t0_; 17570 | T1 t1_; 17571 | const bfunc_t f_; 17572 | }; 17573 | 17574 | template <typename T, typename T0, typename T1, typename T2, typename ProcessMode> 17575 | class T0oT1oT2 exprtk_final : public T0oT1oT2_base_node<T> 17576 | { 17577 | public: 17578 | 17579 | typedef typename details::functor_t<T> functor_t; 17580 | typedef typename functor_t::bfunc_t bfunc_t; 17581 | typedef T value_type; 17582 | typedef T0oT1oT2<T,T0,T1,T2,ProcessMode> node_type; 17583 | typedef ProcessMode process_mode_t; 17584 | 17585 | T0oT1oT2(T0 p0, T1 p1, T2 p2, const bfunc_t p3, const bfunc_t p4) 17586 | : t0_(p0) 17587 | , t1_(p1) 17588 | , t2_(p2) 17589 | , f0_(p3) 17590 | , f1_(p4) 17591 | {} 17592 | 17593 | inline typename expression_node<T>::node_type type() const exprtk_override 17594 | { 17595 | static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result; 17596 | return result; 17597 | } 17598 | 17599 | inline operator_type operation() 17600 | { 17601 | return e_default; 17602 | } 17603 | 17604 | inline T value() const exprtk_override 17605 | { 17606 | return ProcessMode::process(t0_, t1_, t2_, f0_, f1_); 17607 | } 17608 | 17609 | inline T0 t0() const 17610 | { 17611 | return t0_; 17612 | } 17613 | 17614 | inline T1 t1() const 17615 | { 17616 | return t1_; 17617 | } 17618 | 17619 | inline T2 t2() const 17620 | { 17621 | return t2_; 17622 | } 17623 | 17624 | bfunc_t f0() const 17625 | { 17626 | return f0_; 17627 | } 17628 | 17629 | bfunc_t f1() const 17630 | { 17631 | return f1_; 17632 | } 17633 | 17634 | std::string type_id() const exprtk_override 17635 | { 17636 | return id(); 17637 | } 17638 | 17639 | static inline std::string id() 17640 | { 17641 | return process_mode_t::template id<T0,T1,T2>(); 17642 | } 17643 | 17644 | template <typename Allocator> 17645 | static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, bfunc_t p3, bfunc_t p4) 17646 | { 17647 | return allocator 17648 | .template allocate_type<node_type, T0, T1, T2, bfunc_t, bfunc_t> 17649 | (p0, p1, p2, p3, p4); 17650 | } 17651 | 17652 | private: 17653 | 17654 | T0oT1oT2(const node_type&) exprtk_delete; 17655 | node_type& operator=(const node_type&) exprtk_delete; 17656 | 17657 | T0 t0_; 17658 | T1 t1_; 17659 | T2 t2_; 17660 | const bfunc_t f0_; 17661 | const bfunc_t f1_; 17662 | }; 17663 | 17664 | template <typename T, typename T0_, typename T1_, typename T2_, typename T3_, typename ProcessMode> 17665 | class T0oT1oT2oT3 exprtk_final : public T0oT1oT2oT3_base_node<T> 17666 | { 17667 | public: 17668 | 17669 | typedef typename details::functor_t<T> functor_t; 17670 | typedef typename functor_t::bfunc_t bfunc_t; 17671 | typedef T value_type; 17672 | typedef T0_ T0; 17673 | typedef T1_ T1; 17674 | typedef T2_ T2; 17675 | typedef T3_ T3; 17676 | typedef T0oT1oT2oT3<T,T0,T1,T2,T3,ProcessMode> node_type; 17677 | typedef ProcessMode process_mode_t; 17678 | 17679 | T0oT1oT2oT3(T0 p0, T1 p1, T2 p2, T3 p3, bfunc_t p4, bfunc_t p5, bfunc_t p6) 17680 | : t0_(p0) 17681 | , t1_(p1) 17682 | , t2_(p2) 17683 | , t3_(p3) 17684 | , f0_(p4) 17685 | , f1_(p5) 17686 | , f2_(p6) 17687 | {} 17688 | 17689 | inline T value() const exprtk_override 17690 | { 17691 | return ProcessMode::process(t0_, t1_, t2_, t3_, f0_, f1_, f2_); 17692 | } 17693 | 17694 | inline T0 t0() const 17695 | { 17696 | return t0_; 17697 | } 17698 | 17699 | inline T1 t1() const 17700 | { 17701 | return t1_; 17702 | } 17703 | 17704 | inline T2 t2() const 17705 | { 17706 | return t2_; 17707 | } 17708 | 17709 | inline T3 t3() const 17710 | { 17711 | return t3_; 17712 | } 17713 | 17714 | inline bfunc_t f0() const 17715 | { 17716 | return f0_; 17717 | } 17718 | 17719 | inline bfunc_t f1() const 17720 | { 17721 | return f1_; 17722 | } 17723 | 17724 | inline bfunc_t f2() const 17725 | { 17726 | return f2_; 17727 | } 17728 | 17729 | inline std::string type_id() const exprtk_override 17730 | { 17731 | return id(); 17732 | } 17733 | 17734 | static inline std::string id() 17735 | { 17736 | return process_mode_t::template id<T0, T1, T2, T3>(); 17737 | } 17738 | 17739 | template <typename Allocator> 17740 | static inline expression_node<T>* allocate(Allocator& allocator, 17741 | T0 p0, T1 p1, T2 p2, T3 p3, 17742 | bfunc_t p4, bfunc_t p5, bfunc_t p6) 17743 | { 17744 | return allocator 17745 | .template allocate_type<node_type, T0, T1, T2, T3, bfunc_t, bfunc_t> 17746 | (p0, p1, p2, p3, p4, p5, p6); 17747 | } 17748 | 17749 | private: 17750 | 17751 | T0oT1oT2oT3(const node_type&) exprtk_delete; 17752 | node_type& operator=(const node_type&) exprtk_delete; 17753 | 17754 | T0 t0_; 17755 | T1 t1_; 17756 | T2 t2_; 17757 | T3 t3_; 17758 | const bfunc_t f0_; 17759 | const bfunc_t f1_; 17760 | const bfunc_t f2_; 17761 | }; 17762 | 17763 | template <typename T, typename T0, typename T1, typename T2> 17764 | class T0oT1oT2_sf3 exprtk_final : public T0oT1oT2_base_node<T> 17765 | { 17766 | public: 17767 | 17768 | typedef typename details::functor_t<T> functor_t; 17769 | typedef typename functor_t::tfunc_t tfunc_t; 17770 | typedef T value_type; 17771 | typedef T0oT1oT2_sf3<T,T0,T1,T2> node_type; 17772 | 17773 | T0oT1oT2_sf3(T0 p0, T1 p1, T2 p2, const tfunc_t p3) 17774 | : t0_(p0) 17775 | , t1_(p1) 17776 | , t2_(p2) 17777 | , f_ (p3) 17778 | {} 17779 | 17780 | inline typename expression_node<T>::node_type type() const exprtk_override 17781 | { 17782 | static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result; 17783 | return result; 17784 | } 17785 | 17786 | inline operator_type operation() const exprtk_override 17787 | { 17788 | return e_default; 17789 | } 17790 | 17791 | inline T value() const exprtk_override 17792 | { 17793 | return f_(t0_, t1_, t2_); 17794 | } 17795 | 17796 | inline T0 t0() const 17797 | { 17798 | return t0_; 17799 | } 17800 | 17801 | inline T1 t1() const 17802 | { 17803 | return t1_; 17804 | } 17805 | 17806 | inline T2 t2() const 17807 | { 17808 | return t2_; 17809 | } 17810 | 17811 | tfunc_t f() const 17812 | { 17813 | return f_; 17814 | } 17815 | 17816 | std::string type_id() const 17817 | { 17818 | return id(); 17819 | } 17820 | 17821 | static inline std::string id() 17822 | { 17823 | return "sf3" 17824 | } 17825 | 17826 | template <typename Allocator> 17827 | static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, tfunc_t p3) 17828 | { 17829 | return allocator 17830 | .template allocate_type<node_type, T0, T1, T2, tfunc_t> 17831 | (p0, p1, p2, p3); 17832 | } 17833 | 17834 | private: 17835 | 17836 | T0oT1oT2_sf3(const node_type&) exprtk_delete; 17837 | node_type& operator=(const node_type&) exprtk_delete; 17838 | 17839 | T0 t0_; 17840 | T1 t1_; 17841 | T2 t2_; 17842 | const tfunc_t f_; 17843 | }; 17844 | 17845 | template <typename T, typename T0, typename T1, typename T2> 17846 | class sf3ext_type_node : public T0oT1oT2_base_node<T> 17847 | { 17848 | public: 17849 | 17850 | virtual ~sf3ext_type_node() 17851 | {} 17852 | 17853 | virtual T0 t0() const = 0; 17854 | 17855 | virtual T1 t1() const = 0; 17856 | 17857 | virtual T2 t2() const = 0; 17858 | }; 17859 | 17860 | template <typename T, typename T0, typename T1, typename T2, typename SF3Operation> 17861 | class T0oT1oT2_sf3ext exprtk_final : public sf3ext_type_node<T,T0,T1,T2> 17862 | { 17863 | public: 17864 | 17865 | typedef T value_type; 17866 | typedef T0oT1oT2_sf3ext<T, T0, T1, T2, SF3Operation> node_type; 17867 | 17868 | T0oT1oT2_sf3ext(T0 p0, T1 p1, T2 p2) 17869 | : t0_(p0) 17870 | , t1_(p1) 17871 | , t2_(p2) 17872 | {} 17873 | 17874 | inline typename expression_node<T>::node_type type() const exprtk_override 17875 | { 17876 | static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result; 17877 | return result; 17878 | } 17879 | 17880 | inline operator_type operation() 17881 | { 17882 | return e_default; 17883 | } 17884 | 17885 | inline T value() const exprtk_override 17886 | { 17887 | return SF3Operation::process(t0_, t1_, t2_); 17888 | } 17889 | 17890 | T0 t0() const exprtk_override 17891 | { 17892 | return t0_; 17893 | } 17894 | 17895 | T1 t1() const exprtk_override 17896 | { 17897 | return t1_; 17898 | } 17899 | 17900 | T2 t2() const exprtk_override 17901 | { 17902 | return t2_; 17903 | } 17904 | 17905 | std::string type_id() const exprtk_override 17906 | { 17907 | return id(); 17908 | } 17909 | 17910 | static inline std::string id() 17911 | { 17912 | return SF3Operation::id(); 17913 | } 17914 | 17915 | template <typename Allocator> 17916 | static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2) 17917 | { 17918 | return allocator 17919 | .template allocate_type<node_type, T0, T1, T2> 17920 | (p0, p1, p2); 17921 | } 17922 | 17923 | private: 17924 | 17925 | T0oT1oT2_sf3ext(const node_type&) exprtk_delete; 17926 | node_type& operator=(const node_type&) exprtk_delete; 17927 | 17928 | T0 t0_; 17929 | T1 t1_; 17930 | T2 t2_; 17931 | }; 17932 | 17933 | template <typename T> 17934 | inline bool is_sf3ext_node(const expression_node<T>* n) 17935 | { 17936 | switch (n->type()) 17937 | { 17938 | case expression_node<T>::e_vovov : return true; 17939 | case expression_node<T>::e_vovoc : return true; 17940 | case expression_node<T>::e_vocov : return true; 17941 | case expression_node<T>::e_covov : return true; 17942 | case expression_node<T>::e_covoc : return true; 17943 | default : return false; 17944 | } 17945 | } 17946 | 17947 | template <typename T, typename T0, typename T1, typename T2, typename T3> 17948 | class T0oT1oT2oT3_sf4 exprtk_final : public T0oT1oT2_base_node<T> 17949 | { 17950 | public: 17951 | 17952 | typedef typename details::functor_t<T> functor_t; 17953 | typedef typename functor_t::qfunc_t qfunc_t; 17954 | typedef T value_type; 17955 | typedef T0oT1oT2oT3_sf4<T, T0, T1, T2, T3> node_type; 17956 | 17957 | T0oT1oT2oT3_sf4(T0 p0, T1 p1, T2 p2, T3 p3, const qfunc_t p4) 17958 | : t0_(p0) 17959 | , t1_(p1) 17960 | , t2_(p2) 17961 | , t3_(p3) 17962 | , f_ (p4) 17963 | {} 17964 | 17965 | inline typename expression_node<T>::node_type type() const exprtk_override 17966 | { 17967 | static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result; 17968 | return result; 17969 | } 17970 | 17971 | inline operator_type operation() const exprtk_override 17972 | { 17973 | return e_default; 17974 | } 17975 | 17976 | inline T value() const exprtk_override 17977 | { 17978 | return f_(t0_, t1_, t2_, t3_); 17979 | } 17980 | 17981 | inline T0 t0() const 17982 | { 17983 | return t0_; 17984 | } 17985 | 17986 | inline T1 t1() const 17987 | { 17988 | return t1_; 17989 | } 17990 | 17991 | inline T2 t2() const 17992 | { 17993 | return t2_; 17994 | } 17995 | 17996 | inline T3 t3() const 17997 | { 17998 | return t3_; 17999 | } 18000 | 18001 | qfunc_t f() const 18002 | { 18003 | return f_; 18004 | } 18005 | 18006 | std::string type_id() const 18007 | { 18008 | return id(); 18009 | } 18010 | 18011 | static inline std::string id() 18012 | { 18013 | return "sf4" 18014 | } 18015 | 18016 | template <typename Allocator> 18017 | static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, T3 p3, qfunc_t p4) 18018 | { 18019 | return allocator 18020 | .template allocate_type<node_type, T0, T1, T2, T3, qfunc_t> 18021 | (p0, p1, p2, p3, p4); 18022 | } 18023 | 18024 | private: 18025 | 18026 | T0oT1oT2oT3_sf4(const node_type&) exprtk_delete; 18027 | node_type& operator=(const node_type&) exprtk_delete; 18028 | 18029 | T0 t0_; 18030 | T1 t1_; 18031 | T2 t2_; 18032 | T3 t3_; 18033 | const qfunc_t f_; 18034 | }; 18035 | 18036 | template <typename T, typename T0, typename T1, typename T2, typename T3, typename SF4Operation> 18037 | class T0oT1oT2oT3_sf4ext exprtk_final : public T0oT1oT2oT3_base_node<T> 18038 | { 18039 | public: 18040 | 18041 | typedef T value_type; 18042 | typedef T0oT1oT2oT3_sf4ext<T, T0, T1, T2, T3, SF4Operation> node_type; 18043 | 18044 | T0oT1oT2oT3_sf4ext(T0 p0, T1 p1, T2 p2, T3 p3) 18045 | : t0_(p0) 18046 | , t1_(p1) 18047 | , t2_(p2) 18048 | , t3_(p3) 18049 | {} 18050 | 18051 | inline typename expression_node<T>::node_type type() const exprtk_override 18052 | { 18053 | static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result; 18054 | return result; 18055 | } 18056 | 18057 | inline T value() const exprtk_override 18058 | { 18059 | return SF4Operation::process(t0_, t1_, t2_, t3_); 18060 | } 18061 | 18062 | inline T0 t0() const 18063 | { 18064 | return t0_; 18065 | } 18066 | 18067 | inline T1 t1() const 18068 | { 18069 | return t1_; 18070 | } 18071 | 18072 | inline T2 t2() const 18073 | { 18074 | return t2_; 18075 | } 18076 | 18077 | inline T3 t3() const 18078 | { 18079 | return t3_; 18080 | } 18081 | 18082 | std::string type_id() const exprtk_override 18083 | { 18084 | return id(); 18085 | } 18086 | 18087 | static inline std::string id() 18088 | { 18089 | return SF4Operation::id(); 18090 | } 18091 | 18092 | template <typename Allocator> 18093 | static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, T3 p3) 18094 | { 18095 | return allocator 18096 | .template allocate_type<node_type, T0, T1, T2, T3> 18097 | (p0, p1, p2, p3); 18098 | } 18099 | 18100 | private: 18101 | 18102 | T0oT1oT2oT3_sf4ext(const node_type&) exprtk_delete; 18103 | node_type& operator=(const node_type&) exprtk_delete; 18104 | 18105 | T0 t0_; 18106 | T1 t1_; 18107 | T2 t2_; 18108 | T3 t3_; 18109 | }; 18110 | 18111 | template <typename T> 18112 | inline bool is_sf4ext_node(const expression_node<T>* n) 18113 | { 18114 | switch (n->type()) 18115 | { 18116 | case expression_node<T>::e_vovovov : return true; 18117 | case expression_node<T>::e_vovovoc : return true; 18118 | case expression_node<T>::e_vovocov : return true; 18119 | case expression_node<T>::e_vocovov : return true; 18120 | case expression_node<T>::e_covovov : return true; 18121 | case expression_node<T>::e_covocov : return true; 18122 | case expression_node<T>::e_vocovoc : return true; 18123 | case expression_node<T>::e_covovoc : return true; 18124 | case expression_node<T>::e_vococov : return true; 18125 | default : return false; 18126 | } 18127 | } 18128 | 18129 | template <typename T, typename T0, typename T1> 18130 | struct T0oT1_define 18131 | { 18132 | typedef details::T0oT1<T, T0, T1> type0; 18133 | }; 18134 | 18135 | template <typename T, typename T0, typename T1, typename T2> 18136 | struct T0oT1oT2_define 18137 | { 18138 | typedef details::T0oT1oT2<T, T0, T1, T2, typename T0oT1oT2process<T>::mode0> type0; 18139 | typedef details::T0oT1oT2<T, T0, T1, T2, typename T0oT1oT2process<T>::mode1> type1; 18140 | typedef details::T0oT1oT2_sf3<T, T0, T1, T2> sf3_type; 18141 | typedef details::sf3ext_type_node<T, T0, T1, T2> sf3_type_node; 18142 | }; 18143 | 18144 | template <typename T, typename T0, typename T1, typename T2, typename T3> 18145 | struct T0oT1oT2oT3_define 18146 | { 18147 | typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode0> type0; 18148 | typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode1> type1; 18149 | typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode2> type2; 18150 | typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode3> type3; 18151 | typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode4> type4; 18152 | typedef details::T0oT1oT2oT3_sf4<T, T0, T1, T2, T3> sf4_type; 18153 | }; 18154 | 18155 | template <typename T, typename Operation> 18156 | class vov_node exprtk_final : public vov_base_node<T> 18157 | { 18158 | public: 18159 | 18160 | typedef expression_node<T>* expression_ptr; 18161 | typedef Operation operation_t; 18162 | 18163 | // variable op variable node 18164 | explicit vov_node(const T& var0, const T& var1) 18165 | : v0_(var0) 18166 | , v1_(var1) 18167 | {} 18168 | 18169 | inline T value() const exprtk_override 18170 | { 18171 | return Operation::process(v0_,v1_); 18172 | } 18173 | 18174 | inline typename expression_node<T>::node_type type() const exprtk_override 18175 | { 18176 | return Operation::type(); 18177 | } 18178 | 18179 | inline operator_type operation() const exprtk_override 18180 | { 18181 | return Operation::operation(); 18182 | } 18183 | 18184 | inline const T& v0() const exprtk_override 18185 | { 18186 | return v0_; 18187 | } 18188 | 18189 | inline const T& v1() const exprtk_override 18190 | { 18191 | return v1_; 18192 | } 18193 | 18194 | protected: 18195 | 18196 | const T& v0_; 18197 | const T& v1_; 18198 | 18199 | private: 18200 | 18201 | vov_node(const vov_node<T,Operation>&) exprtk_delete; 18202 | vov_node<T,Operation>& operator=(const vov_node<T,Operation>&) exprtk_delete; 18203 | }; 18204 | 18205 | template <typename T, typename Operation> 18206 | class cov_node exprtk_final : public cov_base_node<T> 18207 | { 18208 | public: 18209 | 18210 | typedef expression_node<T>* expression_ptr; 18211 | typedef Operation operation_t; 18212 | 18213 | // constant op variable node 18214 | explicit cov_node(const T& const_var, const T& var) 18215 | : c_(const_var) 18216 | , v_(var) 18217 | {} 18218 | 18219 | inline T value() const exprtk_override 18220 | { 18221 | return Operation::process(c_,v_); 18222 | } 18223 | 18224 | inline typename expression_node<T>::node_type type() const exprtk_override 18225 | { 18226 | return Operation::type(); 18227 | } 18228 | 18229 | inline operator_type operation() const exprtk_override 18230 | { 18231 | return Operation::operation(); 18232 | } 18233 | 18234 | inline const T c() const exprtk_override 18235 | { 18236 | return c_; 18237 | } 18238 | 18239 | inline const T& v() const exprtk_override 18240 | { 18241 | return v_; 18242 | } 18243 | 18244 | protected: 18245 | 18246 | const T c_; 18247 | const T& v_; 18248 | 18249 | private: 18250 | 18251 | cov_node(const cov_node<T,Operation>&) exprtk_delete; 18252 | cov_node<T,Operation>& operator=(const cov_node<T,Operation>&) exprtk_delete; 18253 | }; 18254 | 18255 | template <typename T, typename Operation> 18256 | class voc_node exprtk_final : public voc_base_node<T> 18257 | { 18258 | public: 18259 | 18260 | typedef expression_node<T>* expression_ptr; 18261 | typedef Operation operation_t; 18262 | 18263 | // variable op constant node 18264 | explicit voc_node(const T& var, const T& const_var) 18265 | : v_(var) 18266 | , c_(const_var) 18267 | {} 18268 | 18269 | inline T value() const exprtk_override 18270 | { 18271 | return Operation::process(v_,c_); 18272 | } 18273 | 18274 | inline operator_type operation() const exprtk_override 18275 | { 18276 | return Operation::operation(); 18277 | } 18278 | 18279 | inline const T c() const exprtk_override 18280 | { 18281 | return c_; 18282 | } 18283 | 18284 | inline const T& v() const exprtk_override 18285 | { 18286 | return v_; 18287 | } 18288 | 18289 | protected: 18290 | 18291 | const T& v_; 18292 | const T c_; 18293 | 18294 | private: 18295 | 18296 | voc_node(const voc_node<T,Operation>&) exprtk_delete; 18297 | voc_node<T,Operation>& operator=(const voc_node<T,Operation>&) exprtk_delete; 18298 | }; 18299 | 18300 | template <typename T, typename Operation> 18301 | class vob_node exprtk_final : public vob_base_node<T> 18302 | { 18303 | public: 18304 | 18305 | typedef expression_node<T>* expression_ptr; 18306 | typedef std::pair<expression_ptr,bool> branch_t; 18307 | typedef Operation operation_t; 18308 | 18309 | // variable op binary node 18310 | explicit vob_node(const T& var, const expression_ptr branch) 18311 | : v_(var) 18312 | { 18313 | construct_branch_pair(branch_, branch); 18314 | assert(valid()); 18315 | } 18316 | 18317 | inline T value() const exprtk_override 18318 | { 18319 | return Operation::process(v_,branch_.first->value()); 18320 | } 18321 | 18322 | inline const T& v() const exprtk_override 18323 | { 18324 | return v_; 18325 | } 18326 | 18327 | inline bool valid() const exprtk_override 18328 | { 18329 | return branch_.first && branch_.first->valid(); 18330 | } 18331 | 18332 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 18333 | { 18334 | return branch_.first; 18335 | } 18336 | 18337 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 18338 | { 18339 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 18340 | } 18341 | 18342 | std::size_t node_depth() const exprtk_override 18343 | { 18344 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 18345 | } 18346 | 18347 | private: 18348 | 18349 | vob_node(const vob_node<T,Operation>&) exprtk_delete; 18350 | vob_node<T,Operation>& operator=(const vob_node<T,Operation>&) exprtk_delete; 18351 | 18352 | const T& v_; 18353 | branch_t branch_; 18354 | }; 18355 | 18356 | template <typename T, typename Operation> 18357 | class bov_node exprtk_final : public bov_base_node<T> 18358 | { 18359 | public: 18360 | 18361 | typedef expression_node<T>* expression_ptr; 18362 | typedef std::pair<expression_ptr,bool> branch_t; 18363 | typedef Operation operation_t; 18364 | 18365 | // binary node op variable node 18366 | explicit bov_node(const expression_ptr branch, const T& var) 18367 | : v_(var) 18368 | { 18369 | construct_branch_pair(branch_, branch); 18370 | assert(valid()); 18371 | } 18372 | 18373 | inline T value() const exprtk_override 18374 | { 18375 | return Operation::process(branch_.first->value(),v_); 18376 | } 18377 | 18378 | inline const T& v() const exprtk_override 18379 | { 18380 | return v_; 18381 | } 18382 | 18383 | inline bool valid() const exprtk_override 18384 | { 18385 | return branch_.first && branch_.first->valid(); 18386 | } 18387 | 18388 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 18389 | { 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 | bov_node(const bov_node<T,Operation>&) exprtk_delete; 18406 | bov_node<T,Operation>& operator=(const bov_node<T,Operation>&) exprtk_delete; 18407 | 18408 | const T& v_; 18409 | branch_t branch_; 18410 | }; 18411 | 18412 | template <typename T, typename Operation> 18413 | class cob_node exprtk_final : public cob_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 | // constant op variable node 18422 | explicit cob_node(const T const_var, const expression_ptr branch) 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(c_,branch_.first->value()); 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 | cob_node(const cob_node<T,Operation>&) exprtk_delete; 18478 | cob_node<T,Operation>& operator=(const cob_node<T,Operation>&) exprtk_delete; 18479 | 18480 | const T c_; 18481 | branch_t branch_; 18482 | }; 18483 | 18484 | template <typename T, typename Operation> 18485 | class boc_node exprtk_final : public boc_base_node<T> 18486 | { 18487 | public: 18488 | 18489 | typedef expression_node<T>* expression_ptr; 18490 | typedef std::pair<expression_ptr,bool> branch_t; 18491 | typedef Operation operation_t; 18492 | 18493 | // binary node op constant node 18494 | explicit boc_node(const expression_ptr branch, const T const_var) 18495 | : c_(const_var) 18496 | { 18497 | construct_branch_pair(branch_, branch); 18498 | assert(valid()); 18499 | } 18500 | 18501 | inline T value() const exprtk_override 18502 | { 18503 | return Operation::process(branch_.first->value(),c_); 18504 | } 18505 | 18506 | inline operator_type operation() const exprtk_override 18507 | { 18508 | return Operation::operation(); 18509 | } 18510 | 18511 | inline const T c() const exprtk_override 18512 | { 18513 | return c_; 18514 | } 18515 | 18516 | inline void set_c(const T new_c) exprtk_override 18517 | { 18518 | (*const_cast<T*>(&c_)) = new_c; 18519 | } 18520 | 18521 | inline bool valid() const exprtk_override 18522 | { 18523 | return branch_.first && branch_.first->valid(); 18524 | } 18525 | 18526 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 18527 | { 18528 | return branch_.first; 18529 | } 18530 | 18531 | inline expression_node<T>* move_branch(const std::size_t&) exprtk_override 18532 | { 18533 | branch_.second = false; 18534 | return branch_.first; 18535 | } 18536 | 18537 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 18538 | { 18539 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 18540 | } 18541 | 18542 | std::size_t node_depth() const exprtk_override 18543 | { 18544 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 18545 | } 18546 | 18547 | private: 18548 | 18549 | boc_node(const boc_node<T,Operation>&) exprtk_delete; 18550 | boc_node<T,Operation>& operator=(const boc_node<T,Operation>&) exprtk_delete; 18551 | 18552 | const T c_; 18553 | branch_t branch_; 18554 | }; 18555 | 18556 | #ifndef exprtk_disable_string_capabilities 18557 | template <typename T, typename SType0, typename SType1, typename Operation> 18558 | class sos_node exprtk_final : public sos_base_node<T> 18559 | { 18560 | public: 18561 | 18562 | typedef expression_node<T>* expression_ptr; 18563 | typedef Operation operation_t; 18564 | 18565 | // string op string node 18566 | explicit sos_node(SType0 p0, SType1 p1) 18567 | : s0_(p0) 18568 | , s1_(p1) 18569 | {} 18570 | 18571 | inline T value() const exprtk_override 18572 | { 18573 | return Operation::process(s0_,s1_); 18574 | } 18575 | 18576 | inline typename expression_node<T>::node_type type() const exprtk_override 18577 | { 18578 | return Operation::type(); 18579 | } 18580 | 18581 | inline operator_type operation() const exprtk_override 18582 | { 18583 | return Operation::operation(); 18584 | } 18585 | 18586 | inline std::string& s0() 18587 | { 18588 | return s0_; 18589 | } 18590 | 18591 | inline std::string& s1() 18592 | { 18593 | return s1_; 18594 | } 18595 | 18596 | protected: 18597 | 18598 | SType0 s0_; 18599 | SType1 s1_; 18600 | 18601 | private: 18602 | 18603 | sos_node(const sos_node<T,SType0,SType1,Operation>&) exprtk_delete; 18604 | sos_node<T,SType0,SType1,Operation>& operator=(const sos_node<T,SType0,SType1,Operation>&) exprtk_delete; 18605 | }; 18606 | 18607 | template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation> 18608 | class str_xrox_node exprtk_final : public sos_base_node<T> 18609 | { 18610 | public: 18611 | 18612 | typedef expression_node<T>* expression_ptr; 18613 | typedef Operation operation_t; 18614 | typedef str_xrox_node<T,SType0,SType1,RangePack,Operation> node_type; 18615 | 18616 | // string-range op string node 18617 | explicit str_xrox_node(SType0 p0, SType1 p1, RangePack rp0) 18618 | : s0_ (p0 ) 18619 | , s1_ (p1 ) 18620 | , rp0_(rp0) 18621 | {} 18622 | 18623 | ~str_xrox_node() exprtk_override 18624 | { 18625 | rp0_.free(); 18626 | } 18627 | 18628 | inline T value() const exprtk_override 18629 | { 18630 | std::size_t r0 = 0; 18631 | std::size_t r1 = 0; 18632 | 18633 | if (rp0_(r0, r1, s0_)) 18634 | return Operation::process(s0_.substr(r0, (r1 - r0)), s1_); 18635 | else 18636 | return T(0); 18637 | } 18638 | 18639 | inline typename expression_node<T>::node_type type() const exprtk_override 18640 | { 18641 | return Operation::type(); 18642 | } 18643 | 18644 | inline operator_type operation() const exprtk_override 18645 | { 18646 | return Operation::operation(); 18647 | } 18648 | 18649 | inline std::string& s0() 18650 | { 18651 | return s0_; 18652 | } 18653 | 18654 | inline std::string& s1() 18655 | { 18656 | return s1_; 18657 | } 18658 | 18659 | protected: 18660 | 18661 | SType0 s0_; 18662 | SType1 s1_; 18663 | RangePack rp0_; 18664 | 18665 | private: 18666 | 18667 | str_xrox_node(const node_type&) exprtk_delete; 18668 | node_type& operator=(const node_type&) exprtk_delete; 18669 | }; 18670 | 18671 | template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation> 18672 | class str_xoxr_node exprtk_final : public sos_base_node<T> 18673 | { 18674 | public: 18675 | 18676 | typedef expression_node<T>* expression_ptr; 18677 | typedef Operation operation_t; 18678 | typedef str_xoxr_node<T,SType0,SType1,RangePack,Operation> node_type; 18679 | 18680 | // string op string range node 18681 | explicit str_xoxr_node(SType0 p0, SType1 p1, RangePack rp1) 18682 | : s0_ (p0 ) 18683 | , s1_ (p1 ) 18684 | , rp1_(rp1) 18685 | {} 18686 | 18687 | ~str_xoxr_node() 18688 | { 18689 | rp1_.free(); 18690 | } 18691 | 18692 | inline T value() const exprtk_override 18693 | { 18694 | std::size_t r0 = 0; 18695 | std::size_t r1 = 0; 18696 | 18697 | if (rp1_(r0, r1, s1_)) 18698 | { 18699 | return Operation::process 18700 | ( 18701 | s0_, 18702 | s1_.substr(r0, (r1 - r0)) 18703 | ); 18704 | } 18705 | else 18706 | return T(0); 18707 | } 18708 | 18709 | inline typename expression_node<T>::node_type type() const exprtk_override 18710 | { 18711 | return Operation::type(); 18712 | } 18713 | 18714 | inline operator_type operation() const exprtk_override 18715 | { 18716 | return Operation::operation(); 18717 | } 18718 | 18719 | inline std::string& s0() 18720 | { 18721 | return s0_; 18722 | } 18723 | 18724 | inline std::string& s1() 18725 | { 18726 | return s1_; 18727 | } 18728 | 18729 | protected: 18730 | 18731 | SType0 s0_; 18732 | SType1 s1_; 18733 | RangePack rp1_; 18734 | 18735 | private: 18736 | 18737 | str_xoxr_node(const node_type&) exprtk_delete; 18738 | node_type& operator=(const node_type&) exprtk_delete; 18739 | }; 18740 | 18741 | template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation> 18742 | class str_xroxr_node exprtk_final : public sos_base_node<T> 18743 | { 18744 | public: 18745 | 18746 | typedef expression_node<T>* expression_ptr; 18747 | typedef Operation operation_t; 18748 | typedef str_xroxr_node<T,SType0,SType1,RangePack,Operation> node_type; 18749 | 18750 | // string-range op string-range node 18751 | explicit str_xroxr_node(SType0 p0, SType1 p1, RangePack rp0, RangePack rp1) 18752 | : s0_ (p0 ) 18753 | , s1_ (p1 ) 18754 | , rp0_(rp0) 18755 | , rp1_(rp1) 18756 | {} 18757 | 18758 | ~str_xroxr_node() exprtk_override 18759 | { 18760 | rp0_.free(); 18761 | rp1_.free(); 18762 | } 18763 | 18764 | inline T value() const exprtk_override 18765 | { 18766 | std::size_t r0_0 = 0; 18767 | std::size_t r0_1 = 0; 18768 | std::size_t r1_0 = 0; 18769 | std::size_t r1_1 = 0; 18770 | 18771 | if ( 18772 | rp0_(r0_0, r1_0, s0_) && 18773 | rp1_(r0_1, r1_1, s1_) 18774 | ) 18775 | { 18776 | return Operation::process 18777 | ( 18778 | s0_.substr(r0_0, (r1_0 - r0_0)), 18779 | s1_.substr(r0_1, (r1_1 - r0_1)) 18780 | ); 18781 | } 18782 | else 18783 | return T(0); 18784 | } 18785 | 18786 | inline typename expression_node<T>::node_type type() const exprtk_override 18787 | { 18788 | return Operation::type(); 18789 | } 18790 | 18791 | inline operator_type operation() const exprtk_override 18792 | { 18793 | return Operation::operation(); 18794 | } 18795 | 18796 | inline std::string& s0() 18797 | { 18798 | return s0_; 18799 | } 18800 | 18801 | inline std::string& s1() 18802 | { 18803 | return s1_; 18804 | } 18805 | 18806 | protected: 18807 | 18808 | SType0 s0_; 18809 | SType1 s1_; 18810 | RangePack rp0_; 18811 | RangePack rp1_; 18812 | 18813 | private: 18814 | 18815 | str_xroxr_node(const node_type&) exprtk_delete; 18816 | node_type& operator=(const node_type&) exprtk_delete; 18817 | }; 18818 | 18819 | template <typename T, typename Operation> 18820 | class str_sogens_node exprtk_final : public binary_node<T> 18821 | { 18822 | public: 18823 | 18824 | typedef expression_node <T>* expression_ptr; 18825 | typedef string_base_node<T>* str_base_ptr; 18826 | typedef range_pack <T> range_t; 18827 | typedef range_t* range_ptr; 18828 | typedef range_interface <T> irange_t; 18829 | typedef irange_t* irange_ptr; 18830 | 18831 | using binary_node<T>::branch; 18832 | 18833 | str_sogens_node(const operator_type& opr, 18834 | expression_ptr branch0, 18835 | expression_ptr branch1) 18836 | : binary_node<T>(opr, branch0, branch1) 18837 | , str0_base_ptr_ (0) 18838 | , str1_base_ptr_ (0) 18839 | , str0_range_ptr_(0) 18840 | , str1_range_ptr_(0) 18841 | , initialised_ (false) 18842 | { 18843 | if (is_generally_string_node(branch(0))) 18844 | { 18845 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0)); 18846 | 18847 | if (0 == str0_base_ptr_) 18848 | return; 18849 | 18850 | irange_ptr range = dynamic_cast<irange_ptr>(branch(0)); 18851 | 18852 | if (0 == range) 18853 | return; 18854 | 18855 | str0_range_ptr_ = &(range->range_ref()); 18856 | } 18857 | 18858 | if (is_generally_string_node(branch(1))) 18859 | { 18860 | str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1)); 18861 | 18862 | if (0 == str1_base_ptr_) 18863 | return; 18864 | 18865 | irange_ptr range = dynamic_cast<irange_ptr>(branch(1)); 18866 | 18867 | if (0 == range) 18868 | return; 18869 | 18870 | str1_range_ptr_ = &(range->range_ref()); 18871 | } 18872 | 18873 | initialised_ = 18874 | str0_base_ptr_ && 18875 | str1_base_ptr_ && 18876 | str0_range_ptr_ && 18877 | str1_range_ptr_; 18878 | 18879 | assert(valid()); 18880 | } 18881 | 18882 | inline T value() const exprtk_override 18883 | { 18884 | branch(0)->value(); 18885 | branch(1)->value(); 18886 | 18887 | std::size_t str0_r0 = 0; 18888 | std::size_t str0_r1 = 0; 18889 | 18890 | std::size_t str1_r0 = 0; 18891 | std::size_t str1_r1 = 0; 18892 | 18893 | const range_t& range0 = (*str0_range_ptr_); 18894 | const range_t& range1 = (*str1_range_ptr_); 18895 | 18896 | if ( 18897 | range0(str0_r0, str0_r1, *str0_base_ptr_) && 18898 | range1(str1_r0, str1_r1, *str1_base_ptr_) 18899 | ) 18900 | { 18901 | return Operation::process 18902 | ( 18903 | str0_base_ptr_->str().substr(str0_r0,(str0_r1 - str0_r0)), 18904 | str1_base_ptr_->str().substr(str1_r0,(str1_r1 - str1_r0)) 18905 | ); 18906 | } 18907 | 18908 | return std::numeric_limits<T>::quiet_NaN(); 18909 | } 18910 | 18911 | inline typename expression_node<T>::node_type type() const exprtk_override 18912 | { 18913 | return Operation::type(); 18914 | } 18915 | 18916 | inline bool valid() const exprtk_override 18917 | { 18918 | return initialised_; 18919 | } 18920 | 18921 | private: 18922 | 18923 | str_sogens_node(const str_sogens_node<T,Operation>&) exprtk_delete; 18924 | str_sogens_node<T,Operation>& operator=(const str_sogens_node<T,Operation>&) exprtk_delete; 18925 | 18926 | str_base_ptr str0_base_ptr_; 18927 | str_base_ptr str1_base_ptr_; 18928 | range_ptr str0_range_ptr_; 18929 | range_ptr str1_range_ptr_; 18930 | bool initialised_; 18931 | }; 18932 | 18933 | template <typename T, typename SType0, typename SType1, typename SType2, typename Operation> 18934 | class sosos_node exprtk_final : public sosos_base_node<T> 18935 | { 18936 | public: 18937 | 18938 | typedef expression_node<T>* expression_ptr; 18939 | typedef Operation operation_t; 18940 | typedef sosos_node<T, SType0, SType1, SType2, Operation> node_type; 18941 | 18942 | // string op string op string node 18943 | explicit sosos_node(SType0 p0, SType1 p1, SType2 p2) 18944 | : s0_(p0) 18945 | , s1_(p1) 18946 | , s2_(p2) 18947 | {} 18948 | 18949 | inline T value() const exprtk_override 18950 | { 18951 | return Operation::process(s0_, s1_, s2_); 18952 | } 18953 | 18954 | inline typename expression_node<T>::node_type type() const exprtk_override 18955 | { 18956 | return Operation::type(); 18957 | } 18958 | 18959 | inline operator_type operation() const exprtk_override 18960 | { 18961 | return Operation::operation(); 18962 | } 18963 | 18964 | inline std::string& s0() 18965 | { 18966 | return s0_; 18967 | } 18968 | 18969 | inline std::string& s1() 18970 | { 18971 | return s1_; 18972 | } 18973 | 18974 | inline std::string& s2() 18975 | { 18976 | return s2_; 18977 | } 18978 | 18979 | protected: 18980 | 18981 | SType0 s0_; 18982 | SType1 s1_; 18983 | SType2 s2_; 18984 | 18985 | private: 18986 | 18987 | sosos_node(const node_type&) exprtk_delete; 18988 | node_type& operator=(const node_type&) exprtk_delete; 18989 | }; 18990 | #endif 18991 | 18992 | template <typename T, typename PowOp> 18993 | class ipow_node exprtk_final: public expression_node<T> 18994 | { 18995 | public: 18996 | 18997 | typedef expression_node<T>* expression_ptr; 18998 | typedef PowOp operation_t; 18999 | 19000 | explicit ipow_node(const T& v) 19001 | : v_(v) 19002 | {} 19003 | 19004 | inline T value() const exprtk_override 19005 | { 19006 | return PowOp::result(v_); 19007 | } 19008 | 19009 | inline typename expression_node<T>::node_type type() const exprtk_override 19010 | { 19011 | return expression_node<T>::e_ipow; 19012 | } 19013 | 19014 | private: 19015 | 19016 | ipow_node(const ipow_node<T,PowOp>&) exprtk_delete; 19017 | ipow_node<T,PowOp>& operator=(const ipow_node<T,PowOp>&) exprtk_delete; 19018 | 19019 | const T& v_; 19020 | }; 19021 | 19022 | template <typename T, typename PowOp> 19023 | class bipow_node exprtk_final : public expression_node<T> 19024 | { 19025 | public: 19026 | 19027 | typedef expression_node<T>* expression_ptr; 19028 | typedef std::pair<expression_ptr, bool> branch_t; 19029 | typedef PowOp operation_t; 19030 | 19031 | explicit bipow_node(expression_ptr branch) 19032 | { 19033 | construct_branch_pair(branch_, branch); 19034 | assert(valid()); 19035 | } 19036 | 19037 | inline T value() const exprtk_override 19038 | { 19039 | return PowOp::result(branch_.first->value()); 19040 | } 19041 | 19042 | inline typename expression_node<T>::node_type type() const exprtk_override 19043 | { 19044 | return expression_node<T>::e_ipow; 19045 | } 19046 | 19047 | inline bool valid() const exprtk_override 19048 | { 19049 | return branch_.first && branch_.first->valid(); 19050 | } 19051 | 19052 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 19053 | { 19054 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 19055 | } 19056 | 19057 | std::size_t node_depth() const exprtk_override 19058 | { 19059 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 19060 | } 19061 | 19062 | private: 19063 | 19064 | bipow_node(const bipow_node<T,PowOp>&) exprtk_delete; 19065 | bipow_node<T,PowOp>& operator=(const bipow_node<T,PowOp>&) exprtk_delete; 19066 | 19067 | branch_t branch_; 19068 | }; 19069 | 19070 | template <typename T, typename PowOp> 19071 | class ipowinv_node exprtk_final : public expression_node<T> 19072 | { 19073 | public: 19074 | 19075 | typedef expression_node<T>* expression_ptr; 19076 | typedef PowOp operation_t; 19077 | 19078 | explicit ipowinv_node(const T& v) 19079 | : v_(v) 19080 | {} 19081 | 19082 | inline T value() const exprtk_override 19083 | { 19084 | return (T(1) / PowOp::result(v_)); 19085 | } 19086 | 19087 | inline typename expression_node<T>::node_type type() const exprtk_override 19088 | { 19089 | return expression_node<T>::e_ipowinv; 19090 | } 19091 | 19092 | private: 19093 | 19094 | ipowinv_node(const ipowinv_node<T,PowOp>&) exprtk_delete; 19095 | ipowinv_node<T,PowOp>& operator=(const ipowinv_node<T,PowOp>&) exprtk_delete; 19096 | 19097 | const T& v_; 19098 | }; 19099 | 19100 | template <typename T, typename PowOp> 19101 | class bipowinv_node exprtk_final : public expression_node<T> 19102 | { 19103 | public: 19104 | 19105 | typedef expression_node<T>* expression_ptr; 19106 | typedef std::pair<expression_ptr, bool> branch_t; 19107 | typedef PowOp operation_t; 19108 | 19109 | explicit bipowinv_node(expression_ptr branch) 19110 | { 19111 | construct_branch_pair(branch_, branch); 19112 | assert(valid()); 19113 | } 19114 | 19115 | inline T value() const exprtk_override 19116 | { 19117 | return (T(1) / PowOp::result(branch_.first->value())); 19118 | } 19119 | 19120 | inline typename expression_node<T>::node_type type() const exprtk_override 19121 | { 19122 | return expression_node<T>::e_ipowinv; 19123 | } 19124 | 19125 | inline bool valid() const exprtk_override 19126 | { 19127 | return branch_.first && branch_.first->valid(); 19128 | } 19129 | 19130 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 19131 | { 19132 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 19133 | } 19134 | 19135 | std::size_t node_depth() const exprtk_override 19136 | { 19137 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 19138 | } 19139 | 19140 | private: 19141 | 19142 | bipowinv_node(const bipowinv_node<T,PowOp>&) exprtk_delete; 19143 | bipowinv_node<T,PowOp>& operator=(const bipowinv_node<T,PowOp>&) exprtk_delete; 19144 | 19145 | branch_t branch_; 19146 | }; 19147 | 19148 | template <typename T> 19149 | inline bool is_vov_node(const expression_node<T>* node) 19150 | { 19151 | return (0 != dynamic_cast<const vov_base_node<T>*>(node)); 19152 | } 19153 | 19154 | template <typename T> 19155 | inline bool is_cov_node(const expression_node<T>* node) 19156 | { 19157 | return (0 != dynamic_cast<const cov_base_node<T>*>(node)); 19158 | } 19159 | 19160 | template <typename T> 19161 | inline bool is_voc_node(const expression_node<T>* node) 19162 | { 19163 | return (0 != dynamic_cast<const voc_base_node<T>*>(node)); 19164 | } 19165 | 19166 | template <typename T> 19167 | inline bool is_cob_node(const expression_node<T>* node) 19168 | { 19169 | return (0 != dynamic_cast<const cob_base_node<T>*>(node)); 19170 | } 19171 | 19172 | template <typename T> 19173 | inline bool is_boc_node(const expression_node<T>* node) 19174 | { 19175 | return (0 != dynamic_cast<const boc_base_node<T>*>(node)); 19176 | } 19177 | 19178 | template <typename T> 19179 | inline bool is_t0ot1ot2_node(const expression_node<T>* node) 19180 | { 19181 | return (0 != dynamic_cast<const T0oT1oT2_base_node<T>*>(node)); 19182 | } 19183 | 19184 | template <typename T> 19185 | inline bool is_t0ot1ot2ot3_node(const expression_node<T>* node) 19186 | { 19187 | return (0 != dynamic_cast<const T0oT1oT2oT3_base_node<T>*>(node)); 19188 | } 19189 | 19190 | template <typename T> 19191 | inline bool is_uv_node(const expression_node<T>* node) 19192 | { 19193 | return (0 != dynamic_cast<const uv_base_node<T>*>(node)); 19194 | } 19195 | 19196 | template <typename T> 19197 | inline bool is_string_node(const expression_node<T>* node) 19198 | { 19199 | return node && (expression_node<T>::e_stringvar == node->type()); 19200 | } 19201 | 19202 | template <typename T> 19203 | inline bool is_string_range_node(const expression_node<T>* node) 19204 | { 19205 | return node && (expression_node<T>::e_stringvarrng == node->type()); 19206 | } 19207 | 19208 | template <typename T> 19209 | inline bool is_const_string_node(const expression_node<T>* node) 19210 | { 19211 | return node && (expression_node<T>::e_stringconst == node->type()); 19212 | } 19213 | 19214 | template <typename T> 19215 | inline bool is_const_string_range_node(const expression_node<T>* node) 19216 | { 19217 | return node && (expression_node<T>::e_cstringvarrng == node->type()); 19218 | } 19219 | 19220 | template <typename T> 19221 | inline bool is_string_assignment_node(const expression_node<T>* node) 19222 | { 19223 | return node && (expression_node<T>::e_strass == node->type()); 19224 | } 19225 | 19226 | template <typename T> 19227 | inline bool is_string_concat_node(const expression_node<T>* node) 19228 | { 19229 | return node && (expression_node<T>::e_strconcat == node->type()); 19230 | } 19231 | 19232 | template <typename T> 19233 | inline bool is_string_function_node(const expression_node<T>* node) 19234 | { 19235 | return node && (expression_node<T>::e_strfunction == node->type()); 19236 | } 19237 | 19238 | template <typename T> 19239 | inline bool is_string_condition_node(const expression_node<T>* node) 19240 | { 19241 | return node && (expression_node<T>::e_strcondition == node->type()); 19242 | } 19243 | 19244 | template <typename T> 19245 | inline bool is_string_ccondition_node(const expression_node<T>* node) 19246 | { 19247 | return node && (expression_node<T>::e_strccondition == node->type()); 19248 | } 19249 | 19250 | template <typename T> 19251 | inline bool is_string_vararg_node(const expression_node<T>* node) 19252 | { 19253 | return node && (expression_node<T>::e_stringvararg == node->type()); 19254 | } 19255 | 19256 | template <typename T> 19257 | inline bool is_genricstring_range_node(const expression_node<T>* node) 19258 | { 19259 | return node && (expression_node<T>::e_strgenrange == node->type()); 19260 | } 19261 | 19262 | template <typename T> 19263 | inline bool is_generally_string_node(const expression_node<T>* node) 19264 | { 19265 | if (node) 19266 | { 19267 | switch (node->type()) 19268 | { 19269 | case expression_node<T>::e_stringvar : 19270 | case expression_node<T>::e_stringconst : 19271 | case expression_node<T>::e_stringvarrng : 19272 | case expression_node<T>::e_cstringvarrng : 19273 | case expression_node<T>::e_strgenrange : 19274 | case expression_node<T>::e_strass : 19275 | case expression_node<T>::e_strconcat : 19276 | case expression_node<T>::e_strfunction : 19277 | case expression_node<T>::e_strcondition : 19278 | case expression_node<T>::e_strccondition : 19279 | case expression_node<T>::e_stringvararg : return true; 19280 | default : return false; 19281 | } 19282 | } 19283 | 19284 | return false; 19285 | } 19286 | 19287 | template <typename T> 19288 | inline bool is_loop_node(const expression_node<T>* node) 19289 | { 19290 | if (node) 19291 | { 19292 | switch (node->type()) 19293 | { 19294 | case expression_node<T>::e_for : 19295 | case expression_node<T>::e_repeat : 19296 | case expression_node<T>::e_while : return true; 19297 | default : return false; 19298 | } 19299 | } 19300 | 19301 | return false; 19302 | } 19303 | 19304 | template <typename T> 19305 | inline bool is_block_node(const expression_node<T>* node) 19306 | { 19307 | if (node) 19308 | { 19309 | if (is_loop_node(node)) 19310 | { 19311 | return true; 19312 | } 19313 | 19314 | switch (node->type()) 19315 | { 19316 | case expression_node<T>::e_conditional : 19317 | case expression_node<T>::e_mswitch : 19318 | case expression_node<T>::e_switch : 19319 | case expression_node<T>::e_vararg : return true; 19320 | default : return false; 19321 | } 19322 | } 19323 | 19324 | return false; 19325 | } 19326 | 19327 | class node_allocator 19328 | { 19329 | public: 19330 | 19331 | template <typename ResultNode, typename OpType, typename ExprNode> 19332 | inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[1]) 19333 | { 19334 | expression_node<typename ResultNode::value_type>* result = 19335 | allocate<ResultNode>(operation, branch[0]); 19336 | result->node_depth(); 19337 | return result; 19338 | } 19339 | 19340 | template <typename ResultNode, typename OpType, typename ExprNode> 19341 | inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[2]) 19342 | { 19343 | expression_node<typename ResultNode::value_type>* result = 19344 | allocate<ResultNode>(operation, branch[0], branch[1]); 19345 | result->node_depth(); 19346 | return result; 19347 | } 19348 | 19349 | template <typename ResultNode, typename OpType, typename ExprNode> 19350 | inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[3]) 19351 | { 19352 | expression_node<typename ResultNode::value_type>* result = 19353 | allocate<ResultNode>(operation, branch[0], branch[1], branch[2]); 19354 | result->node_depth(); 19355 | return result; 19356 | } 19357 | 19358 | template <typename ResultNode, typename OpType, typename ExprNode> 19359 | inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[4]) 19360 | { 19361 | expression_node<typename ResultNode::value_type>* result = 19362 | allocate<ResultNode>(operation, branch[0], branch[1], branch[2], branch[3]); 19363 | result->node_depth(); 19364 | return result; 19365 | } 19366 | 19367 | template <typename ResultNode, typename OpType, typename ExprNode> 19368 | inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[5]) 19369 | { 19370 | expression_node<typename ResultNode::value_type>* result = 19371 | allocate<ResultNode>(operation, branch[0],branch[1], branch[2], branch[3], branch[4]); 19372 | result->node_depth(); 19373 | return result; 19374 | } 19375 | 19376 | template <typename ResultNode, typename OpType, typename ExprNode> 19377 | inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[6]) 19378 | { 19379 | expression_node<typename ResultNode::value_type>* result = 19380 | allocate<ResultNode>(operation, branch[0], branch[1], branch[2], branch[3], branch[4], branch[5]); 19381 | result->node_depth(); 19382 | return result; 19383 | } 19384 | 19385 | template <typename node_type> 19386 | inline expression_node<typename node_type::value_type>* allocate() const 19387 | { 19388 | return (new node_type()); 19389 | } 19390 | 19391 | template <typename node_type, 19392 | typename Type, 19393 | typename Allocator, 19394 | template <typename, typename> class Sequence> 19395 | inline expression_node<typename node_type::value_type>* allocate(const Sequence<Type,Allocator>& seq) const 19396 | { 19397 | expression_node<typename node_type::value_type>* 19398 | result = (new node_type(seq)); 19399 | result->node_depth(); 19400 | return result; 19401 | } 19402 | 19403 | template <typename node_type, typename T1> 19404 | inline expression_node<typename node_type::value_type>* allocate(T1& t1) const 19405 | { 19406 | expression_node<typename node_type::value_type>* 19407 | result = (new node_type(t1)); 19408 | result->node_depth(); 19409 | return result; 19410 | } 19411 | 19412 | template <typename node_type, typename T1> 19413 | inline expression_node<typename node_type::value_type>* allocate_c(const T1& t1) const 19414 | { 19415 | expression_node<typename node_type::value_type>* 19416 | result = (new node_type(t1)); 19417 | result->node_depth(); 19418 | return result; 19419 | } 19420 | 19421 | template <typename node_type, 19422 | typename T1, typename T2> 19423 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2) const 19424 | { 19425 | expression_node<typename node_type::value_type>* 19426 | result = (new node_type(t1, t2)); 19427 | result->node_depth(); 19428 | return result; 19429 | } 19430 | 19431 | template <typename node_type, 19432 | typename T1, typename T2> 19433 | inline expression_node<typename node_type::value_type>* allocate_cr(const T1& t1, T2& t2) const 19434 | { 19435 | expression_node<typename node_type::value_type>* 19436 | result = (new node_type(t1, t2)); 19437 | result->node_depth(); 19438 | return result; 19439 | } 19440 | 19441 | template <typename node_type, 19442 | typename T1, typename T2> 19443 | inline expression_node<typename node_type::value_type>* allocate_rc(T1& t1, const T2& t2) const 19444 | { 19445 | expression_node<typename node_type::value_type>* 19446 | result = (new node_type(t1, t2)); 19447 | result->node_depth(); 19448 | return result; 19449 | } 19450 | 19451 | template <typename node_type, 19452 | typename T1, typename T2> 19453 | inline expression_node<typename node_type::value_type>* allocate_rr(T1& t1, T2& t2) const 19454 | { 19455 | expression_node<typename node_type::value_type>* 19456 | result = (new node_type(t1, t2)); 19457 | result->node_depth(); 19458 | return result; 19459 | } 19460 | 19461 | template <typename node_type, 19462 | typename T1, typename T2> 19463 | inline expression_node<typename node_type::value_type>* allocate_tt(T1 t1, T2 t2) const 19464 | { 19465 | expression_node<typename node_type::value_type>* 19466 | result = (new node_type(t1, t2)); 19467 | result->node_depth(); 19468 | return result; 19469 | } 19470 | 19471 | template <typename node_type, 19472 | typename T1, typename T2, typename T3> 19473 | inline expression_node<typename node_type::value_type>* allocate_ttt(T1 t1, T2 t2, T3 t3) const 19474 | { 19475 | expression_node<typename node_type::value_type>* 19476 | result = (new node_type(t1, t2, t3)); 19477 | result->node_depth(); 19478 | return result; 19479 | } 19480 | 19481 | template <typename node_type, 19482 | typename T1, typename T2, typename T3, typename T4> 19483 | inline expression_node<typename node_type::value_type>* allocate_tttt(T1 t1, T2 t2, T3 t3, T4 t4) const 19484 | { 19485 | expression_node<typename node_type::value_type>* 19486 | result = (new node_type(t1, t2, t3, t4)); 19487 | result->node_depth(); 19488 | return result; 19489 | } 19490 | 19491 | template <typename node_type, 19492 | typename T1, typename T2, typename T3> 19493 | inline expression_node<typename node_type::value_type>* allocate_rrr(T1& t1, T2& t2, T3& t3) const 19494 | { 19495 | expression_node<typename node_type::value_type>* 19496 | result = (new node_type(t1, t2, t3)); 19497 | result->node_depth(); 19498 | return result; 19499 | } 19500 | 19501 | template <typename node_type, 19502 | typename T1, typename T2, typename T3, typename T4> 19503 | inline expression_node<typename node_type::value_type>* allocate_rrrr(T1& t1, T2& t2, T3& t3, T4& t4) const 19504 | { 19505 | expression_node<typename node_type::value_type>* 19506 | result = (new node_type(t1, t2, t3, t4)); 19507 | result->node_depth(); 19508 | return result; 19509 | } 19510 | 19511 | template <typename node_type, 19512 | typename T1, typename T2, typename T3, typename T4, typename T5> 19513 | inline expression_node<typename node_type::value_type>* allocate_rrrrr(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5) const 19514 | { 19515 | expression_node<typename node_type::value_type>* 19516 | result = (new node_type(t1, t2, t3, t4, t5)); 19517 | result->node_depth(); 19518 | return result; 19519 | } 19520 | 19521 | template <typename node_type, 19522 | typename T1, typename T2, typename T3> 19523 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19524 | const T3& t3) const 19525 | { 19526 | expression_node<typename node_type::value_type>* 19527 | result = (new node_type(t1, t2, t3)); 19528 | result->node_depth(); 19529 | return result; 19530 | } 19531 | 19532 | template <typename node_type, 19533 | typename T1, typename T2, 19534 | typename T3, typename T4> 19535 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19536 | const T3& t3, const T4& t4) const 19537 | { 19538 | expression_node<typename node_type::value_type>* 19539 | result = (new node_type(t1, t2, t3, t4)); 19540 | result->node_depth(); 19541 | return result; 19542 | } 19543 | 19544 | template <typename node_type, 19545 | typename T1, typename T2, 19546 | typename T3, typename T4, typename T5> 19547 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19548 | const T3& t3, const T4& t4, 19549 | const T5& t5) const 19550 | { 19551 | expression_node<typename node_type::value_type>* 19552 | result = (new node_type(t1, t2, t3, t4, t5)); 19553 | result->node_depth(); 19554 | return result; 19555 | } 19556 | 19557 | template <typename node_type, 19558 | typename T1, typename T2, 19559 | typename T3, typename T4, typename T5, typename T6> 19560 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19561 | const T3& t3, const T4& t4, 19562 | const T5& t5, const T6& t6) const 19563 | { 19564 | expression_node<typename node_type::value_type>* 19565 | result = (new node_type(t1, t2, t3, t4, t5, t6)); 19566 | result->node_depth(); 19567 | return result; 19568 | } 19569 | 19570 | template <typename node_type, 19571 | typename T1, typename T2, 19572 | typename T3, typename T4, 19573 | typename T5, typename T6, typename T7> 19574 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19575 | const T3& t3, const T4& t4, 19576 | const T5& t5, const T6& t6, 19577 | const T7& t7) const 19578 | { 19579 | expression_node<typename node_type::value_type>* 19580 | result = (new node_type(t1, t2, t3, t4, t5, t6, t7)); 19581 | result->node_depth(); 19582 | return result; 19583 | } 19584 | 19585 | template <typename node_type, 19586 | typename T1, typename T2, 19587 | typename T3, typename T4, 19588 | typename T5, typename T6, 19589 | typename T7, typename T8> 19590 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19591 | const T3& t3, const T4& t4, 19592 | const T5& t5, const T6& t6, 19593 | const T7& t7, const T8& t8) const 19594 | { 19595 | expression_node<typename node_type::value_type>* 19596 | result = (new node_type(t1, t2, t3, t4, t5, t6, t7, t8)); 19597 | result->node_depth(); 19598 | return result; 19599 | } 19600 | 19601 | template <typename node_type, 19602 | typename T1, typename T2, 19603 | typename T3, typename T4, 19604 | typename T5, typename T6, 19605 | typename T7, typename T8, typename T9> 19606 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19607 | const T3& t3, const T4& t4, 19608 | const T5& t5, const T6& t6, 19609 | const T7& t7, const T8& t8, 19610 | const T9& t9) const 19611 | { 19612 | expression_node<typename node_type::value_type>* 19613 | result = (new node_type(t1, t2, t3, t4, t5, t6, t7, t8, t9)); 19614 | result->node_depth(); 19615 | return result; 19616 | } 19617 | 19618 | template <typename node_type, 19619 | typename T1, typename T2, 19620 | typename T3, typename T4, 19621 | typename T5, typename T6, 19622 | typename T7, typename T8, 19623 | typename T9, typename T10> 19624 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19625 | const T3& t3, const T4& t4, 19626 | const T5& t5, const T6& t6, 19627 | const T7& t7, const T8& t8, 19628 | const T9& t9, const T10& t10) const 19629 | { 19630 | expression_node<typename node_type::value_type>* 19631 | result = (new node_type(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10)); 19632 | result->node_depth(); 19633 | return result; 19634 | } 19635 | 19636 | template <typename node_type, 19637 | typename T1, typename T2, typename T3> 19638 | inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, T3 t3) const 19639 | { 19640 | expression_node<typename node_type::value_type>* 19641 | result = (new node_type(t1, t2, t3)); 19642 | result->node_depth(); 19643 | return result; 19644 | } 19645 | 19646 | template <typename node_type, 19647 | typename T1, typename T2, 19648 | typename T3, typename T4> 19649 | inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, 19650 | T3 t3, T4 t4) const 19651 | { 19652 | expression_node<typename node_type::value_type>* 19653 | result = (new node_type(t1, t2, t3, t4)); 19654 | result->node_depth(); 19655 | return result; 19656 | } 19657 | 19658 | template <typename node_type, 19659 | typename T1, typename T2, 19660 | typename T3, typename T4, 19661 | typename T5> 19662 | inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, 19663 | T3 t3, T4 t4, 19664 | T5 t5) const 19665 | { 19666 | expression_node<typename node_type::value_type>* 19667 | result = (new node_type(t1, t2, t3, t4, t5)); 19668 | result->node_depth(); 19669 | return result; 19670 | } 19671 | 19672 | template <typename node_type, 19673 | typename T1, typename T2, 19674 | typename T3, typename T4, 19675 | typename T5, typename T6> 19676 | inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, 19677 | T3 t3, T4 t4, 19678 | T5 t5, T6 t6) const 19679 | { 19680 | expression_node<typename node_type::value_type>* 19681 | result = (new node_type(t1, t2, t3, t4, t5, t6)); 19682 | result->node_depth(); 19683 | return result; 19684 | } 19685 | 19686 | template <typename node_type, 19687 | typename T1, typename T2, 19688 | typename T3, typename T4, 19689 | typename T5, typename T6, typename T7> 19690 | inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, 19691 | T3 t3, T4 t4, 19692 | T5 t5, T6 t6, 19693 | T7 t7) const 19694 | { 19695 | expression_node<typename node_type::value_type>* 19696 | result = (new node_type(t1, t2, t3, t4, t5, t6, t7)); 19697 | result->node_depth(); 19698 | return result; 19699 | } 19700 | 19701 | template <typename T> 19702 | void inline free(expression_node<T>*& e) const 19703 | { 19704 | exprtk_debug(("node_allocator::free() - deleting expression_node " 19705 | "type: %03d addr: %p\n", 19706 | static_cast<int>(e->type()), 19707 | reinterpret_cast<void*>(e))); 19708 | delete e; 19709 | e = 0; 19710 | } 19711 | }; 19712 | 19713 | inline void load_operations_map(std::multimap<std::string,details::base_operation_t,details::ilesscompare>& m) 19714 | { 19715 | #define register_op(Symbol, Type, Args) \ 19716 | m.insert(std::make_pair(std::string(Symbol),details::base_operation_t(Type,Args))); \ 19717 | 19718 | register_op("abs" , e_abs , 1) 19719 | register_op("acos" , e_acos , 1) 19720 | register_op("acosh" , e_acosh , 1) 19721 | register_op("asin" , e_asin , 1) 19722 | register_op("asinh" , e_asinh , 1) 19723 | register_op("atan" , e_atan , 1) 19724 | register_op("atanh" , e_atanh , 1) 19725 | register_op("ceil" , e_ceil , 1) 19726 | register_op("cos" , e_cos , 1) 19727 | register_op("cosh" , e_cosh , 1) 19728 | register_op("exp" , e_exp , 1) 19729 | register_op("expm1" , e_expm1 , 1) 19730 | register_op("floor" , e_floor , 1) 19731 | register_op("log" , e_log , 1) 19732 | register_op("log10" , e_log10 , 1) 19733 | register_op("log2" , e_log2 , 1) 19734 | register_op("log1p" , e_log1p , 1) 19735 | register_op("round" , e_round , 1) 19736 | register_op("sin" , e_sin , 1) 19737 | register_op("sinc" , e_sinc , 1) 19738 | register_op("sinh" , e_sinh , 1) 19739 | register_op("sec" , e_sec , 1) 19740 | register_op("csc" , e_csc , 1) 19741 | register_op("sqrt" , e_sqrt , 1) 19742 | register_op("tan" , e_tan , 1) 19743 | register_op("tanh" , e_tanh , 1) 19744 | register_op("cot" , e_cot , 1) 19745 | register_op("rad2deg" , e_r2d , 1) 19746 | register_op("deg2rad" , e_d2r , 1) 19747 | register_op("deg2grad" , e_d2g , 1) 19748 | register_op("grad2deg" , e_g2d , 1) 19749 | register_op("sgn" , e_sgn , 1) 19750 | register_op("not" , e_notl , 1) 19751 | register_op("erf" , e_erf , 1) 19752 | register_op("erfc" , e_erfc , 1) 19753 | register_op("ncdf" , e_ncdf , 1) 19754 | register_op("frac" , e_frac , 1) 19755 | register_op("trunc" , e_trunc , 1) 19756 | register_op("atan2" , e_atan2 , 2) 19757 | register_op("mod" , e_mod , 2) 19758 | register_op("logn" , e_logn , 2) 19759 | register_op("pow" , e_pow , 2) 19760 | register_op("root" , e_root , 2) 19761 | register_op("roundn" , e_roundn , 2) 19762 | register_op("equal" , e_equal , 2) 19763 | register_op("not_equal" , e_nequal , 2) 19764 | register_op("hypot" , e_hypot , 2) 19765 | register_op("shr" , e_shr , 2) 19766 | register_op("shl" , e_shl , 2) 19767 | register_op("clamp" , e_clamp , 3) 19768 | register_op("iclamp" , e_iclamp , 3) 19769 | register_op("inrange" , e_inrange , 3) 19770 | #undef register_op 19771 | } 19772 | 19773 | } // namespace details 19774 | 19775 | class function_traits 19776 | { 19777 | public: 19778 | 19779 | function_traits() 19780 | : allow_zero_parameters_(false) 19781 | , has_side_effects_(true) 19782 | , min_num_args_(0) 19783 | , max_num_args_(std::numeric_limits<std::size_t>::max()) 19784 | {} 19785 | 19786 | inline bool& allow_zero_parameters() 19787 | { 19788 | return allow_zero_parameters_; 19789 | } 19790 | 19791 | inline bool& has_side_effects() 19792 | { 19793 | return has_side_effects_; 19794 | } 19795 | 19796 | std::size_t& min_num_args() 19797 | { 19798 | return min_num_args_; 19799 | } 19800 | 19801 | std::size_t& max_num_args() 19802 | { 19803 | return max_num_args_; 19804 | } 19805 | 19806 | private: 19807 | 19808 | bool allow_zero_parameters_; 19809 | bool has_side_effects_; 19810 | std::size_t min_num_args_; 19811 | std::size_t max_num_args_; 19812 | }; 19813 | 19814 | template <typename FunctionType> 19815 | void enable_zero_parameters(FunctionType& func) 19816 | { 19817 | func.allow_zero_parameters() = true; 19818 | 19819 | if (0 != func.min_num_args()) 19820 | { 19821 | func.min_num_args() = 0; 19822 | } 19823 | } 19824 | 19825 | template <typename FunctionType> 19826 | void disable_zero_parameters(FunctionType& func) 19827 | { 19828 | func.allow_zero_parameters() = false; 19829 | } 19830 | 19831 | template <typename FunctionType> 19832 | void enable_has_side_effects(FunctionType& func) 19833 | { 19834 | func.has_side_effects() = true; 19835 | } 19836 | 19837 | template <typename FunctionType> 19838 | void disable_has_side_effects(FunctionType& func) 19839 | { 19840 | func.has_side_effects() = false; 19841 | } 19842 | 19843 | template <typename FunctionType> 19844 | void set_min_num_args(FunctionType& func, const std::size_t& num_args) 19845 | { 19846 | func.min_num_args() = num_args; 19847 | 19848 | if ((0 != func.min_num_args()) && func.allow_zero_parameters()) 19849 | func.allow_zero_parameters() = false; 19850 | } 19851 | 19852 | template <typename FunctionType> 19853 | void set_max_num_args(FunctionType& func, const std::size_t& num_args) 19854 | { 19855 | func.max_num_args() = num_args; 19856 | } 19857 | 19858 | template <typename T> 19859 | class ifunction : public function_traits 19860 | { 19861 | public: 19862 | 19863 | explicit ifunction(const std::size_t& pc) 19864 | : param_count(pc) 19865 | {} 19866 | 19867 | virtual ~ifunction() 19868 | {} 19869 | 19870 | #define empty_method_body(N) \ 19871 | { \ 19872 | exprtk_debug(("ifunction::operator() - Operator(" #N ") has not been overridden\n")); \ 19873 | return std::numeric_limits<T>::quiet_NaN(); \ 19874 | } \ 19875 | 19876 | inline virtual T operator() () 19877 | empty_method_body(0) 19878 | 19879 | inline virtual T operator() (const T&) 19880 | empty_method_body(1) 19881 | 19882 | inline virtual T operator() (const T&,const T&) 19883 | empty_method_body(2) 19884 | 19885 | inline virtual T operator() (const T&, const T&, const T&) 19886 | empty_method_body(3) 19887 | 19888 | inline virtual T operator() (const T&, const T&, const T&, const T&) 19889 | empty_method_body(4) 19890 | 19891 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&) 19892 | empty_method_body(5) 19893 | 19894 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&) 19895 | empty_method_body(6) 19896 | 19897 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19898 | empty_method_body(7) 19899 | 19900 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19901 | empty_method_body(8) 19902 | 19903 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19904 | empty_method_body(9) 19905 | 19906 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19907 | empty_method_body(10) 19908 | 19909 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19910 | const T&) 19911 | empty_method_body(11) 19912 | 19913 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19914 | const T&, const T&) 19915 | empty_method_body(12) 19916 | 19917 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19918 | const T&, const T&, const T&) 19919 | empty_method_body(13) 19920 | 19921 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19922 | const T&, const T&, const T&, const T&) 19923 | empty_method_body(14) 19924 | 19925 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19926 | const T&, const T&, const T&, const T&, const T&) 19927 | empty_method_body(15) 19928 | 19929 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19930 | const T&, const T&, const T&, const T&, const T&, const T&) 19931 | empty_method_body(16) 19932 | 19933 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19934 | const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19935 | empty_method_body(17) 19936 | 19937 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19938 | const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19939 | empty_method_body(18) 19940 | 19941 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19942 | const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19943 | empty_method_body(19) 19944 | 19945 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19946 | const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19947 | empty_method_body(20) 19948 | 19949 | #undef empty_method_body 19950 | 19951 | std::size_t param_count; 19952 | }; 19953 | 19954 | template <typename T> 19955 | class ivararg_function : public function_traits 19956 | { 19957 | public: 19958 | 19959 | virtual ~ivararg_function() 19960 | {} 19961 | 19962 | inline virtual T operator() (const std::vector<T>&) 19963 | { 19964 | exprtk_debug(("ivararg_function::operator() - Operator has not been overridden\n")); 19965 | return std::numeric_limits<T>::quiet_NaN(); 19966 | } 19967 | }; 19968 | 19969 | template <typename T> 19970 | class igeneric_function : public function_traits 19971 | { 19972 | public: 19973 | 19974 | enum return_type 19975 | { 19976 | e_rtrn_scalar = 0, 19977 | e_rtrn_string = 1, 19978 | e_rtrn_overload = 2 19979 | }; 19980 | 19981 | typedef T type; 19982 | typedef type_store<T> generic_type; 19983 | typedef typename generic_type::parameter_list parameter_list_t; 19984 | 19985 | explicit igeneric_function(const std::string& param_seq = "", const return_type rtr_type = e_rtrn_scalar) 19986 | : parameter_sequence(param_seq) 19987 | , rtrn_type(rtr_type) 19988 | {} 19989 | 19990 | virtual ~igeneric_function() 19991 | {} 19992 | 19993 | #define igeneric_function_empty_body(N) \ 19994 | { \ 19995 | exprtk_debug(("igeneric_function::operator() - Operator(" #N ") has not been overridden\n")); \ 19996 | return std::numeric_limits<T>::quiet_NaN(); \ 19997 | } \ 19998 | 19999 | // f(i_0,i_1,....,i_N) --> Scalar 20000 | inline virtual T operator() (parameter_list_t) 20001 | igeneric_function_empty_body(1) 20002 | 20003 | // f(i_0,i_1,....,i_N) --> String 20004 | inline virtual T operator() (std::string&, parameter_list_t) 20005 | igeneric_function_empty_body(2) 20006 | 20007 | // f(psi,i_0,i_1,....,i_N) --> Scalar 20008 | inline virtual T operator() (const std::size_t&, parameter_list_t) 20009 | igeneric_function_empty_body(3) 20010 | 20011 | // f(psi,i_0,i_1,....,i_N) --> String 20012 | inline virtual T operator() (const std::size_t&, std::string&, parameter_list_t) 20013 | igeneric_function_empty_body(4) 20014 | 20015 | #undef igeneric_function_empty_body 20016 | 20017 | std::string parameter_sequence; 20018 | return_type rtrn_type; 20019 | 20020 | static inline std::string generate_prefix_args(const std::string& prefix_args, std::size_t start = 0, std::size_t end = 10) 20021 | { 20022 | std::string result; 20023 | 20024 | for (std::size_t i = start; i <= end; ++i) 20025 | { 20026 | result += prefix_args + std::string(i,'?'); 20027 | result += (i != end) ? "|" : "" 20028 | } 20029 | 20030 | return result; 20031 | } 20032 | 20033 | static inline std::string generate_suffix_args(const std::string& suffix_args, std::size_t start = 0, std::size_t end = 10) 20034 | { 20035 | std::string result; 20036 | 20037 | for (std::size_t i = start; i <= end; ++i) 20038 | { 20039 | result += std::string(i,'?') + suffix_args; 20040 | result += (i != end) ? "|" : "" 20041 | } 20042 | 20043 | return result; 20044 | } 20045 | }; 20046 | 20047 | #ifndef exprtk_disable_string_capabilities 20048 | template <typename T> 20049 | class stringvar_base 20050 | { 20051 | public: 20052 | 20053 | typedef typename details::stringvar_node<T> stringvar_node_t; 20054 | 20055 | stringvar_base(const std::string& name, stringvar_node_t* svn) 20056 | : name_(name) 20057 | , string_varnode_(svn) 20058 | {} 20059 | 20060 | bool valid() const 20061 | { 20062 | return !name_.empty() && (0 != string_varnode_); 20063 | } 20064 | 20065 | std::string name() const 20066 | { 20067 | assert(string_varnode_); 20068 | return name_; 20069 | } 20070 | 20071 | void rebase(std::string& s) 20072 | { 20073 | assert(string_varnode_); 20074 | string_varnode_->rebase(s); 20075 | } 20076 | 20077 | private: 20078 | 20079 | std::string name_; 20080 | stringvar_node_t* string_varnode_; 20081 | }; 20082 | #endif 20083 | 20084 | template <typename T> class parser; 20085 | template <typename T> class expression_helper; 20086 | 20087 | template <typename T> 20088 | class symbol_table 20089 | { 20090 | public: 20091 | 20092 | enum symtab_mutability_type 20093 | { 20094 | e_unknown = 0, 20095 | e_mutable = 1, 20096 | e_immutable = 2 20097 | }; 20098 | 20099 | typedef T (*ff00_functor)(); 20100 | typedef T (*ff01_functor)(T); 20101 | typedef T (*ff02_functor)(T, T); 20102 | typedef T (*ff03_functor)(T, T, T); 20103 | typedef T (*ff04_functor)(T, T, T, T); 20104 | typedef T (*ff05_functor)(T, T, T, T, T); 20105 | typedef T (*ff06_functor)(T, T, T, T, T, T); 20106 | typedef T (*ff07_functor)(T, T, T, T, T, T, T); 20107 | typedef T (*ff08_functor)(T, T, T, T, T, T, T, T); 20108 | typedef T (*ff09_functor)(T, T, T, T, T, T, T, T, T); 20109 | typedef T (*ff10_functor)(T, T, T, T, T, T, T, T, T, T); 20110 | typedef T (*ff11_functor)(T, T, T, T, T, T, T, T, T, T, T); 20111 | typedef T (*ff12_functor)(T, T, T, T, T, T, T, T, T, T, T, T); 20112 | typedef T (*ff13_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T); 20113 | typedef T (*ff14_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T); 20114 | typedef T (*ff15_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T, T); 20115 | 20116 | protected: 20117 | 20118 | struct freefunc00 exprtk_final : public exprtk::ifunction<T> 20119 | { 20120 | using exprtk::ifunction<T>::operator(); 20121 | 20122 | explicit freefunc00(ff00_functor ff) : exprtk::ifunction<T>(0), f(ff) {} 20123 | inline T operator() () exprtk_override 20124 | { return f(); } 20125 | ff00_functor f; 20126 | }; 20127 | 20128 | struct freefunc01 exprtk_final : public exprtk::ifunction<T> 20129 | { 20130 | using exprtk::ifunction<T>::operator(); 20131 | 20132 | explicit freefunc01(ff01_functor ff) : exprtk::ifunction<T>(1), f(ff) {} 20133 | inline T operator() (const T& v0) exprtk_override 20134 | { return f(v0); } 20135 | ff01_functor f; 20136 | }; 20137 | 20138 | struct freefunc02 exprtk_final : public exprtk::ifunction<T> 20139 | { 20140 | using exprtk::ifunction<T>::operator(); 20141 | 20142 | explicit freefunc02(ff02_functor ff) : exprtk::ifunction<T>(2), f(ff) {} 20143 | inline T operator() (const T& v0, const T& v1) exprtk_override 20144 | { return f(v0, v1); } 20145 | ff02_functor f; 20146 | }; 20147 | 20148 | struct freefunc03 exprtk_final : public exprtk::ifunction<T> 20149 | { 20150 | using exprtk::ifunction<T>::operator(); 20151 | 20152 | explicit freefunc03(ff03_functor ff) : exprtk::ifunction<T>(3), f(ff) {} 20153 | inline T operator() (const T& v0, const T& v1, const T& v2) exprtk_override 20154 | { return f(v0, v1, v2); } 20155 | ff03_functor f; 20156 | }; 20157 | 20158 | struct freefunc04 exprtk_final : public exprtk::ifunction<T> 20159 | { 20160 | using exprtk::ifunction<T>::operator(); 20161 | 20162 | explicit freefunc04(ff04_functor ff) : exprtk::ifunction<T>(4), f(ff) {} 20163 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3) exprtk_override 20164 | { return f(v0, v1, v2, v3); } 20165 | ff04_functor f; 20166 | }; 20167 | 20168 | struct freefunc05 exprtk_final : public exprtk::ifunction<T> 20169 | { 20170 | using exprtk::ifunction<T>::operator(); 20171 | 20172 | explicit freefunc05(ff05_functor ff) : exprtk::ifunction<T>(5), f(ff) {} 20173 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4) exprtk_override 20174 | { return f(v0, v1, v2, v3, v4); } 20175 | ff05_functor f; 20176 | }; 20177 | 20178 | struct freefunc06 exprtk_final : public exprtk::ifunction<T> 20179 | { 20180 | using exprtk::ifunction<T>::operator(); 20181 | 20182 | explicit freefunc06(ff06_functor ff) : exprtk::ifunction<T>(6), f(ff) {} 20183 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5) exprtk_override 20184 | { return f(v0, v1, v2, v3, v4, v5); } 20185 | ff06_functor f; 20186 | }; 20187 | 20188 | struct freefunc07 exprtk_final : public exprtk::ifunction<T> 20189 | { 20190 | using exprtk::ifunction<T>::operator(); 20191 | 20192 | explicit freefunc07(ff07_functor ff) : exprtk::ifunction<T>(7), f(ff) {} 20193 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, 20194 | const T& v5, const T& v6) exprtk_override 20195 | { return f(v0, v1, v2, v3, v4, v5, v6); } 20196 | ff07_functor f; 20197 | }; 20198 | 20199 | struct freefunc08 exprtk_final : public exprtk::ifunction<T> 20200 | { 20201 | using exprtk::ifunction<T>::operator(); 20202 | 20203 | explicit freefunc08(ff08_functor ff) : exprtk::ifunction<T>(8), f(ff) {} 20204 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, 20205 | const T& v5, const T& v6, const T& v7) exprtk_override 20206 | { return f(v0, v1, v2, v3, v4, v5, v6, v7); } 20207 | ff08_functor f; 20208 | }; 20209 | 20210 | struct freefunc09 exprtk_final : public exprtk::ifunction<T> 20211 | { 20212 | using exprtk::ifunction<T>::operator(); 20213 | 20214 | explicit freefunc09(ff09_functor ff) : exprtk::ifunction<T>(9), f(ff) {} 20215 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, 20216 | const T& v5, const T& v6, const T& v7, const T& v8) exprtk_override 20217 | { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8); } 20218 | ff09_functor f; 20219 | }; 20220 | 20221 | struct freefunc10 exprtk_final : public exprtk::ifunction<T> 20222 | { 20223 | using exprtk::ifunction<T>::operator(); 20224 | 20225 | explicit freefunc10(ff10_functor ff) : exprtk::ifunction<T>(10), f(ff) {} 20226 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, 20227 | const T& v5, const T& v6, const T& v7, const T& v8, const T& v9) exprtk_override 20228 | { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9); } 20229 | ff10_functor f; 20230 | }; 20231 | 20232 | struct freefunc11 exprtk_final : public exprtk::ifunction<T> 20233 | { 20234 | using exprtk::ifunction<T>::operator(); 20235 | 20236 | explicit freefunc11(ff11_functor ff) : exprtk::ifunction<T>(11), f(ff) {} 20237 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, 20238 | const T& v5, const T& v6, const T& v7, const T& v8, const T& v9, const T& v10) exprtk_override 20239 | { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10); } 20240 | ff11_functor f; 20241 | }; 20242 | 20243 | struct freefunc12 exprtk_final : public exprtk::ifunction<T> 20244 | { 20245 | using exprtk::ifunction<T>::operator(); 20246 | 20247 | explicit freefunc12(ff12_functor ff) : exprtk::ifunction<T>(12), f(ff) {} 20248 | inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04, 20249 | const T& v05, const T& v06, const T& v07, const T& v08, const T& v09, 20250 | const T& v10, const T& v11) exprtk_override 20251 | { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11); } 20252 | ff12_functor f; 20253 | }; 20254 | 20255 | struct freefunc13 exprtk_final : public exprtk::ifunction<T> 20256 | { 20257 | using exprtk::ifunction<T>::operator(); 20258 | 20259 | explicit freefunc13(ff13_functor ff) : exprtk::ifunction<T>(13), f(ff) {} 20260 | inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04, 20261 | const T& v05, const T& v06, const T& v07, const T& v08, const T& v09, 20262 | const T& v10, const T& v11, const T& v12) exprtk_override 20263 | { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12); } 20264 | ff13_functor f; 20265 | }; 20266 | 20267 | struct freefunc14 exprtk_final : public exprtk::ifunction<T> 20268 | { 20269 | using exprtk::ifunction<T>::operator(); 20270 | 20271 | explicit freefunc14(ff14_functor ff) : exprtk::ifunction<T>(14), f(ff) {} 20272 | inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04, 20273 | const T& v05, const T& v06, const T& v07, const T& v08, const T& v09, 20274 | const T& v10, const T& v11, const T& v12, const T& v13) exprtk_override 20275 | { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12, v13); } 20276 | ff14_functor f; 20277 | }; 20278 | 20279 | struct freefunc15 exprtk_final : public exprtk::ifunction<T> 20280 | { 20281 | using exprtk::ifunction<T>::operator(); 20282 | 20283 | explicit freefunc15(ff15_functor ff) : exprtk::ifunction<T>(15), f(ff) {} 20284 | inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04, 20285 | const T& v05, const T& v06, const T& v07, const T& v08, const T& v09, 20286 | const T& v10, const T& v11, const T& v12, const T& v13, const T& v14) exprtk_override 20287 | { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12, v13, v14); } 20288 | ff15_functor f; 20289 | }; 20290 | 20291 | template <typename Type, typename RawType> 20292 | struct type_store 20293 | { 20294 | typedef details::expression_node<T>* expression_ptr; 20295 | typedef typename details::variable_node<T> variable_node_t; 20296 | typedef ifunction<T> ifunction_t; 20297 | typedef ivararg_function<T> ivararg_function_t; 20298 | typedef igeneric_function<T> igeneric_function_t; 20299 | typedef details::vector_holder<T> vector_t; 20300 | #ifndef exprtk_disable_string_capabilities 20301 | typedef typename details::stringvar_node<T> stringvar_node_t; 20302 | #endif 20303 | 20304 | typedef Type type_t; 20305 | typedef type_t* type_ptr; 20306 | typedef std::pair<bool,type_ptr> type_pair_t; 20307 | typedef std::map<std::string,type_pair_t,details::ilesscompare> type_map_t; 20308 | typedef typename type_map_t::iterator tm_itr_t; 20309 | typedef typename type_map_t::const_iterator tm_const_itr_t; 20310 | 20311 | enum { lut_size = 256 }; 20312 | 20313 | type_map_t map; 20314 | std::size_t size; 20315 | 20316 | type_store() 20317 | : size(0) 20318 | {} 20319 | 20320 | struct deleter 20321 | { 20322 | #define exprtk_define_process(Type) \ 20323 | static inline void process(std::pair<bool,Type*>& n) \ 20324 | { \ 20325 | delete n.second; \ 20326 | } \ 20327 | 20328 | exprtk_define_process(variable_node_t ) 20329 | exprtk_define_process(vector_t ) 20330 | #ifndef exprtk_disable_string_capabilities 20331 | exprtk_define_process(stringvar_node_t) 20332 | #endif 20333 | 20334 | #undef exprtk_define_process 20335 | 20336 | template <typename DeleteType> 20337 | static inline void process(std::pair<bool,DeleteType*>&) 20338 | {} 20339 | }; 20340 | 20341 | inline bool symbol_exists(const std::string& symbol_name) const 20342 | { 20343 | if (symbol_name.empty()) 20344 | return false; 20345 | else if (map.end() != map.find(symbol_name)) 20346 | return true; 20347 | else 20348 | return false; 20349 | } 20350 | 20351 | template <typename PtrType> 20352 | inline std::string entity_name(const PtrType& ptr) const 20353 | { 20354 | if (map.empty()) 20355 | return std::string(); 20356 | 20357 | tm_const_itr_t itr = map.begin(); 20358 | 20359 | while (map.end() != itr) 20360 | { 20361 | if (itr->second.second == ptr) 20362 | { 20363 | return itr->first; 20364 | } 20365 | else 20366 | ++itr; 20367 | } 20368 | 20369 | return std::string(); 20370 | } 20371 | 20372 | inline bool is_constant(const std::string& symbol_name) const 20373 | { 20374 | if (symbol_name.empty()) 20375 | return false; 20376 | else 20377 | { 20378 | const tm_const_itr_t itr = map.find(symbol_name); 20379 | 20380 | if (map.end() == itr) 20381 | return false; 20382 | else 20383 | return (*itr).second.first; 20384 | } 20385 | } 20386 | 20387 | template <typename Tie, typename RType> 20388 | inline bool add_impl(const std::string& symbol_name, RType t, const bool is_const) 20389 | { 20390 | if (symbol_name.size() > 1) 20391 | { 20392 | for (std::size_t i = 0; i < details::reserved_symbols_size; ++i) 20393 | { 20394 | if (details::imatch(symbol_name, details::reserved_symbols[i])) 20395 | { 20396 | return false; 20397 | } 20398 | } 20399 | } 20400 | 20401 | const tm_itr_t itr = map.find(symbol_name); 20402 | 20403 | if (map.end() == itr) 20404 | { 20405 | map[symbol_name] = Tie::make(t,is_const); 20406 | ++size; 20407 | } 20408 | 20409 | return true; 20410 | } 20411 | 20412 | struct tie_array 20413 | { 20414 | static inline std::pair<bool,vector_t*> make(std::pair<T*,std::size_t> v, const bool is_const = false) 20415 | { 20416 | return std::make_pair(is_const, new vector_t(v.first, v.second)); 20417 | } 20418 | }; 20419 | 20420 | struct tie_stdvec 20421 | { 20422 | template <typename Allocator> 20423 | static inline std::pair<bool,vector_t*> make(std::vector<T,Allocator>& v, const bool is_const = false) 20424 | { 20425 | return std::make_pair(is_const, new vector_t(v)); 20426 | } 20427 | }; 20428 | 20429 | struct tie_vecview 20430 | { 20431 | static inline std::pair<bool,vector_t*> make(exprtk::vector_view<T>& v, const bool is_const = false) 20432 | { 20433 | return std::make_pair(is_const, new vector_t(v)); 20434 | } 20435 | }; 20436 | 20437 | struct tie_stddeq 20438 | { 20439 | template <typename Allocator> 20440 | static inline std::pair<bool,vector_t*> make(std::deque<T,Allocator>& v, const bool is_const = false) 20441 | { 20442 | return std::make_pair(is_const, new vector_t(v)); 20443 | } 20444 | }; 20445 | 20446 | template <std::size_t v_size> 20447 | inline bool add(const std::string& symbol_name, T (&v)[v_size], const bool is_const = false) 20448 | { 20449 | return add_impl<tie_array,std::pair<T*,std::size_t> > 20450 | (symbol_name, std::make_pair(v,v_size), is_const); 20451 | } 20452 | 20453 | inline bool add(const std::string& symbol_name, T* v, const std::size_t v_size, const bool is_const = false) 20454 | { 20455 | return add_impl<tie_array,std::pair<T*,std::size_t> > 20456 | (symbol_name, std::make_pair(v,v_size), is_const); 20457 | } 20458 | 20459 | template <typename Allocator> 20460 | inline bool add(const std::string& symbol_name, std::vector<T,Allocator>& v, const bool is_const = false) 20461 | { 20462 | return add_impl<tie_stdvec,std::vector<T,Allocator>&> 20463 | (symbol_name, v, is_const); 20464 | } 20465 | 20466 | inline bool add(const std::string& symbol_name, exprtk::vector_view<T>& v, const bool is_const = false) 20467 | { 20468 | return add_impl<tie_vecview,exprtk::vector_view<T>&> 20469 | (symbol_name, v, is_const); 20470 | } 20471 | 20472 | template <typename Allocator> 20473 | inline bool add(const std::string& symbol_name, std::deque<T,Allocator>& v, const bool is_const = false) 20474 | { 20475 | return add_impl<tie_stddeq,std::deque<T,Allocator>&> 20476 | (symbol_name, v, is_const); 20477 | } 20478 | 20479 | inline bool add(const std::string& symbol_name, RawType& t_, const bool is_const = false) 20480 | { 20481 | struct tie 20482 | { 20483 | static inline std::pair<bool,variable_node_t*> make(T& t, const bool is_constant = false) 20484 | { 20485 | return std::make_pair(is_constant, new variable_node_t(t)); 20486 | } 20487 | 20488 | #ifndef exprtk_disable_string_capabilities 20489 | static inline std::pair<bool,stringvar_node_t*> make(std::string& t, const bool is_constant = false) 20490 | { 20491 | return std::make_pair(is_constant, new stringvar_node_t(t)); 20492 | } 20493 | #endif 20494 | 20495 | static inline std::pair<bool,function_t*> make(function_t& t, const bool is_constant = false) 20496 | { 20497 | return std::make_pair(is_constant,&t); 20498 | } 20499 | 20500 | static inline std::pair<bool,vararg_function_t*> make(vararg_function_t& t, const bool is_constant = false) 20501 | { 20502 | return std::make_pair(is_constant,&t); 20503 | } 20504 | 20505 | static inline std::pair<bool,generic_function_t*> make(generic_function_t& t, const bool is_constant = false) 20506 | { 20507 | return std::make_pair(is_constant,&t); 20508 | } 20509 | }; 20510 | 20511 | const tm_itr_t itr = map.find(symbol_name); 20512 | 20513 | if (map.end() == itr) 20514 | { 20515 | map[symbol_name] = tie::make(t_,is_const); 20516 | ++size; 20517 | } 20518 | 20519 | return true; 20520 | } 20521 | 20522 | inline type_ptr get(const std::string& symbol_name) const 20523 | { 20524 | const tm_const_itr_t itr = map.find(symbol_name); 20525 | 20526 | if (map.end() == itr) 20527 | return reinterpret_cast<type_ptr>(0); 20528 | else 20529 | return itr->second.second; 20530 | } 20531 | 20532 | template <typename TType, typename TRawType, typename PtrType> 20533 | struct ptr_match 20534 | { 20535 | static inline bool test(const PtrType, const void*) 20536 | { 20537 | return false; 20538 | } 20539 | }; 20540 | 20541 | template <typename TType, typename TRawType> 20542 | struct ptr_match<TType,TRawType,variable_node_t*> 20543 | { 20544 | static inline bool test(const variable_node_t* p, const void* ptr) 20545 | { 20546 | exprtk_debug(("ptr_match::test() - %p <--> %p\n", reinterpret_cast<const void*>(&(p->ref())), ptr)); 20547 | return (&(p->ref()) == ptr); 20548 | } 20549 | }; 20550 | 20551 | inline type_ptr get_from_varptr(const void* ptr) const 20552 | { 20553 | tm_const_itr_t itr = map.begin(); 20554 | 20555 | while (map.end() != itr) 20556 | { 20557 | type_ptr ret_ptr = itr->second.second; 20558 | 20559 | if (ptr_match<Type,RawType,type_ptr>::test(ret_ptr,ptr)) 20560 | { 20561 | return ret_ptr; 20562 | } 20563 | 20564 | ++itr; 20565 | } 20566 | 20567 | return type_ptr(0); 20568 | } 20569 | 20570 | inline bool remove(const std::string& symbol_name, const bool delete_node = true) 20571 | { 20572 | const tm_itr_t itr = map.find(symbol_name); 20573 | 20574 | if (map.end() != itr) 20575 | { 20576 | if (delete_node) 20577 | { 20578 | deleter::process((*itr).second); 20579 | } 20580 | 20581 | map.erase(itr); 20582 | --size; 20583 | 20584 | return true; 20585 | } 20586 | else 20587 | return false; 20588 | } 20589 | 20590 | inline RawType& type_ref(const std::string& symbol_name) 20591 | { 20592 | struct init_type 20593 | { 20594 | static inline double set(double) { return (0.0); } 20595 | static inline double set(long double) { return (0.0); } 20596 | static inline float set(float) { return (0.0f); } 20597 | static inline std::string set(std::string&) { return std::string(""); } 20598 | }; 20599 | 20600 | static RawType null_type = init_type::set(RawType()); 20601 | 20602 | const tm_const_itr_t itr = map.find(symbol_name); 20603 | 20604 | if (map.end() == itr) 20605 | return null_type; 20606 | else 20607 | return itr->second.second->ref(); 20608 | } 20609 | 20610 | inline void clear(const bool delete_node = true) 20611 | { 20612 | if (!map.empty()) 20613 | { 20614 | if (delete_node) 20615 | { 20616 | tm_itr_t itr = map.begin(); 20617 | tm_itr_t end = map.end (); 20618 | 20619 | while (end != itr) 20620 | { 20621 | deleter::process((*itr).second); 20622 | ++itr; 20623 | } 20624 | } 20625 | 20626 | map.clear(); 20627 | } 20628 | 20629 | size = 0; 20630 | } 20631 | 20632 | template <typename Allocator, 20633 | template <typename, typename> class Sequence> 20634 | inline std::size_t get_list(Sequence<std::pair<std::string,RawType>,Allocator>& list) const 20635 | { 20636 | std::size_t count = 0; 20637 | 20638 | if (!map.empty()) 20639 | { 20640 | tm_const_itr_t itr = map.begin(); 20641 | tm_const_itr_t end = map.end (); 20642 | 20643 | while (end != itr) 20644 | { 20645 | list.push_back(std::make_pair((*itr).first,itr->second.second->ref())); 20646 | ++itr; 20647 | ++count; 20648 | } 20649 | } 20650 | 20651 | return count; 20652 | } 20653 | 20654 | template <typename Allocator, 20655 | template <typename, typename> class Sequence> 20656 | inline std::size_t get_list(Sequence<std::string,Allocator>& vlist) const 20657 | { 20658 | std::size_t count = 0; 20659 | 20660 | if (!map.empty()) 20661 | { 20662 | tm_const_itr_t itr = map.begin(); 20663 | tm_const_itr_t end = map.end (); 20664 | 20665 | while (end != itr) 20666 | { 20667 | vlist.push_back((*itr).first); 20668 | ++itr; 20669 | ++count; 20670 | } 20671 | } 20672 | 20673 | return count; 20674 | } 20675 | }; 20676 | 20677 | typedef details::expression_node<T>* expression_ptr; 20678 | typedef typename details::variable_node<T> variable_t; 20679 | typedef typename details::vector_holder<T> vector_holder_t; 20680 | typedef variable_t* variable_ptr; 20681 | #ifndef exprtk_disable_string_capabilities 20682 | typedef typename details::stringvar_node<T> stringvar_t; 20683 | typedef stringvar_t* stringvar_ptr; 20684 | #endif 20685 | typedef ifunction <T> function_t; 20686 | typedef ivararg_function <T> vararg_function_t; 20687 | typedef igeneric_function<T> generic_function_t; 20688 | typedef function_t* function_ptr; 20689 | typedef vararg_function_t* vararg_function_ptr; 20690 | typedef generic_function_t* generic_function_ptr; 20691 | 20692 | static const std::size_t lut_size = 256; 20693 | 20694 | // Symbol Table Holder 20695 | struct control_block 20696 | { 20697 | struct st_data 20698 | { 20699 | type_store<variable_t , T > variable_store; 20700 | type_store<function_t , function_t > function_store; 20701 | type_store<vararg_function_t , vararg_function_t > vararg_function_store; 20702 | type_store<generic_function_t, generic_function_t> generic_function_store; 20703 | type_store<generic_function_t, generic_function_t> string_function_store; 20704 | type_store<generic_function_t, generic_function_t> overload_function_store; 20705 | type_store<vector_holder_t , vector_holder_t > vector_store; 20706 | #ifndef exprtk_disable_string_capabilities 20707 | type_store<stringvar_t , std::string > stringvar_store; 20708 | #endif 20709 | 20710 | st_data() 20711 | { 20712 | for (std::size_t i = 0; i < details::reserved_words_size; ++i) 20713 | { 20714 | reserved_symbol_table_.insert(details::reserved_words[i]); 20715 | } 20716 | 20717 | for (std::size_t i = 0; i < details::reserved_symbols_size; ++i) 20718 | { 20719 | reserved_symbol_table_.insert(details::reserved_symbols[i]); 20720 | } 20721 | } 20722 | 20723 | ~st_data() 20724 | { 20725 | for (std::size_t i = 0; i < free_function_list_.size(); ++i) 20726 | { 20727 | delete free_function_list_[i]; 20728 | } 20729 | } 20730 | 20731 | inline bool is_reserved_symbol(const std::string& symbol) const 20732 | { 20733 | return (reserved_symbol_table_.end() != reserved_symbol_table_.find(symbol)); 20734 | } 20735 | 20736 | static inline st_data* create() 20737 | { 20738 | return (new st_data); 20739 | } 20740 | 20741 | static inline void destroy(st_data*& sd) 20742 | { 20743 | delete sd; 20744 | sd = reinterpret_cast<st_data*>(0); 20745 | } 20746 | 20747 | std::list<T> local_symbol_list_; 20748 | std::list<std::string> local_stringvar_list_; 20749 | std::set<std::string> reserved_symbol_table_; 20750 | std::vector<ifunction<T>*> free_function_list_; 20751 | }; 20752 | 20753 | control_block() 20754 | : ref_count(1) 20755 | , data_(st_data::create()) 20756 | , mutability_(e_mutable) 20757 | {} 20758 | 20759 | explicit control_block(st_data* data) 20760 | : ref_count(1) 20761 | , data_(data) 20762 | , mutability_(e_mutable) 20763 | {} 20764 | 20765 | ~control_block() 20766 | { 20767 | if (data_ && (0 == ref_count)) 20768 | { 20769 | st_data::destroy(data_); 20770 | } 20771 | } 20772 | 20773 | static inline control_block* create() 20774 | { 20775 | return (new control_block); 20776 | } 20777 | 20778 | template <typename SymTab> 20779 | static inline void destroy(control_block*& cntrl_blck, SymTab* sym_tab) 20780 | { 20781 | if (cntrl_blck) 20782 | { 20783 | if ( 20784 | (0 != cntrl_blck->ref_count) && 20785 | (0 == --cntrl_blck->ref_count) 20786 | ) 20787 | { 20788 | if (sym_tab) 20789 | sym_tab->clear(); 20790 | 20791 | delete cntrl_blck; 20792 | } 20793 | 20794 | cntrl_blck = 0; 20795 | } 20796 | } 20797 | 20798 | void set_mutability(const symtab_mutability_type mutability) 20799 | { 20800 | mutability_ = mutability; 20801 | } 20802 | 20803 | std::size_t ref_count; 20804 | st_data* data_; 20805 | symtab_mutability_type mutability_; 20806 | }; 20807 | 20808 | public: 20809 | 20810 | explicit symbol_table(const symtab_mutability_type mutability = e_mutable) 20811 | : control_block_(control_block::create()) 20812 | { 20813 | control_block_->set_mutability(mutability); 20814 | clear(); 20815 | } 20816 | 20817 | ~symbol_table() 20818 | { 20819 | exprtk::details::dump_ptr("~symbol_table", this); 20820 | control_block::destroy(control_block_, this); 20821 | } 20822 | 20823 | symbol_table(const symbol_table<T>& st) 20824 | { 20825 | control_block_ = st.control_block_; 20826 | control_block_->ref_count++; 20827 | } 20828 | 20829 | inline symbol_table<T>& operator=(const symbol_table<T>& st) 20830 | { 20831 | if (this != &st) 20832 | { 20833 | control_block::destroy(control_block_,reinterpret_cast<symbol_table<T>*>(0)); 20834 | 20835 | control_block_ = st.control_block_; 20836 | control_block_->ref_count++; 20837 | } 20838 | 20839 | return (*this); 20840 | } 20841 | 20842 | inline bool operator==(const symbol_table<T>& st) const 20843 | { 20844 | return (this == &st) || (control_block_ == st.control_block_); 20845 | } 20846 | 20847 | inline symtab_mutability_type mutability() const 20848 | { 20849 | return valid() ? control_block_->mutability_ : e_unknown; 20850 | } 20851 | 20852 | inline void clear_variables(const bool delete_node = true) 20853 | { 20854 | local_data().variable_store.clear(delete_node); 20855 | } 20856 | 20857 | inline void clear_functions() 20858 | { 20859 | local_data().function_store.clear(); 20860 | } 20861 | 20862 | inline void clear_strings() 20863 | { 20864 | #ifndef exprtk_disable_string_capabilities 20865 | local_data().stringvar_store.clear(); 20866 | #endif 20867 | } 20868 | 20869 | inline void clear_vectors() 20870 | { 20871 | local_data().vector_store.clear(); 20872 | } 20873 | 20874 | inline void clear_local_constants() 20875 | { 20876 | local_data().local_symbol_list_.clear(); 20877 | } 20878 | 20879 | inline void clear() 20880 | { 20881 | if (!valid()) return; 20882 | clear_variables (); 20883 | clear_functions (); 20884 | clear_strings (); 20885 | clear_vectors (); 20886 | clear_local_constants(); 20887 | } 20888 | 20889 | inline std::size_t variable_count() const 20890 | { 20891 | if (valid()) 20892 | return local_data().variable_store.size; 20893 | else 20894 | return 0; 20895 | } 20896 | 20897 | #ifndef exprtk_disable_string_capabilities 20898 | inline std::size_t stringvar_count() const 20899 | { 20900 | if (valid()) 20901 | return local_data().stringvar_store.size; 20902 | else 20903 | return 0; 20904 | } 20905 | #endif 20906 | 20907 | inline std::size_t function_count() const 20908 | { 20909 | if (valid()) 20910 | return local_data().function_store.size; 20911 | else 20912 | return 0; 20913 | } 20914 | 20915 | inline std::size_t vector_count() const 20916 | { 20917 | if (valid()) 20918 | return local_data().vector_store.size; 20919 | else 20920 | return 0; 20921 | } 20922 | 20923 | inline variable_ptr get_variable(const std::string& variable_name) const 20924 | { 20925 | if (!valid()) 20926 | return reinterpret_cast<variable_ptr>(0); 20927 | else if (!valid_symbol(variable_name)) 20928 | return reinterpret_cast<variable_ptr>(0); 20929 | else 20930 | return local_data().variable_store.get(variable_name); 20931 | } 20932 | 20933 | inline variable_ptr get_variable(const T& var_ref) const 20934 | { 20935 | if (!valid()) 20936 | return reinterpret_cast<variable_ptr>(0); 20937 | else 20938 | return local_data().variable_store.get_from_varptr( 20939 | reinterpret_cast<const void*>(&var_ref)); 20940 | } 20941 | 20942 | #ifndef exprtk_disable_string_capabilities 20943 | inline stringvar_ptr get_stringvar(const std::string& string_name) const 20944 | { 20945 | if (!valid()) 20946 | return reinterpret_cast<stringvar_ptr>(0); 20947 | else if (!valid_symbol(string_name)) 20948 | return reinterpret_cast<stringvar_ptr>(0); 20949 | else 20950 | return local_data().stringvar_store.get(string_name); 20951 | } 20952 | 20953 | inline stringvar_base<T> get_stringvar_base(const std::string& string_name) const 20954 | { 20955 | static stringvar_base<T> null_stringvar_base("",reinterpret_cast<stringvar_ptr>(0)); 20956 | if (!valid()) 20957 | return null_stringvar_base; 20958 | else if (!valid_symbol(string_name)) 20959 | return null_stringvar_base; 20960 | 20961 | stringvar_ptr stringvar = local_data().stringvar_store.get(string_name); 20962 | 20963 | if (0 == stringvar) 20964 | { 20965 | return null_stringvar_base; 20966 | } 20967 | 20968 | return stringvar_base<T>(string_name,stringvar); 20969 | } 20970 | #endif 20971 | 20972 | inline function_ptr get_function(const std::string& function_name) const 20973 | { 20974 | if (!valid()) 20975 | return reinterpret_cast<function_ptr>(0); 20976 | else if (!valid_symbol(function_name)) 20977 | return reinterpret_cast<function_ptr>(0); 20978 | else 20979 | return local_data().function_store.get(function_name); 20980 | } 20981 | 20982 | inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name) const 20983 | { 20984 | if (!valid()) 20985 | return reinterpret_cast<vararg_function_ptr>(0); 20986 | else if (!valid_symbol(vararg_function_name)) 20987 | return reinterpret_cast<vararg_function_ptr>(0); 20988 | else 20989 | return local_data().vararg_function_store.get(vararg_function_name); 20990 | } 20991 | 20992 | inline generic_function_ptr get_generic_function(const std::string& function_name) const 20993 | { 20994 | if (!valid()) 20995 | return reinterpret_cast<generic_function_ptr>(0); 20996 | else if (!valid_symbol(function_name)) 20997 | return reinterpret_cast<generic_function_ptr>(0); 20998 | else 20999 | return local_data().generic_function_store.get(function_name); 21000 | } 21001 | 21002 | inline generic_function_ptr get_string_function(const std::string& function_name) const 21003 | { 21004 | if (!valid()) 21005 | return reinterpret_cast<generic_function_ptr>(0); 21006 | else if (!valid_symbol(function_name)) 21007 | return reinterpret_cast<generic_function_ptr>(0); 21008 | else 21009 | return local_data().string_function_store.get(function_name); 21010 | } 21011 | 21012 | inline generic_function_ptr get_overload_function(const std::string& function_name) const 21013 | { 21014 | if (!valid()) 21015 | return reinterpret_cast<generic_function_ptr>(0); 21016 | else if (!valid_symbol(function_name)) 21017 | return reinterpret_cast<generic_function_ptr>(0); 21018 | else 21019 | return local_data().overload_function_store.get(function_name); 21020 | } 21021 | 21022 | typedef vector_holder_t* vector_holder_ptr; 21023 | 21024 | inline vector_holder_ptr get_vector(const std::string& vector_name) const 21025 | { 21026 | if (!valid()) 21027 | return reinterpret_cast<vector_holder_ptr>(0); 21028 | else if (!valid_symbol(vector_name)) 21029 | return reinterpret_cast<vector_holder_ptr>(0); 21030 | else 21031 | return local_data().vector_store.get(vector_name); 21032 | } 21033 | 21034 | inline T& variable_ref(const std::string& symbol_name) 21035 | { 21036 | static T null_var = T(0); 21037 | if (!valid()) 21038 | return null_var; 21039 | else if (!valid_symbol(symbol_name)) 21040 | return null_var; 21041 | else 21042 | return local_data().variable_store.type_ref(symbol_name); 21043 | } 21044 | 21045 | #ifndef exprtk_disable_string_capabilities 21046 | inline std::string& stringvar_ref(const std::string& symbol_name) 21047 | { 21048 | static std::string null_stringvar; 21049 | if (!valid()) 21050 | return null_stringvar; 21051 | else if (!valid_symbol(symbol_name)) 21052 | return null_stringvar; 21053 | else 21054 | return local_data().stringvar_store.type_ref(symbol_name); 21055 | } 21056 | #endif 21057 | 21058 | inline bool is_constant_node(const std::string& symbol_name) const 21059 | { 21060 | if (!valid()) 21061 | return false; 21062 | else if (!valid_symbol(symbol_name)) 21063 | return false; 21064 | else 21065 | return local_data().variable_store.is_constant(symbol_name); 21066 | } 21067 | 21068 | #ifndef exprtk_disable_string_capabilities 21069 | inline bool is_constant_string(const std::string& symbol_name) const 21070 | { 21071 | if (!valid()) 21072 | return false; 21073 | else if (!valid_symbol(symbol_name)) 21074 | return false; 21075 | else if (!local_data().stringvar_store.symbol_exists(symbol_name)) 21076 | return false; 21077 | else 21078 | return local_data().stringvar_store.is_constant(symbol_name); 21079 | } 21080 | #endif 21081 | 21082 | inline bool create_variable(const std::string& variable_name, const T& value = T(0)) 21083 | { 21084 | if (!valid()) 21085 | return false; 21086 | else if (!valid_symbol(variable_name)) 21087 | return false; 21088 | else if (symbol_exists(variable_name)) 21089 | return false; 21090 | 21091 | local_data().local_symbol_list_.push_back(value); 21092 | T& t = local_data().local_symbol_list_.back(); 21093 | 21094 | return add_variable(variable_name,t); 21095 | } 21096 | 21097 | #ifndef exprtk_disable_string_capabilities 21098 | inline bool create_stringvar(const std::string& stringvar_name, const std::string& value = std::string("")) 21099 | { 21100 | if (!valid()) 21101 | return false; 21102 | else if (!valid_symbol(stringvar_name)) 21103 | return false; 21104 | else if (symbol_exists(stringvar_name)) 21105 | return false; 21106 | 21107 | local_data().local_stringvar_list_.push_back(value); 21108 | std::string& s = local_data().local_stringvar_list_.back(); 21109 | 21110 | return add_stringvar(stringvar_name,s); 21111 | } 21112 | #endif 21113 | 21114 | inline bool add_variable(const std::string& variable_name, T& t, const bool is_constant = false) 21115 | { 21116 | if (!valid()) 21117 | return false; 21118 | else if (!valid_symbol(variable_name)) 21119 | return false; 21120 | else if (symbol_exists(variable_name)) 21121 | return false; 21122 | else 21123 | return local_data().variable_store.add(variable_name, t, is_constant); 21124 | } 21125 | 21126 | inline bool add_constant(const std::string& constant_name, const T& value) 21127 | { 21128 | if (!valid()) 21129 | return false; 21130 | else if (!valid_symbol(constant_name)) 21131 | return false; 21132 | else if (symbol_exists(constant_name)) 21133 | return false; 21134 | 21135 | local_data().local_symbol_list_.push_back(value); 21136 | T& t = local_data().local_symbol_list_.back(); 21137 | 21138 | return add_variable(constant_name, t, true); 21139 | } 21140 | 21141 | #ifndef exprtk_disable_string_capabilities 21142 | inline bool add_stringvar(const std::string& stringvar_name, std::string& s, const bool is_constant = false) 21143 | { 21144 | if (!valid()) 21145 | return false; 21146 | else if (!valid_symbol(stringvar_name)) 21147 | return false; 21148 | else if (symbol_exists(stringvar_name)) 21149 | return false; 21150 | else 21151 | return local_data().stringvar_store.add(stringvar_name, s, is_constant); 21152 | } 21153 | #endif 21154 | 21155 | inline bool add_function(const std::string& function_name, function_t& function) 21156 | { 21157 | if (!valid()) 21158 | return false; 21159 | else if (!valid_symbol(function_name)) 21160 | return false; 21161 | else if (symbol_exists(function_name)) 21162 | return false; 21163 | else 21164 | return local_data().function_store.add(function_name,function); 21165 | } 21166 | 21167 | inline bool add_function(const std::string& vararg_function_name, vararg_function_t& vararg_function) 21168 | { 21169 | if (!valid()) 21170 | return false; 21171 | else if (!valid_symbol(vararg_function_name)) 21172 | return false; 21173 | else if (symbol_exists(vararg_function_name)) 21174 | return false; 21175 | else 21176 | return local_data().vararg_function_store.add(vararg_function_name,vararg_function); 21177 | } 21178 | 21179 | inline bool add_function(const std::string& function_name, generic_function_t& function) 21180 | { 21181 | if (!valid()) 21182 | return false; 21183 | else if (!valid_symbol(function_name)) 21184 | return false; 21185 | else if (symbol_exists(function_name)) 21186 | return false; 21187 | else 21188 | { 21189 | switch (function.rtrn_type) 21190 | { 21191 | case generic_function_t::e_rtrn_scalar : 21192 | return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ? 21193 | local_data().generic_function_store.add(function_name,function) : false; 21194 | 21195 | case generic_function_t::e_rtrn_string : 21196 | return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ? 21197 | local_data().string_function_store.add(function_name,function) : false; 21198 | 21199 | case generic_function_t::e_rtrn_overload : 21200 | return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|:")) ? 21201 | local_data().overload_function_store.add(function_name,function) : false; 21202 | } 21203 | } 21204 | 21205 | return false; 21206 | } 21207 | 21208 | #define exprtk_define_freefunction(NN) \ 21209 | inline bool add_function(const std::string& function_name, ff##NN##_functor function) \ 21210 | { \ 21211 | if (!valid()) \ 21212 | { return false; } \ 21213 | if (!valid_symbol(function_name)) \ 21214 | { return false; } \ 21215 | if (symbol_exists(function_name)) \ 21216 | { return false; } \ 21217 | \ 21218 | exprtk::ifunction<T>* ifunc = new freefunc##NN(function); \ 21219 | \ 21220 | local_data().free_function_list_.push_back(ifunc); \ 21221 | \ 21222 | return add_function(function_name,(*local_data().free_function_list_.back())); \ 21223 | } \ 21224 | 21225 | exprtk_define_freefunction(00) exprtk_define_freefunction(01) 21226 | exprtk_define_freefunction(02) exprtk_define_freefunction(03) 21227 | exprtk_define_freefunction(04) exprtk_define_freefunction(05) 21228 | exprtk_define_freefunction(06) exprtk_define_freefunction(07) 21229 | exprtk_define_freefunction(08) exprtk_define_freefunction(09) 21230 | exprtk_define_freefunction(10) exprtk_define_freefunction(11) 21231 | exprtk_define_freefunction(12) exprtk_define_freefunction(13) 21232 | exprtk_define_freefunction(14) exprtk_define_freefunction(15) 21233 | 21234 | #undef exprtk_define_freefunction 21235 | 21236 | inline bool add_reserved_function(const std::string& function_name, function_t& function) 21237 | { 21238 | if (!valid()) 21239 | return false; 21240 | else if (!valid_symbol(function_name,false)) 21241 | return false; 21242 | else if (symbol_exists(function_name,false)) 21243 | return false; 21244 | else 21245 | return local_data().function_store.add(function_name,function); 21246 | } 21247 | 21248 | inline bool add_reserved_function(const std::string& vararg_function_name, vararg_function_t& vararg_function) 21249 | { 21250 | if (!valid()) 21251 | return false; 21252 | else if (!valid_symbol(vararg_function_name,false)) 21253 | return false; 21254 | else if (symbol_exists(vararg_function_name,false)) 21255 | return false; 21256 | else 21257 | return local_data().vararg_function_store.add(vararg_function_name,vararg_function); 21258 | } 21259 | 21260 | inline bool add_reserved_function(const std::string& function_name, generic_function_t& function) 21261 | { 21262 | if (!valid()) 21263 | return false; 21264 | else if (!valid_symbol(function_name,false)) 21265 | return false; 21266 | else if (symbol_exists(function_name,false)) 21267 | return false; 21268 | else 21269 | { 21270 | switch (function.rtrn_type) 21271 | { 21272 | case generic_function_t::e_rtrn_scalar : 21273 | return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ? 21274 | local_data().generic_function_store.add(function_name,function) : false; 21275 | 21276 | case generic_function_t::e_rtrn_string : 21277 | return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ? 21278 | local_data().string_function_store.add(function_name,function) : false; 21279 | 21280 | case generic_function_t::e_rtrn_overload : 21281 | return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|:")) ? 21282 | local_data().overload_function_store.add(function_name,function) : false; 21283 | } 21284 | } 21285 | 21286 | return false; 21287 | } 21288 | 21289 | #define exprtk_define_reserved_function(NN) \ 21290 | inline bool add_reserved_function(const std::string& function_name, ff##NN##_functor function) \ 21291 | { \ 21292 | if (!valid()) \ 21293 | { return false; } \ 21294 | if (!valid_symbol(function_name,false)) \ 21295 | { return false; } \ 21296 | if (symbol_exists(function_name,false)) \ 21297 | { return false; } \ 21298 | \ 21299 | exprtk::ifunction<T>* ifunc = new freefunc##NN(function); \ 21300 | \ 21301 | local_data().free_function_list_.push_back(ifunc); \ 21302 | \ 21303 | return add_reserved_function(function_name,(*local_data().free_function_list_.back())); \ 21304 | } \ 21305 | 21306 | exprtk_define_reserved_function(00) exprtk_define_reserved_function(01) 21307 | exprtk_define_reserved_function(02) exprtk_define_reserved_function(03) 21308 | exprtk_define_reserved_function(04) exprtk_define_reserved_function(05) 21309 | exprtk_define_reserved_function(06) exprtk_define_reserved_function(07) 21310 | exprtk_define_reserved_function(08) exprtk_define_reserved_function(09) 21311 | exprtk_define_reserved_function(10) exprtk_define_reserved_function(11) 21312 | exprtk_define_reserved_function(12) exprtk_define_reserved_function(13) 21313 | exprtk_define_reserved_function(14) exprtk_define_reserved_function(15) 21314 | 21315 | #undef exprtk_define_reserved_function 21316 | 21317 | template <std::size_t N> 21318 | inline bool add_vector(const std::string& vector_name, T (&v)[N]) 21319 | { 21320 | if (!valid()) 21321 | return false; 21322 | else if (!valid_symbol(vector_name)) 21323 | return false; 21324 | else if (symbol_exists(vector_name)) 21325 | return false; 21326 | else 21327 | return local_data().vector_store.add(vector_name,v); 21328 | } 21329 | 21330 | inline bool add_vector(const std::string& vector_name, T* v, const std::size_t& v_size) 21331 | { 21332 | if (!valid()) 21333 | return false; 21334 | else if (!valid_symbol(vector_name)) 21335 | return false; 21336 | else if (symbol_exists(vector_name)) 21337 | return false; 21338 | else if (0 == v_size) 21339 | return false; 21340 | else 21341 | return local_data().vector_store.add(vector_name, v, v_size); 21342 | } 21343 | 21344 | template <typename Allocator> 21345 | inline bool add_vector(const std::string& vector_name, std::vector<T,Allocator>& v) 21346 | { 21347 | if (!valid()) 21348 | return false; 21349 | else if (!valid_symbol(vector_name)) 21350 | return false; 21351 | else if (symbol_exists(vector_name)) 21352 | return false; 21353 | else if (0 == v.size()) 21354 | return false; 21355 | else 21356 | return local_data().vector_store.add(vector_name,v); 21357 | } 21358 | 21359 | inline bool add_vector(const std::string& vector_name, exprtk::vector_view<T>& v) 21360 | { 21361 | if (!valid()) 21362 | return false; 21363 | else if (!valid_symbol(vector_name)) 21364 | return false; 21365 | else if (symbol_exists(vector_name)) 21366 | return false; 21367 | else if (0 == v.size()) 21368 | return false; 21369 | else 21370 | return local_data().vector_store.add(vector_name,v); 21371 | } 21372 | 21373 | inline bool remove_variable(const std::string& variable_name, const bool delete_node = true) 21374 | { 21375 | if (!valid()) 21376 | return false; 21377 | else 21378 | return local_data().variable_store.remove(variable_name, delete_node); 21379 | } 21380 | 21381 | #ifndef exprtk_disable_string_capabilities 21382 | inline bool remove_stringvar(const std::string& string_name) 21383 | { 21384 | if (!valid()) 21385 | return false; 21386 | else 21387 | return local_data().stringvar_store.remove(string_name); 21388 | } 21389 | #endif 21390 | 21391 | inline bool remove_function(const std::string& function_name) 21392 | { 21393 | if (!valid()) 21394 | return false; 21395 | else 21396 | return local_data().function_store.remove(function_name); 21397 | } 21398 | 21399 | inline bool remove_vararg_function(const std::string& vararg_function_name) 21400 | { 21401 | if (!valid()) 21402 | return false; 21403 | else 21404 | return local_data().vararg_function_store.remove(vararg_function_name); 21405 | } 21406 | 21407 | inline bool remove_vector(const std::string& vector_name) 21408 | { 21409 | if (!valid()) 21410 | return false; 21411 | else 21412 | return local_data().vector_store.remove(vector_name); 21413 | } 21414 | 21415 | inline bool add_constants() 21416 | { 21417 | return add_pi () && 21418 | add_epsilon () && 21419 | add_infinity() ; 21420 | } 21421 | 21422 | inline bool add_pi() 21423 | { 21424 | const typename details::numeric::details::number_type<T>::type num_type; 21425 | static const T local_pi = details::numeric::details::const_pi_impl<T>(num_type); 21426 | return add_constant("pi",local_pi); 21427 | } 21428 | 21429 | inline bool add_epsilon() 21430 | { 21431 | static const T local_epsilon = details::numeric::details::epsilon_type<T>::value(); 21432 | return add_constant("epsilon",local_epsilon); 21433 | } 21434 | 21435 | inline bool add_infinity() 21436 | { 21437 | static const T local_infinity = std::numeric_limits<T>::infinity(); 21438 | return add_constant("inf",local_infinity); 21439 | } 21440 | 21441 | template <typename Package> 21442 | inline bool add_package(Package& package) 21443 | { 21444 | return package.register_package(*this); 21445 | } 21446 | 21447 | template <typename Allocator, 21448 | template <typename, typename> class Sequence> 21449 | inline std::size_t get_variable_list(Sequence<std::pair<std::string,T>,Allocator>& vlist) const 21450 | { 21451 | if (!valid()) 21452 | return 0; 21453 | else 21454 | return local_data().variable_store.get_list(vlist); 21455 | } 21456 | 21457 | template <typename Allocator, 21458 | template <typename, typename> class Sequence> 21459 | inline std::size_t get_variable_list(Sequence<std::string,Allocator>& vlist) const 21460 | { 21461 | if (!valid()) 21462 | return 0; 21463 | else 21464 | return local_data().variable_store.get_list(vlist); 21465 | } 21466 | 21467 | #ifndef exprtk_disable_string_capabilities 21468 | template <typename Allocator, 21469 | template <typename, typename> class Sequence> 21470 | inline std::size_t get_stringvar_list(Sequence<std::pair<std::string,std::string>,Allocator>& svlist) const 21471 | { 21472 | if (!valid()) 21473 | return 0; 21474 | else 21475 | return local_data().stringvar_store.get_list(svlist); 21476 | } 21477 | 21478 | template <typename Allocator, 21479 | template <typename, typename> class Sequence> 21480 | inline std::size_t get_stringvar_list(Sequence<std::string,Allocator>& svlist) const 21481 | { 21482 | if (!valid()) 21483 | return 0; 21484 | else 21485 | return local_data().stringvar_store.get_list(svlist); 21486 | } 21487 | #endif 21488 | 21489 | template <typename Allocator, 21490 | template <typename, typename> class Sequence> 21491 | inline std::size_t get_vector_list(Sequence<std::string,Allocator>& vec_list) const 21492 | { 21493 | if (!valid()) 21494 | return 0; 21495 | else 21496 | return local_data().vector_store.get_list(vec_list); 21497 | } 21498 | 21499 | template <typename Allocator, 21500 | template <typename, typename> class Sequence> 21501 | inline std::size_t get_function_list(Sequence<std::string,Allocator>& function_list) const 21502 | { 21503 | if (!valid()) 21504 | return 0; 21505 | 21506 | std::vector<std::string> function_names; 21507 | std::size_t count = 0; 21508 | 21509 | count += local_data().function_store .get_list(function_names); 21510 | count += local_data().vararg_function_store .get_list(function_names); 21511 | count += local_data().generic_function_store .get_list(function_names); 21512 | count += local_data().string_function_store .get_list(function_names); 21513 | count += local_data().overload_function_store.get_list(function_names); 21514 | 21515 | std::set<std::string> function_set; 21516 | 21517 | for (std::size_t i = 0; i < function_names.size(); ++i) 21518 | { 21519 | function_set.insert(function_names[i]); 21520 | } 21521 | 21522 | std::copy(function_set.begin(), function_set.end(), 21523 | std::back_inserter(function_list)); 21524 | 21525 | return count; 21526 | } 21527 | 21528 | inline std::vector<std::string> get_function_list() const 21529 | { 21530 | std::vector<std::string> result; 21531 | get_function_list(result); 21532 | return result; 21533 | } 21534 | 21535 | inline bool symbol_exists(const std::string& symbol_name, const bool check_reserved_symb = true) const 21536 | { 21537 | /* 21538 | Function will return true if symbol_name exists as either a 21539 | reserved symbol, variable, stringvar, vector or function name 21540 | in any of the type stores. 21541 | */ 21542 | if (!valid()) 21543 | return false; 21544 | else if (local_data().variable_store.symbol_exists(symbol_name)) 21545 | return true; 21546 | #ifndef exprtk_disable_string_capabilities 21547 | else if (local_data().stringvar_store.symbol_exists(symbol_name)) 21548 | return true; 21549 | #endif 21550 | else if (local_data().vector_store.symbol_exists(symbol_name)) 21551 | return true; 21552 | else if (local_data().function_store.symbol_exists(symbol_name)) 21553 | return true; 21554 | else if (check_reserved_symb && local_data().is_reserved_symbol(symbol_name)) 21555 | return true; 21556 | else 21557 | return false; 21558 | } 21559 | 21560 | inline bool is_variable(const std::string& variable_name) const 21561 | { 21562 | if (!valid()) 21563 | return false; 21564 | else 21565 | return local_data().variable_store.symbol_exists(variable_name); 21566 | } 21567 | 21568 | #ifndef exprtk_disable_string_capabilities 21569 | inline bool is_stringvar(const std::string& stringvar_name) const 21570 | { 21571 | if (!valid()) 21572 | return false; 21573 | else 21574 | return local_data().stringvar_store.symbol_exists(stringvar_name); 21575 | } 21576 | 21577 | inline bool is_conststr_stringvar(const std::string& symbol_name) const 21578 | { 21579 | if (!valid()) 21580 | return false; 21581 | else if (!valid_symbol(symbol_name)) 21582 | return false; 21583 | else if (!local_data().stringvar_store.symbol_exists(symbol_name)) 21584 | return false; 21585 | 21586 | return ( 21587 | local_data().stringvar_store.symbol_exists(symbol_name) || 21588 | local_data().stringvar_store.is_constant (symbol_name) 21589 | ); 21590 | } 21591 | #endif 21592 | 21593 | inline bool is_function(const std::string& function_name) const 21594 | { 21595 | if (!valid()) 21596 | return false; 21597 | else 21598 | return local_data().function_store.symbol_exists(function_name); 21599 | } 21600 | 21601 | inline bool is_vararg_function(const std::string& vararg_function_name) const 21602 | { 21603 | if (!valid()) 21604 | return false; 21605 | else 21606 | return local_data().vararg_function_store.symbol_exists(vararg_function_name); 21607 | } 21608 | 21609 | inline bool is_vector(const std::string& vector_name) const 21610 | { 21611 | if (!valid()) 21612 | return false; 21613 | else 21614 | return local_data().vector_store.symbol_exists(vector_name); 21615 | } 21616 | 21617 | inline std::string get_variable_name(const expression_ptr& ptr) const 21618 | { 21619 | return local_data().variable_store.entity_name(ptr); 21620 | } 21621 | 21622 | inline std::string get_vector_name(const vector_holder_ptr& ptr) const 21623 | { 21624 | return local_data().vector_store.entity_name(ptr); 21625 | } 21626 | 21627 | #ifndef exprtk_disable_string_capabilities 21628 | inline std::string get_stringvar_name(const expression_ptr& ptr) const 21629 | { 21630 | return local_data().stringvar_store.entity_name(ptr); 21631 | } 21632 | 21633 | inline std::string get_conststr_stringvar_name(const expression_ptr& ptr) const 21634 | { 21635 | return local_data().stringvar_store.entity_name(ptr); 21636 | } 21637 | #endif 21638 | 21639 | inline bool valid() const 21640 | { 21641 | // Symbol table sanity check. 21642 | return control_block_ && control_block_->data_; 21643 | } 21644 | 21645 | inline void load_from(const symbol_table<T>& st) 21646 | { 21647 | { 21648 | std::vector<std::string> name_list; 21649 | 21650 | st.local_data().function_store.get_list(name_list); 21651 | 21652 | if (!name_list.empty()) 21653 | { 21654 | for (std::size_t i = 0; i < name_list.size(); ++i) 21655 | { 21656 | exprtk::ifunction<T>& ifunc = *st.get_function(name_list[i]); 21657 | add_function(name_list[i],ifunc); 21658 | } 21659 | } 21660 | } 21661 | 21662 | { 21663 | std::vector<std::string> name_list; 21664 | 21665 | st.local_data().vararg_function_store.get_list(name_list); 21666 | 21667 | if (!name_list.empty()) 21668 | { 21669 | for (std::size_t i = 0; i < name_list.size(); ++i) 21670 | { 21671 | exprtk::ivararg_function<T>& ivafunc = *st.get_vararg_function(name_list[i]); 21672 | add_function(name_list[i],ivafunc); 21673 | } 21674 | } 21675 | } 21676 | 21677 | { 21678 | std::vector<std::string> name_list; 21679 | 21680 | st.local_data().generic_function_store.get_list(name_list); 21681 | 21682 | if (!name_list.empty()) 21683 | { 21684 | for (std::size_t i = 0; i < name_list.size(); ++i) 21685 | { 21686 | exprtk::igeneric_function<T>& ifunc = *st.get_generic_function(name_list[i]); 21687 | add_function(name_list[i],ifunc); 21688 | } 21689 | } 21690 | } 21691 | 21692 | { 21693 | std::vector<std::string> name_list; 21694 | 21695 | st.local_data().string_function_store.get_list(name_list); 21696 | 21697 | if (!name_list.empty()) 21698 | { 21699 | for (std::size_t i = 0; i < name_list.size(); ++i) 21700 | { 21701 | exprtk::igeneric_function<T>& ifunc = *st.get_string_function(name_list[i]); 21702 | add_function(name_list[i],ifunc); 21703 | } 21704 | } 21705 | } 21706 | 21707 | { 21708 | std::vector<std::string> name_list; 21709 | 21710 | st.local_data().overload_function_store.get_list(name_list); 21711 | 21712 | if (!name_list.empty()) 21713 | { 21714 | for (std::size_t i = 0; i < name_list.size(); ++i) 21715 | { 21716 | exprtk::igeneric_function<T>& ifunc = *st.get_overload_function(name_list[i]); 21717 | add_function(name_list[i],ifunc); 21718 | } 21719 | } 21720 | } 21721 | } 21722 | 21723 | inline void load_variables_from(const symbol_table<T>& st) 21724 | { 21725 | std::vector<std::string> name_list; 21726 | 21727 | st.local_data().variable_store.get_list(name_list); 21728 | 21729 | if (!name_list.empty()) 21730 | { 21731 | for (std::size_t i = 0; i < name_list.size(); ++i) 21732 | { 21733 | T& variable = st.get_variable(name_list[i])->ref(); 21734 | add_variable(name_list[i], variable); 21735 | } 21736 | } 21737 | } 21738 | 21739 | inline void load_vectors_from(const symbol_table<T>& st) 21740 | { 21741 | std::vector<std::string> name_list; 21742 | 21743 | st.local_data().vector_store.get_list(name_list); 21744 | 21745 | if (!name_list.empty()) 21746 | { 21747 | for (std::size_t i = 0; i < name_list.size(); ++i) 21748 | { 21749 | vector_holder_t& vecholder = *st.get_vector(name_list[i]); 21750 | add_vector(name_list[i], vecholder.data(), vecholder.size()); 21751 | } 21752 | } 21753 | } 21754 | 21755 | private: 21756 | 21757 | inline bool valid_symbol(const std::string& symbol, const bool check_reserved_symb = true) const 21758 | { 21759 | if (symbol.empty()) 21760 | return false; 21761 | else if (!details::is_letter(symbol[0])) 21762 | return false; 21763 | else if (symbol.size() > 1) 21764 | { 21765 | for (std::size_t i = 1; i < symbol.size(); ++i) 21766 | { 21767 | if ( 21768 | !details::is_letter_or_digit(symbol[i]) && 21769 | ('_' != symbol[i]) 21770 | ) 21771 | { 21772 | if ((i < (symbol.size() - 1)) && ('.' == symbol[i])) 21773 | continue; 21774 | else 21775 | return false; 21776 | } 21777 | } 21778 | } 21779 | 21780 | return (check_reserved_symb) ? (!local_data().is_reserved_symbol(symbol)) : true; 21781 | } 21782 | 21783 | inline bool valid_function(const std::string& symbol) const 21784 | { 21785 | if (symbol.empty()) 21786 | return false; 21787 | else if (!details::is_letter(symbol[0])) 21788 | return false; 21789 | else if (symbol.size() > 1) 21790 | { 21791 | for (std::size_t i = 1; i < symbol.size(); ++i) 21792 | { 21793 | if ( 21794 | !details::is_letter_or_digit(symbol[i]) && 21795 | ('_' != symbol[i]) 21796 | ) 21797 | { 21798 | if ((i < (symbol.size() - 1)) && ('.' == symbol[i])) 21799 | continue; 21800 | else 21801 | return false; 21802 | } 21803 | } 21804 | } 21805 | 21806 | return true; 21807 | } 21808 | 21809 | typedef typename control_block::st_data local_data_t; 21810 | 21811 | inline local_data_t& local_data() 21812 | { 21813 | return *(control_block_->data_); 21814 | } 21815 | 21816 | inline const local_data_t& local_data() const 21817 | { 21818 | return *(control_block_->data_); 21819 | } 21820 | 21821 | control_block* control_block_; 21822 | 21823 | friend class parser<T>; 21824 | }; // class symbol_table 21825 | 21826 | template <typename T> 21827 | class function_compositor; 21828 | 21829 | template <typename T> 21830 | class expression 21831 | { 21832 | private: 21833 | 21834 | typedef details::expression_node<T>* expression_ptr; 21835 | typedef details::vector_holder<T>* vector_holder_ptr; 21836 | typedef std::vector<symbol_table<T> > symtab_list_t; 21837 | 21838 | struct control_block 21839 | { 21840 | enum data_type 21841 | { 21842 | e_unknown , 21843 | e_expr , 21844 | e_vecholder, 21845 | e_data , 21846 | e_vecdata , 21847 | e_string 21848 | }; 21849 | 21850 | static std::string to_str(data_type dt) 21851 | { 21852 | switch (dt) 21853 | { 21854 | case e_unknown : return "e_unknown " 21855 | case e_expr : return "e_expr" ; 21856 | case e_vecholder : return "e_vecholder" 21857 | case e_data : return "e_data" ; 21858 | case e_vecdata : return "e_vecdata" ; 21859 | case e_string : return "e_string" ; 21860 | } 21861 | 21862 | return "" 21863 | } 21864 | 21865 | struct data_pack 21866 | { 21867 | data_pack() 21868 | : pointer(0) 21869 | , type(e_unknown) 21870 | , size(0) 21871 | {} 21872 | 21873 | data_pack(void* ptr, const data_type dt, const std::size_t sz = 0) 21874 | : pointer(ptr) 21875 | , type(dt) 21876 | , size(sz) 21877 | {} 21878 | 21879 | void* pointer; 21880 | data_type type; 21881 | std::size_t size; 21882 | }; 21883 | 21884 | typedef std::vector<data_pack> local_data_list_t; 21885 | typedef results_context<T> results_context_t; 21886 | typedef control_block* cntrl_blck_ptr_t; 21887 | 21888 | control_block() 21889 | : ref_count(0) 21890 | , expr (0) 21891 | , results (0) 21892 | , retinv_null(false) 21893 | , return_invoked(&retinv_null) 21894 | {} 21895 | 21896 | explicit control_block(expression_ptr e) 21897 | : ref_count(1) 21898 | , expr (e) 21899 | , results (0) 21900 | , retinv_null(false) 21901 | , return_invoked(&retinv_null) 21902 | {} 21903 | 21904 | ~control_block() 21905 | { 21906 | if (expr && details::branch_deletable(expr)) 21907 | { 21908 | destroy_node(expr); 21909 | } 21910 | 21911 | if (!local_data_list.empty()) 21912 | { 21913 | for (std::size_t i = 0; i < local_data_list.size(); ++i) 21914 | { 21915 | switch (local_data_list[i].type) 21916 | { 21917 | case e_expr : delete reinterpret_cast<expression_ptr>(local_data_list[i].pointer); 21918 | break; 21919 | 21920 | case e_vecholder : delete reinterpret_cast<vector_holder_ptr>(local_data_list[i].pointer); 21921 | break; 21922 | 21923 | case e_data : delete reinterpret_cast<T*>(local_data_list[i].pointer); 21924 | break; 21925 | 21926 | case e_vecdata : delete [] reinterpret_cast<T*>(local_data_list[i].pointer); 21927 | break; 21928 | 21929 | case e_string : delete reinterpret_cast<std::string*>(local_data_list[i].pointer); 21930 | break; 21931 | 21932 | default : break; 21933 | } 21934 | } 21935 | } 21936 | 21937 | if (results) 21938 | { 21939 | delete results; 21940 | } 21941 | } 21942 | 21943 | static inline cntrl_blck_ptr_t create(expression_ptr e) 21944 | { 21945 | return new control_block(e); 21946 | } 21947 | 21948 | static inline void destroy(cntrl_blck_ptr_t& cntrl_blck) 21949 | { 21950 | if (cntrl_blck) 21951 | { 21952 | if ( 21953 | (0 != cntrl_blck->ref_count) && 21954 | (0 == --cntrl_blck->ref_count) 21955 | ) 21956 | { 21957 | delete cntrl_blck; 21958 | } 21959 | 21960 | cntrl_blck = 0; 21961 | } 21962 | } 21963 | 21964 | std::size_t ref_count; 21965 | expression_ptr expr; 21966 | local_data_list_t local_data_list; 21967 | results_context_t* results; 21968 | bool retinv_null; 21969 | bool* return_invoked; 21970 | 21971 | friend class function_compositor<T>; 21972 | }; 21973 | 21974 | public: 21975 | 21976 | expression() 21977 | : control_block_(0) 21978 | { 21979 | set_expression(new details::null_node<T>()); 21980 | } 21981 | 21982 | expression(const expression<T>& e) 21983 | : control_block_ (e.control_block_ ) 21984 | , symbol_table_list_(e.symbol_table_list_) 21985 | { 21986 | control_block_->ref_count++; 21987 | } 21988 | 21989 | explicit expression(const symbol_table<T>& symbol_table) 21990 | : control_block_(0) 21991 | { 21992 | set_expression(new details::null_node<T>()); 21993 | symbol_table_list_.push_back(symbol_table); 21994 | } 21995 | 21996 | inline expression<T>& operator=(const expression<T>& e) 21997 | { 21998 | if (this != &e) 21999 | { 22000 | if (control_block_) 22001 | { 22002 | if ( 22003 | (0 != control_block_->ref_count) && 22004 | (0 == --control_block_->ref_count) 22005 | ) 22006 | { 22007 | delete control_block_; 22008 | } 22009 | 22010 | control_block_ = 0; 22011 | } 22012 | 22013 | control_block_ = e.control_block_; 22014 | control_block_->ref_count++; 22015 | symbol_table_list_ = e.symbol_table_list_; 22016 | } 22017 | 22018 | return *this; 22019 | } 22020 | 22021 | inline bool operator==(const expression<T>& e) const 22022 | { 22023 | return (this == &e); 22024 | } 22025 | 22026 | inline bool operator!() const 22027 | { 22028 | return ( 22029 | (0 == control_block_ ) || 22030 | (0 == control_block_->expr) 22031 | ); 22032 | } 22033 | 22034 | inline expression<T>& release() 22035 | { 22036 | exprtk::details::dump_ptr("expression::release", this); 22037 | control_block::destroy(control_block_); 22038 | 22039 | return (*this); 22040 | } 22041 | 22042 | ~expression() 22043 | { 22044 | control_block::destroy(control_block_); 22045 | } 22046 | 22047 | inline T value() const 22048 | { 22049 | assert(control_block_ ); 22050 | assert(control_block_->expr); 22051 | 22052 | return control_block_->expr->value(); 22053 | } 22054 | 22055 | inline T operator() () const 22056 | { 22057 | return value(); 22058 | } 22059 | 22060 | inline operator T() const 22061 | { 22062 | return value(); 22063 | } 22064 | 22065 | inline operator bool() const 22066 | { 22067 | return details::is_true(value()); 22068 | } 22069 | 22070 | inline bool register_symbol_table(symbol_table<T>& st) 22071 | { 22072 | for (std::size_t i = 0; i < symbol_table_list_.size(); ++i) 22073 | { 22074 | if (st == symbol_table_list_[i]) 22075 | { 22076 | return false; 22077 | } 22078 | } 22079 | 22080 | symbol_table_list_.push_back(st); 22081 | return true; 22082 | } 22083 | 22084 | inline const symbol_table<T>& get_symbol_table(const std::size_t& index = 0) const 22085 | { 22086 | return symbol_table_list_[index]; 22087 | } 22088 | 22089 | inline symbol_table<T>& get_symbol_table(const std::size_t& index = 0) 22090 | { 22091 | return symbol_table_list_[index]; 22092 | } 22093 | 22094 | std::size_t num_symbol_tables() const 22095 | { 22096 | return symbol_table_list_.size(); 22097 | } 22098 | 22099 | typedef results_context<T> results_context_t; 22100 | 22101 | inline const results_context_t& results() const 22102 | { 22103 | if (control_block_->results) 22104 | return (*control_block_->results); 22105 | else 22106 | { 22107 | static const results_context_t null_results; 22108 | return null_results; 22109 | } 22110 | } 22111 | 22112 | inline bool return_invoked() const 22113 | { 22114 | assert(control_block_); 22115 | 22116 | return control_block_ && 22117 | control_block_->return_invoked && 22118 | (*control_block_->return_invoked); 22119 | } 22120 | 22121 | private: 22122 | 22123 | inline symtab_list_t get_symbol_table_list() const 22124 | { 22125 | return symbol_table_list_; 22126 | } 22127 | 22128 | inline void set_expression(const expression_ptr expr) 22129 | { 22130 | if (expr) 22131 | { 22132 | if (control_block_) 22133 | { 22134 | if (0 == --control_block_->ref_count) 22135 | { 22136 | delete control_block_; 22137 | } 22138 | } 22139 | 22140 | control_block_ = control_block::create(expr); 22141 | } 22142 | } 22143 | 22144 | inline void register_local_var(expression_ptr expr) 22145 | { 22146 | if (expr) 22147 | { 22148 | if (control_block_) 22149 | { 22150 | control_block_-> 22151 | local_data_list.push_back( 22152 | typename expression<T>::control_block:: 22153 | data_pack(reinterpret_cast<void*>(expr), 22154 | control_block::e_expr)); 22155 | } 22156 | } 22157 | } 22158 | 22159 | inline void register_local_var(vector_holder_ptr vec_holder) 22160 | { 22161 | if (vec_holder) 22162 | { 22163 | if (control_block_) 22164 | { 22165 | control_block_-> 22166 | local_data_list.push_back( 22167 | typename expression<T>::control_block:: 22168 | data_pack(reinterpret_cast<void*>(vec_holder), 22169 | control_block::e_vecholder)); 22170 | } 22171 | } 22172 | } 22173 | 22174 | inline void register_local_data(void* data, const std::size_t& size = 0, const std::size_t data_mode = 0) 22175 | { 22176 | if (data) 22177 | { 22178 | if (control_block_) 22179 | { 22180 | typename control_block::data_type dt = control_block::e_data; 22181 | 22182 | switch (data_mode) 22183 | { 22184 | case 0 : dt = control_block::e_data; break; 22185 | case 1 : dt = control_block::e_vecdata; break; 22186 | case 2 : dt = control_block::e_string; break; 22187 | } 22188 | 22189 | control_block_-> 22190 | local_data_list.push_back( 22191 | typename expression<T>::control_block:: 22192 | data_pack(reinterpret_cast<void*>(data), dt, size)); 22193 | } 22194 | } 22195 | } 22196 | 22197 | inline const typename control_block::local_data_list_t& local_data_list() 22198 | { 22199 | if (control_block_) 22200 | { 22201 | return control_block_->local_data_list; 22202 | } 22203 | else 22204 | { 22205 | static typename control_block::local_data_list_t null_local_data_list; 22206 | return null_local_data_list; 22207 | } 22208 | } 22209 | 22210 | inline void register_return_results(results_context_t* rc) 22211 | { 22212 | if (control_block_ && rc) 22213 | { 22214 | control_block_->results = rc; 22215 | } 22216 | } 22217 | 22218 | inline void set_retinvk(bool* retinvk_ptr) 22219 | { 22220 | if (control_block_) 22221 | { 22222 | control_block_->return_invoked = retinvk_ptr; 22223 | } 22224 | } 22225 | 22226 | control_block* control_block_; 22227 | symtab_list_t symbol_table_list_; 22228 | 22229 | friend class parser<T>; 22230 | friend class expression_helper<T>; 22231 | friend class function_compositor<T>; 22232 | template <typename TT> 22233 | friend bool is_valid(const expression<TT>& expr); 22234 | }; // class expression 22235 | 22236 | template <typename T> 22237 | class expression_helper 22238 | { 22239 | public: 22240 | 22241 | enum node_types 22242 | { 22243 | e_literal, 22244 | e_variable, 22245 | e_string, 22246 | e_unary, 22247 | e_binary, 22248 | e_function, 22249 | e_vararg, 22250 | e_null, 22251 | e_assert, 22252 | e_sf3ext, 22253 | e_sf4ext 22254 | }; 22255 | 22256 | static inline bool is_literal(const expression<T>& expr) 22257 | { 22258 | return expr.control_block_ && details::is_literal_node(expr.control_block_->expr); 22259 | } 22260 | 22261 | static inline bool is_variable(const expression<T>& expr) 22262 | { 22263 | return expr.control_block_ && details::is_variable_node(expr.control_block_->expr); 22264 | } 22265 | 22266 | static inline bool is_string(const expression<T>& expr) 22267 | { 22268 | return expr.control_block_ && details::is_generally_string_node(expr.control_block_->expr); 22269 | } 22270 | 22271 | static inline bool is_unary(const expression<T>& expr) 22272 | { 22273 | return expr.control_block_ && details::is_unary_node(expr.control_block_->expr); 22274 | } 22275 | 22276 | static inline bool is_binary(const expression<T>& expr) 22277 | { 22278 | return expr.control_block_ && details::is_binary_node(expr.control_block_->expr); 22279 | } 22280 | 22281 | static inline bool is_function(const expression<T>& expr) 22282 | { 22283 | return expr.control_block_ && details::is_function(expr.control_block_->expr); 22284 | } 22285 | 22286 | static inline bool is_vararg(const expression<T>& expr) 22287 | { 22288 | return expr.control_block_ && details::is_vararg_node(expr.control_block_->expr); 22289 | } 22290 | 22291 | static inline bool is_null(const expression<T>& expr) 22292 | { 22293 | return expr.control_block_ && details::is_null_node(expr.control_block_->expr); 22294 | } 22295 | 22296 | static inline bool is_assert(const expression<T>& expr) 22297 | { 22298 | return expr.control_block_ && details::is_assert_node(expr.control_block_->expr); 22299 | } 22300 | 22301 | static inline bool is_sf3ext(const expression<T>& expr) 22302 | { 22303 | return expr.control_block_ && details::is_sf3ext_node(expr.control_block_->expr); 22304 | } 22305 | 22306 | static inline bool is_sf4ext(const expression<T>& expr) 22307 | { 22308 | return expr.control_block_ && details::is_sf4ext_node(expr.control_block_->expr); 22309 | } 22310 | 22311 | static inline bool is_type(const expression<T>& expr, const node_types node_type) 22312 | { 22313 | if (0 == expr.control_block_) 22314 | { 22315 | return false; 22316 | } 22317 | 22318 | switch (node_type) 22319 | { 22320 | case e_literal : return is_literal_node(expr); 22321 | case e_variable : return is_variable (expr); 22322 | case e_string : return is_string (expr); 22323 | case e_unary : return is_unary (expr); 22324 | case e_binary : return is_binary (expr); 22325 | case e_function : return is_function (expr); 22326 | case e_null : return is_null (expr); 22327 | case e_assert : return is_assert (expr); 22328 | case e_sf3ext : return is_sf3ext (expr); 22329 | case e_sf4ext : return is_sf4ext (expr); 22330 | }; 22331 | 22332 | return false; 22333 | } 22334 | 22335 | static inline bool match_type_sequence(const expression<T>& expr, const std::vector<node_types>& type_seq) 22336 | { 22337 | if ((0 == expr.control_block_) || !is_vararg(expr)) 22338 | { 22339 | return false; 22340 | } 22341 | 22342 | typedef details::vararg_node<T, exprtk::details::vararg_multi_op<T> > mo_vararg_t; 22343 | 22344 | mo_vararg_t* vnode = dynamic_cast<mo_vararg_t*>(expr.control_block_->expr); 22345 | 22346 | if ( 22347 | (0 == vnode) || 22348 | type_seq.empty() || 22349 | (vnode->size() < type_seq.size()) 22350 | ) 22351 | { 22352 | return false; 22353 | } 22354 | 22355 | for (std::size_t i = 0; i < type_seq.size(); ++i) 22356 | { 22357 | assert((*vnode)[i]); 22358 | 22359 | switch (type_seq[i]) 22360 | { 22361 | case e_literal : { if (details::is_literal_node ((*vnode)[i])) continue; } break; 22362 | case e_variable : { if (details::is_variable_node ((*vnode)[i])) continue; } break; 22363 | case e_string : { if (details::is_generally_string_node((*vnode)[i])) continue; } break; 22364 | case e_unary : { if (details::is_unary_node ((*vnode)[i])) continue; } break; 22365 | case e_binary : { if (details::is_binary_node ((*vnode)[i])) continue; } break; 22366 | case e_function : { if (details::is_function ((*vnode)[i])) continue; } break; 22367 | case e_null : { if (details::is_null_node ((*vnode)[i])) continue; } break; 22368 | case e_assert : { if (details::is_assert_node ((*vnode)[i])) continue; } break; 22369 | case e_sf3ext : { if (details::is_sf3ext_node ((*vnode)[i])) continue; } break; 22370 | case e_sf4ext : { if (details::is_sf4ext_node ((*vnode)[i])) continue; } break; 22371 | case e_vararg : break; 22372 | } 22373 | 22374 | return false; 22375 | } 22376 | 22377 | return true; 22378 | } 22379 | }; 22380 | 22381 | template <typename T> 22382 | inline bool is_valid(const expression<T>& expr) 22383 | { 22384 | return expr.control_block_ && !expression_helper<T>::is_null(expr); 22385 | } 22386 | 22387 | namespace parser_error 22388 | { 22389 | enum error_mode 22390 | { 22391 | e_unknown = 0, 22392 | e_syntax = 1, 22393 | e_token = 2, 22394 | e_numeric = 4, 22395 | e_symtab = 5, 22396 | e_lexer = 6, 22397 | e_synthesis = 7, 22398 | e_helper = 8, 22399 | e_parser = 9 22400 | }; 22401 | 22402 | struct type 22403 | { 22404 | type() 22405 | : mode(parser_error::e_unknown) 22406 | , line_no (0) 22407 | , column_no(0) 22408 | {} 22409 | 22410 | lexer::token token; 22411 | error_mode mode; 22412 | std::string diagnostic; 22413 | std::string src_location; 22414 | std::string error_line; 22415 | std::size_t line_no; 22416 | std::size_t column_no; 22417 | }; 22418 | 22419 | inline type make_error(const error_mode mode, 22420 | const std::string& diagnostic = "", 22421 | const std::string& src_location = "") 22422 | { 22423 | type t; 22424 | t.mode = mode; 22425 | t.token.type = lexer::token::e_error; 22426 | t.diagnostic = diagnostic; 22427 | t.src_location = src_location; 22428 | exprtk_debug(("%s\n", diagnostic .c_str())); 22429 | return t; 22430 | } 22431 | 22432 | inline type make_error(const error_mode mode, 22433 | const lexer::token& tk, 22434 | const std::string& diagnostic = "", 22435 | const std::string& src_location = "") 22436 | { 22437 | type t; 22438 | t.mode = mode; 22439 | t.token = tk; 22440 | t.diagnostic = diagnostic; 22441 | t.src_location = src_location; 22442 | exprtk_debug(("%s\n", diagnostic .c_str())); 22443 | return t; 22444 | } 22445 | 22446 | inline std::string to_str(error_mode mode) 22447 | { 22448 | switch (mode) 22449 | { 22450 | case e_unknown : return std::string("Unknown Error"); 22451 | case e_syntax : return std::string("Syntax Error" ); 22452 | case e_token : return std::string("Token Error" ); 22453 | case e_numeric : return std::string("Numeric Error"); 22454 | case e_symtab : return std::string("Symbol Error" ); 22455 | case e_lexer : return std::string("Lexer Error" ); 22456 | case e_helper : return std::string("Helper Error" ); 22457 | case e_parser : return std::string("Parser Error" ); 22458 | default : return std::string("Unknown Error"); 22459 | } 22460 | } 22461 | 22462 | inline bool update_error(type& error, const std::string& expression) 22463 | { 22464 | if ( 22465 | expression.empty() || 22466 | (error.token.position > expression.size()) || 22467 | (std::numeric_limits<std::size_t>::max() == error.token.position) 22468 | ) 22469 | { 22470 | return false; 22471 | } 22472 | 22473 | std::size_t error_line_start = 0; 22474 | 22475 | for (std::size_t i = error.token.position; i > 0; --i) 22476 | { 22477 | const details::char_t c = expression[i]; 22478 | 22479 | if (('\n' == c) || ('\r' == c)) 22480 | { 22481 | error_line_start = i + 1; 22482 | break; 22483 | } 22484 | } 22485 | 22486 | std::size_t next_nl_position = std::min(expression.size(), 22487 | expression.find_first_of('\n',error.token.position + 1)); 22488 | 22489 | error.column_no = error.token.position - error_line_start; 22490 | error.error_line = expression.substr(error_line_start, 22491 | next_nl_position - error_line_start); 22492 | 22493 | error.line_no = 0; 22494 | 22495 | for (std::size_t i = 0; i < next_nl_position; ++i) 22496 | { 22497 | if ('\n' == expression[i]) 22498 | ++error.line_no; 22499 | } 22500 | 22501 | return true; 22502 | } 22503 | 22504 | inline void dump_error(const type& error) 22505 | { 22506 | printf("Position: %02d Type: [%s] Msg: %s\n", 22507 | static_cast<int>(error.token.position), 22508 | exprtk::parser_error::to_str(error.mode).c_str(), 22509 | error.diagnostic.c_str()); 22510 | } 22511 | } 22512 | 22513 | namespace details 22514 | { 22515 | template <typename Parser> 22516 | inline void disable_type_checking(Parser& p) 22517 | { 22518 | p.state_.type_check_enabled = false; 22519 | } 22520 | } 22521 | 22522 | template <typename T> 22523 | class parser : public lexer::parser_helper 22524 | { 22525 | private: 22526 | 22527 | enum precedence_level 22528 | { 22529 | e_level00, e_level01, e_level02, e_level03, e_level04, 22530 | e_level05, e_level06, e_level07, e_level08, e_level09, 22531 | e_level10, e_level11, e_level12, e_level13, e_level14 22532 | }; 22533 | 22534 | typedef const T& cref_t; 22535 | typedef const T const_t; 22536 | typedef ifunction<T> F; 22537 | typedef ivararg_function<T> VAF; 22538 | typedef igeneric_function<T> GF; 22539 | typedef ifunction<T> ifunction_t; 22540 | typedef ivararg_function<T> ivararg_function_t; 22541 | typedef igeneric_function<T> igeneric_function_t; 22542 | typedef details::expression_node<T> expression_node_t; 22543 | typedef details::literal_node<T> literal_node_t; 22544 | typedef details::unary_node<T> unary_node_t; 22545 | typedef details::binary_node<T> binary_node_t; 22546 | typedef details::trinary_node<T> trinary_node_t; 22547 | typedef details::quaternary_node<T> quaternary_node_t; 22548 | typedef details::conditional_node<T> conditional_node_t; 22549 | typedef details::cons_conditional_node<T> cons_conditional_node_t; 22550 | typedef details::while_loop_node<T> while_loop_node_t; 22551 | typedef details::repeat_until_loop_node<T> repeat_until_loop_node_t; 22552 | typedef details::for_loop_node<T> for_loop_node_t; 22553 | typedef details::while_loop_rtc_node<T> while_loop_rtc_node_t; 22554 | typedef details::repeat_until_loop_rtc_node<T> repeat_until_loop_rtc_node_t; 22555 | typedef details::for_loop_rtc_node<T> for_loop_rtc_node_t; 22556 | #ifndef exprtk_disable_break_continue 22557 | typedef details::while_loop_bc_node<T> while_loop_bc_node_t; 22558 | typedef details::repeat_until_loop_bc_node<T> repeat_until_loop_bc_node_t; 22559 | typedef details::for_loop_bc_node<T> for_loop_bc_node_t; 22560 | typedef details::while_loop_bc_rtc_node<T> while_loop_bc_rtc_node_t; 22561 | typedef details::repeat_until_loop_bc_rtc_node<T> repeat_until_loop_bc_rtc_node_t; 22562 | typedef details::for_loop_bc_rtc_node<T> for_loop_bc_rtc_node_t; 22563 | #endif 22564 | typedef details::switch_node<T> switch_node_t; 22565 | typedef details::variable_node<T> variable_node_t; 22566 | typedef details::vector_elem_node<T> vector_elem_node_t; 22567 | typedef details::vector_celem_node<T> vector_celem_node_t; 22568 | typedef details::vector_elem_rtc_node<T> vector_elem_rtc_node_t; 22569 | typedef details::vector_celem_rtc_node<T> vector_celem_rtc_node_t; 22570 | typedef details::rebasevector_elem_node<T> rebasevector_elem_node_t; 22571 | typedef details::rebasevector_celem_node<T> rebasevector_celem_node_t; 22572 | typedef details::rebasevector_elem_rtc_node<T> rebasevector_elem_rtc_node_t; 22573 | typedef details::rebasevector_celem_rtc_node<T> rebasevector_celem_rtc_node_t; 22574 | typedef details::vector_node<T> vector_node_t; 22575 | typedef details::vector_size_node<T> vector_size_node_t; 22576 | typedef details::range_pack<T> range_t; 22577 | #ifndef exprtk_disable_string_capabilities 22578 | typedef details::stringvar_node<T> stringvar_node_t; 22579 | typedef details::string_literal_node<T> string_literal_node_t; 22580 | typedef details::string_range_node<T> string_range_node_t; 22581 | typedef details::const_string_range_node<T> const_string_range_node_t; 22582 | typedef details::generic_string_range_node<T> generic_string_range_node_t; 22583 | typedef details::string_concat_node<T> string_concat_node_t; 22584 | typedef details::assignment_string_node<T> assignment_string_node_t; 22585 | typedef details::assignment_string_range_node<T> assignment_string_range_node_t; 22586 | typedef details::conditional_string_node<T> conditional_string_node_t; 22587 | typedef details::cons_conditional_str_node<T> cons_conditional_str_node_t; 22588 | #endif 22589 | typedef details::assignment_node<T> assignment_node_t; 22590 | typedef details::assignment_vec_elem_node<T> assignment_vec_elem_node_t; 22591 | typedef details::assignment_vec_elem_rtc_node<T> assignment_vec_elem_rtc_node_t; 22592 | typedef details::assignment_rebasevec_elem_node<T> assignment_rebasevec_elem_node_t; 22593 | typedef details::assignment_rebasevec_elem_rtc_node<T> assignment_rebasevec_elem_rtc_node_t; 22594 | typedef details::assignment_rebasevec_celem_node<T> assignment_rebasevec_celem_node_t; 22595 | typedef details::assignment_vec_node<T> assignment_vec_node_t; 22596 | typedef details::assignment_vecvec_node<T> assignment_vecvec_node_t; 22597 | typedef details::conditional_vector_node<T> conditional_vector_node_t; 22598 | typedef details::scand_node<T> scand_node_t; 22599 | typedef details::scor_node<T> scor_node_t; 22600 | typedef lexer::token token_t; 22601 | typedef expression_node_t* expression_node_ptr; 22602 | typedef expression<T> expression_t; 22603 | typedef symbol_table<T> symbol_table_t; 22604 | typedef typename expression<T>::symtab_list_t symbol_table_list_t; 22605 | typedef details::vector_holder<T> vector_holder_t; 22606 | typedef vector_holder_t* vector_holder_ptr; 22607 | 22608 | typedef typename details::functor_t<T> functor_t; 22609 | typedef typename functor_t::qfunc_t quaternary_functor_t; 22610 | typedef typename functor_t::tfunc_t trinary_functor_t; 22611 | typedef typename functor_t::bfunc_t binary_functor_t; 22612 | typedef typename functor_t::ufunc_t unary_functor_t; 22613 | 22614 | typedef details::operator_type operator_t; 22615 | 22616 | typedef std::map<operator_t, unary_functor_t > unary_op_map_t; 22617 | typedef std::map<operator_t, binary_functor_t > binary_op_map_t; 22618 | typedef std::map<operator_t, trinary_functor_t> trinary_op_map_t; 22619 | 22620 | typedef std::map<std::string,std::pair<trinary_functor_t ,operator_t> > sf3_map_t; 22621 | typedef std::map<std::string,std::pair<quaternary_functor_t,operator_t> > sf4_map_t; 22622 | 22623 | typedef std::map<binary_functor_t,operator_t> inv_binary_op_map_t; 22624 | typedef std::multimap<std::string,details::base_operation_t,details::ilesscompare> base_ops_map_t; 22625 | typedef std::set<std::string,details::ilesscompare> disabled_func_set_t; 22626 | 22627 | typedef details::T0oT1_define<T, cref_t , cref_t > vov_t; 22628 | typedef details::T0oT1_define<T, const_t, cref_t > cov_t; 22629 | typedef details::T0oT1_define<T, cref_t , const_t> voc_t; 22630 | 22631 | typedef details::T0oT1oT2_define<T, cref_t , cref_t , cref_t > vovov_t; 22632 | typedef details::T0oT1oT2_define<T, cref_t , cref_t , const_t> vovoc_t; 22633 | typedef details::T0oT1oT2_define<T, cref_t , const_t, cref_t > vocov_t; 22634 | typedef details::T0oT1oT2_define<T, const_t, cref_t , cref_t > covov_t; 22635 | typedef details::T0oT1oT2_define<T, const_t, cref_t , const_t> covoc_t; 22636 | typedef details::T0oT1oT2_define<T, const_t, const_t, cref_t > cocov_t; 22637 | typedef details::T0oT1oT2_define<T, cref_t , const_t, const_t> vococ_t; 22638 | 22639 | typedef details::T0oT1oT2oT3_define<T, cref_t , cref_t , cref_t , cref_t > vovovov_t; 22640 | typedef details::T0oT1oT2oT3_define<T, cref_t , cref_t , cref_t , const_t> vovovoc_t; 22641 | typedef details::T0oT1oT2oT3_define<T, cref_t , cref_t , const_t, cref_t > vovocov_t; 22642 | typedef details::T0oT1oT2oT3_define<T, cref_t , const_t, cref_t , cref_t > vocovov_t; 22643 | typedef details::T0oT1oT2oT3_define<T, const_t, cref_t , cref_t , cref_t > covovov_t; 22644 | 22645 | typedef details::T0oT1oT2oT3_define<T, const_t, cref_t , const_t, cref_t > covocov_t; 22646 | typedef details::T0oT1oT2oT3_define<T, cref_t , const_t, cref_t , const_t> vocovoc_t; 22647 | typedef details::T0oT1oT2oT3_define<T, const_t, cref_t , cref_t , const_t> covovoc_t; 22648 | typedef details::T0oT1oT2oT3_define<T, cref_t , const_t, const_t, cref_t > vococov_t; 22649 | 22650 | typedef results_context<T> results_context_t; 22651 | 22652 | typedef parser_helper prsrhlpr_t; 22653 | 22654 | struct scope_element 22655 | { 22656 | enum element_type 22657 | { 22658 | e_none , 22659 | e_literal , 22660 | e_variable, 22661 | e_vector , 22662 | e_vecelem , 22663 | e_string 22664 | }; 22665 | 22666 | typedef details::vector_holder<T> vector_holder_t; 22667 | typedef literal_node_t* literal_node_ptr; 22668 | typedef variable_node_t* variable_node_ptr; 22669 | typedef vector_holder_t* vector_holder_ptr; 22670 | typedef expression_node_t* expression_node_ptr; 22671 | #ifndef exprtk_disable_string_capabilities 22672 | typedef stringvar_node_t* stringvar_node_ptr; 22673 | #endif 22674 | 22675 | scope_element() 22676 | : name("???") 22677 | , size (std::numeric_limits<std::size_t>::max()) 22678 | , index(std::numeric_limits<std::size_t>::max()) 22679 | , depth(std::numeric_limits<std::size_t>::max()) 22680 | , ref_count(0) 22681 | , ip_index (0) 22682 | , type (e_none) 22683 | , active (false) 22684 | , data (0) 22685 | , var_node (0) 22686 | , vec_node (0) 22687 | #ifndef exprtk_disable_string_capabilities 22688 | , str_node(0) 22689 | #endif 22690 | {} 22691 | 22692 | bool operator < (const scope_element& se) const 22693 | { 22694 | if (ip_index < se.ip_index) 22695 | return true; 22696 | else if (ip_index > se.ip_index) 22697 | return false; 22698 | else if (depth < se.depth) 22699 | return true; 22700 | else if (depth > se.depth) 22701 | return false; 22702 | else if (index < se.index) 22703 | return true; 22704 | else if (index > se.index) 22705 | return false; 22706 | else 22707 | return (name < se.name); 22708 | } 22709 | 22710 | void clear() 22711 | { 22712 | name = "???" 22713 | size = std::numeric_limits<std::size_t>::max(); 22714 | index = std::numeric_limits<std::size_t>::max(); 22715 | depth = std::numeric_limits<std::size_t>::max(); 22716 | type = e_none; 22717 | active = false; 22718 | ref_count = 0; 22719 | ip_index = 0; 22720 | data = 0; 22721 | var_node = 0; 22722 | vec_node = 0; 22723 | #ifndef exprtk_disable_string_capabilities 22724 | str_node = 0; 22725 | #endif 22726 | } 22727 | 22728 | std::string name; 22729 | std::size_t size; 22730 | std::size_t index; 22731 | std::size_t depth; 22732 | std::size_t ref_count; 22733 | std::size_t ip_index; 22734 | element_type type; 22735 | bool active; 22736 | void* data; 22737 | expression_node_ptr var_node; 22738 | vector_holder_ptr vec_node; 22739 | #ifndef exprtk_disable_string_capabilities 22740 | stringvar_node_ptr str_node; 22741 | #endif 22742 | }; 22743 | 22744 | class scope_element_manager 22745 | { 22746 | public: 22747 | 22748 | typedef expression_node_t* expression_node_ptr; 22749 | typedef variable_node_t* variable_node_ptr; 22750 | typedef parser<T> parser_t; 22751 | 22752 | explicit scope_element_manager(parser<T>& p) 22753 | : parser_(p) 22754 | , input_param_cnt_(0) 22755 | , total_local_symb_size_bytes_(0) 22756 | {} 22757 | 22758 | inline std::size_t size() const 22759 | { 22760 | return element_.size(); 22761 | } 22762 | 22763 | inline bool empty() const 22764 | { 22765 | return element_.empty(); 22766 | } 22767 | 22768 | inline scope_element& get_element(const std::size_t& index) 22769 | { 22770 | if (index < element_.size()) 22771 | return element_[index]; 22772 | else 22773 | return null_element_; 22774 | } 22775 | 22776 | inline scope_element& get_element(const std::string& var_name, 22777 | const std::size_t index = std::numeric_limits<std::size_t>::max()) 22778 | { 22779 | const std::size_t current_depth = parser_.state_.scope_depth; 22780 | 22781 | for (std::size_t i = 0; i < element_.size(); ++i) 22782 | { 22783 | scope_element& se = element_[i]; 22784 | 22785 | if (se.depth > current_depth) 22786 | continue; 22787 | else if ( 22788 | details::imatch(se.name, var_name) && 22789 | (se.index == index) 22790 | ) 22791 | return se; 22792 | } 22793 | 22794 | return null_element_; 22795 | } 22796 | 22797 | inline scope_element& get_active_element(const std::string& var_name, 22798 | const std::size_t index = std::numeric_limits<std::size_t>::max()) 22799 | { 22800 | const std::size_t current_depth = parser_.state_.scope_depth; 22801 | 22802 | for (std::size_t i = 0; i < element_.size(); ++i) 22803 | { 22804 | scope_element& se = element_[i]; 22805 | 22806 | if (se.depth > current_depth) 22807 | continue; 22808 | else if ( 22809 | details::imatch(se.name, var_name) && 22810 | (se.index == index) && 22811 | (se.active) 22812 | ) 22813 | return se; 22814 | } 22815 | 22816 | return null_element_; 22817 | } 22818 | 22819 | inline bool add_element(const scope_element& se) 22820 | { 22821 | for (std::size_t i = 0; i < element_.size(); ++i) 22822 | { 22823 | scope_element& cse = element_[i]; 22824 | 22825 | if ( 22826 | details::imatch(cse.name, se.name) && 22827 | (cse.depth <= se.depth) && 22828 | (cse.index == se.index) && 22829 | (cse.size == se.size ) && 22830 | (cse.type == se.type ) && 22831 | (cse.active) 22832 | ) 22833 | return false; 22834 | } 22835 | 22836 | switch (se.type) 22837 | { 22838 | case scope_element::e_variable : total_local_symb_size_bytes_ += sizeof(T); 22839 | break; 22840 | 22841 | case scope_element::e_literal : total_local_symb_size_bytes_ += sizeof(T); 22842 | break; 22843 | 22844 | case scope_element::e_vector : total_local_symb_size_bytes_ += sizeof(T) * se.size; 22845 | break; 22846 | 22847 | default : break; 22848 | } 22849 | 22850 | element_.push_back(se); 22851 | std::sort(element_.begin(),element_.end()); 22852 | 22853 | return true; 22854 | } 22855 | 22856 | inline void deactivate(const std::size_t& scope_depth) 22857 | { 22858 | exprtk_debug(("deactivate() - Scope depth: %d\n", 22859 | static_cast<int>(parser_.state_.scope_depth))); 22860 | 22861 | for (std::size_t i = 0; i < element_.size(); ++i) 22862 | { 22863 | scope_element& se = element_[i]; 22864 | 22865 | if (se.active && (se.depth >= scope_depth)) 22866 | { 22867 | exprtk_debug(("deactivate() - element[%02d] '%s'\n", 22868 | static_cast<int>(i), 22869 | se.name.c_str())); 22870 | 22871 | se.active = false; 22872 | } 22873 | } 22874 | } 22875 | 22876 | inline void free_element(scope_element& se) 22877 | { 22878 | exprtk_debug(("free_element() - se[%s]\n", se.name.c_str())); 22879 | 22880 | switch (se.type) 22881 | { 22882 | case scope_element::e_literal : delete reinterpret_cast<T*>(se.data); 22883 | delete se.var_node; 22884 | break; 22885 | 22886 | case scope_element::e_variable : delete reinterpret_cast<T*>(se.data); 22887 | delete se.var_node; 22888 | break; 22889 | 22890 | case scope_element::e_vector : delete[] reinterpret_cast<T*>(se.data); 22891 | delete se.vec_node; 22892 | break; 22893 | 22894 | case scope_element::e_vecelem : delete se.var_node; 22895 | break; 22896 | 22897 | #ifndef exprtk_disable_string_capabilities 22898 | case scope_element::e_string : delete reinterpret_cast<std::string*>(se.data); 22899 | delete se.str_node; 22900 | break; 22901 | #endif 22902 | 22903 | default : return; 22904 | } 22905 | 22906 | se.clear(); 22907 | } 22908 | 22909 | inline void cleanup() 22910 | { 22911 | for (std::size_t i = 0; i < element_.size(); ++i) 22912 | { 22913 | free_element(element_[i]); 22914 | } 22915 | 22916 | element_.clear(); 22917 | 22918 | input_param_cnt_ = 0; 22919 | total_local_symb_size_bytes_ = 0; 22920 | } 22921 | 22922 | inline std::size_t total_local_symb_size_bytes() const 22923 | { 22924 | return total_local_symb_size_bytes_; 22925 | } 22926 | 22927 | inline std::size_t next_ip_index() 22928 | { 22929 | return ++input_param_cnt_; 22930 | } 22931 | 22932 | inline expression_node_ptr get_variable(const T& v) 22933 | { 22934 | for (std::size_t i = 0; i < element_.size(); ++i) 22935 | { 22936 | scope_element& se = element_[i]; 22937 | 22938 | if ( 22939 | se.active && 22940 | se.var_node && 22941 | details::is_variable_node(se.var_node) 22942 | ) 22943 | { 22944 | variable_node_ptr vn = reinterpret_cast<variable_node_ptr>(se.var_node); 22945 | 22946 | if (&(vn->ref()) == (&v)) 22947 | { 22948 | return se.var_node; 22949 | } 22950 | } 22951 | } 22952 | 22953 | return expression_node_ptr(0); 22954 | } 22955 | 22956 | inline std::string get_vector_name(const T* data) 22957 | { 22958 | for (std::size_t i = 0; i < element_.size(); ++i) 22959 | { 22960 | scope_element& se = element_[i]; 22961 | 22962 | if ( 22963 | se.active && 22964 | se.vec_node && 22965 | (se.vec_node->data() == data) 22966 | ) 22967 | { 22968 | return se.name; 22969 | } 22970 | } 22971 | 22972 | return "neo-vector" 22973 | } 22974 | 22975 | private: 22976 | 22977 | scope_element_manager(const scope_element_manager&) exprtk_delete; 22978 | scope_element_manager& operator=(const scope_element_manager&) exprtk_delete; 22979 | 22980 | parser_t& parser_; 22981 | std::vector<scope_element> element_; 22982 | scope_element null_element_; 22983 | std::size_t input_param_cnt_; 22984 | std::size_t total_local_symb_size_bytes_; 22985 | }; 22986 | 22987 | class scope_handler 22988 | { 22989 | public: 22990 | 22991 | typedef parser<T> parser_t; 22992 | 22993 | explicit scope_handler(parser<T>& p) 22994 | : parser_(p) 22995 | { 22996 | parser_.state_.scope_depth++; 22997 | #ifdef exprtk_enable_debugging 22998 | const std::string depth(2 * parser_.state_.scope_depth,'-'); 22999 | exprtk_debug(("%s> Scope Depth: %02d\n", 23000 | depth.c_str(), 23001 | static_cast<int>(parser_.state_.scope_depth))); 23002 | #endif 23003 | } 23004 | 23005 | ~scope_handler() 23006 | { 23007 | parser_.sem_.deactivate(parser_.state_.scope_depth); 23008 | parser_.state_.scope_depth--; 23009 | #ifdef exprtk_enable_debugging 23010 | const std::string depth(2 * parser_.state_.scope_depth,'-'); 23011 | exprtk_debug(("<%s Scope Depth: %02d\n", 23012 | depth.c_str(), 23013 | static_cast<int>(parser_.state_.scope_depth))); 23014 | #endif 23015 | } 23016 | 23017 | private: 23018 | 23019 | scope_handler(const scope_handler&) exprtk_delete; 23020 | scope_handler& operator=(const scope_handler&) exprtk_delete; 23021 | 23022 | parser_t& parser_; 23023 | }; 23024 | 23025 | template <typename T_> 23026 | struct halfopen_range_policy 23027 | { 23028 | static inline bool is_within(const T_& v, const T_& begin, const T_& end) 23029 | { 23030 | assert(begin <= end); 23031 | return (begin <= v) && (v < end); 23032 | } 23033 | 23034 | static inline bool is_less(const T_& v, const T_& begin) 23035 | { 23036 | return (v < begin); 23037 | } 23038 | 23039 | static inline bool is_greater(const T_& v, const T_& end) 23040 | { 23041 | return (end <= v); 23042 | } 23043 | 23044 | static inline bool end_inclusive() 23045 | { 23046 | return false; 23047 | } 23048 | }; 23049 | 23050 | template <typename T_> 23051 | struct closed_range_policy 23052 | { 23053 | static inline bool is_within(const T_& v, const T_& begin, const T_& end) 23054 | { 23055 | assert(begin <= end); 23056 | return (begin <= v) && (v <= end); 23057 | } 23058 | 23059 | static inline bool is_less(const T_& v, const T_& begin) 23060 | { 23061 | return (v < begin); 23062 | } 23063 | 23064 | static inline bool is_greater(const T_& v, const T_& end) 23065 | { 23066 | return (end < v); 23067 | } 23068 | 23069 | static inline bool end_inclusive() 23070 | { 23071 | return true; 23072 | } 23073 | }; 23074 | 23075 | template <typename IntervalPointType, 23076 | typename RangePolicy = halfopen_range_policy<IntervalPointType> > 23077 | class interval_container_t 23078 | { 23079 | public: 23080 | 23081 | typedef IntervalPointType interval_point_t; 23082 | typedef std::pair<interval_point_t, interval_point_t> interval_t; 23083 | typedef std::map<interval_point_t, interval_t> interval_map_t; 23084 | typedef typename interval_map_t::const_iterator interval_map_citr_t; 23085 | 23086 | std::size_t size() const 23087 | { 23088 | return interval_map_.size(); 23089 | } 23090 | 23091 | void reset() 23092 | { 23093 | interval_map_.clear(); 23094 | } 23095 | 23096 | bool in_interval(const interval_point_t point, interval_t& interval) const 23097 | { 23098 | interval_map_citr_t itr = RangePolicy::end_inclusive() ? 23099 | interval_map_.lower_bound(point): 23100 | interval_map_.upper_bound(point); 23101 | 23102 | for (; itr != interval_map_.end(); ++itr) 23103 | { 23104 | const interval_point_t& begin = itr->second.first; 23105 | const interval_point_t& end = itr->second.second; 23106 | 23107 | if (RangePolicy::is_within(point, begin, end)) 23108 | { 23109 | interval = interval_t(begin,end); 23110 | return true; 23111 | } 23112 | else if (RangePolicy::is_greater(point, end)) 23113 | { 23114 | break; 23115 | } 23116 | } 23117 | 23118 | return false; 23119 | } 23120 | 23121 | bool in_interval(const interval_point_t point) const 23122 | { 23123 | interval_t interval; 23124 | return in_interval(point,interval); 23125 | } 23126 | 23127 | bool add_interval(const interval_point_t begin, const interval_point_t end) 23128 | { 23129 | if ((end <= begin) || in_interval(begin) || in_interval(end)) 23130 | { 23131 | return false; 23132 | } 23133 | 23134 | interval_map_[end] = std::make_pair(begin, end); 23135 | 23136 | return true; 23137 | } 23138 | 23139 | bool add_interval(const interval_t interval) 23140 | { 23141 | return add_interval(interval.first, interval.second); 23142 | } 23143 | 23144 | private: 23145 | 23146 | interval_map_t interval_map_; 23147 | }; 23148 | 23149 | class stack_limit_handler 23150 | { 23151 | public: 23152 | 23153 | typedef parser<T> parser_t; 23154 | 23155 | explicit stack_limit_handler(parser<T>& p) 23156 | : parser_(p) 23157 | , limit_exceeded_(false) 23158 | { 23159 | if (++parser_.state_.stack_depth > parser_.settings_.max_stack_depth_) 23160 | { 23161 | limit_exceeded_ = true; 23162 | parser_.set_error(make_error( 23163 | parser_error::e_parser, 23164 | "ERR000 - Current stack depth " + details::to_str(parser_.state_.stack_depth) + 23165 | " exceeds maximum allowed stack depth of " + details::to_str(parser_.settings_.max_stack_depth_), 23166 | exprtk_error_location)); 23167 | } 23168 | } 23169 | 23170 | ~stack_limit_handler() 23171 | { 23172 | assert(parser_.state_.stack_depth > 0); 23173 | parser_.state_.stack_depth--; 23174 | } 23175 | 23176 | bool operator!() 23177 | { 23178 | return limit_exceeded_; 23179 | } 23180 | 23181 | private: 23182 | 23183 | stack_limit_handler(const stack_limit_handler&) exprtk_delete; 23184 | stack_limit_handler& operator=(const stack_limit_handler&) exprtk_delete; 23185 | 23186 | parser_t& parser_; 23187 | bool limit_exceeded_; 23188 | }; 23189 | 23190 | struct symtab_store 23191 | { 23192 | symbol_table_list_t symtab_list_; 23193 | 23194 | typedef typename symbol_table_t::local_data_t local_data_t; 23195 | typedef typename symbol_table_t::variable_ptr variable_ptr; 23196 | typedef typename symbol_table_t::function_ptr function_ptr; 23197 | #ifndef exprtk_disable_string_capabilities 23198 | typedef typename symbol_table_t::stringvar_ptr stringvar_ptr; 23199 | #endif 23200 | typedef typename symbol_table_t::vector_holder_ptr vector_holder_ptr; 23201 | typedef typename symbol_table_t::vararg_function_ptr vararg_function_ptr; 23202 | typedef typename symbol_table_t::generic_function_ptr generic_function_ptr; 23203 | 23204 | struct variable_context 23205 | { 23206 | variable_context() 23207 | : symbol_table(0) 23208 | , variable(0) 23209 | {} 23210 | 23211 | const symbol_table_t* symbol_table; 23212 | variable_ptr variable; 23213 | }; 23214 | 23215 | struct vector_context 23216 | { 23217 | vector_context() 23218 | : symbol_table(0) 23219 | , vector_holder(0) 23220 | {} 23221 | 23222 | const symbol_table_t* symbol_table; 23223 | vector_holder_ptr vector_holder; 23224 | }; 23225 | 23226 | #ifndef exprtk_disable_string_capabilities 23227 | struct string_context 23228 | { 23229 | string_context() 23230 | : symbol_table(0) 23231 | , str_var(0) 23232 | {} 23233 | 23234 | const symbol_table_t* symbol_table; 23235 | stringvar_ptr str_var; 23236 | }; 23237 | #endif 23238 | 23239 | inline bool empty() const 23240 | { 23241 | return symtab_list_.empty(); 23242 | } 23243 | 23244 | inline void clear() 23245 | { 23246 | symtab_list_.clear(); 23247 | } 23248 | 23249 | inline bool valid() const 23250 | { 23251 | if (!empty()) 23252 | { 23253 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23254 | { 23255 | if (symtab_list_[i].valid()) 23256 | return true; 23257 | } 23258 | } 23259 | 23260 | return false; 23261 | } 23262 | 23263 | inline bool valid_symbol(const std::string& symbol) const 23264 | { 23265 | if (!symtab_list_.empty()) 23266 | return symtab_list_[0].valid_symbol(symbol); 23267 | else 23268 | return false; 23269 | } 23270 | 23271 | inline bool valid_function_name(const std::string& symbol) const 23272 | { 23273 | if (!symtab_list_.empty()) 23274 | return symtab_list_[0].valid_function(symbol); 23275 | else 23276 | return false; 23277 | } 23278 | 23279 | inline variable_context get_variable_context(const std::string& variable_name) const 23280 | { 23281 | variable_context result; 23282 | 23283 | if (valid_symbol(variable_name)) 23284 | { 23285 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23286 | { 23287 | if (!symtab_list_[i].valid()) 23288 | { 23289 | continue; 23290 | } 23291 | 23292 | result.variable = local_data(i) 23293 | .variable_store.get(variable_name); 23294 | if (result.variable) 23295 | { 23296 | result.symbol_table = &symtab_list_[i]; 23297 | break; 23298 | } 23299 | } 23300 | } 23301 | 23302 | return result; 23303 | } 23304 | 23305 | inline variable_ptr get_variable(const std::string& variable_name) const 23306 | { 23307 | if (!valid_symbol(variable_name)) 23308 | return reinterpret_cast<variable_ptr>(0); 23309 | 23310 | variable_ptr result = reinterpret_cast<variable_ptr>(0); 23311 | 23312 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23313 | { 23314 | if (!symtab_list_[i].valid()) 23315 | continue; 23316 | else 23317 | result = local_data(i) 23318 | .variable_store.get(variable_name); 23319 | 23320 | if (result) break; 23321 | } 23322 | 23323 | return result; 23324 | } 23325 | 23326 | inline variable_ptr get_variable(const T& var_ref) const 23327 | { 23328 | variable_ptr result = reinterpret_cast<variable_ptr>(0); 23329 | 23330 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23331 | { 23332 | if (!symtab_list_[i].valid()) 23333 | continue; 23334 | else 23335 | result = local_data(i).variable_store 23336 | .get_from_varptr(reinterpret_cast<const void*>(&var_ref)); 23337 | 23338 | if (result) break; 23339 | } 23340 | 23341 | return result; 23342 | } 23343 | 23344 | #ifndef exprtk_disable_string_capabilities 23345 | inline string_context get_string_context(const std::string& string_name) const 23346 | { 23347 | string_context result; 23348 | 23349 | if (!valid_symbol(string_name)) 23350 | return result; 23351 | 23352 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23353 | { 23354 | if (!symtab_list_[i].valid()) 23355 | { 23356 | continue; 23357 | } 23358 | 23359 | result.str_var = local_data(i).stringvar_store.get(string_name); 23360 | 23361 | if (result.str_var) 23362 | { 23363 | result.symbol_table = &symtab_list_[i]; 23364 | break; 23365 | } 23366 | } 23367 | 23368 | return result; 23369 | } 23370 | 23371 | inline stringvar_ptr get_stringvar(const std::string& string_name) const 23372 | { 23373 | if (!valid_symbol(string_name)) 23374 | return reinterpret_cast<stringvar_ptr>(0); 23375 | 23376 | stringvar_ptr result = reinterpret_cast<stringvar_ptr>(0); 23377 | 23378 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23379 | { 23380 | if (!symtab_list_[i].valid()) 23381 | continue; 23382 | else 23383 | result = local_data(i) 23384 | .stringvar_store.get(string_name); 23385 | 23386 | if (result) break; 23387 | } 23388 | 23389 | return result; 23390 | } 23391 | #endif 23392 | 23393 | inline function_ptr get_function(const std::string& function_name) const 23394 | { 23395 | if (!valid_function_name(function_name)) 23396 | return reinterpret_cast<function_ptr>(0); 23397 | 23398 | function_ptr result = reinterpret_cast<function_ptr>(0); 23399 | 23400 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23401 | { 23402 | if (!symtab_list_[i].valid()) 23403 | continue; 23404 | else 23405 | result = local_data(i) 23406 | .function_store.get(function_name); 23407 | 23408 | if (result) break; 23409 | } 23410 | 23411 | return result; 23412 | } 23413 | 23414 | inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name) const 23415 | { 23416 | if (!valid_function_name(vararg_function_name)) 23417 | return reinterpret_cast<vararg_function_ptr>(0); 23418 | 23419 | vararg_function_ptr result = reinterpret_cast<vararg_function_ptr>(0); 23420 | 23421 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23422 | { 23423 | if (!symtab_list_[i].valid()) 23424 | continue; 23425 | else 23426 | result = local_data(i) 23427 | .vararg_function_store.get(vararg_function_name); 23428 | 23429 | if (result) break; 23430 | } 23431 | 23432 | return result; 23433 | } 23434 | 23435 | inline generic_function_ptr get_generic_function(const std::string& function_name) const 23436 | { 23437 | if (!valid_function_name(function_name)) 23438 | return reinterpret_cast<generic_function_ptr>(0); 23439 | 23440 | generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0); 23441 | 23442 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23443 | { 23444 | if (!symtab_list_[i].valid()) 23445 | continue; 23446 | else 23447 | result = local_data(i) 23448 | .generic_function_store.get(function_name); 23449 | 23450 | if (result) break; 23451 | } 23452 | 23453 | return result; 23454 | } 23455 | 23456 | inline generic_function_ptr get_string_function(const std::string& function_name) const 23457 | { 23458 | if (!valid_function_name(function_name)) 23459 | return reinterpret_cast<generic_function_ptr>(0); 23460 | 23461 | generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0); 23462 | 23463 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23464 | { 23465 | if (!symtab_list_[i].valid()) 23466 | continue; 23467 | else 23468 | result = 23469 | local_data(i).string_function_store.get(function_name); 23470 | 23471 | if (result) break; 23472 | } 23473 | 23474 | return result; 23475 | } 23476 | 23477 | inline generic_function_ptr get_overload_function(const std::string& function_name) const 23478 | { 23479 | if (!valid_function_name(function_name)) 23480 | return reinterpret_cast<generic_function_ptr>(0); 23481 | 23482 | generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0); 23483 | 23484 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23485 | { 23486 | if (!symtab_list_[i].valid()) 23487 | continue; 23488 | else 23489 | result = 23490 | local_data(i).overload_function_store.get(function_name); 23491 | 23492 | if (result) break; 23493 | } 23494 | 23495 | return result; 23496 | } 23497 | 23498 | inline vector_context get_vector_context(const std::string& vector_name) const 23499 | { 23500 | vector_context result; 23501 | if (!valid_symbol(vector_name)) 23502 | return result; 23503 | 23504 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23505 | { 23506 | if (!symtab_list_[i].valid()) 23507 | { 23508 | continue; 23509 | } 23510 | 23511 | result.vector_holder = local_data(i).vector_store.get(vector_name); 23512 | 23513 | if (result.vector_holder) 23514 | { 23515 | result.symbol_table = &symtab_list_[i]; 23516 | break; 23517 | } 23518 | } 23519 | 23520 | return result; 23521 | } 23522 | 23523 | inline vector_holder_ptr get_vector(const std::string& vector_name) const 23524 | { 23525 | if (!valid_symbol(vector_name)) 23526 | return reinterpret_cast<vector_holder_ptr>(0); 23527 | 23528 | vector_holder_ptr result = reinterpret_cast<vector_holder_ptr>(0); 23529 | 23530 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23531 | { 23532 | if (!symtab_list_[i].valid()) 23533 | { 23534 | continue; 23535 | } 23536 | 23537 | result = local_data(i).vector_store.get(vector_name); 23538 | 23539 | if (result) 23540 | { 23541 | break; 23542 | } 23543 | } 23544 | 23545 | return result; 23546 | } 23547 | 23548 | inline bool is_constant_node(const std::string& symbol_name) const 23549 | { 23550 | if (!valid_symbol(symbol_name)) 23551 | return false; 23552 | 23553 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23554 | { 23555 | if (!symtab_list_[i].valid()) 23556 | { 23557 | continue; 23558 | } 23559 | 23560 | if (local_data(i).variable_store.is_constant(symbol_name)) 23561 | { 23562 | return true; 23563 | } 23564 | } 23565 | 23566 | return false; 23567 | } 23568 | 23569 | #ifndef exprtk_disable_string_capabilities 23570 | inline bool is_constant_string(const std::string& symbol_name) const 23571 | { 23572 | if (!valid_symbol(symbol_name)) 23573 | return false; 23574 | 23575 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23576 | { 23577 | if (!symtab_list_[i].valid()) 23578 | continue; 23579 | else if (!local_data(i).stringvar_store.symbol_exists(symbol_name)) 23580 | continue; 23581 | else if (local_data(i).stringvar_store.is_constant(symbol_name)) 23582 | return true; 23583 | } 23584 | 23585 | return false; 23586 | } 23587 | #endif 23588 | 23589 | inline bool symbol_exists(const std::string& symbol) const 23590 | { 23591 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23592 | { 23593 | if (!symtab_list_[i].valid()) 23594 | { 23595 | continue; 23596 | } 23597 | 23598 | if (symtab_list_[i].symbol_exists(symbol)) 23599 | { 23600 | return true; 23601 | } 23602 | } 23603 | 23604 | return false; 23605 | } 23606 | 23607 | inline bool is_variable(const std::string& variable_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 | symtab_list_[i].local_data().variable_store 23615 | .symbol_exists(variable_name) 23616 | ) 23617 | return true; 23618 | } 23619 | 23620 | return false; 23621 | } 23622 | 23623 | #ifndef exprtk_disable_string_capabilities 23624 | inline bool is_stringvar(const std::string& stringvar_name) const 23625 | { 23626 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23627 | { 23628 | if (!symtab_list_[i].valid()) 23629 | continue; 23630 | else if ( 23631 | symtab_list_[i].local_data().stringvar_store 23632 | .symbol_exists(stringvar_name) 23633 | ) 23634 | return true; 23635 | } 23636 | 23637 | return false; 23638 | } 23639 | 23640 | inline bool is_conststr_stringvar(const std::string& symbol_name) const 23641 | { 23642 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23643 | { 23644 | if (!symtab_list_[i].valid()) 23645 | continue; 23646 | else if ( 23647 | symtab_list_[i].local_data().stringvar_store 23648 | .symbol_exists(symbol_name) 23649 | ) 23650 | { 23651 | return ( 23652 | local_data(i).stringvar_store.symbol_exists(symbol_name) || 23653 | local_data(i).stringvar_store.is_constant (symbol_name) 23654 | ); 23655 | 23656 | } 23657 | } 23658 | 23659 | return false; 23660 | } 23661 | #endif 23662 | 23663 | inline bool is_function(const std::string& function_name) const 23664 | { 23665 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23666 | { 23667 | if (!symtab_list_[i].valid()) 23668 | continue; 23669 | else if ( 23670 | local_data(i).vararg_function_store 23671 | .symbol_exists(function_name) 23672 | ) 23673 | return true; 23674 | } 23675 | 23676 | return false; 23677 | } 23678 | 23679 | inline bool is_vararg_function(const std::string& vararg_function_name) const 23680 | { 23681 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23682 | { 23683 | if (!symtab_list_[i].valid()) 23684 | continue; 23685 | else if ( 23686 | local_data(i).vararg_function_store 23687 | .symbol_exists(vararg_function_name) 23688 | ) 23689 | return true; 23690 | } 23691 | 23692 | return false; 23693 | } 23694 | 23695 | inline bool is_vector(const std::string& vector_name) const 23696 | { 23697 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23698 | { 23699 | if (!symtab_list_[i].valid()) 23700 | continue; 23701 | else if ( 23702 | local_data(i).vector_store 23703 | .symbol_exists(vector_name) 23704 | ) 23705 | return true; 23706 | } 23707 | 23708 | return false; 23709 | } 23710 | 23711 | inline std::string get_variable_name(const expression_node_ptr& ptr) const 23712 | { 23713 | return local_data().variable_store.entity_name(ptr); 23714 | } 23715 | 23716 | inline std::string get_vector_name(const vector_holder_ptr& ptr) const 23717 | { 23718 | return local_data().vector_store.entity_name(ptr); 23719 | } 23720 | 23721 | #ifndef exprtk_disable_string_capabilities 23722 | inline std::string get_stringvar_name(const expression_node_ptr& ptr) const 23723 | { 23724 | return local_data().stringvar_store.entity_name(ptr); 23725 | } 23726 | 23727 | inline std::string get_conststr_stringvar_name(const expression_node_ptr& ptr) const 23728 | { 23729 | return local_data().stringvar_store.entity_name(ptr); 23730 | } 23731 | #endif 23732 | 23733 | inline local_data_t& local_data(const std::size_t& index = 0) 23734 | { 23735 | return symtab_list_[index].local_data(); 23736 | } 23737 | 23738 | inline const local_data_t& local_data(const std::size_t& index = 0) const 23739 | { 23740 | return symtab_list_[index].local_data(); 23741 | } 23742 | 23743 | inline symbol_table_t& get_symbol_table(const std::size_t& index = 0) 23744 | { 23745 | return symtab_list_[index]; 23746 | } 23747 | }; 23748 | 23749 | struct parser_state 23750 | { 23751 | parser_state() 23752 | : type_check_enabled(true) 23753 | { 23754 | reset(); 23755 | } 23756 | 23757 | void reset() 23758 | { 23759 | parsing_return_stmt = false; 23760 | parsing_break_stmt = false; 23761 | parsing_assert_stmt = false; 23762 | return_stmt_present = false; 23763 | side_effect_present = false; 23764 | scope_depth = 0; 23765 | stack_depth = 0; 23766 | parsing_loop_stmt_count = 0; 23767 | } 23768 | 23769 | #ifndef exprtk_enable_debugging 23770 | void activate_side_effect(const std::string&) 23771 | #else 23772 | void activate_side_effect(const std::string& source) 23773 | #endif 23774 | { 23775 | if (!side_effect_present) 23776 | { 23777 | side_effect_present = true; 23778 | 23779 | exprtk_debug(("activate_side_effect() - caller: %s\n", source.c_str())); 23780 | } 23781 | } 23782 | 23783 | bool parsing_return_stmt; 23784 | bool parsing_break_stmt; 23785 | bool parsing_assert_stmt; 23786 | bool return_stmt_present; 23787 | bool side_effect_present; 23788 | bool type_check_enabled; 23789 | std::size_t scope_depth; 23790 | std::size_t stack_depth; 23791 | std::size_t parsing_loop_stmt_count; 23792 | }; 23793 | 23794 | public: 23795 | 23796 | struct unknown_symbol_resolver 23797 | { 23798 | 23799 | enum usr_symbol_type 23800 | { 23801 | e_usr_unknown_type = 0, 23802 | e_usr_variable_type = 1, 23803 | e_usr_constant_type = 2 23804 | }; 23805 | 23806 | enum usr_mode 23807 | { 23808 | e_usrmode_default = 0, 23809 | e_usrmode_extended = 1 23810 | }; 23811 | 23812 | usr_mode mode; 23813 | 23814 | explicit unknown_symbol_resolver(const usr_mode m = e_usrmode_default) 23815 | : mode(m) 23816 | {} 23817 | 23818 | virtual ~unknown_symbol_resolver() 23819 | {} 23820 | 23821 | virtual bool process(const std::string& /*unknown_symbol*/, 23822 | usr_symbol_type& st, 23823 | T& default_value, 23824 | std::string& error_message) 23825 | { 23826 | if (e_usrmode_default != mode) 23827 | return false; 23828 | 23829 | st = e_usr_variable_type; 23830 | default_value = T(0); 23831 | error_message.clear(); 23832 | 23833 | return true; 23834 | } 23835 | 23836 | virtual bool process(const std::string& /* unknown_symbol */, 23837 | symbol_table_t& /* symbol_table */, 23838 | std::string& /* error_message */) 23839 | { 23840 | return false; 23841 | } 23842 | }; 23843 | 23844 | enum collect_type 23845 | { 23846 | e_ct_none = 0, 23847 | e_ct_variables = 1, 23848 | e_ct_functions = 2, 23849 | e_ct_assignments = 4 23850 | }; 23851 | 23852 | enum symbol_type 23853 | { 23854 | e_st_unknown = 0, 23855 | e_st_variable = 1, 23856 | e_st_vector = 2, 23857 | e_st_vecelem = 3, 23858 | e_st_string = 4, 23859 | e_st_function = 5, 23860 | e_st_local_variable = 6, 23861 | e_st_local_vector = 7, 23862 | e_st_local_string = 8 23863 | }; 23864 | 23865 | class dependent_entity_collector 23866 | { 23867 | public: 23868 | 23869 | typedef std::pair<std::string,symbol_type> symbol_t; 23870 | typedef std::vector<symbol_t> symbol_list_t; 23871 | 23872 | explicit dependent_entity_collector(const std::size_t options = e_ct_none) 23873 | : options_(options) 23874 | , collect_variables_ ((options_ & e_ct_variables ) == e_ct_variables ) 23875 | , collect_functions_ ((options_ & e_ct_functions ) == e_ct_functions ) 23876 | , collect_assignments_((options_ & e_ct_assignments) == e_ct_assignments) 23877 | , return_present_ (false) 23878 | , final_stmt_return_(false) 23879 | {} 23880 | 23881 | template <typename Allocator, 23882 | template <typename, typename> class Sequence> 23883 | inline std::size_t symbols(Sequence<symbol_t,Allocator>& symbols_list) 23884 | { 23885 | if (!collect_variables_ && !collect_functions_) 23886 | return 0; 23887 | else if (symbol_name_list_.empty()) 23888 | return 0; 23889 | 23890 | for (std::size_t i = 0; i < symbol_name_list_.size(); ++i) 23891 | { 23892 | details::case_normalise(symbol_name_list_[i].first); 23893 | } 23894 | 23895 | std::sort(symbol_name_list_.begin(), symbol_name_list_.end()); 23896 | 23897 | std::unique_copy 23898 | ( 23899 | symbol_name_list_.begin(), 23900 | symbol_name_list_.end (), 23901 | std::back_inserter(symbols_list) 23902 | ); 23903 | 23904 | return symbols_list.size(); 23905 | } 23906 | 23907 | template <typename Allocator, 23908 | template <typename, typename> class Sequence> 23909 | inline std::size_t assignment_symbols(Sequence<symbol_t,Allocator>& assignment_list) 23910 | { 23911 | if (!collect_assignments_) 23912 | return 0; 23913 | else if (assignment_name_list_.empty()) 23914 | return 0; 23915 | 23916 | for (std::size_t i = 0; i < assignment_name_list_.size(); ++i) 23917 | { 23918 | details::case_normalise(assignment_name_list_[i].first); 23919 | } 23920 | 23921 | std::sort(assignment_name_list_.begin(),assignment_name_list_.end()); 23922 | 23923 | std::unique_copy 23924 | ( 23925 | assignment_name_list_.begin(), 23926 | assignment_name_list_.end (), 23927 | std::back_inserter(assignment_list) 23928 | ); 23929 | 23930 | return assignment_list.size(); 23931 | } 23932 | 23933 | void clear() 23934 | { 23935 | symbol_name_list_ .clear(); 23936 | assignment_name_list_.clear(); 23937 | retparam_list_ .clear(); 23938 | return_present_ = false; 23939 | final_stmt_return_ = false; 23940 | } 23941 | 23942 | bool& collect_variables() 23943 | { 23944 | return collect_variables_; 23945 | } 23946 | 23947 | bool& collect_functions() 23948 | { 23949 | return collect_functions_; 23950 | } 23951 | 23952 | bool& collect_assignments() 23953 | { 23954 | return collect_assignments_; 23955 | } 23956 | 23957 | bool return_present() const 23958 | { 23959 | return return_present_; 23960 | } 23961 | 23962 | bool final_stmt_return() const 23963 | { 23964 | return final_stmt_return_; 23965 | } 23966 | 23967 | typedef std::vector<std::string> retparam_list_t; 23968 | 23969 | retparam_list_t return_param_type_list() const 23970 | { 23971 | return retparam_list_; 23972 | } 23973 | 23974 | private: 23975 | 23976 | inline void add_symbol(const std::string& symbol, const symbol_type st) 23977 | { 23978 | switch (st) 23979 | { 23980 | case e_st_variable : 23981 | case e_st_vector : 23982 | case e_st_string : 23983 | case e_st_local_variable : 23984 | case e_st_local_vector : 23985 | case e_st_local_string : if (collect_variables_) 23986 | symbol_name_list_ 23987 | .push_back(std::make_pair(symbol, st)); 23988 | break; 23989 | 23990 | case e_st_function : if (collect_functions_) 23991 | symbol_name_list_ 23992 | .push_back(std::make_pair(symbol, st)); 23993 | break; 23994 | 23995 | default : return; 23996 | } 23997 | } 23998 | 23999 | inline void add_assignment(const std::string& symbol, const symbol_type st) 24000 | { 24001 | switch (st) 24002 | { 24003 | case e_st_variable : 24004 | case e_st_vector : 24005 | case e_st_string : if (collect_assignments_) 24006 | assignment_name_list_ 24007 | .push_back(std::make_pair(symbol, st)); 24008 | break; 24009 | 24010 | default : return; 24011 | } 24012 | } 24013 | 24014 | std::size_t options_; 24015 | bool collect_variables_; 24016 | bool collect_functions_; 24017 | bool collect_assignments_; 24018 | bool return_present_; 24019 | bool final_stmt_return_; 24020 | symbol_list_t symbol_name_list_; 24021 | symbol_list_t assignment_name_list_; 24022 | retparam_list_t retparam_list_; 24023 | 24024 | friend class parser<T>; 24025 | }; 24026 | 24027 | class settings_store 24028 | { 24029 | private: 24030 | 24031 | typedef std::set<std::string,details::ilesscompare> disabled_entity_set_t; 24032 | typedef disabled_entity_set_t::iterator des_itr_t; 24033 | 24034 | public: 24035 | 24036 | enum settings_compilation_options 24037 | { 24038 | e_unknown = 0, 24039 | e_replacer = 1, 24040 | e_joiner = 2, 24041 | e_numeric_check = 4, 24042 | e_bracket_check = 8, 24043 | e_sequence_check = 16, 24044 | e_commutative_check = 32, 24045 | e_strength_reduction = 64, 24046 | e_disable_vardef = 128, 24047 | e_collect_vars = 256, 24048 | e_collect_funcs = 512, 24049 | e_collect_assings = 1024, 24050 | e_disable_usr_on_rsrvd = 2048, 24051 | e_disable_zero_return = 4096 24052 | }; 24053 | 24054 | enum settings_base_funcs 24055 | { 24056 | e_bf_unknown = 0, 24057 | e_bf_abs , e_bf_acos , e_bf_acosh , e_bf_asin , 24058 | e_bf_asinh , e_bf_atan , e_bf_atan2 , e_bf_atanh , 24059 | e_bf_avg , e_bf_ceil , e_bf_clamp , e_bf_cos , 24060 | e_bf_cosh , e_bf_cot , e_bf_csc , e_bf_equal , 24061 | e_bf_erf , e_bf_erfc , e_bf_exp , e_bf_expm1 , 24062 | e_bf_floor , e_bf_frac , e_bf_hypot , e_bf_iclamp , 24063 | e_bf_like , e_bf_log , e_bf_log10 , e_bf_log1p , 24064 | e_bf_log2 , e_bf_logn , e_bf_mand , e_bf_max , 24065 | e_bf_min , e_bf_mod , e_bf_mor , e_bf_mul , 24066 | e_bf_ncdf , e_bf_pow , e_bf_root , e_bf_round , 24067 | e_bf_roundn , e_bf_sec , e_bf_sgn , e_bf_sin , 24068 | e_bf_sinc , e_bf_sinh , e_bf_sqrt , e_bf_sum , 24069 | e_bf_swap , e_bf_tan , e_bf_tanh , e_bf_trunc , 24070 | e_bf_not_equal , e_bf_inrange , e_bf_deg2grad , e_bf_deg2rad , 24071 | e_bf_rad2deg , e_bf_grad2deg 24072 | }; 24073 | 24074 | enum settings_control_structs 24075 | { 24076 | e_ctrl_unknown = 0, 24077 | e_ctrl_ifelse, 24078 | e_ctrl_switch, 24079 | e_ctrl_for_loop, 24080 | e_ctrl_while_loop, 24081 | e_ctrl_repeat_loop, 24082 | e_ctrl_return 24083 | }; 24084 | 24085 | enum settings_logic_opr 24086 | { 24087 | e_logic_unknown = 0, 24088 | e_logic_and, e_logic_nand , e_logic_nor , 24089 | e_logic_not, e_logic_or , e_logic_xnor, 24090 | e_logic_xor, e_logic_scand, e_logic_scor 24091 | }; 24092 | 24093 | enum settings_arithmetic_opr 24094 | { 24095 | e_arith_unknown = 0, 24096 | e_arith_add, e_arith_sub, e_arith_mul, 24097 | e_arith_div, e_arith_mod, e_arith_pow 24098 | }; 24099 | 24100 | enum settings_assignment_opr 24101 | { 24102 | e_assign_unknown = 0, 24103 | e_assign_assign, e_assign_addass, e_assign_subass, 24104 | e_assign_mulass, e_assign_divass, e_assign_modass 24105 | }; 24106 | 24107 | enum settings_inequality_opr 24108 | { 24109 | e_ineq_unknown = 0, 24110 | e_ineq_lt , e_ineq_lte, e_ineq_eq , 24111 | e_ineq_equal, e_ineq_ne , e_ineq_nequal, 24112 | e_ineq_gte , e_ineq_gt 24113 | }; 24114 | 24115 | static const std::size_t default_compile_all_opts = 24116 | e_replacer + 24117 | e_joiner + 24118 | e_numeric_check + 24119 | e_bracket_check + 24120 | e_sequence_check + 24121 | e_commutative_check + 24122 | e_strength_reduction; 24123 | 24124 | settings_store(const std::size_t compile_options = default_compile_all_opts) 24125 | : max_stack_depth_(400) 24126 | , max_node_depth_(10000) 24127 | , max_total_local_symbol_size_bytes_(2000000000) 24128 | , max_local_vector_size_(max_total_local_symbol_size_bytes_ / sizeof(T)) 24129 | { 24130 | load_compile_options(compile_options); 24131 | } 24132 | 24133 | settings_store& enable_all_base_functions() 24134 | { 24135 | disabled_func_set_.clear(); 24136 | return (*this); 24137 | } 24138 | 24139 | settings_store& enable_all_control_structures() 24140 | { 24141 | disabled_ctrl_set_.clear(); 24142 | return (*this); 24143 | } 24144 | 24145 | settings_store& enable_all_logic_ops() 24146 | { 24147 | disabled_logic_set_.clear(); 24148 | return (*this); 24149 | } 24150 | 24151 | settings_store& enable_all_arithmetic_ops() 24152 | { 24153 | disabled_arithmetic_set_.clear(); 24154 | return (*this); 24155 | } 24156 | 24157 | settings_store& enable_all_assignment_ops() 24158 | { 24159 | disabled_assignment_set_.clear(); 24160 | return (*this); 24161 | } 24162 | 24163 | settings_store& enable_all_inequality_ops() 24164 | { 24165 | disabled_inequality_set_.clear(); 24166 | return (*this); 24167 | } 24168 | 24169 | settings_store& enable_local_vardef() 24170 | { 24171 | disable_vardef_ = false; 24172 | return (*this); 24173 | } 24174 | 24175 | settings_store& enable_commutative_check() 24176 | { 24177 | enable_commutative_check_ = true; 24178 | return (*this); 24179 | } 24180 | 24181 | settings_store& enable_strength_reduction() 24182 | { 24183 | enable_strength_reduction_ = true; 24184 | return (*this); 24185 | } 24186 | 24187 | settings_store& disable_all_base_functions() 24188 | { 24189 | std::copy(details::base_function_list, 24190 | details::base_function_list + details::base_function_list_size, 24191 | std::insert_iterator<disabled_entity_set_t> 24192 | (disabled_func_set_, disabled_func_set_.begin())); 24193 | return (*this); 24194 | } 24195 | 24196 | settings_store& disable_all_control_structures() 24197 | { 24198 | std::copy(details::cntrl_struct_list, 24199 | details::cntrl_struct_list + details::cntrl_struct_list_size, 24200 | std::insert_iterator<disabled_entity_set_t> 24201 | (disabled_ctrl_set_, disabled_ctrl_set_.begin())); 24202 | return (*this); 24203 | } 24204 | 24205 | settings_store& disable_all_logic_ops() 24206 | { 24207 | std::copy(details::logic_ops_list, 24208 | details::logic_ops_list + details::logic_ops_list_size, 24209 | std::insert_iterator<disabled_entity_set_t> 24210 | (disabled_logic_set_, disabled_logic_set_.begin())); 24211 | return (*this); 24212 | } 24213 | 24214 | settings_store& disable_all_arithmetic_ops() 24215 | { 24216 | std::copy(details::arithmetic_ops_list, 24217 | details::arithmetic_ops_list + details::arithmetic_ops_list_size, 24218 | std::insert_iterator<disabled_entity_set_t> 24219 | (disabled_arithmetic_set_, disabled_arithmetic_set_.begin())); 24220 | return (*this); 24221 | } 24222 | 24223 | settings_store& disable_all_assignment_ops() 24224 | { 24225 | std::copy(details::assignment_ops_list, 24226 | details::assignment_ops_list + details::assignment_ops_list_size, 24227 | std::insert_iterator<disabled_entity_set_t> 24228 | (disabled_assignment_set_, disabled_assignment_set_.begin())); 24229 | return (*this); 24230 | } 24231 | 24232 | settings_store& disable_all_inequality_ops() 24233 | { 24234 | std::copy(details::inequality_ops_list, 24235 | details::inequality_ops_list + details::inequality_ops_list_size, 24236 | std::insert_iterator<disabled_entity_set_t> 24237 | (disabled_inequality_set_, disabled_inequality_set_.begin())); 24238 | return (*this); 24239 | } 24240 | 24241 | settings_store& disable_local_vardef() 24242 | { 24243 | disable_vardef_ = true; 24244 | return (*this); 24245 | } 24246 | 24247 | settings_store& disable_commutative_check() 24248 | { 24249 | enable_commutative_check_ = false; 24250 | return (*this); 24251 | } 24252 | 24253 | settings_store& disable_strength_reduction() 24254 | { 24255 | enable_strength_reduction_ = false; 24256 | return (*this); 24257 | } 24258 | 24259 | bool replacer_enabled () const { return enable_replacer_; } 24260 | bool commutative_check_enabled () const { return enable_commutative_check_; } 24261 | bool joiner_enabled () const { return enable_joiner_; } 24262 | bool numeric_check_enabled () const { return enable_numeric_check_; } 24263 | bool bracket_check_enabled () const { return enable_bracket_check_; } 24264 | bool sequence_check_enabled () const { return enable_sequence_check_; } 24265 | bool strength_reduction_enabled () const { return enable_strength_reduction_; } 24266 | bool collect_variables_enabled () const { return enable_collect_vars_; } 24267 | bool collect_functions_enabled () const { return enable_collect_funcs_; } 24268 | bool collect_assignments_enabled() const { return enable_collect_assings_; } 24269 | bool vardef_disabled () const { return disable_vardef_; } 24270 | bool rsrvd_sym_usr_disabled () const { return disable_rsrvd_sym_usr_; } 24271 | bool zero_return_disabled () const { return disable_zero_return_; } 24272 | 24273 | bool function_enabled(const std::string& function_name) const 24274 | { 24275 | if (disabled_func_set_.empty()) 24276 | return true; 24277 | else 24278 | return (disabled_func_set_.end() == disabled_func_set_.find(function_name)); 24279 | } 24280 | 24281 | bool control_struct_enabled(const std::string& control_struct) const 24282 | { 24283 | if (disabled_ctrl_set_.empty()) 24284 | return true; 24285 | else 24286 | return (disabled_ctrl_set_.end() == disabled_ctrl_set_.find(control_struct)); 24287 | } 24288 | 24289 | bool logic_enabled(const std::string& logic_operation) const 24290 | { 24291 | if (disabled_logic_set_.empty()) 24292 | return true; 24293 | else 24294 | return (disabled_logic_set_.end() == disabled_logic_set_.find(logic_operation)); 24295 | } 24296 | 24297 | bool arithmetic_enabled(const details::operator_type& arithmetic_operation) const 24298 | { 24299 | if (disabled_arithmetic_set_.empty()) 24300 | return true; 24301 | else 24302 | return disabled_arithmetic_set_.end() == disabled_arithmetic_set_ 24303 | .find(arith_opr_to_string(arithmetic_operation)); 24304 | } 24305 | 24306 | bool assignment_enabled(const details::operator_type& assignment) const 24307 | { 24308 | if (disabled_assignment_set_.empty()) 24309 | return true; 24310 | else 24311 | return disabled_assignment_set_.end() == disabled_assignment_set_ 24312 | .find(assign_opr_to_string(assignment)); 24313 | } 24314 | 24315 | bool inequality_enabled(const details::operator_type& inequality) const 24316 | { 24317 | if (disabled_inequality_set_.empty()) 24318 | return true; 24319 | else 24320 | return disabled_inequality_set_.end() == disabled_inequality_set_ 24321 | .find(inequality_opr_to_string(inequality)); 24322 | } 24323 | 24324 | bool function_disabled(const std::string& function_name) const 24325 | { 24326 | if (disabled_func_set_.empty()) 24327 | return false; 24328 | else 24329 | return (disabled_func_set_.end() != disabled_func_set_.find(function_name)); 24330 | } 24331 | 24332 | bool control_struct_disabled(const std::string& control_struct) const 24333 | { 24334 | if (disabled_ctrl_set_.empty()) 24335 | return false; 24336 | else 24337 | return (disabled_ctrl_set_.end() != disabled_ctrl_set_.find(control_struct)); 24338 | } 24339 | 24340 | bool logic_disabled(const std::string& logic_operation) const 24341 | { 24342 | if (disabled_logic_set_.empty()) 24343 | return false; 24344 | else 24345 | return (disabled_logic_set_.end() != disabled_logic_set_.find(logic_operation)); 24346 | } 24347 | 24348 | bool assignment_disabled(const details::operator_type assignment_operation) const 24349 | { 24350 | if (disabled_assignment_set_.empty()) 24351 | return false; 24352 | else 24353 | return disabled_assignment_set_.end() != disabled_assignment_set_ 24354 | .find(assign_opr_to_string(assignment_operation)); 24355 | } 24356 | 24357 | bool logic_disabled(const details::operator_type logic_operation) const 24358 | { 24359 | if (disabled_logic_set_.empty()) 24360 | return false; 24361 | else 24362 | return disabled_logic_set_.end() != disabled_logic_set_ 24363 | .find(logic_opr_to_string(logic_operation)); 24364 | } 24365 | 24366 | bool arithmetic_disabled(const details::operator_type arithmetic_operation) const 24367 | { 24368 | if (disabled_arithmetic_set_.empty()) 24369 | return false; 24370 | else 24371 | return disabled_arithmetic_set_.end() != disabled_arithmetic_set_ 24372 | .find(arith_opr_to_string(arithmetic_operation)); 24373 | } 24374 | 24375 | bool inequality_disabled(const details::operator_type& inequality) const 24376 | { 24377 | if (disabled_inequality_set_.empty()) 24378 | return false; 24379 | else 24380 | return disabled_inequality_set_.end() != disabled_inequality_set_ 24381 | .find(inequality_opr_to_string(inequality)); 24382 | } 24383 | 24384 | settings_store& disable_base_function(const settings_base_funcs bf) 24385 | { 24386 | if ( 24387 | (e_bf_unknown != bf) && 24388 | (static_cast<std::size_t>(bf) < (details::base_function_list_size + 1)) 24389 | ) 24390 | { 24391 | disabled_func_set_.insert(details::base_function_list[bf - 1]); 24392 | } 24393 | 24394 | return (*this); 24395 | } 24396 | 24397 | settings_store& disable_control_structure(const settings_control_structs ctrl_struct) 24398 | { 24399 | if ( 24400 | (e_ctrl_unknown != ctrl_struct) && 24401 | (static_cast<std::size_t>(ctrl_struct) < (details::cntrl_struct_list_size + 1)) 24402 | ) 24403 | { 24404 | disabled_ctrl_set_.insert(details::cntrl_struct_list[ctrl_struct - 1]); 24405 | } 24406 | 24407 | return (*this); 24408 | } 24409 | 24410 | settings_store& disable_logic_operation(const settings_logic_opr logic) 24411 | { 24412 | if ( 24413 | (e_logic_unknown != logic) && 24414 | (static_cast<std::size_t>(logic) < (details::logic_ops_list_size + 1)) 24415 | ) 24416 | { 24417 | disabled_logic_set_.insert(details::logic_ops_list[logic - 1]); 24418 | } 24419 | 24420 | return (*this); 24421 | } 24422 | 24423 | settings_store& disable_arithmetic_operation(const settings_arithmetic_opr arithmetic) 24424 | { 24425 | if ( 24426 | (e_arith_unknown != arithmetic) && 24427 | (static_cast<std::size_t>(arithmetic) < (details::arithmetic_ops_list_size + 1)) 24428 | ) 24429 | { 24430 | disabled_arithmetic_set_.insert(details::arithmetic_ops_list[arithmetic - 1]); 24431 | } 24432 | 24433 | return (*this); 24434 | } 24435 | 24436 | settings_store& disable_assignment_operation(const settings_assignment_opr assignment) 24437 | { 24438 | if ( 24439 | (e_assign_unknown != assignment) && 24440 | (static_cast<std::size_t>(assignment) < (details::assignment_ops_list_size + 1)) 24441 | ) 24442 | { 24443 | disabled_assignment_set_.insert(details::assignment_ops_list[assignment - 1]); 24444 | } 24445 | 24446 | return (*this); 24447 | } 24448 | 24449 | settings_store& disable_inequality_operation(const settings_inequality_opr inequality) 24450 | { 24451 | if ( 24452 | (e_ineq_unknown != inequality) && 24453 | (static_cast<std::size_t>(inequality) < (details::inequality_ops_list_size + 1)) 24454 | ) 24455 | { 24456 | disabled_inequality_set_.insert(details::inequality_ops_list[inequality - 1]); 24457 | } 24458 | 24459 | return (*this); 24460 | } 24461 | 24462 | settings_store& enable_base_function(const settings_base_funcs bf) 24463 | { 24464 | if ( 24465 | (e_bf_unknown != bf) && 24466 | (static_cast<std::size_t>(bf) < (details::base_function_list_size + 1)) 24467 | ) 24468 | { 24469 | const des_itr_t itr = disabled_func_set_.find(details::base_function_list[bf - 1]); 24470 | 24471 | if (disabled_func_set_.end() != itr) 24472 | { 24473 | disabled_func_set_.erase(itr); 24474 | } 24475 | } 24476 | 24477 | return (*this); 24478 | } 24479 | 24480 | settings_store& enable_control_structure(const settings_control_structs ctrl_struct) 24481 | { 24482 | if ( 24483 | (e_ctrl_unknown != ctrl_struct) && 24484 | (static_cast<std::size_t>(ctrl_struct) < (details::cntrl_struct_list_size + 1)) 24485 | ) 24486 | { 24487 | const des_itr_t itr = disabled_ctrl_set_.find(details::cntrl_struct_list[ctrl_struct - 1]); 24488 | 24489 | if (disabled_ctrl_set_.end() != itr) 24490 | { 24491 | disabled_ctrl_set_.erase(itr); 24492 | } 24493 | } 24494 | 24495 | return (*this); 24496 | } 24497 | 24498 | settings_store& enable_logic_operation(const settings_logic_opr logic) 24499 | { 24500 | if ( 24501 | (e_logic_unknown != logic) && 24502 | (static_cast<std::size_t>(logic) < (details::logic_ops_list_size + 1)) 24503 | ) 24504 | { 24505 | const des_itr_t itr = disabled_logic_set_.find(details::logic_ops_list[logic - 1]); 24506 | 24507 | if (disabled_logic_set_.end() != itr) 24508 | { 24509 | disabled_logic_set_.erase(itr); 24510 | } 24511 | } 24512 | 24513 | return (*this); 24514 | } 24515 | 24516 | settings_store& enable_arithmetic_operation(const settings_arithmetic_opr arithmetic) 24517 | { 24518 | if ( 24519 | (e_arith_unknown != arithmetic) && 24520 | (static_cast<std::size_t>(arithmetic) < (details::arithmetic_ops_list_size + 1)) 24521 | ) 24522 | { 24523 | const des_itr_t itr = disabled_arithmetic_set_.find(details::arithmetic_ops_list[arithmetic - 1]); 24524 | 24525 | if (disabled_arithmetic_set_.end() != itr) 24526 | { 24527 | disabled_arithmetic_set_.erase(itr); 24528 | } 24529 | } 24530 | 24531 | return (*this); 24532 | } 24533 | 24534 | settings_store& enable_assignment_operation(const settings_assignment_opr assignment) 24535 | { 24536 | if ( 24537 | (e_assign_unknown != assignment) && 24538 | (static_cast<std::size_t>(assignment) < (details::assignment_ops_list_size + 1)) 24539 | ) 24540 | { 24541 | const des_itr_t itr = disabled_assignment_set_.find(details::assignment_ops_list[assignment - 1]); 24542 | 24543 | if (disabled_assignment_set_.end() != itr) 24544 | { 24545 | disabled_assignment_set_.erase(itr); 24546 | } 24547 | } 24548 | 24549 | return (*this); 24550 | } 24551 | 24552 | settings_store& enable_inequality_operation(const settings_inequality_opr inequality) 24553 | { 24554 | if ( 24555 | (e_ineq_unknown != inequality) && 24556 | (static_cast<std::size_t>(inequality) < (details::inequality_ops_list_size + 1)) 24557 | ) 24558 | { 24559 | const des_itr_t itr = disabled_inequality_set_.find(details::inequality_ops_list[inequality - 1]); 24560 | 24561 | if (disabled_inequality_set_.end() != itr) 24562 | { 24563 | disabled_inequality_set_.erase(itr); 24564 | } 24565 | } 24566 | 24567 | return (*this); 24568 | } 24569 | 24570 | void set_max_stack_depth(const std::size_t max_stack_depth) 24571 | { 24572 | max_stack_depth_ = max_stack_depth; 24573 | } 24574 | 24575 | void set_max_node_depth(const std::size_t max_node_depth) 24576 | { 24577 | max_node_depth_ = max_node_depth; 24578 | } 24579 | 24580 | void set_max_local_vector_size(const std::size_t max_local_vector_size) 24581 | { 24582 | max_local_vector_size_ = max_local_vector_size; 24583 | } 24584 | 24585 | void set_max_total_local_symbol_size_bytes(const std::size_t max_total_lcl_symb_size) 24586 | { 24587 | max_total_local_symbol_size_bytes_ = max_total_lcl_symb_size; 24588 | } 24589 | 24590 | std::size_t max_stack_depth() const 24591 | { 24592 | return max_stack_depth_; 24593 | } 24594 | 24595 | std::size_t max_node_depth() const 24596 | { 24597 | return max_node_depth_; 24598 | } 24599 | 24600 | std::size_t max_local_vector_size() const 24601 | { 24602 | return max_local_vector_size_; 24603 | } 24604 | 24605 | std::size_t max_total_local_symbol_size_bytes() const 24606 | { 24607 | return max_total_local_symbol_size_bytes_; 24608 | } 24609 | 24610 | private: 24611 | 24612 | void load_compile_options(const std::size_t compile_options) 24613 | { 24614 | enable_replacer_ = (compile_options & e_replacer ) == e_replacer; 24615 | enable_joiner_ = (compile_options & e_joiner ) == e_joiner; 24616 | enable_numeric_check_ = (compile_options & e_numeric_check ) == e_numeric_check; 24617 | enable_bracket_check_ = (compile_options & e_bracket_check ) == e_bracket_check; 24618 | enable_sequence_check_ = (compile_options & e_sequence_check ) == e_sequence_check; 24619 | enable_commutative_check_ = (compile_options & e_commutative_check ) == e_commutative_check; 24620 | enable_strength_reduction_ = (compile_options & e_strength_reduction ) == e_strength_reduction; 24621 | enable_collect_vars_ = (compile_options & e_collect_vars ) == e_collect_vars; 24622 | enable_collect_funcs_ = (compile_options & e_collect_funcs ) == e_collect_funcs; 24623 | enable_collect_assings_ = (compile_options & e_collect_assings ) == e_collect_assings; 24624 | disable_vardef_ = (compile_options & e_disable_vardef ) == e_disable_vardef; 24625 | disable_rsrvd_sym_usr_ = (compile_options & e_disable_usr_on_rsrvd) == e_disable_usr_on_rsrvd; 24626 | disable_zero_return_ = (compile_options & e_disable_zero_return ) == e_disable_zero_return; 24627 | } 24628 | 24629 | std::string assign_opr_to_string(details::operator_type opr) const 24630 | { 24631 | switch (opr) 24632 | { 24633 | case details::e_assign : return ":=" 24634 | case details::e_addass : return "+=" 24635 | case details::e_subass : return "-=" 24636 | case details::e_mulass : return "*=" 24637 | case details::e_divass : return "/=" 24638 | case details::e_modass : return "%=" 24639 | default : return "" ; 24640 | } 24641 | } 24642 | 24643 | std::string arith_opr_to_string(details::operator_type opr) const 24644 | { 24645 | switch (opr) 24646 | { 24647 | case details::e_add : return "+" 24648 | case details::e_sub : return "-" 24649 | case details::e_mul : return "*" 24650 | case details::e_div : return "/" 24651 | case details::e_mod : return "%" 24652 | case details::e_pow : return "^" 24653 | default : return "" ; 24654 | } 24655 | } 24656 | 24657 | std::string inequality_opr_to_string(details::operator_type opr) const 24658 | { 24659 | switch (opr) 24660 | { 24661 | case details::e_lt : return "<" ; 24662 | case details::e_lte : return "<=" 24663 | case details::e_eq : return "==" 24664 | case details::e_equal : return "=" ; 24665 | case details::e_ne : return "!=" 24666 | case details::e_nequal: return "<>" 24667 | case details::e_gte : return ">=" 24668 | case details::e_gt : return ">" ; 24669 | default : return "" ; 24670 | } 24671 | } 24672 | 24673 | std::string logic_opr_to_string(details::operator_type opr) const 24674 | { 24675 | switch (opr) 24676 | { 24677 | case details::e_and : return "and" ; 24678 | case details::e_or : return "or" ; 24679 | case details::e_xor : return "xor" ; 24680 | case details::e_nand : return "nand" 24681 | case details::e_nor : return "nor" ; 24682 | case details::e_xnor : return "xnor" 24683 | case details::e_notl : return "not" ; 24684 | default : return "" ; 24685 | } 24686 | } 24687 | 24688 | bool enable_replacer_; 24689 | bool enable_joiner_; 24690 | bool enable_numeric_check_; 24691 | bool enable_bracket_check_; 24692 | bool enable_sequence_check_; 24693 | bool enable_commutative_check_; 24694 | bool enable_strength_reduction_; 24695 | bool enable_collect_vars_; 24696 | bool enable_collect_funcs_; 24697 | bool enable_collect_assings_; 24698 | bool disable_vardef_; 24699 | bool disable_rsrvd_sym_usr_; 24700 | bool disable_zero_return_; 24701 | 24702 | disabled_entity_set_t disabled_func_set_ ; 24703 | disabled_entity_set_t disabled_ctrl_set_ ; 24704 | disabled_entity_set_t disabled_logic_set_; 24705 | disabled_entity_set_t disabled_arithmetic_set_; 24706 | disabled_entity_set_t disabled_assignment_set_; 24707 | disabled_entity_set_t disabled_inequality_set_; 24708 | 24709 | std::size_t max_stack_depth_; 24710 | std::size_t max_node_depth_; 24711 | std::size_t max_total_local_symbol_size_bytes_; 24712 | std::size_t max_local_vector_size_; 24713 | 24714 | friend class parser<T>; 24715 | }; 24716 | 24717 | typedef settings_store settings_t; 24718 | 24719 | explicit parser(const settings_t& settings = settings_t()) 24720 | : settings_(settings) 24721 | , resolve_unknown_symbol_(false) 24722 | , results_context_(0) 24723 | , unknown_symbol_resolver_(reinterpret_cast<unknown_symbol_resolver*>(0)) 24724 | #ifdef _MSC_VER 24725 | #pragma warning(push) 24726 | #pragma warning (disable:4355) 24727 | #endif 24728 | , sem_(*this) 24729 | #ifdef _MSC_VER 24730 | #pragma warning(pop) 24731 | #endif 24732 | , operator_joiner_2_(2) 24733 | , operator_joiner_3_(3) 24734 | , loop_runtime_check_(0) 24735 | , vector_access_runtime_check_(0) 24736 | , compilation_check_ptr_(0) 24737 | , assert_check_(0) 24738 | { 24739 | init_precompilation(); 24740 | 24741 | load_operations_map (base_ops_map_ ); 24742 | load_unary_operations_map (unary_op_map_ ); 24743 | load_binary_operations_map (binary_op_map_ ); 24744 | load_inv_binary_operations_map(inv_binary_op_map_); 24745 | load_sf3_map (sf3_map_ ); 24746 | load_sf4_map (sf4_map_ ); 24747 | 24748 | expression_generator_.init_synthesize_map(); 24749 | expression_generator_.set_parser(*this); 24750 | expression_generator_.set_uom (unary_op_map_ ); 24751 | expression_generator_.set_bom (binary_op_map_ ); 24752 | expression_generator_.set_ibom(inv_binary_op_map_); 24753 | expression_generator_.set_sf3m(sf3_map_ ); 24754 | expression_generator_.set_sf4m(sf4_map_ ); 24755 | expression_generator_.set_strength_reduction_state(settings_.strength_reduction_enabled()); 24756 | } 24757 | 24758 | ~parser() 24759 | {} 24760 | 24761 | inline void init_precompilation() 24762 | { 24763 | dec_.collect_variables() = 24764 | settings_.collect_variables_enabled(); 24765 | 24766 | dec_.collect_functions() = 24767 | settings_.collect_functions_enabled(); 24768 | 24769 | dec_.collect_assignments() = 24770 | settings_.collect_assignments_enabled(); 24771 | 24772 | if (settings_.replacer_enabled()) 24773 | { 24774 | symbol_replacer_.clear(); 24775 | symbol_replacer_.add_replace("true" , "1", lexer::token::e_number); 24776 | symbol_replacer_.add_replace("false", "0", lexer::token::e_number); 24777 | helper_assembly_.token_modifier_list.clear(); 24778 | helper_assembly_.register_modifier(&symbol_replacer_); 24779 | } 24780 | 24781 | if (settings_.commutative_check_enabled()) 24782 | { 24783 | for (std::size_t i = 0; i < details::reserved_words_size; ++i) 24784 | { 24785 | commutative_inserter_.ignore_symbol(details::reserved_words[i]); 24786 | } 24787 | 24788 | helper_assembly_.token_inserter_list.clear(); 24789 | helper_assembly_.register_inserter(&commutative_inserter_); 24790 | } 24791 | 24792 | if (settings_.joiner_enabled()) 24793 | { 24794 | helper_assembly_.token_joiner_list.clear(); 24795 | helper_assembly_.register_joiner(&operator_joiner_2_); 24796 | helper_assembly_.register_joiner(&operator_joiner_3_); 24797 | } 24798 | 24799 | if ( 24800 | settings_.numeric_check_enabled () || 24801 | settings_.bracket_check_enabled () || 24802 | settings_.sequence_check_enabled() 24803 | ) 24804 | { 24805 | helper_assembly_.token_scanner_list.clear(); 24806 | 24807 | if (settings_.numeric_check_enabled()) 24808 | { 24809 | helper_assembly_.register_scanner(&numeric_checker_); 24810 | } 24811 | 24812 | if (settings_.bracket_check_enabled()) 24813 | { 24814 | helper_assembly_.register_scanner(&bracket_checker_); 24815 | } 24816 | 24817 | if (settings_.sequence_check_enabled()) 24818 | { 24819 | helper_assembly_.register_scanner(&sequence_validator_ ); 24820 | helper_assembly_.register_scanner(&sequence_validator_3tkns_); 24821 | } 24822 | } 24823 | } 24824 | 24825 | inline bool compile(const std::string& expression_string, expression<T>& expr) 24826 | { 24827 | state_ .reset(); 24828 | error_list_ .clear(); 24829 | brkcnt_list_ .clear(); 24830 | synthesis_error_ .clear(); 24831 | immutable_memory_map_.reset(); 24832 | immutable_symtok_map_.clear(); 24833 | current_state_stack_ .clear(); 24834 | assert_ids_ .clear(); 24835 | sem_ .cleanup(); 24836 | 24837 | return_cleanup(); 24838 | 24839 | if (!valid_settings()) 24840 | { 24841 | return false; 24842 | } 24843 | 24844 | expression_generator_.set_allocator(node_allocator_); 24845 | 24846 | if (expression_string.empty()) 24847 | { 24848 | set_error(make_error( 24849 | parser_error::e_syntax, 24850 | "ERR001 - Empty expression!", 24851 | exprtk_error_location)); 24852 | 24853 | return false; 24854 | } 24855 | 24856 | if (!init(expression_string)) 24857 | { 24858 | process_lexer_errors(); 24859 | return false; 24860 | } 24861 | 24862 | if (lexer().empty()) 24863 | { 24864 | set_error(make_error( 24865 | parser_error::e_syntax, 24866 | "ERR002 - Empty expression!", 24867 | exprtk_error_location)); 24868 | 24869 | return false; 24870 | } 24871 | 24872 | if (halt_compilation_check()) 24873 | { 24874 | exprtk_debug(("halt_compilation_check() - compile checkpoint 0\n")); 24875 | sem_.cleanup(); 24876 | return false; 24877 | } 24878 | 24879 | if (!run_assemblies()) 24880 | { 24881 | sem_.cleanup(); 24882 | return false; 24883 | } 24884 | 24885 | if (halt_compilation_check()) 24886 | { 24887 | exprtk_debug(("halt_compilation_check() - compile checkpoint 1\n")); 24888 | sem_.cleanup(); 24889 | return false; 24890 | } 24891 | 24892 | symtab_store_.symtab_list_ = expr.get_symbol_table_list(); 24893 | dec_.clear(); 24894 | 24895 | lexer().begin(); 24896 | 24897 | next_token(); 24898 | 24899 | expression_node_ptr e = parse_corpus(); 24900 | 24901 | if ((0 != e) && (token_t::e_eof == current_token().type)) 24902 | { 24903 | bool* retinvk_ptr = 0; 24904 | 24905 | if (state_.return_stmt_present) 24906 | { 24907 | dec_.return_present_ = true; 24908 | 24909 | e = expression_generator_ 24910 | .return_envelope(e, results_context_, retinvk_ptr); 24911 | } 24912 | 24913 | expr.set_expression(e); 24914 | expr.set_retinvk(retinvk_ptr); 24915 | 24916 | register_local_vars(expr); 24917 | register_return_results(expr); 24918 | 24919 | return !(!expr); 24920 | } 24921 | else 24922 | { 24923 | if (error_list_.empty()) 24924 | { 24925 | set_error(make_error( 24926 | parser_error::e_syntax, 24927 | current_token(), 24928 | "ERR003 - Invalid expression encountered", 24929 | exprtk_error_location)); 24930 | } 24931 | 24932 | if ((0 != e) && branch_deletable(e)) 24933 | { 24934 | destroy_node(e); 24935 | } 24936 | 24937 | dec_.clear (); 24938 | sem_.cleanup (); 24939 | return_cleanup(); 24940 | expr = expression_t(); 24941 | 24942 | return false; 24943 | } 24944 | } 24945 | 24946 | inline expression_t compile(const std::string& expression_string, symbol_table_t& symtab) 24947 | { 24948 | expression_t expression; 24949 | expression.register_symbol_table(symtab); 24950 | compile(expression_string,expression); 24951 | return expression; 24952 | } 24953 | 24954 | void process_lexer_errors() 24955 | { 24956 | for (std::size_t i = 0; i < lexer().size(); ++i) 24957 | { 24958 | if (lexer()[i].is_error()) 24959 | { 24960 | std::string diagnostic = "ERR004 - " 24961 | 24962 | switch (lexer()[i].type) 24963 | { 24964 | case lexer::token::e_error : diagnostic += "General token error" 24965 | break; 24966 | 24967 | case lexer::token::e_err_symbol : diagnostic += "Symbol error" 24968 | break; 24969 | 24970 | case lexer::token::e_err_number : diagnostic += "Invalid numeric token" 24971 | break; 24972 | 24973 | case lexer::token::e_err_string : diagnostic += "Invalid string token" 24974 | break; 24975 | 24976 | case lexer::token::e_err_sfunc : diagnostic += "Invalid special function token" 24977 | break; 24978 | 24979 | default : diagnostic += "Unknown compiler error" 24980 | } 24981 | 24982 | set_error(make_error( 24983 | parser_error::e_lexer, 24984 | lexer()[i], 24985 | diagnostic + ": " + lexer()[i].value, 24986 | exprtk_error_location)); 24987 | } 24988 | } 24989 | } 24990 | 24991 | inline bool run_assemblies() 24992 | { 24993 | if (settings_.commutative_check_enabled()) 24994 | { 24995 | helper_assembly_.run_inserters(lexer()); 24996 | } 24997 | 24998 | if (settings_.joiner_enabled()) 24999 | { 25000 | helper_assembly_.run_joiners(lexer()); 25001 | } 25002 | 25003 | if (settings_.replacer_enabled()) 25004 | { 25005 | helper_assembly_.run_modifiers(lexer()); 25006 | } 25007 | 25008 | if ( 25009 | settings_.numeric_check_enabled () || 25010 | settings_.bracket_check_enabled () || 25011 | settings_.sequence_check_enabled() 25012 | ) 25013 | { 25014 | if (!helper_assembly_.run_scanners(lexer())) 25015 | { 25016 | if (helper_assembly_.error_token_scanner) 25017 | { 25018 | lexer::helper::bracket_checker* bracket_checker_ptr = 0; 25019 | lexer::helper::numeric_checker<T>* numeric_checker_ptr = 0; 25020 | lexer::helper::sequence_validator* sequence_validator_ptr = 0; 25021 | lexer::helper::sequence_validator_3tokens* sequence_validator3_ptr = 0; 25022 | 25023 | if (0 != (bracket_checker_ptr = dynamic_cast<lexer::helper::bracket_checker*>(helper_assembly_.error_token_scanner))) 25024 | { 25025 | set_error(make_error( 25026 | parser_error::e_token, 25027 | bracket_checker_ptr->error_token(), 25028 | "ERR005 - Mismatched brackets: '" + bracket_checker_ptr->error_token().value + "'", 25029 | exprtk_error_location)); 25030 | } 25031 | else if (0 != (numeric_checker_ptr = dynamic_cast<lexer::helper::numeric_checker<T>*>(helper_assembly_.error_token_scanner))) 25032 | { 25033 | for (std::size_t i = 0; i < numeric_checker_ptr->error_count(); ++i) 25034 | { 25035 | lexer::token error_token = lexer()[numeric_checker_ptr->error_index(i)]; 25036 | 25037 | set_error(make_error( 25038 | parser_error::e_token, 25039 | error_token, 25040 | "ERR006 - Invalid numeric token: '" + error_token.value + "'", 25041 | exprtk_error_location)); 25042 | } 25043 | 25044 | if (numeric_checker_ptr->error_count()) 25045 | { 25046 | numeric_checker_ptr->clear_errors(); 25047 | } 25048 | } 25049 | else if (0 != (sequence_validator_ptr = dynamic_cast<lexer::helper::sequence_validator*>(helper_assembly_.error_token_scanner))) 25050 | { 25051 | for (std::size_t i = 0; i < sequence_validator_ptr->error_count(); ++i) 25052 | { 25053 | std::pair<lexer::token,lexer::token> error_token = sequence_validator_ptr->error(i); 25054 | 25055 | set_error(make_error( 25056 | parser_error::e_token, 25057 | error_token.first, 25058 | "ERR007 - Invalid token sequence: '" + 25059 | error_token.first.value + "' and '" + 25060 | error_token.second.value + "'", 25061 | exprtk_error_location)); 25062 | } 25063 | 25064 | if (sequence_validator_ptr->error_count()) 25065 | { 25066 | sequence_validator_ptr->clear_errors(); 25067 | } 25068 | } 25069 | else if (0 != (sequence_validator3_ptr = dynamic_cast<lexer::helper::sequence_validator_3tokens*>(helper_assembly_.error_token_scanner))) 25070 | { 25071 | for (std::size_t i = 0; i < sequence_validator3_ptr->error_count(); ++i) 25072 | { 25073 | std::pair<lexer::token,lexer::token> error_token = sequence_validator3_ptr->error(i); 25074 | 25075 | set_error(make_error( 25076 | parser_error::e_token, 25077 | error_token.first, 25078 | "ERR008 - Invalid token sequence: '" + 25079 | error_token.first.value + "' and '" + 25080 | error_token.second.value + "'", 25081 | exprtk_error_location)); 25082 | } 25083 | 25084 | if (sequence_validator3_ptr->error_count()) 25085 | { 25086 | sequence_validator3_ptr->clear_errors(); 25087 | } 25088 | } 25089 | } 25090 | 25091 | return false; 25092 | } 25093 | } 25094 | 25095 | return true; 25096 | } 25097 | 25098 | inline settings_store& settings() 25099 | { 25100 | return settings_; 25101 | } 25102 | 25103 | inline parser_error::type get_error(const std::size_t& index) const 25104 | { 25105 | if (index < error_list_.size()) 25106 | { 25107 | return error_list_[index]; 25108 | } 25109 | 25110 | throw std::invalid_argument("parser::get_error() - Invalid error index specified"); 25111 | } 25112 | 25113 | inline std::string error() const 25114 | { 25115 | if (!error_list_.empty()) 25116 | { 25117 | return error_list_[0].diagnostic; 25118 | } 25119 | else 25120 | return std::string("No Error"); 25121 | } 25122 | 25123 | inline std::size_t error_count() const 25124 | { 25125 | return error_list_.size(); 25126 | } 25127 | 25128 | inline dependent_entity_collector& dec() 25129 | { 25130 | return dec_; 25131 | } 25132 | 25133 | inline std::size_t total_local_symbol_size_bytes() const 25134 | { 25135 | return sem_.total_local_symb_size_bytes(); 25136 | } 25137 | 25138 | inline bool replace_symbol(const std::string& old_symbol, const std::string& new_symbol) 25139 | { 25140 | if (!settings_.replacer_enabled()) 25141 | return false; 25142 | else if (details::is_reserved_word(old_symbol)) 25143 | return false; 25144 | else 25145 | return symbol_replacer_.add_replace(old_symbol,new_symbol,lexer::token::e_symbol); 25146 | } 25147 | 25148 | inline bool remove_replace_symbol(const std::string& symbol) 25149 | { 25150 | if (!settings_.replacer_enabled()) 25151 | return false; 25152 | else if (details::is_reserved_word(symbol)) 25153 | return false; 25154 | else 25155 | return symbol_replacer_.remove(symbol); 25156 | } 25157 | 25158 | inline void enable_unknown_symbol_resolver(unknown_symbol_resolver* usr = reinterpret_cast<unknown_symbol_resolver*>(0)) 25159 | { 25160 | resolve_unknown_symbol_ = true; 25161 | 25162 | if (usr) 25163 | unknown_symbol_resolver_ = usr; 25164 | else 25165 | unknown_symbol_resolver_ = &default_usr_; 25166 | } 25167 | 25168 | inline void enable_unknown_symbol_resolver(unknown_symbol_resolver& usr) 25169 | { 25170 | enable_unknown_symbol_resolver(&usr); 25171 | } 25172 | 25173 | inline void disable_unknown_symbol_resolver() 25174 | { 25175 | resolve_unknown_symbol_ = false; 25176 | unknown_symbol_resolver_ = &default_usr_; 25177 | } 25178 | 25179 | inline void register_loop_runtime_check(loop_runtime_check& lrtchk) 25180 | { 25181 | loop_runtime_check_ = &lrtchk; 25182 | } 25183 | 25184 | inline void register_vector_access_runtime_check(vector_access_runtime_check& vartchk) 25185 | { 25186 | vector_access_runtime_check_ = &vartchk; 25187 | } 25188 | 25189 | inline void register_compilation_timeout_check(compilation_check& compchk) 25190 | { 25191 | compilation_check_ptr_ = &compchk; 25192 | } 25193 | 25194 | inline void register_assert_check(assert_check& assrt_chck) 25195 | { 25196 | assert_check_ = &assrt_chck; 25197 | } 25198 | 25199 | inline void clear_loop_runtime_check() 25200 | { 25201 | loop_runtime_check_ = loop_runtime_check_ptr(0); 25202 | } 25203 | 25204 | inline void clear_vector_access_runtime_check() 25205 | { 25206 | vector_access_runtime_check_ = vector_access_runtime_check_ptr(0); 25207 | } 25208 | 25209 | inline void clear_compilation_timeout_check() 25210 | { 25211 | compilation_check_ptr_ = compilation_check_ptr(0); 25212 | } 25213 | 25214 | inline void clear_assert_check() 25215 | { 25216 | assert_check_ = assert_check_ptr(0); 25217 | } 25218 | 25219 | private: 25220 | 25221 | inline bool valid_base_operation(const std::string& symbol) const 25222 | { 25223 | const std::size_t length = symbol.size(); 25224 | 25225 | if ( 25226 | (length < 3) || // Shortest base op symbol length 25227 | (length > 9) // Longest base op symbol length 25228 | ) 25229 | return false; 25230 | else 25231 | return settings_.function_enabled(symbol) && 25232 | (base_ops_map_.end() != base_ops_map_.find(symbol)); 25233 | } 25234 | 25235 | inline bool valid_vararg_operation(const std::string& symbol) const 25236 | { 25237 | static const std::string s_sum = "sum" ; 25238 | static const std::string s_mul = "mul" ; 25239 | static const std::string s_avg = "avg" ; 25240 | static const std::string s_min = "min" ; 25241 | static const std::string s_max = "max" ; 25242 | static const std::string s_mand = "mand" 25243 | static const std::string s_mor = "mor" ; 25244 | static const std::string s_multi = "~" ; 25245 | static const std::string s_mswitch = "[*]" ; 25246 | 25247 | return 25248 | ( 25249 | details::imatch(symbol,s_sum ) || 25250 | details::imatch(symbol,s_mul ) || 25251 | details::imatch(symbol,s_avg ) || 25252 | details::imatch(symbol,s_min ) || 25253 | details::imatch(symbol,s_max ) || 25254 | details::imatch(symbol,s_mand ) || 25255 | details::imatch(symbol,s_mor ) || 25256 | details::imatch(symbol,s_multi ) || 25257 | details::imatch(symbol,s_mswitch) 25258 | ) && 25259 | settings_.function_enabled(symbol); 25260 | } 25261 | 25262 | bool is_invalid_logic_operation(const details::operator_type operation) const 25263 | { 25264 | return settings_.logic_disabled(operation); 25265 | } 25266 | 25267 | bool is_invalid_arithmetic_operation(const details::operator_type operation) const 25268 | { 25269 | return settings_.arithmetic_disabled(operation); 25270 | } 25271 | 25272 | bool is_invalid_assignment_operation(const details::operator_type operation) const 25273 | { 25274 | return settings_.assignment_disabled(operation); 25275 | } 25276 | 25277 | bool is_invalid_inequality_operation(const details::operator_type operation) const 25278 | { 25279 | return settings_.inequality_disabled(operation); 25280 | } 25281 | 25282 | #ifdef exprtk_enable_debugging 25283 | inline void next_token() 25284 | { 25285 | const std::string ct_str = current_token().value; 25286 | const std::size_t ct_pos = current_token().position; 25287 | parser_helper::next_token(); 25288 | const std::string depth(2 * state_.scope_depth,' '); 25289 | exprtk_debug(("%s" 25290 | "prev[%s | %04d] --> curr[%s | %04d] stack_level: %3d\n", 25291 | depth.c_str(), 25292 | ct_str.c_str(), 25293 | static_cast<unsigned int>(ct_pos), 25294 | current_token().value.c_str(), 25295 | static_cast<unsigned int>(current_token().position), 25296 | static_cast<unsigned int>(state_.stack_depth))); 25297 | } 25298 | #endif 25299 | 25300 | inline expression_node_ptr parse_corpus() 25301 | { 25302 | std::vector<expression_node_ptr> arg_list; 25303 | std::vector<bool> side_effect_list; 25304 | 25305 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 25306 | 25307 | lexer::token begin_token; 25308 | lexer::token end_token; 25309 | 25310 | for ( ; ; ) 25311 | { 25312 | state_.side_effect_present = false; 25313 | 25314 | begin_token = current_token(); 25315 | 25316 | expression_node_ptr arg = parse_expression(); 25317 | 25318 | if (0 == arg) 25319 | { 25320 | if (error_list_.empty()) 25321 | { 25322 | set_error(make_error( 25323 | parser_error::e_syntax, 25324 | current_token(), 25325 | "ERR009 - Invalid expression encountered", 25326 | exprtk_error_location)); 25327 | } 25328 | 25329 | return error_node(); 25330 | } 25331 | else 25332 | { 25333 | arg_list.push_back(arg); 25334 | 25335 | side_effect_list.push_back(state_.side_effect_present); 25336 | 25337 | end_token = current_token(); 25338 | 25339 | const std::string sub_expr = construct_subexpr(begin_token, end_token); 25340 | 25341 | exprtk_debug(("parse_corpus(%02d) Subexpr: %s\n", 25342 | static_cast<int>(arg_list.size() - 1), 25343 | sub_expr.c_str())); 25344 | 25345 | exprtk_debug(("parse_corpus(%02d) - Side effect present: %s\n", 25346 | static_cast<int>(arg_list.size() - 1), 25347 | state_.side_effect_present ? "true" : "false")); 25348 | 25349 | exprtk_debug(("-------------------------------------------------\n")); 25350 | } 25351 | 25352 | if (token_is(token_t::e_eof,prsrhlpr_t::e_hold)) 25353 | { 25354 | if (lexer().finished()) 25355 | break; 25356 | else 25357 | next_token(); 25358 | } 25359 | else if ( 25360 | !settings_.commutative_check_enabled() && 25361 | ( 25362 | current_token().type == token_t::e_symbol || 25363 | current_token().type == token_t::e_number || 25364 | current_token().type == token_t::e_string || 25365 | token_is_bracket(prsrhlpr_t::e_hold) 25366 | ) 25367 | ) 25368 | { 25369 | set_error(make_error( 25370 | parser_error::e_syntax, 25371 | current_token(), 25372 | "ERR010 - Invalid syntax '" + current_token().value + "' possible missing operator or context", 25373 | exprtk_error_location)); 25374 | 25375 | return error_node(); 25376 | } 25377 | } 25378 | 25379 | if ( 25380 | !arg_list.empty() && 25381 | is_return_node(arg_list.back()) 25382 | ) 25383 | { 25384 | dec_.final_stmt_return_ = true; 25385 | } 25386 | 25387 | const expression_node_ptr result = simplify(arg_list,side_effect_list); 25388 | 25389 | svd.delete_ptr = (0 == result); 25390 | 25391 | return result; 25392 | } 25393 | 25394 | std::string construct_subexpr(lexer::token& begin_token, 25395 | lexer::token& end_token, 25396 | const bool cleanup_whitespace = true) 25397 | { 25398 | std::string result = lexer().substr(begin_token.position,end_token.position); 25399 | if (cleanup_whitespace) 25400 | { 25401 | for (std::size_t i = 0; i < result.size(); ++i) 25402 | { 25403 | if (details::is_whitespace(result[i])) result[i] = ' '; 25404 | } 25405 | } 25406 | 25407 | return result; 25408 | } 25409 | 25410 | static const precedence_level default_precedence = e_level00; 25411 | 25412 | struct state_t 25413 | { 25414 | inline void set(const precedence_level& l, 25415 | const precedence_level& r, 25416 | const details::operator_type& o, 25417 | const token_t& tkn = token_t()) 25418 | { 25419 | left = l; 25420 | right = r; 25421 | operation = o; 25422 | token = tkn; 25423 | } 25424 | 25425 | inline void reset() 25426 | { 25427 | left = e_level00; 25428 | right = e_level00; 25429 | operation = details::e_default; 25430 | } 25431 | 25432 | precedence_level left; 25433 | precedence_level right; 25434 | details::operator_type operation; 25435 | token_t token; 25436 | }; 25437 | 25438 | inline void push_current_state(const state_t current_state) 25439 | { 25440 | current_state_stack_.push_back(current_state); 25441 | } 25442 | 25443 | inline void pop_current_state() 25444 | { 25445 | if (!current_state_stack_.empty()) 25446 | { 25447 | current_state_stack_.pop_back(); 25448 | } 25449 | } 25450 | 25451 | inline state_t current_state() const 25452 | { 25453 | return (!current_state_stack_.empty()) ? 25454 | current_state_stack_.back() : 25455 | state_t(); 25456 | } 25457 | 25458 | inline bool halt_compilation_check() 25459 | { 25460 | compilation_check::compilation_context context; 25461 | 25462 | if (compilation_check_ptr_ && !compilation_check_ptr_->continue_compilation(context)) 25463 | { 25464 | const std::string error_message = 25465 | !context.error_message.empty() ? " Details: " + context.error_message : "" 25466 | 25467 | set_error(make_error( 25468 | parser_error::e_parser, 25469 | token_t(), 25470 | "ERR011 - Internal compilation check failed." + error_message, 25471 | exprtk_error_location)); 25472 | 25473 | return true; 25474 | } 25475 | 25476 | return false; 25477 | } 25478 | 25479 | inline expression_node_ptr parse_expression(precedence_level precedence = e_level00) 25480 | { 25481 | if (halt_compilation_check()) 25482 | { 25483 | exprtk_debug(("halt_compilation_check() - parse_expression checkpoint 2\n")); 25484 | return error_node(); 25485 | } 25486 | 25487 | stack_limit_handler slh(*this); 25488 | 25489 | if (!slh) 25490 | { 25491 | return error_node(); 25492 | } 25493 | 25494 | expression_node_ptr expression = parse_branch(precedence); 25495 | 25496 | if (0 == expression) 25497 | { 25498 | return error_node(); 25499 | } 25500 | 25501 | if (token_is(token_t::e_eof,prsrhlpr_t::e_hold)) 25502 | { 25503 | return expression; 25504 | } 25505 | 25506 | bool break_loop = false; 25507 | 25508 | state_t current_state; 25509 | 25510 | for ( ; ; ) 25511 | { 25512 | current_state.reset(); 25513 | 25514 | switch (current_token().type) 25515 | { 25516 | case token_t::e_assign : current_state.set(e_level00, e_level00, details::e_assign, current_token()); break; 25517 | case token_t::e_addass : current_state.set(e_level00, e_level00, details::e_addass, current_token()); break; 25518 | case token_t::e_subass : current_state.set(e_level00, e_level00, details::e_subass, current_token()); break; 25519 | case token_t::e_mulass : current_state.set(e_level00, e_level00, details::e_mulass, current_token()); break; 25520 | case token_t::e_divass : current_state.set(e_level00, e_level00, details::e_divass, current_token()); break; 25521 | case token_t::e_modass : current_state.set(e_level00, e_level00, details::e_modass, current_token()); break; 25522 | case token_t::e_swap : current_state.set(e_level00, e_level00, details::e_swap , current_token()); break; 25523 | case token_t::e_lt : current_state.set(e_level05, e_level06, details::e_lt , current_token()); break; 25524 | case token_t::e_lte : current_state.set(e_level05, e_level06, details::e_lte , current_token()); break; 25525 | case token_t::e_eq : current_state.set(e_level05, e_level06, details::e_eq , current_token()); break; 25526 | case token_t::e_ne : current_state.set(e_level05, e_level06, details::e_ne , current_token()); break; 25527 | case token_t::e_gte : current_state.set(e_level05, e_level06, details::e_gte , current_token()); break; 25528 | case token_t::e_gt : current_state.set(e_level05, e_level06, details::e_gt , current_token()); break; 25529 | case token_t::e_add : current_state.set(e_level07, e_level08, details::e_add , current_token()); break; 25530 | case token_t::e_sub : current_state.set(e_level07, e_level08, details::e_sub , current_token()); break; 25531 | case token_t::e_div : current_state.set(e_level10, e_level11, details::e_div , current_token()); break; 25532 | case token_t::e_mul : current_state.set(e_level10, e_level11, details::e_mul , current_token()); break; 25533 | case token_t::e_mod : current_state.set(e_level10, e_level11, details::e_mod , current_token()); break; 25534 | case token_t::e_pow : current_state.set(e_level12, e_level12, details::e_pow , current_token()); break; 25535 | default : 25536 | if (token_t::e_symbol == current_token().type) 25537 | { 25538 | static const std::string s_and = "and" ; 25539 | static const std::string s_nand = "nand" ; 25540 | static const std::string s_or = "or" ; 25541 | static const std::string s_nor = "nor" ; 25542 | static const std::string s_xor = "xor" ; 25543 | static const std::string s_xnor = "xnor" ; 25544 | static const std::string s_in = "in" ; 25545 | static const std::string s_like = "like" ; 25546 | static const std::string s_ilike = "ilike" 25547 | static const std::string s_and1 = "&" ; 25548 | static const std::string s_or1 = "|" ; 25549 | static const std::string s_not = "not" ; 25550 | 25551 | if (details::imatch(current_token().value,s_and)) 25552 | { 25553 | current_state.set(e_level03, e_level04, details::e_and, current_token()); 25554 | break; 25555 | } 25556 | else if (details::imatch(current_token().value,s_and1)) 25557 | { 25558 | #ifndef exprtk_disable_sc_andor 25559 | current_state.set(e_level03, e_level04, details::e_scand, current_token()); 25560 | #else 25561 | current_state.set(e_level03, e_level04, details::e_and, current_token()); 25562 | #endif 25563 | break; 25564 | } 25565 | else if (details::imatch(current_token().value,s_nand)) 25566 | { 25567 | current_state.set(e_level03, e_level04, details::e_nand, current_token()); 25568 | break; 25569 | } 25570 | else if (details::imatch(current_token().value,s_or)) 25571 | { 25572 | current_state.set(e_level01, e_level02, details::e_or, current_token()); 25573 | break; 25574 | } 25575 | else if (details::imatch(current_token().value,s_or1)) 25576 | { 25577 | #ifndef exprtk_disable_sc_andor 25578 | current_state.set(e_level01, e_level02, details::e_scor, current_token()); 25579 | #else 25580 | current_state.set(e_level01, e_level02, details::e_or, current_token()); 25581 | #endif 25582 | break; 25583 | } 25584 | else if (details::imatch(current_token().value,s_nor)) 25585 | { 25586 | current_state.set(e_level01, e_level02, details::e_nor, current_token()); 25587 | break; 25588 | } 25589 | else if (details::imatch(current_token().value,s_xor)) 25590 | { 25591 | current_state.set(e_level01, e_level02, details::e_xor, current_token()); 25592 | break; 25593 | } 25594 | else if (details::imatch(current_token().value,s_xnor)) 25595 | { 25596 | current_state.set(e_level01, e_level02, details::e_xnor, current_token()); 25597 | break; 25598 | } 25599 | else if (details::imatch(current_token().value,s_in)) 25600 | { 25601 | current_state.set(e_level04, e_level04, details::e_in, current_token()); 25602 | break; 25603 | } 25604 | else if (details::imatch(current_token().value,s_like)) 25605 | { 25606 | current_state.set(e_level04, e_level04, details::e_like, current_token()); 25607 | break; 25608 | } 25609 | else if (details::imatch(current_token().value,s_ilike)) 25610 | { 25611 | current_state.set(e_level04, e_level04, details::e_ilike, current_token()); 25612 | break; 25613 | } 25614 | else if (details::imatch(current_token().value,s_not)) 25615 | { 25616 | break; 25617 | } 25618 | } 25619 | 25620 | break_loop = true; 25621 | } 25622 | 25623 | if (break_loop) 25624 | { 25625 | parse_pending_string_rangesize(expression); 25626 | break; 25627 | } 25628 | else if (current_state.left < precedence) 25629 | break; 25630 | 25631 | const lexer::token prev_token = current_token(); 25632 | 25633 | next_token(); 25634 | 25635 | expression_node_ptr right_branch = error_node(); 25636 | expression_node_ptr new_expression = error_node(); 25637 | 25638 | if (is_invalid_logic_operation(current_state.operation)) 25639 | { 25640 | free_node(node_allocator_, expression); 25641 | 25642 | set_error(make_error( 25643 | parser_error::e_syntax, 25644 | prev_token, 25645 | "ERR012 - Invalid or disabled logic operation '" + details::to_str(current_state.operation) + "'", 25646 | exprtk_error_location)); 25647 | 25648 | return error_node(); 25649 | } 25650 | else if (is_invalid_arithmetic_operation(current_state.operation)) 25651 | { 25652 | free_node(node_allocator_, expression); 25653 | 25654 | set_error(make_error( 25655 | parser_error::e_syntax, 25656 | prev_token, 25657 | "ERR013 - Invalid or disabled arithmetic operation '" + details::to_str(current_state.operation) + "'", 25658 | exprtk_error_location)); 25659 | 25660 | return error_node(); 25661 | } 25662 | else if (is_invalid_inequality_operation(current_state.operation)) 25663 | { 25664 | free_node(node_allocator_, expression); 25665 | 25666 | set_error(make_error( 25667 | parser_error::e_syntax, 25668 | prev_token, 25669 | "ERR014 - Invalid inequality operation '" + details::to_str(current_state.operation) + "'", 25670 | exprtk_error_location)); 25671 | 25672 | return error_node(); 25673 | } 25674 | else if (is_invalid_assignment_operation(current_state.operation)) 25675 | { 25676 | free_node(node_allocator_, expression); 25677 | 25678 | set_error(make_error( 25679 | parser_error::e_syntax, 25680 | prev_token, 25681 | "ERR015 - Invalid or disabled assignment operation '" + details::to_str(current_state.operation) + "'", 25682 | exprtk_error_location)); 25683 | 25684 | return error_node(); 25685 | } 25686 | 25687 | if (0 != (right_branch = parse_expression(current_state.right))) 25688 | { 25689 | if ( 25690 | details::is_return_node(expression ) || 25691 | details::is_return_node(right_branch) 25692 | ) 25693 | { 25694 | free_node(node_allocator_, expression ); 25695 | free_node(node_allocator_, right_branch); 25696 | 25697 | set_error(make_error( 25698 | parser_error::e_syntax, 25699 | prev_token, 25700 | "ERR016 - Return statements cannot be part of sub-expressions", 25701 | exprtk_error_location)); 25702 | 25703 | return error_node(); 25704 | } 25705 | 25706 | push_current_state(current_state); 25707 | 25708 | new_expression = expression_generator_ 25709 | ( 25710 | current_state.operation, 25711 | expression, 25712 | right_branch 25713 | ); 25714 | 25715 | pop_current_state(); 25716 | } 25717 | 25718 | if (0 == new_expression) 25719 | { 25720 | if (error_list_.empty()) 25721 | { 25722 | set_error(make_error( 25723 | parser_error::e_syntax, 25724 | prev_token, 25725 | !synthesis_error_.empty() ? 25726 | synthesis_error_ : 25727 | "ERR017 - General parsing error at token: '" + prev_token.value + "'", 25728 | exprtk_error_location)); 25729 | } 25730 | 25731 | free_node(node_allocator_, expression ); 25732 | free_node(node_allocator_, right_branch); 25733 | 25734 | return error_node(); 25735 | } 25736 | else 25737 | { 25738 | if ( 25739 | token_is(token_t::e_ternary,prsrhlpr_t::e_hold) && 25740 | (e_level00 == precedence) 25741 | ) 25742 | { 25743 | expression = parse_ternary_conditional_statement(new_expression); 25744 | } 25745 | else 25746 | expression = new_expression; 25747 | 25748 | parse_pending_string_rangesize(expression); 25749 | } 25750 | } 25751 | 25752 | if ((0 != expression) && (expression->node_depth() > settings_.max_node_depth_)) 25753 | { 25754 | set_error(make_error( 25755 | parser_error::e_syntax, 25756 | current_token(), 25757 | "ERR018 - Expression depth of " + details::to_str(static_cast<int>(expression->node_depth())) + 25758 | " exceeds maximum allowed expression depth of " + details::to_str(static_cast<int>(settings_.max_node_depth_)), 25759 | exprtk_error_location)); 25760 | 25761 | free_node(node_allocator_, expression); 25762 | 25763 | return error_node(); 25764 | } 25765 | else if ( 25766 | !settings_.commutative_check_enabled() && 25767 | !details::is_logic_opr(current_token().value) && 25768 | (current_state.operation == details::e_default) && 25769 | ( 25770 | current_token().type == token_t::e_symbol || 25771 | current_token().type == token_t::e_number || 25772 | current_token().type == token_t::e_string 25773 | ) 25774 | ) 25775 | { 25776 | set_error(make_error( 25777 | parser_error::e_syntax, 25778 | current_token(), 25779 | "ERR019 - Invalid syntax '" + current_token().value + "' possible missing operator or context", 25780 | exprtk_error_location)); 25781 | 25782 | free_node(node_allocator_, expression); 25783 | 25784 | return error_node(); 25785 | } 25786 | 25787 | return expression; 25788 | } 25789 | 25790 | bool simplify_unary_negation_branch(expression_node_ptr& node) 25791 | { 25792 | { 25793 | typedef details::unary_branch_node<T,details::neg_op<T> > ubn_t; 25794 | ubn_t* n = dynamic_cast<ubn_t*>(node); 25795 | 25796 | if (n) 25797 | { 25798 | expression_node_ptr un_r = n->branch(0); 25799 | n->release(); 25800 | free_node(node_allocator_, node); 25801 | node = un_r; 25802 | 25803 | return true; 25804 | } 25805 | } 25806 | 25807 | { 25808 | typedef details::unary_variable_node<T,details::neg_op<T> > uvn_t; 25809 | 25810 | uvn_t* n = dynamic_cast<uvn_t*>(node); 25811 | 25812 | if (n) 25813 | { 25814 | const T& v = n->v(); 25815 | expression_node_ptr return_node = error_node(); 25816 | 25817 | if ( 25818 | (0 != (return_node = symtab_store_.get_variable(v))) || 25819 | (0 != (return_node = sem_ .get_variable(v))) 25820 | ) 25821 | { 25822 | free_node(node_allocator_, node); 25823 | node = return_node; 25824 | 25825 | return true; 25826 | } 25827 | else 25828 | { 25829 | set_error(make_error( 25830 | parser_error::e_syntax, 25831 | current_token(), 25832 | "ERR020 - Failed to find variable node in symbol table", 25833 | exprtk_error_location)); 25834 | 25835 | free_node(node_allocator_, node); 25836 | 25837 | return false; 25838 | } 25839 | } 25840 | } 25841 | 25842 | return false; 25843 | } 25844 | 25845 | static inline expression_node_ptr error_node() 25846 | { 25847 | return reinterpret_cast<expression_node_ptr>(0); 25848 | } 25849 | 25850 | struct scoped_expression_delete 25851 | { 25852 | scoped_expression_delete(parser<T>& pr, expression_node_ptr& expression) 25853 | : delete_ptr(true) 25854 | , parser_(pr) 25855 | , expression_(expression) 25856 | {} 25857 | 25858 | ~scoped_expression_delete() 25859 | { 25860 | if (delete_ptr) 25861 | { 25862 | free_node(parser_.node_allocator_, expression_); 25863 | } 25864 | } 25865 | 25866 | bool delete_ptr; 25867 | parser<T>& parser_; 25868 | expression_node_ptr& expression_; 25869 | 25870 | private: 25871 | 25872 | scoped_expression_delete(const scoped_expression_delete&) exprtk_delete; 25873 | scoped_expression_delete& operator=(const scoped_expression_delete&) exprtk_delete; 25874 | }; 25875 | 25876 | template <typename Type, std::size_t N> 25877 | struct scoped_delete 25878 | { 25879 | typedef Type* ptr_t; 25880 | 25881 | scoped_delete(parser<T>& pr, ptr_t& p) 25882 | : delete_ptr(true) 25883 | , parser_(pr) 25884 | , p_(&p) 25885 | {} 25886 | 25887 | scoped_delete(parser<T>& pr, ptr_t (&p)[N]) 25888 | : delete_ptr(true) 25889 | , parser_(pr) 25890 | , p_(&p[0]) 25891 | {} 25892 | 25893 | ~scoped_delete() 25894 | { 25895 | if (delete_ptr) 25896 | { 25897 | for (std::size_t i = 0; i < N; ++i) 25898 | { 25899 | free_node(parser_.node_allocator_, p_[i]); 25900 | } 25901 | } 25902 | } 25903 | 25904 | bool delete_ptr; 25905 | parser<T>& parser_; 25906 | ptr_t* p_; 25907 | 25908 | private: 25909 | 25910 | scoped_delete(const scoped_delete<Type,N>&) exprtk_delete; 25911 | scoped_delete<Type,N>& operator=(const scoped_delete<Type,N>&) exprtk_delete; 25912 | }; 25913 | 25914 | template <typename Type> 25915 | struct scoped_deq_delete 25916 | { 25917 | typedef Type* ptr_t; 25918 | 25919 | scoped_deq_delete(parser<T>& pr, std::deque<ptr_t>& deq) 25920 | : delete_ptr(true) 25921 | , parser_(pr) 25922 | , deq_(deq) 25923 | {} 25924 | 25925 | ~scoped_deq_delete() 25926 | { 25927 | if (delete_ptr && !deq_.empty()) 25928 | { 25929 | for (std::size_t i = 0; i < deq_.size(); ++i) 25930 | { 25931 | exprtk_debug(("~scoped_deq_delete() - deleting node: %p\n", reinterpret_cast<void*>(deq_[i]))); 25932 | free_node(parser_.node_allocator_,deq_[i]); 25933 | } 25934 | 25935 | deq_.clear(); 25936 | } 25937 | } 25938 | 25939 | bool delete_ptr; 25940 | parser<T>& parser_; 25941 | std::deque<ptr_t>& deq_; 25942 | 25943 | private: 25944 | 25945 | scoped_deq_delete(const scoped_deq_delete<Type>&) exprtk_delete; 25946 | scoped_deq_delete<Type>& operator=(const scoped_deq_delete<Type>&) exprtk_delete; 25947 | }; 25948 | 25949 | template <typename Type> 25950 | struct scoped_vec_delete 25951 | { 25952 | typedef Type* ptr_t; 25953 | 25954 | scoped_vec_delete(parser<T>& pr, std::vector<ptr_t>& vec) 25955 | : delete_ptr(true) 25956 | , parser_(pr) 25957 | , vec_(vec) 25958 | {} 25959 | 25960 | ~scoped_vec_delete() 25961 | { 25962 | if (delete_ptr && !vec_.empty()) 25963 | { 25964 | for (std::size_t i = 0; i < vec_.size(); ++i) 25965 | { 25966 | exprtk_debug(("~scoped_vec_delete() - deleting node: %p\n", reinterpret_cast<void*>(vec_[i]))); 25967 | free_node(parser_.node_allocator_,vec_[i]); 25968 | } 25969 | 25970 | vec_.clear(); 25971 | } 25972 | } 25973 | 25974 | ptr_t operator[](const std::size_t index) 25975 | { 25976 | return vec_[index]; 25977 | } 25978 | 25979 | bool delete_ptr; 25980 | parser<T>& parser_; 25981 | std::vector<ptr_t>& vec_; 25982 | 25983 | private: 25984 | 25985 | scoped_vec_delete(const scoped_vec_delete<Type>&) exprtk_delete; 25986 | scoped_vec_delete<Type>& operator=(const scoped_vec_delete<Type>&) exprtk_delete; 25987 | }; 25988 | 25989 | struct scoped_bool_negator 25990 | { 25991 | explicit scoped_bool_negator(bool& bb) 25992 | : b(bb) 25993 | { b = !b; } 25994 | 25995 | ~scoped_bool_negator() 25996 | { b = !b; } 25997 | 25998 | bool& b; 25999 | }; 26000 | 26001 | struct scoped_bool_or_restorer 26002 | { 26003 | explicit scoped_bool_or_restorer(bool& bb) 26004 | : b(bb) 26005 | , original_value_(bb) 26006 | {} 26007 | 26008 | ~scoped_bool_or_restorer() 26009 | { 26010 | b = b || original_value_; 26011 | } 26012 | 26013 | bool& b; 26014 | bool original_value_; 26015 | }; 26016 | 26017 | struct scoped_inc_dec 26018 | { 26019 | explicit scoped_inc_dec(std::size_t& v) 26020 | : v_(v) 26021 | { ++v_; } 26022 | 26023 | ~scoped_inc_dec() 26024 | { 26025 | assert(v_ > 0); 26026 | --v_; 26027 | } 26028 | 26029 | std::size_t& v_; 26030 | }; 26031 | 26032 | inline expression_node_ptr parse_function_invocation(ifunction<T>* function, const std::string& function_name) 26033 | { 26034 | expression_node_ptr func_node = reinterpret_cast<expression_node_ptr>(0); 26035 | 26036 | switch (function->param_count) 26037 | { 26038 | case 0 : func_node = parse_function_call_0 (function,function_name); break; 26039 | case 1 : func_node = parse_function_call< 1>(function,function_name); break; 26040 | case 2 : func_node = parse_function_call< 2>(function,function_name); break; 26041 | case 3 : func_node = parse_function_call< 3>(function,function_name); break; 26042 | case 4 : func_node = parse_function_call< 4>(function,function_name); break; 26043 | case 5 : func_node = parse_function_call< 5>(function,function_name); break; 26044 | case 6 : func_node = parse_function_call< 6>(function,function_name); break; 26045 | case 7 : func_node = parse_function_call< 7>(function,function_name); break; 26046 | case 8 : func_node = parse_function_call< 8>(function,function_name); break; 26047 | case 9 : func_node = parse_function_call< 9>(function,function_name); break; 26048 | case 10 : func_node = parse_function_call<10>(function,function_name); break; 26049 | case 11 : func_node = parse_function_call<11>(function,function_name); break; 26050 | case 12 : func_node = parse_function_call<12>(function,function_name); break; 26051 | case 13 : func_node = parse_function_call<13>(function,function_name); break; 26052 | case 14 : func_node = parse_function_call<14>(function,function_name); break; 26053 | case 15 : func_node = parse_function_call<15>(function,function_name); break; 26054 | case 16 : func_node = parse_function_call<16>(function,function_name); break; 26055 | case 17 : func_node = parse_function_call<17>(function,function_name); break; 26056 | case 18 : func_node = parse_function_call<18>(function,function_name); break; 26057 | case 19 : func_node = parse_function_call<19>(function,function_name); break; 26058 | case 20 : func_node = parse_function_call<20>(function,function_name); break; 26059 | default : { 26060 | set_error(make_error( 26061 | parser_error::e_syntax, 26062 | current_token(), 26063 | "ERR021 - Invalid number of parameters for function: '" + function_name + "'", 26064 | exprtk_error_location)); 26065 | 26066 | return error_node(); 26067 | } 26068 | } 26069 | 26070 | if (func_node) 26071 | return func_node; 26072 | else 26073 | { 26074 | set_error(make_error( 26075 | parser_error::e_syntax, 26076 | current_token(), 26077 | "ERR022 - Failed to generate call to function: '" + function_name + "'", 26078 | exprtk_error_location)); 26079 | 26080 | return error_node(); 26081 | } 26082 | } 26083 | 26084 | template <std::size_t NumberofParameters> 26085 | inline expression_node_ptr parse_function_call(ifunction<T>* function, const std::string& function_name) 26086 | { 26087 | #ifdef _MSC_VER 26088 | #pragma warning(push) 26089 | #pragma warning(disable: 4127) 26090 | #endif 26091 | if (0 == NumberofParameters) 26092 | { 26093 | set_error(make_error( 26094 | parser_error::e_syntax, 26095 | current_token(), 26096 | "ERR023 - Expecting ifunction '" + function_name + "' to have non-zero parameter count", 26097 | exprtk_error_location)); 26098 | 26099 | return error_node(); 26100 | } 26101 | #ifdef _MSC_VER 26102 | #pragma warning(pop) 26103 | #endif 26104 | 26105 | expression_node_ptr branch[NumberofParameters]; 26106 | expression_node_ptr result = error_node(); 26107 | 26108 | std::fill_n(branch, NumberofParameters, reinterpret_cast<expression_node_ptr>(0)); 26109 | 26110 | scoped_delete<expression_node_t,NumberofParameters> sd((*this),branch); 26111 | 26112 | next_token(); 26113 | 26114 | if (!token_is(token_t::e_lbracket)) 26115 | { 26116 | set_error(make_error( 26117 | parser_error::e_syntax, 26118 | current_token(), 26119 | "ERR024 - Expecting argument list for function: '" + function_name + "'", 26120 | exprtk_error_location)); 26121 | 26122 | return error_node(); 26123 | } 26124 | 26125 | for (int i = 0; i < static_cast<int>(NumberofParameters); ++i) 26126 | { 26127 | branch[i] = parse_expression(); 26128 | 26129 | if (0 == branch[i]) 26130 | { 26131 | set_error(make_error( 26132 | parser_error::e_syntax, 26133 | current_token(), 26134 | "ERR025 - Failed to parse argument " + details::to_str(i) + " for function: '" + function_name + "'", 26135 | exprtk_error_location)); 26136 | 26137 | return error_node(); 26138 | } 26139 | else if (i < static_cast<int>(NumberofParameters - 1)) 26140 | { 26141 | if (!token_is(token_t::e_comma)) 26142 | { 26143 | set_error(make_error( 26144 | parser_error::e_syntax, 26145 | current_token(), 26146 | "ERR026 - Invalid number of arguments for function: '" + function_name + "'", 26147 | exprtk_error_location)); 26148 | 26149 | return error_node(); 26150 | } 26151 | } 26152 | } 26153 | 26154 | if (!token_is(token_t::e_rbracket)) 26155 | { 26156 | set_error(make_error( 26157 | parser_error::e_syntax, 26158 | current_token(), 26159 | "ERR027 - Invalid number of arguments for function: '" + function_name + "'", 26160 | exprtk_error_location)); 26161 | 26162 | return error_node(); 26163 | } 26164 | else 26165 | result = expression_generator_.function(function,branch); 26166 | 26167 | sd.delete_ptr = (0 == result); 26168 | 26169 | return result; 26170 | } 26171 | 26172 | inline expression_node_ptr parse_function_call_0(ifunction<T>* function, const std::string& function_name) 26173 | { 26174 | expression_node_ptr result = expression_generator_.function(function); 26175 | 26176 | state_.side_effect_present = function->has_side_effects(); 26177 | 26178 | next_token(); 26179 | 26180 | if ( 26181 | token_is(token_t::e_lbracket) && 26182 | !token_is(token_t::e_rbracket) 26183 | ) 26184 | { 26185 | set_error(make_error( 26186 | parser_error::e_syntax, 26187 | current_token(), 26188 | "ERR028 - Expecting '()' to proceed call to function: '" + function_name + "'", 26189 | exprtk_error_location)); 26190 | 26191 | free_node(node_allocator_, result); 26192 | 26193 | return error_node(); 26194 | } 26195 | else 26196 | return result; 26197 | } 26198 | 26199 | template <std::size_t MaxNumberofParameters> 26200 | inline std::size_t parse_base_function_call(expression_node_ptr (¶m_list)[MaxNumberofParameters], const std::string& function_name = "") 26201 | { 26202 | std::fill_n(param_list, MaxNumberofParameters, reinterpret_cast<expression_node_ptr>(0)); 26203 | 26204 | scoped_delete<expression_node_t,MaxNumberofParameters> sd((*this),param_list); 26205 | 26206 | next_token(); 26207 | 26208 | if (!token_is(token_t::e_lbracket)) 26209 | { 26210 | set_error(make_error( 26211 | parser_error::e_syntax, 26212 | current_token(), 26213 | "ERR029 - Expected a '(' at start of function call to '" + function_name + 26214 | "', instead got: '" + current_token().value + "'", 26215 | exprtk_error_location)); 26216 | 26217 | return 0; 26218 | } 26219 | 26220 | if (token_is(token_t::e_rbracket, e_hold)) 26221 | { 26222 | set_error(make_error( 26223 | parser_error::e_syntax, 26224 | current_token(), 26225 | "ERR030 - Expected at least one input parameter for function call '" + function_name + "'", 26226 | exprtk_error_location)); 26227 | 26228 | return 0; 26229 | } 26230 | 26231 | std::size_t param_index = 0; 26232 | 26233 | for (; param_index < MaxNumberofParameters; ++param_index) 26234 | { 26235 | param_list[param_index] = parse_expression(); 26236 | 26237 | if (0 == param_list[param_index]) 26238 | return 0; 26239 | else if (token_is(token_t::e_rbracket)) 26240 | { 26241 | sd.delete_ptr = false; 26242 | break; 26243 | } 26244 | else if (token_is(token_t::e_comma)) 26245 | continue; 26246 | else 26247 | { 26248 | set_error(make_error( 26249 | parser_error::e_syntax, 26250 | current_token(), 26251 | "ERR031 - Expected a ',' between function input parameters, instead got: '" + current_token().value + "'", 26252 | exprtk_error_location)); 26253 | 26254 | return 0; 26255 | } 26256 | } 26257 | 26258 | if (sd.delete_ptr) 26259 | { 26260 | set_error(make_error( 26261 | parser_error::e_syntax, 26262 | current_token(), 26263 | "ERR032 - Invalid number of input parameters passed to function '" + function_name + "'", 26264 | exprtk_error_location)); 26265 | 26266 | return 0; 26267 | } 26268 | 26269 | return (param_index + 1); 26270 | } 26271 | 26272 | inline expression_node_ptr parse_base_operation() 26273 | { 26274 | typedef std::pair<base_ops_map_t::iterator,base_ops_map_t::iterator> map_range_t; 26275 | 26276 | const std::string operation_name = current_token().value; 26277 | const token_t diagnostic_token = current_token(); 26278 | 26279 | map_range_t itr_range = base_ops_map_.equal_range(operation_name); 26280 | 26281 | if (0 == std::distance(itr_range.first,itr_range.second)) 26282 | { 26283 | set_error(make_error( 26284 | parser_error::e_syntax, 26285 | diagnostic_token, 26286 | "ERR033 - No entry found for base operation: " + operation_name, 26287 | exprtk_error_location)); 26288 | 26289 | return error_node(); 26290 | } 26291 | 26292 | static const std::size_t MaxNumberofParameters = 4; 26293 | expression_node_ptr param_list[MaxNumberofParameters] = {0}; 26294 | 26295 | const std::size_t parameter_count = parse_base_function_call(param_list, operation_name); 26296 | 26297 | if ((parameter_count > 0) && (parameter_count <= MaxNumberofParameters)) 26298 | { 26299 | for (base_ops_map_t::iterator itr = itr_range.first; itr != itr_range.second; ++itr) 26300 | { 26301 | const details::base_operation_t& operation = itr->second; 26302 | 26303 | if (operation.num_params == parameter_count) 26304 | { 26305 | switch (parameter_count) 26306 | { 26307 | #define base_opr_case(N) \ 26308 | case N : { \ 26309 | expression_node_ptr pl##N[N] = {0}; \ 26310 | std::copy(param_list, param_list + N, pl##N); \ 26311 | lodge_symbol(operation_name, e_st_function); \ 26312 | return expression_generator_(operation.type, pl##N); \ 26313 | } \ 26314 | 26315 | base_opr_case(1) 26316 | base_opr_case(2) 26317 | base_opr_case(3) 26318 | base_opr_case(4) 26319 | #undef base_opr_case 26320 | } 26321 | } 26322 | } 26323 | } 26324 | 26325 | for (std::size_t i = 0; i < MaxNumberofParameters; ++i) 26326 | { 26327 | free_node(node_allocator_, param_list[i]); 26328 | } 26329 | 26330 | set_error(make_error( 26331 | parser_error::e_syntax, 26332 | diagnostic_token, 26333 | "ERR034 - Invalid number of input parameters for call to function: '" + operation_name + "'", 26334 | exprtk_error_location)); 26335 | 26336 | return error_node(); 26337 | } 26338 | 26339 | inline expression_node_ptr parse_conditional_statement_01(expression_node_ptr condition) 26340 | { 26341 | // Parse: [if][(][condition][,][consequent][,][alternative][)] 26342 | 26343 | expression_node_ptr consequent = error_node(); 26344 | expression_node_ptr alternative = error_node(); 26345 | 26346 | bool result = true; 26347 | 26348 | if (!token_is(token_t::e_comma)) 26349 | { 26350 | set_error(make_error( 26351 | parser_error::e_syntax, 26352 | current_token(), 26353 | "ERR035 - Expected ',' between if-statement condition and consequent", 26354 | exprtk_error_location)); 26355 | 26356 | result = false; 26357 | } 26358 | else if (0 == (consequent = parse_expression())) 26359 | { 26360 | set_error(make_error( 26361 | parser_error::e_syntax, 26362 | current_token(), 26363 | "ERR036 - Failed to parse consequent for if-statement", 26364 | exprtk_error_location)); 26365 | 26366 | result = false; 26367 | } 26368 | else if (!token_is(token_t::e_comma)) 26369 | { 26370 | set_error(make_error( 26371 | parser_error::e_syntax, 26372 | current_token(), 26373 | "ERR037 - Expected ',' between if-statement consequent and alternative", 26374 | exprtk_error_location)); 26375 | 26376 | result = false; 26377 | } 26378 | else if (0 == (alternative = parse_expression())) 26379 | { 26380 | set_error(make_error( 26381 | parser_error::e_syntax, 26382 | current_token(), 26383 | "ERR038 - Failed to parse alternative for if-statement", 26384 | exprtk_error_location)); 26385 | 26386 | result = false; 26387 | } 26388 | else if (!token_is(token_t::e_rbracket)) 26389 | { 26390 | set_error(make_error( 26391 | parser_error::e_syntax, 26392 | current_token(), 26393 | "ERR039 - Expected ')' at the end of if-statement", 26394 | exprtk_error_location)); 26395 | 26396 | result = false; 26397 | } 26398 | 26399 | #ifndef exprtk_disable_string_capabilities 26400 | if (result) 26401 | { 26402 | const bool consq_is_str = is_generally_string_node(consequent ); 26403 | const bool alter_is_str = is_generally_string_node(alternative); 26404 | 26405 | if (consq_is_str || alter_is_str) 26406 | { 26407 | if (consq_is_str && alter_is_str) 26408 | { 26409 | expression_node_ptr result_node = 26410 | expression_generator_ 26411 | .conditional_string(condition, consequent, alternative); 26412 | 26413 | if (result_node && result_node->valid()) 26414 | { 26415 | return result_node; 26416 | } 26417 | 26418 | set_error(make_error( 26419 | parser_error::e_synthesis, 26420 | current_token(), 26421 | "ERR040 - Failed to synthesize node: conditional_string", 26422 | exprtk_error_location)); 26423 | 26424 | free_node(node_allocator_, result_node); 26425 | return error_node(); 26426 | } 26427 | 26428 | set_error(make_error( 26429 | parser_error::e_syntax, 26430 | current_token(), 26431 | "ERR041 - Return types of if-statement differ: string/non-string", 26432 | exprtk_error_location)); 26433 | 26434 | result = false; 26435 | } 26436 | } 26437 | #endif 26438 | 26439 | if (result) 26440 | { 26441 | const bool consq_is_vec = is_ivector_node(consequent ); 26442 | const bool alter_is_vec = is_ivector_node(alternative); 26443 | 26444 | if (consq_is_vec || alter_is_vec) 26445 | { 26446 | if (consq_is_vec && alter_is_vec) 26447 | { 26448 | return expression_generator_ 26449 | .conditional_vector(condition, consequent, alternative); 26450 | } 26451 | 26452 | set_error(make_error( 26453 | parser_error::e_syntax, 26454 | current_token(), 26455 | "ERR042 - Return types of if-statement differ: vector/non-vector", 26456 | exprtk_error_location)); 26457 | 26458 | result = false; 26459 | } 26460 | } 26461 | 26462 | if (!result) 26463 | { 26464 | free_node(node_allocator_, condition ); 26465 | free_node(node_allocator_, consequent ); 26466 | free_node(node_allocator_, alternative); 26467 | 26468 | return error_node(); 26469 | } 26470 | else 26471 | return expression_generator_ 26472 | .conditional(condition, consequent, alternative); 26473 | } 26474 | 26475 | inline expression_node_ptr parse_conditional_statement_02(expression_node_ptr condition) 26476 | { 26477 | expression_node_ptr consequent = error_node(); 26478 | expression_node_ptr alternative = error_node(); 26479 | 26480 | bool result = true; 26481 | 26482 | if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) 26483 | { 26484 | if (0 == (consequent = parse_multi_sequence("if-statement-01"))) 26485 | { 26486 | set_error(make_error( 26487 | parser_error::e_syntax, 26488 | current_token(), 26489 | "ERR043 - Failed to parse body of consequent for if-statement", 26490 | exprtk_error_location)); 26491 | 26492 | result = false; 26493 | } 26494 | else if 26495 | ( 26496 | !settings_.commutative_check_enabled() && 26497 | !token_is("else",prsrhlpr_t::e_hold) && 26498 | !token_is_loop(prsrhlpr_t::e_hold) && 26499 | !token_is_arithmetic_opr(prsrhlpr_t::e_hold) && 26500 | !token_is_right_bracket (prsrhlpr_t::e_hold) && 26501 | !token_is_ineq_opr (prsrhlpr_t::e_hold) && 26502 | !token_is(token_t::e_ternary,prsrhlpr_t::e_hold) && 26503 | !token_is(token_t::e_eof ,prsrhlpr_t::e_hold) 26504 | ) 26505 | { 26506 | set_error(make_error( 26507 | parser_error::e_syntax, 26508 | current_token(), 26509 | "ERR044 - Expected ';' at the end of the consequent for if-statement (1)", 26510 | exprtk_error_location)); 26511 | 26512 | result = false; 26513 | } 26514 | } 26515 | else 26516 | { 26517 | if ( 26518 | settings_.commutative_check_enabled() && 26519 | token_is(token_t::e_mul,prsrhlpr_t::e_hold) 26520 | ) 26521 | { 26522 | next_token(); 26523 | } 26524 | 26525 | if (0 != (consequent = parse_expression())) 26526 | { 26527 | if (!token_is(token_t::e_eof, prsrhlpr_t::e_hold)) 26528 | { 26529 | set_error(make_error( 26530 | parser_error::e_syntax, 26531 | current_token(), 26532 | "ERR045 - Expected ';' at the end of the consequent for if-statement (2)", 26533 | exprtk_error_location)); 26534 | 26535 | result = false; 26536 | } 26537 | } 26538 | else 26539 | { 26540 | set_error(make_error( 26541 | parser_error::e_syntax, 26542 | current_token(), 26543 | "ERR046 - Failed to parse body of consequent for if-statement", 26544 | exprtk_error_location)); 26545 | 26546 | result = false; 26547 | } 26548 | } 26549 | 26550 | if (result) 26551 | { 26552 | if ( 26553 | details::imatch(current_token().value,"else") || 26554 | (token_is(token_t::e_eof, prsrhlpr_t::e_hold) && peek_token_is("else")) 26555 | ) 26556 | { 26557 | next_token(); 26558 | 26559 | if (details::imatch(current_token().value,"else")) 26560 | { 26561 | next_token(); 26562 | } 26563 | 26564 | if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) 26565 | { 26566 | if (0 == (alternative = parse_multi_sequence("else-statement-01"))) 26567 | { 26568 | set_error(make_error( 26569 | parser_error::e_syntax, 26570 | current_token(), 26571 | "ERR047 - Failed to parse body of the 'else' for if-statement", 26572 | exprtk_error_location)); 26573 | 26574 | result = false; 26575 | } 26576 | } 26577 | else if (details::imatch(current_token().value,"if")) 26578 | { 26579 | if (0 == (alternative = parse_conditional_statement())) 26580 | { 26581 | set_error(make_error( 26582 | parser_error::e_syntax, 26583 | current_token(), 26584 | "ERR048 - Failed to parse body of if-else statement", 26585 | exprtk_error_location)); 26586 | 26587 | result = false; 26588 | } 26589 | } 26590 | else if (0 != (alternative = parse_expression())) 26591 | { 26592 | if ( 26593 | !token_is(token_t::e_ternary , prsrhlpr_t::e_hold) && 26594 | !token_is(token_t::e_rcrlbracket, prsrhlpr_t::e_hold) && 26595 | !token_is(token_t::e_eof) 26596 | ) 26597 | { 26598 | set_error(make_error( 26599 | parser_error::e_syntax, 26600 | current_token(), 26601 | "ERR049 - Expected ';' at the end of the 'else-if' for the if-statement", 26602 | exprtk_error_location)); 26603 | 26604 | result = false; 26605 | } 26606 | } 26607 | else 26608 | { 26609 | set_error(make_error( 26610 | parser_error::e_syntax, 26611 | current_token(), 26612 | "ERR050 - Failed to parse body of the 'else' for if-statement", 26613 | exprtk_error_location)); 26614 | 26615 | result = false; 26616 | } 26617 | } 26618 | } 26619 | 26620 | #ifndef exprtk_disable_string_capabilities 26621 | if (result) 26622 | { 26623 | const bool consq_is_str = is_generally_string_node(consequent ); 26624 | const bool alter_is_str = is_generally_string_node(alternative); 26625 | 26626 | if (consq_is_str || alter_is_str) 26627 | { 26628 | if (consq_is_str && alter_is_str) 26629 | { 26630 | return expression_generator_ 26631 | .conditional_string(condition, consequent, alternative); 26632 | } 26633 | 26634 | set_error(make_error( 26635 | parser_error::e_syntax, 26636 | current_token(), 26637 | "ERR051 - Return types of if-statement differ: string/non-string", 26638 | exprtk_error_location)); 26639 | 26640 | result = false; 26641 | } 26642 | } 26643 | #endif 26644 | 26645 | if (result) 26646 | { 26647 | const bool consq_is_vec = is_ivector_node(consequent ); 26648 | const bool alter_is_vec = is_ivector_node(alternative); 26649 | 26650 | if (consq_is_vec || alter_is_vec) 26651 | { 26652 | if (consq_is_vec && alter_is_vec) 26653 | { 26654 | return expression_generator_ 26655 | .conditional_vector(condition, consequent, alternative); 26656 | } 26657 | 26658 | set_error(make_error( 26659 | parser_error::e_syntax, 26660 | current_token(), 26661 | "ERR052 - Return types of if-statement differ: vector/non-vector", 26662 | exprtk_error_location)); 26663 | 26664 | result = false; 26665 | } 26666 | } 26667 | 26668 | if (!result) 26669 | { 26670 | free_node(node_allocator_, condition ); 26671 | free_node(node_allocator_, consequent ); 26672 | free_node(node_allocator_, alternative); 26673 | 26674 | return error_node(); 26675 | } 26676 | else 26677 | return expression_generator_ 26678 | .conditional(condition, consequent, alternative); 26679 | } 26680 | 26681 | inline expression_node_ptr parse_conditional_statement() 26682 | { 26683 | expression_node_ptr condition = error_node(); 26684 | 26685 | next_token(); 26686 | 26687 | if (!token_is(token_t::e_lbracket)) 26688 | { 26689 | set_error(make_error( 26690 | parser_error::e_syntax, 26691 | current_token(), 26692 | "ERR053 - Expected '(' at start of if-statement, instead got: '" + current_token().value + "'", 26693 | exprtk_error_location)); 26694 | 26695 | return error_node(); 26696 | } 26697 | else if (0 == (condition = parse_expression())) 26698 | { 26699 | set_error(make_error( 26700 | parser_error::e_syntax, 26701 | current_token(), 26702 | "ERR054 - Failed to parse condition for if-statement", 26703 | exprtk_error_location)); 26704 | 26705 | return error_node(); 26706 | } 26707 | else if (token_is(token_t::e_comma,prsrhlpr_t::e_hold)) 26708 | { 26709 | // if (x,y,z) 26710 | return parse_conditional_statement_01(condition); 26711 | } 26712 | else if (token_is(token_t::e_rbracket)) 26713 | { 26714 | /* 26715 | 00. if (x) y; 26716 | 01. if (x) y; else z; 26717 | 02. if (x) y; else {z0; ... zn;} 26718 | 03. if (x) y; else if (z) w; 26719 | 04. if (x) y; else if (z) w; else u; 26720 | 05. if (x) y; else if (z) w; else {u0; ... un;} 26721 | 06. if (x) y; else if (z) {w0; ... wn;} 26722 | 07. if (x) {y0; ... yn;} 26723 | 08. if (x) {y0; ... yn;} else z; 26724 | 09. if (x) {y0; ... yn;} else {z0; ... zn;}; 26725 | 10. if (x) {y0; ... yn;} else if (z) w; 26726 | 11. if (x) {y0; ... yn;} else if (z) w; else u; 26727 | 12. if (x) {y0; ... nex;} else if (z) w; else {u0 ... un;} 26728 | 13. if (x) {y0; ... yn;} else if (z) {w0; ... wn;} 26729 | */ 26730 | return parse_conditional_statement_02(condition); 26731 | } 26732 | 26733 | set_error(make_error( 26734 | parser_error::e_syntax, 26735 | current_token(), 26736 | "ERR055 - Invalid if-statement", 26737 | exprtk_error_location)); 26738 | 26739 | free_node(node_allocator_, condition); 26740 | 26741 | return error_node(); 26742 | } 26743 | 26744 | inline expression_node_ptr parse_ternary_conditional_statement(expression_node_ptr condition) 26745 | { 26746 | // Parse: [condition][?][consequent][:][alternative] 26747 | expression_node_ptr consequent = error_node(); 26748 | expression_node_ptr alternative = error_node(); 26749 | 26750 | bool result = true; 26751 | 26752 | if (0 == condition) 26753 | { 26754 | set_error(make_error( 26755 | parser_error::e_syntax, 26756 | current_token(), 26757 | "ERR056 - Encountered invalid condition branch for ternary if-statement", 26758 | exprtk_error_location)); 26759 | 26760 | return error_node(); 26761 | } 26762 | else if (!token_is(token_t::e_ternary)) 26763 | { 26764 | set_error(make_error( 26765 | parser_error::e_syntax, 26766 | current_token(), 26767 | "ERR057 - Expected '?' after condition of ternary if-statement", 26768 | exprtk_error_location)); 26769 | 26770 | result = false; 26771 | } 26772 | else if (0 == (consequent = parse_expression())) 26773 | { 26774 | set_error(make_error( 26775 | parser_error::e_syntax, 26776 | current_token(), 26777 | "ERR058 - Failed to parse consequent for ternary if-statement", 26778 | exprtk_error_location)); 26779 | 26780 | result = false; 26781 | } 26782 | else if (!token_is(token_t::e_colon)) 26783 | { 26784 | set_error(make_error( 26785 | parser_error::e_syntax, 26786 | current_token(), 26787 | "ERR059 - Expected ':' between ternary if-statement consequent and alternative", 26788 | exprtk_error_location)); 26789 | 26790 | result = false; 26791 | } 26792 | else if (0 == (alternative = parse_expression())) 26793 | { 26794 | set_error(make_error( 26795 | parser_error::e_syntax, 26796 | current_token(), 26797 | "ERR060 - Failed to parse alternative for ternary if-statement", 26798 | exprtk_error_location)); 26799 | 26800 | result = false; 26801 | } 26802 | 26803 | #ifndef exprtk_disable_string_capabilities 26804 | if (result) 26805 | { 26806 | const bool consq_is_str = is_generally_string_node(consequent ); 26807 | const bool alter_is_str = is_generally_string_node(alternative); 26808 | 26809 | if (consq_is_str || alter_is_str) 26810 | { 26811 | if (consq_is_str && alter_is_str) 26812 | { 26813 | return expression_generator_ 26814 | .conditional_string(condition, consequent, alternative); 26815 | } 26816 | 26817 | set_error(make_error( 26818 | parser_error::e_syntax, 26819 | current_token(), 26820 | "ERR061 - Return types of ternary differ: string/non-string", 26821 | exprtk_error_location)); 26822 | 26823 | result = false; 26824 | } 26825 | } 26826 | #endif 26827 | 26828 | if (result) 26829 | { 26830 | const bool consq_is_vec = is_ivector_node(consequent ); 26831 | const bool alter_is_vec = is_ivector_node(alternative); 26832 | 26833 | if (consq_is_vec || alter_is_vec) 26834 | { 26835 | if (consq_is_vec && alter_is_vec) 26836 | { 26837 | return expression_generator_ 26838 | .conditional_vector(condition, consequent, alternative); 26839 | } 26840 | 26841 | set_error(make_error( 26842 | parser_error::e_syntax, 26843 | current_token(), 26844 | "ERR062 - Return types of ternary differ: vector/non-vector", 26845 | exprtk_error_location)); 26846 | 26847 | result = false; 26848 | } 26849 | } 26850 | 26851 | if (!result) 26852 | { 26853 | free_node(node_allocator_, condition ); 26854 | free_node(node_allocator_, consequent ); 26855 | free_node(node_allocator_, alternative); 26856 | 26857 | return error_node(); 26858 | } 26859 | else 26860 | return expression_generator_ 26861 | .conditional(condition, consequent, alternative); 26862 | } 26863 | 26864 | inline expression_node_ptr parse_not_statement() 26865 | { 26866 | if (settings_.logic_disabled("not")) 26867 | { 26868 | set_error(make_error( 26869 | parser_error::e_syntax, 26870 | current_token(), 26871 | "ERR063 - Invalid or disabled logic operation 'not'", 26872 | exprtk_error_location)); 26873 | 26874 | return error_node(); 26875 | } 26876 | 26877 | return parse_base_operation(); 26878 | } 26879 | 26880 | void handle_brkcnt_scope_exit() 26881 | { 26882 | assert(!brkcnt_list_.empty()); 26883 | brkcnt_list_.pop_front(); 26884 | } 26885 | 26886 | inline expression_node_ptr parse_while_loop() 26887 | { 26888 | // Parse: [while][(][test expr][)][{][expression][}] 26889 | expression_node_ptr condition = error_node(); 26890 | expression_node_ptr branch = error_node(); 26891 | expression_node_ptr result_node = error_node(); 26892 | 26893 | bool result = true; 26894 | 26895 | next_token(); 26896 | 26897 | if (!token_is(token_t::e_lbracket)) 26898 | { 26899 | set_error(make_error( 26900 | parser_error::e_syntax, 26901 | current_token(), 26902 | "ERR064 - Expected '(' at start of while-loop condition statement", 26903 | exprtk_error_location)); 26904 | 26905 | return error_node(); 26906 | } 26907 | else if (0 == (condition = parse_expression())) 26908 | { 26909 | set_error(make_error( 26910 | parser_error::e_syntax, 26911 | current_token(), 26912 | "ERR065 - Failed to parse condition for while-loop", 26913 | exprtk_error_location)); 26914 | 26915 | return error_node(); 26916 | } 26917 | else if (!token_is(token_t::e_rbracket)) 26918 | { 26919 | set_error(make_error( 26920 | parser_error::e_syntax, 26921 | current_token(), 26922 | "ERR066 - Expected ')' at end of while-loop condition statement", 26923 | exprtk_error_location)); 26924 | 26925 | result = false; 26926 | } 26927 | 26928 | brkcnt_list_.push_front(false); 26929 | 26930 | if (result) 26931 | { 26932 | scoped_inc_dec sid(state_.parsing_loop_stmt_count); 26933 | 26934 | if (0 == (branch = parse_multi_sequence("while-loop", true))) 26935 | { 26936 | set_error(make_error( 26937 | parser_error::e_syntax, 26938 | current_token(), 26939 | "ERR067 - Failed to parse body of while-loop")); 26940 | result = false; 26941 | } 26942 | else if (0 == (result_node = expression_generator_.while_loop(condition, 26943 | branch, 26944 | brkcnt_list_.front()))) 26945 | { 26946 | set_error(make_error( 26947 | parser_error::e_syntax, 26948 | current_token(), 26949 | "ERR068 - Failed to synthesize while-loop", 26950 | exprtk_error_location)); 26951 | 26952 | result = false; 26953 | } 26954 | } 26955 | 26956 | handle_brkcnt_scope_exit(); 26957 | 26958 | if (!result) 26959 | { 26960 | free_node(node_allocator_, branch ); 26961 | free_node(node_allocator_, condition ); 26962 | free_node(node_allocator_, result_node); 26963 | 26964 | return error_node(); 26965 | } 26966 | 26967 | if (result_node && result_node->valid()) 26968 | { 26969 | return result_node; 26970 | } 26971 | 26972 | set_error(make_error( 26973 | parser_error::e_synthesis, 26974 | current_token(), 26975 | "ERR069 - Failed to synthesize 'valid' while-loop", 26976 | exprtk_error_location)); 26977 | 26978 | free_node(node_allocator_, result_node); 26979 | 26980 | return error_node(); 26981 | } 26982 | 26983 | inline expression_node_ptr parse_repeat_until_loop() 26984 | { 26985 | // Parse: [repeat][{][expression][}][until][(][test expr][)] 26986 | expression_node_ptr condition = error_node(); 26987 | expression_node_ptr branch = error_node(); 26988 | next_token(); 26989 | 26990 | std::vector<expression_node_ptr> arg_list; 26991 | std::vector<bool> side_effect_list; 26992 | 26993 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 26994 | 26995 | brkcnt_list_.push_front(false); 26996 | 26997 | if (details::imatch(current_token().value,"until")) 26998 | { 26999 | next_token(); 27000 | branch = node_allocator_.allocate<details::null_node<T> >(); 27001 | } 27002 | else 27003 | { 27004 | const token_t::token_type separator = token_t::e_eof; 27005 | 27006 | scope_handler sh(*this); 27007 | 27008 | scoped_bool_or_restorer sbr(state_.side_effect_present); 27009 | 27010 | scoped_inc_dec sid(state_.parsing_loop_stmt_count); 27011 | 27012 | for ( ; ; ) 27013 | { 27014 | state_.side_effect_present = false; 27015 | 27016 | expression_node_ptr arg = parse_expression(); 27017 | 27018 | if (0 == arg) 27019 | return error_node(); 27020 | else 27021 | { 27022 | arg_list.push_back(arg); 27023 | side_effect_list.push_back(state_.side_effect_present); 27024 | } 27025 | 27026 | if (details::imatch(current_token().value,"until")) 27027 | { 27028 | next_token(); 27029 | break; 27030 | } 27031 | 27032 | const bool is_next_until = peek_token_is(token_t::e_symbol) && 27033 | peek_token_is("until"); 27034 | 27035 | if (!token_is(separator) && is_next_until) 27036 | { 27037 | set_error(make_error( 27038 | parser_error::e_syntax, 27039 | current_token(), 27040 | "ERR070 - Expected '" + token_t::to_str(separator) + "' in body of repeat until loop", 27041 | exprtk_error_location)); 27042 | 27043 | return error_node(); 27044 | } 27045 | 27046 | if (details::imatch(current_token().value,"until")) 27047 | { 27048 | next_token(); 27049 | break; 27050 | } 27051 | } 27052 | 27053 | branch = simplify(arg_list,side_effect_list); 27054 | 27055 | svd.delete_ptr = (0 == branch); 27056 | 27057 | if (svd.delete_ptr) 27058 | { 27059 | set_error(make_error( 27060 | parser_error::e_syntax, 27061 | current_token(), 27062 | "ERR071 - Failed to parse body of repeat until loop", 27063 | exprtk_error_location)); 27064 | 27065 | return error_node(); 27066 | } 27067 | } 27068 | 27069 | if (!token_is(token_t::e_lbracket)) 27070 | { 27071 | set_error(make_error( 27072 | parser_error::e_syntax, 27073 | current_token(), 27074 | "ERR072 - Expected '(' before condition statement of repeat until loop", 27075 | exprtk_error_location)); 27076 | 27077 | free_node(node_allocator_, branch); 27078 | return error_node(); 27079 | } 27080 | else if (0 == (condition = parse_expression())) 27081 | { 27082 | set_error(make_error( 27083 | parser_error::e_syntax, 27084 | current_token(), 27085 | "ERR073 - Failed to parse condition for repeat until loop", 27086 | exprtk_error_location)); 27087 | 27088 | free_node(node_allocator_, branch); 27089 | return error_node(); 27090 | } 27091 | else if (!token_is(token_t::e_rbracket)) 27092 | { 27093 | set_error(make_error( 27094 | parser_error::e_syntax, 27095 | current_token(), 27096 | "ERR074 - Expected ')' after condition of repeat until loop", 27097 | exprtk_error_location)); 27098 | 27099 | free_node(node_allocator_, branch ); 27100 | free_node(node_allocator_, condition); 27101 | 27102 | return error_node(); 27103 | } 27104 | 27105 | expression_node_ptr result_node = 27106 | expression_generator_ 27107 | .repeat_until_loop( 27108 | condition, 27109 | branch, 27110 | brkcnt_list_.front()); 27111 | 27112 | if (0 == result_node) 27113 | { 27114 | set_error(make_error( 27115 | parser_error::e_syntax, 27116 | current_token(), 27117 | "ERR075 - Failed to synthesize repeat until loop", 27118 | exprtk_error_location)); 27119 | 27120 | free_node(node_allocator_, condition); 27121 | 27122 | return error_node(); 27123 | } 27124 | 27125 | handle_brkcnt_scope_exit(); 27126 | 27127 | if (result_node && result_node->valid()) 27128 | { 27129 | return result_node; 27130 | } 27131 | 27132 | set_error(make_error( 27133 | parser_error::e_synthesis, 27134 | current_token(), 27135 | "ERR076 - Failed to synthesize 'valid' repeat until loop", 27136 | exprtk_error_location)); 27137 | 27138 | free_node(node_allocator_, result_node); 27139 | 27140 | return error_node(); 27141 | } 27142 | 27143 | inline expression_node_ptr parse_for_loop() 27144 | { 27145 | expression_node_ptr initialiser = error_node(); 27146 | expression_node_ptr condition = error_node(); 27147 | expression_node_ptr incrementor = error_node(); 27148 | expression_node_ptr loop_body = error_node(); 27149 | 27150 | scope_element* se = 0; 27151 | bool result = true; 27152 | 27153 | next_token(); 27154 | 27155 | scope_handler sh(*this); 27156 | 27157 | if (!token_is(token_t::e_lbracket)) 27158 | { 27159 | set_error(make_error( 27160 | parser_error::e_syntax, 27161 | current_token(), 27162 | "ERR077 - Expected '(' at start of for-loop", 27163 | exprtk_error_location)); 27164 | 27165 | return error_node(); 27166 | } 27167 | 27168 | if (!token_is(token_t::e_eof)) 27169 | { 27170 | if ( 27171 | !token_is(token_t::e_symbol,prsrhlpr_t::e_hold) && 27172 | details::imatch(current_token().value,"var") 27173 | ) 27174 | { 27175 | next_token(); 27176 | 27177 | if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold)) 27178 | { 27179 | set_error(make_error( 27180 | parser_error::e_syntax, 27181 | current_token(), 27182 | "ERR078 - Expected a variable at the start of initialiser section of for-loop", 27183 | exprtk_error_location)); 27184 | 27185 | return error_node(); 27186 | } 27187 | else if (!peek_token_is(token_t::e_assign)) 27188 | { 27189 | set_error(make_error( 27190 | parser_error::e_syntax, 27191 | current_token(), 27192 | "ERR079 - Expected variable assignment of initialiser section of for-loop", 27193 | exprtk_error_location)); 27194 | 27195 | return error_node(); 27196 | } 27197 | 27198 | const std::string loop_counter_symbol = current_token().value; 27199 | 27200 | se = &sem_.get_element(loop_counter_symbol); 27201 | 27202 | if ((se->name == loop_counter_symbol) && se->active) 27203 | { 27204 | set_error(make_error( 27205 | parser_error::e_syntax, 27206 | current_token(), 27207 | "ERR080 - For-loop variable '" + loop_counter_symbol+ "' is being shadowed by a previous declaration", 27208 | exprtk_error_location)); 27209 | 27210 | return error_node(); 27211 | } 27212 | else if (!symtab_store_.is_variable(loop_counter_symbol)) 27213 | { 27214 | if ( 27215 | !se->active && 27216 | (se->name == loop_counter_symbol) && 27217 | (se->type == scope_element::e_variable) 27218 | ) 27219 | { 27220 | se->active = true; 27221 | se->ref_count++; 27222 | } 27223 | else 27224 | { 27225 | scope_element nse; 27226 | nse.name = loop_counter_symbol; 27227 | nse.active = true; 27228 | nse.ref_count = 1; 27229 | nse.type = scope_element::e_variable; 27230 | nse.depth = state_.scope_depth; 27231 | nse.data = new T(T(0)); 27232 | nse.var_node = node_allocator_.allocate<variable_node_t>(*reinterpret_cast<T*>(nse.data)); 27233 | 27234 | if (!sem_.add_element(nse)) 27235 | { 27236 | set_error(make_error( 27237 | parser_error::e_syntax, 27238 | current_token(), 27239 | "ERR081 - Failed to add new local variable '" + loop_counter_symbol + "' to SEM", 27240 | exprtk_error_location)); 27241 | 27242 | sem_.free_element(nse); 27243 | 27244 | result = false; 27245 | } 27246 | else 27247 | { 27248 | exprtk_debug(("parse_for_loop() - INFO - Added new local variable: %s\n", nse.name.c_str())); 27249 | 27250 | state_.activate_side_effect("parse_for_loop()"); 27251 | } 27252 | } 27253 | } 27254 | } 27255 | 27256 | if (0 == (initialiser = parse_expression())) 27257 | { 27258 | set_error(make_error( 27259 | parser_error::e_syntax, 27260 | current_token(), 27261 | "ERR082 - Failed to parse initialiser of for-loop", 27262 | exprtk_error_location)); 27263 | 27264 | result = false; 27265 | } 27266 | else if (!token_is(token_t::e_eof)) 27267 | { 27268 | set_error(make_error( 27269 | parser_error::e_syntax, 27270 | current_token(), 27271 | "ERR083 - Expected ';' after initialiser of for-loop", 27272 | exprtk_error_location)); 27273 | 27274 | result = false; 27275 | } 27276 | } 27277 | 27278 | if (!token_is(token_t::e_eof)) 27279 | { 27280 | if (0 == (condition = parse_expression())) 27281 | { 27282 | set_error(make_error( 27283 | parser_error::e_syntax, 27284 | current_token(), 27285 | "ERR084 - Failed to parse condition of for-loop", 27286 | exprtk_error_location)); 27287 | 27288 | result = false; 27289 | } 27290 | else if (!token_is(token_t::e_eof)) 27291 | { 27292 | set_error(make_error( 27293 | parser_error::e_syntax, 27294 | current_token(), 27295 | "ERR085 - Expected ';' after condition section of for-loop", 27296 | exprtk_error_location)); 27297 | 27298 | result = false; 27299 | } 27300 | } 27301 | 27302 | if (!token_is(token_t::e_rbracket)) 27303 | { 27304 | if (0 == (incrementor = parse_expression())) 27305 | { 27306 | set_error(make_error( 27307 | parser_error::e_syntax, 27308 | current_token(), 27309 | "ERR086 - Failed to parse incrementor of for-loop", 27310 | exprtk_error_location)); 27311 | 27312 | result = false; 27313 | } 27314 | else if (!token_is(token_t::e_rbracket)) 27315 | { 27316 | set_error(make_error( 27317 | parser_error::e_syntax, 27318 | current_token(), 27319 | "ERR087 - Expected ')' after incrementor section of for-loop", 27320 | exprtk_error_location)); 27321 | 27322 | result = false; 27323 | } 27324 | } 27325 | 27326 | if (result) 27327 | { 27328 | brkcnt_list_.push_front(false); 27329 | 27330 | scoped_inc_dec sid(state_.parsing_loop_stmt_count); 27331 | 27332 | if (0 == (loop_body = parse_multi_sequence("for-loop", true))) 27333 | { 27334 | set_error(make_error( 27335 | parser_error::e_syntax, 27336 | current_token(), 27337 | "ERR088 - Failed to parse body of for-loop", 27338 | exprtk_error_location)); 27339 | 27340 | result = false; 27341 | } 27342 | } 27343 | 27344 | if (!result) 27345 | { 27346 | if (se) 27347 | { 27348 | se->ref_count--; 27349 | } 27350 | 27351 | free_node(node_allocator_, initialiser); 27352 | free_node(node_allocator_, condition ); 27353 | free_node(node_allocator_, incrementor); 27354 | free_node(node_allocator_, loop_body ); 27355 | return error_node(); 27356 | } 27357 | 27358 | expression_node_ptr result_node = 27359 | expression_generator_.for_loop(initialiser, 27360 | condition, 27361 | incrementor, 27362 | loop_body, 27363 | brkcnt_list_.front()); 27364 | handle_brkcnt_scope_exit(); 27365 | 27366 | if (result_node && result_node->valid()) 27367 | { 27368 | return result_node; 27369 | } 27370 | 27371 | set_error(make_error( 27372 | parser_error::e_synthesis, 27373 | current_token(), 27374 | "ERR089 - Failed to synthesize 'valid' for-loop", 27375 | exprtk_error_location)); 27376 | 27377 | free_node(node_allocator_, result_node); 27378 | 27379 | return error_node(); 27380 | } 27381 | 27382 | inline expression_node_ptr parse_switch_statement() 27383 | { 27384 | std::vector<expression_node_ptr> arg_list; 27385 | 27386 | if (!details::imatch(current_token().value,"switch")) 27387 | { 27388 | set_error(make_error( 27389 | parser_error::e_syntax, 27390 | current_token(), 27391 | "ERR090 - Expected keyword 'switch'", 27392 | exprtk_error_location)); 27393 | 27394 | return error_node(); 27395 | } 27396 | 27397 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 27398 | 27399 | next_token(); 27400 | 27401 | if (!token_is(token_t::e_lcrlbracket)) 27402 | { 27403 | set_error(make_error( 27404 | parser_error::e_syntax, 27405 | current_token(), 27406 | "ERR091 - Expected '{' for call to switch statement", 27407 | exprtk_error_location)); 27408 | 27409 | return error_node(); 27410 | } 27411 | 27412 | expression_node_ptr default_statement = error_node(); 27413 | 27414 | scoped_expression_delete defstmt_delete((*this), default_statement); 27415 | 27416 | for ( ; ; ) 27417 | { 27418 | if (details::imatch("case",current_token().value)) 27419 | { 27420 | next_token(); 27421 | 27422 | expression_node_ptr condition = parse_expression(); 27423 | 27424 | if (0 == condition) 27425 | return error_node(); 27426 | else if (!token_is(token_t::e_colon)) 27427 | { 27428 | set_error(make_error( 27429 | parser_error::e_syntax, 27430 | current_token(), 27431 | "ERR092 - Expected ':' for case of switch statement", 27432 | exprtk_error_location)); 27433 | 27434 | free_node(node_allocator_, condition); 27435 | 27436 | return error_node(); 27437 | } 27438 | 27439 | expression_node_ptr consequent = 27440 | (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) ? 27441 | parse_multi_sequence("switch-consequent") : 27442 | parse_expression(); 27443 | 27444 | if (0 == consequent) 27445 | { 27446 | free_node(node_allocator_, condition); 27447 | 27448 | return error_node(); 27449 | } 27450 | else if (!token_is(token_t::e_eof)) 27451 | { 27452 | set_error(make_error( 27453 | parser_error::e_syntax, 27454 | current_token(), 27455 | "ERR093 - Expected ';' at end of case for switch statement", 27456 | exprtk_error_location)); 27457 | 27458 | free_node(node_allocator_, condition ); 27459 | free_node(node_allocator_, consequent); 27460 | 27461 | return error_node(); 27462 | } 27463 | 27464 | // Can we optimise away the case statement? 27465 | if (is_constant_node(condition) && is_false(condition)) 27466 | { 27467 | free_node(node_allocator_, condition ); 27468 | free_node(node_allocator_, consequent); 27469 | } 27470 | else 27471 | { 27472 | arg_list.push_back(condition ); 27473 | arg_list.push_back(consequent); 27474 | } 27475 | 27476 | } 27477 | else if (details::imatch("default",current_token().value)) 27478 | { 27479 | if (0 != default_statement) 27480 | { 27481 | set_error(make_error( 27482 | parser_error::e_syntax, 27483 | current_token(), 27484 | "ERR094 - Multiple default cases for switch statement", 27485 | exprtk_error_location)); 27486 | 27487 | return error_node(); 27488 | } 27489 | 27490 | next_token(); 27491 | 27492 | if (!token_is(token_t::e_colon)) 27493 | { 27494 | set_error(make_error( 27495 | parser_error::e_syntax, 27496 | current_token(), 27497 | "ERR095 - Expected ':' for default of switch statement", 27498 | exprtk_error_location)); 27499 | 27500 | return error_node(); 27501 | } 27502 | 27503 | default_statement = 27504 | (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) ? 27505 | parse_multi_sequence("switch-default"): 27506 | parse_expression(); 27507 | 27508 | if (0 == default_statement) 27509 | return error_node(); 27510 | else if (!token_is(token_t::e_eof)) 27511 | { 27512 | set_error(make_error( 27513 | parser_error::e_syntax, 27514 | current_token(), 27515 | "ERR096 - Expected ';' at end of default for switch statement", 27516 | exprtk_error_location)); 27517 | 27518 | return error_node(); 27519 | } 27520 | } 27521 | else if (token_is(token_t::e_rcrlbracket)) 27522 | break; 27523 | else 27524 | { 27525 | set_error(make_error( 27526 | parser_error::e_syntax, 27527 | current_token(), 27528 | "ERR097 - Expected '}' at end of switch statement", 27529 | exprtk_error_location)); 27530 | 27531 | return error_node(); 27532 | } 27533 | } 27534 | 27535 | const bool default_statement_present = (0 != default_statement); 27536 | 27537 | if (default_statement_present) 27538 | { 27539 | arg_list.push_back(default_statement); 27540 | } 27541 | else 27542 | { 27543 | arg_list.push_back(node_allocator_.allocate_c<literal_node_t>(std::numeric_limits<T>::quiet_NaN())); 27544 | } 27545 | 27546 | expression_node_ptr result = expression_generator_.switch_statement(arg_list, (0 != default_statement)); 27547 | 27548 | svd.delete_ptr = (0 == result); 27549 | defstmt_delete.delete_ptr = (0 == result); 27550 | 27551 | return result; 27552 | } 27553 | 27554 | inline expression_node_ptr parse_multi_switch_statement() 27555 | { 27556 | std::vector<expression_node_ptr> arg_list; 27557 | 27558 | if (!details::imatch(current_token().value,"[*]")) 27559 | { 27560 | set_error(make_error( 27561 | parser_error::e_syntax, 27562 | current_token(), 27563 | "ERR098 - Expected token '[*]'", 27564 | exprtk_error_location)); 27565 | 27566 | return error_node(); 27567 | } 27568 | 27569 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 27570 | 27571 | next_token(); 27572 | 27573 | if (!token_is(token_t::e_lcrlbracket)) 27574 | { 27575 | set_error(make_error( 27576 | parser_error::e_syntax, 27577 | current_token(), 27578 | "ERR099 - Expected '{' for call to [*] statement", 27579 | exprtk_error_location)); 27580 | 27581 | return error_node(); 27582 | } 27583 | 27584 | for ( ; ; ) 27585 | { 27586 | if (!details::imatch("case",current_token().value)) 27587 | { 27588 | set_error(make_error( 27589 | parser_error::e_syntax, 27590 | current_token(), 27591 | "ERR100 - Expected a 'case' statement for multi-switch", 27592 | exprtk_error_location)); 27593 | 27594 | return error_node(); 27595 | } 27596 | 27597 | next_token(); 27598 | 27599 | expression_node_ptr condition = parse_expression(); 27600 | 27601 | if (0 == condition) 27602 | return error_node(); 27603 | 27604 | if (!token_is(token_t::e_colon)) 27605 | { 27606 | set_error(make_error( 27607 | parser_error::e_syntax, 27608 | current_token(), 27609 | "ERR101 - Expected ':' for case of [*] statement", 27610 | exprtk_error_location)); 27611 | 27612 | free_node(node_allocator_, condition); 27613 | 27614 | return error_node(); 27615 | } 27616 | 27617 | expression_node_ptr consequent = 27618 | (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) ? 27619 | parse_multi_sequence("multi-switch-consequent") : 27620 | parse_expression(); 27621 | 27622 | if (0 == consequent) 27623 | { 27624 | free_node(node_allocator_, condition); 27625 | return error_node(); 27626 | } 27627 | 27628 | if (!token_is(token_t::e_eof)) 27629 | { 27630 | set_error(make_error( 27631 | parser_error::e_syntax, 27632 | current_token(), 27633 | "ERR102 - Expected ';' at end of case for [*] statement", 27634 | exprtk_error_location)); 27635 | 27636 | free_node(node_allocator_, condition ); 27637 | free_node(node_allocator_, consequent); 27638 | 27639 | return error_node(); 27640 | } 27641 | 27642 | // Can we optimise away the case statement? 27643 | if (is_constant_node(condition) && is_false(condition)) 27644 | { 27645 | free_node(node_allocator_, condition ); 27646 | free_node(node_allocator_, consequent); 27647 | } 27648 | else 27649 | { 27650 | arg_list.push_back(condition ); 27651 | arg_list.push_back(consequent); 27652 | } 27653 | 27654 | if (token_is(token_t::e_rcrlbracket,prsrhlpr_t::e_hold)) 27655 | { 27656 | break; 27657 | } 27658 | } 27659 | 27660 | if (!token_is(token_t::e_rcrlbracket)) 27661 | { 27662 | set_error(make_error( 27663 | parser_error::e_syntax, 27664 | current_token(), 27665 | "ERR103 - Expected '}' at end of [*] statement", 27666 | exprtk_error_location)); 27667 | 27668 | return error_node(); 27669 | } 27670 | 27671 | const expression_node_ptr result = expression_generator_.multi_switch_statement(arg_list); 27672 | 27673 | svd.delete_ptr = (0 == result); 27674 | 27675 | return result; 27676 | } 27677 | 27678 | inline expression_node_ptr parse_vararg_function() 27679 | { 27680 | std::vector<expression_node_ptr> arg_list; 27681 | 27682 | details::operator_type opt_type = details::e_default; 27683 | const std::string symbol = current_token().value; 27684 | 27685 | if (details::imatch(symbol,"~")) 27686 | { 27687 | next_token(); 27688 | return check_block_statement_closure(parse_multi_sequence()); 27689 | } 27690 | else if (details::imatch(symbol,"[*]")) 27691 | { 27692 | return check_block_statement_closure(parse_multi_switch_statement()); 27693 | } 27694 | else if (details::imatch(symbol, "avg" )) opt_type = details::e_avg ; 27695 | else if (details::imatch(symbol, "mand")) opt_type = details::e_mand; 27696 | else if (details::imatch(symbol, "max" )) opt_type = details::e_max ; 27697 | else if (details::imatch(symbol, "min" )) opt_type = details::e_min ; 27698 | else if (details::imatch(symbol, "mor" )) opt_type = details::e_mor ; 27699 | else if (details::imatch(symbol, "mul" )) opt_type = details::e_prod; 27700 | else if (details::imatch(symbol, "sum" )) opt_type = details::e_sum ; 27701 | else 27702 | { 27703 | set_error(make_error( 27704 | parser_error::e_syntax, 27705 | current_token(), 27706 | "ERR104 - Unsupported built-in vararg function: " + symbol, 27707 | exprtk_error_location)); 27708 | 27709 | return error_node(); 27710 | } 27711 | 27712 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 27713 | 27714 | lodge_symbol(symbol, e_st_function); 27715 | 27716 | next_token(); 27717 | 27718 | if (!token_is(token_t::e_lbracket)) 27719 | { 27720 | set_error(make_error( 27721 | parser_error::e_syntax, 27722 | current_token(), 27723 | "ERR105 - Expected '(' for call to vararg function: " + symbol, 27724 | exprtk_error_location)); 27725 | 27726 | return error_node(); 27727 | } 27728 | 27729 | if (token_is(token_t::e_rbracket)) 27730 | { 27731 | set_error(make_error( 27732 | parser_error::e_syntax, 27733 | current_token(), 27734 | "ERR106 - vararg function: " + symbol + 27735 | " requires at least one input parameter", 27736 | exprtk_error_location)); 27737 | 27738 | return error_node(); 27739 | } 27740 | 27741 | for ( ; ; ) 27742 | { 27743 | expression_node_ptr arg = parse_expression(); 27744 | 27745 | if (0 == arg) 27746 | return error_node(); 27747 | else 27748 | arg_list.push_back(arg); 27749 | 27750 | if (token_is(token_t::e_rbracket)) 27751 | break; 27752 | else if (!token_is(token_t::e_comma)) 27753 | { 27754 | set_error(make_error( 27755 | parser_error::e_syntax, 27756 | current_token(), 27757 | "ERR107 - Expected ',' for call to vararg function: " + symbol, 27758 | exprtk_error_location)); 27759 | 27760 | return error_node(); 27761 | } 27762 | } 27763 | 27764 | const expression_node_ptr result = expression_generator_.vararg_function(opt_type,arg_list); 27765 | 27766 | svd.delete_ptr = (0 == result); 27767 | return result; 27768 | } 27769 | 27770 | #ifndef exprtk_disable_string_capabilities 27771 | inline expression_node_ptr parse_string_range_statement(expression_node_ptr& expression) 27772 | { 27773 | if (!token_is(token_t::e_lsqrbracket)) 27774 | { 27775 | set_error(make_error( 27776 | parser_error::e_syntax, 27777 | current_token(), 27778 | "ERR108 - Expected '[' as start of string range definition", 27779 | exprtk_error_location)); 27780 | 27781 | free_node(node_allocator_, expression); 27782 | 27783 | return error_node(); 27784 | } 27785 | else if (token_is(token_t::e_rsqrbracket)) 27786 | { 27787 | return node_allocator_.allocate<details::string_size_node<T> >(expression); 27788 | } 27789 | 27790 | range_t rp; 27791 | 27792 | if (!parse_range(rp,true)) 27793 | { 27794 | free_node(node_allocator_, expression); 27795 | 27796 | return error_node(); 27797 | } 27798 | 27799 | expression_node_ptr result = expression_generator_(expression,rp); 27800 | 27801 | if (0 == result) 27802 | { 27803 | set_error(make_error( 27804 | parser_error::e_syntax, 27805 | current_token(), 27806 | "ERR109 - Failed to generate string range node", 27807 | exprtk_error_location)); 27808 | 27809 | free_node(node_allocator_, expression); 27810 | rp.free(); 27811 | } 27812 | 27813 | rp.clear(); 27814 | 27815 | if (result && result->valid()) 27816 | { 27817 | return result; 27818 | } 27819 | 27820 | set_error(make_error( 27821 | parser_error::e_synthesis, 27822 | current_token(), 27823 | "ERR110 - Failed to synthesize node: string_range_node", 27824 | exprtk_error_location)); 27825 | 27826 | free_node(node_allocator_, result); 27827 | rp.free(); 27828 | return error_node(); 27829 | } 27830 | #else 27831 | inline expression_node_ptr parse_string_range_statement(expression_node_ptr&) 27832 | { 27833 | return error_node(); 27834 | } 27835 | #endif 27836 | 27837 | inline bool parse_pending_string_rangesize(expression_node_ptr& expression) 27838 | { 27839 | // Allow no more than 100 range calls, eg: s[][][]...[][] 27840 | const std::size_t max_rangesize_parses = 100; 27841 | 27842 | std::size_t i = 0; 27843 | 27844 | while 27845 | ( 27846 | (0 != expression) && 27847 | (i++ < max_rangesize_parses) && 27848 | error_list_.empty() && 27849 | is_generally_string_node(expression) && 27850 | token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold) 27851 | ) 27852 | { 27853 | expression = parse_string_range_statement(expression); 27854 | } 27855 | 27856 | return (i > 1); 27857 | } 27858 | 27859 | inline void parse_pending_vector_index_operator(expression_node_ptr& expression) 27860 | { 27861 | if 27862 | ( 27863 | (0 != expression) && 27864 | error_list_.empty() && 27865 | is_ivector_node(expression) 27866 | ) 27867 | { 27868 | if ( 27869 | settings_.commutative_check_enabled() && 27870 | token_is(token_t::e_mul,prsrhlpr_t::e_hold) && 27871 | peek_token_is(token_t::e_lsqrbracket) 27872 | ) 27873 | { 27874 | token_is(token_t::e_mul); 27875 | token_is(token_t::e_lsqrbracket); 27876 | } 27877 | else if (token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold)) 27878 | { 27879 | token_is(token_t::e_lsqrbracket); 27880 | } 27881 | else if ( 27882 | token_is(token_t::e_rbracket,prsrhlpr_t::e_hold) && 27883 | peek_token_is(token_t::e_lsqrbracket) 27884 | ) 27885 | { 27886 | token_is(token_t::e_rbracket ); 27887 | token_is(token_t::e_lsqrbracket); 27888 | } 27889 | else 27890 | return; 27891 | 27892 | details::vector_interface<T>* vi = dynamic_cast<details::vector_interface<T>*>(expression); 27893 | 27894 | if (vi) 27895 | { 27896 | details::vector_holder<T>& vec = vi->vec()->vec_holder(); 27897 | const std::string vector_name = sem_.get_vector_name(vec.data()); 27898 | expression_node_ptr index = parse_vector_index(vector_name); 27899 | 27900 | if (index) 27901 | { 27902 | expression = synthesize_vector_element(vector_name, &vec, expression, index); 27903 | return; 27904 | } 27905 | } 27906 | 27907 | free_node(node_allocator_, expression); 27908 | expression = error_node(); 27909 | } 27910 | } 27911 | 27912 | template <typename Allocator1, 27913 | typename Allocator2, 27914 | template <typename, typename> class Sequence> 27915 | inline expression_node_ptr simplify(Sequence<expression_node_ptr,Allocator1>& expression_list, 27916 | Sequence<bool,Allocator2>& side_effect_list, 27917 | const bool specialise_on_final_type = false) 27918 | { 27919 | if (expression_list.empty()) 27920 | return error_node(); 27921 | else if (1 == expression_list.size()) 27922 | return expression_list[0]; 27923 | 27924 | Sequence<expression_node_ptr,Allocator1> tmp_expression_list; 27925 | 27926 | exprtk_debug(("simplify() - expression_list.size: %d side_effect_list.size(): %d\n", 27927 | static_cast<int>(expression_list .size()), 27928 | static_cast<int>(side_effect_list.size()))); 27929 | 27930 | bool return_node_present = false; 27931 | 27932 | for (std::size_t i = 0; i < (expression_list.size() - 1); ++i) 27933 | { 27934 | if (is_variable_node(expression_list[i])) 27935 | continue; 27936 | else if ( 27937 | is_return_node (expression_list[i]) || 27938 | is_break_node (expression_list[i]) || 27939 | is_continue_node(expression_list[i]) 27940 | ) 27941 | { 27942 | tmp_expression_list.push_back(expression_list[i]); 27943 | 27944 | // Remove all subexpressions after first short-circuit 27945 | // node has been encountered. 27946 | 27947 | for (std::size_t j = i + 1; j < expression_list.size(); ++j) 27948 | { 27949 | free_node(node_allocator_, expression_list[j]); 27950 | } 27951 | 27952 | return_node_present = true; 27953 | 27954 | break; 27955 | } 27956 | else if ( 27957 | is_constant_node(expression_list[i]) || 27958 | is_null_node (expression_list[i]) || 27959 | !side_effect_list[i] 27960 | ) 27961 | { 27962 | free_node(node_allocator_, expression_list[i]); 27963 | continue; 27964 | } 27965 | else 27966 | tmp_expression_list.push_back(expression_list[i]); 27967 | } 27968 | 27969 | if (!return_node_present) 27970 | { 27971 | tmp_expression_list.push_back(expression_list.back()); 27972 | } 27973 | 27974 | expression_list.swap(tmp_expression_list); 27975 | 27976 | if (tmp_expression_list.size() > expression_list.size()) 27977 | { 27978 | exprtk_debug(("simplify() - Reduced subexpressions from %d to %d\n", 27979 | static_cast<int>(tmp_expression_list.size()), 27980 | static_cast<int>(expression_list .size()))); 27981 | } 27982 | 27983 | if ( 27984 | return_node_present || 27985 | side_effect_list.back() || 27986 | (expression_list.size() > 1) 27987 | ) 27988 | state_.activate_side_effect("simplify()"); 27989 | 27990 | if (1 == expression_list.size()) 27991 | return expression_list[0]; 27992 | else if (specialise_on_final_type && is_generally_string_node(expression_list.back())) 27993 | return expression_generator_.vararg_function(details::e_smulti,expression_list); 27994 | else 27995 | return expression_generator_.vararg_function(details::e_multi,expression_list); 27996 | } 27997 | 27998 | inline expression_node_ptr parse_multi_sequence(const std::string& source = "", 27999 | const bool enforce_crlbrackets = false) 28000 | { 28001 | token_t::token_type open_bracket = token_t::e_lcrlbracket; 28002 | token_t::token_type close_bracket = token_t::e_rcrlbracket; 28003 | token_t::token_type separator = token_t::e_eof; 28004 | 28005 | if (!token_is(open_bracket)) 28006 | { 28007 | if (!enforce_crlbrackets && token_is(token_t::e_lbracket)) 28008 | { 28009 | open_bracket = token_t::e_lbracket; 28010 | close_bracket = token_t::e_rbracket; 28011 | separator = token_t::e_comma; 28012 | } 28013 | else 28014 | { 28015 | set_error(make_error( 28016 | parser_error::e_syntax, 28017 | current_token(), 28018 | "ERR111 - Expected '" + token_t::to_str(open_bracket) + "' for call to multi-sequence" + 28019 | ((!source.empty()) ? std::string(" section of " + source): ""), 28020 | exprtk_error_location)); 28021 | 28022 | return error_node(); 28023 | } 28024 | } 28025 | else if (token_is(close_bracket)) 28026 | { 28027 | return node_allocator_.allocate<details::null_node<T> >(); 28028 | } 28029 | 28030 | std::vector<expression_node_ptr> arg_list; 28031 | std::vector<bool> side_effect_list; 28032 | 28033 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 28034 | 28035 | scope_handler sh(*this); 28036 | 28037 | scoped_bool_or_restorer sbr(state_.side_effect_present); 28038 | 28039 | for ( ; ; ) 28040 | { 28041 | state_.side_effect_present = false; 28042 | 28043 | expression_node_ptr arg = parse_expression(); 28044 | 28045 | if (0 == arg) 28046 | return error_node(); 28047 | else 28048 | { 28049 | arg_list.push_back(arg); 28050 | side_effect_list.push_back(state_.side_effect_present); 28051 | } 28052 | 28053 | if (token_is(close_bracket)) 28054 | break; 28055 | 28056 | const bool is_next_close = peek_token_is(close_bracket); 28057 | 28058 | if (!token_is(separator) && is_next_close) 28059 | { 28060 | set_error(make_error( 28061 | parser_error::e_syntax, 28062 | current_token(), 28063 | "ERR112 - Expected '" + lexer::token::seperator_to_str(separator) + "' for call to multi-sequence section of " + source, 28064 | exprtk_error_location)); 28065 | 28066 | return error_node(); 28067 | } 28068 | 28069 | if (token_is(close_bracket)) 28070 | break; 28071 | } 28072 | 28073 | expression_node_ptr result = simplify(arg_list, side_effect_list, source.empty()); 28074 | 28075 | svd.delete_ptr = (0 == result); 28076 | return result; 28077 | } 28078 | 28079 | inline bool parse_range(range_t& rp, const bool skip_lsqr = false) 28080 | { 28081 | // Examples of valid ranges: 28082 | // 1. [1:5] -> [1,5) 28083 | // 2. [ :5] -> [0,5) 28084 | // 3. [1: ] -> [1,end) 28085 | // 4. [x:y] -> [x,y) where x <= y 28086 | // 5. [x+1:y/2] -> [x+1,y/2) where x+1 <= y/2 28087 | // 6. [ :y] -> [0,y) where 0 <= y 28088 | // 7. [x: ] -> [x,end) where x <= end 28089 | 28090 | rp.clear(); 28091 | 28092 | if (!skip_lsqr && !token_is(token_t::e_lsqrbracket)) 28093 | { 28094 | set_error(make_error( 28095 | parser_error::e_syntax, 28096 | current_token(), 28097 | "ERR113 - Expected '[' for start of range", 28098 | exprtk_error_location)); 28099 | 28100 | return false; 28101 | } 28102 | 28103 | if (token_is(token_t::e_colon)) 28104 | { 28105 | rp.n0_c.first = true; 28106 | rp.n0_c.second = 0; 28107 | rp.cache.first = 0; 28108 | } 28109 | else 28110 | { 28111 | expression_node_ptr r0 = parse_expression(); 28112 | 28113 | if (0 == r0) 28114 | { 28115 | set_error(make_error( 28116 | parser_error::e_syntax, 28117 | current_token(), 28118 | "ERR114 - Failed parse begin section of range", 28119 | exprtk_error_location)); 28120 | 28121 | return false; 28122 | } 28123 | else if (is_constant_node(r0)) 28124 | { 28125 | const T r0_value = r0->value(); 28126 | 28127 | if (r0_value >= T(0)) 28128 | { 28129 | rp.n0_c.first = true; 28130 | rp.n0_c.second = static_cast<std::size_t>(details::numeric::to_int64(r0_value)); 28131 | rp.cache.first = rp.n0_c.second; 28132 | } 28133 | 28134 | free_node(node_allocator_, r0); 28135 | 28136 | if (r0_value < T(0)) 28137 | { 28138 | set_error(make_error( 28139 | parser_error::e_syntax, 28140 | current_token(), 28141 | "ERR115 - Range lower bound less than zero! Constraint: r0 >= 0", 28142 | exprtk_error_location)); 28143 | 28144 | return false; 28145 | } 28146 | } 28147 | else 28148 | { 28149 | rp.n0_e.first = true; 28150 | rp.n0_e.second = r0; 28151 | } 28152 | 28153 | if (!token_is(token_t::e_colon)) 28154 | { 28155 | set_error(make_error( 28156 | parser_error::e_syntax, 28157 | current_token(), 28158 | "ERR116 - Expected ':' for break in range", 28159 | exprtk_error_location)); 28160 | 28161 | rp.free(); 28162 | 28163 | return false; 28164 | } 28165 | } 28166 | 28167 | if (token_is(token_t::e_rsqrbracket)) 28168 | { 28169 | rp.n1_c.first = true; 28170 | rp.n1_c.second = std::numeric_limits<std::size_t>::max(); 28171 | } 28172 | else 28173 | { 28174 | expression_node_ptr r1 = parse_expression(); 28175 | 28176 | if (0 == r1) 28177 | { 28178 | set_error(make_error( 28179 | parser_error::e_syntax, 28180 | current_token(), 28181 | "ERR117 - Failed parse end section of range", 28182 | exprtk_error_location)); 28183 | 28184 | rp.free(); 28185 | 28186 | return false; 28187 | } 28188 | else if (is_constant_node(r1)) 28189 | { 28190 | const T r1_value = r1->value(); 28191 | 28192 | if (r1_value >= T(0)) 28193 | { 28194 | rp.n1_c.first = true; 28195 | rp.n1_c.second = static_cast<std::size_t>(details::numeric::to_int64(r1_value)); 28196 | rp.cache.second = rp.n1_c.second; 28197 | } 28198 | 28199 | free_node(node_allocator_, r1); 28200 | 28201 | if (r1_value < T(0)) 28202 | { 28203 | set_error(make_error( 28204 | parser_error::e_syntax, 28205 | current_token(), 28206 | "ERR118 - Range upper bound less than zero! Constraint: r1 >= 0", 28207 | exprtk_error_location)); 28208 | 28209 | rp.free(); 28210 | 28211 | return false; 28212 | } 28213 | } 28214 | else 28215 | { 28216 | rp.n1_e.first = true; 28217 | rp.n1_e.second = r1; 28218 | } 28219 | 28220 | if (!token_is(token_t::e_rsqrbracket)) 28221 | { 28222 | set_error(make_error( 28223 | parser_error::e_syntax, 28224 | current_token(), 28225 | "ERR119 - Expected ']' for start of range", 28226 | exprtk_error_location)); 28227 | 28228 | rp.free(); 28229 | 28230 | return false; 28231 | } 28232 | } 28233 | 28234 | if (rp.const_range()) 28235 | { 28236 | std::size_t r0 = 0; 28237 | std::size_t r1 = 0; 28238 | 28239 | bool rp_result = false; 28240 | 28241 | try 28242 | { 28243 | rp_result = rp(r0, r1, typename range_t::size_holder_t()); 28244 | } 28245 | catch (std::runtime_error&) 28246 | {} 28247 | 28248 | if (!rp_result || (r0 > r1)) 28249 | { 28250 | set_error(make_error( 28251 | parser_error::e_syntax, 28252 | current_token(), 28253 | "ERR120 - Invalid range, Constraint: r0 <= r1", 28254 | exprtk_error_location)); 28255 | 28256 | return false; 28257 | } 28258 | } 28259 | 28260 | return true; 28261 | } 28262 | 28263 | inline void lodge_symbol(const std::string& symbol, 28264 | const symbol_type st) 28265 | { 28266 | dec_.add_symbol(symbol,st); 28267 | } 28268 | 28269 | #ifndef exprtk_disable_string_capabilities 28270 | inline expression_node_ptr parse_string() 28271 | { 28272 | const std::string symbol = current_token().value; 28273 | 28274 | typedef details::stringvar_node<T>* strvar_node_t; 28275 | 28276 | expression_node_ptr result = error_node(); 28277 | strvar_node_t const_str_node = static_cast<strvar_node_t>(0); 28278 | 28279 | scope_element& se = sem_.get_active_element(symbol); 28280 | 28281 | if (scope_element::e_string == se.type) 28282 | { 28283 | se.active = true; 28284 | result = se.str_node; 28285 | lodge_symbol(symbol, e_st_local_string); 28286 | } 28287 | else 28288 | { 28289 | typedef typename symtab_store::string_context str_ctxt_t; 28290 | str_ctxt_t str_ctx = symtab_store_.get_string_context(symbol); 28291 | 28292 | if ((0 == str_ctx.str_var) || !symtab_store_.is_conststr_stringvar(symbol)) 28293 | { 28294 | set_error(make_error( 28295 | parser_error::e_syntax, 28296 | current_token(), 28297 | "ERR121 - Unknown string symbol", 28298 | exprtk_error_location)); 28299 | 28300 | return error_node(); 28301 | } 28302 | 28303 | assert(str_ctx.str_var != 0); 28304 | assert(str_ctx.symbol_table != 0); 28305 | 28306 | result = str_ctx.str_var; 28307 | 28308 | if (symtab_store_.is_constant_string(symbol)) 28309 | { 28310 | const_str_node = static_cast<strvar_node_t>(result); 28311 | result = expression_generator_(const_str_node->str()); 28312 | } 28313 | else if (symbol_table_t::e_immutable == str_ctx.symbol_table->mutability()) 28314 | { 28315 | lodge_immutable_symbol( 28316 | current_token(), 28317 | make_memory_range(str_ctx.str_var->base(), str_ctx.str_var->size())); 28318 | } 28319 | 28320 | lodge_symbol(symbol, e_st_string); 28321 | } 28322 | 28323 | if (peek_token_is(token_t::e_lsqrbracket)) 28324 | { 28325 | next_token(); 28326 | 28327 | if (peek_token_is(token_t::e_rsqrbracket)) 28328 | { 28329 | next_token(); 28330 | next_token(); 28331 | 28332 | if (const_str_node) 28333 | { 28334 | free_node(node_allocator_, result); 28335 | 28336 | return expression_generator_(T(const_str_node->size())); 28337 | } 28338 | else 28339 | return node_allocator_.allocate<details::stringvar_size_node<T> > 28340 | (static_cast<details::stringvar_node<T>*>(result)->ref()); 28341 | } 28342 | 28343 | range_t rp; 28344 | 28345 | if (!parse_range(rp)) 28346 | { 28347 | free_node(node_allocator_, result); 28348 | 28349 | return error_node(); 28350 | } 28351 | else if (const_str_node) 28352 | { 28353 | free_node(node_allocator_, result); 28354 | result = expression_generator_(const_str_node->ref(),rp); 28355 | } 28356 | else 28357 | result = expression_generator_(static_cast<details::stringvar_node<T>*> 28358 | (result)->ref(), rp); 28359 | 28360 | if (result) 28361 | rp.clear(); 28362 | } 28363 | else 28364 | next_token(); 28365 | 28366 | return result; 28367 | } 28368 | #else 28369 | inline expression_node_ptr parse_string() 28370 | { 28371 | return error_node(); 28372 | } 28373 | #endif 28374 | 28375 | #ifndef exprtk_disable_string_capabilities 28376 | inline expression_node_ptr parse_const_string() 28377 | { 28378 | const std::string const_str = current_token().value; 28379 | expression_node_ptr result = expression_generator_(const_str); 28380 | 28381 | if (peek_token_is(token_t::e_lsqrbracket)) 28382 | { 28383 | next_token(); 28384 | 28385 | if (peek_token_is(token_t::e_rsqrbracket)) 28386 | { 28387 | next_token(); 28388 | next_token(); 28389 | 28390 | free_node(node_allocator_, result); 28391 | 28392 | return expression_generator_(T(const_str.size())); 28393 | } 28394 | 28395 | range_t rp; 28396 | 28397 | if (!parse_range(rp)) 28398 | { 28399 | free_node(node_allocator_, result); 28400 | rp.free(); 28401 | 28402 | return error_node(); 28403 | } 28404 | 28405 | free_node(node_allocator_, result); 28406 | 28407 | if (rp.n1_c.first && (rp.n1_c.second == std::numeric_limits<std::size_t>::max())) 28408 | { 28409 | rp.n1_c.second = const_str.size(); 28410 | rp.cache.second = rp.n1_c.second; 28411 | } 28412 | 28413 | if ( 28414 | (rp.n0_c.first && (rp.n0_c.second >= const_str.size())) || 28415 | (rp.n1_c.first && (rp.n1_c.second > const_str.size())) 28416 | ) 28417 | { 28418 | set_error(make_error( 28419 | parser_error::e_syntax, 28420 | current_token(), 28421 | "ERR122 - Overflow in range for string: '" + const_str + "'[" + 28422 | (rp.n0_c.first ? details::to_str(static_cast<int>(rp.n0_c.second)) : "?") + ":" + 28423 | (rp.n1_c.first ? details::to_str(static_cast<int>(rp.n1_c.second)) : "?") + "]", 28424 | exprtk_error_location)); 28425 | 28426 | rp.free(); 28427 | 28428 | return error_node(); 28429 | } 28430 | 28431 | result = expression_generator_(const_str,rp); 28432 | 28433 | if (result) 28434 | rp.clear(); 28435 | } 28436 | else 28437 | next_token(); 28438 | 28439 | return result; 28440 | } 28441 | #else 28442 | inline expression_node_ptr parse_const_string() 28443 | { 28444 | return error_node(); 28445 | } 28446 | #endif 28447 | 28448 | inline expression_node_ptr parse_vector_index(const std::string& vector_name = "") 28449 | { 28450 | expression_node_ptr index_expr = error_node(); 28451 | 28452 | if (0 == (index_expr = parse_expression())) 28453 | { 28454 | set_error(make_error( 28455 | parser_error::e_syntax, 28456 | current_token(), 28457 | "ERR123 - Failed to parse index for vector: '" + vector_name + "'", 28458 | exprtk_error_location)); 28459 | 28460 | return error_node(); 28461 | } 28462 | else if (!token_is(token_t::e_rsqrbracket)) 28463 | { 28464 | set_error(make_error( 28465 | parser_error::e_syntax, 28466 | current_token(), 28467 | "ERR124 - Expected ']' for index of vector: '" + vector_name + "'", 28468 | exprtk_error_location)); 28469 | 28470 | free_node(node_allocator_, index_expr); 28471 | 28472 | return error_node(); 28473 | } 28474 | 28475 | return index_expr; 28476 | } 28477 | 28478 | inline expression_node_ptr parse_vector() 28479 | { 28480 | const std::string vector_name = current_token().value; 28481 | 28482 | vector_holder_ptr vec = vector_holder_ptr(0); 28483 | 28484 | const scope_element& se = sem_.get_active_element(vector_name); 28485 | 28486 | if ( 28487 | !details::imatch(se.name, vector_name) || 28488 | (se.depth > state_.scope_depth) || 28489 | (scope_element::e_vector != se.type) 28490 | ) 28491 | { 28492 | typedef typename symtab_store::vector_context vec_ctxt_t; 28493 | vec_ctxt_t vec_ctx = symtab_store_.get_vector_context(vector_name); 28494 | 28495 | if (0 == vec_ctx.vector_holder) 28496 | { 28497 | set_error(make_error( 28498 | parser_error::e_syntax, 28499 | current_token(), 28500 | "ERR125 - Symbol '" + vector_name + " not a vector", 28501 | exprtk_error_location)); 28502 | 28503 | return error_node(); 28504 | } 28505 | 28506 | assert(0 != vec_ctx.vector_holder); 28507 | assert(0 != vec_ctx.symbol_table ); 28508 | 28509 | vec = vec_ctx.vector_holder; 28510 | 28511 | if (symbol_table_t::e_immutable == vec_ctx.symbol_table->mutability()) 28512 | { 28513 | lodge_immutable_symbol( 28514 | current_token(), 28515 | make_memory_range(vec->data(), vec->size())); 28516 | } 28517 | } 28518 | else 28519 | { 28520 | vec = se.vec_node; 28521 | } 28522 | 28523 | assert(0 != vec); 28524 | 28525 | next_token(); 28526 | 28527 | if (!token_is(token_t::e_lsqrbracket)) 28528 | { 28529 | return node_allocator_.allocate<vector_node_t>(vec); 28530 | } 28531 | else if (token_is(token_t::e_rsqrbracket)) 28532 | { 28533 | return (vec->rebaseable()) ? 28534 | node_allocator_.allocate<vector_size_node_t>(vec) : 28535 | expression_generator_(T(vec->size())); 28536 | } 28537 | 28538 | expression_node_ptr index_expr = parse_vector_index(vector_name); 28539 | 28540 | if (index_expr) 28541 | { 28542 | expression_node_ptr vec_node = node_allocator_.allocate<vector_node_t>(vec); 28543 | 28544 | return synthesize_vector_element(vector_name, vec, vec_node, index_expr); 28545 | } 28546 | 28547 | return error_node(); 28548 | } 28549 | 28550 | inline expression_node_ptr synthesize_vector_element(const std::string& vector_name, 28551 | vector_holder_ptr vec, 28552 | expression_node_ptr vec_node, 28553 | expression_node_ptr index_expr) 28554 | { 28555 | // Perform compile-time range check 28556 | if (details::is_constant_node(index_expr)) 28557 | { 28558 | const std::size_t index = static_cast<std::size_t>(details::numeric::to_int32(index_expr->value())); 28559 | const std::size_t vec_size = vec->size(); 28560 | 28561 | if (index >= vec_size) 28562 | { 28563 | set_error(make_error( 28564 | parser_error::e_syntax, 28565 | current_token(), 28566 | "ERR126 - Index of " + details::to_str(index) + " out of range for " 28567 | "vector '" + vector_name + "' of size " + details::to_str(vec_size), 28568 | exprtk_error_location)); 28569 | 28570 | free_node(node_allocator_, vec_node ); 28571 | free_node(node_allocator_, index_expr); 28572 | 28573 | return error_node(); 28574 | } 28575 | } 28576 | 28577 | return expression_generator_.vector_element(vector_name, vec, vec_node, index_expr); 28578 | } 28579 | 28580 | inline expression_node_ptr parse_vararg_function_call(ivararg_function<T>* vararg_function, const std::string& vararg_function_name) 28581 | { 28582 | std::vector<expression_node_ptr> arg_list; 28583 | 28584 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 28585 | 28586 | next_token(); 28587 | 28588 | if (token_is(token_t::e_lbracket)) 28589 | { 28590 | if (token_is(token_t::e_rbracket)) 28591 | { 28592 | if (!vararg_function->allow_zero_parameters()) 28593 | { 28594 | set_error(make_error( 28595 | parser_error::e_syntax, 28596 | current_token(), 28597 | "ERR127 - Zero parameter call to vararg function: " 28598 | + vararg_function_name + " not allowed", 28599 | exprtk_error_location)); 28600 | 28601 | return error_node(); 28602 | } 28603 | } 28604 | else 28605 | { 28606 | for ( ; ; ) 28607 | { 28608 | expression_node_ptr arg = parse_expression(); 28609 | 28610 | if (0 == arg) 28611 | return error_node(); 28612 | else 28613 | arg_list.push_back(arg); 28614 | 28615 | if (token_is(token_t::e_rbracket)) 28616 | break; 28617 | else if (!token_is(token_t::e_comma)) 28618 | { 28619 | set_error(make_error( 28620 | parser_error::e_syntax, 28621 | current_token(), 28622 | "ERR128 - Expected ',' for call to vararg function: " 28623 | + vararg_function_name, 28624 | exprtk_error_location)); 28625 | 28626 | return error_node(); 28627 | } 28628 | } 28629 | } 28630 | } 28631 | else if (!vararg_function->allow_zero_parameters()) 28632 | { 28633 | set_error(make_error( 28634 | parser_error::e_syntax, 28635 | current_token(), 28636 | "ERR129 - Zero parameter call to vararg function: " 28637 | + vararg_function_name + " not allowed", 28638 | exprtk_error_location)); 28639 | 28640 | return error_node(); 28641 | } 28642 | 28643 | if (arg_list.size() < vararg_function->min_num_args()) 28644 | { 28645 | set_error(make_error( 28646 | parser_error::e_syntax, 28647 | current_token(), 28648 | "ERR130 - Invalid number of parameters to call to vararg function: " 28649 | + vararg_function_name + ", require at least " 28650 | + details::to_str(static_cast<int>(vararg_function->min_num_args())) + " parameters", 28651 | exprtk_error_location)); 28652 | 28653 | return error_node(); 28654 | } 28655 | else if (arg_list.size() > vararg_function->max_num_args()) 28656 | { 28657 | set_error(make_error( 28658 | parser_error::e_syntax, 28659 | current_token(), 28660 | "ERR131 - Invalid number of parameters to call to vararg function: " 28661 | + vararg_function_name + ", require no more than " 28662 | + details::to_str(static_cast<int>(vararg_function->max_num_args())) + " parameters", 28663 | exprtk_error_location)); 28664 | 28665 | return error_node(); 28666 | } 28667 | 28668 | expression_node_ptr result = expression_generator_.vararg_function_call(vararg_function,arg_list); 28669 | 28670 | svd.delete_ptr = (0 == result); 28671 | 28672 | return result; 28673 | } 28674 | 28675 | class type_checker 28676 | { 28677 | public: 28678 | 28679 | enum return_type_t 28680 | { 28681 | e_overload = ' ', 28682 | e_numeric = 'T', 28683 | e_string = 'S' 28684 | }; 28685 | 28686 | struct function_prototype_t 28687 | { 28688 | return_type_t return_type; 28689 | std::string param_seq; 28690 | }; 28691 | 28692 | typedef parser<T> parser_t; 28693 | typedef std::vector<function_prototype_t> function_definition_list_t; 28694 | 28695 | type_checker(parser_t& p, 28696 | const std::string& func_name, 28697 | const std::string& func_prototypes, 28698 | const return_type_t default_return_type) 28699 | : invalid_state_(true) 28700 | , parser_(p) 28701 | , function_name_(func_name) 28702 | , default_return_type_(default_return_type) 28703 | { 28704 | parse_function_prototypes(func_prototypes); 28705 | } 28706 | 28707 | bool verify(const std::string& param_seq, std::size_t& pseq_index) 28708 | { 28709 | if (function_definition_list_.empty()) 28710 | return true; 28711 | 28712 | std::vector<std::pair<std::size_t,char> > error_list; 28713 | 28714 | for (std::size_t i = 0; i < function_definition_list_.size(); ++i) 28715 | { 28716 | details::char_t diff_value = 0; 28717 | std::size_t diff_index = 0; 28718 | 28719 | const bool result = details::sequence_match(function_definition_list_[i].param_seq, 28720 | param_seq, 28721 | diff_index, diff_value); 28722 | 28723 | if (result) 28724 | { 28725 | pseq_index = i; 28726 | return true; 28727 | } 28728 | else 28729 | error_list.push_back(std::make_pair(diff_index, diff_value)); 28730 | } 28731 | 28732 | if (1 == error_list.size()) 28733 | { 28734 | parser_.set_error(make_error( 28735 | parser_error::e_syntax, 28736 | parser_.current_token(), 28737 | "ERR132 - Failed parameter type check for function '" + function_name_ + "', " 28738 | "Expected '" + function_definition_list_[0].param_seq + 28739 | "' call set: '" + param_seq + "'", 28740 | exprtk_error_location)); 28741 | } 28742 | else 28743 | { 28744 | // find first with largest diff_index; 28745 | std::size_t max_diff_index = 0; 28746 | 28747 | for (std::size_t i = 1; i < error_list.size(); ++i) 28748 | { 28749 | if (error_list[i].first > error_list[max_diff_index].first) 28750 | { 28751 | max_diff_index = i; 28752 | } 28753 | } 28754 | 28755 | parser_.set_error(make_error( 28756 | parser_error::e_syntax, 28757 | parser_.current_token(), 28758 | "ERR133 - Failed parameter type check for function '" + function_name_ + "', " 28759 | "Best match: '" + function_definition_list_[max_diff_index].param_seq + 28760 | "' call set: '" + param_seq + "'", 28761 | exprtk_error_location)); 28762 | } 28763 | 28764 | return false; 28765 | } 28766 | 28767 | std::size_t paramseq_count() const 28768 | { 28769 | return function_definition_list_.size(); 28770 | } 28771 | 28772 | std::string paramseq(const std::size_t& index) const 28773 | { 28774 | return function_definition_list_[index].param_seq; 28775 | } 28776 | 28777 | return_type_t return_type(const std::size_t& index) const 28778 | { 28779 | return function_definition_list_[index].return_type; 28780 | } 28781 | 28782 | bool invalid() const 28783 | { 28784 | return !invalid_state_; 28785 | } 28786 | 28787 | bool allow_zero_parameters() const 28788 | { 28789 | 28790 | for (std::size_t i = 0; i < function_definition_list_.size(); ++i) 28791 | { 28792 | if (std::string::npos != function_definition_list_[i].param_seq.find("Z")) 28793 | { 28794 | return true; 28795 | } 28796 | } 28797 | 28798 | return false; 28799 | } 28800 | 28801 | private: 28802 | 28803 | std::vector<std::string> split_param_seq(const std::string& param_seq, const details::char_t delimiter = '|') const 28804 | { 28805 | std::string::const_iterator current_begin = param_seq.begin(); 28806 | std::string::const_iterator iter = param_seq.begin(); 28807 | 28808 | std::vector<std::string> result; 28809 | 28810 | while (iter != param_seq.end()) 28811 | { 28812 | if (*iter == delimiter) 28813 | { 28814 | result.push_back(std::string(current_begin, iter)); 28815 | current_begin = ++iter; 28816 | } 28817 | else 28818 | ++iter; 28819 | } 28820 | 28821 | if (current_begin != iter) 28822 | { 28823 | result.push_back(std::string(current_begin, iter)); 28824 | } 28825 | 28826 | return result; 28827 | } 28828 | 28829 | inline bool is_valid_token(std::string param_seq, 28830 | function_prototype_t& funcproto) const 28831 | { 28832 | // Determine return type 28833 | funcproto.return_type = default_return_type_; 28834 | 28835 | if (param_seq.size() > 2) 28836 | { 28837 | if (':' == param_seq[1]) 28838 | { 28839 | // Note: Only overloaded igeneric functions can have return 28840 | // type definitions. 28841 | if (type_checker::e_overload != default_return_type_) 28842 | return false; 28843 | 28844 | switch (param_seq[0]) 28845 | { 28846 | case 'T' : funcproto.return_type = type_checker::e_numeric; 28847 | break; 28848 | 28849 | case 'S' : funcproto.return_type = type_checker::e_string; 28850 | break; 28851 | 28852 | default : return false; 28853 | } 28854 | 28855 | param_seq.erase(0,2); 28856 | } 28857 | } 28858 | 28859 | if ( 28860 | (std::string::npos != param_seq.find("?*")) || 28861 | (std::string::npos != param_seq.find("**")) 28862 | ) 28863 | { 28864 | return false; 28865 | } 28866 | else if ( 28867 | (std::string::npos == param_seq.find_first_not_of("STV*?|")) || 28868 | ("Z" == param_seq) 28869 | ) 28870 | { 28871 | funcproto.param_seq = param_seq; 28872 | return true; 28873 | } 28874 | 28875 | return false; 28876 | } 28877 | 28878 | void parse_function_prototypes(const std::string& func_prototypes) 28879 | { 28880 | if (func_prototypes.empty()) 28881 | return; 28882 | 28883 | std::vector<std::string> param_seq_list = split_param_seq(func_prototypes); 28884 | 28885 | typedef std::map<std::string,std::size_t> param_seq_map_t; 28886 | param_seq_map_t param_seq_map; 28887 | 28888 | for (std::size_t i = 0; i < param_seq_list.size(); ++i) 28889 | { 28890 | function_prototype_t func_proto; 28891 | 28892 | if (!is_valid_token(param_seq_list[i], func_proto)) 28893 | { 28894 | invalid_state_ = false; 28895 | 28896 | parser_.set_error(make_error( 28897 | parser_error::e_syntax, 28898 | parser_.current_token(), 28899 | "ERR134 - Invalid parameter sequence of '" + param_seq_list[i] + 28900 | "' for function: " + function_name_, 28901 | exprtk_error_location)); 28902 | return; 28903 | } 28904 | 28905 | param_seq_map_t::const_iterator seq_itr = param_seq_map.find(param_seq_list[i]); 28906 | 28907 | if (param_seq_map.end() != seq_itr) 28908 | { 28909 | invalid_state_ = false; 28910 | 28911 | parser_.set_error(make_error( 28912 | parser_error::e_syntax, 28913 | parser_.current_token(), 28914 | "ERR135 - Function '" + function_name_ + "' has a parameter sequence conflict between " + 28915 | "pseq_idx[" + details::to_str(seq_itr->second) + "] and" + 28916 | "pseq_idx[" + details::to_str(i) + "] " + 28917 | "param seq: " + param_seq_list[i], 28918 | exprtk_error_location)); 28919 | return; 28920 | } 28921 | 28922 | function_definition_list_.push_back(func_proto); 28923 | } 28924 | } 28925 | 28926 | type_checker(const type_checker&) exprtk_delete; 28927 | type_checker& operator=(const type_checker&) exprtk_delete; 28928 | 28929 | bool invalid_state_; 28930 | parser_t& parser_; 28931 | std::string function_name_; 28932 | const return_type_t default_return_type_; 28933 | function_definition_list_t function_definition_list_; 28934 | }; 28935 | 28936 | inline expression_node_ptr parse_generic_function_call(igeneric_function<T>* function, const std::string& function_name) 28937 | { 28938 | std::vector<expression_node_ptr> arg_list; 28939 | 28940 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 28941 | 28942 | next_token(); 28943 | 28944 | std::string param_type_list; 28945 | 28946 | type_checker tc( 28947 | (*this), 28948 | function_name, 28949 | function->parameter_sequence, 28950 | type_checker::e_string); 28951 | 28952 | if (tc.invalid()) 28953 | { 28954 | set_error(make_error( 28955 | parser_error::e_syntax, 28956 | current_token(), 28957 | "ERR136 - Type checker instantiation failure for generic function: " + function_name, 28958 | exprtk_error_location)); 28959 | 28960 | return error_node(); 28961 | } 28962 | 28963 | if (token_is(token_t::e_lbracket)) 28964 | { 28965 | if (token_is(token_t::e_rbracket)) 28966 | { 28967 | if ( 28968 | !function->allow_zero_parameters() && 28969 | !tc .allow_zero_parameters() 28970 | ) 28971 | { 28972 | set_error(make_error( 28973 | parser_error::e_syntax, 28974 | current_token(), 28975 | "ERR137 - Zero parameter call to generic function: " 28976 | + function_name + " not allowed", 28977 | exprtk_error_location)); 28978 | 28979 | return error_node(); 28980 | } 28981 | } 28982 | else 28983 | { 28984 | for ( ; ; ) 28985 | { 28986 | expression_node_ptr arg = parse_expression(); 28987 | 28988 | if (0 == arg) 28989 | return error_node(); 28990 | 28991 | if (is_ivector_node(arg)) 28992 | param_type_list += 'V'; 28993 | else if (is_generally_string_node(arg)) 28994 | param_type_list += 'S'; 28995 | else // Everything else is assumed to be a scalar returning expression 28996 | param_type_list += 'T'; 28997 | 28998 | arg_list.push_back(arg); 28999 | 29000 | if (token_is(token_t::e_rbracket)) 29001 | break; 29002 | else if (!token_is(token_t::e_comma)) 29003 | { 29004 | set_error(make_error( 29005 | parser_error::e_syntax, 29006 | current_token(), 29007 | "ERR138 - Expected ',' for call to generic function: " + function_name, 29008 | exprtk_error_location)); 29009 | 29010 | return error_node(); 29011 | } 29012 | } 29013 | } 29014 | } 29015 | else if ( 29016 | !function->parameter_sequence.empty() && 29017 | function->allow_zero_parameters () && 29018 | !tc .allow_zero_parameters () 29019 | ) 29020 | { 29021 | set_error(make_error( 29022 | parser_error::e_syntax, 29023 | current_token(), 29024 | "ERR139 - Zero parameter call to generic function: " 29025 | + function_name + " not allowed", 29026 | exprtk_error_location)); 29027 | 29028 | return error_node(); 29029 | } 29030 | 29031 | std::size_t param_seq_index = 0; 29032 | 29033 | if ( 29034 | state_.type_check_enabled && 29035 | !tc.verify(param_type_list, param_seq_index) 29036 | ) 29037 | { 29038 | set_error(make_error( 29039 | parser_error::e_syntax, 29040 | current_token(), 29041 | "ERR140 - Invalid input parameter sequence for call to generic function: " + function_name, 29042 | exprtk_error_location)); 29043 | 29044 | return error_node(); 29045 | } 29046 | 29047 | expression_node_ptr result = 29048 | (tc.paramseq_count() <= 1) ? 29049 | expression_generator_ 29050 | .generic_function_call(function, arg_list) : 29051 | expression_generator_ 29052 | .generic_function_call(function, arg_list, param_seq_index); 29053 | 29054 | svd.delete_ptr = (0 == result); 29055 | 29056 | return result; 29057 | } 29058 | 29059 | inline bool parse_igeneric_function_params(std::string& param_type_list, 29060 | std::vector<expression_node_ptr>& arg_list, 29061 | const std::string& function_name, 29062 | igeneric_function<T>* function, 29063 | const type_checker& tc) 29064 | { 29065 | if (token_is(token_t::e_lbracket)) 29066 | { 29067 | if (token_is(token_t::e_rbracket)) 29068 | { 29069 | if ( 29070 | !function->allow_zero_parameters() && 29071 | !tc .allow_zero_parameters() 29072 | ) 29073 | { 29074 | set_error(make_error( 29075 | parser_error::e_syntax, 29076 | current_token(), 29077 | "ERR141 - Zero parameter call to generic function: " 29078 | + function_name + " not allowed", 29079 | exprtk_error_location)); 29080 | 29081 | return false; 29082 | } 29083 | } 29084 | else 29085 | { 29086 | for ( ; ; ) 29087 | { 29088 | expression_node_ptr arg = parse_expression(); 29089 | 29090 | if (0 == arg) 29091 | return false; 29092 | 29093 | if (is_ivector_node(arg)) 29094 | param_type_list += 'V'; 29095 | else if (is_generally_string_node(arg)) 29096 | param_type_list += 'S'; 29097 | else // Everything else is a scalar returning expression 29098 | param_type_list += 'T'; 29099 | 29100 | arg_list.push_back(arg); 29101 | 29102 | if (token_is(token_t::e_rbracket)) 29103 | break; 29104 | else if (!token_is(token_t::e_comma)) 29105 | { 29106 | set_error(make_error( 29107 | parser_error::e_syntax, 29108 | current_token(), 29109 | "ERR142 - Expected ',' for call to string function: " + function_name, 29110 | exprtk_error_location)); 29111 | 29112 | return false; 29113 | } 29114 | } 29115 | } 29116 | 29117 | return true; 29118 | } 29119 | else 29120 | return false; 29121 | } 29122 | 29123 | #ifndef exprtk_disable_string_capabilities 29124 | inline expression_node_ptr parse_string_function_call(igeneric_function<T>* function, const std::string& function_name) 29125 | { 29126 | // Move pass the function name 29127 | next_token(); 29128 | 29129 | std::string param_type_list; 29130 | 29131 | type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_string); 29132 | 29133 | if ( 29134 | (!function->parameter_sequence.empty()) && 29135 | (0 == tc.paramseq_count()) 29136 | ) 29137 | { 29138 | return error_node(); 29139 | } 29140 | 29141 | std::vector<expression_node_ptr> arg_list; 29142 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 29143 | 29144 | if (!parse_igeneric_function_params(param_type_list, arg_list, function_name, function, tc)) 29145 | { 29146 | return error_node(); 29147 | } 29148 | 29149 | std::size_t param_seq_index = 0; 29150 | 29151 | if (!tc.verify(param_type_list, param_seq_index)) 29152 | { 29153 | set_error(make_error( 29154 | parser_error::e_syntax, 29155 | current_token(), 29156 | "ERR143 - Invalid input parameter sequence for call to string function: " + function_name, 29157 | exprtk_error_location)); 29158 | 29159 | return error_node(); 29160 | } 29161 | 29162 | expression_node_ptr result = 29163 | (tc.paramseq_count() <= 1) ? 29164 | expression_generator_ 29165 | .string_function_call(function, arg_list) : 29166 | expression_generator_ 29167 | .string_function_call(function, arg_list, param_seq_index); 29168 | 29169 | svd.delete_ptr = (0 == result); 29170 | 29171 | return result; 29172 | } 29173 | 29174 | inline expression_node_ptr parse_overload_function_call(igeneric_function<T>* function, const std::string& function_name) 29175 | { 29176 | // Move pass the function name 29177 | next_token(); 29178 | 29179 | std::string param_type_list; 29180 | 29181 | type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_overload); 29182 | 29183 | if ( 29184 | (!function->parameter_sequence.empty()) && 29185 | (0 == tc.paramseq_count()) 29186 | ) 29187 | { 29188 | return error_node(); 29189 | } 29190 | 29191 | std::vector<expression_node_ptr> arg_list; 29192 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 29193 | 29194 | if (!parse_igeneric_function_params(param_type_list, arg_list, function_name, function, tc)) 29195 | { 29196 | return error_node(); 29197 | } 29198 | 29199 | std::size_t param_seq_index = 0; 29200 | 29201 | if (!tc.verify(param_type_list, param_seq_index)) 29202 | { 29203 | set_error(make_error( 29204 | parser_error::e_syntax, 29205 | current_token(), 29206 | "ERR144 - Invalid input parameter sequence for call to overloaded function: " + function_name, 29207 | exprtk_error_location)); 29208 | 29209 | return error_node(); 29210 | } 29211 | 29212 | expression_node_ptr result = error_node(); 29213 | 29214 | if (type_checker::e_numeric == tc.return_type(param_seq_index)) 29215 | { 29216 | if (tc.paramseq_count() <= 1) 29217 | result = expression_generator_ 29218 | .generic_function_call(function, arg_list); 29219 | else 29220 | result = expression_generator_ 29221 | .generic_function_call(function, arg_list, param_seq_index); 29222 | } 29223 | else if (type_checker::e_string == tc.return_type(param_seq_index)) 29224 | { 29225 | if (tc.paramseq_count() <= 1) 29226 | result = expression_generator_ 29227 | .string_function_call(function, arg_list); 29228 | else 29229 | result = expression_generator_ 29230 | .string_function_call(function, arg_list, param_seq_index); 29231 | } 29232 | else 29233 | { 29234 | set_error(make_error( 29235 | parser_error::e_syntax, 29236 | current_token(), 29237 | "ERR145 - Invalid return type for call to overloaded function: " + function_name, 29238 | exprtk_error_location)); 29239 | } 29240 | 29241 | svd.delete_ptr = (0 == result); 29242 | return result; 29243 | } 29244 | #endif 29245 | 29246 | template <typename Type, std::size_t NumberOfParameters> 29247 | struct parse_special_function_impl 29248 | { 29249 | static inline expression_node_ptr process(parser<Type>& p, const details::operator_type opt_type, const std::string& sf_name) 29250 | { 29251 | expression_node_ptr branch[NumberOfParameters]; 29252 | expression_node_ptr result = error_node(); 29253 | 29254 | std::fill_n(branch, NumberOfParameters, reinterpret_cast<expression_node_ptr>(0)); 29255 | 29256 | scoped_delete<expression_node_t,NumberOfParameters> sd(p,branch); 29257 | 29258 | p.next_token(); 29259 | 29260 | if (!p.token_is(token_t::e_lbracket)) 29261 | { 29262 | p.set_error(make_error( 29263 | parser_error::e_syntax, 29264 | p.current_token(), 29265 | "ERR146 - Expected '(' for special function '" + sf_name + "'", 29266 | exprtk_error_location)); 29267 | 29268 | return error_node(); 29269 | } 29270 | 29271 | for (std::size_t i = 0; i < NumberOfParameters; ++i) 29272 | { 29273 | branch[i] = p.parse_expression(); 29274 | 29275 | if (0 == branch[i]) 29276 | { 29277 | return p.error_node(); 29278 | } 29279 | else if (i < (NumberOfParameters - 1)) 29280 | { 29281 | if (!p.token_is(token_t::e_comma)) 29282 | { 29283 | p.set_error(make_error( 29284 | parser_error::e_syntax, 29285 | p.current_token(), 29286 | "ERR147 - Expected ',' before next parameter of special function '" + sf_name + "'", 29287 | exprtk_error_location)); 29288 | 29289 | return p.error_node(); 29290 | } 29291 | } 29292 | } 29293 | 29294 | if (!p.token_is(token_t::e_rbracket)) 29295 | { 29296 | p.set_error(make_error( 29297 | parser_error::e_syntax, 29298 | p.current_token(), 29299 | "ERR148 - Invalid number of parameters for special function '" + sf_name + "'", 29300 | exprtk_error_location)); 29301 | 29302 | return p.error_node(); 29303 | } 29304 | else 29305 | result = p.expression_generator_.special_function(opt_type,branch); 29306 | 29307 | sd.delete_ptr = (0 == result); 29308 | 29309 | return result; 29310 | } 29311 | }; 29312 | 29313 | inline expression_node_ptr parse_special_function() 29314 | { 29315 | const std::string sf_name = current_token().value; 29316 | 29317 | // Expect: $fDD(expr0,expr1,expr2) or $fDD(expr0,expr1,expr2,expr3) 29318 | if ( 29319 | !details::is_digit(sf_name[2]) || 29320 | !details::is_digit(sf_name[3]) 29321 | ) 29322 | { 29323 | set_error(make_error( 29324 | parser_error::e_token, 29325 | current_token(), 29326 | "ERR149 - Invalid special function[1]: " + sf_name, 29327 | exprtk_error_location)); 29328 | 29329 | return error_node(); 29330 | } 29331 | 29332 | const int id = (sf_name[2] - '0') * 10 + 29333 | (sf_name[3] - '0'); 29334 | 29335 | if (id >= details::e_sffinal) 29336 | { 29337 | set_error(make_error( 29338 | parser_error::e_token, 29339 | current_token(), 29340 | "ERR150 - Invalid special function[2]: " + sf_name, 29341 | exprtk_error_location)); 29342 | 29343 | return error_node(); 29344 | } 29345 | 29346 | const int sf_3_to_4 = details::e_sf48; 29347 | const details::operator_type opt_type = details::operator_type(id + 1000); 29348 | const std::size_t NumberOfParameters = (id < (sf_3_to_4 - 1000)) ? 3U : 4U; 29349 | 29350 | switch (NumberOfParameters) 29351 | { 29352 | case 3 : return parse_special_function_impl<T,3>::process((*this), opt_type, sf_name); 29353 | case 4 : return parse_special_function_impl<T,4>::process((*this), opt_type, sf_name); 29354 | default : return error_node(); 29355 | } 29356 | } 29357 | 29358 | inline expression_node_ptr parse_null_statement() 29359 | { 29360 | next_token(); 29361 | return node_allocator_.allocate<details::null_node<T> >(); 29362 | } 29363 | 29364 | #ifndef exprtk_disable_break_continue 29365 | inline expression_node_ptr parse_break_statement() 29366 | { 29367 | if (state_.parsing_break_stmt) 29368 | { 29369 | set_error(make_error( 29370 | parser_error::e_syntax, 29371 | current_token(), 29372 | "ERR151 - Invoking 'break' within a break call is not allowed", 29373 | exprtk_error_location)); 29374 | 29375 | return error_node(); 29376 | } 29377 | else if (0 == state_.parsing_loop_stmt_count) 29378 | { 29379 | set_error(make_error( 29380 | parser_error::e_syntax, 29381 | current_token(), 29382 | "ERR152 - Invalid use of 'break', allowed only in the scope of a loop", 29383 | exprtk_error_location)); 29384 | 29385 | return error_node(); 29386 | } 29387 | 29388 | scoped_bool_negator sbn(state_.parsing_break_stmt); 29389 | 29390 | if (!brkcnt_list_.empty()) 29391 | { 29392 | next_token(); 29393 | 29394 | brkcnt_list_.front() = true; 29395 | 29396 | expression_node_ptr return_expr = error_node(); 29397 | 29398 | if (token_is(token_t::e_lsqrbracket)) 29399 | { 29400 | if (0 == (return_expr = parse_expression())) 29401 | { 29402 | set_error(make_error( 29403 | parser_error::e_syntax, 29404 | current_token(), 29405 | "ERR153 - Failed to parse return expression for 'break' statement", 29406 | exprtk_error_location)); 29407 | 29408 | return error_node(); 29409 | } 29410 | else if (!token_is(token_t::e_rsqrbracket)) 29411 | { 29412 | set_error(make_error( 29413 | parser_error::e_syntax, 29414 | current_token(), 29415 | "ERR154 - Expected ']' at the completion of break's return expression", 29416 | exprtk_error_location)); 29417 | 29418 | free_node(node_allocator_, return_expr); 29419 | 29420 | return error_node(); 29421 | } 29422 | } 29423 | 29424 | state_.activate_side_effect("parse_break_statement()"); 29425 | 29426 | return node_allocator_.allocate<details::break_node<T> >(return_expr); 29427 | } 29428 | else 29429 | { 29430 | set_error(make_error( 29431 | parser_error::e_syntax, 29432 | current_token(), 29433 | "ERR155 - Invalid use of 'break', allowed only in the scope of a loop", 29434 | exprtk_error_location)); 29435 | } 29436 | 29437 | return error_node(); 29438 | } 29439 | 29440 | inline expression_node_ptr parse_continue_statement() 29441 | { 29442 | if (0 == state_.parsing_loop_stmt_count) 29443 | { 29444 | set_error(make_error( 29445 | parser_error::e_syntax, 29446 | current_token(), 29447 | "ERR156 - Invalid use of 'continue', allowed only in the scope of a loop", 29448 | exprtk_error_location)); 29449 | 29450 | return error_node(); 29451 | } 29452 | else 29453 | { 29454 | next_token(); 29455 | 29456 | brkcnt_list_.front() = true; 29457 | state_.activate_side_effect("parse_continue_statement()"); 29458 | 29459 | return node_allocator_.allocate<details::continue_node<T> >(); 29460 | } 29461 | } 29462 | #endif 29463 | 29464 | inline expression_node_ptr parse_define_vector_statement(const std::string& vec_name) 29465 | { 29466 | expression_node_ptr size_expression_node = error_node(); 29467 | 29468 | if (!token_is(token_t::e_lsqrbracket)) 29469 | { 29470 | set_error(make_error( 29471 | parser_error::e_syntax, 29472 | current_token(), 29473 | "ERR157 - Expected '[' as part of vector size definition", 29474 | exprtk_error_location)); 29475 | 29476 | return error_node(); 29477 | } 29478 | else if (0 == (size_expression_node = parse_expression())) 29479 | { 29480 | set_error(make_error( 29481 | parser_error::e_syntax, 29482 | current_token(), 29483 | "ERR158 - Failed to determine size of vector '" + vec_name + "'", 29484 | exprtk_error_location)); 29485 | 29486 | return error_node(); 29487 | } 29488 | else if (!is_constant_node(size_expression_node)) 29489 | { 29490 | const bool is_rebaseble_vector = 29491 | (size_expression_node->type() == details::expression_node<T>::e_vecsize) && 29492 | static_cast<details::vector_size_node<T>*>(size_expression_node)->vec_holder()->rebaseable(); 29493 | 29494 | free_node(node_allocator_, size_expression_node); 29495 | 29496 | const std::string error_msg = (is_rebaseble_vector) ? 29497 | std::string("Rebasable/Resizable vector cannot be used to define the size of vector") : 29498 | std::string("Expected a constant literal number as size of vector"); 29499 | set_error(make_error( 29500 | parser_error::e_syntax, 29501 | current_token(), 29502 | "ERR159 - " + error_msg + " '" + vec_name + "'", 29503 | exprtk_error_location)); 29504 | 29505 | return error_node(); 29506 | } 29507 | 29508 | const T vector_size = size_expression_node->value(); 29509 | 29510 | free_node(node_allocator_, size_expression_node); 29511 | 29512 | const std::size_t max_vector_size = settings_.max_local_vector_size(); 29513 | 29514 | if ( 29515 | (vector_size <= T(0)) || 29516 | std::not_equal_to<T>() 29517 | (T(0),vector_size - details::numeric::trunc(vector_size)) || 29518 | (static_cast<std::size_t>(vector_size) > max_vector_size) 29519 | ) 29520 | { 29521 | set_error(make_error( 29522 | parser_error::e_syntax, 29523 | current_token(), 29524 | "ERR160 - Invalid vector size. Must be an integer in the " 29525 | "range [0," + details::to_str(static_cast<std::size_t>(max_vector_size)) + "], size: " + 29526 | details::to_str(details::numeric::to_int32(vector_size)), 29527 | exprtk_error_location)); 29528 | 29529 | return error_node(); 29530 | } 29531 | 29532 | typename symbol_table_t::vector_holder_ptr vec_holder = typename symbol_table_t::vector_holder_ptr(0); 29533 | 29534 | const std::size_t vec_size = static_cast<std::size_t>(details::numeric::to_int32(vector_size)); 29535 | const std::size_t predicted_total_lclsymb_size = sizeof(T) * vec_size + sem_.total_local_symb_size_bytes(); 29536 | 29537 | if (predicted_total_lclsymb_size > settings().max_total_local_symbol_size_bytes()) 29538 | { 29539 | set_error(make_error( 29540 | parser_error::e_syntax, 29541 | current_token(), 29542 | "ERR161 - Adding vector '" + vec_name + "' of size " + details::to_str(vec_size) + " bytes " 29543 | "will exceed max total local symbol size of: " + details::to_str(settings().max_total_local_symbol_size_bytes()) + " bytes, " 29544 | "current total size: " + details::to_str(sem_.total_local_symb_size_bytes()) + " bytes", 29545 | exprtk_error_location)); 29546 | 29547 | return error_node(); 29548 | } 29549 | 29550 | scope_element& se = sem_.get_element(vec_name); 29551 | 29552 | if (se.name == vec_name) 29553 | { 29554 | if (se.active) 29555 | { 29556 | set_error(make_error( 29557 | parser_error::e_syntax, 29558 | current_token(), 29559 | "ERR162 - Illegal redefinition of local vector: '" + vec_name + "'", 29560 | exprtk_error_location)); 29561 | 29562 | return error_node(); 29563 | } 29564 | else if ( 29565 | (se.size == vec_size) && 29566 | (scope_element::e_vector == se.type) 29567 | ) 29568 | { 29569 | vec_holder = se.vec_node; 29570 | se.active = true; 29571 | se.depth = state_.scope_depth; 29572 | se.ref_count++; 29573 | } 29574 | } 29575 | 29576 | if (0 == vec_holder) 29577 | { 29578 | scope_element nse; 29579 | nse.name = vec_name; 29580 | nse.active = true; 29581 | nse.ref_count = 1; 29582 | nse.type = scope_element::e_vector; 29583 | nse.depth = state_.scope_depth; 29584 | nse.size = vec_size; 29585 | nse.data = new T[vec_size]; 29586 | nse.vec_node = new typename scope_element::vector_holder_t(reinterpret_cast<T*>(nse.data),nse.size); 29587 | 29588 | details::set_zero_value(reinterpret_cast<T*>(nse.data),vec_size); 29589 | 29590 | if (!sem_.add_element(nse)) 29591 | { 29592 | set_error(make_error( 29593 | parser_error::e_syntax, 29594 | current_token(), 29595 | "ERR163 - Failed to add new local vector '" + vec_name + "' to SEM", 29596 | exprtk_error_location)); 29597 | 29598 | sem_.free_element(nse); 29599 | 29600 | return error_node(); 29601 | } 29602 | 29603 | assert(sem_.total_local_symb_size_bytes() <= settings().max_total_local_symbol_size_bytes()); 29604 | 29605 | vec_holder = nse.vec_node; 29606 | 29607 | exprtk_debug(("parse_define_vector_statement() - INFO - Added new local vector: %s[%d]\n", 29608 | nse.name.c_str(), 29609 | static_cast<int>(nse.size))); 29610 | } 29611 | 29612 | state_.activate_side_effect("parse_define_vector_statement()"); 29613 | 29614 | lodge_symbol(vec_name, e_st_local_vector); 29615 | 29616 | std::vector<expression_node_ptr> vec_initilizer_list; 29617 | 29618 | scoped_vec_delete<expression_node_t> svd((*this), vec_initilizer_list); 29619 | 29620 | bool single_value_initialiser = false; 29621 | bool range_value_initialiser = false; 29622 | bool vec_to_vec_initialiser = false; 29623 | bool null_initialisation = false; 29624 | 29625 | if (!token_is(token_t::e_rsqrbracket)) 29626 | { 29627 | set_error(make_error( 29628 | parser_error::e_syntax, 29629 | current_token(), 29630 | "ERR164 - Expected ']' as part of vector size definition", 29631 | exprtk_error_location)); 29632 | 29633 | return error_node(); 29634 | } 29635 | else if (!token_is(token_t::e_eof, prsrhlpr_t::e_hold)) 29636 | { 29637 | if (!token_is(token_t::e_assign)) 29638 | { 29639 | set_error(make_error( 29640 | parser_error::e_syntax, 29641 | current_token(), 29642 | "ERR165 - Expected ':=' as part of vector definition", 29643 | exprtk_error_location)); 29644 | 29645 | return error_node(); 29646 | } 29647 | else if (token_is(token_t::e_lsqrbracket)) 29648 | { 29649 | expression_node_ptr initialiser_component = parse_expression(); 29650 | 29651 | if (0 == initialiser_component) 29652 | { 29653 | set_error(make_error( 29654 | parser_error::e_syntax, 29655 | current_token(), 29656 | "ERR166 - Failed to parse first component of vector initialiser for vector: " + vec_name, 29657 | exprtk_error_location)); 29658 | 29659 | return error_node(); 29660 | } 29661 | 29662 | vec_initilizer_list.push_back(initialiser_component); 29663 | 29664 | if (token_is(token_t::e_colon)) 29665 | { 29666 | initialiser_component = parse_expression(); 29667 | 29668 | if (0 == initialiser_component) 29669 | { 29670 | set_error(make_error( 29671 | parser_error::e_syntax, 29672 | current_token(), 29673 | "ERR167 - Failed to parse second component of vector initialiser for vector: " + vec_name, 29674 | exprtk_error_location)); 29675 | 29676 | return error_node(); 29677 | } 29678 | 29679 | vec_initilizer_list.push_back(initialiser_component); 29680 | } 29681 | 29682 | if (!token_is(token_t::e_rsqrbracket)) 29683 | { 29684 | set_error(make_error( 29685 | parser_error::e_syntax, 29686 | current_token(), 29687 | "ERR168 - Expected ']' to close single value vector initialiser", 29688 | exprtk_error_location)); 29689 | 29690 | return error_node(); 29691 | } 29692 | 29693 | switch (vec_initilizer_list.size()) 29694 | { 29695 | case 1 : single_value_initialiser = true; break; 29696 | case 2 : range_value_initialiser = true; break; 29697 | } 29698 | } 29699 | else if (!token_is(token_t::e_lcrlbracket)) 29700 | { 29701 | expression_node_ptr initialiser = error_node(); 29702 | 29703 | // Is this a vector to vector assignment and initialisation? 29704 | if (token_t::e_symbol == current_token().type) 29705 | { 29706 | // Is it a locally defined vector? 29707 | const scope_element& lcl_se = sem_.get_active_element(current_token().value); 29708 | 29709 | if (scope_element::e_vector == lcl_se.type) 29710 | { 29711 | if (0 != (initialiser = parse_expression())) 29712 | vec_initilizer_list.push_back(initialiser); 29713 | else 29714 | return error_node(); 29715 | } 29716 | // Are we dealing with a user defined vector? 29717 | else if (symtab_store_.is_vector(current_token().value)) 29718 | { 29719 | lodge_symbol(current_token().value, e_st_vector); 29720 | 29721 | if (0 != (initialiser = parse_expression())) 29722 | vec_initilizer_list.push_back(initialiser); 29723 | else 29724 | return error_node(); 29725 | } 29726 | // Are we dealing with a null initialisation vector definition? 29727 | else if (token_is(token_t::e_symbol,"null")) 29728 | null_initialisation = true; 29729 | } 29730 | 29731 | if (!null_initialisation) 29732 | { 29733 | if (0 == initialiser) 29734 | { 29735 | set_error(make_error( 29736 | parser_error::e_syntax, 29737 | current_token(), 29738 | "ERR169 - Expected '{' as part of vector initialiser list", 29739 | exprtk_error_location)); 29740 | 29741 | return error_node(); 29742 | } 29743 | else 29744 | vec_to_vec_initialiser = true; 29745 | } 29746 | } 29747 | else if (!token_is(token_t::e_rcrlbracket)) 29748 | { 29749 | for ( ; ; ) 29750 | { 29751 | expression_node_ptr initialiser = parse_expression(); 29752 | 29753 | if (0 == initialiser) 29754 | { 29755 | set_error(make_error( 29756 | parser_error::e_syntax, 29757 | current_token(), 29758 | "ERR170 - Expected '{' as part of vector initialiser list", 29759 | exprtk_error_location)); 29760 | 29761 | return error_node(); 29762 | } 29763 | else 29764 | vec_initilizer_list.push_back(initialiser); 29765 | 29766 | if (token_is(token_t::e_rcrlbracket)) 29767 | break; 29768 | 29769 | const bool is_next_close = peek_token_is(token_t::e_rcrlbracket); 29770 | 29771 | if (!token_is(token_t::e_comma) && is_next_close) 29772 | { 29773 | set_error(make_error( 29774 | parser_error::e_syntax, 29775 | current_token(), 29776 | "ERR171 - Expected ',' between vector initialisers", 29777 | exprtk_error_location)); 29778 | 29779 | return error_node(); 29780 | } 29781 | 29782 | if (token_is(token_t::e_rcrlbracket)) 29783 | break; 29784 | } 29785 | } 29786 | 29787 | if ( 29788 | !token_is(token_t::e_rbracket , prsrhlpr_t::e_hold) && 29789 | !token_is(token_t::e_rcrlbracket, prsrhlpr_t::e_hold) && 29790 | !token_is(token_t::e_rsqrbracket, prsrhlpr_t::e_hold) 29791 | ) 29792 | { 29793 | if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold)) 29794 | { 29795 | set_error(make_error( 29796 | parser_error::e_syntax, 29797 | current_token(), 29798 | "ERR172 - Expected ';' at end of vector definition", 29799 | exprtk_error_location)); 29800 | 29801 | return error_node(); 29802 | } 29803 | } 29804 | 29805 | if ( 29806 | !single_value_initialiser && 29807 | !range_value_initialiser && 29808 | (T(vec_initilizer_list.size()) > vector_size) 29809 | ) 29810 | { 29811 | set_error(make_error( 29812 | parser_error::e_syntax, 29813 | current_token(), 29814 | "ERR173 - Initialiser list larger than the number of elements in the vector: '" + vec_name + "'", 29815 | exprtk_error_location)); 29816 | 29817 | return error_node(); 29818 | } 29819 | } 29820 | 29821 | expression_node_ptr result = error_node(); 29822 | 29823 | if ( 29824 | (vec_initilizer_list.size() == 1) && 29825 | single_value_initialiser 29826 | ) 29827 | { 29828 | if (details::is_constant_node(vec_initilizer_list[0])) 29829 | { 29830 | // vector_init_zero_value_node var v[10] := [0] 29831 | if (T(0) == vec_initilizer_list[0]->value()) 29832 | { 29833 | result = node_allocator_ 29834 | .allocate<details::vector_init_zero_value_node<T> >( 29835 | (*vec_holder)[0], 29836 | vec_size, 29837 | vec_initilizer_list); 29838 | } 29839 | else 29840 | { 29841 | // vector_init_single_constvalue_node var v[10] := [123] 29842 | result = node_allocator_ 29843 | .allocate<details::vector_init_single_constvalue_node<T> >( 29844 | (*vec_holder)[0], 29845 | vec_size, 29846 | vec_initilizer_list); 29847 | } 29848 | } 29849 | else 29850 | { 29851 | // vector_init_single_value_node var v[10] := [123 + (x / y)] 29852 | result = node_allocator_ 29853 | .allocate<details::vector_init_single_value_node<T> >( 29854 | (*vec_holder)[0], 29855 | vec_size, 29856 | vec_initilizer_list); 29857 | } 29858 | } 29859 | else if ( 29860 | (vec_initilizer_list.size() == 2) && 29861 | range_value_initialiser 29862 | ) 29863 | { 29864 | bool base_const = details::is_constant_node(vec_initilizer_list[0]); 29865 | bool inc_const = details::is_constant_node(vec_initilizer_list[1]); 29866 | 29867 | if (base_const && inc_const) 29868 | { 29869 | // vector_init_single_value_node var v[10] := [1 : 3.5] 29870 | result = node_allocator_ 29871 | .allocate<details::vector_init_iota_constconst_node<T> >( 29872 | (*vec_holder)[0], 29873 | vec_size, 29874 | vec_initilizer_list); 29875 | } 29876 | else if (base_const && !inc_const) 29877 | { 29878 | // vector_init_single_value_node var v[10] := [1 : x + y] 29879 | result = node_allocator_ 29880 | .allocate<details::vector_init_iota_constnconst_node<T> >( 29881 | (*vec_holder)[0], 29882 | vec_size, 29883 | vec_initilizer_list); 29884 | } 29885 | else if (!base_const && inc_const) 29886 | { 29887 | // vector_init_single_value_node var v[10] := [x + y : 3] 29888 | result = node_allocator_ 29889 | .allocate<details::vector_init_iota_nconstconst_node<T> >( 29890 | (*vec_holder)[0], 29891 | vec_size, 29892 | vec_initilizer_list); 29893 | } 29894 | else if (!base_const && !inc_const) 29895 | { 29896 | // vector_init_single_value_node var v[10] := [x + y : z / w] 29897 | result = node_allocator_ 29898 | .allocate<details::vector_init_iota_nconstnconst_node<T> >( 29899 | (*vec_holder)[0], 29900 | vec_size, 29901 | vec_initilizer_list); 29902 | } 29903 | } 29904 | else if (null_initialisation) 29905 | result = expression_generator_(T(0.0)); 29906 | else if (vec_to_vec_initialiser) 29907 | { 29908 | expression_node_ptr vec_node = node_allocator_.allocate<vector_node_t>(vec_holder); 29909 | 29910 | result = expression_generator_( 29911 | details::e_assign, 29912 | vec_node, 29913 | vec_initilizer_list[0]); 29914 | } 29915 | else 29916 | { 29917 | result = node_allocator_ 29918 | .allocate<details::vector_initialisation_node<T> >( 29919 | (*vec_holder)[0], 29920 | vec_size, 29921 | vec_initilizer_list, 29922 | single_value_initialiser); 29923 | } 29924 | 29925 | svd.delete_ptr = false; 29926 | 29927 | if (result && result->valid()) 29928 | { 29929 | return result; 29930 | } 29931 | 29932 | details::free_node(node_allocator_, result); 29933 | 29934 | set_error(make_error( 29935 | parser_error::e_synthesis, 29936 | current_token(), 29937 | "ERR174 - Failed to generate initialisation node for vector: " + vec_name, 29938 | exprtk_error_location)); 29939 | 29940 | return error_node(); 29941 | } 29942 | 29943 | #ifndef exprtk_disable_string_capabilities 29944 | inline expression_node_ptr parse_define_string_statement(const std::string& str_name, expression_node_ptr initialisation_expression) 29945 | { 29946 | stringvar_node_t* str_node = reinterpret_cast<stringvar_node_t*>(0); 29947 | 29948 | scope_element& se = sem_.get_element(str_name); 29949 | 29950 | if (se.name == str_name) 29951 | { 29952 | if (se.active) 29953 | { 29954 | set_error(make_error( 29955 | parser_error::e_syntax, 29956 | current_token(), 29957 | "ERR175 - Illegal redefinition of local variable: '" + str_name + "'", 29958 | exprtk_error_location)); 29959 | 29960 | free_node(node_allocator_, initialisation_expression); 29961 | 29962 | return error_node(); 29963 | } 29964 | else if (scope_element::e_string == se.type) 29965 | { 29966 | str_node = se.str_node; 29967 | se.active = true; 29968 | se.depth = state_.scope_depth; 29969 | se.ref_count++; 29970 | } 29971 | } 29972 | 29973 | if (0 == str_node) 29974 | { 29975 | scope_element nse; 29976 | nse.name = str_name; 29977 | nse.active = true; 29978 | nse.ref_count = 1; 29979 | nse.type = scope_element::e_string; 29980 | nse.depth = state_.scope_depth; 29981 | nse.data = new std::string; 29982 | nse.str_node = new stringvar_node_t(*reinterpret_cast<std::string*>(nse.data)); 29983 | 29984 | if (!sem_.add_element(nse)) 29985 | { 29986 | set_error(make_error( 29987 | parser_error::e_syntax, 29988 | current_token(), 29989 | "ERR176 - Failed to add new local string variable '" + str_name + "' to SEM", 29990 | exprtk_error_location)); 29991 | 29992 | free_node(node_allocator_, initialisation_expression); 29993 | 29994 | sem_.free_element(nse); 29995 | 29996 | return error_node(); 29997 | } 29998 | 29999 | assert(sem_.total_local_symb_size_bytes() <= settings().max_total_local_symbol_size_bytes()); 30000 | 30001 | str_node = nse.str_node; 30002 | 30003 | exprtk_debug(("parse_define_string_statement() - INFO - Added new local string variable: %s\n", nse.name.c_str())); 30004 | } 30005 | 30006 | lodge_symbol(str_name, e_st_local_string); 30007 | 30008 | state_.activate_side_effect("parse_define_string_statement()"); 30009 | 30010 | expression_node_ptr branch[2] = {0}; 30011 | 30012 | branch[0] = str_node; 30013 | branch[1] = initialisation_expression; 30014 | 30015 | return expression_generator_(details::e_assign,branch); 30016 | } 30017 | #else 30018 | inline expression_node_ptr parse_define_string_statement(const std::string&, expression_node_ptr) 30019 | { 30020 | return error_node(); 30021 | } 30022 | #endif 30023 | 30024 | inline bool local_variable_is_shadowed(const std::string& symbol) 30025 | { 30026 | const scope_element& se = sem_.get_element(symbol); 30027 | return (se.name == symbol) && se.active; 30028 | } 30029 | 30030 | inline expression_node_ptr parse_define_var_statement() 30031 | { 30032 | if (settings_.vardef_disabled()) 30033 | { 30034 | set_error(make_error( 30035 | parser_error::e_syntax, 30036 | current_token(), 30037 | "ERR177 - Illegal variable definition", 30038 | exprtk_error_location)); 30039 | 30040 | return error_node(); 30041 | } 30042 | else if (!details::imatch(current_token().value,"var")) 30043 | { 30044 | return error_node(); 30045 | } 30046 | else 30047 | next_token(); 30048 | 30049 | const std::string var_name = current_token().value; 30050 | 30051 | expression_node_ptr initialisation_expression = error_node(); 30052 | 30053 | if (!token_is(token_t::e_symbol)) 30054 | { 30055 | set_error(make_error( 30056 | parser_error::e_syntax, 30057 | current_token(), 30058 | "ERR178 - Expected a symbol for variable definition", 30059 | exprtk_error_location)); 30060 | 30061 | return error_node(); 30062 | } 30063 | else if (details::is_reserved_symbol(var_name)) 30064 | { 30065 | set_error(make_error( 30066 | parser_error::e_syntax, 30067 | current_token(), 30068 | "ERR179 - Illegal redefinition of reserved keyword: '" + var_name + "'", 30069 | exprtk_error_location)); 30070 | 30071 | return error_node(); 30072 | } 30073 | else if (symtab_store_.symbol_exists(var_name)) 30074 | { 30075 | set_error(make_error( 30076 | parser_error::e_syntax, 30077 | current_token(), 30078 | "ERR180 - Illegal redefinition of variable '" + var_name + "'", 30079 | exprtk_error_location)); 30080 | 30081 | return error_node(); 30082 | } 30083 | else if (local_variable_is_shadowed(var_name)) 30084 | { 30085 | set_error(make_error( 30086 | parser_error::e_syntax, 30087 | current_token(), 30088 | "ERR181 - Illegal redefinition of local variable: '" + var_name + "'", 30089 | exprtk_error_location)); 30090 | 30091 | return error_node(); 30092 | } 30093 | else if (token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold)) 30094 | { 30095 | return parse_define_vector_statement(var_name); 30096 | } 30097 | else if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) 30098 | { 30099 | return parse_uninitialised_var_statement(var_name); 30100 | } 30101 | else if (token_is(token_t::e_assign)) 30102 | { 30103 | if (0 == (initialisation_expression = parse_expression())) 30104 | { 30105 | set_error(make_error( 30106 | parser_error::e_syntax, 30107 | current_token(), 30108 | "ERR182 - Failed to parse initialisation expression for variable '" + var_name + "'", 30109 | exprtk_error_location)); 30110 | 30111 | return error_node(); 30112 | } 30113 | } 30114 | 30115 | if ( 30116 | !token_is(token_t::e_rbracket , prsrhlpr_t::e_hold) && 30117 | !token_is(token_t::e_rcrlbracket, prsrhlpr_t::e_hold) && 30118 | !token_is(token_t::e_rsqrbracket, prsrhlpr_t::e_hold) 30119 | ) 30120 | { 30121 | if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold)) 30122 | { 30123 | set_error(make_error( 30124 | parser_error::e_syntax, 30125 | current_token(), 30126 | "ERR183 - Expected ';' after variable '" + var_name + "' definition", 30127 | exprtk_error_location)); 30128 | 30129 | free_node(node_allocator_, initialisation_expression); 30130 | 30131 | return error_node(); 30132 | } 30133 | } 30134 | 30135 | if ( 30136 | (0 != initialisation_expression) && 30137 | details::is_generally_string_node(initialisation_expression) 30138 | ) 30139 | { 30140 | return parse_define_string_statement(var_name,initialisation_expression); 30141 | } 30142 | 30143 | expression_node_ptr var_node = reinterpret_cast<expression_node_ptr>(0); 30144 | 30145 | scope_element& se = sem_.get_element(var_name); 30146 | 30147 | if (se.name == var_name) 30148 | { 30149 | if (se.active) 30150 | { 30151 | set_error(make_error( 30152 | parser_error::e_syntax, 30153 | current_token(), 30154 | "ERR184 - Illegal redefinition of local variable: '" + var_name + "'", 30155 | exprtk_error_location)); 30156 | 30157 | free_node(node_allocator_, initialisation_expression); 30158 | 30159 | return error_node(); 30160 | } 30161 | else if (scope_element::e_variable == se.type) 30162 | { 30163 | var_node = se.var_node; 30164 | se.active = true; 30165 | se.depth = state_.scope_depth; 30166 | se.ref_count++; 30167 | } 30168 | } 30169 | 30170 | if (0 == var_node) 30171 | { 30172 | const std::size_t predicted_total_lclsymb_size = sizeof(T) + sem_.total_local_symb_size_bytes(); 30173 | 30174 | if (predicted_total_lclsymb_size > settings().max_total_local_symbol_size_bytes()) 30175 | { 30176 | set_error(make_error( 30177 | parser_error::e_syntax, 30178 | current_token(), 30179 | "ERR185 - Adding variable '" + var_name + "' " 30180 | "will exceed max total local symbol size of: " + details::to_str(settings().max_total_local_symbol_size_bytes()) + " bytes, " 30181 | "current total size: " + details::to_str(sem_.total_local_symb_size_bytes()) + " bytes", 30182 | exprtk_error_location)); 30183 | 30184 | free_node(node_allocator_, initialisation_expression); 30185 | 30186 | return error_node(); 30187 | } 30188 | 30189 | scope_element nse; 30190 | nse.name = var_name; 30191 | nse.active = true; 30192 | nse.ref_count = 1; 30193 | nse.type = scope_element::e_variable; 30194 | nse.depth = state_.scope_depth; 30195 | nse.data = new T(T(0)); 30196 | nse.var_node = node_allocator_.allocate<variable_node_t>(*reinterpret_cast<T*>(nse.data)); 30197 | 30198 | if (!sem_.add_element(nse)) 30199 | { 30200 | set_error(make_error( 30201 | parser_error::e_syntax, 30202 | current_token(), 30203 | "ERR186 - Failed to add new local variable '" + var_name + "' to SEM", 30204 | exprtk_error_location)); 30205 | 30206 | free_node(node_allocator_, initialisation_expression); 30207 | 30208 | sem_.free_element(nse); 30209 | 30210 | return error_node(); 30211 | } 30212 | 30213 | assert(sem_.total_local_symb_size_bytes() <= settings().max_total_local_symbol_size_bytes()); 30214 | 30215 | var_node = nse.var_node; 30216 | 30217 | exprtk_debug(("parse_define_var_statement() - INFO - Added new local variable: %s\n", nse.name.c_str())); 30218 | } 30219 | 30220 | state_.activate_side_effect("parse_define_var_statement()"); 30221 | 30222 | lodge_symbol(var_name, e_st_local_variable); 30223 | 30224 | expression_node_ptr branch[2] = {0}; 30225 | 30226 | branch[0] = var_node; 30227 | branch[1] = initialisation_expression ? initialisation_expression : expression_generator_(T(0)); 30228 | 30229 | return expression_generator_(details::e_assign,branch); 30230 | } 30231 | 30232 | inline expression_node_ptr parse_define_constvar_statement() 30233 | { 30234 | if (settings_.vardef_disabled()) 30235 | { 30236 | set_error(make_error( 30237 | parser_error::e_syntax, 30238 | current_token(), 30239 | "ERR187 - Illegal const variable definition", 30240 | exprtk_error_location)); 30241 | 30242 | return error_node(); 30243 | } 30244 | else if (!token_is("const")) 30245 | { 30246 | set_error(make_error( 30247 | parser_error::e_syntax, 30248 | current_token(), 30249 | "ERR188 - Expected 'const' keyword for const-variable definition", 30250 | exprtk_error_location)); 30251 | 30252 | return error_node(); 30253 | } 30254 | else if (!token_is("var")) 30255 | { 30256 | set_error(make_error( 30257 | parser_error::e_syntax, 30258 | current_token(), 30259 | "ERR189 - Expected 'var' keyword for const-variable definition", 30260 | exprtk_error_location)); 30261 | 30262 | return error_node(); 30263 | } 30264 | 30265 | const std::string var_name = current_token().value; 30266 | 30267 | expression_node_ptr initialisation_expression = error_node(); 30268 | 30269 | if (!token_is(token_t::e_symbol)) 30270 | { 30271 | set_error(make_error( 30272 | parser_error::e_syntax, 30273 | current_token(), 30274 | "ERR190 - Expected a symbol for const-variable definition", 30275 | exprtk_error_location)); 30276 | 30277 | return error_node(); 30278 | } 30279 | else if (details::is_reserved_symbol(var_name)) 30280 | { 30281 | set_error(make_error( 30282 | parser_error::e_syntax, 30283 | current_token(), 30284 | "ERR191 - Illegal redefinition of reserved keyword: '" + var_name + "'", 30285 | exprtk_error_location)); 30286 | 30287 | return error_node(); 30288 | } 30289 | else if (symtab_store_.symbol_exists(var_name)) 30290 | { 30291 | set_error(make_error( 30292 | parser_error::e_syntax, 30293 | current_token(), 30294 | "ERR192 - Illegal redefinition of variable '" + var_name + "'", 30295 | exprtk_error_location)); 30296 | 30297 | return error_node(); 30298 | } 30299 | else if (local_variable_is_shadowed(var_name)) 30300 | { 30301 | set_error(make_error( 30302 | parser_error::e_syntax, 30303 | current_token(), 30304 | "ERR193 - Illegal redefinition of local variable: '" + var_name + "'", 30305 | exprtk_error_location)); 30306 | 30307 | return error_node(); 30308 | } 30309 | else if (!token_is(token_t::e_assign)) 30310 | { 30311 | set_error(make_error( 30312 | parser_error::e_syntax, 30313 | current_token(), 30314 | "ERR194 - Expected assignment operator after const-variable: '" + var_name + "' definition", 30315 | exprtk_error_location)); 30316 | 30317 | return error_node(); 30318 | } 30319 | else if (0 == (initialisation_expression = parse_expression())) 30320 | { 30321 | set_error(make_error( 30322 | parser_error::e_syntax, 30323 | current_token(), 30324 | "ERR195 - Failed to parse initialisation expression for const-variable: '" + var_name + "'", 30325 | exprtk_error_location)); 30326 | 30327 | return error_node(); 30328 | } 30329 | 30330 | if (!details::is_literal_node(initialisation_expression)) 30331 | { 30332 | set_error(make_error( 30333 | parser_error::e_syntax, 30334 | current_token(), 30335 | "ERR196 - initialisation expression for const-variable: '" + var_name + "' must be a constant/literal", 30336 | exprtk_error_location)); 30337 | 30338 | free_node(node_allocator_, initialisation_expression); 30339 | 30340 | return error_node(); 30341 | } 30342 | 30343 | assert(initialisation_expression); 30344 | 30345 | const T init_value = initialisation_expression->value(); 30346 | 30347 | free_node(node_allocator_, initialisation_expression); 30348 | 30349 | expression_node_ptr var_node = reinterpret_cast<expression_node_ptr>(0); 30350 | 30351 | scope_element& se = sem_.get_element(var_name); 30352 | 30353 | if (se.name == var_name) 30354 | { 30355 | if (se.active) 30356 | { 30357 | set_error(make_error( 30358 | parser_error::e_syntax, 30359 | current_token(), 30360 | "ERR197 - Illegal redefinition of local variable: '" + var_name + "'", 30361 | exprtk_error_location)); 30362 | 30363 | return error_node(); 30364 | } 30365 | else if (scope_element::e_literal == se.type) 30366 | { 30367 | var_node = se.var_node; 30368 | se.active = true; 30369 | se.depth = state_.scope_depth; 30370 | se.ref_count++; 30371 | } 30372 | } 30373 | 30374 | if (0 == var_node) 30375 | { 30376 | const std::size_t predicted_total_lclsymb_size = sizeof(T) + sem_.total_local_symb_size_bytes(); 30377 | 30378 | if (predicted_total_lclsymb_size > settings().max_total_local_symbol_size_bytes()) 30379 | { 30380 | set_error(make_error( 30381 | parser_error::e_syntax, 30382 | current_token(), 30383 | "ERR198 - Adding variable '" + var_name + "' " 30384 | "will exceed max total local symbol size of: " + details::to_str(settings().max_total_local_symbol_size_bytes()) + " bytes, " 30385 | "current total size: " + details::to_str(sem_.total_local_symb_size_bytes()) + " bytes", 30386 | exprtk_error_location)); 30387 | 30388 | return error_node(); 30389 | } 30390 | 30391 | scope_element nse; 30392 | nse.name = var_name; 30393 | nse.active = true; 30394 | nse.ref_count = 1; 30395 | nse.type = scope_element::e_literal; 30396 | nse.depth = state_.scope_depth; 30397 | nse.data = 0; 30398 | nse.var_node = node_allocator_.allocate<literal_node_t>(init_value); 30399 | 30400 | if (!sem_.add_element(nse)) 30401 | { 30402 | set_error(make_error( 30403 | parser_error::e_syntax, 30404 | current_token(), 30405 | "ERR199 - Failed to add new local const-variable '" + var_name + "' to SEM", 30406 | exprtk_error_location)); 30407 | 30408 | sem_.free_element(nse); 30409 | 30410 | return error_node(); 30411 | } 30412 | 30413 | assert(sem_.total_local_symb_size_bytes() <= settings().max_total_local_symbol_size_bytes()); 30414 | 30415 | var_node = nse.var_node; 30416 | 30417 | exprtk_debug(("parse_define_constvar_statement() - INFO - Added new local const-variable: %s\n", nse.name.c_str())); 30418 | } 30419 | 30420 | state_.activate_side_effect("parse_define_constvar_statement()"); 30421 | 30422 | lodge_symbol(var_name, e_st_local_variable); 30423 | 30424 | return expression_generator_(var_node->value()); 30425 | } 30426 | 30427 | inline expression_node_ptr parse_uninitialised_var_statement(const std::string& var_name) 30428 | { 30429 | if ( 30430 | !token_is(token_t::e_lcrlbracket) || 30431 | !token_is(token_t::e_rcrlbracket) 30432 | ) 30433 | { 30434 | set_error(make_error( 30435 | parser_error::e_syntax, 30436 | current_token(), 30437 | "ERR200 - Expected a '{}' for uninitialised var definition", 30438 | exprtk_error_location)); 30439 | 30440 | return error_node(); 30441 | } 30442 | else if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold)) 30443 | { 30444 | set_error(make_error( 30445 | parser_error::e_syntax, 30446 | current_token(), 30447 | "ERR201 - Expected ';' after uninitialised variable definition", 30448 | exprtk_error_location)); 30449 | 30450 | return error_node(); 30451 | } 30452 | 30453 | expression_node_ptr var_node = reinterpret_cast<expression_node_ptr>(0); 30454 | 30455 | scope_element& se = sem_.get_element(var_name); 30456 | 30457 | if (se.name == var_name) 30458 | { 30459 | if (se.active) 30460 | { 30461 | set_error(make_error( 30462 | parser_error::e_syntax, 30463 | current_token(), 30464 | "ERR202 - Illegal redefinition of local variable: '" + var_name + "'", 30465 | exprtk_error_location)); 30466 | 30467 | return error_node(); 30468 | } 30469 | else if (scope_element::e_variable == se.type) 30470 | { 30471 | var_node = se.var_node; 30472 | se.active = true; 30473 | se.ref_count++; 30474 | } 30475 | } 30476 | 30477 | if (0 == var_node) 30478 | { 30479 | const std::size_t predicted_total_lclsymb_size = sizeof(T) + sem_.total_local_symb_size_bytes(); 30480 | 30481 | if (predicted_total_lclsymb_size > settings().max_total_local_symbol_size_bytes()) 30482 | { 30483 | set_error(make_error( 30484 | parser_error::e_syntax, 30485 | current_token(), 30486 | "ERR203 - Adding variable '" + var_name + "' " 30487 | "will exceed max total local symbol size of: " + details::to_str(settings().max_total_local_symbol_size_bytes()) + " bytes, " 30488 | "current total size: " + details::to_str(sem_.total_local_symb_size_bytes()) + " bytes", 30489 | exprtk_error_location)); 30490 | 30491 | return error_node(); 30492 | } 30493 | 30494 | scope_element nse; 30495 | nse.name = var_name; 30496 | nse.active = true; 30497 | nse.ref_count = 1; 30498 | nse.type = scope_element::e_variable; 30499 | nse.depth = state_.scope_depth; 30500 | nse.ip_index = sem_.next_ip_index(); 30501 | nse.data = new T(T(0)); 30502 | nse.var_node = node_allocator_.allocate<variable_node_t>(*reinterpret_cast<T*>(nse.data)); 30503 | 30504 | if (!sem_.add_element(nse)) 30505 | { 30506 | set_error(make_error( 30507 | parser_error::e_syntax, 30508 | current_token(), 30509 | "ERR204 - Failed to add new local variable '" + var_name + "' to SEM", 30510 | exprtk_error_location)); 30511 | 30512 | sem_.free_element(nse); 30513 | 30514 | return error_node(); 30515 | } 30516 | 30517 | assert(sem_.total_local_symb_size_bytes() <= settings().max_total_local_symbol_size_bytes()); 30518 | 30519 | exprtk_debug(("parse_uninitialised_var_statement() - INFO - Added new local variable: %s\n", 30520 | nse.name.c_str())); 30521 | } 30522 | 30523 | lodge_symbol(var_name, e_st_local_variable); 30524 | 30525 | state_.activate_side_effect("parse_uninitialised_var_statement()"); 30526 | 30527 | return expression_generator_(T(0)); 30528 | } 30529 | 30530 | inline expression_node_ptr parse_swap_statement() 30531 | { 30532 | if (!details::imatch(current_token().value,"swap")) 30533 | { 30534 | return error_node(); 30535 | } 30536 | else 30537 | next_token(); 30538 | 30539 | if (!token_is(token_t::e_lbracket)) 30540 | { 30541 | set_error(make_error( 30542 | parser_error::e_syntax, 30543 | current_token(), 30544 | "ERR205 - Expected '(' at start of swap statement", 30545 | exprtk_error_location)); 30546 | 30547 | return error_node(); 30548 | } 30549 | 30550 | expression_node_ptr variable0 = error_node(); 30551 | expression_node_ptr variable1 = error_node(); 30552 | 30553 | bool variable0_generated = false; 30554 | bool variable1_generated = false; 30555 | 30556 | const std::string var0_name = current_token().value; 30557 | 30558 | if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold)) 30559 | { 30560 | set_error(make_error( 30561 | parser_error::e_syntax, 30562 | current_token(), 30563 | "ERR206 - Expected a symbol for variable or vector element definition", 30564 | exprtk_error_location)); 30565 | 30566 | return error_node(); 30567 | } 30568 | else if (peek_token_is(token_t::e_lsqrbracket)) 30569 | { 30570 | if (0 == (variable0 = parse_vector())) 30571 | { 30572 | set_error(make_error( 30573 | parser_error::e_syntax, 30574 | current_token(), 30575 | "ERR207 - First parameter to swap is an invalid vector element: '" + var0_name + "'", 30576 | exprtk_error_location)); 30577 | 30578 | return error_node(); 30579 | } 30580 | 30581 | variable0_generated = true; 30582 | } 30583 | else 30584 | { 30585 | if (symtab_store_.is_variable(var0_name)) 30586 | { 30587 | variable0 = symtab_store_.get_variable(var0_name); 30588 | } 30589 | 30590 | const scope_element& se = sem_.get_element(var0_name); 30591 | 30592 | if ( 30593 | (se.active) && 30594 | (se.name == var0_name) && 30595 | (scope_element::e_variable == se.type) 30596 | ) 30597 | { 30598 | variable0 = se.var_node; 30599 | } 30600 | 30601 | lodge_symbol(var0_name, e_st_variable); 30602 | 30603 | if (0 == variable0) 30604 | { 30605 | set_error(make_error( 30606 | parser_error::e_syntax, 30607 | current_token(), 30608 | "ERR208 - First parameter to swap is an invalid variable: '" + var0_name + "'", 30609 | exprtk_error_location)); 30610 | 30611 | return error_node(); 30612 | } 30613 | else 30614 | next_token(); 30615 | } 30616 | 30617 | if (!token_is(token_t::e_comma)) 30618 | { 30619 | set_error(make_error( 30620 | parser_error::e_syntax, 30621 | current_token(), 30622 | "ERR209 - Expected ',' between parameters to swap", 30623 | exprtk_error_location)); 30624 | 30625 | if (variable0_generated) 30626 | { 30627 | free_node(node_allocator_, variable0); 30628 | } 30629 | 30630 | return error_node(); 30631 | } 30632 | 30633 | const std::string var1_name = current_token().value; 30634 | 30635 | if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold)) 30636 | { 30637 | set_error(make_error( 30638 | parser_error::e_syntax, 30639 | current_token(), 30640 | "ERR210 - Expected a symbol for variable or vector element definition", 30641 | exprtk_error_location)); 30642 | 30643 | if (variable0_generated) 30644 | { 30645 | free_node(node_allocator_, variable0); 30646 | } 30647 | 30648 | return error_node(); 30649 | } 30650 | else if (peek_token_is(token_t::e_lsqrbracket)) 30651 | { 30652 | if (0 == (variable1 = parse_vector())) 30653 | { 30654 | set_error(make_error( 30655 | parser_error::e_syntax, 30656 | current_token(), 30657 | "ERR211 - Second parameter to swap is an invalid vector element: '" + var1_name + "'", 30658 | exprtk_error_location)); 30659 | 30660 | if (variable0_generated) 30661 | { 30662 | free_node(node_allocator_, variable0); 30663 | } 30664 | 30665 | return error_node(); 30666 | } 30667 | 30668 | variable1_generated = true; 30669 | } 30670 | else 30671 | { 30672 | if (symtab_store_.is_variable(var1_name)) 30673 | { 30674 | variable1 = symtab_store_.get_variable(var1_name); 30675 | } 30676 | 30677 | const scope_element& se = sem_.get_element(var1_name); 30678 | 30679 | if ( 30680 | (se.active) && 30681 | (se.name == var1_name) && 30682 | (scope_element::e_variable == se.type) 30683 | ) 30684 | { 30685 | variable1 = se.var_node; 30686 | } 30687 | 30688 | lodge_symbol(var1_name, e_st_variable); 30689 | 30690 | if (0 == variable1) 30691 | { 30692 | set_error(make_error( 30693 | parser_error::e_syntax, 30694 | current_token(), 30695 | "ERR212 - Second parameter to swap is an invalid variable: '" + var1_name + "'", 30696 | exprtk_error_location)); 30697 | 30698 | if (variable0_generated) 30699 | { 30700 | free_node(node_allocator_, variable0); 30701 | } 30702 | 30703 | return error_node(); 30704 | } 30705 | else 30706 | next_token(); 30707 | } 30708 | 30709 | if (!token_is(token_t::e_rbracket)) 30710 | { 30711 | set_error(make_error( 30712 | parser_error::e_syntax, 30713 | current_token(), 30714 | "ERR213 - Expected ')' at end of swap statement", 30715 | exprtk_error_location)); 30716 | 30717 | if (variable0_generated) 30718 | { 30719 | free_node(node_allocator_, variable0); 30720 | } 30721 | 30722 | if (variable1_generated) 30723 | { 30724 | free_node(node_allocator_, variable1); 30725 | } 30726 | 30727 | return error_node(); 30728 | } 30729 | 30730 | typedef details::variable_node<T>* variable_node_ptr; 30731 | 30732 | variable_node_ptr v0 = variable_node_ptr(0); 30733 | variable_node_ptr v1 = variable_node_ptr(0); 30734 | 30735 | expression_node_ptr result = error_node(); 30736 | 30737 | if ( 30738 | (0 != (v0 = dynamic_cast<variable_node_ptr>(variable0))) && 30739 | (0 != (v1 = dynamic_cast<variable_node_ptr>(variable1))) 30740 | ) 30741 | { 30742 | result = node_allocator_.allocate<details::swap_node<T> >(v0, v1); 30743 | 30744 | if (variable0_generated) 30745 | { 30746 | free_node(node_allocator_, variable0); 30747 | } 30748 | 30749 | if (variable1_generated) 30750 | { 30751 | free_node(node_allocator_, variable1); 30752 | } 30753 | } 30754 | else 30755 | result = node_allocator_.allocate<details::swap_generic_node<T> > 30756 | (variable0, variable1); 30757 | 30758 | state_.activate_side_effect("parse_swap_statement()"); 30759 | 30760 | return result; 30761 | } 30762 | 30763 | #ifndef exprtk_disable_return_statement 30764 | inline expression_node_ptr parse_return_statement() 30765 | { 30766 | if (state_.parsing_return_stmt) 30767 | { 30768 | set_error(make_error( 30769 | parser_error::e_syntax, 30770 | current_token(), 30771 | "ERR214 - Return call within a return call is not allowed", 30772 | exprtk_error_location)); 30773 | 30774 | return error_node(); 30775 | } 30776 | 30777 | scoped_bool_negator sbn(state_.parsing_return_stmt); 30778 | 30779 | std::vector<expression_node_ptr> arg_list; 30780 | 30781 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 30782 | 30783 | if (!details::imatch(current_token().value,"return")) 30784 | { 30785 | return error_node(); 30786 | } 30787 | else 30788 | next_token(); 30789 | 30790 | if (!token_is(token_t::e_lsqrbracket)) 30791 | { 30792 | set_error(make_error( 30793 | parser_error::e_syntax, 30794 | current_token(), 30795 | "ERR215 - Expected '[' at start of return statement", 30796 | exprtk_error_location)); 30797 | 30798 | return error_node(); 30799 | } 30800 | else if (!token_is(token_t::e_rsqrbracket)) 30801 | { 30802 | for ( ; ; ) 30803 | { 30804 | expression_node_ptr arg = parse_expression(); 30805 | 30806 | if (0 == arg) 30807 | return error_node(); 30808 | 30809 | arg_list.push_back(arg); 30810 | 30811 | if (token_is(token_t::e_rsqrbracket)) 30812 | break; 30813 | else if (!token_is(token_t::e_comma)) 30814 | { 30815 | set_error(make_error( 30816 | parser_error::e_syntax, 30817 | current_token(), 30818 | "ERR216 - Expected ',' between values during call to return", 30819 | exprtk_error_location)); 30820 | 30821 | return error_node(); 30822 | } 30823 | } 30824 | } 30825 | else if (settings_.zero_return_disabled()) 30826 | { 30827 | set_error(make_error( 30828 | parser_error::e_syntax, 30829 | current_token(), 30830 | "ERR217 - Zero parameter return statement not allowed", 30831 | exprtk_error_location)); 30832 | 30833 | return error_node(); 30834 | } 30835 | 30836 | const lexer::token prev_token = current_token(); 30837 | 30838 | if (token_is(token_t::e_rsqrbracket)) 30839 | { 30840 | if (!arg_list.empty()) 30841 | { 30842 | set_error(make_error( 30843 | parser_error::e_syntax, 30844 | prev_token, 30845 | "ERR218 - Invalid ']' found during return call", 30846 | exprtk_error_location)); 30847 | 30848 | return error_node(); 30849 | } 30850 | } 30851 | 30852 | std::string ret_param_type_list; 30853 | 30854 | for (std::size_t i = 0; i < arg_list.size(); ++i) 30855 | { 30856 | if (0 == arg_list[i]) 30857 | return error_node(); 30858 | else if (is_ivector_node(arg_list[i])) 30859 | ret_param_type_list += 'V'; 30860 | else if (is_generally_string_node(arg_list[i])) 30861 | ret_param_type_list += 'S'; 30862 | else 30863 | ret_param_type_list += 'T'; 30864 | } 30865 | 30866 | dec_.retparam_list_.push_back(ret_param_type_list); 30867 | 30868 | expression_node_ptr result = expression_generator_.return_call(arg_list); 30869 | 30870 | svd.delete_ptr = (0 == result); 30871 | 30872 | state_.return_stmt_present = true; 30873 | 30874 | state_.activate_side_effect("parse_return_statement()"); 30875 | 30876 | return result; 30877 | } 30878 | #else 30879 | inline expression_node_ptr parse_return_statement() 30880 | { 30881 | return error_node(); 30882 | } 30883 | #endif 30884 | 30885 | inline expression_node_ptr parse_assert_statement() 30886 | { 30887 | assert(details::imatch(current_token().value, "assert")); 30888 | 30889 | if (state_.parsing_assert_stmt) 30890 | { 30891 | set_error(make_error( 30892 | parser_error::e_syntax, 30893 | current_token(), 30894 | "ERR219 - Assert statement within an assert statement is not allowed", 30895 | exprtk_error_location)); 30896 | 30897 | return error_node(); 30898 | } 30899 | 30900 | scoped_bool_negator sbn(state_.parsing_assert_stmt); 30901 | 30902 | next_token(); 30903 | 30904 | std::vector<expression_node_ptr> assert_arg_list(3, error_node()); 30905 | scoped_vec_delete<expression_node_t> svd((*this), assert_arg_list); 30906 | 30907 | expression_node_ptr& assert_condition = assert_arg_list[0]; 30908 | expression_node_ptr& assert_message = assert_arg_list[1]; 30909 | expression_node_ptr& assert_id = assert_arg_list[2]; 30910 | 30911 | if (!token_is(token_t::e_lbracket)) 30912 | { 30913 | set_error(make_error( 30914 | parser_error::e_syntax, 30915 | current_token(), 30916 | "ERR220 - Expected '(' at start of assert statement", 30917 | exprtk_error_location)); 30918 | 30919 | return error_node(); 30920 | } 30921 | 30922 | const token_t start_token = current_token(); 30923 | 30924 | // Parse the assert condition 30925 | if (0 == (assert_condition = parse_expression())) 30926 | { 30927 | set_error(make_error( 30928 | parser_error::e_syntax, 30929 | current_token(), 30930 | "ERR221 - Failed to parse condition for assert statement", 30931 | exprtk_error_location)); 30932 | 30933 | return error_node(); 30934 | } 30935 | 30936 | const token_t end_token = current_token(); 30937 | 30938 | if (!token_is(token_t::e_rbracket)) 30939 | { 30940 | if (!token_is(token_t::e_comma)) 30941 | { 30942 | set_error(make_error( 30943 | parser_error::e_syntax, 30944 | current_token(), 30945 | "ERR222 - Expected ',' between condition and message for assert statement", 30946 | exprtk_error_location)); 30947 | 30948 | return error_node(); 30949 | } 30950 | // Parse the assert message 30951 | else if ( 30952 | (0 == (assert_message = parse_expression())) || 30953 | !details::is_generally_string_node(assert_message) 30954 | ) 30955 | { 30956 | set_error(make_error( 30957 | parser_error::e_syntax, 30958 | current_token(), 30959 | "ERR223 - " + 30960 | (assert_message ? 30961 | std::string("Expected string for assert message") : 30962 | std::string("Failed to parse message for assert statement")), 30963 | exprtk_error_location)); 30964 | 30965 | return error_node(); 30966 | } 30967 | else if (!token_is(token_t::e_rbracket)) 30968 | { 30969 | if (!token_is(token_t::e_comma)) 30970 | { 30971 | set_error(make_error( 30972 | parser_error::e_syntax, 30973 | current_token(), 30974 | "ERR224 - Expected ',' between message and ID for assert statement", 30975 | exprtk_error_location)); 30976 | 30977 | return error_node(); 30978 | } 30979 | // Parse assert ID 30980 | else if ( 30981 | (0 == (assert_id = parse_expression())) || 30982 | !details::is_const_string_node(assert_id) 30983 | ) 30984 | { 30985 | set_error(make_error( 30986 | parser_error::e_syntax, 30987 | current_token(), 30988 | "ERR225 - " + 30989 | (assert_id ? 30990 | std::string("Expected literal string for assert ID") : 30991 | std::string("Failed to parse string for assert ID")), 30992 | exprtk_error_location)); 30993 | 30994 | return error_node(); 30995 | } 30996 | else if (!token_is(token_t::e_rbracket)) 30997 | { 30998 | set_error(make_error( 30999 | parser_error::e_syntax, 31000 | current_token(), 31001 | "ERR226 - Expected ')' at start of assert statement", 31002 | exprtk_error_location)); 31003 | 31004 | return error_node(); 31005 | } 31006 | } 31007 | } 31008 | 31009 | exprtk::assert_check::assert_context context; 31010 | context.condition = lexer().substr(start_token.position, end_token.position); 31011 | context.offet = start_token.position; 31012 | 31013 | if (0 == assert_check_) 31014 | { 31015 | exprtk_debug(("parse_assert_statement() - assert functionality is disabled. assert condition: %s\n", 31016 | context.condition.c_str())); 31017 | 31018 | return new details::null_node<T>(); 31019 | } 31020 | 31021 | #ifndef exprtk_disable_string_capabilities 31022 | if (assert_message && details::is_const_string_node(assert_message)) 31023 | { 31024 | context.message = dynamic_cast<details::string_base_node<T>*>(assert_message)->str(); 31025 | } 31026 | 31027 | if (assert_id && details::is_const_string_node(assert_id)) 31028 | { 31029 | context.id = dynamic_cast<details::string_base_node<T>*>(assert_id)->str(); 31030 | 31031 | if (assert_ids_.end() != assert_ids_.find(context.id)) 31032 | { 31033 | set_error(make_error( 31034 | parser_error::e_syntax, 31035 | current_token(), 31036 | "ERR227 - Duplicate assert ID: " + context.id, 31037 | exprtk_error_location)); 31038 | 31039 | return error_node(); 31040 | } 31041 | 31042 | assert_ids_.insert(context.id); 31043 | free_node(node_allocator_, assert_id); 31044 | } 31045 | #endif 31046 | 31047 | expression_node_ptr result_node = 31048 | expression_generator_.assert_call( 31049 | assert_condition, 31050 | assert_message, 31051 | context); 31052 | 31053 | exprtk_debug(("parse_assert_statement() - assert condition: [%s]\n", context.condition.c_str() )); 31054 | exprtk_debug(("parse_assert_statement() - assert message: [%s]\n", context.message .c_str() )); 31055 | exprtk_debug(("parse_assert_statement() - assert id: [%s]\n", context.id .c_str() )); 31056 | exprtk_debug(("parse_assert_statement() - assert offset: [%d]\n", static_cast<int>(context.offet))); 31057 | 31058 | if (0 == result_node) 31059 | { 31060 | set_error(make_error( 31061 | parser_error::e_syntax, 31062 | current_token(), 31063 | "ERR228 - Failed to synthesize assert", 31064 | exprtk_error_location)); 31065 | 31066 | return error_node(); 31067 | } 31068 | 31069 | svd.delete_ptr = false; 31070 | return result_node; 31071 | } 31072 | 31073 | inline bool post_variable_process(const std::string& symbol) 31074 | { 31075 | if ( 31076 | peek_token_is(token_t::e_lbracket ) || 31077 | peek_token_is(token_t::e_lcrlbracket) || 31078 | peek_token_is(token_t::e_lsqrbracket) 31079 | ) 31080 | { 31081 | if (!settings_.commutative_check_enabled()) 31082 | { 31083 | set_error(make_error( 31084 | parser_error::e_syntax, 31085 | current_token(), 31086 | "ERR229 - Invalid sequence of variable '" + symbol + "' and bracket", 31087 | exprtk_error_location)); 31088 | 31089 | return false; 31090 | } 31091 | 31092 | lexer().insert_front(token_t::e_mul); 31093 | } 31094 | 31095 | return true; 31096 | } 31097 | 31098 | inline bool post_bracket_process(const typename token_t::token_type& token, expression_node_ptr& branch) 31099 | { 31100 | bool implied_mul = false; 31101 | 31102 | if (details::is_generally_string_node(branch)) 31103 | return true; 31104 | 31105 | if (details::is_ivector_node(branch)) 31106 | return true; 31107 | 31108 | const lexer::parser_helper::token_advance_mode hold = prsrhlpr_t::e_hold; 31109 | 31110 | switch (token) 31111 | { 31112 | case token_t::e_lcrlbracket : implied_mul = token_is(token_t::e_lbracket , hold) || 31113 | token_is(token_t::e_lcrlbracket, hold) || 31114 | token_is(token_t::e_lsqrbracket, hold) ; 31115 | break; 31116 | 31117 | case token_t::e_lbracket : implied_mul = token_is(token_t::e_lbracket , hold) || 31118 | token_is(token_t::e_lcrlbracket, hold) || 31119 | token_is(token_t::e_lsqrbracket, hold) ; 31120 | break; 31121 | 31122 | case token_t::e_lsqrbracket : implied_mul = token_is(token_t::e_lbracket , hold) || 31123 | token_is(token_t::e_lcrlbracket, hold) || 31124 | token_is(token_t::e_lsqrbracket, hold) ; 31125 | break; 31126 | 31127 | default : return true; 31128 | } 31129 | 31130 | if (implied_mul) 31131 | { 31132 | if (!settings_.commutative_check_enabled()) 31133 | { 31134 | set_error(make_error( 31135 | parser_error::e_syntax, 31136 | current_token(), 31137 | "ERR230 - Invalid sequence of brackets", 31138 | exprtk_error_location)); 31139 | 31140 | return false; 31141 | } 31142 | else if (token_t::e_eof != current_token().type) 31143 | { 31144 | lexer().insert_front(current_token().type); 31145 | lexer().insert_front(token_t::e_mul); 31146 | next_token(); 31147 | } 31148 | } 31149 | 31150 | return true; 31151 | } 31152 | 31153 | typedef typename interval_container_t<const void*>::interval_t interval_t; 31154 | typedef interval_container_t<const void*> immutable_memory_map_t; 31155 | typedef std::map<interval_t,token_t> immutable_symtok_map_t; 31156 | 31157 | inline interval_t make_memory_range(const T& t) 31158 | { 31159 | const T* begin = reinterpret_cast<const T*>(&t); 31160 | const T* end = begin + 1; 31161 | return interval_t(begin, end); 31162 | } 31163 | 31164 | inline interval_t make_memory_range(const T* begin, const std::size_t size) 31165 | { 31166 | return interval_t(begin, begin + size); 31167 | } 31168 | 31169 | inline interval_t make_memory_range(details::char_cptr begin, const std::size_t size) 31170 | { 31171 | return interval_t(begin, begin + size); 31172 | } 31173 | 31174 | void lodge_immutable_symbol(const lexer::token& token, const interval_t interval) 31175 | { 31176 | immutable_memory_map_.add_interval(interval); 31177 | immutable_symtok_map_[interval] = token; 31178 | } 31179 | 31180 | inline expression_node_ptr parse_symtab_symbol() 31181 | { 31182 | const std::string symbol = current_token().value; 31183 | 31184 | // Are we dealing with a variable or a special constant? 31185 | typedef typename symtab_store::variable_context var_ctxt_t; 31186 | var_ctxt_t var_ctx = symtab_store_.get_variable_context(symbol); 31187 | 31188 | if (var_ctx.variable) 31189 | { 31190 | assert(var_ctx.symbol_table); 31191 | 31192 | expression_node_ptr result_variable = var_ctx.variable; 31193 | 31194 | if (symtab_store_.is_constant_node(symbol)) 31195 | { 31196 | result_variable = expression_generator_(var_ctx.variable->value()); 31197 | } 31198 | else if (symbol_table_t::e_immutable == var_ctx.symbol_table->mutability()) 31199 | { 31200 | lodge_immutable_symbol(current_token(), make_memory_range(var_ctx.variable->ref())); 31201 | result_variable = var_ctx.variable; 31202 | } 31203 | 31204 | if (!post_variable_process(symbol)) 31205 | { 31206 | free_node(node_allocator_, result_variable); 31207 | 31208 | return error_node(); 31209 | } 31210 | 31211 | lodge_symbol(symbol, e_st_variable); 31212 | 31213 | next_token(); 31214 | 31215 | return result_variable; 31216 | } 31217 | 31218 | // Are we dealing with a locally defined variable, vector or string? 31219 | if (!sem_.empty()) 31220 | { 31221 | scope_element& se = sem_.get_active_element(symbol); 31222 | 31223 | if (se.active && details::imatch(se.name, symbol)) 31224 | { 31225 | if ( 31226 | (scope_element::e_variable == se.type) || 31227 | (scope_element::e_literal == se.type) 31228 | ) 31229 | { 31230 | se.active = true; 31231 | lodge_symbol(symbol, e_st_local_variable); 31232 | 31233 | if (!post_variable_process(symbol)) 31234 | return error_node(); 31235 | 31236 | next_token(); 31237 | 31238 | return (scope_element::e_variable == se.type) ? 31239 | se.var_node : 31240 | expression_generator_(se.var_node->value()); 31241 | } 31242 | else if (scope_element::e_vector == se.type) 31243 | { 31244 | return parse_vector(); 31245 | } 31246 | #ifndef exprtk_disable_string_capabilities 31247 | else if (scope_element::e_string == se.type) 31248 | { 31249 | return parse_string(); 31250 | } 31251 | #endif 31252 | } 31253 | } 31254 | 31255 | #ifndef exprtk_disable_string_capabilities 31256 | // Are we dealing with a string variable? 31257 | if (symtab_store_.is_stringvar(symbol)) 31258 | { 31259 | return parse_string(); 31260 | } 31261 | #endif 31262 | 31263 | { 31264 | // Are we dealing with a function? 31265 | ifunction<T>* function = symtab_store_.get_function(symbol); 31266 | 31267 | if (function) 31268 | { 31269 | lodge_symbol(symbol, e_st_function); 31270 | 31271 | expression_node_ptr func_node = 31272 | parse_function_invocation(function,symbol); 31273 | 31274 | if (func_node) 31275 | return func_node; 31276 | else 31277 | { 31278 | set_error(make_error( 31279 | parser_error::e_syntax, 31280 | current_token(), 31281 | "ERR231 - Failed to generate node for function: '" + symbol + "'", 31282 | exprtk_error_location)); 31283 | 31284 | return error_node(); 31285 | } 31286 | } 31287 | } 31288 | 31289 | { 31290 | // Are we dealing with a vararg function? 31291 | ivararg_function<T>* vararg_function = symtab_store_.get_vararg_function(symbol); 31292 | 31293 | if (vararg_function) 31294 | { 31295 | lodge_symbol(symbol, e_st_function); 31296 | 31297 | expression_node_ptr vararg_func_node = 31298 | parse_vararg_function_call(vararg_function, symbol); 31299 | 31300 | if (vararg_func_node) 31301 | return vararg_func_node; 31302 | else 31303 | { 31304 | set_error(make_error( 31305 | parser_error::e_syntax, 31306 | current_token(), 31307 | "ERR232 - Failed to generate node for vararg function: '" + symbol + "'", 31308 | exprtk_error_location)); 31309 | 31310 | return error_node(); 31311 | } 31312 | } 31313 | } 31314 | 31315 | { 31316 | // Are we dealing with a vararg generic function? 31317 | igeneric_function<T>* generic_function = symtab_store_.get_generic_function(symbol); 31318 | 31319 | if (generic_function) 31320 | { 31321 | lodge_symbol(symbol, e_st_function); 31322 | 31323 | expression_node_ptr genericfunc_node = 31324 | parse_generic_function_call(generic_function, symbol); 31325 | 31326 | if (genericfunc_node) 31327 | return genericfunc_node; 31328 | else 31329 | { 31330 | set_error(make_error( 31331 | parser_error::e_syntax, 31332 | current_token(), 31333 | "ERR233 - Failed to generate node for generic function: '" + symbol + "'", 31334 | exprtk_error_location)); 31335 | 31336 | return error_node(); 31337 | } 31338 | } 31339 | } 31340 | 31341 | #ifndef exprtk_disable_string_capabilities 31342 | { 31343 | // Are we dealing with a vararg string returning function? 31344 | igeneric_function<T>* string_function = symtab_store_.get_string_function(symbol); 31345 | 31346 | if (string_function) 31347 | { 31348 | lodge_symbol(symbol, e_st_function); 31349 | 31350 | expression_node_ptr stringfunc_node = 31351 | parse_string_function_call(string_function, symbol); 31352 | 31353 | if (stringfunc_node) 31354 | return stringfunc_node; 31355 | else 31356 | { 31357 | set_error(make_error( 31358 | parser_error::e_syntax, 31359 | current_token(), 31360 | "ERR234 - Failed to generate node for string function: '" + symbol + "'", 31361 | exprtk_error_location)); 31362 | 31363 | return error_node(); 31364 | } 31365 | } 31366 | } 31367 | 31368 | { 31369 | // Are we dealing with a vararg overloaded scalar/string returning function? 31370 | igeneric_function<T>* overload_function = symtab_store_.get_overload_function(symbol); 31371 | 31372 | if (overload_function) 31373 | { 31374 | lodge_symbol(symbol, e_st_function); 31375 | 31376 | expression_node_ptr overloadfunc_node = 31377 | parse_overload_function_call(overload_function, symbol); 31378 | 31379 | if (overloadfunc_node) 31380 | return overloadfunc_node; 31381 | else 31382 | { 31383 | set_error(make_error( 31384 | parser_error::e_syntax, 31385 | current_token(), 31386 | "ERR235 - Failed to generate node for overload function: '" + symbol + "'", 31387 | exprtk_error_location)); 31388 | 31389 | return error_node(); 31390 | } 31391 | } 31392 | } 31393 | #endif 31394 | 31395 | // Are we dealing with a vector? 31396 | if (symtab_store_.is_vector(symbol)) 31397 | { 31398 | lodge_symbol(symbol, e_st_vector); 31399 | return parse_vector(); 31400 | } 31401 | 31402 | if (details::is_reserved_symbol(symbol)) 31403 | { 31404 | if ( 31405 | settings_.function_enabled(symbol) || 31406 | !details::is_base_function(symbol) 31407 | ) 31408 | { 31409 | set_error(make_error( 31410 | parser_error::e_syntax, 31411 | current_token(), 31412 | "ERR236 - Invalid use of reserved symbol '" + symbol + "'", 31413 | exprtk_error_location)); 31414 | 31415 | return error_node(); 31416 | } 31417 | } 31418 | 31419 | // Should we handle unknown symbols? 31420 | if (resolve_unknown_symbol_ && unknown_symbol_resolver_) 31421 | { 31422 | if (!(settings_.rsrvd_sym_usr_disabled() && details::is_reserved_symbol(symbol))) 31423 | { 31424 | symbol_table_t& symtab = symtab_store_.get_symbol_table(); 31425 | 31426 | std::string error_message; 31427 | 31428 | if (unknown_symbol_resolver::e_usrmode_default == unknown_symbol_resolver_->mode) 31429 | { 31430 | T default_value = T(0); 31431 | 31432 | typename unknown_symbol_resolver::usr_symbol_type usr_symbol_type = unknown_symbol_resolver::e_usr_unknown_type; 31433 | 31434 | if (unknown_symbol_resolver_->process(symbol, usr_symbol_type, default_value, error_message)) 31435 | { 31436 | bool create_result = false; 31437 | 31438 | switch (usr_symbol_type) 31439 | { 31440 | case unknown_symbol_resolver::e_usr_variable_type : 31441 | create_result = symtab.create_variable(symbol, default_value); 31442 | break; 31443 | 31444 | case unknown_symbol_resolver::e_usr_constant_type : 31445 | create_result = symtab.add_constant(symbol, default_value); 31446 | break; 31447 | 31448 | default : create_result = false; 31449 | } 31450 | 31451 | if (create_result) 31452 | { 31453 | expression_node_ptr var = symtab_store_.get_variable(symbol); 31454 | 31455 | if (var) 31456 | { 31457 | if (symtab_store_.is_constant_node(symbol)) 31458 | { 31459 | var = expression_generator_(var->value()); 31460 | } 31461 | 31462 | lodge_symbol(symbol, e_st_variable); 31463 | 31464 | if (!post_variable_process(symbol)) 31465 | { 31466 | free_node(node_allocator_, var); 31467 | return error_node(); 31468 | } 31469 | 31470 | next_token(); 31471 | 31472 | return var; 31473 | } 31474 | } 31475 | } 31476 | 31477 | set_error(make_error( 31478 | parser_error::e_symtab, 31479 | current_token(), 31480 | "ERR237 - Failed to create variable: '" + symbol + "'" + 31481 | (error_message.empty() ? "" : " - " + error_message), 31482 | exprtk_error_location)); 31483 | 31484 | } 31485 | else if (unknown_symbol_resolver::e_usrmode_extended == unknown_symbol_resolver_->mode) 31486 | { 31487 | if (unknown_symbol_resolver_->process(symbol, symtab, error_message)) 31488 | { 31489 | expression_node_ptr result = parse_symtab_symbol(); 31490 | 31491 | if (result) 31492 | { 31493 | return result; 31494 | } 31495 | } 31496 | 31497 | set_error(make_error( 31498 | parser_error::e_symtab, 31499 | current_token(), 31500 | "ERR238 - Failed to resolve symbol: '" + symbol + "'" + 31501 | (error_message.empty() ? "" : " - " + error_message), 31502 | exprtk_error_location)); 31503 | } 31504 | 31505 | return error_node(); 31506 | } 31507 | } 31508 | 31509 | set_error(make_error( 31510 | parser_error::e_syntax, 31511 | current_token(), 31512 | "ERR239 - Undefined symbol: '" + symbol + "'", 31513 | exprtk_error_location)); 31514 | 31515 | return error_node(); 31516 | } 31517 | 31518 | inline expression_node_ptr check_block_statement_closure(expression_node_ptr expression) 31519 | { 31520 | if ( 31521 | expression && 31522 | ( 31523 | (current_token().type == token_t::e_symbol) || 31524 | (current_token().type == token_t::e_number) 31525 | ) 31526 | ) 31527 | { 31528 | free_node(node_allocator_, expression); 31529 | 31530 | set_error(make_error( 31531 | parser_error::e_syntax, 31532 | current_token(), 31533 | "ERR240 - Invalid syntax '" + current_token().value + "' possible missing operator or context", 31534 | exprtk_error_location)); 31535 | 31536 | return error_node(); 31537 | } 31538 | 31539 | return expression; 31540 | } 31541 | 31542 | inline expression_node_ptr parse_symbol() 31543 | { 31544 | static const std::string symbol_if = "if" ; 31545 | static const std::string symbol_while = "while" ; 31546 | static const std::string symbol_repeat = "repeat" ; 31547 | static const std::string symbol_for = "for" ; 31548 | static const std::string symbol_switch = "switch" ; 31549 | static const std::string symbol_null = "null" ; 31550 | static const std::string symbol_break = "break" ; 31551 | static const std::string symbol_continue = "continue" 31552 | static const std::string symbol_var = "var" ; 31553 | static const std::string symbol_const = "const" ; 31554 | static const std::string symbol_swap = "swap" ; 31555 | static const std::string symbol_return = "return" ; 31556 | static const std::string symbol_not = "not" ; 31557 | static const std::string symbol_assert = "assert" ; 31558 | 31559 | const std::string symbol = current_token().value; 31560 | 31561 | if (valid_vararg_operation(symbol)) 31562 | { 31563 | return parse_vararg_function(); 31564 | } 31565 | else if (details::imatch(symbol, symbol_not)) 31566 | { 31567 | return parse_not_statement(); 31568 | } 31569 | else if (valid_base_operation(symbol)) 31570 | { 31571 | return parse_base_operation(); 31572 | } 31573 | else if ( 31574 | details::imatch(symbol, symbol_if) && 31575 | settings_.control_struct_enabled(symbol) 31576 | ) 31577 | { 31578 | return parse_conditional_statement(); 31579 | } 31580 | else if ( 31581 | details::imatch(symbol, symbol_while) && 31582 | settings_.control_struct_enabled(symbol) 31583 | ) 31584 | { 31585 | return check_block_statement_closure(parse_while_loop()); 31586 | } 31587 | else if ( 31588 | details::imatch(symbol, symbol_repeat) && 31589 | settings_.control_struct_enabled(symbol) 31590 | ) 31591 | { 31592 | return check_block_statement_closure(parse_repeat_until_loop()); 31593 | } 31594 | else if ( 31595 | details::imatch(symbol, symbol_for) && 31596 | settings_.control_struct_enabled(symbol) 31597 | ) 31598 | { 31599 | return check_block_statement_closure(parse_for_loop()); 31600 | } 31601 | else if ( 31602 | details::imatch(symbol, symbol_switch) && 31603 | settings_.control_struct_enabled(symbol) 31604 | ) 31605 | { 31606 | return check_block_statement_closure(parse_switch_statement()); 31607 | } 31608 | else if (details::is_valid_sf_symbol(symbol)) 31609 | { 31610 | return parse_special_function(); 31611 | } 31612 | else if (details::imatch(symbol, symbol_null)) 31613 | { 31614 | return parse_null_statement(); 31615 | } 31616 | #ifndef exprtk_disable_break_continue 31617 | else if (details::imatch(symbol, symbol_break)) 31618 | { 31619 | return parse_break_statement(); 31620 | } 31621 | else if (details::imatch(symbol, symbol_continue)) 31622 | { 31623 | return parse_continue_statement(); 31624 | } 31625 | #endif 31626 | else if (details::imatch(symbol, symbol_var)) 31627 | { 31628 | return parse_define_var_statement(); 31629 | } 31630 | else if (details::imatch(symbol, symbol_const)) 31631 | { 31632 | return parse_define_constvar_statement(); 31633 | } 31634 | else if (details::imatch(symbol, symbol_swap)) 31635 | { 31636 | return parse_swap_statement(); 31637 | } 31638 | #ifndef exprtk_disable_return_statement 31639 | else if ( 31640 | details::imatch(symbol, symbol_return) && 31641 | settings_.control_struct_enabled(symbol) 31642 | ) 31643 | { 31644 | return check_block_statement_closure(parse_return_statement()); 31645 | } 31646 | #endif 31647 | else if (details::imatch(symbol, symbol_assert)) 31648 | { 31649 | return parse_assert_statement(); 31650 | } 31651 | else if (symtab_store_.valid() || !sem_.empty()) 31652 | { 31653 | return parse_symtab_symbol(); 31654 | } 31655 | else 31656 | { 31657 | set_error(make_error( 31658 | parser_error::e_symtab, 31659 | current_token(), 31660 | "ERR241 - Unknown variable or function encountered. Symbol table(s) " 31661 | "is either invalid or does not contain symbol: '" + symbol + "'", 31662 | exprtk_error_location)); 31663 | 31664 | return error_node(); 31665 | } 31666 | } 31667 | 31668 | inline expression_node_ptr parse_branch(precedence_level precedence = e_level00) 31669 | { 31670 | stack_limit_handler slh(*this); 31671 | 31672 | if (!slh) 31673 | { 31674 | return error_node(); 31675 | } 31676 | 31677 | expression_node_ptr branch = error_node(); 31678 | 31679 | if (token_t::e_number == current_token().type) 31680 | { 31681 | T numeric_value = T(0); 31682 | 31683 | if (details::string_to_real(current_token().value, numeric_value)) 31684 | { 31685 | expression_node_ptr literal_exp = expression_generator_(numeric_value); 31686 | 31687 | if (0 == literal_exp) 31688 | { 31689 | set_error(make_error( 31690 | parser_error::e_numeric, 31691 | current_token(), 31692 | "ERR242 - Failed generate node for scalar: '" + current_token().value + "'", 31693 | exprtk_error_location)); 31694 | 31695 | return error_node(); 31696 | } 31697 | 31698 | next_token(); 31699 | branch = literal_exp; 31700 | } 31701 | else 31702 | { 31703 | set_error(make_error( 31704 | parser_error::e_numeric, 31705 | current_token(), 31706 | "ERR243 - Failed to convert '" + current_token().value + "' to a number", 31707 | exprtk_error_location)); 31708 | 31709 | return error_node(); 31710 | } 31711 | } 31712 | else if (token_t::e_symbol == current_token().type) 31713 | { 31714 | branch = parse_symbol(); 31715 | } 31716 | #ifndef exprtk_disable_string_capabilities 31717 | else if (token_t::e_string == current_token().type) 31718 | { 31719 | branch = parse_const_string(); 31720 | } 31721 | #endif 31722 | else if (token_t::e_lbracket == current_token().type) 31723 | { 31724 | next_token(); 31725 | 31726 | if (0 == (branch = parse_expression())) 31727 | { 31728 | return error_node(); 31729 | } 31730 | 31731 | token_is(token_t::e_eof); 31732 | 31733 | if (!token_is(token_t::e_rbracket)) 31734 | { 31735 | set_error(make_error( 31736 | parser_error::e_syntax, 31737 | current_token(), 31738 | "ERR244 - Expected ')' instead of: '" + current_token().value + "'", 31739 | exprtk_error_location)); 31740 | 31741 | details::free_node(node_allocator_, branch); 31742 | 31743 | return error_node(); 31744 | } 31745 | else if (!post_bracket_process(token_t::e_lbracket,branch)) 31746 | { 31747 | details::free_node(node_allocator_, branch); 31748 | 31749 | return error_node(); 31750 | } 31751 | 31752 | parse_pending_vector_index_operator(branch); 31753 | } 31754 | else if (token_t::e_lsqrbracket == current_token().type) 31755 | { 31756 | next_token(); 31757 | 31758 | if (0 == (branch = parse_expression())) 31759 | return error_node(); 31760 | else if (!token_is(token_t::e_rsqrbracket)) 31761 | { 31762 | set_error(make_error( 31763 | parser_error::e_syntax, 31764 | current_token(), 31765 | "ERR245 - Expected ']' instead of: '" + current_token().value + "'", 31766 | exprtk_error_location)); 31767 | 31768 | details::free_node(node_allocator_, branch); 31769 | 31770 | return error_node(); 31771 | } 31772 | else if (!post_bracket_process(token_t::e_lsqrbracket,branch)) 31773 | { 31774 | details::free_node(node_allocator_, branch); 31775 | 31776 | return error_node(); 31777 | } 31778 | } 31779 | else if (token_t::e_lcrlbracket == current_token().type) 31780 | { 31781 | next_token(); 31782 | 31783 | if (0 == (branch = parse_expression())) 31784 | return error_node(); 31785 | else if (!token_is(token_t::e_rcrlbracket)) 31786 | { 31787 | set_error(make_error( 31788 | parser_error::e_syntax, 31789 | current_token(), 31790 | "ERR246 - Expected '}' instead of: '" + current_token().value + "'", 31791 | exprtk_error_location)); 31792 | 31793 | details::free_node(node_allocator_, branch); 31794 | 31795 | return error_node(); 31796 | } 31797 | else if (!post_bracket_process(token_t::e_lcrlbracket,branch)) 31798 | { 31799 | details::free_node(node_allocator_, branch); 31800 | 31801 | return error_node(); 31802 | } 31803 | } 31804 | else if (token_t::e_sub == current_token().type) 31805 | { 31806 | next_token(); 31807 | branch = parse_expression(e_level11); 31808 | 31809 | if ( 31810 | branch && 31811 | !( 31812 | details::is_neg_unary_node (branch) && 31813 | simplify_unary_negation_branch(branch) 31814 | ) 31815 | ) 31816 | { 31817 | expression_node_ptr result = expression_generator_(details::e_neg,branch); 31818 | 31819 | if (0 == result) 31820 | { 31821 | details::free_node(node_allocator_, branch); 31822 | 31823 | return error_node(); 31824 | } 31825 | else 31826 | branch = result; 31827 | } 31828 | } 31829 | else if (token_t::e_add == current_token().type) 31830 | { 31831 | next_token(); 31832 | branch = parse_expression(e_level13); 31833 | } 31834 | else if (token_t::e_eof == current_token().type) 31835 | { 31836 | set_error(make_error( 31837 | parser_error::e_syntax, 31838 | current_token(), 31839 | "ERR247 - Premature end of expression[1]", 31840 | exprtk_error_location)); 31841 | 31842 | return error_node(); 31843 | } 31844 | else 31845 | { 31846 | set_error(make_error( 31847 | parser_error::e_syntax, 31848 | current_token(), 31849 | "ERR248 - Premature end of expression[2]", 31850 | exprtk_error_location)); 31851 | 31852 | return error_node(); 31853 | } 31854 | 31855 | if ( 31856 | branch && 31857 | (e_level00 == precedence) && 31858 | token_is(token_t::e_ternary,prsrhlpr_t::e_hold) 31859 | ) 31860 | { 31861 | branch = parse_ternary_conditional_statement(branch); 31862 | } 31863 | 31864 | parse_pending_string_rangesize(branch); 31865 | 31866 | return branch; 31867 | } 31868 | 31869 | template <typename Type> 31870 | class expression_generator 31871 | { 31872 | public: 31873 | 31874 | typedef details::expression_node<Type>* expression_node_ptr; 31875 | typedef expression_node_ptr (*synthesize_functor_t)(expression_generator<T>&, const details::operator_type& operation, expression_node_ptr (&branch)[2]); 31876 | typedef std::map<std::string,synthesize_functor_t> synthesize_map_t; 31877 | typedef typename exprtk::parser<Type> parser_t; 31878 | typedef const Type& vtype; 31879 | typedef const Type ctype; 31880 | 31881 | inline void init_synthesize_map() 31882 | { 31883 | #ifndef exprtk_disable_enhanced_features 31884 | synthesize_map_["(v)o(v)"] = synthesize_vov_expression::process; 31885 | synthesize_map_["(c)o(v)"] = synthesize_cov_expression::process; 31886 | synthesize_map_["(v)o(c)"] = synthesize_voc_expression::process; 31887 | 31888 | #define register_synthezier(S) \ 31889 | synthesize_map_[S ::node_type::id()] = S ::process; \ 31890 | 31891 | register_synthezier(synthesize_vovov_expression0) 31892 | register_synthezier(synthesize_vovov_expression1) 31893 | register_synthezier(synthesize_vovoc_expression0) 31894 | register_synthezier(synthesize_vovoc_expression1) 31895 | register_synthezier(synthesize_vocov_expression0) 31896 | register_synthezier(synthesize_vocov_expression1) 31897 | register_synthezier(synthesize_covov_expression0) 31898 | register_synthezier(synthesize_covov_expression1) 31899 | register_synthezier(synthesize_covoc_expression0) 31900 | register_synthezier(synthesize_covoc_expression1) 31901 | register_synthezier(synthesize_cocov_expression1) 31902 | register_synthezier(synthesize_vococ_expression0) 31903 | 31904 | register_synthezier(synthesize_vovovov_expression0) 31905 | register_synthezier(synthesize_vovovoc_expression0) 31906 | register_synthezier(synthesize_vovocov_expression0) 31907 | register_synthezier(synthesize_vocovov_expression0) 31908 | register_synthezier(synthesize_covovov_expression0) 31909 | register_synthezier(synthesize_covocov_expression0) 31910 | register_synthezier(synthesize_vocovoc_expression0) 31911 | register_synthezier(synthesize_covovoc_expression0) 31912 | register_synthezier(synthesize_vococov_expression0) 31913 | 31914 | register_synthezier(synthesize_vovovov_expression1) 31915 | register_synthezier(synthesize_vovovoc_expression1) 31916 | register_synthezier(synthesize_vovocov_expression1) 31917 | register_synthezier(synthesize_vocovov_expression1) 31918 | register_synthezier(synthesize_covovov_expression1) 31919 | register_synthezier(synthesize_covocov_expression1) 31920 | register_synthezier(synthesize_vocovoc_expression1) 31921 | register_synthezier(synthesize_covovoc_expression1) 31922 | register_synthezier(synthesize_vococov_expression1) 31923 | 31924 | register_synthezier(synthesize_vovovov_expression2) 31925 | register_synthezier(synthesize_vovovoc_expression2) 31926 | register_synthezier(synthesize_vovocov_expression2) 31927 | register_synthezier(synthesize_vocovov_expression2) 31928 | register_synthezier(synthesize_covovov_expression2) 31929 | register_synthezier(synthesize_covocov_expression2) 31930 | register_synthezier(synthesize_vocovoc_expression2) 31931 | register_synthezier(synthesize_covovoc_expression2) 31932 | 31933 | register_synthezier(synthesize_vovovov_expression3) 31934 | register_synthezier(synthesize_vovovoc_expression3) 31935 | register_synthezier(synthesize_vovocov_expression3) 31936 | register_synthezier(synthesize_vocovov_expression3) 31937 | register_synthezier(synthesize_covovov_expression3) 31938 | register_synthezier(synthesize_covocov_expression3) 31939 | register_synthezier(synthesize_vocovoc_expression3) 31940 | register_synthezier(synthesize_covovoc_expression3) 31941 | register_synthezier(synthesize_vococov_expression3) 31942 | 31943 | register_synthezier(synthesize_vovovov_expression4) 31944 | register_synthezier(synthesize_vovovoc_expression4) 31945 | register_synthezier(synthesize_vovocov_expression4) 31946 | register_synthezier(synthesize_vocovov_expression4) 31947 | register_synthezier(synthesize_covovov_expression4) 31948 | register_synthezier(synthesize_covocov_expression4) 31949 | register_synthezier(synthesize_vocovoc_expression4) 31950 | register_synthezier(synthesize_covovoc_expression4) 31951 | 31952 | #undef register_synthezier 31953 | #endif 31954 | } 31955 | 31956 | inline void set_parser(parser_t& p) 31957 | { 31958 | parser_ = &p; 31959 | } 31960 | 31961 | inline void set_uom(unary_op_map_t& unary_op_map) 31962 | { 31963 | unary_op_map_ = &unary_op_map; 31964 | } 31965 | 31966 | inline void set_bom(binary_op_map_t& binary_op_map) 31967 | { 31968 | binary_op_map_ = &binary_op_map; 31969 | } 31970 | 31971 | inline void set_ibom(inv_binary_op_map_t& inv_binary_op_map) 31972 | { 31973 | inv_binary_op_map_ = &inv_binary_op_map; 31974 | } 31975 | 31976 | inline void set_sf3m(sf3_map_t& sf3_map) 31977 | { 31978 | sf3_map_ = &sf3_map; 31979 | } 31980 | 31981 | inline void set_sf4m(sf4_map_t& sf4_map) 31982 | { 31983 | sf4_map_ = &sf4_map; 31984 | } 31985 | 31986 | inline void set_allocator(details::node_allocator& na) 31987 | { 31988 | node_allocator_ = &na; 31989 | } 31990 | 31991 | inline void set_strength_reduction_state(const bool enabled) 31992 | { 31993 | strength_reduction_enabled_ = enabled; 31994 | } 31995 | 31996 | inline bool strength_reduction_enabled() const 31997 | { 31998 | return strength_reduction_enabled_; 31999 | } 32000 | 32001 | inline bool valid_operator(const details::operator_type& operation, binary_functor_t& bop) 32002 | { 32003 | typename binary_op_map_t::iterator bop_itr = binary_op_map_->find(operation); 32004 | 32005 | if (binary_op_map_->end() == bop_itr) 32006 | return false; 32007 | 32008 | bop = bop_itr->second; 32009 | 32010 | return true; 32011 | } 32012 | 32013 | inline bool valid_operator(const details::operator_type& operation, unary_functor_t& uop) 32014 | { 32015 | typename unary_op_map_t::iterator uop_itr = unary_op_map_->find(operation); 32016 | 32017 | if ((*unary_op_map_).end() == uop_itr) 32018 | return false; 32019 | 32020 | uop = uop_itr->second; 32021 | 32022 | return true; 32023 | } 32024 | 32025 | inline details::operator_type get_operator(const binary_functor_t& bop) const 32026 | { 32027 | return (*inv_binary_op_map_).find(bop)->second; 32028 | } 32029 | 32030 | inline expression_node_ptr operator() (const Type& v) const 32031 | { 32032 | return node_allocator_->allocate<literal_node_t>(v); 32033 | } 32034 | 32035 | #ifndef exprtk_disable_string_capabilities 32036 | inline expression_node_ptr operator() (const std::string& s) const 32037 | { 32038 | return node_allocator_->allocate<string_literal_node_t>(s); 32039 | } 32040 | 32041 | inline expression_node_ptr operator() (std::string& s, range_t& rp) const 32042 | { 32043 | return node_allocator_->allocate_rr<string_range_node_t>(s,rp); 32044 | } 32045 | 32046 | inline expression_node_ptr operator() (const std::string& s, range_t& rp) const 32047 | { 32048 | return node_allocator_->allocate_tt<const_string_range_node_t>(s,rp); 32049 | } 32050 | 32051 | inline expression_node_ptr operator() (expression_node_ptr branch, range_t& rp) const 32052 | { 32053 | if (is_generally_string_node(branch)) 32054 | return node_allocator_->allocate_tt<generic_string_range_node_t>(branch,rp); 32055 | else 32056 | return error_node(); 32057 | } 32058 | #endif 32059 | 32060 | inline bool unary_optimisable(const details::operator_type& operation) const 32061 | { 32062 | return (details::e_abs == operation) || (details::e_acos == operation) || 32063 | (details::e_acosh == operation) || (details::e_asin == operation) || 32064 | (details::e_asinh == operation) || (details::e_atan == operation) || 32065 | (details::e_atanh == operation) || (details::e_ceil == operation) || 32066 | (details::e_cos == operation) || (details::e_cosh == operation) || 32067 | (details::e_exp == operation) || (details::e_expm1 == operation) || 32068 | (details::e_floor == operation) || (details::e_log == operation) || 32069 | (details::e_log10 == operation) || (details::e_log2 == operation) || 32070 | (details::e_log1p == operation) || (details::e_neg == operation) || 32071 | (details::e_pos == operation) || (details::e_round == operation) || 32072 | (details::e_sin == operation) || (details::e_sinc == operation) || 32073 | (details::e_sinh == operation) || (details::e_sqrt == operation) || 32074 | (details::e_tan == operation) || (details::e_tanh == operation) || 32075 | (details::e_cot == operation) || (details::e_sec == operation) || 32076 | (details::e_csc == operation) || (details::e_r2d == operation) || 32077 | (details::e_d2r == operation) || (details::e_d2g == operation) || 32078 | (details::e_g2d == operation) || (details::e_notl == operation) || 32079 | (details::e_sgn == operation) || (details::e_erf == operation) || 32080 | (details::e_erfc == operation) || (details::e_ncdf == operation) || 32081 | (details::e_frac == operation) || (details::e_trunc == operation) ; 32082 | } 32083 | 32084 | inline bool sf3_optimisable(const std::string& sf3id, trinary_functor_t& tfunc) const 32085 | { 32086 | typename sf3_map_t::const_iterator itr = sf3_map_->find(sf3id); 32087 | 32088 | if (sf3_map_->end() == itr) 32089 | return false; 32090 | else 32091 | tfunc = itr->second.first; 32092 | 32093 | return true; 32094 | } 32095 | 32096 | inline bool sf4_optimisable(const std::string& sf4id, quaternary_functor_t& qfunc) const 32097 | { 32098 | typename sf4_map_t::const_iterator itr = sf4_map_->find(sf4id); 32099 | 32100 | if (sf4_map_->end() == itr) 32101 | return false; 32102 | else 32103 | qfunc = itr->second.first; 32104 | 32105 | return true; 32106 | } 32107 | 32108 | inline bool sf3_optimisable(const std::string& sf3id, details::operator_type& operation) const 32109 | { 32110 | typename sf3_map_t::const_iterator itr = sf3_map_->find(sf3id); 32111 | 32112 | if (sf3_map_->end() == itr) 32113 | return false; 32114 | else 32115 | operation = itr->second.second; 32116 | 32117 | return true; 32118 | } 32119 | 32120 | inline bool sf4_optimisable(const std::string& sf4id, details::operator_type& operation) const 32121 | { 32122 | typename sf4_map_t::const_iterator itr = sf4_map_->find(sf4id); 32123 | 32124 | if (sf4_map_->end() == itr) 32125 | return false; 32126 | else 32127 | operation = itr->second.second; 32128 | 32129 | return true; 32130 | } 32131 | 32132 | inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[1]) 32133 | { 32134 | if (0 == branch[0]) 32135 | { 32136 | return error_node(); 32137 | } 32138 | else if (details::is_null_node(branch[0])) 32139 | { 32140 | return branch[0]; 32141 | } 32142 | else if (details::is_break_node(branch[0])) 32143 | { 32144 | parser_->set_error(parser_error::make_error( 32145 | parser_error::e_syntax, 32146 | parser_->current_state().token, 32147 | "ERR249 - Invalid use of break statement", 32148 | exprtk_error_location)); 32149 | 32150 | parser_->node_allocator_.free(branch[0]); 32151 | 32152 | return error_node(); 32153 | } 32154 | else if (details::is_continue_node(branch[0])) 32155 | { 32156 | parser_->set_error(parser_error::make_error( 32157 | parser_error::e_syntax, 32158 | parser_->current_state().token, 32159 | "ERR250 - Invalid use of continue statement", 32160 | exprtk_error_location)); 32161 | 32162 | parser_->node_allocator_.free(branch[0]); 32163 | 32164 | return error_node(); 32165 | } 32166 | else if (details::is_constant_node(branch[0])) 32167 | { 32168 | return synthesize_expression<unary_node_t,1>(operation,branch); 32169 | } 32170 | else if (unary_optimisable(operation) && details::is_variable_node(branch[0])) 32171 | { 32172 | return synthesize_uv_expression(operation,branch); 32173 | } 32174 | else if (unary_optimisable(operation) && details::is_ivector_node(branch[0])) 32175 | { 32176 | return synthesize_uvec_expression(operation,branch); 32177 | } 32178 | else 32179 | return synthesize_unary_expression(operation,branch); 32180 | } 32181 | 32182 | inline bool is_assignment_operation(const details::operator_type& operation) const 32183 | { 32184 | return ( 32185 | (details::e_addass == operation) || 32186 | (details::e_subass == operation) || 32187 | (details::e_mulass == operation) || 32188 | (details::e_divass == operation) || 32189 | (details::e_modass == operation) 32190 | ) && 32191 | parser_->settings_.assignment_enabled(operation); 32192 | } 32193 | 32194 | #ifndef exprtk_disable_string_capabilities 32195 | inline bool valid_string_operation(const details::operator_type& operation) const 32196 | { 32197 | return (details::e_add == operation) || 32198 | (details::e_lt == operation) || 32199 | (details::e_lte == operation) || 32200 | (details::e_gt == operation) || 32201 | (details::e_gte == operation) || 32202 | (details::e_eq == operation) || 32203 | (details::e_ne == operation) || 32204 | (details::e_in == operation) || 32205 | (details::e_like == operation) || 32206 | (details::e_ilike == operation) || 32207 | (details::e_assign == operation) || 32208 | (details::e_addass == operation) || 32209 | (details::e_swap == operation) ; 32210 | } 32211 | #else 32212 | inline bool valid_string_operation(const details::operator_type&) const 32213 | { 32214 | return false; 32215 | } 32216 | #endif 32217 | 32218 | inline std::string to_str(const details::operator_type& operation) const 32219 | { 32220 | switch (operation) 32221 | { 32222 | case details::e_add : return "+" ; 32223 | case details::e_sub : return "-" ; 32224 | case details::e_mul : return "*" ; 32225 | case details::e_div : return "/" ; 32226 | case details::e_mod : return "%" ; 32227 | case details::e_pow : return "^" ; 32228 | case details::e_lt : return "<" ; 32229 | case details::e_lte : return "<=" ; 32230 | case details::e_gt : return ">" ; 32231 | case details::e_gte : return ">=" ; 32232 | case details::e_eq : return "==" ; 32233 | case details::e_ne : return "!=" ; 32234 | case details::e_and : return "and" ; 32235 | case details::e_nand : return "nand" ; 32236 | case details::e_or : return "or" ; 32237 | case details::e_nor : return "nor" ; 32238 | case details::e_xor : return "xor" ; 32239 | case details::e_xnor : return "xnor" ; 32240 | default : return "UNKNOWN" 32241 | } 32242 | } 32243 | 32244 | inline bool operation_optimisable(const details::operator_type& operation) const 32245 | { 32246 | return (details::e_add == operation) || 32247 | (details::e_sub == operation) || 32248 | (details::e_mul == operation) || 32249 | (details::e_div == operation) || 32250 | (details::e_mod == operation) || 32251 | (details::e_pow == operation) || 32252 | (details::e_lt == operation) || 32253 | (details::e_lte == operation) || 32254 | (details::e_gt == operation) || 32255 | (details::e_gte == operation) || 32256 | (details::e_eq == operation) || 32257 | (details::e_ne == operation) || 32258 | (details::e_and == operation) || 32259 | (details::e_nand == operation) || 32260 | (details::e_or == operation) || 32261 | (details::e_nor == operation) || 32262 | (details::e_xor == operation) || 32263 | (details::e_xnor == operation) ; 32264 | } 32265 | 32266 | inline std::string branch_to_id(expression_node_ptr branch) const 32267 | { 32268 | static const std::string null_str ("(null)" ); 32269 | static const std::string const_str ("(c)" ); 32270 | static const std::string var_str ("(v)" ); 32271 | static const std::string vov_str ("(vov)" ); 32272 | static const std::string cov_str ("(cov)" ); 32273 | static const std::string voc_str ("(voc)" ); 32274 | static const std::string str_str ("(s)" ); 32275 | static const std::string strrng_str ("(rngs)" ); 32276 | static const std::string cs_str ("(cs)" ); 32277 | static const std::string cstrrng_str("(crngs)"); 32278 | 32279 | if (details::is_null_node(branch)) 32280 | return null_str; 32281 | else if (details::is_constant_node(branch)) 32282 | return const_str; 32283 | else if (details::is_variable_node(branch)) 32284 | return var_str; 32285 | else if (details::is_vov_node(branch)) 32286 | return vov_str; 32287 | else if (details::is_cov_node(branch)) 32288 | return cov_str; 32289 | else if (details::is_voc_node(branch)) 32290 | return voc_str; 32291 | else if (details::is_string_node(branch)) 32292 | return str_str; 32293 | else if (details::is_const_string_node(branch)) 32294 | return cs_str; 32295 | else if (details::is_string_range_node(branch)) 32296 | return strrng_str; 32297 | else if (details::is_const_string_range_node(branch)) 32298 | return cstrrng_str; 32299 | else if (details::is_t0ot1ot2_node(branch)) 32300 | return "(" + dynamic_cast<details::T0oT1oT2_base_node<T>*>(branch)->type_id() + ")" 32301 | else if (details::is_t0ot1ot2ot3_node(branch)) 32302 | return "(" + dynamic_cast<details::T0oT1oT2oT3_base_node<T>*>(branch)->type_id() + ")" 32303 | else 32304 | return "ERROR" 32305 | } 32306 | 32307 | inline std::string branch_to_id(expression_node_ptr (&branch)[2]) const 32308 | { 32309 | return branch_to_id(branch[0]) + std::string("o") + branch_to_id(branch[1]); 32310 | } 32311 | 32312 | inline bool cov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32313 | { 32314 | if (!operation_optimisable(operation)) 32315 | return false; 32316 | else 32317 | return details::is_constant_node(branch[0]) && 32318 | details::is_variable_node(branch[1]) ; 32319 | } 32320 | 32321 | inline bool voc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32322 | { 32323 | if (!operation_optimisable(operation)) 32324 | return false; 32325 | else 32326 | return details::is_variable_node(branch[0]) && 32327 | details::is_constant_node(branch[1]) ; 32328 | } 32329 | 32330 | inline bool vov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32331 | { 32332 | if (!operation_optimisable(operation)) 32333 | return false; 32334 | else 32335 | return details::is_variable_node(branch[0]) && 32336 | details::is_variable_node(branch[1]) ; 32337 | } 32338 | 32339 | inline bool cob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32340 | { 32341 | if (!operation_optimisable(operation)) 32342 | return false; 32343 | else 32344 | return details::is_constant_node(branch[0]) && 32345 | !details::is_constant_node(branch[1]) ; 32346 | } 32347 | 32348 | inline bool boc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32349 | { 32350 | if (!operation_optimisable(operation)) 32351 | return false; 32352 | else 32353 | return !details::is_constant_node(branch[0]) && 32354 | details::is_constant_node(branch[1]) ; 32355 | } 32356 | 32357 | inline bool cocob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32358 | { 32359 | if ( 32360 | (details::e_add == operation) || 32361 | (details::e_sub == operation) || 32362 | (details::e_mul == operation) || 32363 | (details::e_div == operation) 32364 | ) 32365 | { 32366 | return (details::is_constant_node(branch[0]) && details::is_cob_node(branch[1])) || 32367 | (details::is_constant_node(branch[1]) && details::is_cob_node(branch[0])) ; 32368 | } 32369 | else 32370 | return false; 32371 | } 32372 | 32373 | inline bool coboc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32374 | { 32375 | if ( 32376 | (details::e_add == operation) || 32377 | (details::e_sub == operation) || 32378 | (details::e_mul == operation) || 32379 | (details::e_div == operation) 32380 | ) 32381 | { 32382 | return (details::is_constant_node(branch[0]) && details::is_boc_node(branch[1])) || 32383 | (details::is_constant_node(branch[1]) && details::is_boc_node(branch[0])) ; 32384 | } 32385 | else 32386 | return false; 32387 | } 32388 | 32389 | inline bool uvouv_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32390 | { 32391 | if (!operation_optimisable(operation)) 32392 | return false; 32393 | else 32394 | return details::is_uv_node(branch[0]) && 32395 | details::is_uv_node(branch[1]) ; 32396 | } 32397 | 32398 | inline bool vob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32399 | { 32400 | if (!operation_optimisable(operation)) 32401 | return false; 32402 | else 32403 | return details::is_variable_node(branch[0]) && 32404 | !details::is_variable_node(branch[1]) ; 32405 | } 32406 | 32407 | inline bool bov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32408 | { 32409 | if (!operation_optimisable(operation)) 32410 | return false; 32411 | else 32412 | return !details::is_variable_node(branch[0]) && 32413 | details::is_variable_node(branch[1]) ; 32414 | } 32415 | 32416 | inline bool binext_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32417 | { 32418 | if (!operation_optimisable(operation)) 32419 | return false; 32420 | else 32421 | return !details::is_constant_node(branch[0]) || 32422 | !details::is_constant_node(branch[1]) ; 32423 | } 32424 | 32425 | inline bool is_invalid_assignment_op(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32426 | { 32427 | if (is_assignment_operation(operation)) 32428 | { 32429 | const bool b1_is_genstring = details::is_generally_string_node(branch[1]); 32430 | 32431 | if (details::is_string_node(branch[0])) 32432 | return !b1_is_genstring; 32433 | else if (details::is_literal_node(branch[0])) 32434 | return true; 32435 | else 32436 | return ( 32437 | !details::is_variable_node (branch[0]) && 32438 | !details::is_vector_elem_node (branch[0]) && 32439 | !details::is_vector_celem_node (branch[0]) && 32440 | !details::is_vector_elem_rtc_node (branch[0]) && 32441 | !details::is_vector_celem_rtc_node (branch[0]) && 32442 | !details::is_rebasevector_elem_node (branch[0]) && 32443 | !details::is_rebasevector_celem_node (branch[0]) && 32444 | !details::is_rebasevector_elem_rtc_node (branch[0]) && 32445 | !details::is_rebasevector_celem_rtc_node(branch[0]) && 32446 | !details::is_vector_node (branch[0]) 32447 | ) 32448 | || b1_is_genstring; 32449 | } 32450 | else 32451 | return false; 32452 | } 32453 | 32454 | inline bool is_constpow_operation(const details::operator_type& operation, expression_node_ptr(&branch)[2]) const 32455 | { 32456 | if ( 32457 | !details::is_constant_node(branch[1]) || 32458 | details::is_constant_node(branch[0]) || 32459 | details::is_variable_node(branch[0]) || 32460 | details::is_vector_node (branch[0]) || 32461 | details::is_generally_string_node(branch[0]) 32462 | ) 32463 | return false; 32464 | 32465 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 32466 | 32467 | return cardinal_pow_optimisable(operation, c); 32468 | } 32469 | 32470 | inline bool is_invalid_break_continue_op(expression_node_ptr (&branch)[2]) const 32471 | { 32472 | return ( 32473 | details::is_break_node (branch[0]) || 32474 | details::is_break_node (branch[1]) || 32475 | details::is_continue_node(branch[0]) || 32476 | details::is_continue_node(branch[1]) 32477 | ); 32478 | } 32479 | 32480 | inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32481 | { 32482 | const bool b0_string = is_generally_string_node(branch[0]); 32483 | const bool b1_string = is_generally_string_node(branch[1]); 32484 | 32485 | bool result = false; 32486 | 32487 | if (b0_string != b1_string) 32488 | result = true; 32489 | else if (!valid_string_operation(operation) && b0_string && b1_string) 32490 | result = true; 32491 | 32492 | if (result) 32493 | { 32494 | parser_->set_synthesis_error("Invalid string operation"); 32495 | } 32496 | 32497 | return result; 32498 | } 32499 | 32500 | inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[3]) const 32501 | { 32502 | const bool b0_string = is_generally_string_node(branch[0]); 32503 | const bool b1_string = is_generally_string_node(branch[1]); 32504 | const bool b2_string = is_generally_string_node(branch[2]); 32505 | 32506 | bool result = false; 32507 | 32508 | if ((b0_string != b1_string) || (b1_string != b2_string)) 32509 | result = true; 32510 | else if ((details::e_inrange != operation) && b0_string && b1_string && b2_string) 32511 | result = true; 32512 | 32513 | if (result) 32514 | { 32515 | parser_->set_synthesis_error("Invalid string operation"); 32516 | } 32517 | 32518 | return result; 32519 | } 32520 | 32521 | inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32522 | { 32523 | const bool b0_string = is_generally_string_node(branch[0]); 32524 | const bool b1_string = is_generally_string_node(branch[1]); 32525 | 32526 | return (b0_string && b1_string && valid_string_operation(operation)); 32527 | } 32528 | 32529 | inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[3]) const 32530 | { 32531 | const bool b0_string = is_generally_string_node(branch[0]); 32532 | const bool b1_string = is_generally_string_node(branch[1]); 32533 | const bool b2_string = is_generally_string_node(branch[2]); 32534 | 32535 | return (b0_string && b1_string && b2_string && (details::e_inrange == operation)); 32536 | } 32537 | 32538 | #ifndef exprtk_disable_sc_andor 32539 | inline bool is_shortcircuit_expression(const details::operator_type& operation) const 32540 | { 32541 | return ( 32542 | (details::e_scand == operation) || 32543 | (details::e_scor == operation) 32544 | ); 32545 | } 32546 | #else 32547 | inline bool is_shortcircuit_expression(const details::operator_type&) const 32548 | { 32549 | return false; 32550 | } 32551 | #endif 32552 | 32553 | inline bool is_null_present(expression_node_ptr (&branch)[2]) const 32554 | { 32555 | return ( 32556 | details::is_null_node(branch[0]) || 32557 | details::is_null_node(branch[1]) 32558 | ); 32559 | } 32560 | 32561 | inline bool is_vector_eqineq_logic_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32562 | { 32563 | if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1])) 32564 | return false; 32565 | else 32566 | return ( 32567 | (details::e_lt == operation) || 32568 | (details::e_lte == operation) || 32569 | (details::e_gt == operation) || 32570 | (details::e_gte == operation) || 32571 | (details::e_eq == operation) || 32572 | (details::e_ne == operation) || 32573 | (details::e_equal == operation) || 32574 | (details::e_and == operation) || 32575 | (details::e_nand == operation) || 32576 | (details::e_or == operation) || 32577 | (details::e_nor == operation) || 32578 | (details::e_xor == operation) || 32579 | (details::e_xnor == operation) 32580 | ); 32581 | } 32582 | 32583 | inline bool is_vector_arithmetic_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32584 | { 32585 | if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1])) 32586 | return false; 32587 | else 32588 | return ( 32589 | (details::e_add == operation) || 32590 | (details::e_sub == operation) || 32591 | (details::e_mul == operation) || 32592 | (details::e_div == operation) || 32593 | (details::e_pow == operation) 32594 | ); 32595 | } 32596 | 32597 | inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[2]) 32598 | { 32599 | if ((0 == branch[0]) || (0 == branch[1])) 32600 | { 32601 | details::free_all_nodes(*node_allocator_, branch); 32602 | 32603 | parser_->set_error(parser_error::make_error( 32604 | parser_error::e_syntax, 32605 | parser_->current_state().token, 32606 | "ERR251 - Invalid branches received for operator '" + details::to_str(operation) + "'", 32607 | exprtk_error_location)); 32608 | 32609 | return error_node(); 32610 | } 32611 | else if (is_invalid_string_op(operation,branch)) 32612 | { 32613 | details::free_all_nodes(*node_allocator_, branch); 32614 | 32615 | parser_->set_error(parser_error::make_error( 32616 | parser_error::e_syntax, 32617 | parser_->current_state().token, 32618 | "ERR252 - Invalid branch pair for string operator '" + details::to_str(operation) + "'", 32619 | exprtk_error_location)); 32620 | 32621 | return error_node(); 32622 | } 32623 | else if (is_invalid_assignment_op(operation,branch)) 32624 | { 32625 | details::free_all_nodes(*node_allocator_, branch); 32626 | 32627 | parser_->set_error(parser_error::make_error( 32628 | parser_error::e_syntax, 32629 | parser_->current_state().token, 32630 | "ERR253 - Invalid branch pair for assignment operator '" + details::to_str(operation) + "'", 32631 | exprtk_error_location)); 32632 | 32633 | return error_node(); 32634 | } 32635 | else if (is_invalid_break_continue_op(branch)) 32636 | { 32637 | details::free_all_nodes(*node_allocator_, branch); 32638 | 32639 | parser_->set_error(parser_error::make_error( 32640 | parser_error::e_syntax, 32641 | parser_->current_state().token, 32642 | "ERR254 - Invalid branch pair for break/continue operator '" + details::to_str(operation) + "'", 32643 | exprtk_error_location)); 32644 | 32645 | return error_node(); 32646 | } 32647 | else if (details::e_assign == operation) 32648 | { 32649 | return synthesize_assignment_expression(operation, branch); 32650 | } 32651 | else if (details::e_swap == operation) 32652 | { 32653 | return synthesize_swap_expression(branch); 32654 | } 32655 | else if (is_assignment_operation(operation)) 32656 | { 32657 | return synthesize_assignment_operation_expression(operation, branch); 32658 | } 32659 | else if (is_vector_eqineq_logic_operation(operation, branch)) 32660 | { 32661 | return synthesize_veceqineqlogic_operation_expression(operation, branch); 32662 | } 32663 | else if (is_vector_arithmetic_operation(operation, branch)) 32664 | { 32665 | return synthesize_vecarithmetic_operation_expression(operation, branch); 32666 | } 32667 | else if (is_shortcircuit_expression(operation)) 32668 | { 32669 | return synthesize_shortcircuit_expression(operation, branch); 32670 | } 32671 | else if (is_string_operation(operation, branch)) 32672 | { 32673 | return synthesize_string_expression(operation, branch); 32674 | } 32675 | else if (is_null_present(branch)) 32676 | { 32677 | return synthesize_null_expression(operation, branch); 32678 | } 32679 | #ifndef exprtk_disable_cardinal_pow_optimisation 32680 | else if (is_constpow_operation(operation, branch)) 32681 | { 32682 | return cardinal_pow_optimisation(branch); 32683 | } 32684 | #endif 32685 | 32686 | expression_node_ptr result = error_node(); 32687 | 32688 | #ifndef exprtk_disable_enhanced_features 32689 | if (synthesize_expression(operation, branch, result)) 32690 | { 32691 | return result; 32692 | } 32693 | else 32694 | #endif 32695 | 32696 | { 32697 | /* 32698 | Possible reductions: 32699 | 1. c o cob -> cob 32700 | 2. cob o c -> cob 32701 | 3. c o boc -> boc 32702 | 4. boc o c -> boc 32703 | */ 32704 | result = error_node(); 32705 | 32706 | if (cocob_optimisable(operation, branch)) 32707 | { 32708 | result = synthesize_cocob_expression::process((*this), operation, branch); 32709 | } 32710 | else if (coboc_optimisable(operation, branch) && (0 == result)) 32711 | { 32712 | result = synthesize_coboc_expression::process((*this), operation, branch); 32713 | } 32714 | 32715 | if (result) 32716 | return result; 32717 | } 32718 | 32719 | if (uvouv_optimisable(operation, branch)) 32720 | { 32721 | return synthesize_uvouv_expression(operation, branch); 32722 | } 32723 | else if (vob_optimisable(operation, branch)) 32724 | { 32725 | return synthesize_vob_expression::process((*this), operation, branch); 32726 | } 32727 | else if (bov_optimisable(operation, branch)) 32728 | { 32729 | return synthesize_bov_expression::process((*this), operation, branch); 32730 | } 32731 | else if (cob_optimisable(operation, branch)) 32732 | { 32733 | return synthesize_cob_expression::process((*this), operation, branch); 32734 | } 32735 | else if (boc_optimisable(operation, branch)) 32736 | { 32737 | return synthesize_boc_expression::process((*this), operation, branch); 32738 | } 32739 | #ifndef exprtk_disable_enhanced_features 32740 | else if (cov_optimisable(operation, branch)) 32741 | { 32742 | return synthesize_cov_expression::process((*this), operation, branch); 32743 | } 32744 | #endif 32745 | else if (binext_optimisable(operation, branch)) 32746 | { 32747 | return synthesize_binary_ext_expression::process((*this), operation, branch); 32748 | } 32749 | else 32750 | return synthesize_expression<binary_node_t,2>(operation, branch); 32751 | } 32752 | 32753 | inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[3]) 32754 | { 32755 | if ( 32756 | (0 == branch[0]) || 32757 | (0 == branch[1]) || 32758 | (0 == branch[2]) 32759 | ) 32760 | { 32761 | details::free_all_nodes(*node_allocator_,branch); 32762 | 32763 | parser_->set_error(parser_error::make_error( 32764 | parser_error::e_syntax, 32765 | parser_->current_state().token, 32766 | "ERR255 - Invalid branches operator '" + details::to_str(operation) + "'", 32767 | exprtk_error_location)); 32768 | 32769 | return error_node(); 32770 | } 32771 | else if (is_invalid_string_op(operation, branch)) 32772 | { 32773 | details::free_all_nodes(*node_allocator_,branch); 32774 | 32775 | parser_->set_error(parser_error::make_error( 32776 | parser_error::e_syntax, 32777 | parser_->current_state().token, 32778 | "ERR256 - Invalid branches for string operator '" + details::to_str(operation) + "'", 32779 | exprtk_error_location)); 32780 | 32781 | return error_node(); 32782 | } 32783 | else if (is_string_operation(operation, branch)) 32784 | { 32785 | return synthesize_string_expression(operation, branch); 32786 | } 32787 | else 32788 | return synthesize_expression<trinary_node_t,3>(operation, branch); 32789 | } 32790 | 32791 | inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[4]) 32792 | { 32793 | return synthesize_expression<quaternary_node_t,4>(operation,branch); 32794 | } 32795 | 32796 | inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr b0) 32797 | { 32798 | expression_node_ptr branch[1] = { b0 }; 32799 | return (*this)(operation,branch); 32800 | } 32801 | 32802 | inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr& b0, expression_node_ptr& b1) 32803 | { 32804 | expression_node_ptr result = error_node(); 32805 | 32806 | if ((0 != b0) && (0 != b1)) 32807 | { 32808 | expression_node_ptr branch[2] = { b0, b1 }; 32809 | result = expression_generator<Type>::operator()(operation, branch); 32810 | b0 = branch[0]; 32811 | b1 = branch[1]; 32812 | } 32813 | 32814 | return result; 32815 | } 32816 | 32817 | inline expression_node_ptr conditional(expression_node_ptr condition, 32818 | expression_node_ptr consequent, 32819 | expression_node_ptr alternative) const 32820 | { 32821 | if ((0 == condition) || (0 == consequent)) 32822 | { 32823 | details::free_node(*node_allocator_, condition ); 32824 | details::free_node(*node_allocator_, consequent ); 32825 | details::free_node(*node_allocator_, alternative); 32826 | 32827 | const std::string invalid_branches = 32828 | ((0 == condition ) ? std::string("condition ") : "") + 32829 | ((0 == consequent) ? std::string("consequent") : "") ; 32830 | 32831 | parser_->set_error(parser_error::make_error( 32832 | parser_error::e_parser, 32833 | parser_->current_state().token, 32834 | "ERR257 - Invalid " + invalid_branches + " for conditional statement", 32835 | exprtk_error_location)); 32836 | 32837 | return error_node(); 32838 | } 32839 | // Can the condition be immediately evaluated? if so optimise. 32840 | else if (details::is_constant_node(condition)) 32841 | { 32842 | // True branch 32843 | if (details::is_true(condition)) 32844 | { 32845 | details::free_node(*node_allocator_, condition ); 32846 | details::free_node(*node_allocator_, alternative); 32847 | 32848 | return consequent; 32849 | } 32850 | // False branch 32851 | else 32852 | { 32853 | details::free_node(*node_allocator_, condition ); 32854 | details::free_node(*node_allocator_, consequent); 32855 | 32856 | if (alternative) 32857 | return alternative; 32858 | else 32859 | return node_allocator_->allocate<details::null_node<T> >(); 32860 | } 32861 | } 32862 | 32863 | expression_node_ptr result = error_node(); 32864 | std::string node_name = "Unknown!" 32865 | 32866 | if ((0 != consequent) && (0 != alternative)) 32867 | { 32868 | result = node_allocator_->allocate<conditional_node_t>(condition, consequent, alternative); 32869 | node_name = "conditional_node_t" 32870 | } 32871 | else 32872 | { 32873 | result = node_allocator_->allocate<cons_conditional_node_t>(condition, consequent); 32874 | node_name = "cons_conditional_node_t" 32875 | } 32876 | 32877 | if (result && result->valid()) 32878 | { 32879 | return result; 32880 | } 32881 | 32882 | parser_->set_error(parser_error::make_error( 32883 | parser_error::e_parser, 32884 | token_t(), 32885 | "ERR258 - Failed to synthesize node: " + node_name, 32886 | exprtk_error_location)); 32887 | 32888 | details::free_node(*node_allocator_, result); 32889 | return error_node(); 32890 | } 32891 | 32892 | #ifndef exprtk_disable_string_capabilities 32893 | inline expression_node_ptr conditional_string(expression_node_ptr condition, 32894 | expression_node_ptr consequent, 32895 | expression_node_ptr alternative) const 32896 | { 32897 | if ((0 == condition) || (0 == consequent)) 32898 | { 32899 | details::free_node(*node_allocator_, condition ); 32900 | details::free_node(*node_allocator_, consequent ); 32901 | details::free_node(*node_allocator_, alternative); 32902 | 32903 | const std::string invalid_branches = 32904 | ((0 == condition ) ? std::string("condition ") : "") + 32905 | ((0 == consequent) ? std::string("consequent") : "") ; 32906 | 32907 | parser_->set_error(parser_error::make_error( 32908 | parser_error::e_parser, 32909 | parser_->current_state().token, 32910 | "ERR259 - Invalid " + invalid_branches + " for string conditional statement", 32911 | exprtk_error_location)); 32912 | 32913 | return error_node(); 32914 | } 32915 | // Can the condition be immediately evaluated? if so optimise. 32916 | else if (details::is_constant_node(condition)) 32917 | { 32918 | // True branch 32919 | if (details::is_true(condition)) 32920 | { 32921 | details::free_node(*node_allocator_, condition ); 32922 | details::free_node(*node_allocator_, alternative); 32923 | 32924 | return consequent; 32925 | } 32926 | // False branch 32927 | else 32928 | { 32929 | details::free_node(*node_allocator_, condition ); 32930 | details::free_node(*node_allocator_, consequent); 32931 | 32932 | if (alternative) 32933 | return alternative; 32934 | else 32935 | return node_allocator_-> 32936 | allocate_c<details::string_literal_node<Type> >(""); 32937 | } 32938 | } 32939 | else if ((0 != consequent) && (0 != alternative)) 32940 | { 32941 | expression_node_ptr result = 32942 | node_allocator_->allocate<conditional_string_node_t>(condition, consequent, alternative); 32943 | 32944 | if (result && result->valid()) 32945 | { 32946 | return result; 32947 | } 32948 | 32949 | parser_->set_error(parser_error::make_error( 32950 | parser_error::e_parser, 32951 | token_t(), 32952 | "ERR260 - Failed to synthesize node: conditional_string_node_t", 32953 | exprtk_error_location)); 32954 | 32955 | details::free_node(*node_allocator_, result); 32956 | } 32957 | 32958 | return error_node(); 32959 | } 32960 | #else 32961 | inline expression_node_ptr conditional_string(expression_node_ptr, 32962 | expression_node_ptr, 32963 | expression_node_ptr) const 32964 | { 32965 | return error_node(); 32966 | } 32967 | #endif 32968 | 32969 | inline expression_node_ptr conditional_vector(expression_node_ptr condition, 32970 | expression_node_ptr consequent, 32971 | expression_node_ptr alternative) const 32972 | { 32973 | if ((0 == condition) || (0 == consequent)) 32974 | { 32975 | details::free_node(*node_allocator_, condition ); 32976 | details::free_node(*node_allocator_, consequent ); 32977 | details::free_node(*node_allocator_, alternative); 32978 | 32979 | const std::string invalid_branches = 32980 | ((0 == condition ) ? std::string("condition ") : "") + 32981 | ((0 == consequent) ? std::string("consequent") : "") ; 32982 | 32983 | parser_->set_error(parser_error::make_error( 32984 | parser_error::e_parser, 32985 | parser_->current_state().token, 32986 | "ERR261 - Invalid " + invalid_branches + " for vector conditional statement", 32987 | exprtk_error_location)); 32988 | 32989 | return error_node(); 32990 | } 32991 | // Can the condition be immediately evaluated? if so optimise. 32992 | else if (details::is_constant_node(condition)) 32993 | { 32994 | // True branch 32995 | if (details::is_true(condition)) 32996 | { 32997 | details::free_node(*node_allocator_, condition ); 32998 | details::free_node(*node_allocator_, alternative); 32999 | 33000 | return consequent; 33001 | } 33002 | // False branch 33003 | else 33004 | { 33005 | details::free_node(*node_allocator_, condition ); 33006 | details::free_node(*node_allocator_, consequent); 33007 | 33008 | if (alternative) 33009 | return alternative; 33010 | else 33011 | return node_allocator_->allocate<details::null_node<T> >(); 33012 | 33013 | } 33014 | } 33015 | else if ((0 != consequent) && (0 != alternative)) 33016 | { 33017 | return node_allocator_-> 33018 | allocate<conditional_vector_node_t>(condition, consequent, alternative); 33019 | } 33020 | else 33021 | return error_node(); 33022 | } 33023 | 33024 | inline loop_runtime_check_ptr get_loop_runtime_check(const loop_runtime_check::loop_types loop_type) const 33025 | { 33026 | if ( 33027 | parser_->loop_runtime_check_ && 33028 | (loop_type == (parser_->loop_runtime_check_->loop_set & loop_type)) 33029 | ) 33030 | { 33031 | return parser_->loop_runtime_check_; 33032 | } 33033 | 33034 | return loop_runtime_check_ptr(0); 33035 | } 33036 | 33037 | inline vector_access_runtime_check_ptr get_vector_access_runtime_check() const 33038 | { 33039 | return parser_->vector_access_runtime_check_; 33040 | } 33041 | 33042 | inline expression_node_ptr while_loop(expression_node_ptr& condition, 33043 | expression_node_ptr& branch, 33044 | const bool break_continue_present = false) const 33045 | { 33046 | if ( 33047 | !break_continue_present && 33048 | !parser_->state_.return_stmt_present && 33049 | details::is_constant_node(condition) 33050 | ) 33051 | { 33052 | expression_node_ptr result = error_node(); 33053 | if (details::is_true(condition)) 33054 | { 33055 | // Infinite loops are not allowed. 33056 | 33057 | parser_->set_error(parser_error::make_error( 33058 | parser_error::e_parser, 33059 | parser_->current_state().token, 33060 | "ERR262 - Infinite loop condition without 'break' or 'return' not allowed in while-loops", 33061 | exprtk_error_location)); 33062 | 33063 | result = error_node(); 33064 | } 33065 | else 33066 | result = node_allocator_->allocate<details::null_node<Type> >(); 33067 | 33068 | details::free_node(*node_allocator_, condition); 33069 | details::free_node(*node_allocator_, branch ); 33070 | 33071 | return result; 33072 | } 33073 | else if (details::is_null_node(condition)) 33074 | { 33075 | details::free_node(*node_allocator_,condition); 33076 | 33077 | return branch; 33078 | } 33079 | 33080 | loop_runtime_check_ptr rtc = get_loop_runtime_check(loop_runtime_check::e_while_loop); 33081 | 33082 | if (!break_continue_present) 33083 | { 33084 | if (rtc) 33085 | return node_allocator_->allocate<while_loop_rtc_node_t> 33086 | (condition, branch, rtc); 33087 | else 33088 | return node_allocator_->allocate<while_loop_node_t> 33089 | (condition, branch); 33090 | } 33091 | #ifndef exprtk_disable_break_continue 33092 | else 33093 | { 33094 | if (rtc) 33095 | return node_allocator_->allocate<while_loop_bc_rtc_node_t> 33096 | (condition, branch, rtc); 33097 | else 33098 | return node_allocator_->allocate<while_loop_bc_node_t> 33099 | (condition, branch); 33100 | } 33101 | #else 33102 | return error_node(); 33103 | #endif 33104 | } 33105 | 33106 | inline expression_node_ptr repeat_until_loop(expression_node_ptr& condition, 33107 | expression_node_ptr& branch, 33108 | const bool break_continue_present = false) const 33109 | { 33110 | if (!break_continue_present && details::is_constant_node(condition)) 33111 | { 33112 | if ( 33113 | details::is_true(condition) && 33114 | details::is_constant_node(branch) 33115 | ) 33116 | { 33117 | free_node(*node_allocator_,condition); 33118 | 33119 | return branch; 33120 | } 33121 | 33122 | details::free_node(*node_allocator_, condition); 33123 | details::free_node(*node_allocator_, branch ); 33124 | 33125 | return error_node(); 33126 | } 33127 | else if (details::is_null_node(condition)) 33128 | { 33129 | details::free_node(*node_allocator_,condition); 33130 | 33131 | return branch; 33132 | } 33133 | 33134 | loop_runtime_check_ptr rtc = get_loop_runtime_check(loop_runtime_check::e_repeat_until_loop); 33135 | 33136 | if (!break_continue_present) 33137 | { 33138 | if (rtc) 33139 | return node_allocator_->allocate<repeat_until_loop_rtc_node_t> 33140 | (condition, branch, rtc); 33141 | else 33142 | return node_allocator_->allocate<repeat_until_loop_node_t> 33143 | (condition, branch); 33144 | } 33145 | #ifndef exprtk_disable_break_continue 33146 | else 33147 | { 33148 | if (rtc) 33149 | return node_allocator_->allocate<repeat_until_loop_bc_rtc_node_t> 33150 | (condition, branch, rtc); 33151 | else 33152 | return node_allocator_->allocate<repeat_until_loop_bc_node_t> 33153 | (condition, branch); 33154 | } 33155 | #else 33156 | return error_node(); 33157 | #endif 33158 | } 33159 | 33160 | inline expression_node_ptr for_loop(expression_node_ptr& initialiser, 33161 | expression_node_ptr& condition, 33162 | expression_node_ptr& incrementor, 33163 | expression_node_ptr& loop_body, 33164 | bool break_continue_present = false) const 33165 | { 33166 | if ( 33167 | !break_continue_present && 33168 | !parser_->state_.return_stmt_present && 33169 | details::is_constant_node(condition) 33170 | ) 33171 | { 33172 | expression_node_ptr result = error_node(); 33173 | 33174 | if (details::is_true(condition)) 33175 | { 33176 | // Infinite loops are not allowed. 33177 | 33178 | parser_->set_error(parser_error::make_error( 33179 | parser_error::e_parser, 33180 | parser_->current_state().token, 33181 | "ERR263 - Infinite loop condition without 'break' or 'return' not allowed in for-loop", 33182 | exprtk_error_location)); 33183 | 33184 | result = error_node(); 33185 | } 33186 | else 33187 | result = node_allocator_->allocate<details::null_node<Type> >(); 33188 | 33189 | details::free_node(*node_allocator_, initialiser); 33190 | details::free_node(*node_allocator_, condition ); 33191 | details::free_node(*node_allocator_, incrementor); 33192 | details::free_node(*node_allocator_, loop_body ); 33193 | 33194 | return result; 33195 | } 33196 | else if (details::is_null_node(condition) || (0 == condition)) 33197 | { 33198 | details::free_node(*node_allocator_, initialiser); 33199 | details::free_node(*node_allocator_, condition ); 33200 | details::free_node(*node_allocator_, incrementor); 33201 | 33202 | return loop_body; 33203 | } 33204 | 33205 | loop_runtime_check_ptr rtc = get_loop_runtime_check(loop_runtime_check::e_for_loop); 33206 | 33207 | if (!break_continue_present) 33208 | { 33209 | if (rtc) 33210 | return node_allocator_->allocate<for_loop_rtc_node_t> 33211 | ( 33212 | initialiser, 33213 | condition, 33214 | incrementor, 33215 | loop_body, 33216 | rtc 33217 | ); 33218 | else 33219 | return node_allocator_->allocate<for_loop_node_t> 33220 | ( 33221 | initialiser, 33222 | condition, 33223 | incrementor, 33224 | loop_body 33225 | ); 33226 | } 33227 | #ifndef exprtk_disable_break_continue 33228 | else 33229 | { 33230 | if (rtc) 33231 | return node_allocator_->allocate<for_loop_bc_rtc_node_t> 33232 | ( 33233 | initialiser, 33234 | condition, 33235 | incrementor, 33236 | loop_body, 33237 | rtc 33238 | ); 33239 | else 33240 | return node_allocator_->allocate<for_loop_bc_node_t> 33241 | ( 33242 | initialiser, 33243 | condition, 33244 | incrementor, 33245 | loop_body 33246 | ); 33247 | } 33248 | #else 33249 | return error_node(); 33250 | #endif 33251 | } 33252 | 33253 | template <typename Allocator, 33254 | template <typename, typename> class Sequence> 33255 | inline expression_node_ptr const_optimise_switch(Sequence<expression_node_ptr,Allocator>& arg_list) 33256 | { 33257 | expression_node_ptr result = error_node(); 33258 | 33259 | for (std::size_t i = 0; i < (arg_list.size() / 2); ++i) 33260 | { 33261 | expression_node_ptr condition = arg_list[(2 * i) ]; 33262 | expression_node_ptr consequent = arg_list[(2 * i) + 1]; 33263 | 33264 | if ((0 == result) && details::is_true(condition)) 33265 | { 33266 | result = consequent; 33267 | break; 33268 | } 33269 | } 33270 | 33271 | if (0 == result) 33272 | { 33273 | result = arg_list.back(); 33274 | } 33275 | 33276 | for (std::size_t i = 0; i < arg_list.size(); ++i) 33277 | { 33278 | expression_node_ptr current_expr = arg_list[i]; 33279 | 33280 | if (current_expr && (current_expr != result)) 33281 | { 33282 | free_node(*node_allocator_,current_expr); 33283 | } 33284 | } 33285 | 33286 | return result; 33287 | } 33288 | 33289 | template <typename Allocator, 33290 | template <typename, typename> class Sequence> 33291 | inline expression_node_ptr const_optimise_mswitch(Sequence<expression_node_ptr,Allocator>& arg_list) 33292 | { 33293 | expression_node_ptr result = error_node(); 33294 | 33295 | for (std::size_t i = 0; i < (arg_list.size() / 2); ++i) 33296 | { 33297 | expression_node_ptr condition = arg_list[(2 * i) ]; 33298 | expression_node_ptr consequent = arg_list[(2 * i) + 1]; 33299 | 33300 | if (details::is_true(condition)) 33301 | { 33302 | result = consequent; 33303 | } 33304 | } 33305 | 33306 | if (0 == result) 33307 | { 33308 | const T zero = T(0); 33309 | result = node_allocator_->allocate<literal_node_t>(zero); 33310 | } 33311 | 33312 | for (std::size_t i = 0; i < arg_list.size(); ++i) 33313 | { 33314 | expression_node_ptr& current_expr = arg_list[i]; 33315 | 33316 | if (current_expr && (current_expr != result)) 33317 | { 33318 | details::free_node(*node_allocator_,current_expr); 33319 | } 33320 | } 33321 | 33322 | return result; 33323 | } 33324 | 33325 | struct switch_nodes 33326 | { 33327 | typedef std::vector<std::pair<expression_node_ptr,bool> > arg_list_t; 33328 | 33329 | #define case_stmt(N) \ 33330 | if (is_true(arg[(2 * N)].first)) { return arg[(2 * N) + 1].first->value(); } \ 33331 | 33332 | struct switch_impl_1 33333 | { 33334 | static inline T process(const arg_list_t& arg) 33335 | { 33336 | case_stmt(0) 33337 | 33338 | assert(arg.size() == ((2 * 1) + 1)); 33339 | 33340 | return arg.back().first->value(); 33341 | } 33342 | }; 33343 | 33344 | struct switch_impl_2 33345 | { 33346 | static inline T process(const arg_list_t& arg) 33347 | { 33348 | case_stmt(0) case_stmt(1) 33349 | 33350 | assert(arg.size() == ((2 * 2) + 1)); 33351 | 33352 | return arg.back().first->value(); 33353 | } 33354 | }; 33355 | 33356 | struct switch_impl_3 33357 | { 33358 | static inline T process(const arg_list_t& arg) 33359 | { 33360 | case_stmt(0) case_stmt(1) 33361 | case_stmt(2) 33362 | 33363 | assert(arg.size() == ((2 * 3) + 1)); 33364 | 33365 | return arg.back().first->value(); 33366 | } 33367 | }; 33368 | 33369 | struct switch_impl_4 33370 | { 33371 | static inline T process(const arg_list_t& arg) 33372 | { 33373 | case_stmt(0) case_stmt(1) 33374 | case_stmt(2) case_stmt(3) 33375 | 33376 | assert(arg.size() == ((2 * 4) + 1)); 33377 | 33378 | return arg.back().first->value(); 33379 | } 33380 | }; 33381 | 33382 | struct switch_impl_5 33383 | { 33384 | static inline T process(const arg_list_t& arg) 33385 | { 33386 | case_stmt(0) case_stmt(1) 33387 | case_stmt(2) case_stmt(3) 33388 | case_stmt(4) 33389 | 33390 | assert(arg.size() == ((2 * 5) + 1)); 33391 | 33392 | return arg.back().first->value(); 33393 | } 33394 | }; 33395 | 33396 | struct switch_impl_6 33397 | { 33398 | static inline T process(const arg_list_t& arg) 33399 | { 33400 | case_stmt(0) case_stmt(1) 33401 | case_stmt(2) case_stmt(3) 33402 | case_stmt(4) case_stmt(5) 33403 | 33404 | assert(arg.size() == ((2 * 6) + 1)); 33405 | 33406 | return arg.back().first->value(); 33407 | } 33408 | }; 33409 | 33410 | struct switch_impl_7 33411 | { 33412 | static inline T process(const arg_list_t& arg) 33413 | { 33414 | case_stmt(0) case_stmt(1) 33415 | case_stmt(2) case_stmt(3) 33416 | case_stmt(4) case_stmt(5) 33417 | case_stmt(6) 33418 | 33419 | assert(arg.size() == ((2 * 7) + 1)); 33420 | 33421 | return arg.back().first->value(); 33422 | } 33423 | }; 33424 | 33425 | #undef case_stmt 33426 | }; 33427 | 33428 | template <typename Allocator, 33429 | template <typename, typename> class Sequence> 33430 | inline expression_node_ptr switch_statement(Sequence<expression_node_ptr,Allocator>& arg_list, const bool default_statement_present) 33431 | { 33432 | if (arg_list.empty()) 33433 | return error_node(); 33434 | else if ( 33435 | !all_nodes_valid(arg_list) || 33436 | (!default_statement_present && (arg_list.size() < 2)) 33437 | ) 33438 | { 33439 | details::free_all_nodes(*node_allocator_,arg_list); 33440 | 33441 | return error_node(); 33442 | } 33443 | else if (is_constant_foldable(arg_list)) 33444 | return const_optimise_switch(arg_list); 33445 | 33446 | switch ((arg_list.size() - 1) / 2) 33447 | { 33448 | #define case_stmt(N) \ 33449 | case N : \ 33450 | return node_allocator_-> \ 33451 | allocate<details::switch_n_node \ 33452 | <Type,typename switch_nodes::switch_impl_##N > >(arg_list); \ 33453 | 33454 | case_stmt(1) 33455 | case_stmt(2) 33456 | case_stmt(3) 33457 | case_stmt(4) 33458 | case_stmt(5) 33459 | case_stmt(6) 33460 | case_stmt(7) 33461 | #undef case_stmt 33462 | 33463 | default : return node_allocator_->allocate<details::switch_node<Type> >(arg_list); 33464 | } 33465 | } 33466 | 33467 | template <typename Allocator, 33468 | template <typename, typename> class Sequence> 33469 | inline expression_node_ptr multi_switch_statement(Sequence<expression_node_ptr,Allocator>& arg_list) 33470 | { 33471 | if (!all_nodes_valid(arg_list)) 33472 | { 33473 | details::free_all_nodes(*node_allocator_,arg_list); 33474 | 33475 | return error_node(); 33476 | } 33477 | else if (is_constant_foldable(arg_list)) 33478 | return const_optimise_mswitch(arg_list); 33479 | else 33480 | return node_allocator_->allocate<details::multi_switch_node<Type> >(arg_list); 33481 | } 33482 | 33483 | inline expression_node_ptr assert_call(expression_node_ptr& assert_condition, 33484 | expression_node_ptr& assert_message, 33485 | const assert_check::assert_context& context) 33486 | { 33487 | typedef details::assert_node<Type> alloc_type; 33488 | 33489 | expression_node_ptr result = node_allocator_->allocate_rrrr<alloc_type> 33490 | (assert_condition, assert_message, parser_->assert_check_, context); 33491 | 33492 | if (result && result->valid()) 33493 | { 33494 | parser_->state_.activate_side_effect("assert_call()"); 33495 | return result; 33496 | } 33497 | 33498 | details::free_node(*node_allocator_, result ); 33499 | details::free_node(*node_allocator_, assert_condition); 33500 | details::free_node(*node_allocator_, assert_message ); 33501 | 33502 | return error_node(); 33503 | } 33504 | 33505 | #define unary_opr_switch_statements \ 33506 | case_stmt(details::e_abs , details::abs_op ) \ 33507 | case_stmt(details::e_acos , details::acos_op ) \ 33508 | case_stmt(details::e_acosh , details::acosh_op) \ 33509 | case_stmt(details::e_asin , details::asin_op ) \ 33510 | case_stmt(details::e_asinh , details::asinh_op) \ 33511 | case_stmt(details::e_atan , details::atan_op ) \ 33512 | case_stmt(details::e_atanh , details::atanh_op) \ 33513 | case_stmt(details::e_ceil , details::ceil_op ) \ 33514 | case_stmt(details::e_cos , details::cos_op ) \ 33515 | case_stmt(details::e_cosh , details::cosh_op ) \ 33516 | case_stmt(details::e_exp , details::exp_op ) \ 33517 | case_stmt(details::e_expm1 , details::expm1_op) \ 33518 | case_stmt(details::e_floor , details::floor_op) \ 33519 | case_stmt(details::e_log , details::log_op ) \ 33520 | case_stmt(details::e_log10 , details::log10_op) \ 33521 | case_stmt(details::e_log2 , details::log2_op ) \ 33522 | case_stmt(details::e_log1p , details::log1p_op) \ 33523 | case_stmt(details::e_neg , details::neg_op ) \ 33524 | case_stmt(details::e_pos , details::pos_op ) \ 33525 | case_stmt(details::e_round , details::round_op) \ 33526 | case_stmt(details::e_sin , details::sin_op ) \ 33527 | case_stmt(details::e_sinc , details::sinc_op ) \ 33528 | case_stmt(details::e_sinh , details::sinh_op ) \ 33529 | case_stmt(details::e_sqrt , details::sqrt_op ) \ 33530 | case_stmt(details::e_tan , details::tan_op ) \ 33531 | case_stmt(details::e_tanh , details::tanh_op ) \ 33532 | case_stmt(details::e_cot , details::cot_op ) \ 33533 | case_stmt(details::e_sec , details::sec_op ) \ 33534 | case_stmt(details::e_csc , details::csc_op ) \ 33535 | case_stmt(details::e_r2d , details::r2d_op ) \ 33536 | case_stmt(details::e_d2r , details::d2r_op ) \ 33537 | case_stmt(details::e_d2g , details::d2g_op ) \ 33538 | case_stmt(details::e_g2d , details::g2d_op ) \ 33539 | case_stmt(details::e_notl , details::notl_op ) \ 33540 | case_stmt(details::e_sgn , details::sgn_op ) \ 33541 | case_stmt(details::e_erf , details::erf_op ) \ 33542 | case_stmt(details::e_erfc , details::erfc_op ) \ 33543 | case_stmt(details::e_ncdf , details::ncdf_op ) \ 33544 | case_stmt(details::e_frac , details::frac_op ) \ 33545 | case_stmt(details::e_trunc , details::trunc_op) \ 33546 | 33547 | inline expression_node_ptr synthesize_uv_expression(const details::operator_type& operation, 33548 | expression_node_ptr (&branch)[1]) 33549 | { 33550 | T& v = static_cast<details::variable_node<T>*>(branch[0])->ref(); 33551 | 33552 | switch (operation) 33553 | { 33554 | #define case_stmt(op0, op1) \ 33555 | case op0 : return node_allocator_-> \ 33556 | allocate<typename details::unary_variable_node<Type,op1<Type> > >(v); \ 33557 | 33558 | unary_opr_switch_statements 33559 | #undef case_stmt 33560 | default : return error_node(); 33561 | } 33562 | } 33563 | 33564 | inline expression_node_ptr synthesize_uvec_expression(const details::operator_type& operation, 33565 | expression_node_ptr (&branch)[1]) 33566 | { 33567 | switch (operation) 33568 | { 33569 | #define case_stmt(op0, op1) \ 33570 | case op0 : return node_allocator_-> \ 33571 | allocate<typename details::unary_vector_node<Type,op1<Type> > > \ 33572 | (operation, branch[0]); \ 33573 | 33574 | unary_opr_switch_statements 33575 | #undef case_stmt 33576 | default : return error_node(); 33577 | } 33578 | } 33579 | 33580 | inline expression_node_ptr synthesize_unary_expression(const details::operator_type& operation, 33581 | expression_node_ptr (&branch)[1]) 33582 | { 33583 | switch (operation) 33584 | { 33585 | #define case_stmt(op0, op1) \ 33586 | case op0 : return node_allocator_-> \ 33587 | allocate<typename details::unary_branch_node<Type,op1<Type> > >(branch[0]); \ 33588 | 33589 | unary_opr_switch_statements 33590 | #undef case_stmt 33591 | default : return error_node(); 33592 | } 33593 | } 33594 | 33595 | inline expression_node_ptr const_optimise_sf3(const details::operator_type& operation, 33596 | expression_node_ptr (&branch)[3]) 33597 | { 33598 | expression_node_ptr temp_node = error_node(); 33599 | 33600 | switch (operation) 33601 | { 33602 | #define case_stmt(op) \ 33603 | case details::e_sf##op : temp_node = node_allocator_-> \ 33604 | allocate<details::sf3_node<Type,details::sf##op##_op<Type> > > \ 33605 | (operation, branch); \ 33606 | break; \ 33607 | 33608 | case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03) 33609 | case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07) 33610 | case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11) 33611 | case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15) 33612 | case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19) 33613 | case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23) 33614 | case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27) 33615 | case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31) 33616 | case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35) 33617 | case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39) 33618 | case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43) 33619 | case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47) 33620 | #undef case_stmt 33621 | default : return error_node(); 33622 | } 33623 | 33624 | assert(temp_node); 33625 | 33626 | const T v = temp_node->value(); 33627 | 33628 | details::free_node(*node_allocator_,temp_node); 33629 | 33630 | return node_allocator_->allocate<literal_node_t>(v); 33631 | } 33632 | 33633 | inline expression_node_ptr varnode_optimise_sf3(const details::operator_type& operation, expression_node_ptr (&branch)[3]) 33634 | { 33635 | typedef details::variable_node<Type>* variable_ptr; 33636 | 33637 | const Type& v0 = static_cast<variable_ptr>(branch[0])->ref(); 33638 | const Type& v1 = static_cast<variable_ptr>(branch[1])->ref(); 33639 | const Type& v2 = static_cast<variable_ptr>(branch[2])->ref(); 33640 | 33641 | switch (operation) 33642 | { 33643 | #define case_stmt(op) \ 33644 | case details::e_sf##op : return node_allocator_-> \ 33645 | allocate_rrr<details::sf3_var_node<Type,details::sf##op##_op<Type> > > \ 33646 | (v0, v1, v2); \ 33647 | 33648 | case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03) 33649 | case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07) 33650 | case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11) 33651 | case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15) 33652 | case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19) 33653 | case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23) 33654 | case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27) 33655 | case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31) 33656 | case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35) 33657 | case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39) 33658 | case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43) 33659 | case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47) 33660 | #undef case_stmt 33661 | default : return error_node(); 33662 | } 33663 | } 33664 | 33665 | inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[3]) 33666 | { 33667 | if (!all_nodes_valid(branch)) 33668 | return error_node(); 33669 | else if (is_constant_foldable(branch)) 33670 | return const_optimise_sf3(operation,branch); 33671 | else if (all_nodes_variables(branch)) 33672 | return varnode_optimise_sf3(operation,branch); 33673 | else 33674 | { 33675 | switch (operation) 33676 | { 33677 | #define case_stmt(op) \ 33678 | case details::e_sf##op : return node_allocator_-> \ 33679 | allocate<details::sf3_node<Type,details::sf##op##_op<Type> > > \ 33680 | (operation, branch); \ 33681 | 33682 | case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03) 33683 | case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07) 33684 | case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11) 33685 | case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15) 33686 | case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19) 33687 | case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23) 33688 | case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27) 33689 | case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31) 33690 | case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35) 33691 | case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39) 33692 | case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43) 33693 | case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47) 33694 | #undef case_stmt 33695 | default : return error_node(); 33696 | } 33697 | } 33698 | } 33699 | 33700 | inline expression_node_ptr const_optimise_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4]) 33701 | { 33702 | expression_node_ptr temp_node = error_node(); 33703 | 33704 | switch (operation) 33705 | { 33706 | #define case_stmt(op) \ 33707 | case details::e_sf##op : temp_node = node_allocator_-> \ 33708 | allocate<details::sf4_node<Type,details::sf##op##_op<Type> > > \ 33709 | (operation, branch); \ 33710 | break; \ 33711 | 33712 | case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51) 33713 | case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55) 33714 | case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59) 33715 | case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63) 33716 | case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67) 33717 | case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71) 33718 | case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75) 33719 | case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79) 33720 | case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83) 33721 | case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87) 33722 | case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91) 33723 | case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95) 33724 | case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99) 33725 | #undef case_stmt 33726 | default : return error_node(); 33727 | } 33728 | 33729 | assert(temp_node); 33730 | 33731 | const T v = temp_node->value(); 33732 | 33733 | details::free_node(*node_allocator_,temp_node); 33734 | 33735 | return node_allocator_->allocate<literal_node_t>(v); 33736 | } 33737 | 33738 | inline expression_node_ptr varnode_optimise_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4]) 33739 | { 33740 | typedef details::variable_node<Type>* variable_ptr; 33741 | 33742 | const Type& v0 = static_cast<variable_ptr>(branch[0])->ref(); 33743 | const Type& v1 = static_cast<variable_ptr>(branch[1])->ref(); 33744 | const Type& v2 = static_cast<variable_ptr>(branch[2])->ref(); 33745 | const Type& v3 = static_cast<variable_ptr>(branch[3])->ref(); 33746 | 33747 | switch (operation) 33748 | { 33749 | #define case_stmt(op) \ 33750 | case details::e_sf##op : return node_allocator_-> \ 33751 | allocate_rrrr<details::sf4_var_node<Type,details::sf##op##_op<Type> > > \ 33752 | (v0, v1, v2, v3); \ 33753 | 33754 | case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51) 33755 | case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55) 33756 | case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59) 33757 | case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63) 33758 | case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67) 33759 | case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71) 33760 | case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75) 33761 | case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79) 33762 | case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83) 33763 | case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87) 33764 | case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91) 33765 | case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95) 33766 | case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99) 33767 | #undef case_stmt 33768 | default : return error_node(); 33769 | } 33770 | } 33771 | 33772 | inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[4]) 33773 | { 33774 | if (!all_nodes_valid(branch)) 33775 | return error_node(); 33776 | else if (is_constant_foldable(branch)) 33777 | return const_optimise_sf4(operation,branch); 33778 | else if (all_nodes_variables(branch)) 33779 | return varnode_optimise_sf4(operation,branch); 33780 | switch (operation) 33781 | { 33782 | #define case_stmt(op) \ 33783 | case details::e_sf##op : return node_allocator_-> \ 33784 | allocate<details::sf4_node<Type,details::sf##op##_op<Type> > > \ 33785 | (operation, branch); \ 33786 | 33787 | case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51) 33788 | case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55) 33789 | case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59) 33790 | case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63) 33791 | case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67) 33792 | case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71) 33793 | case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75) 33794 | case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79) 33795 | case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83) 33796 | case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87) 33797 | case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91) 33798 | case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95) 33799 | case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99) 33800 | #undef case_stmt 33801 | default : return error_node(); 33802 | } 33803 | } 33804 | 33805 | template <typename Allocator, 33806 | template <typename, typename> class Sequence> 33807 | inline expression_node_ptr const_optimise_varargfunc(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list) 33808 | { 33809 | expression_node_ptr temp_node = error_node(); 33810 | 33811 | switch (operation) 33812 | { 33813 | #define case_stmt(op0, op1) \ 33814 | case op0 : temp_node = node_allocator_-> \ 33815 | allocate<details::vararg_node<Type,op1<Type> > > \ 33816 | (arg_list); \ 33817 | break; \ 33818 | 33819 | case_stmt(details::e_sum , details::vararg_add_op ) 33820 | case_stmt(details::e_prod , details::vararg_mul_op ) 33821 | case_stmt(details::e_avg , details::vararg_avg_op ) 33822 | case_stmt(details::e_min , details::vararg_min_op ) 33823 | case_stmt(details::e_max , details::vararg_max_op ) 33824 | case_stmt(details::e_mand , details::vararg_mand_op ) 33825 | case_stmt(details::e_mor , details::vararg_mor_op ) 33826 | case_stmt(details::e_multi , details::vararg_multi_op) 33827 | #undef case_stmt 33828 | default : return error_node(); 33829 | } 33830 | 33831 | const T v = temp_node->value(); 33832 | 33833 | details::free_node(*node_allocator_,temp_node); 33834 | 33835 | return node_allocator_->allocate<literal_node_t>(v); 33836 | } 33837 | 33838 | inline bool special_one_parameter_vararg(const details::operator_type& operation) const 33839 | { 33840 | return ( 33841 | (details::e_sum == operation) || 33842 | (details::e_prod == operation) || 33843 | (details::e_avg == operation) || 33844 | (details::e_min == operation) || 33845 | (details::e_max == operation) 33846 | ); 33847 | } 33848 | 33849 | template <typename Allocator, 33850 | template <typename, typename> class Sequence> 33851 | inline expression_node_ptr varnode_optimise_varargfunc(const details::operator_type& operation, 33852 | Sequence<expression_node_ptr,Allocator>& arg_list) 33853 | { 33854 | switch (operation) 33855 | { 33856 | #define case_stmt(op0, op1) \ 33857 | case op0 : return node_allocator_-> \ 33858 | allocate<details::vararg_varnode<Type,op1<Type> > >(arg_list); \ 33859 | 33860 | case_stmt(details::e_sum , details::vararg_add_op ) 33861 | case_stmt(details::e_prod , details::vararg_mul_op ) 33862 | case_stmt(details::e_avg , details::vararg_avg_op ) 33863 | case_stmt(details::e_min , details::vararg_min_op ) 33864 | case_stmt(details::e_max , details::vararg_max_op ) 33865 | case_stmt(details::e_mand , details::vararg_mand_op ) 33866 | case_stmt(details::e_mor , details::vararg_mor_op ) 33867 | case_stmt(details::e_multi , details::vararg_multi_op) 33868 | #undef case_stmt 33869 | default : return error_node(); 33870 | } 33871 | } 33872 | 33873 | template <typename Allocator, 33874 | template <typename, typename> class Sequence> 33875 | inline expression_node_ptr vectorize_func(const details::operator_type& operation, 33876 | Sequence<expression_node_ptr,Allocator>& arg_list) 33877 | { 33878 | if (1 == arg_list.size()) 33879 | { 33880 | switch (operation) 33881 | { 33882 | #define case_stmt(op0, op1) \ 33883 | case op0 : return node_allocator_-> \ 33884 | allocate<details::vectorize_node<Type,op1<Type> > >(arg_list[0]); \ 33885 | 33886 | case_stmt(details::e_sum , details::vec_add_op) 33887 | case_stmt(details::e_prod , details::vec_mul_op) 33888 | case_stmt(details::e_avg , details::vec_avg_op) 33889 | case_stmt(details::e_min , details::vec_min_op) 33890 | case_stmt(details::e_max , details::vec_max_op) 33891 | #undef case_stmt 33892 | default : return error_node(); 33893 | } 33894 | } 33895 | else 33896 | return error_node(); 33897 | } 33898 | 33899 | template <typename Allocator, 33900 | template <typename, typename> class Sequence> 33901 | inline expression_node_ptr vararg_function(const details::operator_type& operation, 33902 | Sequence<expression_node_ptr,Allocator>& arg_list) 33903 | { 33904 | if (!all_nodes_valid(arg_list)) 33905 | { 33906 | details::free_all_nodes(*node_allocator_,arg_list); 33907 | 33908 | return error_node(); 33909 | } 33910 | else if (is_constant_foldable(arg_list)) 33911 | return const_optimise_varargfunc(operation,arg_list); 33912 | else if ((1 == arg_list.size()) && details::is_ivector_node(arg_list[0])) 33913 | return vectorize_func(operation,arg_list); 33914 | else if ((1 == arg_list.size()) && special_one_parameter_vararg(operation)) 33915 | return arg_list[0]; 33916 | else if (all_nodes_variables(arg_list)) 33917 | return varnode_optimise_varargfunc(operation,arg_list); 33918 | 33919 | #ifndef exprtk_disable_string_capabilities 33920 | if (details::e_smulti == operation) 33921 | { 33922 | expression_node_ptr result = node_allocator_-> 33923 | allocate<details::str_vararg_node<Type,details::vararg_multi_op<Type> > >(arg_list); 33924 | if (result && result->valid()) 33925 | { 33926 | return result; 33927 | } 33928 | 33929 | parser_->set_error(parser_error::make_error( 33930 | parser_error::e_synthesis, 33931 | token_t(), 33932 | "ERR264 - Failed to synthesize node: str_vararg_node<vararg_multi_op>", 33933 | exprtk_error_location)); 33934 | 33935 | details::free_node(*node_allocator_, result); 33936 | } 33937 | else 33938 | #endif 33939 | { 33940 | expression_node_ptr result = error_node(); 33941 | 33942 | switch (operation) 33943 | { 33944 | #define case_stmt(op0, op1) \ 33945 | case op0 : result = node_allocator_-> \ 33946 | allocate<details::vararg_node<Type,op1<Type> > >(arg_list); \ 33947 | break; \ 33948 | 33949 | case_stmt(details::e_sum , details::vararg_add_op ) 33950 | case_stmt(details::e_prod , details::vararg_mul_op ) 33951 | case_stmt(details::e_avg , details::vararg_avg_op ) 33952 | case_stmt(details::e_min , details::vararg_min_op ) 33953 | case_stmt(details::e_max , details::vararg_max_op ) 33954 | case_stmt(details::e_mand , details::vararg_mand_op ) 33955 | case_stmt(details::e_mor , details::vararg_mor_op ) 33956 | case_stmt(details::e_multi , details::vararg_multi_op) 33957 | #undef case_stmt 33958 | default : return error_node(); 33959 | } 33960 | 33961 | if (result && result->valid()) 33962 | { 33963 | return result; 33964 | } 33965 | 33966 | parser_->set_error(parser_error::make_error( 33967 | parser_error::e_synthesis, 33968 | token_t(), 33969 | "ERR265 - Failed to synthesize node: vararg_node", 33970 | exprtk_error_location)); 33971 | 33972 | details::free_node(*node_allocator_, result); 33973 | } 33974 | 33975 | return error_node(); 33976 | } 33977 | 33978 | template <std::size_t N> 33979 | inline expression_node_ptr function(ifunction_t* f, expression_node_ptr (&b)[N]) 33980 | { 33981 | typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t; 33982 | expression_node_ptr result = synthesize_expression<function_N_node_t,N>(f,b); 33983 | 33984 | if (0 == result) 33985 | return error_node(); 33986 | else 33987 | { 33988 | // Can the function call be completely optimised? 33989 | if (details::is_constant_node(result)) 33990 | return result; 33991 | else if (!all_nodes_valid(b)) 33992 | { 33993 | details::free_node(*node_allocator_,result); 33994 | std::fill_n(b, N, reinterpret_cast<expression_node_ptr>(0)); 33995 | 33996 | return error_node(); 33997 | } 33998 | else if (N != f->param_count) 33999 | { 34000 | details::free_node(*node_allocator_,result); 34001 | std::fill_n(b, N, reinterpret_cast<expression_node_ptr>(0)); 34002 | 34003 | return error_node(); 34004 | } 34005 | 34006 | function_N_node_t* func_node_ptr = reinterpret_cast<function_N_node_t*>(result); 34007 | 34008 | if (!func_node_ptr->init_branches(b)) 34009 | { 34010 | details::free_node(*node_allocator_,result); 34011 | std::fill_n(b, N, reinterpret_cast<expression_node_ptr>(0)); 34012 | 34013 | return error_node(); 34014 | } 34015 | 34016 | if (result && result->valid()) 34017 | { 34018 | return result; 34019 | } 34020 | 34021 | parser_->set_error(parser_error::make_error( 34022 | parser_error::e_synthesis, 34023 | token_t(), 34024 | "ERR266 - Failed to synthesize node: function_N_node_t", 34025 | exprtk_error_location)); 34026 | 34027 | details::free_node(*node_allocator_, result); 34028 | return error_node(); 34029 | } 34030 | } 34031 | 34032 | inline expression_node_ptr function(ifunction_t* f) 34033 | { 34034 | typedef typename details::function_N_node<Type,ifunction_t,0> function_N_node_t; 34035 | return node_allocator_->allocate<function_N_node_t>(f); 34036 | } 34037 | 34038 | inline expression_node_ptr vararg_function_call(ivararg_function_t* vaf, 34039 | std::vector<expression_node_ptr>& arg_list) 34040 | { 34041 | if (!all_nodes_valid(arg_list)) 34042 | { 34043 | details::free_all_nodes(*node_allocator_,arg_list); 34044 | 34045 | return error_node(); 34046 | } 34047 | 34048 | typedef details::vararg_function_node<Type,ivararg_function_t> alloc_type; 34049 | 34050 | expression_node_ptr result = node_allocator_->allocate<alloc_type>(vaf,arg_list); 34051 | 34052 | if ( 34053 | !arg_list.empty() && 34054 | !vaf->has_side_effects() && 34055 | is_constant_foldable(arg_list) 34056 | ) 34057 | { 34058 | const Type v = result->value(); 34059 | details::free_node(*node_allocator_,result); 34060 | result = node_allocator_->allocate<literal_node_t>(v); 34061 | } 34062 | 34063 | parser_->state_.activate_side_effect("vararg_function_call()"); 34064 | 34065 | if (result && result->valid()) 34066 | { 34067 | return result; 34068 | } 34069 | 34070 | parser_->set_error(parser_error::make_error( 34071 | parser_error::e_synthesis, 34072 | token_t(), 34073 | "ERR267 - Failed to synthesize node: vararg_function_node<ivararg_function_t>", 34074 | exprtk_error_location)); 34075 | 34076 | details::free_node(*node_allocator_, result); 34077 | return error_node(); 34078 | } 34079 | 34080 | inline expression_node_ptr generic_function_call(igeneric_function_t* gf, 34081 | std::vector<expression_node_ptr>& arg_list, 34082 | const std::size_t& param_seq_index = std::numeric_limits<std::size_t>::max()) 34083 | { 34084 | if (!all_nodes_valid(arg_list)) 34085 | { 34086 | details::free_all_nodes(*node_allocator_,arg_list); 34087 | return error_node(); 34088 | } 34089 | 34090 | typedef details::generic_function_node <Type,igeneric_function_t> alloc_type1; 34091 | typedef details::multimode_genfunction_node<Type,igeneric_function_t> alloc_type2; 34092 | 34093 | const std::size_t no_psi = std::numeric_limits<std::size_t>::max(); 34094 | 34095 | expression_node_ptr result = error_node(); 34096 | std::string node_name = "Unknown" 34097 | 34098 | if (no_psi == param_seq_index) 34099 | { 34100 | result = node_allocator_->allocate<alloc_type1>(arg_list,gf); 34101 | node_name = "generic_function_node<igeneric_function_t>" 34102 | } 34103 | else 34104 | { 34105 | result = node_allocator_->allocate<alloc_type2>(gf, param_seq_index, arg_list); 34106 | node_name = "multimode_genfunction_node<igeneric_function_t>" 34107 | } 34108 | 34109 | alloc_type1* genfunc_node_ptr = static_cast<alloc_type1*>(result); 34110 | 34111 | assert(genfunc_node_ptr); 34112 | 34113 | if ( 34114 | !arg_list.empty() && 34115 | !gf->has_side_effects() && 34116 | parser_->state_.type_check_enabled && 34117 | is_constant_foldable(arg_list) 34118 | ) 34119 | { 34120 | genfunc_node_ptr->init_branches(); 34121 | 34122 | const Type v = result->value(); 34123 | 34124 | details::free_node(*node_allocator_,result); 34125 | 34126 | return node_allocator_->allocate<literal_node_t>(v); 34127 | } 34128 | else if (genfunc_node_ptr->init_branches()) 34129 | { 34130 | if (result && result->valid()) 34131 | { 34132 | parser_->state_.activate_side_effect("generic_function_call()"); 34133 | return result; 34134 | } 34135 | 34136 | parser_->set_error(parser_error::make_error( 34137 | parser_error::e_synthesis, 34138 | token_t(), 34139 | "ERR268 - Failed to synthesize node: " + node_name, 34140 | exprtk_error_location)); 34141 | 34142 | details::free_node(*node_allocator_, result); 34143 | return error_node(); 34144 | } 34145 | else 34146 | { 34147 | details::free_node(*node_allocator_, result); 34148 | details::free_all_nodes(*node_allocator_, arg_list); 34149 | 34150 | return error_node(); 34151 | } 34152 | } 34153 | 34154 | #ifndef exprtk_disable_string_capabilities 34155 | inline expression_node_ptr string_function_call(igeneric_function_t* gf, 34156 | std::vector<expression_node_ptr>& arg_list, 34157 | const std::size_t& param_seq_index = std::numeric_limits<std::size_t>::max()) 34158 | { 34159 | if (!all_nodes_valid(arg_list)) 34160 | { 34161 | details::free_all_nodes(*node_allocator_,arg_list); 34162 | return error_node(); 34163 | } 34164 | 34165 | typedef details::string_function_node <Type,igeneric_function_t> alloc_type1; 34166 | typedef details::multimode_strfunction_node<Type,igeneric_function_t> alloc_type2; 34167 | 34168 | const std::size_t no_psi = std::numeric_limits<std::size_t>::max(); 34169 | 34170 | expression_node_ptr result = error_node(); 34171 | std::string node_name = "Unknown" 34172 | 34173 | if (no_psi == param_seq_index) 34174 | { 34175 | result = node_allocator_->allocate<alloc_type1>(gf,arg_list); 34176 | node_name = "string_function_node<igeneric_function_t>" 34177 | } 34178 | else 34179 | { 34180 | result = node_allocator_->allocate<alloc_type2>(gf, param_seq_index, arg_list); 34181 | node_name = "multimode_strfunction_node<igeneric_function_t>" 34182 | } 34183 | 34184 | alloc_type1* strfunc_node_ptr = static_cast<alloc_type1*>(result); 34185 | 34186 | assert(strfunc_node_ptr); 34187 | 34188 | if ( 34189 | !arg_list.empty() && 34190 | !gf->has_side_effects() && 34191 | is_constant_foldable(arg_list) 34192 | ) 34193 | { 34194 | strfunc_node_ptr->init_branches(); 34195 | 34196 | const Type v = result->value(); 34197 | 34198 | details::free_node(*node_allocator_,result); 34199 | 34200 | return node_allocator_->allocate<literal_node_t>(v); 34201 | } 34202 | else if (strfunc_node_ptr->init_branches()) 34203 | { 34204 | if (result && result->valid()) 34205 | { 34206 | parser_->state_.activate_side_effect("string_function_call()"); 34207 | return result; 34208 | } 34209 | 34210 | parser_->set_error(parser_error::make_error( 34211 | parser_error::e_synthesis, 34212 | token_t(), 34213 | "ERR269 - Failed to synthesize node: " + node_name, 34214 | exprtk_error_location)); 34215 | 34216 | details::free_node(*node_allocator_, result); 34217 | return error_node(); 34218 | } 34219 | else 34220 | { 34221 | details::free_node (*node_allocator_,result ); 34222 | details::free_all_nodes(*node_allocator_,arg_list); 34223 | 34224 | return error_node(); 34225 | } 34226 | } 34227 | #endif 34228 | 34229 | #ifndef exprtk_disable_return_statement 34230 | inline expression_node_ptr return_call(std::vector<expression_node_ptr>& arg_list) 34231 | { 34232 | if (!all_nodes_valid(arg_list)) 34233 | { 34234 | details::free_all_nodes(*node_allocator_,arg_list); 34235 | return error_node(); 34236 | } 34237 | 34238 | typedef details::return_node<Type> alloc_type; 34239 | 34240 | expression_node_ptr result = node_allocator_-> 34241 | allocate_rr<alloc_type>(arg_list,parser_->results_ctx()); 34242 | 34243 | alloc_type* return_node_ptr = static_cast<alloc_type*>(result); 34244 | 34245 | assert(return_node_ptr); 34246 | 34247 | if (return_node_ptr->init_branches()) 34248 | { 34249 | if (result && result->valid()) 34250 | { 34251 | parser_->state_.activate_side_effect("return_call()"); 34252 | return result; 34253 | } 34254 | 34255 | parser_->set_error(parser_error::make_error( 34256 | parser_error::e_synthesis, 34257 | token_t(), 34258 | "ERR270 - Failed to synthesize node: return_node", 34259 | exprtk_error_location)); 34260 | 34261 | details::free_node(*node_allocator_, result); 34262 | return error_node(); 34263 | } 34264 | else 34265 | { 34266 | details::free_node (*node_allocator_, result ); 34267 | details::free_all_nodes(*node_allocator_, arg_list); 34268 | 34269 | return error_node(); 34270 | } 34271 | } 34272 | 34273 | inline expression_node_ptr return_envelope(expression_node_ptr body, 34274 | results_context_t* rc, 34275 | bool*& return_invoked) 34276 | { 34277 | typedef details::return_envelope_node<Type> alloc_type; 34278 | 34279 | expression_node_ptr result = node_allocator_-> 34280 | allocate_cr<alloc_type>(body,(*rc)); 34281 | 34282 | return_invoked = static_cast<alloc_type*>(result)->retinvk_ptr(); 34283 | 34284 | return result; 34285 | } 34286 | #else 34287 | inline expression_node_ptr return_call(std::vector<expression_node_ptr>&) 34288 | { 34289 | return error_node(); 34290 | } 34291 | 34292 | inline expression_node_ptr return_envelope(expression_node_ptr, 34293 | results_context_t*, 34294 | bool*&) 34295 | { 34296 | return error_node(); 34297 | } 34298 | #endif 34299 | 34300 | inline expression_node_ptr vector_element(const std::string& symbol, 34301 | vector_holder_ptr vector_base, 34302 | expression_node_ptr vec_node, 34303 | expression_node_ptr index) 34304 | { 34305 | expression_node_ptr result = error_node(); 34306 | std::string node_name = "Unknown" 34307 | 34308 | if (details::is_constant_node(index)) 34309 | { 34310 | const std::size_t vec_index = static_cast<std::size_t>(details::numeric::to_int64(index->value())); 34311 | 34312 | details::free_node(*node_allocator_,index); 34313 | 34314 | if (vec_index >= vector_base->size()) 34315 | { 34316 | parser_->set_error(parser_error::make_error( 34317 | parser_error::e_parser, 34318 | token_t(), 34319 | "ERR271 - Index of " + details::to_str(vec_index) + " out of range for " 34320 | "vector '" + symbol + "' of size " + details::to_str(vector_base->size()), 34321 | exprtk_error_location)); 34322 | 34323 | details::free_node(*node_allocator_,vec_node); 34324 | 34325 | return error_node(); 34326 | } 34327 | 34328 | if (vector_base->rebaseable()) 34329 | { 34330 | vector_access_runtime_check_ptr rtc = get_vector_access_runtime_check(); 34331 | 34332 | result = (rtc) ? 34333 | node_allocator_->allocate<rebasevector_celem_rtc_node_t>(vec_node, vec_index, vector_base, rtc) : 34334 | node_allocator_->allocate<rebasevector_celem_node_t >(vec_node, vec_index, vector_base ) ; 34335 | 34336 | node_name = (rtc) ? 34337 | "rebasevector_elem_rtc_node_t" : 34338 | "rebasevector_elem_node_t" ; 34339 | 34340 | if (result && result->valid()) 34341 | { 34342 | return result; 34343 | } 34344 | 34345 | parser_->set_error(parser_error::make_error( 34346 | parser_error::e_synthesis, 34347 | token_t(), 34348 | "ERR272 - Failed to synthesize node: " + node_name + " for vector: " + symbol, 34349 | exprtk_error_location)); 34350 | 34351 | details::free_node(*node_allocator_, result); 34352 | return error_node(); 34353 | } 34354 | else if (details::is_ivector_node(vec_node) && !details::is_vector_node(vec_node)) 34355 | { 34356 | vector_access_runtime_check_ptr rtc = get_vector_access_runtime_check(); 34357 | 34358 | result = (rtc) ? 34359 | node_allocator_->allocate<vector_celem_rtc_node_t>(vec_node, vec_index, vector_base, rtc) : 34360 | node_allocator_->allocate<vector_celem_node_t >(vec_node, vec_index, vector_base ) ; 34361 | 34362 | node_name = (rtc) ? 34363 | "vector_elem_rtc_node_t" : 34364 | "vector_elem_node_t" ; 34365 | 34366 | if (result && result->valid()) 34367 | { 34368 | return result; 34369 | } 34370 | 34371 | parser_->set_error(parser_error::make_error( 34372 | parser_error::e_synthesis, 34373 | token_t(), 34374 | "ERR273 - Failed to synthesize node: " + node_name + " for vector: " + symbol, 34375 | exprtk_error_location)); 34376 | 34377 | details::free_node(*node_allocator_, result); 34378 | return error_node(); 34379 | } 34380 | 34381 | const scope_element& se = parser_->sem_.get_element(symbol,vec_index); 34382 | 34383 | if (se.index == vec_index) 34384 | { 34385 | result = se.var_node; 34386 | details::free_node(*node_allocator_,vec_node); 34387 | } 34388 | else 34389 | { 34390 | scope_element nse; 34391 | nse.name = symbol; 34392 | nse.active = true; 34393 | nse.ref_count = 1; 34394 | nse.type = scope_element::e_vecelem; 34395 | nse.index = vec_index; 34396 | nse.depth = parser_->state_.scope_depth; 34397 | nse.data = 0; 34398 | nse.var_node = node_allocator_->allocate<variable_node_t>((*(*vector_base)[vec_index])); 34399 | 34400 | if (!parser_->sem_.add_element(nse)) 34401 | { 34402 | parser_->set_synthesis_error("Failed to add new local vector element to SEM [1]"); 34403 | 34404 | parser_->sem_.free_element(nse); 34405 | 34406 | result = error_node(); 34407 | } 34408 | 34409 | assert(parser_->sem_.total_local_symb_size_bytes() <= parser_->settings().max_total_local_symbol_size_bytes()); 34410 | 34411 | details::free_node(*node_allocator_,vec_node); 34412 | 34413 | exprtk_debug(("vector_element() - INFO - Added new local vector element: %s\n", nse.name.c_str())); 34414 | 34415 | parser_->state_.activate_side_effect("vector_element()"); 34416 | 34417 | result = nse.var_node; 34418 | node_name = "variable_node_t" 34419 | } 34420 | } 34421 | else 34422 | { 34423 | vector_access_runtime_check_ptr rtc = get_vector_access_runtime_check(); 34424 | 34425 | if (vector_base->rebaseable()) 34426 | { 34427 | result = (rtc) ? 34428 | node_allocator_->allocate<rebasevector_elem_rtc_node_t>(vec_node, index, vector_base, rtc) : 34429 | node_allocator_->allocate<rebasevector_elem_node_t >(vec_node, index, vector_base ) ; 34430 | 34431 | node_name = (rtc) ? 34432 | "rebasevector_elem_rtc_node_t" : 34433 | "rebasevector_elem_node_t" ; 34434 | } 34435 | else 34436 | { 34437 | result = rtc ? 34438 | node_allocator_->allocate<vector_elem_rtc_node_t>(vec_node, index, vector_base, rtc) : 34439 | node_allocator_->allocate<vector_elem_node_t >(vec_node, index, vector_base ) ; 34440 | 34441 | node_name = (rtc) ? 34442 | "vector_elem_rtc_node_t" : 34443 | "vector_elem_node_t" ; 34444 | } 34445 | } 34446 | 34447 | if (result && result->valid()) 34448 | { 34449 | return result; 34450 | } 34451 | 34452 | parser_->set_error(parser_error::make_error( 34453 | parser_error::e_synthesis, 34454 | token_t(), 34455 | "ERR274 - Failed to synthesize node: " + node_name, 34456 | exprtk_error_location)); 34457 | 34458 | details::free_node(*node_allocator_, result); 34459 | return error_node(); 34460 | } 34461 | 34462 | private: 34463 | 34464 | template <std::size_t N, typename NodePtr> 34465 | inline bool is_constant_foldable(NodePtr (&b)[N]) const 34466 | { 34467 | for (std::size_t i = 0; i < N; ++i) 34468 | { 34469 | if (0 == b[i]) 34470 | return false; 34471 | else if (!details::is_constant_node(b[i])) 34472 | return false; 34473 | } 34474 | 34475 | return true; 34476 | } 34477 | 34478 | template <typename NodePtr, 34479 | typename Allocator, 34480 | template <typename, typename> class Sequence> 34481 | inline bool is_constant_foldable(const Sequence<NodePtr,Allocator>& b) const 34482 | { 34483 | for (std::size_t i = 0; i < b.size(); ++i) 34484 | { 34485 | if (0 == b[i]) 34486 | return false; 34487 | else if (!details::is_constant_node(b[i])) 34488 | return false; 34489 | } 34490 | 34491 | return true; 34492 | } 34493 | 34494 | void lodge_assignment(symbol_type cst, expression_node_ptr node) 34495 | { 34496 | parser_->state_.activate_side_effect("lodge_assignment()"); 34497 | 34498 | if (!parser_->dec_.collect_assignments()) 34499 | return; 34500 | 34501 | std::string symbol_name; 34502 | 34503 | switch (cst) 34504 | { 34505 | case e_st_variable : symbol_name = parser_->symtab_store_ 34506 | .get_variable_name(node); 34507 | break; 34508 | 34509 | #ifndef exprtk_disable_string_capabilities 34510 | case e_st_string : symbol_name = parser_->symtab_store_ 34511 | .get_stringvar_name(node); 34512 | break; 34513 | #endif 34514 | 34515 | case e_st_vector : { 34516 | typedef details::vector_holder<T> vector_holder_t; 34517 | 34518 | vector_holder_t& vh = static_cast<vector_node_t*>(node)->vec_holder(); 34519 | 34520 | symbol_name = parser_->symtab_store_.get_vector_name(&vh); 34521 | } 34522 | break; 34523 | 34524 | case e_st_vecelem : { 34525 | typedef details::vector_holder<T> vector_holder_t; 34526 | 34527 | vector_holder_t& vh = static_cast<vector_elem_node_t*>(node)->vec_holder(); 34528 | 34529 | symbol_name = parser_->symtab_store_.get_vector_name(&vh); 34530 | 34531 | cst = e_st_vector; 34532 | } 34533 | break; 34534 | 34535 | default : return; 34536 | } 34537 | 34538 | if (!symbol_name.empty()) 34539 | { 34540 | parser_->dec_.add_assignment(symbol_name,cst); 34541 | } 34542 | } 34543 | 34544 | const void* base_ptr(expression_node_ptr node) 34545 | { 34546 | if (node) 34547 | { 34548 | switch (node->type()) 34549 | { 34550 | case details::expression_node<T>::e_variable: 34551 | return reinterpret_cast<const void*>(&static_cast<variable_node_t*>(node)->ref()); 34552 | 34553 | case details::expression_node<T>::e_vecelem: 34554 | return reinterpret_cast<const void*>(static_cast<vector_elem_node_t*>(node)->vec_holder().data()); 34555 | 34556 | case details::expression_node<T>::e_veccelem: 34557 | return reinterpret_cast<const void*>(static_cast<vector_celem_node_t*>(node)->vec_holder().data()); 34558 | 34559 | case details::expression_node<T>::e_vecelemrtc: 34560 | return reinterpret_cast<const void*>(static_cast<vector_elem_rtc_node_t*>(node)->vec_holder().data()); 34561 | 34562 | case details::expression_node<T>::e_veccelemrtc: 34563 | return reinterpret_cast<const void*>(static_cast<vector_celem_rtc_node_t*>(node)->vec_holder().data()); 34564 | 34565 | case details::expression_node<T>::e_rbvecelem: 34566 | return reinterpret_cast<const void*>(static_cast<rebasevector_elem_node_t*>(node)->vec_holder().data()); 34567 | 34568 | case details::expression_node<T>::e_rbvecelemrtc: 34569 | return reinterpret_cast<const void*>(static_cast<rebasevector_elem_rtc_node_t*>(node)->vec_holder().data()); 34570 | 34571 | case details::expression_node<T>::e_rbveccelem: 34572 | return reinterpret_cast<const void*>(static_cast<rebasevector_celem_node_t*>(node)->vec_holder().data()); 34573 | 34574 | case details::expression_node<T>::e_rbveccelemrtc: 34575 | return reinterpret_cast<const void*>(static_cast<rebasevector_celem_rtc_node_t*>(node)->vec_holder().data()); 34576 | 34577 | case details::expression_node<T>::e_vector: 34578 | return reinterpret_cast<const void*>(static_cast<vector_node_t*>(node)->vec_holder().data()); 34579 | 34580 | #ifndef exprtk_disable_string_capabilities 34581 | case details::expression_node<T>::e_stringvar: 34582 | return reinterpret_cast<const void*>((static_cast<stringvar_node_t*>(node)->base())); 34583 | 34584 | case details::expression_node<T>::e_stringvarrng: 34585 | return reinterpret_cast<const void*>((static_cast<string_range_node_t*>(node)->base())); 34586 | #endif 34587 | default : return reinterpret_cast<const void*>(0); 34588 | } 34589 | } 34590 | 34591 | return reinterpret_cast<const void*>(0); 34592 | } 34593 | 34594 | bool assign_immutable_symbol(expression_node_ptr node) 34595 | { 34596 | interval_t interval; 34597 | const void* baseptr_addr = base_ptr(node); 34598 | 34599 | exprtk_debug(("assign_immutable_symbol - base ptr addr: %p\n", baseptr_addr)); 34600 | 34601 | if (parser_->immutable_memory_map_.in_interval(baseptr_addr,interval)) 34602 | { 34603 | typename immutable_symtok_map_t::iterator itr = parser_->immutable_symtok_map_.find(interval); 34604 | 34605 | if (parser_->immutable_symtok_map_.end() != itr) 34606 | { 34607 | token_t& token = itr->second; 34608 | parser_->set_error(parser_error::make_error( 34609 | parser_error::e_parser, 34610 | token, 34611 | "ERR275 - Symbol '" + token.value + "' cannot be assigned-to as it is immutable.", 34612 | exprtk_error_location)); 34613 | } 34614 | else 34615 | parser_->set_synthesis_error("Unable to assign symbol is immutable."); 34616 | 34617 | return true; 34618 | } 34619 | 34620 | return false; 34621 | } 34622 | 34623 | inline expression_node_ptr synthesize_assignment_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2]) 34624 | { 34625 | if (assign_immutable_symbol(branch[0])) 34626 | { 34627 | return error_node(); 34628 | } 34629 | else if (details::is_variable_node(branch[0])) 34630 | { 34631 | lodge_assignment(e_st_variable,branch[0]); 34632 | return synthesize_expression<assignment_node_t,2>(operation,branch); 34633 | } 34634 | else if (details::is_vector_elem_node(branch[0]) || details::is_vector_celem_node(branch[0])) 34635 | { 34636 | lodge_assignment(e_st_vecelem,branch[0]); 34637 | return synthesize_expression<assignment_vec_elem_node_t, 2>(operation, branch); 34638 | } 34639 | else if (details::is_vector_elem_rtc_node(branch[0]) || details::is_vector_celem_rtc_node(branch[0])) 34640 | { 34641 | lodge_assignment(e_st_vecelem,branch[0]); 34642 | return synthesize_expression<assignment_vec_elem_rtc_node_t, 2>(operation, branch); 34643 | } 34644 | else if (details::is_rebasevector_elem_node(branch[0])) 34645 | { 34646 | lodge_assignment(e_st_vecelem,branch[0]); 34647 | return synthesize_expression<assignment_rebasevec_elem_node_t, 2>(operation, branch); 34648 | } 34649 | else if (details::is_rebasevector_elem_rtc_node(branch[0])) 34650 | { 34651 | lodge_assignment(e_st_vecelem,branch[0]); 34652 | return synthesize_expression<assignment_rebasevec_elem_rtc_node_t, 2>(operation, branch); 34653 | } 34654 | else if (details::is_rebasevector_celem_node(branch[0])) 34655 | { 34656 | lodge_assignment(e_st_vecelem,branch[0]); 34657 | return synthesize_expression<assignment_rebasevec_celem_node_t, 2>(operation, branch); 34658 | } 34659 | #ifndef exprtk_disable_string_capabilities 34660 | else if (details::is_string_node(branch[0])) 34661 | { 34662 | lodge_assignment(e_st_string,branch[0]); 34663 | return synthesize_expression<assignment_string_node_t,2>(operation, branch); 34664 | } 34665 | else if (details::is_string_range_node(branch[0])) 34666 | { 34667 | lodge_assignment(e_st_string,branch[0]); 34668 | return synthesize_expression<assignment_string_range_node_t,2>(operation, branch); 34669 | } 34670 | #endif 34671 | else if (details::is_vector_node(branch[0])) 34672 | { 34673 | lodge_assignment(e_st_vector,branch[0]); 34674 | 34675 | if (details::is_ivector_node(branch[1])) 34676 | return synthesize_expression<assignment_vecvec_node_t,2>(operation, branch); 34677 | else 34678 | return synthesize_expression<assignment_vec_node_t,2>(operation, branch); 34679 | } 34680 | else if (details::is_literal_node(branch[0])) 34681 | { 34682 | parser_->set_error(parser_error::make_error( 34683 | parser_error::e_syntax, 34684 | parser_->current_state().token, 34685 | "ERR276 - Cannot assign value to const variable", 34686 | exprtk_error_location)); 34687 | 34688 | return error_node(); 34689 | } 34690 | else 34691 | { 34692 | parser_->set_error(parser_error::make_error( 34693 | parser_error::e_syntax, 34694 | parser_->current_state().token, 34695 | "ERR277 - Invalid branches for assignment operator '" + details::to_str(operation) + "'", 34696 | exprtk_error_location)); 34697 | 34698 | return error_node(); 34699 | } 34700 | } 34701 | 34702 | inline expression_node_ptr synthesize_assignment_operation_expression(const details::operator_type& operation, 34703 | expression_node_ptr (&branch)[2]) 34704 | { 34705 | if (assign_immutable_symbol(branch[0])) 34706 | { 34707 | return error_node(); 34708 | } 34709 | 34710 | expression_node_ptr result = error_node(); 34711 | std::string node_name = "Unknown" 34712 | 34713 | if (details::is_variable_node(branch[0])) 34714 | { 34715 | lodge_assignment(e_st_variable,branch[0]); 34716 | 34717 | switch (operation) 34718 | { 34719 | #define case_stmt(op0, op1) \ 34720 | case op0 : result = node_allocator_-> \ 34721 | template allocate_rrr<typename details::assignment_op_node<Type,op1<Type> > > \ 34722 | (operation, branch[0], branch[1]); \ 34723 | node_name = "assignment_op_node" \ 34724 | break; \ 34725 | 34726 | case_stmt(details::e_addass , details::add_op) 34727 | case_stmt(details::e_subass , details::sub_op) 34728 | case_stmt(details::e_mulass , details::mul_op) 34729 | case_stmt(details::e_divass , details::div_op) 34730 | case_stmt(details::e_modass , details::mod_op) 34731 | #undef case_stmt 34732 | default : return error_node(); 34733 | } 34734 | } 34735 | else if (details::is_vector_elem_node(branch[0])) 34736 | { 34737 | lodge_assignment(e_st_vecelem,branch[0]); 34738 | 34739 | switch (operation) 34740 | { 34741 | #define case_stmt(op0, op1) \ 34742 | case op0 : result = node_allocator_-> \ 34743 | template allocate_rrr<typename details::assignment_vec_elem_op_node<Type,op1<Type> > > \ 34744 | (operation, branch[0], branch[1]); \ 34745 | node_name = "assignment_vec_elem_op_node" \ 34746 | break; \ 34747 | 34748 | case_stmt(details::e_addass , details::add_op) 34749 | case_stmt(details::e_subass , details::sub_op) 34750 | case_stmt(details::e_mulass , details::mul_op) 34751 | case_stmt(details::e_divass , details::div_op) 34752 | case_stmt(details::e_modass , details::mod_op) 34753 | #undef case_stmt 34754 | default : return error_node(); 34755 | } 34756 | } 34757 | else if (details::is_vector_elem_rtc_node(branch[0])) 34758 | { 34759 | lodge_assignment(e_st_vecelem,branch[0]); 34760 | 34761 | switch (operation) 34762 | { 34763 | #define case_stmt(op0, op1) \ 34764 | case op0 : result = node_allocator_-> \ 34765 | template allocate_rrr<typename details::assignment_vec_elem_op_rtc_node<Type,op1<Type> > > \ 34766 | (operation, branch[0], branch[1]); \ 34767 | node_name = "assignment_vec_elem_op_rtc_node" \ 34768 | break; \ 34769 | 34770 | case_stmt(details::e_addass , details::add_op) 34771 | case_stmt(details::e_subass , details::sub_op) 34772 | case_stmt(details::e_mulass , details::mul_op) 34773 | case_stmt(details::e_divass , details::div_op) 34774 | case_stmt(details::e_modass , details::mod_op) 34775 | #undef case_stmt 34776 | default : return error_node(); 34777 | } 34778 | } 34779 | else if (details::is_vector_celem_rtc_node(branch[0])) 34780 | { 34781 | lodge_assignment(e_st_vecelem,branch[0]); 34782 | 34783 | switch (operation) 34784 | { 34785 | #define case_stmt(op0, op1) \ 34786 | case op0 : result = node_allocator_-> \ 34787 | template allocate_rrr<typename details::assignment_vec_celem_op_rtc_node<Type,op1<Type> > > \ 34788 | (operation, branch[0], branch[1]); \ 34789 | node_name = "assignment_vec_celem_op_rtc_node" \ 34790 | break; \ 34791 | 34792 | case_stmt(details::e_addass , details::add_op) 34793 | case_stmt(details::e_subass , details::sub_op) 34794 | case_stmt(details::e_mulass , details::mul_op) 34795 | case_stmt(details::e_divass , details::div_op) 34796 | case_stmt(details::e_modass , details::mod_op) 34797 | #undef case_stmt 34798 | default : return error_node(); 34799 | } 34800 | } 34801 | else if (details::is_rebasevector_elem_node(branch[0])) 34802 | { 34803 | lodge_assignment(e_st_vecelem,branch[0]); 34804 | 34805 | switch (operation) 34806 | { 34807 | #define case_stmt(op0, op1) \ 34808 | case op0 : result = node_allocator_-> \ 34809 | template allocate_rrr<typename details::assignment_rebasevec_elem_op_node<Type,op1<Type> > > \ 34810 | (operation, branch[0], branch[1]); \ 34811 | node_name = "assignment_rebasevec_elem_op_node" \ 34812 | break; \ 34813 | 34814 | case_stmt(details::e_addass , details::add_op) 34815 | case_stmt(details::e_subass , details::sub_op) 34816 | case_stmt(details::e_mulass , details::mul_op) 34817 | case_stmt(details::e_divass , details::div_op) 34818 | case_stmt(details::e_modass , details::mod_op) 34819 | #undef case_stmt 34820 | default : return error_node(); 34821 | } 34822 | } 34823 | else if (details::is_rebasevector_celem_node(branch[0])) 34824 | { 34825 | lodge_assignment(e_st_vecelem,branch[0]); 34826 | 34827 | switch (operation) 34828 | { 34829 | #define case_stmt(op0, op1) \ 34830 | case op0 : result = node_allocator_-> \ 34831 | template allocate_rrr<typename details::assignment_rebasevec_celem_op_node<Type,op1<Type> > > \ 34832 | (operation, branch[0], branch[1]); \ 34833 | node_name = "assignment_rebasevec_celem_op_node" \ 34834 | break; \ 34835 | 34836 | case_stmt(details::e_addass , details::add_op) 34837 | case_stmt(details::e_subass , details::sub_op) 34838 | case_stmt(details::e_mulass , details::mul_op) 34839 | case_stmt(details::e_divass , details::div_op) 34840 | case_stmt(details::e_modass , details::mod_op) 34841 | #undef case_stmt 34842 | default : return error_node(); 34843 | } 34844 | } 34845 | else if (details::is_rebasevector_elem_rtc_node(branch[0])) 34846 | { 34847 | lodge_assignment(e_st_vecelem,branch[0]); 34848 | 34849 | switch (operation) 34850 | { 34851 | #define case_stmt(op0, op1) \ 34852 | case op0 : result = node_allocator_-> \ 34853 | template allocate_rrr<typename details::assignment_rebasevec_elem_op_rtc_node<Type,op1<Type> > > \ 34854 | (operation, branch[0], branch[1]); \ 34855 | node_name = "assignment_rebasevec_elem_op_rtc_node" \ 34856 | break; \ 34857 | 34858 | case_stmt(details::e_addass , details::add_op) 34859 | case_stmt(details::e_subass , details::sub_op) 34860 | case_stmt(details::e_mulass , details::mul_op) 34861 | case_stmt(details::e_divass , details::div_op) 34862 | case_stmt(details::e_modass , details::mod_op) 34863 | #undef case_stmt 34864 | default : return error_node(); 34865 | } 34866 | } 34867 | else if (details::is_rebasevector_celem_rtc_node(branch[0])) 34868 | { 34869 | lodge_assignment(e_st_vecelem,branch[0]); 34870 | 34871 | switch (operation) 34872 | { 34873 | #define case_stmt(op0, op1) \ 34874 | case op0 : result = node_allocator_-> \ 34875 | template allocate_rrr<typename details::assignment_rebasevec_celem_op_rtc_node<Type,op1<Type> > > \ 34876 | (operation, branch[0], branch[1]); \ 34877 | node_name = "assignment_rebasevec_celem_op_rtc_node" \ 34878 | break; \ 34879 | 34880 | case_stmt(details::e_addass , details::add_op) 34881 | case_stmt(details::e_subass , details::sub_op) 34882 | case_stmt(details::e_mulass , details::mul_op) 34883 | case_stmt(details::e_divass , details::div_op) 34884 | case_stmt(details::e_modass , details::mod_op) 34885 | #undef case_stmt 34886 | default : return error_node(); 34887 | } 34888 | } 34889 | else if (details::is_vector_node(branch[0])) 34890 | { 34891 | lodge_assignment(e_st_vector,branch[0]); 34892 | 34893 | if (details::is_ivector_node(branch[1])) 34894 | { 34895 | switch (operation) 34896 | { 34897 | #define case_stmt(op0, op1) \ 34898 | case op0 : result = node_allocator_-> \ 34899 | template allocate_rrr<typename details::assignment_vecvec_op_node<Type,op1<Type> > > \ 34900 | (operation, branch[0], branch[1]); \ 34901 | node_name = "assignment_rebasevec_celem_op_node" \ 34902 | break; \ 34903 | 34904 | case_stmt(details::e_addass , details::add_op) 34905 | case_stmt(details::e_subass , details::sub_op) 34906 | case_stmt(details::e_mulass , details::mul_op) 34907 | case_stmt(details::e_divass , details::div_op) 34908 | case_stmt(details::e_modass , details::mod_op) 34909 | #undef case_stmt 34910 | default : return error_node(); 34911 | } 34912 | } 34913 | else 34914 | { 34915 | switch (operation) 34916 | { 34917 | #define case_stmt(op0, op1) \ 34918 | case op0 : result = node_allocator_-> \ 34919 | template allocate_rrr<typename details::assignment_vec_op_node<Type,op1<Type> > > \ 34920 | (operation, branch[0], branch[1]); \ 34921 | node_name = "assignment_vec_op_node" \ 34922 | break; \ 34923 | 34924 | case_stmt(details::e_addass , details::add_op) 34925 | case_stmt(details::e_subass , details::sub_op) 34926 | case_stmt(details::e_mulass , details::mul_op) 34927 | case_stmt(details::e_divass , details::div_op) 34928 | case_stmt(details::e_modass , details::mod_op) 34929 | #undef case_stmt 34930 | default : return error_node(); 34931 | } 34932 | } 34933 | } 34934 | #ifndef exprtk_disable_string_capabilities 34935 | else if ( 34936 | (details::e_addass == operation) && 34937 | details::is_string_node(branch[0]) 34938 | ) 34939 | { 34940 | typedef details::assignment_string_node<T,details::asn_addassignment> addass_t; 34941 | 34942 | lodge_assignment(e_st_string,branch[0]); 34943 | 34944 | result = synthesize_expression<addass_t,2>(operation,branch); 34945 | node_name = "assignment_string_node<T,details::asn_addassignment>" 34946 | } 34947 | #endif 34948 | else 34949 | { 34950 | parser_->set_error(parser_error::make_error( 34951 | parser_error::e_syntax, 34952 | parser_->current_state().token, 34953 | "ERR278 - Invalid branches for assignment operator '" + details::to_str(operation) + "'", 34954 | exprtk_error_location)); 34955 | 34956 | return error_node(); 34957 | } 34958 | 34959 | if (result && result->valid()) 34960 | { 34961 | return result; 34962 | } 34963 | 34964 | parser_->set_error(parser_error::make_error( 34965 | parser_error::e_synthesis, 34966 | token_t(), 34967 | "ERR279 - Failed to synthesize node: " + node_name, 34968 | exprtk_error_location)); 34969 | 34970 | details::free_node(*node_allocator_, result); 34971 | return error_node(); 34972 | } 34973 | 34974 | inline expression_node_ptr synthesize_veceqineqlogic_operation_expression(const details::operator_type& operation, 34975 | expression_node_ptr (&branch)[2]) 34976 | { 34977 | const bool is_b0_ivec = details::is_ivector_node(branch[0]); 34978 | const bool is_b1_ivec = details::is_ivector_node(branch[1]); 34979 | 34980 | #define batch_eqineq_logic_case \ 34981 | case_stmt(details::e_lt , details::lt_op ) \ 34982 | case_stmt(details::e_lte , details::lte_op ) \ 34983 | case_stmt(details::e_gt , details::gt_op ) \ 34984 | case_stmt(details::e_gte , details::gte_op ) \ 34985 | case_stmt(details::e_eq , details::eq_op ) \ 34986 | case_stmt(details::e_ne , details::ne_op ) \ 34987 | case_stmt(details::e_equal , details::equal_op) \ 34988 | case_stmt(details::e_and , details::and_op ) \ 34989 | case_stmt(details::e_nand , details::nand_op ) \ 34990 | case_stmt(details::e_or , details::or_op ) \ 34991 | case_stmt(details::e_nor , details::nor_op ) \ 34992 | case_stmt(details::e_xor , details::xor_op ) \ 34993 | case_stmt(details::e_xnor , details::xnor_op ) \ 34994 | 34995 | expression_node_ptr result = error_node(); 34996 | std::string node_name = "Unknown" 34997 | 34998 | if (is_b0_ivec && is_b1_ivec) 34999 | { 35000 | switch (operation) 35001 | { 35002 | #define case_stmt(op0, op1) \ 35003 | case op0 : result = node_allocator_-> \ 35004 | template allocate_rrr<typename details::vec_binop_vecvec_node<Type,op1<Type> > > \ 35005 | (operation, branch[0], branch[1]); \ 35006 | node_name = "vec_binop_vecvec_node" \ 35007 | break; \ 35008 | 35009 | batch_eqineq_logic_case 35010 | #undef case_stmt 35011 | default : return error_node(); 35012 | } 35013 | } 35014 | else if (is_b0_ivec && !is_b1_ivec) 35015 | { 35016 | switch (operation) 35017 | { 35018 | #define case_stmt(op0, op1) \ 35019 | case op0 : result = node_allocator_-> \ 35020 | template allocate_rrr<typename details::vec_binop_vecval_node<Type,op1<Type> > > \ 35021 | (operation, branch[0], branch[1]); \ 35022 | node_name = "vec_binop_vecval_node" \ 35023 | break; \ 35024 | 35025 | batch_eqineq_logic_case 35026 | #undef case_stmt 35027 | default : return error_node(); 35028 | } 35029 | } 35030 | else if (!is_b0_ivec && is_b1_ivec) 35031 | { 35032 | switch (operation) 35033 | { 35034 | #define case_stmt(op0, op1) \ 35035 | case op0 : result = node_allocator_-> \ 35036 | template allocate_rrr<typename details::vec_binop_valvec_node<Type,op1<Type> > > \ 35037 | (operation, branch[0], branch[1]); \ 35038 | node_name = "vec_binop_valvec_node" \ 35039 | break; \ 35040 | 35041 | batch_eqineq_logic_case 35042 | #undef case_stmt 35043 | default : return error_node(); 35044 | } 35045 | } 35046 | else 35047 | return error_node(); 35048 | 35049 | if (result && result->valid()) 35050 | { 35051 | return result; 35052 | } 35053 | 35054 | parser_->set_error(parser_error::make_error( 35055 | parser_error::e_synthesis, 35056 | token_t(), 35057 | "ERR280 - Failed to synthesize node: " + node_name, 35058 | exprtk_error_location)); 35059 | 35060 | details::free_node(*node_allocator_, result); 35061 | return error_node(); 35062 | 35063 | #undef batch_eqineq_logic_case 35064 | } 35065 | 35066 | inline expression_node_ptr synthesize_vecarithmetic_operation_expression(const details::operator_type& operation, 35067 | expression_node_ptr (&branch)[2]) 35068 | { 35069 | const bool is_b0_ivec = details::is_ivector_node(branch[0]); 35070 | const bool is_b1_ivec = details::is_ivector_node(branch[1]); 35071 | 35072 | #define vector_ops \ 35073 | case_stmt(details::e_add , details::add_op) \ 35074 | case_stmt(details::e_sub , details::sub_op) \ 35075 | case_stmt(details::e_mul , details::mul_op) \ 35076 | case_stmt(details::e_div , details::div_op) \ 35077 | case_stmt(details::e_mod , details::mod_op) \ 35078 | 35079 | expression_node_ptr result = error_node(); 35080 | std::string node_name = "Unknown" 35081 | 35082 | if (is_b0_ivec && is_b1_ivec) 35083 | { 35084 | switch (operation) 35085 | { 35086 | #define case_stmt(op0, op1) \ 35087 | case op0 : result = node_allocator_-> \ 35088 | template allocate_rrr<typename details::vec_binop_vecvec_node<Type,op1<Type> > > \ 35089 | (operation, branch[0], branch[1]); \ 35090 | node_name = "vec_binop_vecvec_node" \ 35091 | break; \ 35092 | 35093 | vector_ops 35094 | case_stmt(details::e_pow,details:: pow_op) 35095 | #undef case_stmt 35096 | default : return error_node(); 35097 | } 35098 | } 35099 | else if (is_b0_ivec && !is_b1_ivec) 35100 | { 35101 | switch (operation) 35102 | { 35103 | #define case_stmt(op0, op1) \ 35104 | case op0 : result = node_allocator_-> \ 35105 | template allocate_rrr<typename details::vec_binop_vecval_node<Type,op1<Type> > > \ 35106 | (operation, branch[0], branch[1]); \ 35107 | node_name = "vec_binop_vecval_node(b0ivec,!b1ivec)" \ 35108 | break; \ 35109 | 35110 | vector_ops 35111 | case_stmt(details::e_pow,details:: pow_op) 35112 | #undef case_stmt 35113 | default : return error_node(); 35114 | } 35115 | } 35116 | else if (!is_b0_ivec && is_b1_ivec) 35117 | { 35118 | switch (operation) 35119 | { 35120 | #define case_stmt(op0, op1) \ 35121 | case op0 : result = node_allocator_-> \ 35122 | template allocate_rrr<typename details::vec_binop_valvec_node<Type,op1<Type> > > \ 35123 | (operation, branch[0], branch[1]); \ 35124 | node_name = "vec_binop_vecval_node(!b0ivec,b1ivec)" \ 35125 | break; \ 35126 | 35127 | vector_ops 35128 | #undef case_stmt 35129 | default : return error_node(); 35130 | } 35131 | } 35132 | else 35133 | return error_node(); 35134 | 35135 | if (result && result->valid()) 35136 | { 35137 | return result; 35138 | } 35139 | 35140 | parser_->set_error(parser_error::make_error( 35141 | parser_error::e_synthesis, 35142 | token_t(), 35143 | "ERR281 - Failed to synthesize node: " + node_name, 35144 | exprtk_error_location)); 35145 | 35146 | details::free_node(*node_allocator_, result); 35147 | return error_node(); 35148 | 35149 | #undef vector_ops 35150 | } 35151 | 35152 | inline expression_node_ptr synthesize_swap_expression(expression_node_ptr (&branch)[2]) 35153 | { 35154 | const bool v0_is_ivar = details::is_ivariable_node(branch[0]); 35155 | const bool v1_is_ivar = details::is_ivariable_node(branch[1]); 35156 | 35157 | const bool v0_is_ivec = details::is_ivector_node (branch[0]); 35158 | const bool v1_is_ivec = details::is_ivector_node (branch[1]); 35159 | 35160 | #ifndef exprtk_disable_string_capabilities 35161 | const bool v0_is_str = details::is_generally_string_node(branch[0]); 35162 | const bool v1_is_str = details::is_generally_string_node(branch[1]); 35163 | #endif 35164 | 35165 | expression_node_ptr result = error_node(); 35166 | std::string node_name = "Unknown" 35167 | 35168 | if (v0_is_ivar && v1_is_ivar) 35169 | { 35170 | typedef details::variable_node<T>* variable_node_ptr; 35171 | 35172 | variable_node_ptr v0 = variable_node_ptr(0); 35173 | variable_node_ptr v1 = variable_node_ptr(0); 35174 | 35175 | if ( 35176 | (0 != (v0 = dynamic_cast<variable_node_ptr>(branch[0]))) && 35177 | (0 != (v1 = dynamic_cast<variable_node_ptr>(branch[1]))) 35178 | ) 35179 | { 35180 | result = node_allocator_->allocate<details::swap_node<T> >(v0,v1); 35181 | node_name = "swap_node" 35182 | } 35183 | else 35184 | { 35185 | result = node_allocator_->allocate<details::swap_generic_node<T> >(branch[0],branch[1]); 35186 | node_name = "swap_generic_node" 35187 | } 35188 | } 35189 | else if (v0_is_ivec && v1_is_ivec) 35190 | { 35191 | result = node_allocator_->allocate<details::swap_vecvec_node<T> >(branch[0],branch[1]); 35192 | node_name = "swap_vecvec_node" 35193 | } 35194 | #ifndef exprtk_disable_string_capabilities 35195 | else if (v0_is_str && v1_is_str) 35196 | { 35197 | if (is_string_node(branch[0]) && is_string_node(branch[1])) 35198 | { 35199 | result = node_allocator_->allocate<details::swap_string_node<T> > 35200 | (branch[0], branch[1]); 35201 | node_name = "swap_string_node" 35202 | } 35203 | else 35204 | { 35205 | result = node_allocator_->allocate<details::swap_genstrings_node<T> > 35206 | (branch[0], branch[1]); 35207 | node_name = "swap_genstrings_node" 35208 | } 35209 | } 35210 | #endif 35211 | else 35212 | { 35213 | parser_->set_synthesis_error("Only variables, strings, vectors or vector elements can be swapped"); 35214 | return error_node(); 35215 | } 35216 | 35217 | if (result && result->valid()) 35218 | { 35219 | parser_->state_.activate_side_effect("synthesize_swap_expression()"); 35220 | return result; 35221 | } 35222 | 35223 | parser_->set_error(parser_error::make_error( 35224 | parser_error::e_synthesis, 35225 | token_t(), 35226 | "ERR282 - Failed to synthesize node: " + node_name, 35227 | exprtk_error_location)); 35228 | 35229 | details::free_node(*node_allocator_, result); 35230 | return error_node(); 35231 | } 35232 | 35233 | #ifndef exprtk_disable_sc_andor 35234 | inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2]) 35235 | { 35236 | expression_node_ptr result = error_node(); 35237 | 35238 | if (details::is_constant_node(branch[0])) 35239 | { 35240 | if ( 35241 | (details::e_scand == operation) && 35242 | std::equal_to<T>()(T(0),branch[0]->value()) 35243 | ) 35244 | result = node_allocator_->allocate_c<literal_node_t>(T(0)); 35245 | else if ( 35246 | (details::e_scor == operation) && 35247 | std::not_equal_to<T>()(T(0),branch[0]->value()) 35248 | ) 35249 | result = node_allocator_->allocate_c<literal_node_t>(T(1)); 35250 | } 35251 | 35252 | if (details::is_constant_node(branch[1]) && (0 == result)) 35253 | { 35254 | if ( 35255 | (details::e_scand == operation) && 35256 | std::equal_to<T>()(T(0),branch[1]->value()) 35257 | ) 35258 | result = node_allocator_->allocate_c<literal_node_t>(T(0)); 35259 | else if ( 35260 | (details::e_scor == operation) && 35261 | std::not_equal_to<T>()(T(0),branch[1]->value()) 35262 | ) 35263 | result = node_allocator_->allocate_c<literal_node_t>(T(1)); 35264 | } 35265 | 35266 | if (result) 35267 | { 35268 | details::free_node(*node_allocator_, branch[0]); 35269 | details::free_node(*node_allocator_, branch[1]); 35270 | 35271 | return result; 35272 | } 35273 | else if (details::e_scand == operation) 35274 | { 35275 | return synthesize_expression<scand_node_t,2>(operation, branch); 35276 | } 35277 | else if (details::e_scor == operation) 35278 | { 35279 | return synthesize_expression<scor_node_t,2>(operation, branch); 35280 | } 35281 | else 35282 | return error_node(); 35283 | } 35284 | #else 35285 | inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type&, expression_node_ptr (&)[2]) 35286 | { 35287 | return error_node(); 35288 | } 35289 | #endif 35290 | 35291 | #define basic_opr_switch_statements \ 35292 | case_stmt(details::e_add , details::add_op) \ 35293 | case_stmt(details::e_sub , details::sub_op) \ 35294 | case_stmt(details::e_mul , details::mul_op) \ 35295 | case_stmt(details::e_div , details::div_op) \ 35296 | case_stmt(details::e_mod , details::mod_op) \ 35297 | case_stmt(details::e_pow , details::pow_op) \ 35298 | 35299 | #define extended_opr_switch_statements \ 35300 | case_stmt(details::e_lt , details::lt_op ) \ 35301 | case_stmt(details::e_lte , details::lte_op ) \ 35302 | case_stmt(details::e_gt , details::gt_op ) \ 35303 | case_stmt(details::e_gte , details::gte_op ) \ 35304 | case_stmt(details::e_eq , details::eq_op ) \ 35305 | case_stmt(details::e_ne , details::ne_op ) \ 35306 | case_stmt(details::e_and , details::and_op ) \ 35307 | case_stmt(details::e_nand , details::nand_op) \ 35308 | case_stmt(details::e_or , details::or_op ) \ 35309 | case_stmt(details::e_nor , details::nor_op ) \ 35310 | case_stmt(details::e_xor , details::xor_op ) \ 35311 | case_stmt(details::e_xnor , details::xnor_op) \ 35312 | 35313 | #ifndef exprtk_disable_cardinal_pow_optimisation 35314 | template <typename TType, template <typename, typename> class IPowNode> 35315 | inline expression_node_ptr cardinal_pow_optimisation_impl(const TType& v, const unsigned int& p) 35316 | { 35317 | switch (p) 35318 | { 35319 | #define case_stmt(cp) \ 35320 | case cp : return node_allocator_-> \ 35321 | allocate<IPowNode<T,details::numeric::fast_exp<T,cp> > >(v); \ 35322 | 35323 | case_stmt( 1) case_stmt( 2) case_stmt( 3) case_stmt( 4) 35324 | case_stmt( 5) case_stmt( 6) case_stmt( 7) case_stmt( 8) 35325 | case_stmt( 9) case_stmt(10) case_stmt(11) case_stmt(12) 35326 | case_stmt(13) case_stmt(14) case_stmt(15) case_stmt(16) 35327 | case_stmt(17) case_stmt(18) case_stmt(19) case_stmt(20) 35328 | case_stmt(21) case_stmt(22) case_stmt(23) case_stmt(24) 35329 | case_stmt(25) case_stmt(26) case_stmt(27) case_stmt(28) 35330 | case_stmt(29) case_stmt(30) case_stmt(31) case_stmt(32) 35331 | case_stmt(33) case_stmt(34) case_stmt(35) case_stmt(36) 35332 | case_stmt(37) case_stmt(38) case_stmt(39) case_stmt(40) 35333 | case_stmt(41) case_stmt(42) case_stmt(43) case_stmt(44) 35334 | case_stmt(45) case_stmt(46) case_stmt(47) case_stmt(48) 35335 | case_stmt(49) case_stmt(50) case_stmt(51) case_stmt(52) 35336 | case_stmt(53) case_stmt(54) case_stmt(55) case_stmt(56) 35337 | case_stmt(57) case_stmt(58) case_stmt(59) case_stmt(60) 35338 | #undef case_stmt 35339 | default : return error_node(); 35340 | } 35341 | } 35342 | 35343 | inline expression_node_ptr cardinal_pow_optimisation(const T& v, const T& c) 35344 | { 35345 | const bool not_recipricol = (c >= T(0)); 35346 | const unsigned int p = static_cast<unsigned int>(details::numeric::to_int32(details::numeric::abs(c))); 35347 | 35348 | if (0 == p) 35349 | return node_allocator_->allocate_c<literal_node_t>(T(1)); 35350 | else if (std::equal_to<T>()(T(2),c)) 35351 | { 35352 | return node_allocator_-> 35353 | template allocate_rr<typename details::vov_node<Type,details::mul_op<Type> > >(v,v); 35354 | } 35355 | else 35356 | { 35357 | if (not_recipricol) 35358 | return cardinal_pow_optimisation_impl<T,details::ipow_node>(v,p); 35359 | else 35360 | return cardinal_pow_optimisation_impl<T,details::ipowinv_node>(v,p); 35361 | } 35362 | } 35363 | 35364 | inline bool cardinal_pow_optimisable(const details::operator_type& operation, const T& c) const 35365 | { 35366 | return (details::e_pow == operation) && (details::numeric::abs(c) <= T(60)) && details::numeric::is_integer(c); 35367 | } 35368 | 35369 | inline expression_node_ptr cardinal_pow_optimisation(expression_node_ptr (&branch)[2]) 35370 | { 35371 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 35372 | const bool not_recipricol = (c >= T(0)); 35373 | const unsigned int p = static_cast<unsigned int>(details::numeric::to_int32(details::numeric::abs(c))); 35374 | 35375 | node_allocator_->free(branch[1]); 35376 | 35377 | if (0 == p) 35378 | { 35379 | details::free_all_nodes(*node_allocator_, branch); 35380 | 35381 | return node_allocator_->allocate_c<literal_node_t>(T(1)); 35382 | } 35383 | else if (not_recipricol) 35384 | return cardinal_pow_optimisation_impl<expression_node_ptr,details::bipow_node>(branch[0],p); 35385 | else 35386 | return cardinal_pow_optimisation_impl<expression_node_ptr,details::bipowinv_node>(branch[0],p); 35387 | } 35388 | #else 35389 | inline expression_node_ptr cardinal_pow_optimisation(T&, const T&) 35390 | { 35391 | return error_node(); 35392 | } 35393 | 35394 | inline bool cardinal_pow_optimisable(const details::operator_type&, const T&) 35395 | { 35396 | return false; 35397 | } 35398 | 35399 | inline expression_node_ptr cardinal_pow_optimisation(expression_node_ptr(&)[2]) 35400 | { 35401 | return error_node(); 35402 | } 35403 | #endif 35404 | 35405 | struct synthesize_binary_ext_expression 35406 | { 35407 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 35408 | const details::operator_type& operation, 35409 | expression_node_ptr (&branch)[2]) 35410 | { 35411 | const bool left_neg = is_neg_unary_node(branch[0]); 35412 | const bool right_neg = is_neg_unary_node(branch[1]); 35413 | 35414 | if (left_neg && right_neg) 35415 | { 35416 | if ( 35417 | (details::e_add == operation) || 35418 | (details::e_sub == operation) || 35419 | (details::e_mul == operation) || 35420 | (details::e_div == operation) 35421 | ) 35422 | { 35423 | if ( 35424 | !expr_gen.parser_->simplify_unary_negation_branch(branch[0]) || 35425 | !expr_gen.parser_->simplify_unary_negation_branch(branch[1]) 35426 | ) 35427 | { 35428 | details::free_all_nodes(*expr_gen.node_allocator_,branch); 35429 | 35430 | return error_node(); 35431 | } 35432 | } 35433 | 35434 | switch (operation) 35435 | { 35436 | // -f(x + 1) + -g(y + 1) --> -(f(x + 1) + g(y + 1)) 35437 | case details::e_add : return expr_gen(details::e_neg, 35438 | expr_gen.node_allocator_-> 35439 | template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > > 35440 | (branch[0],branch[1])); 35441 | 35442 | // -f(x + 1) - -g(y + 1) --> g(y + 1) - f(x + 1) 35443 | case details::e_sub : return expr_gen.node_allocator_-> 35444 | template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > > 35445 | (branch[1],branch[0]); 35446 | 35447 | default : break; 35448 | } 35449 | } 35450 | else if (left_neg && !right_neg) 35451 | { 35452 | if ( 35453 | (details::e_add == operation) || 35454 | (details::e_sub == operation) || 35455 | (details::e_mul == operation) || 35456 | (details::e_div == operation) 35457 | ) 35458 | { 35459 | if (!expr_gen.parser_->simplify_unary_negation_branch(branch[0])) 35460 | { 35461 | details::free_all_nodes(*expr_gen.node_allocator_,branch); 35462 | 35463 | return error_node(); 35464 | } 35465 | 35466 | switch (operation) 35467 | { 35468 | // -f(x + 1) + g(y + 1) --> g(y + 1) - f(x + 1) 35469 | case details::e_add : return expr_gen.node_allocator_-> 35470 | template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > > 35471 | (branch[1], branch[0]); 35472 | 35473 | // -f(x + 1) - g(y + 1) --> -(f(x + 1) + g(y + 1)) 35474 | case details::e_sub : return expr_gen(details::e_neg, 35475 | expr_gen.node_allocator_-> 35476 | template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > > 35477 | (branch[0], branch[1])); 35478 | 35479 | // -f(x + 1) * g(y + 1) --> -(f(x + 1) * g(y + 1)) 35480 | case details::e_mul : return expr_gen(details::e_neg, 35481 | expr_gen.node_allocator_-> 35482 | template allocate<typename details::binary_ext_node<Type,details::mul_op<Type> > > 35483 | (branch[0], branch[1])); 35484 | 35485 | // -f(x + 1) / g(y + 1) --> -(f(x + 1) / g(y + 1)) 35486 | case details::e_div : return expr_gen(details::e_neg, 35487 | expr_gen.node_allocator_-> 35488 | template allocate<typename details::binary_ext_node<Type,details::div_op<Type> > > 35489 | (branch[0], branch[1])); 35490 | 35491 | default : return error_node(); 35492 | } 35493 | } 35494 | } 35495 | else if (!left_neg && right_neg) 35496 | { 35497 | if ( 35498 | (details::e_add == operation) || 35499 | (details::e_sub == operation) || 35500 | (details::e_mul == operation) || 35501 | (details::e_div == operation) 35502 | ) 35503 | { 35504 | if (!expr_gen.parser_->simplify_unary_negation_branch(branch[1])) 35505 | { 35506 | details::free_all_nodes(*expr_gen.node_allocator_,branch); 35507 | 35508 | return error_node(); 35509 | } 35510 | 35511 | switch (operation) 35512 | { 35513 | // f(x + 1) + -g(y + 1) --> f(x + 1) - g(y + 1) 35514 | case details::e_add : return expr_gen.node_allocator_-> 35515 | template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > > 35516 | (branch[0], branch[1]); 35517 | 35518 | // f(x + 1) - - g(y + 1) --> f(x + 1) + g(y + 1) 35519 | case details::e_sub : return expr_gen.node_allocator_-> 35520 | template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > > 35521 | (branch[0], branch[1]); 35522 | 35523 | // f(x + 1) * -g(y + 1) --> -(f(x + 1) * g(y + 1)) 35524 | case details::e_mul : return expr_gen(details::e_neg, 35525 | expr_gen.node_allocator_-> 35526 | template allocate<typename details::binary_ext_node<Type,details::mul_op<Type> > > 35527 | (branch[0], branch[1])); 35528 | 35529 | // f(x + 1) / -g(y + 1) --> -(f(x + 1) / g(y + 1)) 35530 | case details::e_div : return expr_gen(details::e_neg, 35531 | expr_gen.node_allocator_-> 35532 | template allocate<typename details::binary_ext_node<Type,details::div_op<Type> > > 35533 | (branch[0], branch[1])); 35534 | 35535 | default : return error_node(); 35536 | } 35537 | } 35538 | } 35539 | 35540 | switch (operation) 35541 | { 35542 | #define case_stmt(op0, op1) \ 35543 | case op0 : return expr_gen.node_allocator_-> \ 35544 | template allocate<typename details::binary_ext_node<Type,op1<Type> > > \ 35545 | (branch[0], branch[1]); \ 35546 | 35547 | basic_opr_switch_statements 35548 | extended_opr_switch_statements 35549 | #undef case_stmt 35550 | default : return error_node(); 35551 | } 35552 | } 35553 | }; 35554 | 35555 | struct synthesize_vob_expression 35556 | { 35557 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 35558 | const details::operator_type& operation, 35559 | expression_node_ptr (&branch)[2]) 35560 | { 35561 | const Type& v = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 35562 | 35563 | #ifndef exprtk_disable_enhanced_features 35564 | if (details::is_sf3ext_node(branch[1])) 35565 | { 35566 | expression_node_ptr result = error_node(); 35567 | 35568 | const bool synthesis_result = 35569 | synthesize_sf4ext_expression::template compile_right<vtype> 35570 | (expr_gen, v, operation, branch[1], result); 35571 | 35572 | if (synthesis_result) 35573 | { 35574 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35575 | return result; 35576 | } 35577 | } 35578 | #endif 35579 | 35580 | if ( 35581 | (details::e_mul == operation) || 35582 | (details::e_div == operation) 35583 | ) 35584 | { 35585 | if (details::is_uv_node(branch[1])) 35586 | { 35587 | typedef details::uv_base_node<Type>* uvbn_ptr_t; 35588 | 35589 | details::operator_type o = static_cast<uvbn_ptr_t>(branch[1])->operation(); 35590 | 35591 | if (details::e_neg == o) 35592 | { 35593 | const Type& v1 = static_cast<uvbn_ptr_t>(branch[1])->v(); 35594 | 35595 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35596 | 35597 | switch (operation) 35598 | { 35599 | case details::e_mul : return expr_gen(details::e_neg, 35600 | expr_gen.node_allocator_-> 35601 | template allocate_rr<typename details:: 35602 | vov_node<Type,details::mul_op<Type> > >(v,v1)); 35603 | 35604 | case details::e_div : return expr_gen(details::e_neg, 35605 | expr_gen.node_allocator_-> 35606 | template allocate_rr<typename details:: 35607 | vov_node<Type,details::div_op<Type> > >(v,v1)); 35608 | 35609 | default : break; 35610 | } 35611 | } 35612 | } 35613 | } 35614 | 35615 | switch (operation) 35616 | { 35617 | #define case_stmt(op0, op1) \ 35618 | case op0 : return expr_gen.node_allocator_-> \ 35619 | template allocate_rc<typename details::vob_node<Type,op1<Type> > > \ 35620 | (v, branch[1]); \ 35621 | 35622 | basic_opr_switch_statements 35623 | extended_opr_switch_statements 35624 | #undef case_stmt 35625 | default : return error_node(); 35626 | } 35627 | } 35628 | }; 35629 | 35630 | struct synthesize_bov_expression 35631 | { 35632 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 35633 | const details::operator_type& operation, 35634 | expression_node_ptr (&branch)[2]) 35635 | { 35636 | const Type& v = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 35637 | 35638 | #ifndef exprtk_disable_enhanced_features 35639 | if (details::is_sf3ext_node(branch[0])) 35640 | { 35641 | expression_node_ptr result = error_node(); 35642 | 35643 | const bool synthesis_result = 35644 | synthesize_sf4ext_expression::template compile_left<vtype> 35645 | (expr_gen, v, operation, branch[0], result); 35646 | 35647 | if (synthesis_result) 35648 | { 35649 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35650 | 35651 | return result; 35652 | } 35653 | } 35654 | #endif 35655 | 35656 | if ( 35657 | (details::e_add == operation) || 35658 | (details::e_sub == operation) || 35659 | (details::e_mul == operation) || 35660 | (details::e_div == operation) 35661 | ) 35662 | { 35663 | if (details::is_uv_node(branch[0])) 35664 | { 35665 | typedef details::uv_base_node<Type>* uvbn_ptr_t; 35666 | 35667 | details::operator_type o = static_cast<uvbn_ptr_t>(branch[0])->operation(); 35668 | 35669 | if (details::e_neg == o) 35670 | { 35671 | const Type& v0 = static_cast<uvbn_ptr_t>(branch[0])->v(); 35672 | 35673 | details::free_node(*expr_gen.node_allocator_,branch[0]); 35674 | 35675 | switch (operation) 35676 | { 35677 | case details::e_add : return expr_gen.node_allocator_-> 35678 | template allocate_rr<typename details:: 35679 | vov_node<Type,details::sub_op<Type> > >(v,v0); 35680 | 35681 | case details::e_sub : return expr_gen(details::e_neg, 35682 | expr_gen.node_allocator_-> 35683 | template allocate_rr<typename details:: 35684 | vov_node<Type,details::add_op<Type> > >(v0,v)); 35685 | 35686 | case details::e_mul : return expr_gen(details::e_neg, 35687 | expr_gen.node_allocator_-> 35688 | template allocate_rr<typename details:: 35689 | vov_node<Type,details::mul_op<Type> > >(v0,v)); 35690 | 35691 | case details::e_div : return expr_gen(details::e_neg, 35692 | expr_gen.node_allocator_-> 35693 | template allocate_rr<typename details:: 35694 | vov_node<Type,details::div_op<Type> > >(v0,v)); 35695 | default : break; 35696 | } 35697 | } 35698 | } 35699 | } 35700 | 35701 | switch (operation) 35702 | { 35703 | #define case_stmt(op0, op1) \ 35704 | case op0 : return expr_gen.node_allocator_-> \ 35705 | template allocate_cr<typename details::bov_node<Type,op1<Type> > > \ 35706 | (branch[0], v); \ 35707 | 35708 | basic_opr_switch_statements 35709 | extended_opr_switch_statements 35710 | #undef case_stmt 35711 | default : return error_node(); 35712 | } 35713 | } 35714 | }; 35715 | 35716 | struct synthesize_cob_expression 35717 | { 35718 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 35719 | const details::operator_type& operation, 35720 | expression_node_ptr (&branch)[2]) 35721 | { 35722 | const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); 35723 | 35724 | details::free_node(*expr_gen.node_allocator_,branch[0]); 35725 | 35726 | if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation)) 35727 | { 35728 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35729 | 35730 | return expr_gen(T(0)); 35731 | } 35732 | else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation)) 35733 | { 35734 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35735 | 35736 | return expr_gen(T(0)); 35737 | } 35738 | else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation)) 35739 | return branch[1]; 35740 | else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation)) 35741 | return branch[1]; 35742 | 35743 | if (details::is_cob_node(branch[1])) 35744 | { 35745 | // Simplify expressions of the form: 35746 | // 1. (1 * (2 * (3 * (4 * (5 * (6 * (7 * (8 * (9 + x))))))))) --> 40320 * (9 + x) 35747 | // 2. (1 + (2 + (3 + (4 + (5 + (6 + (7 + (8 + (9 + x))))))))) --> 45 + x 35748 | if ( 35749 | (details::e_mul == operation) || 35750 | (details::e_add == operation) 35751 | ) 35752 | { 35753 | details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]); 35754 | 35755 | if (operation == cobnode->operation()) 35756 | { 35757 | switch (operation) 35758 | { 35759 | case details::e_add : cobnode->set_c(c + cobnode->c()); break; 35760 | case details::e_mul : cobnode->set_c(c * cobnode->c()); break; 35761 | default : return error_node(); 35762 | } 35763 | 35764 | return cobnode; 35765 | } 35766 | } 35767 | 35768 | if (operation == details::e_mul) 35769 | { 35770 | details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]); 35771 | details::operator_type cob_opr = cobnode->operation(); 35772 | 35773 | if ( 35774 | (details::e_div == cob_opr) || 35775 | (details::e_mul == cob_opr) 35776 | ) 35777 | { 35778 | switch (cob_opr) 35779 | { 35780 | case details::e_div : cobnode->set_c(c * cobnode->c()); break; 35781 | case details::e_mul : cobnode->set_c(cobnode->c() / c); break; 35782 | default : return error_node(); 35783 | } 35784 | 35785 | return cobnode; 35786 | } 35787 | } 35788 | else if (operation == details::e_div) 35789 | { 35790 | details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]); 35791 | details::operator_type cob_opr = cobnode->operation(); 35792 | 35793 | if ( 35794 | (details::e_div == cob_opr) || 35795 | (details::e_mul == cob_opr) 35796 | ) 35797 | { 35798 | details::expression_node<Type>* new_cobnode = error_node(); 35799 | 35800 | switch (cob_opr) 35801 | { 35802 | case details::e_div : new_cobnode = expr_gen.node_allocator_-> 35803 | template allocate_tt<typename details::cob_node<Type,details::mul_op<Type> > > 35804 | (c / cobnode->c(), cobnode->move_branch(0)); 35805 | break; 35806 | 35807 | case details::e_mul : new_cobnode = expr_gen.node_allocator_-> 35808 | template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > > 35809 | (c / cobnode->c(), cobnode->move_branch(0)); 35810 | break; 35811 | 35812 | default : return error_node(); 35813 | } 35814 | 35815 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35816 | 35817 | return new_cobnode; 35818 | } 35819 | } 35820 | } 35821 | #ifndef exprtk_disable_enhanced_features 35822 | else if (details::is_sf3ext_node(branch[1])) 35823 | { 35824 | expression_node_ptr result = error_node(); 35825 | 35826 | const bool synthesis_result = 35827 | synthesize_sf4ext_expression::template compile_right<ctype> 35828 | (expr_gen, c, operation, branch[1], result); 35829 | 35830 | if (synthesis_result) 35831 | { 35832 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35833 | 35834 | return result; 35835 | } 35836 | } 35837 | #endif 35838 | 35839 | switch (operation) 35840 | { 35841 | #define case_stmt(op0, op1) \ 35842 | case op0 : return expr_gen.node_allocator_-> \ 35843 | template allocate_tt<typename details::cob_node<Type,op1<Type> > > \ 35844 | (c, branch[1]); \ 35845 | 35846 | basic_opr_switch_statements 35847 | extended_opr_switch_statements 35848 | #undef case_stmt 35849 | default : return error_node(); 35850 | } 35851 | } 35852 | }; 35853 | 35854 | struct synthesize_boc_expression 35855 | { 35856 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 35857 | const details::operator_type& operation, 35858 | expression_node_ptr (&branch)[2]) 35859 | { 35860 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 35861 | 35862 | details::free_node(*(expr_gen.node_allocator_), branch[1]); 35863 | 35864 | if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation)) 35865 | { 35866 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35867 | 35868 | return expr_gen(T(0)); 35869 | } 35870 | else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation)) 35871 | { 35872 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35873 | 35874 | return expr_gen(std::numeric_limits<T>::quiet_NaN()); 35875 | } 35876 | else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation)) 35877 | return branch[0]; 35878 | else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation)) 35879 | return branch[0]; 35880 | 35881 | if (details::is_boc_node(branch[0])) 35882 | { 35883 | // Simplify expressions of the form: 35884 | // 1. (((((((((x + 9) * 8) * 7) * 6) * 5) * 4) * 3) * 2) * 1) --> (x + 9) * 40320 35885 | // 2. (((((((((x + 9) + 8) + 7) + 6) + 5) + 4) + 3) + 2) + 1) --> x + 45 35886 | if ( 35887 | (details::e_mul == operation) || 35888 | (details::e_add == operation) 35889 | ) 35890 | { 35891 | details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]); 35892 | 35893 | if (operation == bocnode->operation()) 35894 | { 35895 | switch (operation) 35896 | { 35897 | case details::e_add : bocnode->set_c(c + bocnode->c()); break; 35898 | case details::e_mul : bocnode->set_c(c * bocnode->c()); break; 35899 | default : return error_node(); 35900 | } 35901 | 35902 | return bocnode; 35903 | } 35904 | } 35905 | else if (operation == details::e_div) 35906 | { 35907 | details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]); 35908 | details::operator_type boc_opr = bocnode->operation(); 35909 | 35910 | if ( 35911 | (details::e_div == boc_opr) || 35912 | (details::e_mul == boc_opr) 35913 | ) 35914 | { 35915 | switch (boc_opr) 35916 | { 35917 | case details::e_div : bocnode->set_c(c * bocnode->c()); break; 35918 | case details::e_mul : bocnode->set_c(bocnode->c() / c); break; 35919 | default : return error_node(); 35920 | } 35921 | 35922 | return bocnode; 35923 | } 35924 | } 35925 | else if (operation == details::e_pow) 35926 | { 35927 | // (v ^ c0) ^ c1 --> v ^(c0 * c1) 35928 | details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]); 35929 | details::operator_type boc_opr = bocnode->operation(); 35930 | 35931 | if (details::e_pow == boc_opr) 35932 | { 35933 | bocnode->set_c(bocnode->c() * c); 35934 | 35935 | return bocnode; 35936 | } 35937 | } 35938 | } 35939 | 35940 | #ifndef exprtk_disable_enhanced_features 35941 | if (details::is_sf3ext_node(branch[0])) 35942 | { 35943 | expression_node_ptr result = error_node(); 35944 | 35945 | const bool synthesis_result = 35946 | synthesize_sf4ext_expression::template compile_left<ctype> 35947 | (expr_gen, c, operation, branch[0], result); 35948 | 35949 | if (synthesis_result) 35950 | { 35951 | free_node(*expr_gen.node_allocator_, branch[0]); 35952 | 35953 | return result; 35954 | } 35955 | } 35956 | #endif 35957 | 35958 | switch (operation) 35959 | { 35960 | #define case_stmt(op0, op1) \ 35961 | case op0 : return expr_gen.node_allocator_-> \ 35962 | template allocate_cr<typename details::boc_node<Type,op1<Type> > > \ 35963 | (branch[0], c); \ 35964 | 35965 | basic_opr_switch_statements 35966 | extended_opr_switch_statements 35967 | #undef case_stmt 35968 | default : return error_node(); 35969 | } 35970 | } 35971 | }; 35972 | 35973 | struct synthesize_cocob_expression 35974 | { 35975 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 35976 | const details::operator_type& operation, 35977 | expression_node_ptr (&branch)[2]) 35978 | { 35979 | expression_node_ptr result = error_node(); 35980 | 35981 | // (cob) o c --> cob 35982 | if (details::is_cob_node(branch[0])) 35983 | { 35984 | details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[0]); 35985 | 35986 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 35987 | 35988 | if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation)) 35989 | { 35990 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35991 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35992 | 35993 | return expr_gen(T(0)); 35994 | } 35995 | else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation)) 35996 | { 35997 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35998 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35999 | 36000 | return expr_gen(T(std::numeric_limits<T>::quiet_NaN())); 36001 | } 36002 | else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation)) 36003 | { 36004 | details::free_node(*expr_gen.node_allocator_, branch[1]); 36005 | 36006 | return branch[0]; 36007 | } 36008 | else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation)) 36009 | { 36010 | details::free_node(*expr_gen.node_allocator_, branch[1]); 36011 | 36012 | return branch[0]; 36013 | } 36014 | else if (std::equal_to<T>()(T(1),c) && (details::e_div == operation)) 36015 | { 36016 | details::free_node(*expr_gen.node_allocator_, branch[1]); 36017 | 36018 | return branch[0]; 36019 | } 36020 | 36021 | const bool op_addsub = (details::e_add == cobnode->operation()) || 36022 | (details::e_sub == cobnode->operation()) ; 36023 | 36024 | if (op_addsub) 36025 | { 36026 | switch (operation) 36027 | { 36028 | case details::e_add : cobnode->set_c(cobnode->c() + c); break; 36029 | case details::e_sub : cobnode->set_c(cobnode->c() - c); break; 36030 | default : return error_node(); 36031 | } 36032 | 36033 | result = cobnode; 36034 | } 36035 | else if (details::e_mul == cobnode->operation()) 36036 | { 36037 | switch (operation) 36038 | { 36039 | case details::e_mul : cobnode->set_c(cobnode->c() * c); break; 36040 | case details::e_div : cobnode->set_c(cobnode->c() / c); break; 36041 | default : return error_node(); 36042 | } 36043 | 36044 | result = cobnode; 36045 | } 36046 | else if (details::e_div == cobnode->operation()) 36047 | { 36048 | if (details::e_mul == operation) 36049 | { 36050 | cobnode->set_c(cobnode->c() * c); 36051 | result = cobnode; 36052 | } 36053 | else if (details::e_div == operation) 36054 | { 36055 | result = expr_gen.node_allocator_-> 36056 | template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > > 36057 | (cobnode->c() / c, cobnode->move_branch(0)); 36058 | 36059 | details::free_node(*expr_gen.node_allocator_, branch[0]); 36060 | } 36061 | } 36062 | 36063 | if (result) 36064 | { 36065 | details::free_node(*expr_gen.node_allocator_,branch[1]); 36066 | } 36067 | } 36068 | 36069 | // c o (cob) --> cob 36070 | else if (details::is_cob_node(branch[1])) 36071 | { 36072 | details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]); 36073 | 36074 | const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); 36075 | 36076 | if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation)) 36077 | { 36078 | details::free_node(*expr_gen.node_allocator_, branch[0]); 36079 | details::free_node(*expr_gen.node_allocator_, branch[1]); 36080 | 36081 | return expr_gen(T(0)); 36082 | } 36083 | else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation)) 36084 | { 36085 | details::free_node(*expr_gen.node_allocator_, branch[0]); 36086 | details::free_node(*expr_gen.node_allocator_, branch[1]); 36087 | 36088 | return expr_gen(T(0)); 36089 | } 36090 | else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation)) 36091 | { 36092 | details::free_node(*expr_gen.node_allocator_, branch[0]); 36093 | 36094 | return branch[1]; 36095 | } 36096 | else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation)) 36097 | { 36098 | details::free_node(*expr_gen.node_allocator_, branch[0]); 36099 | 36100 | return branch[1]; 36101 | } 36102 | 36103 | if (details::e_add == cobnode->operation()) 36104 | { 36105 | if (details::e_add == operation) 36106 | { 36107 | cobnode->set_c(c + cobnode->c()); 36108 | result = cobnode; 36109 | } 36110 | else if (details::e_sub == operation) 36111 | { 36112 | result = expr_gen.node_allocator_-> 36113 | template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > > 36114 | (c - cobnode->c(), cobnode->move_branch(0)); 36115 | 36116 | details::free_node(*expr_gen.node_allocator_,branch[1]); 36117 | } 36118 | } 36119 | else if (details::e_sub == cobnode->operation()) 36120 | { 36121 | if (details::e_add == operation) 36122 | { 36123 | cobnode->set_c(c + cobnode->c()); 36124 | result = cobnode; 36125 | } 36126 | else if (details::e_sub == operation) 36127 | { 36128 | result = expr_gen.node_allocator_-> 36129 | template allocate_tt<typename details::cob_node<Type,details::add_op<Type> > > 36130 | (c - cobnode->c(), cobnode->move_branch(0)); 36131 | 36132 | details::free_node(*expr_gen.node_allocator_,branch[1]); 36133 | } 36134 | } 36135 | else if (details::e_mul == cobnode->operation()) 36136 | { 36137 | if (details::e_mul == operation) 36138 | { 36139 | cobnode->set_c(c * cobnode->c()); 36140 | result = cobnode; 36141 | } 36142 | else if (details::e_div == operation) 36143 | { 36144 | result = expr_gen.node_allocator_-> 36145 | template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > > 36146 | (c / cobnode->c(), cobnode->move_branch(0)); 36147 | 36148 | details::free_node(*expr_gen.node_allocator_,branch[1]); 36149 | } 36150 | } 36151 | else if (details::e_div == cobnode->operation()) 36152 | { 36153 | if (details::e_mul == operation) 36154 | { 36155 | cobnode->set_c(c * cobnode->c()); 36156 | result = cobnode; 36157 | } 36158 | else if (details::e_div == operation) 36159 | { 36160 | result = expr_gen.node_allocator_-> 36161 | template allocate_tt<typename details::cob_node<Type,details::mul_op<Type> > > 36162 | (c / cobnode->c(), cobnode->move_branch(0)); 36163 | 36164 | details::free_node(*expr_gen.node_allocator_,branch[1]); 36165 | } 36166 | } 36167 | 36168 | if (result) 36169 | { 36170 | details::free_node(*expr_gen.node_allocator_,branch[0]); 36171 | } 36172 | } 36173 | 36174 | return result; 36175 | } 36176 | }; 36177 | 36178 | struct synthesize_coboc_expression 36179 | { 36180 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36181 | const details::operator_type& operation, 36182 | expression_node_ptr (&branch)[2]) 36183 | { 36184 | expression_node_ptr result = error_node(); 36185 | 36186 | // (boc) o c --> boc 36187 | if (details::is_boc_node(branch[0])) 36188 | { 36189 | details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]); 36190 | 36191 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 36192 | 36193 | if (details::e_add == bocnode->operation()) 36194 | { 36195 | switch (operation) 36196 | { 36197 | case details::e_add : bocnode->set_c(bocnode->c() + c); break; 36198 | case details::e_sub : bocnode->set_c(bocnode->c() - c); break; 36199 | default : return error_node(); 36200 | } 36201 | 36202 | result = bocnode; 36203 | } 36204 | else if (details::e_mul == bocnode->operation()) 36205 | { 36206 | switch (operation) 36207 | { 36208 | case details::e_mul : bocnode->set_c(bocnode->c() * c); break; 36209 | case details::e_div : bocnode->set_c(bocnode->c() / c); break; 36210 | default : return error_node(); 36211 | } 36212 | 36213 | result = bocnode; 36214 | } 36215 | else if (details::e_sub == bocnode->operation()) 36216 | { 36217 | if (details::e_add == operation) 36218 | { 36219 | result = expr_gen.node_allocator_-> 36220 | template allocate_tt<typename details::boc_node<Type,details::add_op<Type> > > 36221 | (bocnode->move_branch(0), c - bocnode->c()); 36222 | 36223 | details::free_node(*expr_gen.node_allocator_,branch[0]); 36224 | } 36225 | else if (details::e_sub == operation) 36226 | { 36227 | bocnode->set_c(bocnode->c() + c); 36228 | result = bocnode; 36229 | } 36230 | } 36231 | else if (details::e_div == bocnode->operation()) 36232 | { 36233 | switch (operation) 36234 | { 36235 | case details::e_div : bocnode->set_c(bocnode->c() * c); break; 36236 | case details::e_mul : bocnode->set_c(bocnode->c() / c); break; 36237 | default : return error_node(); 36238 | } 36239 | 36240 | result = bocnode; 36241 | } 36242 | 36243 | if (result) 36244 | { 36245 | details::free_node(*expr_gen.node_allocator_, branch[1]); 36246 | } 36247 | } 36248 | 36249 | // c o (boc) --> boc 36250 | else if (details::is_boc_node(branch[1])) 36251 | { 36252 | details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[1]); 36253 | 36254 | const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); 36255 | 36256 | if (details::e_add == bocnode->operation()) 36257 | { 36258 | if (details::e_add == operation) 36259 | { 36260 | bocnode->set_c(c + bocnode->c()); 36261 | result = bocnode; 36262 | } 36263 | else if (details::e_sub == operation) 36264 | { 36265 | result = expr_gen.node_allocator_-> 36266 | template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > > 36267 | (c - bocnode->c(), bocnode->move_branch(0)); 36268 | 36269 | details::free_node(*expr_gen.node_allocator_,branch[1]); 36270 | } 36271 | } 36272 | else if (details::e_sub == bocnode->operation()) 36273 | { 36274 | if (details::e_add == operation) 36275 | { 36276 | result = expr_gen.node_allocator_-> 36277 | template allocate_tt<typename details::boc_node<Type,details::add_op<Type> > > 36278 | (bocnode->move_branch(0), c - bocnode->c()); 36279 | 36280 | details::free_node(*expr_gen.node_allocator_,branch[1]); 36281 | } 36282 | else if (details::e_sub == operation) 36283 | { 36284 | result = expr_gen.node_allocator_-> 36285 | template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > > 36286 | (c + bocnode->c(), bocnode->move_branch(0)); 36287 | 36288 | details::free_node(*expr_gen.node_allocator_,branch[1]); 36289 | } 36290 | } 36291 | else if (details::e_mul == bocnode->operation()) 36292 | { 36293 | if (details::e_mul == operation) 36294 | { 36295 | bocnode->set_c(c * bocnode->c()); 36296 | result = bocnode; 36297 | } 36298 | else if (details::e_div == operation) 36299 | { 36300 | result = expr_gen.node_allocator_-> 36301 | template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > > 36302 | (c / bocnode->c(), bocnode->move_branch(0)); 36303 | 36304 | details::free_node(*expr_gen.node_allocator_,branch[1]); 36305 | } 36306 | } 36307 | else if (details::e_div == bocnode->operation()) 36308 | { 36309 | if (details::e_mul == operation) 36310 | { 36311 | bocnode->set_c(bocnode->c() / c); 36312 | result = bocnode; 36313 | } 36314 | else if (details::e_div == operation) 36315 | { 36316 | result = expr_gen.node_allocator_-> 36317 | template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > > 36318 | (c * bocnode->c(), bocnode->move_branch(0)); 36319 | 36320 | details::free_node(*expr_gen.node_allocator_,branch[1]); 36321 | } 36322 | } 36323 | 36324 | if (result) 36325 | { 36326 | details::free_node(*expr_gen.node_allocator_,branch[0]); 36327 | } 36328 | } 36329 | 36330 | return result; 36331 | } 36332 | }; 36333 | 36334 | #ifndef exprtk_disable_enhanced_features 36335 | inline bool synthesize_expression(const details::operator_type& operation, 36336 | expression_node_ptr (&branch)[2], 36337 | expression_node_ptr& result) 36338 | { 36339 | result = error_node(); 36340 | 36341 | if (!operation_optimisable(operation)) 36342 | return false; 36343 | 36344 | const std::string node_id = branch_to_id(branch); 36345 | 36346 | const typename synthesize_map_t::iterator itr = synthesize_map_.find(node_id); 36347 | 36348 | if (synthesize_map_.end() != itr) 36349 | { 36350 | result = itr->second((*this), operation, branch); 36351 | 36352 | return true; 36353 | } 36354 | else 36355 | return false; 36356 | } 36357 | 36358 | struct synthesize_vov_expression 36359 | { 36360 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36361 | const details::operator_type& operation, 36362 | expression_node_ptr (&branch)[2]) 36363 | { 36364 | const Type& v1 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 36365 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 36366 | 36367 | switch (operation) 36368 | { 36369 | #define case_stmt(op0, op1) \ 36370 | case op0 : return expr_gen.node_allocator_-> \ 36371 | template allocate_rr<typename details::vov_node<Type,op1<Type> > > \ 36372 | (v1, v2); \ 36373 | 36374 | basic_opr_switch_statements 36375 | extended_opr_switch_statements 36376 | #undef case_stmt 36377 | default : return error_node(); 36378 | } 36379 | } 36380 | }; 36381 | 36382 | struct synthesize_cov_expression 36383 | { 36384 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36385 | const details::operator_type& operation, 36386 | expression_node_ptr (&branch)[2]) 36387 | { 36388 | const Type c = static_cast<details::literal_node<Type>*> (branch[0])->value(); 36389 | const Type& v = static_cast<details::variable_node<Type>*>(branch[1])->ref (); 36390 | 36391 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 36392 | 36393 | if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation)) 36394 | return expr_gen(T(0)); 36395 | else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation)) 36396 | return expr_gen(T(0)); 36397 | else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation)) 36398 | return static_cast<details::variable_node<Type>*>(branch[1]); 36399 | else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation)) 36400 | return static_cast<details::variable_node<Type>*>(branch[1]); 36401 | 36402 | switch (operation) 36403 | { 36404 | #define case_stmt(op0, op1) \ 36405 | case op0 : return expr_gen.node_allocator_-> \ 36406 | template allocate_cr<typename details::cov_node<Type,op1<Type> > > \ 36407 | (c, v); \ 36408 | 36409 | basic_opr_switch_statements 36410 | extended_opr_switch_statements 36411 | #undef case_stmt 36412 | default : return error_node(); 36413 | } 36414 | } 36415 | }; 36416 | 36417 | struct synthesize_voc_expression 36418 | { 36419 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36420 | const details::operator_type& operation, 36421 | expression_node_ptr (&branch)[2]) 36422 | { 36423 | const Type& v = static_cast<details::variable_node<Type>*>(branch[0])->ref (); 36424 | const Type c = static_cast<details::literal_node<Type>*> (branch[1])->value(); 36425 | 36426 | details::free_node(*(expr_gen.node_allocator_), branch[1]); 36427 | 36428 | if (expr_gen.cardinal_pow_optimisable(operation,c)) 36429 | { 36430 | if (std::equal_to<T>()(T(1),c)) 36431 | return branch[0]; 36432 | else 36433 | return expr_gen.cardinal_pow_optimisation(v,c); 36434 | } 36435 | else if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation)) 36436 | return expr_gen(T(0)); 36437 | else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation)) 36438 | return expr_gen(std::numeric_limits<T>::quiet_NaN()); 36439 | else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation)) 36440 | return static_cast<details::variable_node<Type>*>(branch[0]); 36441 | else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation)) 36442 | return static_cast<details::variable_node<Type>*>(branch[0]); 36443 | else if (std::equal_to<T>()(T(1),c) && (details::e_div == operation)) 36444 | return static_cast<details::variable_node<Type>*>(branch[0]); 36445 | 36446 | switch (operation) 36447 | { 36448 | #define case_stmt(op0, op1) \ 36449 | case op0 : return expr_gen.node_allocator_-> \ 36450 | template allocate_rc<typename details::voc_node<Type,op1<Type> > > \ 36451 | (v, c); \ 36452 | 36453 | basic_opr_switch_statements 36454 | extended_opr_switch_statements 36455 | #undef case_stmt 36456 | default : return error_node(); 36457 | } 36458 | } 36459 | }; 36460 | 36461 | struct synthesize_sf3ext_expression 36462 | { 36463 | template <typename T0, typename T1, typename T2> 36464 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36465 | const details::operator_type& sf3opr, 36466 | T0 t0, T1 t1, T2 t2) 36467 | { 36468 | switch (sf3opr) 36469 | { 36470 | #define case_stmt(op) \ 36471 | case details::e_sf##op : return details::T0oT1oT2_sf3ext<T,T0,T1,T2,details::sf##op##_op<Type> >:: \ 36472 | allocate(*(expr_gen.node_allocator_), t0, t1, t2); \ 36473 | 36474 | case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03) 36475 | case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07) 36476 | case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11) 36477 | case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15) 36478 | case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19) 36479 | case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23) 36480 | case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27) 36481 | case_stmt(28) case_stmt(29) case_stmt(30) 36482 | #undef case_stmt 36483 | default : return error_node(); 36484 | } 36485 | } 36486 | 36487 | template <typename T0, typename T1, typename T2> 36488 | static inline bool compile(expression_generator<Type>& expr_gen, const std::string& id, 36489 | T0 t0, T1 t1, T2 t2, 36490 | expression_node_ptr& result) 36491 | { 36492 | details::operator_type sf3opr; 36493 | 36494 | if (!expr_gen.sf3_optimisable(id,sf3opr)) 36495 | return false; 36496 | else 36497 | result = synthesize_sf3ext_expression::template process<T0, T1, T2> 36498 | (expr_gen, sf3opr, t0, t1, t2); 36499 | 36500 | return true; 36501 | } 36502 | }; 36503 | 36504 | struct synthesize_sf4ext_expression 36505 | { 36506 | template <typename T0, typename T1, typename T2, typename T3> 36507 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36508 | const details::operator_type& sf4opr, 36509 | T0 t0, T1 t1, T2 t2, T3 t3) 36510 | { 36511 | switch (sf4opr) 36512 | { 36513 | #define case_stmt0(op) \ 36514 | case details::e_sf##op : return details::T0oT1oT2oT3_sf4ext<Type,T0,T1,T2,T3,details::sf##op##_op<Type> >:: \ 36515 | allocate(*(expr_gen.node_allocator_), t0, t1, t2, t3); \ 36516 | 36517 | #define case_stmt1(op) \ 36518 | case details::e_sf4ext##op : return details::T0oT1oT2oT3_sf4ext<Type,T0,T1,T2,T3,details::sfext##op##_op<Type> >:: \ 36519 | allocate(*(expr_gen.node_allocator_), t0, t1, t2, t3); \ 36520 | 36521 | case_stmt0(48) case_stmt0(49) case_stmt0(50) case_stmt0(51) 36522 | case_stmt0(52) case_stmt0(53) case_stmt0(54) case_stmt0(55) 36523 | case_stmt0(56) case_stmt0(57) case_stmt0(58) case_stmt0(59) 36524 | case_stmt0(60) case_stmt0(61) case_stmt0(62) case_stmt0(63) 36525 | case_stmt0(64) case_stmt0(65) case_stmt0(66) case_stmt0(67) 36526 | case_stmt0(68) case_stmt0(69) case_stmt0(70) case_stmt0(71) 36527 | case_stmt0(72) case_stmt0(73) case_stmt0(74) case_stmt0(75) 36528 | case_stmt0(76) case_stmt0(77) case_stmt0(78) case_stmt0(79) 36529 | case_stmt0(80) case_stmt0(81) case_stmt0(82) case_stmt0(83) 36530 | 36531 | case_stmt1(00) case_stmt1(01) case_stmt1(02) case_stmt1(03) 36532 | case_stmt1(04) case_stmt1(05) case_stmt1(06) case_stmt1(07) 36533 | case_stmt1(08) case_stmt1(09) case_stmt1(10) case_stmt1(11) 36534 | case_stmt1(12) case_stmt1(13) case_stmt1(14) case_stmt1(15) 36535 | case_stmt1(16) case_stmt1(17) case_stmt1(18) case_stmt1(19) 36536 | case_stmt1(20) case_stmt1(21) case_stmt1(22) case_stmt1(23) 36537 | case_stmt1(24) case_stmt1(25) case_stmt1(26) case_stmt1(27) 36538 | case_stmt1(28) case_stmt1(29) case_stmt1(30) case_stmt1(31) 36539 | case_stmt1(32) case_stmt1(33) case_stmt1(34) case_stmt1(35) 36540 | case_stmt1(36) case_stmt1(37) case_stmt1(38) case_stmt1(39) 36541 | case_stmt1(40) case_stmt1(41) case_stmt1(42) case_stmt1(43) 36542 | case_stmt1(44) case_stmt1(45) case_stmt1(46) case_stmt1(47) 36543 | case_stmt1(48) case_stmt1(49) case_stmt1(50) case_stmt1(51) 36544 | case_stmt1(52) case_stmt1(53) case_stmt1(54) case_stmt1(55) 36545 | case_stmt1(56) case_stmt1(57) case_stmt1(58) case_stmt1(59) 36546 | case_stmt1(60) case_stmt1(61) 36547 | 36548 | #undef case_stmt0 36549 | #undef case_stmt1 36550 | default : return error_node(); 36551 | } 36552 | } 36553 | 36554 | template <typename T0, typename T1, typename T2, typename T3> 36555 | static inline bool compile(expression_generator<Type>& expr_gen, const std::string& id, 36556 | T0 t0, T1 t1, T2 t2, T3 t3, 36557 | expression_node_ptr& result) 36558 | { 36559 | details::operator_type sf4opr; 36560 | 36561 | if (!expr_gen.sf4_optimisable(id,sf4opr)) 36562 | return false; 36563 | else 36564 | result = synthesize_sf4ext_expression::template process<T0, T1, T2, T3> 36565 | (expr_gen, sf4opr, t0, t1, t2, t3); 36566 | 36567 | return true; 36568 | } 36569 | 36570 | // T o (sf3ext) 36571 | template <typename ExternalType> 36572 | static inline bool compile_right(expression_generator<Type>& expr_gen, 36573 | ExternalType t, 36574 | const details::operator_type& operation, 36575 | expression_node_ptr& sf3node, 36576 | expression_node_ptr& result) 36577 | { 36578 | if (!details::is_sf3ext_node(sf3node)) 36579 | return false; 36580 | 36581 | typedef details::T0oT1oT2_base_node<Type>* sf3ext_base_ptr; 36582 | 36583 | sf3ext_base_ptr n = static_cast<sf3ext_base_ptr>(sf3node); 36584 | const std::string id = "t" + expr_gen.to_str(operation) + "(" + n->type_id() + ")" 36585 | 36586 | switch (n->type()) 36587 | { 36588 | case details::expression_node<Type>::e_covoc : return compile_right_impl 36589 | <typename covoc_t::sf3_type_node,ExternalType, ctype, vtype, ctype> 36590 | (expr_gen, id, t, sf3node, result); 36591 | 36592 | case details::expression_node<Type>::e_covov : return compile_right_impl 36593 | <typename covov_t::sf3_type_node,ExternalType, ctype, vtype, vtype> 36594 | (expr_gen, id, t, sf3node, result); 36595 | 36596 | case details::expression_node<Type>::e_vocov : return compile_right_impl 36597 | <typename vocov_t::sf3_type_node,ExternalType, vtype, ctype, vtype> 36598 | (expr_gen, id, t, sf3node, result); 36599 | 36600 | case details::expression_node<Type>::e_vovoc : return compile_right_impl 36601 | <typename vovoc_t::sf3_type_node,ExternalType, vtype, vtype, ctype> 36602 | (expr_gen, id, t, sf3node, result); 36603 | 36604 | case details::expression_node<Type>::e_vovov : return compile_right_impl 36605 | <typename vovov_t::sf3_type_node,ExternalType, vtype, vtype, vtype> 36606 | (expr_gen, id, t, sf3node, result); 36607 | 36608 | default : return false; 36609 | } 36610 | } 36611 | 36612 | // (sf3ext) o T 36613 | template <typename ExternalType> 36614 | static inline bool compile_left(expression_generator<Type>& expr_gen, 36615 | ExternalType t, 36616 | const details::operator_type& operation, 36617 | expression_node_ptr& sf3node, 36618 | expression_node_ptr& result) 36619 | { 36620 | if (!details::is_sf3ext_node(sf3node)) 36621 | return false; 36622 | 36623 | typedef details::T0oT1oT2_base_node<Type>* sf3ext_base_ptr; 36624 | 36625 | sf3ext_base_ptr n = static_cast<sf3ext_base_ptr>(sf3node); 36626 | 36627 | const std::string id = "(" + n->type_id() + ")" + expr_gen.to_str(operation) + "t" 36628 | 36629 | switch (n->type()) 36630 | { 36631 | case details::expression_node<Type>::e_covoc : return compile_left_impl 36632 | <typename covoc_t::sf3_type_node,ExternalType, ctype, vtype, ctype> 36633 | (expr_gen, id, t, sf3node, result); 36634 | 36635 | case details::expression_node<Type>::e_covov : return compile_left_impl 36636 | <typename covov_t::sf3_type_node,ExternalType, ctype, vtype, vtype> 36637 | (expr_gen, id, t, sf3node, result); 36638 | 36639 | case details::expression_node<Type>::e_vocov : return compile_left_impl 36640 | <typename vocov_t::sf3_type_node,ExternalType, vtype, ctype, vtype> 36641 | (expr_gen, id, t, sf3node, result); 36642 | 36643 | case details::expression_node<Type>::e_vovoc : return compile_left_impl 36644 | <typename vovoc_t::sf3_type_node,ExternalType, vtype, vtype, ctype> 36645 | (expr_gen, id, t, sf3node, result); 36646 | 36647 | case details::expression_node<Type>::e_vovov : return compile_left_impl 36648 | <typename vovov_t::sf3_type_node,ExternalType, vtype, vtype, vtype> 36649 | (expr_gen, id, t, sf3node, result); 36650 | 36651 | default : return false; 36652 | } 36653 | } 36654 | 36655 | template <typename SF3TypeNode, typename ExternalType, typename T0, typename T1, typename T2> 36656 | static inline bool compile_right_impl(expression_generator<Type>& expr_gen, 36657 | const std::string& id, 36658 | ExternalType t, 36659 | expression_node_ptr& node, 36660 | expression_node_ptr& result) 36661 | { 36662 | SF3TypeNode* n = dynamic_cast<SF3TypeNode*>(node); 36663 | 36664 | if (n) 36665 | { 36666 | T0 t0 = n->t0(); 36667 | T1 t1 = n->t1(); 36668 | T2 t2 = n->t2(); 36669 | 36670 | return synthesize_sf4ext_expression::template compile<ExternalType, T0, T1, T2> 36671 | (expr_gen, id, t, t0, t1, t2, result); 36672 | } 36673 | else 36674 | return false; 36675 | } 36676 | 36677 | template <typename SF3TypeNode, typename ExternalType, typename T0, typename T1, typename T2> 36678 | static inline bool compile_left_impl(expression_generator<Type>& expr_gen, 36679 | const std::string& id, 36680 | ExternalType t, 36681 | expression_node_ptr& node, 36682 | expression_node_ptr& result) 36683 | { 36684 | SF3TypeNode* n = dynamic_cast<SF3TypeNode*>(node); 36685 | 36686 | if (n) 36687 | { 36688 | T0 t0 = n->t0(); 36689 | T1 t1 = n->t1(); 36690 | T2 t2 = n->t2(); 36691 | 36692 | return synthesize_sf4ext_expression::template compile<T0, T1, T2, ExternalType> 36693 | (expr_gen, id, t0, t1, t2, t, result); 36694 | } 36695 | else 36696 | return false; 36697 | } 36698 | }; 36699 | 36700 | struct synthesize_vovov_expression0 36701 | { 36702 | typedef typename vovov_t::type0 node_type; 36703 | typedef typename vovov_t::sf3_type sf3_type; 36704 | 36705 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36706 | const details::operator_type& operation, 36707 | expression_node_ptr (&branch)[2]) 36708 | { 36709 | // (v0 o0 v1) o1 (v2) 36710 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]); 36711 | const Type& v0 = vov->v0(); 36712 | const Type& v1 = vov->v1(); 36713 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 36714 | const details::operator_type o0 = vov->operation(); 36715 | const details::operator_type o1 = operation; 36716 | 36717 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 36718 | 36719 | expression_node_ptr result = error_node(); 36720 | 36721 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36722 | { 36723 | // (v0 / v1) / v2 --> (vovov) v0 / (v1 * v2) 36724 | if ((details::e_div == o0) && (details::e_div == o1)) 36725 | { 36726 | const bool synthesis_result = 36727 | synthesize_sf3ext_expression:: 36728 | template compile<vtype, vtype, vtype>(expr_gen, "t/(t*t)", v0, v1, v2, result); 36729 | 36730 | exprtk_debug(("(v0 / v1) / v2 --> (vovov) v0 / (v1 * v2)\n")); 36731 | 36732 | return (synthesis_result) ? result : error_node(); 36733 | } 36734 | } 36735 | 36736 | const bool synthesis_result = 36737 | synthesize_sf3ext_expression::template compile<vtype, vtype, vtype> 36738 | (expr_gen, id(expr_gen, o0, o1), v0, v1, v2, result); 36739 | 36740 | if (synthesis_result) 36741 | return result; 36742 | 36743 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36744 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36745 | 36746 | if (!expr_gen.valid_operator(o0,f0)) 36747 | return error_node(); 36748 | else if (!expr_gen.valid_operator(o1,f1)) 36749 | return error_node(); 36750 | else 36751 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, f0, f1); 36752 | } 36753 | 36754 | static inline std::string id(expression_generator<Type>& expr_gen, 36755 | const details::operator_type o0, 36756 | const details::operator_type o1) 36757 | { 36758 | return details::build_string() 36759 | << "(t" << expr_gen.to_str(o0) 36760 | << "t)" << expr_gen.to_str(o1) 36761 | << "t" 36762 | } 36763 | }; 36764 | 36765 | struct synthesize_vovov_expression1 36766 | { 36767 | typedef typename vovov_t::type1 node_type; 36768 | typedef typename vovov_t::sf3_type sf3_type; 36769 | 36770 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36771 | const details::operator_type& operation, 36772 | expression_node_ptr (&branch)[2]) 36773 | { 36774 | // (v0) o0 (v1 o1 v2) 36775 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]); 36776 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 36777 | const Type& v1 = vov->v0(); 36778 | const Type& v2 = vov->v1(); 36779 | const details::operator_type o0 = operation; 36780 | const details::operator_type o1 = vov->operation(); 36781 | 36782 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 36783 | 36784 | expression_node_ptr result = error_node(); 36785 | 36786 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36787 | { 36788 | // v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1 36789 | if ((details::e_div == o0) && (details::e_div == o1)) 36790 | { 36791 | const bool synthesis_result = 36792 | synthesize_sf3ext_expression:: 36793 | template compile<vtype, vtype, vtype>(expr_gen, "(t*t)/t", v0, v2, v1, result); 36794 | 36795 | exprtk_debug(("v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1\n")); 36796 | 36797 | return (synthesis_result) ? result : error_node(); 36798 | } 36799 | } 36800 | 36801 | const bool synthesis_result = 36802 | synthesize_sf3ext_expression::template compile<vtype, vtype, vtype> 36803 | (expr_gen, id(expr_gen, o0, o1), v0, v1, v2, result); 36804 | 36805 | if (synthesis_result) 36806 | return result; 36807 | 36808 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36809 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36810 | 36811 | if (!expr_gen.valid_operator(o0,f0)) 36812 | return error_node(); 36813 | else if (!expr_gen.valid_operator(o1,f1)) 36814 | return error_node(); 36815 | else 36816 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, f0, f1); 36817 | } 36818 | 36819 | static inline std::string id(expression_generator<Type>& expr_gen, 36820 | const details::operator_type o0, 36821 | const details::operator_type o1) 36822 | { 36823 | return details::build_string() 36824 | << "t" << expr_gen.to_str(o0) 36825 | << "(t" << expr_gen.to_str(o1) 36826 | << "t)" 36827 | } 36828 | }; 36829 | 36830 | struct synthesize_vovoc_expression0 36831 | { 36832 | typedef typename vovoc_t::type0 node_type; 36833 | typedef typename vovoc_t::sf3_type sf3_type; 36834 | 36835 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36836 | const details::operator_type& operation, 36837 | expression_node_ptr (&branch)[2]) 36838 | { 36839 | // (v0 o0 v1) o1 (c) 36840 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]); 36841 | const Type& v0 = vov->v0(); 36842 | const Type& v1 = vov->v1(); 36843 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 36844 | const details::operator_type o0 = vov->operation(); 36845 | const details::operator_type o1 = operation; 36846 | 36847 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 36848 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 36849 | 36850 | expression_node_ptr result = error_node(); 36851 | 36852 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36853 | { 36854 | // (v0 / v1) / c --> (vovoc) v0 / (v1 * c) 36855 | if ((details::e_div == o0) && (details::e_div == o1)) 36856 | { 36857 | const bool synthesis_result = 36858 | synthesize_sf3ext_expression:: 36859 | template compile<vtype, vtype, ctype>(expr_gen, "t/(t*t)", v0, v1, c, result); 36860 | 36861 | exprtk_debug(("(v0 / v1) / c --> (vovoc) v0 / (v1 * c)\n")); 36862 | 36863 | return (synthesis_result) ? result : error_node(); 36864 | } 36865 | } 36866 | 36867 | const bool synthesis_result = 36868 | synthesize_sf3ext_expression::template compile<vtype, vtype, ctype> 36869 | (expr_gen, id(expr_gen, o0, o1), v0, v1, c, result); 36870 | 36871 | if (synthesis_result) 36872 | return result; 36873 | 36874 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36875 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36876 | 36877 | if (!expr_gen.valid_operator(o0,f0)) 36878 | return error_node(); 36879 | else if (!expr_gen.valid_operator(o1,f1)) 36880 | return error_node(); 36881 | else 36882 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, f0, f1); 36883 | } 36884 | 36885 | static inline std::string id(expression_generator<Type>& expr_gen, 36886 | const details::operator_type o0, 36887 | const details::operator_type o1) 36888 | { 36889 | return details::build_string() 36890 | << "(t" << expr_gen.to_str(o0) 36891 | << "t)" << expr_gen.to_str(o1) 36892 | << "t" 36893 | } 36894 | }; 36895 | 36896 | struct synthesize_vovoc_expression1 36897 | { 36898 | typedef typename vovoc_t::type1 node_type; 36899 | typedef typename vovoc_t::sf3_type sf3_type; 36900 | 36901 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36902 | const details::operator_type& operation, 36903 | expression_node_ptr (&branch)[2]) 36904 | { 36905 | // (v0) o0 (v1 o1 c) 36906 | const details::voc_base_node<Type>* voc = static_cast<const details::voc_base_node<Type>*>(branch[1]); 36907 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 36908 | const Type& v1 = voc->v(); 36909 | const Type c = voc->c(); 36910 | const details::operator_type o0 = operation; 36911 | const details::operator_type o1 = voc->operation(); 36912 | 36913 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 36914 | 36915 | expression_node_ptr result = error_node(); 36916 | 36917 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36918 | { 36919 | // v0 / (v1 / c) --> (vocov) (v0 * c) / v1 36920 | if ((details::e_div == o0) && (details::e_div == o1)) 36921 | { 36922 | const bool synthesis_result = 36923 | synthesize_sf3ext_expression:: 36924 | template compile<vtype, ctype, vtype>(expr_gen, "(t*t)/t", v0, c, v1, result); 36925 | 36926 | exprtk_debug(("v0 / (v1 / c) --> (vocov) (v0 * c) / v1\n")); 36927 | 36928 | return (synthesis_result) ? result : error_node(); 36929 | } 36930 | } 36931 | 36932 | const bool synthesis_result = 36933 | synthesize_sf3ext_expression::template compile<vtype, vtype, ctype> 36934 | (expr_gen, id(expr_gen, o0, o1), v0, v1, c, result); 36935 | 36936 | if (synthesis_result) 36937 | return result; 36938 | 36939 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36940 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36941 | 36942 | if (!expr_gen.valid_operator(o0,f0)) 36943 | return error_node(); 36944 | else if (!expr_gen.valid_operator(o1,f1)) 36945 | return error_node(); 36946 | else 36947 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, f0, f1); 36948 | } 36949 | 36950 | static inline std::string id(expression_generator<Type>& expr_gen, 36951 | const details::operator_type o0, 36952 | const details::operator_type o1) 36953 | { 36954 | return details::build_string() 36955 | << "t" << expr_gen.to_str(o0) 36956 | << "(t" << expr_gen.to_str(o1) 36957 | << "t)" 36958 | } 36959 | }; 36960 | 36961 | struct synthesize_vocov_expression0 36962 | { 36963 | typedef typename vocov_t::type0 node_type; 36964 | typedef typename vocov_t::sf3_type sf3_type; 36965 | 36966 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36967 | const details::operator_type& operation, 36968 | expression_node_ptr (&branch)[2]) 36969 | { 36970 | // (v0 o0 c) o1 (v1) 36971 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]); 36972 | const Type& v0 = voc->v(); 36973 | const Type c = voc->c(); 36974 | const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 36975 | const details::operator_type o0 = voc->operation(); 36976 | const details::operator_type o1 = operation; 36977 | 36978 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 36979 | 36980 | expression_node_ptr result = error_node(); 36981 | 36982 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36983 | { 36984 | // (v0 / c) / v1 --> (vovoc) v0 / (v1 * c) 36985 | if ((details::e_div == o0) && (details::e_div == o1)) 36986 | { 36987 | const bool synthesis_result = 36988 | synthesize_sf3ext_expression:: 36989 | template compile<vtype, vtype, ctype>(expr_gen, "t/(t*t)", v0, v1, c, result); 36990 | 36991 | exprtk_debug(("(v0 / c) / v1 --> (vovoc) v0 / (v1 * c)\n")); 36992 | 36993 | return (synthesis_result) ? result : error_node(); 36994 | } 36995 | } 36996 | 36997 | const bool synthesis_result = 36998 | synthesize_sf3ext_expression::template compile<vtype, ctype, vtype> 36999 | (expr_gen, id(expr_gen, o0, o1), v0, c, v1, result); 37000 | 37001 | if (synthesis_result) 37002 | return result; 37003 | 37004 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37005 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37006 | 37007 | if (!expr_gen.valid_operator(o0,f0)) 37008 | return error_node(); 37009 | else if (!expr_gen.valid_operator(o1,f1)) 37010 | return error_node(); 37011 | else 37012 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, f0, f1); 37013 | } 37014 | 37015 | static inline std::string id(expression_generator<Type>& expr_gen, 37016 | const details::operator_type o0, 37017 | const details::operator_type o1) 37018 | { 37019 | return details::build_string() 37020 | << "(t" << expr_gen.to_str(o0) 37021 | << "t)" << expr_gen.to_str(o1) 37022 | << "t" 37023 | } 37024 | }; 37025 | 37026 | struct synthesize_vocov_expression1 37027 | { 37028 | typedef typename vocov_t::type1 node_type; 37029 | typedef typename vocov_t::sf3_type sf3_type; 37030 | 37031 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37032 | const details::operator_type& operation, 37033 | expression_node_ptr (&branch)[2]) 37034 | { 37035 | // (v0) o0 (c o1 v1) 37036 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]); 37037 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 37038 | const Type c = cov->c(); 37039 | const Type& v1 = cov->v(); 37040 | const details::operator_type o0 = operation; 37041 | const details::operator_type o1 = cov->operation(); 37042 | 37043 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37044 | 37045 | expression_node_ptr result = error_node(); 37046 | 37047 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37048 | { 37049 | // v0 / (c / v1) --> (vovoc) (v0 * v1) / c 37050 | if ((details::e_div == o0) && (details::e_div == o1)) 37051 | { 37052 | const bool synthesis_result = 37053 | synthesize_sf3ext_expression:: 37054 | template compile<vtype, vtype, ctype>(expr_gen, "(t*t)/t", v0, v1, c, result); 37055 | 37056 | exprtk_debug(("v0 / (c / v1) --> (vovoc) (v0 * v1) / c\n")); 37057 | 37058 | return (synthesis_result) ? result : error_node(); 37059 | } 37060 | } 37061 | 37062 | const bool synthesis_result = 37063 | synthesize_sf3ext_expression::template compile<vtype, ctype, vtype> 37064 | (expr_gen, id(expr_gen, o0, o1), v0, c, v1, result); 37065 | 37066 | if (synthesis_result) 37067 | return result; 37068 | 37069 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37070 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37071 | 37072 | if (!expr_gen.valid_operator(o0,f0)) 37073 | return error_node(); 37074 | else if (!expr_gen.valid_operator(o1,f1)) 37075 | return error_node(); 37076 | else 37077 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, f0, f1); 37078 | } 37079 | 37080 | static inline std::string id(expression_generator<Type>& expr_gen, 37081 | const details::operator_type o0, 37082 | const details::operator_type o1) 37083 | { 37084 | return details::build_string() 37085 | << "t" << expr_gen.to_str(o0) 37086 | << "(t" << expr_gen.to_str(o1) 37087 | << "t)" 37088 | } 37089 | }; 37090 | 37091 | struct synthesize_covov_expression0 37092 | { 37093 | typedef typename covov_t::type0 node_type; 37094 | typedef typename covov_t::sf3_type sf3_type; 37095 | 37096 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37097 | const details::operator_type& operation, 37098 | expression_node_ptr (&branch)[2]) 37099 | { 37100 | // (c o0 v0) o1 (v1) 37101 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]); 37102 | const Type c = cov->c(); 37103 | const Type& v0 = cov->v(); 37104 | const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 37105 | const details::operator_type o0 = cov->operation(); 37106 | const details::operator_type o1 = operation; 37107 | 37108 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37109 | 37110 | expression_node_ptr result = error_node(); 37111 | 37112 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37113 | { 37114 | // (c / v0) / v1 --> (covov) c / (v0 * v1) 37115 | if ((details::e_div == o0) && (details::e_div == o1)) 37116 | { 37117 | const bool synthesis_result = 37118 | synthesize_sf3ext_expression:: 37119 | template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", c, v0, v1, result); 37120 | 37121 | exprtk_debug(("(c / v0) / v1 --> (covov) c / (v0 * v1)\n")); 37122 | 37123 | return (synthesis_result) ? result : error_node(); 37124 | } 37125 | } 37126 | 37127 | const bool synthesis_result = 37128 | synthesize_sf3ext_expression::template compile<ctype, vtype, vtype> 37129 | (expr_gen, id(expr_gen, o0, o1), c, v0, v1, result); 37130 | 37131 | if (synthesis_result) 37132 | return result; 37133 | 37134 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37135 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37136 | 37137 | if (!expr_gen.valid_operator(o0,f0)) 37138 | return error_node(); 37139 | else if (!expr_gen.valid_operator(o1,f1)) 37140 | return error_node(); 37141 | else 37142 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, f0, f1); 37143 | } 37144 | 37145 | static inline std::string id(expression_generator<Type>& expr_gen, 37146 | const details::operator_type o0, 37147 | const details::operator_type o1) 37148 | { 37149 | return details::build_string() 37150 | << "(t" << expr_gen.to_str(o0) 37151 | << "t)" << expr_gen.to_str(o1) 37152 | << "t" 37153 | } 37154 | }; 37155 | 37156 | struct synthesize_covov_expression1 37157 | { 37158 | typedef typename covov_t::type1 node_type; 37159 | typedef typename covov_t::sf3_type sf3_type; 37160 | 37161 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37162 | const details::operator_type& operation, 37163 | expression_node_ptr (&branch)[2]) 37164 | { 37165 | // (c) o0 (v0 o1 v1) 37166 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]); 37167 | const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); 37168 | const Type& v0 = vov->v0(); 37169 | const Type& v1 = vov->v1(); 37170 | const details::operator_type o0 = operation; 37171 | const details::operator_type o1 = vov->operation(); 37172 | 37173 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37174 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37175 | 37176 | expression_node_ptr result = error_node(); 37177 | 37178 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37179 | { 37180 | // c / (v0 / v1) --> (covov) (c * v1) / v0 37181 | if ((details::e_div == o0) && (details::e_div == o1)) 37182 | { 37183 | const bool synthesis_result = 37184 | synthesize_sf3ext_expression:: 37185 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", c, v1, v0, result); 37186 | 37187 | exprtk_debug(("c / (v0 / v1) --> (covov) (c * v1) / v0\n")); 37188 | 37189 | return (synthesis_result) ? result : error_node(); 37190 | } 37191 | } 37192 | 37193 | const bool synthesis_result = 37194 | synthesize_sf3ext_expression::template compile<ctype, vtype, vtype> 37195 | (expr_gen, id(expr_gen, o0, o1), c, v0, v1, result); 37196 | 37197 | if (synthesis_result) 37198 | return result; 37199 | 37200 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37201 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37202 | 37203 | if (!expr_gen.valid_operator(o0,f0)) 37204 | return error_node(); 37205 | else if (!expr_gen.valid_operator(o1,f1)) 37206 | return error_node(); 37207 | else 37208 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, f0, f1); 37209 | } 37210 | 37211 | static inline std::string id(expression_generator<Type>& expr_gen, 37212 | const details::operator_type o0, 37213 | const details::operator_type o1) 37214 | { 37215 | return details::build_string() 37216 | << "t" << expr_gen.to_str(o0) 37217 | << "(t" << expr_gen.to_str(o1) 37218 | << "t)" 37219 | } 37220 | }; 37221 | 37222 | struct synthesize_covoc_expression0 37223 | { 37224 | typedef typename covoc_t::type0 node_type; 37225 | typedef typename covoc_t::sf3_type sf3_type; 37226 | 37227 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37228 | const details::operator_type& operation, 37229 | expression_node_ptr (&branch)[2]) 37230 | { 37231 | // (c0 o0 v) o1 (c1) 37232 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]); 37233 | const Type c0 = cov->c(); 37234 | const Type& v = cov->v(); 37235 | const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); 37236 | const details::operator_type o0 = cov->operation(); 37237 | const details::operator_type o1 = operation; 37238 | 37239 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37240 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37241 | 37242 | expression_node_ptr result = error_node(); 37243 | 37244 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37245 | { 37246 | // (c0 + v) + c1 --> (cov) (c0 + c1) + v 37247 | if ((details::e_add == o0) && (details::e_add == o1)) 37248 | { 37249 | exprtk_debug(("(c0 + v) + c1 --> (cov) (c0 + c1) + v\n")); 37250 | 37251 | return expr_gen.node_allocator_-> 37252 | template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v); 37253 | } 37254 | // (c0 + v) - c1 --> (cov) (c0 - c1) + v 37255 | else if ((details::e_add == o0) && (details::e_sub == o1)) 37256 | { 37257 | exprtk_debug(("(c0 + v) - c1 --> (cov) (c0 - c1) + v\n")); 37258 | 37259 | return expr_gen.node_allocator_-> 37260 | template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v); 37261 | } 37262 | // (c0 - v) + c1 --> (cov) (c0 + c1) - v 37263 | else if ((details::e_sub == o0) && (details::e_add == o1)) 37264 | { 37265 | exprtk_debug(("(c0 - v) + c1 --> (cov) (c0 + c1) - v\n")); 37266 | 37267 | return expr_gen.node_allocator_-> 37268 | template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v); 37269 | } 37270 | // (c0 - v) - c1 --> (cov) (c0 - c1) - v 37271 | else if ((details::e_sub == o0) && (details::e_sub == o1)) 37272 | { 37273 | exprtk_debug(("(c0 - v) - c1 --> (cov) (c0 - c1) - v\n")); 37274 | 37275 | return expr_gen.node_allocator_-> 37276 | template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v); 37277 | } 37278 | // (c0 * v) * c1 --> (cov) (c0 * c1) * v 37279 | else if ((details::e_mul == o0) && (details::e_mul == o1)) 37280 | { 37281 | exprtk_debug(("(c0 * v) * c1 --> (cov) (c0 * c1) * v\n")); 37282 | 37283 | return expr_gen.node_allocator_-> 37284 | template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v); 37285 | } 37286 | // (c0 * v) / c1 --> (cov) (c0 / c1) * v 37287 | else if ((details::e_mul == o0) && (details::e_div == o1)) 37288 | { 37289 | exprtk_debug(("(c0 * v) / c1 --> (cov) (c0 / c1) * v\n")); 37290 | 37291 | return expr_gen.node_allocator_-> 37292 | template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v); 37293 | } 37294 | // (c0 / v) * c1 --> (cov) (c0 * c1) / v 37295 | else if ((details::e_div == o0) && (details::e_mul == o1)) 37296 | { 37297 | exprtk_debug(("(c0 / v) * c1 --> (cov) (c0 * c1) / v\n")); 37298 | 37299 | return expr_gen.node_allocator_-> 37300 | template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v); 37301 | } 37302 | // (c0 / v) / c1 --> (cov) (c0 / c1) / v 37303 | else if ((details::e_div == o0) && (details::e_div == o1)) 37304 | { 37305 | exprtk_debug(("(c0 / v) / c1 --> (cov) (c0 / c1) / v\n")); 37306 | 37307 | return expr_gen.node_allocator_-> 37308 | template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v); 37309 | } 37310 | } 37311 | 37312 | const bool synthesis_result = 37313 | synthesize_sf3ext_expression::template compile<ctype, vtype, ctype> 37314 | (expr_gen, id(expr_gen, o0, o1), c0, v, c1, result); 37315 | 37316 | if (synthesis_result) 37317 | return result; 37318 | 37319 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37320 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37321 | 37322 | if (!expr_gen.valid_operator(o0,f0)) 37323 | return error_node(); 37324 | else if (!expr_gen.valid_operator(o1,f1)) 37325 | return error_node(); 37326 | else 37327 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v, c1, f0, f1); 37328 | } 37329 | 37330 | static inline std::string id(expression_generator<Type>& expr_gen, 37331 | const details::operator_type o0, 37332 | const details::operator_type o1) 37333 | { 37334 | return details::build_string() 37335 | << "(t" << expr_gen.to_str(o0) 37336 | << "t)" << expr_gen.to_str(o1) 37337 | << "t" 37338 | } 37339 | }; 37340 | 37341 | struct synthesize_covoc_expression1 37342 | { 37343 | typedef typename covoc_t::type1 node_type; 37344 | typedef typename covoc_t::sf3_type sf3_type; 37345 | 37346 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37347 | const details::operator_type& operation, 37348 | expression_node_ptr (&branch)[2]) 37349 | { 37350 | // (c0) o0 (v o1 c1) 37351 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]); 37352 | const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); 37353 | const Type& v = voc->v(); 37354 | const Type c1 = voc->c(); 37355 | const details::operator_type o0 = operation; 37356 | const details::operator_type o1 = voc->operation(); 37357 | 37358 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37359 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37360 | 37361 | expression_node_ptr result = error_node(); 37362 | 37363 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37364 | { 37365 | // (c0) + (v + c1) --> (cov) (c0 + c1) + v 37366 | if ((details::e_add == o0) && (details::e_add == o1)) 37367 | { 37368 | exprtk_debug(("(c0) + (v + c1) --> (cov) (c0 + c1) + v\n")); 37369 | 37370 | return expr_gen.node_allocator_-> 37371 | template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v); 37372 | } 37373 | // (c0) + (v - c1) --> (cov) (c0 - c1) + v 37374 | else if ((details::e_add == o0) && (details::e_sub == o1)) 37375 | { 37376 | exprtk_debug(("(c0) + (v - c1) --> (cov) (c0 - c1) + v\n")); 37377 | 37378 | return expr_gen.node_allocator_-> 37379 | template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v); 37380 | } 37381 | // (c0) - (v + c1) --> (cov) (c0 - c1) - v 37382 | else if ((details::e_sub == o0) && (details::e_add == o1)) 37383 | { 37384 | exprtk_debug(("(c0) - (v + c1) --> (cov) (c0 - c1) - v\n")); 37385 | 37386 | return expr_gen.node_allocator_-> 37387 | template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v); 37388 | } 37389 | // (c0) - (v - c1) --> (cov) (c0 + c1) - v 37390 | else if ((details::e_sub == o0) && (details::e_sub == o1)) 37391 | { 37392 | exprtk_debug(("(c0) - (v - c1) --> (cov) (c0 + c1) - v\n")); 37393 | 37394 | return expr_gen.node_allocator_-> 37395 | template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v); 37396 | } 37397 | // (c0) * (v * c1) --> (voc) v * (c0 * c1) 37398 | else if ((details::e_mul == o0) && (details::e_mul == o1)) 37399 | { 37400 | exprtk_debug(("(c0) * (v * c1) --> (voc) v * (c0 * c1)\n")); 37401 | 37402 | return expr_gen.node_allocator_-> 37403 | template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v); 37404 | } 37405 | // (c0) * (v / c1) --> (cov) (c0 / c1) * v 37406 | else if ((details::e_mul == o0) && (details::e_div == o1)) 37407 | { 37408 | exprtk_debug(("(c0) * (v / c1) --> (cov) (c0 / c1) * v\n")); 37409 | 37410 | return expr_gen.node_allocator_-> 37411 | template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v); 37412 | } 37413 | // (c0) / (v * c1) --> (cov) (c0 / c1) / v 37414 | else if ((details::e_div == o0) && (details::e_mul == o1)) 37415 | { 37416 | exprtk_debug(("(c0) / (v * c1) --> (cov) (c0 / c1) / v\n")); 37417 | 37418 | return expr_gen.node_allocator_-> 37419 | template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v); 37420 | } 37421 | // (c0) / (v / c1) --> (cov) (c0 * c1) / v 37422 | else if ((details::e_div == o0) && (details::e_div == o1)) 37423 | { 37424 | exprtk_debug(("(c0) / (v / c1) --> (cov) (c0 * c1) / v\n")); 37425 | 37426 | return expr_gen.node_allocator_-> 37427 | template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v); 37428 | } 37429 | } 37430 | 37431 | const bool synthesis_result = 37432 | synthesize_sf3ext_expression::template compile<ctype, vtype, ctype> 37433 | (expr_gen, id(expr_gen, o0, o1), c0, v, c1, result); 37434 | 37435 | if (synthesis_result) 37436 | return result; 37437 | 37438 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37439 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37440 | 37441 | if (!expr_gen.valid_operator(o0,f0)) 37442 | return error_node(); 37443 | else if (!expr_gen.valid_operator(o1,f1)) 37444 | return error_node(); 37445 | else 37446 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v, c1, f0, f1); 37447 | } 37448 | 37449 | static inline std::string id(expression_generator<Type>& expr_gen, 37450 | const details::operator_type o0, 37451 | const details::operator_type o1) 37452 | { 37453 | return details::build_string() 37454 | << "t" << expr_gen.to_str(o0) 37455 | << "(t" << expr_gen.to_str(o1) 37456 | << "t)" 37457 | } 37458 | }; 37459 | 37460 | struct synthesize_cocov_expression0 37461 | { 37462 | typedef typename cocov_t::type0 node_type; 37463 | static inline expression_node_ptr process(expression_generator<Type>&, 37464 | const details::operator_type&, 37465 | expression_node_ptr (&)[2]) 37466 | { 37467 | // (c0 o0 c1) o1 (v) - Not possible. 37468 | return error_node(); 37469 | } 37470 | }; 37471 | 37472 | struct synthesize_cocov_expression1 37473 | { 37474 | typedef typename cocov_t::type1 node_type; 37475 | typedef typename cocov_t::sf3_type sf3_type; 37476 | 37477 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37478 | const details::operator_type& operation, 37479 | expression_node_ptr (&branch)[2]) 37480 | { 37481 | // (c0) o0 (c1 o1 v) 37482 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]); 37483 | const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); 37484 | const Type c1 = cov->c(); 37485 | const Type& v = cov->v(); 37486 | const details::operator_type o0 = operation; 37487 | const details::operator_type o1 = cov->operation(); 37488 | 37489 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37490 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37491 | 37492 | expression_node_ptr result = error_node(); 37493 | 37494 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37495 | { 37496 | // (c0) + (c1 + v) --> (cov) (c0 + c1) + v 37497 | if ((details::e_add == o0) && (details::e_add == o1)) 37498 | { 37499 | exprtk_debug(("(c0) + (c1 + v) --> (cov) (c0 + c1) + v\n")); 37500 | 37501 | return expr_gen.node_allocator_-> 37502 | template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v); 37503 | } 37504 | // (c0) + (c1 - v) --> (cov) (c0 + c1) - v 37505 | else if ((details::e_add == o0) && (details::e_sub == o1)) 37506 | { 37507 | exprtk_debug(("(c0) + (c1 - v) --> (cov) (c0 + c1) - v\n")); 37508 | 37509 | return expr_gen.node_allocator_-> 37510 | template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v); 37511 | } 37512 | // (c0) - (c1 + v) --> (cov) (c0 - c1) - v 37513 | else if ((details::e_sub == o0) && (details::e_add == o1)) 37514 | { 37515 | exprtk_debug(("(c0) - (c1 + v) --> (cov) (c0 - c1) - v\n")); 37516 | 37517 | return expr_gen.node_allocator_-> 37518 | template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v); 37519 | } 37520 | // (c0) - (c1 - v) --> (cov) (c0 - c1) + v 37521 | else if ((details::e_sub == o0) && (details::e_sub == o1)) 37522 | { 37523 | exprtk_debug(("(c0) - (c1 - v) --> (cov) (c0 - c1) + v\n")); 37524 | 37525 | return expr_gen.node_allocator_-> 37526 | template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v); 37527 | } 37528 | // (c0) * (c1 * v) --> (cov) (c0 * c1) * v 37529 | else if ((details::e_mul == o0) && (details::e_mul == o1)) 37530 | { 37531 | exprtk_debug(("(c0) * (c1 * v) --> (cov) (c0 * c1) * v\n")); 37532 | 37533 | return expr_gen.node_allocator_-> 37534 | template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v); 37535 | } 37536 | // (c0) * (c1 / v) --> (cov) (c0 * c1) / v 37537 | else if ((details::e_mul == o0) && (details::e_div == o1)) 37538 | { 37539 | exprtk_debug(("(c0) * (c1 / v) --> (cov) (c0 * c1) / v\n")); 37540 | 37541 | return expr_gen.node_allocator_-> 37542 | template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v); 37543 | } 37544 | // (c0) / (c1 * v) --> (cov) (c0 / c1) / v 37545 | else if ((details::e_div == o0) && (details::e_mul == o1)) 37546 | { 37547 | exprtk_debug(("(c0) / (c1 * v) --> (cov) (c0 / c1) / v\n")); 37548 | 37549 | return expr_gen.node_allocator_-> 37550 | template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v); 37551 | } 37552 | // (c0) / (c1 / v) --> (cov) (c0 / c1) * v 37553 | else if ((details::e_div == o0) && (details::e_div == o1)) 37554 | { 37555 | exprtk_debug(("(c0) / (c1 / v) --> (cov) (c0 / c1) * v\n")); 37556 | 37557 | return expr_gen.node_allocator_-> 37558 | template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v); 37559 | } 37560 | } 37561 | 37562 | const bool synthesis_result = 37563 | synthesize_sf3ext_expression::template compile<ctype, ctype, vtype> 37564 | (expr_gen, id(expr_gen, o0, o1), c0, c1, v, result); 37565 | 37566 | if (synthesis_result) 37567 | return result; 37568 | 37569 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37570 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37571 | 37572 | if (!expr_gen.valid_operator(o0,f0)) 37573 | return error_node(); 37574 | else if (!expr_gen.valid_operator(o1,f1)) 37575 | return error_node(); 37576 | else 37577 | return node_type::allocate(*(expr_gen.node_allocator_), c0, c1, v, f0, f1); 37578 | } 37579 | 37580 | static inline std::string id(expression_generator<Type>& expr_gen, 37581 | const details::operator_type o0, 37582 | const details::operator_type o1) 37583 | { 37584 | return details::build_string() 37585 | << "t" << expr_gen.to_str(o0) 37586 | << "(t" << expr_gen.to_str(o1) 37587 | << "t)" 37588 | } 37589 | }; 37590 | 37591 | struct synthesize_vococ_expression0 37592 | { 37593 | typedef typename vococ_t::type0 node_type; 37594 | typedef typename vococ_t::sf3_type sf3_type; 37595 | 37596 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37597 | const details::operator_type& operation, 37598 | expression_node_ptr (&branch)[2]) 37599 | { 37600 | // (v o0 c0) o1 (c1) 37601 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]); 37602 | const Type& v = voc->v(); 37603 | const Type& c0 = voc->c(); 37604 | const Type& c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); 37605 | const details::operator_type o0 = voc->operation(); 37606 | const details::operator_type o1 = operation; 37607 | 37608 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37609 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37610 | 37611 | expression_node_ptr result = error_node(); 37612 | 37613 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37614 | { 37615 | // (v + c0) + c1 --> (voc) v + (c0 + c1) 37616 | if ((details::e_add == o0) && (details::e_add == o1)) 37617 | { 37618 | exprtk_debug(("(v + c0) + c1 --> (voc) v + (c0 + c1)\n")); 37619 | 37620 | return expr_gen.node_allocator_-> 37621 | template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c0 + c1); 37622 | } 37623 | // (v + c0) - c1 --> (voc) v + (c0 - c1) 37624 | else if ((details::e_add == o0) && (details::e_sub == o1)) 37625 | { 37626 | exprtk_debug(("(v + c0) - c1 --> (voc) v + (c0 - c1)\n")); 37627 | 37628 | return expr_gen.node_allocator_-> 37629 | template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c0 - c1); 37630 | } 37631 | // (v - c0) + c1 --> (voc) v - (c0 + c1) 37632 | else if ((details::e_sub == o0) && (details::e_add == o1)) 37633 | { 37634 | exprtk_debug(("(v - c0) + c1 --> (voc) v - (c0 + c1)\n")); 37635 | 37636 | return expr_gen.node_allocator_-> 37637 | template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c1 - c0); 37638 | } 37639 | // (v - c0) - c1 --> (voc) v - (c0 + c1) 37640 | else if ((details::e_sub == o0) && (details::e_sub == o1)) 37641 | { 37642 | exprtk_debug(("(v - c0) - c1 --> (voc) v - (c0 + c1)\n")); 37643 | 37644 | return expr_gen.node_allocator_-> 37645 | template allocate_rc<typename details::voc_node<Type,details::sub_op<Type> > >(v, c0 + c1); 37646 | } 37647 | // (v * c0) * c1 --> (voc) v * (c0 * c1) 37648 | else if ((details::e_mul == o0) && (details::e_mul == o1)) 37649 | { 37650 | exprtk_debug(("(v * c0) * c1 --> (voc) v * (c0 * c1)\n")); 37651 | 37652 | return expr_gen.node_allocator_-> 37653 | template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c0 * c1); 37654 | } 37655 | // (v * c0) / c1 --> (voc) v * (c0 / c1) 37656 | else if ((details::e_mul == o0) && (details::e_div == o1)) 37657 | { 37658 | exprtk_debug(("(v * c0) / c1 --> (voc) v * (c0 / c1)\n")); 37659 | 37660 | return expr_gen.node_allocator_-> 37661 | template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c0 / c1); 37662 | } 37663 | // (v / c0) * c1 --> (voc) v * (c1 / c0) 37664 | else if ((details::e_div == o0) && (details::e_mul == o1)) 37665 | { 37666 | exprtk_debug(("(v / c0) * c1 --> (voc) v * (c1 / c0)\n")); 37667 | 37668 | return expr_gen.node_allocator_-> 37669 | template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c1 / c0); 37670 | } 37671 | // (v / c0) / c1 --> (voc) v / (c0 * c1) 37672 | else if ((details::e_div == o0) && (details::e_div == o1)) 37673 | { 37674 | exprtk_debug(("(v / c0) / c1 --> (voc) v / (c0 * c1)\n")); 37675 | 37676 | return expr_gen.node_allocator_-> 37677 | template allocate_rc<typename details::voc_node<Type,details::div_op<Type> > >(v, c0 * c1); 37678 | } 37679 | // (v ^ c0) ^ c1 --> (voc) v ^ (c0 * c1) 37680 | else if ((details::e_pow == o0) && (details::e_pow == o1)) 37681 | { 37682 | exprtk_debug(("(v ^ c0) ^ c1 --> (voc) v ^ (c0 * c1)\n")); 37683 | 37684 | return expr_gen.node_allocator_-> 37685 | template allocate_rc<typename details::voc_node<Type,details::pow_op<Type> > >(v, c0 * c1); 37686 | } 37687 | } 37688 | 37689 | const bool synthesis_result = 37690 | synthesize_sf3ext_expression::template compile<vtype, ctype, ctype> 37691 | (expr_gen, id(expr_gen, o0, o1), v, c0, c1, result); 37692 | 37693 | if (synthesis_result) 37694 | return result; 37695 | 37696 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37697 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37698 | 37699 | if (!expr_gen.valid_operator(o0,f0)) 37700 | return error_node(); 37701 | else if (!expr_gen.valid_operator(o1,f1)) 37702 | return error_node(); 37703 | else 37704 | return node_type::allocate(*(expr_gen.node_allocator_), v, c0, c1, f0, f1); 37705 | } 37706 | 37707 | static inline std::string id(expression_generator<Type>& expr_gen, 37708 | const details::operator_type o0, 37709 | const details::operator_type o1) 37710 | { 37711 | return details::build_string() 37712 | << "(t" << expr_gen.to_str(o0) 37713 | << "t)" << expr_gen.to_str(o1) 37714 | << "t" 37715 | } 37716 | }; 37717 | 37718 | struct synthesize_vococ_expression1 37719 | { 37720 | typedef typename vococ_t::type0 node_type; 37721 | 37722 | static inline expression_node_ptr process(expression_generator<Type>&, 37723 | const details::operator_type&, 37724 | expression_node_ptr (&)[2]) 37725 | { 37726 | // (v) o0 (c0 o1 c1) - Not possible. 37727 | exprtk_debug(("(v) o0 (c0 o1 c1) - Not possible.\n")); 37728 | return error_node(); 37729 | } 37730 | }; 37731 | 37732 | struct synthesize_vovovov_expression0 37733 | { 37734 | typedef typename vovovov_t::type0 node_type; 37735 | typedef typename vovovov_t::sf4_type sf4_type; 37736 | typedef typename node_type::T0 T0; 37737 | typedef typename node_type::T1 T1; 37738 | typedef typename node_type::T2 T2; 37739 | typedef typename node_type::T3 T3; 37740 | 37741 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37742 | const details::operator_type& operation, 37743 | expression_node_ptr (&branch)[2]) 37744 | { 37745 | // (v0 o0 v1) o1 (v2 o2 v3) 37746 | const details::vov_base_node<Type>* vov0 = static_cast<details::vov_base_node<Type>*>(branch[0]); 37747 | const details::vov_base_node<Type>* vov1 = static_cast<details::vov_base_node<Type>*>(branch[1]); 37748 | const Type& v0 = vov0->v0(); 37749 | const Type& v1 = vov0->v1(); 37750 | const Type& v2 = vov1->v0(); 37751 | const Type& v3 = vov1->v1(); 37752 | const details::operator_type o0 = vov0->operation(); 37753 | const details::operator_type o1 = operation; 37754 | const details::operator_type o2 = vov1->operation(); 37755 | 37756 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37757 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37758 | 37759 | expression_node_ptr result = error_node(); 37760 | 37761 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37762 | { 37763 | // (v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3) 37764 | if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 37765 | { 37766 | const bool synthesis_result = 37767 | synthesize_sf4ext_expression:: 37768 | template compile<vtype, vtype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, v3, result); 37769 | 37770 | exprtk_debug(("(v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3)\n")); 37771 | 37772 | return (synthesis_result) ? result : error_node(); 37773 | } 37774 | // (v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2) 37775 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 37776 | { 37777 | const bool synthesis_result = 37778 | synthesize_sf4ext_expression:: 37779 | template compile<vtype, vtype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", v0, v3, v1, v2, result); 37780 | 37781 | exprtk_debug(("(v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2)\n")); 37782 | 37783 | return (synthesis_result) ? result : error_node(); 37784 | } 37785 | // (v0 + v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2) 37786 | else if ((details::e_add == o0) && (details::e_div == o1) && (details::e_div == o2)) 37787 | { 37788 | const bool synthesis_result = 37789 | synthesize_sf4ext_expression:: 37790 | template compile<vtype, vtype, vtype, vtype>(expr_gen, "(t+t)*(t/t)", v0, v1, v3, v2, result); 37791 | 37792 | exprtk_debug(("(v0 + v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2)\n")); 37793 | 37794 | return (synthesis_result) ? result : error_node(); 37795 | } 37796 | // (v0 - v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2) 37797 | else if ((details::e_sub == o0) && (details::e_div == o1) && (details::e_div == o2)) 37798 | { 37799 | const bool synthesis_result = 37800 | synthesize_sf4ext_expression:: 37801 | template compile<vtype, vtype, vtype, vtype>(expr_gen, "(t-t)*(t/t)", v0, v1, v3, v2, result); 37802 | 37803 | exprtk_debug(("(v0 - v1) / (v2 / v3) --> (vovovov) (v0 - v1) * (v3 / v2)\n")); 37804 | 37805 | return (synthesis_result) ? result : error_node(); 37806 | } 37807 | // (v0 * v1) / (v2 / v3) --> (vovovov) ((v0 * v1) * v3) / v2 37808 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) 37809 | { 37810 | const bool synthesis_result = 37811 | synthesize_sf4ext_expression:: 37812 | template compile<vtype, vtype, vtype, vtype>(expr_gen, "((t*t)*t)/t", v0, v1, v3, v2, result); 37813 | 37814 | exprtk_debug(("(v0 * v1) / (v2 / v3) --> (vovovov) ((v0 * v1) * v3) / v2\n")); 37815 | 37816 | return (synthesis_result) ? result : error_node(); 37817 | } 37818 | } 37819 | 37820 | const bool synthesis_result = 37821 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 37822 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result); 37823 | 37824 | if (synthesis_result) 37825 | return result; 37826 | 37827 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37828 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37829 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 37830 | 37831 | if (!expr_gen.valid_operator(o0,f0)) 37832 | return error_node(); 37833 | else if (!expr_gen.valid_operator(o1,f1)) 37834 | return error_node(); 37835 | else if (!expr_gen.valid_operator(o2,f2)) 37836 | return error_node(); 37837 | else 37838 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2); 37839 | } 37840 | 37841 | static inline std::string id(expression_generator<Type>& expr_gen, 37842 | const details::operator_type o0, 37843 | const details::operator_type o1, 37844 | const details::operator_type o2) 37845 | { 37846 | return details::build_string() 37847 | << "(t" << expr_gen.to_str(o0) 37848 | << "t)" << expr_gen.to_str(o1) 37849 | << "(t" << expr_gen.to_str(o2) 37850 | << "t)" 37851 | } 37852 | }; 37853 | 37854 | struct synthesize_vovovoc_expression0 37855 | { 37856 | typedef typename vovovoc_t::type0 node_type; 37857 | typedef typename vovovoc_t::sf4_type sf4_type; 37858 | typedef typename node_type::T0 T0; 37859 | typedef typename node_type::T1 T1; 37860 | typedef typename node_type::T2 T2; 37861 | typedef typename node_type::T3 T3; 37862 | 37863 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37864 | const details::operator_type& operation, 37865 | expression_node_ptr (&branch)[2]) 37866 | { 37867 | // (v0 o0 v1) o1 (v2 o2 c) 37868 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]); 37869 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]); 37870 | const Type& v0 = vov->v0(); 37871 | const Type& v1 = vov->v1(); 37872 | const Type& v2 = voc->v (); 37873 | const Type c = voc->c (); 37874 | const details::operator_type o0 = vov->operation(); 37875 | const details::operator_type o1 = operation; 37876 | const details::operator_type o2 = voc->operation(); 37877 | 37878 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37879 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37880 | 37881 | expression_node_ptr result = error_node(); 37882 | 37883 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37884 | { 37885 | // (v0 / v1) * (v2 / c) --> (vovovoc) (v0 * v2) / (v1 * c) 37886 | if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 37887 | { 37888 | const bool synthesis_result = 37889 | synthesize_sf4ext_expression:: 37890 | template compile<vtype, vtype, vtype, ctype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, c, result); 37891 | 37892 | exprtk_debug(("(v0 / v1) * (v2 / c) --> (vovovoc) (v0 * v2) / (v1 * c)\n")); 37893 | 37894 | return (synthesis_result) ? result : error_node(); 37895 | } 37896 | // (v0 / v1) / (v2 / c) --> (vocovov) (v0 * c) / (v1 * v2) 37897 | if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 37898 | { 37899 | const bool synthesis_result = 37900 | synthesize_sf4ext_expression:: 37901 | template compile<vtype, ctype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", v0, c, v1, v2, result); 37902 | 37903 | exprtk_debug(("(v0 / v1) / (v2 / c) --> (vocovov) (v0 * c) / (v1 * v2)\n")); 37904 | 37905 | return (synthesis_result) ? result : error_node(); 37906 | } 37907 | } 37908 | 37909 | const bool synthesis_result = 37910 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 37911 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result); 37912 | 37913 | if (synthesis_result) 37914 | return result; 37915 | 37916 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37917 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37918 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 37919 | 37920 | if (!expr_gen.valid_operator(o0,f0)) 37921 | return error_node(); 37922 | else if (!expr_gen.valid_operator(o1,f1)) 37923 | return error_node(); 37924 | else if (!expr_gen.valid_operator(o2,f2)) 37925 | return error_node(); 37926 | else 37927 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2); 37928 | } 37929 | 37930 | static inline std::string id(expression_generator<Type>& expr_gen, 37931 | const details::operator_type o0, 37932 | const details::operator_type o1, 37933 | const details::operator_type o2) 37934 | { 37935 | return details::build_string() 37936 | << "(t" << expr_gen.to_str(o0) 37937 | << "t)" << expr_gen.to_str(o1) 37938 | << "(t" << expr_gen.to_str(o2) 37939 | << "t)" 37940 | } 37941 | }; 37942 | 37943 | struct synthesize_vovocov_expression0 37944 | { 37945 | typedef typename vovocov_t::type0 node_type; 37946 | typedef typename vovocov_t::sf4_type sf4_type; 37947 | typedef typename node_type::T0 T0; 37948 | typedef typename node_type::T1 T1; 37949 | typedef typename node_type::T2 T2; 37950 | typedef typename node_type::T3 T3; 37951 | 37952 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37953 | const details::operator_type& operation, 37954 | expression_node_ptr (&branch)[2]) 37955 | { 37956 | // (v0 o0 v1) o1 (c o2 v2) 37957 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]); 37958 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]); 37959 | const Type& v0 = vov->v0(); 37960 | const Type& v1 = vov->v1(); 37961 | const Type& v2 = cov->v (); 37962 | const Type c = cov->c (); 37963 | const details::operator_type o0 = vov->operation(); 37964 | const details::operator_type o1 = operation; 37965 | const details::operator_type o2 = cov->operation(); 37966 | 37967 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37968 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37969 | 37970 | expression_node_ptr result = error_node(); 37971 | 37972 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37973 | { 37974 | // (v0 / v1) * (c / v2) --> (vocovov) (v0 * c) / (v1 * v2) 37975 | if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 37976 | { 37977 | const bool synthesis_result = 37978 | synthesize_sf4ext_expression:: 37979 | template compile<vtype, ctype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", v0, c, v1, v2, result); 37980 | 37981 | exprtk_debug(("(v0 / v1) * (c / v2) --> (vocovov) (v0 * c) / (v1 * v2)\n")); 37982 | 37983 | return (synthesis_result) ? result : error_node(); 37984 | } 37985 | // (v0 / v1) / (c / v2) --> (vovovoc) (v0 * v2) / (v1 * c) 37986 | if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 37987 | { 37988 | const bool synthesis_result = 37989 | synthesize_sf4ext_expression:: 37990 | template compile<vtype, vtype, vtype, ctype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, c, result); 37991 | 37992 | exprtk_debug(("(v0 / v1) / (c / v2) --> (vovovoc) (v0 * v2) / (v1 * c)\n")); 37993 | 37994 | return (synthesis_result) ? result : error_node(); 37995 | } 37996 | } 37997 | 37998 | const bool synthesis_result = 37999 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38000 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result); 38001 | 38002 | if (synthesis_result) 38003 | return result; 38004 | 38005 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38006 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 38007 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 38008 | 38009 | if (!expr_gen.valid_operator(o0,f0)) 38010 | return error_node(); 38011 | else if (!expr_gen.valid_operator(o1,f1)) 38012 | return error_node(); 38013 | else if (!expr_gen.valid_operator(o2,f2)) 38014 | return error_node(); 38015 | else 38016 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2); 38017 | } 38018 | 38019 | static inline std::string id(expression_generator<Type>& expr_gen, 38020 | const details::operator_type o0, 38021 | const details::operator_type o1, 38022 | const details::operator_type o2) 38023 | { 38024 | return details::build_string() 38025 | << "(t" << expr_gen.to_str(o0) 38026 | << "t)" << expr_gen.to_str(o1) 38027 | << "(t" << expr_gen.to_str(o2) 38028 | << "t)" 38029 | } 38030 | }; 38031 | 38032 | struct synthesize_vocovov_expression0 38033 | { 38034 | typedef typename vocovov_t::type0 node_type; 38035 | typedef typename vocovov_t::sf4_type sf4_type; 38036 | typedef typename node_type::T0 T0; 38037 | typedef typename node_type::T1 T1; 38038 | typedef typename node_type::T2 T2; 38039 | typedef typename node_type::T3 T3; 38040 | 38041 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38042 | const details::operator_type& operation, 38043 | expression_node_ptr (&branch)[2]) 38044 | { 38045 | // (v0 o0 c) o1 (v1 o2 v2) 38046 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]); 38047 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]); 38048 | const Type c = voc->c (); 38049 | const Type& v0 = voc->v (); 38050 | const Type& v1 = vov->v0(); 38051 | const Type& v2 = vov->v1(); 38052 | const details::operator_type o0 = voc->operation(); 38053 | const details::operator_type o1 = operation; 38054 | const details::operator_type o2 = vov->operation(); 38055 | 38056 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 38057 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38058 | 38059 | expression_node_ptr result = error_node(); 38060 | 38061 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 38062 | { 38063 | // (v0 / c) * (v1 / v2) --> (vovocov) (v0 * v1) / (c * v2) 38064 | if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 38065 | { 38066 | const bool synthesis_result = 38067 | synthesize_sf4ext_expression:: 38068 | template compile<vtype, vtype, ctype, vtype>(expr_gen, "(t*t)/(t*t)", v0, v1, c, v2, result); 38069 | 38070 | exprtk_debug(("(v0 / c) * (v1 / v2) --> (vovocov) (v0 * v1) / (c * v2)\n")); 38071 | 38072 | return (synthesis_result) ? result : error_node(); 38073 | } 38074 | // (v0 / c) / (v1 / v2) --> (vovocov) (v0 * v2) / (c * v1) 38075 | if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 38076 | { 38077 | const bool synthesis_result = 38078 | synthesize_sf4ext_expression:: 38079 | template compile<vtype, vtype, ctype, vtype>(expr_gen, "(t*t)/(t*t)", v0, v2, c, v1, result); 38080 | 38081 | exprtk_debug(("(v0 / c) / (v1 / v2) --> (vovocov) (v0 * v2) / (c * v1)\n")); 38082 | 38083 | return (synthesis_result) ? result : error_node(); 38084 | } 38085 | } 38086 | 38087 | const bool synthesis_result = 38088 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38089 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result); 38090 | 38091 | if (synthesis_result) 38092 | return result; 38093 | 38094 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38095 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 38096 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 38097 | 38098 | if (!expr_gen.valid_operator(o0,f0)) 38099 | return error_node(); 38100 | else if (!expr_gen.valid_operator(o1,f1)) 38101 | return error_node(); 38102 | else if (!expr_gen.valid_operator(o2,f2)) 38103 | return error_node(); 38104 | else 38105 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2); 38106 | } 38107 | 38108 | static inline std::string id(expression_generator<Type>& expr_gen, 38109 | const details::operator_type o0, 38110 | const details::operator_type o1, 38111 | const details::operator_type o2) 38112 | { 38113 | return details::build_string() 38114 | << "(t" << expr_gen.to_str(o0) 38115 | << "t)" << expr_gen.to_str(o1) 38116 | << "(t" << expr_gen.to_str(o2) 38117 | << "t)" 38118 | } 38119 | }; 38120 | 38121 | struct synthesize_covovov_expression0 38122 | { 38123 | typedef typename covovov_t::type0 node_type; 38124 | typedef typename covovov_t::sf4_type sf4_type; 38125 | typedef typename node_type::T0 T0; 38126 | typedef typename node_type::T1 T1; 38127 | typedef typename node_type::T2 T2; 38128 | typedef typename node_type::T3 T3; 38129 | 38130 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38131 | const details::operator_type& operation, 38132 | expression_node_ptr (&branch)[2]) 38133 | { 38134 | // (c o0 v0) o1 (v1 o2 v2) 38135 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]); 38136 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]); 38137 | const Type c = cov->c (); 38138 | const Type& v0 = cov->v (); 38139 | const Type& v1 = vov->v0(); 38140 | const Type& v2 = vov->v1(); 38141 | const details::operator_type o0 = cov->operation(); 38142 | const details::operator_type o1 = operation; 38143 | const details::operator_type o2 = vov->operation(); 38144 | 38145 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 38146 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38147 | 38148 | expression_node_ptr result = error_node(); 38149 | 38150 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 38151 | { 38152 | // (c / v0) * (v1 / v2) --> (covovov) (c * v1) / (v0 * v2) 38153 | if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 38154 | { 38155 | const bool synthesis_result = 38156 | synthesize_sf4ext_expression:: 38157 | template compile<ctype, vtype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", c, v1, v0, v2, result); 38158 | 38159 | exprtk_debug(("(c / v0) * (v1 / v2) --> (covovov) (c * v1) / (v0 * v2)\n")); 38160 | 38161 | return (synthesis_result) ? result : error_node(); 38162 | } 38163 | // (c / v0) / (v1 / v2) --> (covovov) (c * v2) / (v0 * v1) 38164 | if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 38165 | { 38166 | const bool synthesis_result = 38167 | synthesize_sf4ext_expression:: 38168 | template compile<ctype, vtype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", c, v2, v0, v1, result); 38169 | 38170 | exprtk_debug(("(c / v0) / (v1 / v2) --> (covovov) (c * v2) / (v0 * v1)\n")); 38171 | 38172 | return (synthesis_result) ? result : error_node(); 38173 | } 38174 | } 38175 | 38176 | const bool synthesis_result = 38177 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38178 | (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result); 38179 | 38180 | if (synthesis_result) 38181 | return result; 38182 | 38183 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38184 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 38185 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 38186 | 38187 | if (!expr_gen.valid_operator(o0,f0)) 38188 | return error_node(); 38189 | else if (!expr_gen.valid_operator(o1,f1)) 38190 | return error_node(); 38191 | else if (!expr_gen.valid_operator(o2,f2)) 38192 | return error_node(); 38193 | else 38194 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2); 38195 | } 38196 | 38197 | static inline std::string id(expression_generator<Type>& expr_gen, 38198 | const details::operator_type o0, 38199 | const details::operator_type o1, 38200 | const details::operator_type o2) 38201 | { 38202 | return details::build_string() 38203 | << "(t" << expr_gen.to_str(o0) 38204 | << "t)" << expr_gen.to_str(o1) 38205 | << "(t" << expr_gen.to_str(o2) 38206 | << "t)" 38207 | } 38208 | }; 38209 | 38210 | struct synthesize_covocov_expression0 38211 | { 38212 | typedef typename covocov_t::type0 node_type; 38213 | typedef typename covocov_t::sf4_type sf4_type; 38214 | typedef typename node_type::T0 T0; 38215 | typedef typename node_type::T1 T1; 38216 | typedef typename node_type::T2 T2; 38217 | typedef typename node_type::T3 T3; 38218 | 38219 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38220 | const details::operator_type& operation, 38221 | expression_node_ptr (&branch)[2]) 38222 | { 38223 | // (c0 o0 v0) o1 (c1 o2 v1) 38224 | const details::cov_base_node<Type>* cov0 = static_cast<details::cov_base_node<Type>*>(branch[0]); 38225 | const details::cov_base_node<Type>* cov1 = static_cast<details::cov_base_node<Type>*>(branch[1]); 38226 | const Type c0 = cov0->c(); 38227 | const Type& v0 = cov0->v(); 38228 | const Type c1 = cov1->c(); 38229 | const Type& v1 = cov1->v(); 38230 | const details::operator_type o0 = cov0->operation(); 38231 | const details::operator_type o1 = operation; 38232 | const details::operator_type o2 = cov1->operation(); 38233 | 38234 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 38235 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38236 | 38237 | expression_node_ptr result = error_node(); 38238 | 38239 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 38240 | { 38241 | // (c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1 38242 | if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2)) 38243 | { 38244 | const bool synthesis_result = 38245 | synthesize_sf3ext_expression:: 38246 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result); 38247 | 38248 | exprtk_debug(("(c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n")); 38249 | 38250 | return (synthesis_result) ? result : error_node(); 38251 | } 38252 | // (c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1 38253 | else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2)) 38254 | { 38255 | const bool synthesis_result = 38256 | synthesize_sf3ext_expression:: 38257 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result); 38258 | 38259 | exprtk_debug(("(c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n")); 38260 | 38261 | return (synthesis_result) ? result : error_node(); 38262 | } 38263 | // (c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1 38264 | else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2)) 38265 | { 38266 | const bool synthesis_result = 38267 | synthesize_sf3ext_expression:: 38268 | template compile<ctype, vtype, vtype>(expr_gen, "(t-t)+t", (c0 - c1), v0, v1, result); 38269 | 38270 | exprtk_debug(("(c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1\n")); 38271 | 38272 | return (synthesis_result) ? result : error_node(); 38273 | } 38274 | // (c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1 38275 | else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2)) 38276 | { 38277 | const bool synthesis_result = 38278 | synthesize_sf3ext_expression:: 38279 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result); 38280 | 38281 | exprtk_debug(("(c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n")); 38282 | 38283 | return (synthesis_result) ? result : error_node(); 38284 | } 38285 | // (c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1) 38286 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38287 | { 38288 | const bool synthesis_result = 38289 | synthesize_sf3ext_expression:: 38290 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result); 38291 | 38292 | exprtk_debug(("(c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1)\n")); 38293 | 38294 | return (synthesis_result) ? result : error_node(); 38295 | } 38296 | // (c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1) 38297 | else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 38298 | { 38299 | const bool synthesis_result = 38300 | synthesize_sf3ext_expression:: 38301 | template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", (c0 * c1), v0, v1, result); 38302 | 38303 | exprtk_debug(("(c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1)\n")); 38304 | 38305 | return (synthesis_result) ? result : error_node(); 38306 | } 38307 | // (c0 / v0) / (c1 / v1) --> (covov) ((c0 / c1) * v1) / v0 38308 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 38309 | { 38310 | const bool synthesis_result = 38311 | synthesize_sf3ext_expression:: 38312 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v1, v0, result); 38313 | 38314 | exprtk_debug(("(c0 / v0) / (c1 / v1) --> (covov) ((c0 / c1) * v1) / v0\n")); 38315 | 38316 | return (synthesis_result) ? result : error_node(); 38317 | } 38318 | // (c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1) 38319 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) 38320 | { 38321 | const bool synthesis_result = 38322 | synthesize_sf3ext_expression:: 38323 | template compile<ctype, vtype, vtype>(expr_gen, "t*(t*t)", (c0 / c1), v0, v1, result); 38324 | 38325 | exprtk_debug(("(c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n")); 38326 | 38327 | return (synthesis_result) ? result : error_node(); 38328 | } 38329 | // (c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1) 38330 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38331 | { 38332 | const bool synthesis_result = 38333 | synthesize_sf3ext_expression:: 38334 | template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", (c0 / c1), v0, v1, result); 38335 | 38336 | exprtk_debug(("(c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1)\n")); 38337 | 38338 | return (synthesis_result) ? result : error_node(); 38339 | } 38340 | // (c * v0) +/- (c * v1) --> (covov) c * (v0 +/- v1) 38341 | else if ( 38342 | (std::equal_to<T>()(c0,c1)) && 38343 | (details::e_mul == o0) && 38344 | (details::e_mul == o2) && 38345 | ( 38346 | (details::e_add == o1) || 38347 | (details::e_sub == o1) 38348 | ) 38349 | ) 38350 | { 38351 | std::string specfunc; 38352 | 38353 | switch (o1) 38354 | { 38355 | case details::e_add : specfunc = "t*(t+t)" break; 38356 | case details::e_sub : specfunc = "t*(t-t)" break; 38357 | default : return error_node(); 38358 | } 38359 | 38360 | const bool synthesis_result = 38361 | synthesize_sf3ext_expression:: 38362 | template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result); 38363 | 38364 | exprtk_debug(("(c * v0) +/- (c * v1) --> (covov) c * (v0 +/- v1)\n")); 38365 | 38366 | return (synthesis_result) ? result : error_node(); 38367 | } 38368 | } 38369 | 38370 | const bool synthesis_result = 38371 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38372 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result); 38373 | 38374 | if (synthesis_result) 38375 | return result; 38376 | 38377 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38378 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 38379 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 38380 | 38381 | if (!expr_gen.valid_operator(o0,f0)) 38382 | return error_node(); 38383 | else if (!expr_gen.valid_operator(o1,f1)) 38384 | return error_node(); 38385 | else if (!expr_gen.valid_operator(o2,f2)) 38386 | return error_node(); 38387 | else 38388 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2); 38389 | } 38390 | 38391 | static inline std::string id(expression_generator<Type>& expr_gen, 38392 | const details::operator_type o0, 38393 | const details::operator_type o1, 38394 | const details::operator_type o2) 38395 | { 38396 | return details::build_string() 38397 | << "(t" << expr_gen.to_str(o0) 38398 | << "t)" << expr_gen.to_str(o1) 38399 | << "(t" << expr_gen.to_str(o2) 38400 | << "t)" 38401 | } 38402 | }; 38403 | 38404 | struct synthesize_vocovoc_expression0 38405 | { 38406 | typedef typename vocovoc_t::type0 node_type; 38407 | typedef typename vocovoc_t::sf4_type sf4_type; 38408 | typedef typename node_type::T0 T0; 38409 | typedef typename node_type::T1 T1; 38410 | typedef typename node_type::T2 T2; 38411 | typedef typename node_type::T3 T3; 38412 | 38413 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38414 | const details::operator_type& operation, 38415 | expression_node_ptr (&branch)[2]) 38416 | { 38417 | // (v0 o0 c0) o1 (v1 o2 c1) 38418 | const details::voc_base_node<Type>* voc0 = static_cast<details::voc_base_node<Type>*>(branch[0]); 38419 | const details::voc_base_node<Type>* voc1 = static_cast<details::voc_base_node<Type>*>(branch[1]); 38420 | const Type c0 = voc0->c(); 38421 | const Type& v0 = voc0->v(); 38422 | const Type c1 = voc1->c(); 38423 | const Type& v1 = voc1->v(); 38424 | const details::operator_type o0 = voc0->operation(); 38425 | const details::operator_type o1 = operation; 38426 | const details::operator_type o2 = voc1->operation(); 38427 | 38428 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 38429 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38430 | 38431 | expression_node_ptr result = error_node(); 38432 | 38433 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 38434 | { 38435 | // (v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1 38436 | if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2)) 38437 | { 38438 | const bool synthesis_result = 38439 | synthesize_sf3ext_expression:: 38440 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result); 38441 | 38442 | exprtk_debug(("(v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n")); 38443 | 38444 | return (synthesis_result) ? result : error_node(); 38445 | } 38446 | // (v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1 38447 | else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2)) 38448 | { 38449 | const bool synthesis_result = 38450 | synthesize_sf3ext_expression:: 38451 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result); 38452 | 38453 | exprtk_debug(("(v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n")); 38454 | 38455 | return (synthesis_result) ? result : error_node(); 38456 | } 38457 | // (v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1 38458 | else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2)) 38459 | { 38460 | const bool synthesis_result = 38461 | synthesize_sf3ext_expression:: 38462 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c1 - c0), v0, v1, result); 38463 | 38464 | exprtk_debug(("(v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1\n")); 38465 | 38466 | return (synthesis_result) ? result : error_node(); 38467 | } 38468 | // (v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1 38469 | else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2)) 38470 | { 38471 | const bool synthesis_result = 38472 | synthesize_sf3ext_expression:: 38473 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result); 38474 | 38475 | exprtk_debug(("(v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n")); 38476 | 38477 | return (synthesis_result) ? result : error_node(); 38478 | } 38479 | // (v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1) 38480 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38481 | { 38482 | const bool synthesis_result = 38483 | synthesize_sf3ext_expression:: 38484 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result); 38485 | 38486 | exprtk_debug(("(v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n")); 38487 | 38488 | return (synthesis_result) ? result : error_node(); 38489 | } 38490 | // (v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1 38491 | else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 38492 | { 38493 | const bool synthesis_result = 38494 | synthesize_sf3ext_expression:: 38495 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", Type(1) / (c0 * c1), v0, v1, result); 38496 | 38497 | exprtk_debug(("(v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1\n")); 38498 | 38499 | return (synthesis_result) ? result : error_node(); 38500 | } 38501 | // (v0 / c0) / (v1 / c1) --> (covov) ((c1 / c0) * v0) / v1 38502 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 38503 | { 38504 | const bool synthesis_result = 38505 | synthesize_sf3ext_expression:: 38506 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c1 / c0), v0, v1, result); 38507 | 38508 | exprtk_debug(("(v0 / c0) / (v1 / c1) --> (covov) ((c1 / c0) * v0) / v1\n")); 38509 | 38510 | return (synthesis_result) ? result : error_node(); 38511 | } 38512 | // (v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1) 38513 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) 38514 | { 38515 | const bool synthesis_result = 38516 | synthesize_sf3ext_expression:: 38517 | template compile<ctype, vtype, vtype>(expr_gen, "t*(t/t)", (c0 * c1), v0, v1, result); 38518 | 38519 | exprtk_debug(("(v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n")); 38520 | 38521 | return (synthesis_result) ? result : error_node(); 38522 | } 38523 | // (v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1 38524 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38525 | { 38526 | const bool synthesis_result = 38527 | synthesize_sf3ext_expression:: 38528 | template compile<ctype, vtype, vtype>(expr_gen, "t*(t/t)", Type(1) / (c0 * c1), v0, v1, result); 38529 | 38530 | exprtk_debug(("(v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1\n")); 38531 | 38532 | return (synthesis_result) ? result : error_node(); 38533 | } 38534 | // (v0 / c0) * (v1 + c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 + c1) 38535 | else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_add == o2)) 38536 | { 38537 | const bool synthesis_result = 38538 | synthesize_sf4ext_expression:: 38539 | template compile<vtype, ctype, vtype, ctype>(expr_gen, "(t*t)*(t+t)", v0, T(1) / c0, v1, c1, result); 38540 | 38541 | exprtk_debug(("(v0 / c0) * (v1 + c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 + c1)\n")); 38542 | 38543 | return (synthesis_result) ? result : error_node(); 38544 | } 38545 | // (v0 / c0) * (v1 - c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 - c1) 38546 | else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_sub == o2)) 38547 | { 38548 | const bool synthesis_result = 38549 | synthesize_sf4ext_expression:: 38550 | template compile<vtype, ctype, vtype, ctype>(expr_gen, "(t*t)*(t-t)", v0, T(1) / c0, v1, c1, result); 38551 | 38552 | exprtk_debug(("(v0 / c0) * (v1 - c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 - c1)\n")); 38553 | 38554 | return (synthesis_result) ? result : error_node(); 38555 | } 38556 | // (v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1) 38557 | else if ( 38558 | (std::equal_to<T>()(c0,c1)) && 38559 | (details::e_mul == o0) && 38560 | (details::e_mul == o2) && 38561 | ( 38562 | (details::e_add == o1) || 38563 | (details::e_sub == o1) 38564 | ) 38565 | ) 38566 | { 38567 | std::string specfunc; 38568 | 38569 | switch (o1) 38570 | { 38571 | case details::e_add : specfunc = "t*(t+t)" break; 38572 | case details::e_sub : specfunc = "t*(t-t)" break; 38573 | default : return error_node(); 38574 | } 38575 | 38576 | const bool synthesis_result = 38577 | synthesize_sf3ext_expression:: 38578 | template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result); 38579 | 38580 | exprtk_debug(("(v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n")); 38581 | 38582 | return (synthesis_result) ? result : error_node(); 38583 | } 38584 | // (v0 / c) +/- (v1 / c) --> (vovoc) (v0 +/- v1) / c 38585 | else if ( 38586 | (std::equal_to<T>()(c0,c1)) && 38587 | (details::e_div == o0) && 38588 | (details::e_div == o2) && 38589 | ( 38590 | (details::e_add == o1) || 38591 | (details::e_sub == o1) 38592 | ) 38593 | ) 38594 | { 38595 | std::string specfunc; 38596 | 38597 | switch (o1) 38598 | { 38599 | case details::e_add : specfunc = "(t+t)/t" break; 38600 | case details::e_sub : specfunc = "(t-t)/t" break; 38601 | default : return error_node(); 38602 | } 38603 | 38604 | const bool synthesis_result = 38605 | synthesize_sf3ext_expression:: 38606 | template compile<vtype, vtype, ctype>(expr_gen, specfunc, v0, v1, c0, result); 38607 | 38608 | exprtk_debug(("(v0 / c) +/- (v1 / c) --> (vovoc) (v0 +/- v1) / c\n")); 38609 | 38610 | return (synthesis_result) ? result : error_node(); 38611 | } 38612 | } 38613 | 38614 | const bool synthesis_result = 38615 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38616 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result); 38617 | 38618 | if (synthesis_result) 38619 | return result; 38620 | 38621 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38622 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 38623 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 38624 | 38625 | if (!expr_gen.valid_operator(o0,f0)) 38626 | return error_node(); 38627 | else if (!expr_gen.valid_operator(o1,f1)) 38628 | return error_node(); 38629 | else if (!expr_gen.valid_operator(o2,f2)) 38630 | return error_node(); 38631 | else 38632 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2); 38633 | } 38634 | 38635 | static inline std::string id(expression_generator<Type>& expr_gen, 38636 | const details::operator_type o0, 38637 | const details::operator_type o1, 38638 | const details::operator_type o2) 38639 | { 38640 | return details::build_string() 38641 | << "(t" << expr_gen.to_str(o0) 38642 | << "t)" << expr_gen.to_str(o1) 38643 | << "(t" << expr_gen.to_str(o2) 38644 | << "t)" 38645 | } 38646 | }; 38647 | 38648 | struct synthesize_covovoc_expression0 38649 | { 38650 | typedef typename covovoc_t::type0 node_type; 38651 | typedef typename covovoc_t::sf4_type sf4_type; 38652 | typedef typename node_type::T0 T0; 38653 | typedef typename node_type::T1 T1; 38654 | typedef typename node_type::T2 T2; 38655 | typedef typename node_type::T3 T3; 38656 | 38657 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38658 | const details::operator_type& operation, 38659 | expression_node_ptr (&branch)[2]) 38660 | { 38661 | // (c0 o0 v0) o1 (v1 o2 c1) 38662 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]); 38663 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]); 38664 | const Type c0 = cov->c(); 38665 | const Type& v0 = cov->v(); 38666 | const Type c1 = voc->c(); 38667 | const Type& v1 = voc->v(); 38668 | const details::operator_type o0 = cov->operation(); 38669 | const details::operator_type o1 = operation; 38670 | const details::operator_type o2 = voc->operation(); 38671 | 38672 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 38673 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38674 | 38675 | expression_node_ptr result = error_node(); 38676 | 38677 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 38678 | { 38679 | // (c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1 38680 | if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2)) 38681 | { 38682 | const bool synthesis_result = 38683 | synthesize_sf3ext_expression:: 38684 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result); 38685 | 38686 | exprtk_debug(("(c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n")); 38687 | 38688 | return (synthesis_result) ? result : error_node(); 38689 | } 38690 | // (c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1 38691 | else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2)) 38692 | { 38693 | const bool synthesis_result = 38694 | synthesize_sf3ext_expression:: 38695 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result); 38696 | 38697 | exprtk_debug(("(c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n")); 38698 | 38699 | return (synthesis_result) ? result : error_node(); 38700 | } 38701 | // (c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1 38702 | else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2)) 38703 | { 38704 | const bool synthesis_result = 38705 | synthesize_sf3ext_expression:: 38706 | template compile<ctype, vtype, vtype>(expr_gen, "t-(t+t)", (c0 + c1), v0, v1, result); 38707 | 38708 | exprtk_debug(("(c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1\n")); 38709 | 38710 | return (synthesis_result) ? result : error_node(); 38711 | } 38712 | // (c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1 38713 | else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2)) 38714 | { 38715 | const bool synthesis_result = 38716 | synthesize_sf3ext_expression:: 38717 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result); 38718 | 38719 | exprtk_debug(("(c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n")); 38720 | 38721 | return (synthesis_result) ? result : error_node(); 38722 | } 38723 | // (c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1) 38724 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38725 | { 38726 | const bool synthesis_result = 38727 | synthesize_sf3ext_expression:: 38728 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result); 38729 | 38730 | exprtk_debug(("(c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n")); 38731 | 38732 | return (synthesis_result) ? result : error_node(); 38733 | } 38734 | // (c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0) 38735 | else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 38736 | { 38737 | const bool synthesis_result = 38738 | synthesize_sf3ext_expression:: 38739 | template compile<ctype, vtype, vtype>(expr_gen, "t*(t/t)", (c0 / c1), v1, v0, result); 38740 | 38741 | exprtk_debug(("(c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0)\n")); 38742 | 38743 | return (synthesis_result) ? result : error_node(); 38744 | } 38745 | // (c0 / v0) / (v1 / c1) --> (covov) (c0 * c1) / (v0 * v1) 38746 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 38747 | { 38748 | const bool synthesis_result = 38749 | synthesize_sf3ext_expression:: 38750 | template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", (c0 * c1), v0, v1, result); 38751 | 38752 | exprtk_debug(("(c0 / v0) / (v1 / c1) --> (covov) (c0 * c1) / (v0 * v1)\n")); 38753 | 38754 | return (synthesis_result) ? result : error_node(); 38755 | } 38756 | // (c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1) 38757 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) 38758 | { 38759 | const bool synthesis_result = 38760 | synthesize_sf3ext_expression:: 38761 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 * c1), v0, v1, result); 38762 | 38763 | exprtk_debug(("(c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n")); 38764 | 38765 | return (synthesis_result) ? result : error_node(); 38766 | } 38767 | // (c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1) 38768 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38769 | { 38770 | const bool synthesis_result = 38771 | synthesize_sf3ext_expression:: 38772 | template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", (c0 / c1), v0, v1, result); 38773 | 38774 | exprtk_debug(("(c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1)\n")); 38775 | 38776 | return (synthesis_result) ? result : error_node(); 38777 | } 38778 | // (c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1) 38779 | else if ( 38780 | (std::equal_to<T>()(c0,c1)) && 38781 | (details::e_mul == o0) && 38782 | (details::e_mul == o2) && 38783 | ( 38784 | (details::e_add == o1) || 38785 | (details::e_sub == o1) 38786 | ) 38787 | ) 38788 | { 38789 | std::string specfunc; 38790 | 38791 | switch (o1) 38792 | { 38793 | case details::e_add : specfunc = "t*(t+t)" break; 38794 | case details::e_sub : specfunc = "t*(t-t)" break; 38795 | default : return error_node(); 38796 | } 38797 | 38798 | const bool synthesis_result = 38799 | synthesize_sf3ext_expression:: 38800 | template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result); 38801 | 38802 | exprtk_debug(("(c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n")); 38803 | 38804 | return (synthesis_result) ? result : error_node(); 38805 | } 38806 | } 38807 | 38808 | const bool synthesis_result = 38809 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38810 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result); 38811 | 38812 | if (synthesis_result) 38813 | return result; 38814 | 38815 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38816 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 38817 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 38818 | 38819 | if (!expr_gen.valid_operator(o0,f0)) 38820 | return error_node(); 38821 | else if (!expr_gen.valid_operator(o1,f1)) 38822 | return error_node(); 38823 | else if (!expr_gen.valid_operator(o2,f2)) 38824 | return error_node(); 38825 | else 38826 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2); 38827 | } 38828 | 38829 | static inline std::string id(expression_generator<Type>& expr_gen, 38830 | const details::operator_type o0, 38831 | const details::operator_type o1, 38832 | const details::operator_type o2) 38833 | { 38834 | return details::build_string() 38835 | << "(t" << expr_gen.to_str(o0) 38836 | << "t)" << expr_gen.to_str(o1) 38837 | << "(t" << expr_gen.to_str(o2) 38838 | << "t)" 38839 | } 38840 | }; 38841 | 38842 | struct synthesize_vococov_expression0 38843 | { 38844 | typedef typename vococov_t::type0 node_type; 38845 | typedef typename vococov_t::sf4_type sf4_type; 38846 | typedef typename node_type::T0 T0; 38847 | typedef typename node_type::T1 T1; 38848 | typedef typename node_type::T2 T2; 38849 | typedef typename node_type::T3 T3; 38850 | 38851 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38852 | const details::operator_type& operation, 38853 | expression_node_ptr (&branch)[2]) 38854 | { 38855 | // (v0 o0 c0) o1 (c1 o2 v1) 38856 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]); 38857 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]); 38858 | const Type c0 = voc->c(); 38859 | const Type& v0 = voc->v(); 38860 | const Type c1 = cov->c(); 38861 | const Type& v1 = cov->v(); 38862 | const details::operator_type o0 = voc->operation(); 38863 | const details::operator_type o1 = operation; 38864 | const details::operator_type o2 = cov->operation(); 38865 | 38866 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 38867 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38868 | 38869 | expression_node_ptr result = error_node(); 38870 | 38871 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 38872 | { 38873 | // (v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1 38874 | if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2)) 38875 | { 38876 | const bool synthesis_result = 38877 | synthesize_sf3ext_expression:: 38878 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result); 38879 | 38880 | exprtk_debug(("(v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n")); 38881 | 38882 | return (synthesis_result) ? result : error_node(); 38883 | } 38884 | // (v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1 38885 | else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2)) 38886 | { 38887 | const bool synthesis_result = 38888 | synthesize_sf3ext_expression:: 38889 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result); 38890 | 38891 | exprtk_debug(("(v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n")); 38892 | 38893 | return (synthesis_result) ? result : error_node(); 38894 | } 38895 | // (v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0) 38896 | else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2)) 38897 | { 38898 | const bool synthesis_result = 38899 | synthesize_sf3ext_expression:: 38900 | template compile<vtype, vtype, ctype>(expr_gen, "(t+t)-t", v0, v1, (c1 + c0), result); 38901 | 38902 | exprtk_debug(("(v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0)\n")); 38903 | 38904 | return (synthesis_result) ? result : error_node(); 38905 | } 38906 | // (v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1 38907 | else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2)) 38908 | { 38909 | const bool synthesis_result = 38910 | synthesize_sf3ext_expression:: 38911 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result); 38912 | 38913 | exprtk_debug(("(v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n")); 38914 | 38915 | return (synthesis_result) ? result : error_node(); 38916 | } 38917 | // (v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1) 38918 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38919 | { 38920 | const bool synthesis_result = 38921 | synthesize_sf3ext_expression:: 38922 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result); 38923 | 38924 | exprtk_debug(("(v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1)\n")); 38925 | 38926 | return (synthesis_result) ? result : error_node(); 38927 | } 38928 | // (v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1) 38929 | else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 38930 | { 38931 | const bool synthesis_result = 38932 | synthesize_sf3ext_expression:: 38933 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c1 / c0), v0, v1, result); 38934 | 38935 | exprtk_debug(("(v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1)\n")); 38936 | 38937 | return (synthesis_result) ? result : error_node(); 38938 | } 38939 | // (v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1) 38940 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) 38941 | { 38942 | const bool synthesis_result = 38943 | synthesize_sf3ext_expression:: 38944 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 / c1), v0, v1, result); 38945 | 38946 | exprtk_debug(("(v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n")); 38947 | 38948 | return (synthesis_result) ? result : error_node(); 38949 | } 38950 | // (v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1) 38951 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38952 | { 38953 | const bool synthesis_result = 38954 | synthesize_sf3ext_expression:: 38955 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", Type(1) / (c0 * c1), v0, v1, result); 38956 | 38957 | exprtk_debug(("(v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1)\n")); 38958 | 38959 | return (synthesis_result) ? result : error_node(); 38960 | } 38961 | // (v0 / c0) / (c1 / v1) --> (vovoc) (v0 * v1) * (1 / (c0 * c1)) 38962 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 38963 | { 38964 | const bool synthesis_result = 38965 | synthesize_sf3ext_expression:: 38966 | template compile<vtype, vtype, ctype>(expr_gen, "(t*t)*t", v0, v1, Type(1) / (c0 * c1), result); 38967 | 38968 | exprtk_debug(("(v0 / c0) / (c1 / v1) --> (vovoc) (v0 * v1) * (1 / (c0 * c1))\n")); 38969 | 38970 | return (synthesis_result) ? result : error_node(); 38971 | } 38972 | // (v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1) 38973 | else if ( 38974 | (std::equal_to<T>()(c0,c1)) && 38975 | (details::e_mul == o0) && 38976 | (details::e_mul == o2) && 38977 | ( 38978 | (details::e_add == o1) || (details::e_sub == o1) 38979 | ) 38980 | ) 38981 | { 38982 | std::string specfunc; 38983 | 38984 | switch (o1) 38985 | { 38986 | case details::e_add : specfunc = "t*(t+t)" break; 38987 | case details::e_sub : specfunc = "t*(t-t)" break; 38988 | default : return error_node(); 38989 | } 38990 | 38991 | const bool synthesis_result = 38992 | synthesize_sf3ext_expression:: 38993 | template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result); 38994 | 38995 | exprtk_debug(("(v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1)\n")); 38996 | 38997 | return (synthesis_result) ? result : error_node(); 38998 | } 38999 | } 39000 | 39001 | const bool synthesis_result = 39002 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39003 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result); 39004 | 39005 | if (synthesis_result) 39006 | return result; 39007 | 39008 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39009 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 39010 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 39011 | 39012 | if (!expr_gen.valid_operator(o0,f0)) 39013 | return error_node(); 39014 | else if (!expr_gen.valid_operator(o1,f1)) 39015 | return error_node(); 39016 | else if (!expr_gen.valid_operator(o2,f2)) 39017 | return error_node(); 39018 | else 39019 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2); 39020 | } 39021 | 39022 | static inline std::string id(expression_generator<Type>& expr_gen, 39023 | const details::operator_type o0, 39024 | const details::operator_type o1, 39025 | const details::operator_type o2) 39026 | { 39027 | return details::build_string() 39028 | << "(t" << expr_gen.to_str(o0) 39029 | << "t)" << expr_gen.to_str(o1) 39030 | << "(t" << expr_gen.to_str(o2) 39031 | << "t)" 39032 | } 39033 | }; 39034 | 39035 | struct synthesize_vovovov_expression1 39036 | { 39037 | typedef typename vovovov_t::type1 node_type; 39038 | typedef typename vovovov_t::sf4_type sf4_type; 39039 | typedef typename node_type::T0 T0; 39040 | typedef typename node_type::T1 T1; 39041 | typedef typename node_type::T2 T2; 39042 | typedef typename node_type::T3 T3; 39043 | 39044 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39045 | const details::operator_type& operation, 39046 | expression_node_ptr (&branch)[2]) 39047 | { 39048 | // v0 o0 (v1 o1 (v2 o2 v3)) 39049 | typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t; 39050 | 39051 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]); 39052 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39053 | const Type& v1 = vovov->t0(); 39054 | const Type& v2 = vovov->t1(); 39055 | const Type& v3 = vovov->t2(); 39056 | const details::operator_type o0 = operation; 39057 | const details::operator_type o1 = expr_gen.get_operator(vovov->f0()); 39058 | const details::operator_type o2 = expr_gen.get_operator(vovov->f1()); 39059 | 39060 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39061 | binary_functor_t f1 = vovov->f0(); 39062 | binary_functor_t f2 = vovov->f1(); 39063 | 39064 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39065 | 39066 | expression_node_ptr result = error_node(); 39067 | 39068 | const bool synthesis_result = 39069 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39070 | (expr_gen,id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result); 39071 | 39072 | if (synthesis_result) 39073 | return result; 39074 | else if (!expr_gen.valid_operator(o0,f0)) 39075 | return error_node(); 39076 | 39077 | exprtk_debug(("v0 o0 (v1 o1 (v2 o2 v3))\n")); 39078 | 39079 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2); 39080 | } 39081 | 39082 | static inline std::string id(expression_generator<Type>& expr_gen, 39083 | const details::operator_type o0, 39084 | const details::operator_type o1, 39085 | const details::operator_type o2) 39086 | { 39087 | return details::build_string() 39088 | << "t" << expr_gen.to_str(o0) 39089 | << "(t" << expr_gen.to_str(o1) 39090 | << "(t" << expr_gen.to_str(o2) 39091 | << "t))" 39092 | } 39093 | }; 39094 | 39095 | struct synthesize_vovovoc_expression1 39096 | { 39097 | typedef typename vovovoc_t::type1 node_type; 39098 | typedef typename vovovoc_t::sf4_type sf4_type; 39099 | typedef typename node_type::T0 T0; 39100 | typedef typename node_type::T1 T1; 39101 | typedef typename node_type::T2 T2; 39102 | typedef typename node_type::T3 T3; 39103 | 39104 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39105 | const details::operator_type& operation, 39106 | expression_node_ptr (&branch)[2]) 39107 | { 39108 | // v0 o0 (v1 o1 (v2 o2 c)) 39109 | typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t; 39110 | 39111 | const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]); 39112 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39113 | const Type& v1 = vovoc->t0(); 39114 | const Type& v2 = vovoc->t1(); 39115 | const Type c = vovoc->t2(); 39116 | const details::operator_type o0 = operation; 39117 | const details::operator_type o1 = expr_gen.get_operator(vovoc->f0()); 39118 | const details::operator_type o2 = expr_gen.get_operator(vovoc->f1()); 39119 | 39120 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39121 | binary_functor_t f1 = vovoc->f0(); 39122 | binary_functor_t f2 = vovoc->f1(); 39123 | 39124 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39125 | 39126 | expression_node_ptr result = error_node(); 39127 | 39128 | const bool synthesis_result = 39129 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39130 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result); 39131 | 39132 | if (synthesis_result) 39133 | return result; 39134 | else if (!expr_gen.valid_operator(o0,f0)) 39135 | return error_node(); 39136 | 39137 | exprtk_debug(("v0 o0 (v1 o1 (v2 o2 c))\n")); 39138 | 39139 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2); 39140 | } 39141 | 39142 | static inline std::string id(expression_generator<Type>& expr_gen, 39143 | const details::operator_type o0, 39144 | const details::operator_type o1, 39145 | const details::operator_type o2) 39146 | { 39147 | return details::build_string() 39148 | << "t" << expr_gen.to_str(o0) 39149 | << "(t" << expr_gen.to_str(o1) 39150 | << "(t" << expr_gen.to_str(o2) 39151 | << "t))" 39152 | } 39153 | }; 39154 | 39155 | struct synthesize_vovocov_expression1 39156 | { 39157 | typedef typename vovocov_t::type1 node_type; 39158 | typedef typename vovocov_t::sf4_type sf4_type; 39159 | typedef typename node_type::T0 T0; 39160 | typedef typename node_type::T1 T1; 39161 | typedef typename node_type::T2 T2; 39162 | typedef typename node_type::T3 T3; 39163 | 39164 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39165 | const details::operator_type& operation, 39166 | expression_node_ptr (&branch)[2]) 39167 | { 39168 | // v0 o0 (v1 o1 (c o2 v2)) 39169 | typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t; 39170 | 39171 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]); 39172 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39173 | const Type& v1 = vocov->t0(); 39174 | const Type c = vocov->t1(); 39175 | const Type& v2 = vocov->t2(); 39176 | const details::operator_type o0 = operation; 39177 | const details::operator_type o1 = expr_gen.get_operator(vocov->f0()); 39178 | const details::operator_type o2 = expr_gen.get_operator(vocov->f1()); 39179 | 39180 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39181 | binary_functor_t f1 = vocov->f0(); 39182 | binary_functor_t f2 = vocov->f1(); 39183 | 39184 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39185 | 39186 | expression_node_ptr result = error_node(); 39187 | 39188 | const bool synthesis_result = 39189 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39190 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result); 39191 | 39192 | if (synthesis_result) 39193 | return result; 39194 | if (!expr_gen.valid_operator(o0,f0)) 39195 | return error_node(); 39196 | 39197 | exprtk_debug(("v0 o0 (v1 o1 (c o2 v2))\n")); 39198 | 39199 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2); 39200 | } 39201 | 39202 | static inline std::string id(expression_generator<Type>& expr_gen, 39203 | const details::operator_type o0, 39204 | const details::operator_type o1, 39205 | const details::operator_type o2) 39206 | { 39207 | return details::build_string() 39208 | << "t" << expr_gen.to_str(o0) 39209 | << "(t" << expr_gen.to_str(o1) 39210 | << "(t" << expr_gen.to_str(o2) 39211 | << "t))" 39212 | } 39213 | }; 39214 | 39215 | struct synthesize_vocovov_expression1 39216 | { 39217 | typedef typename vocovov_t::type1 node_type; 39218 | typedef typename vocovov_t::sf4_type sf4_type; 39219 | typedef typename node_type::T0 T0; 39220 | typedef typename node_type::T1 T1; 39221 | typedef typename node_type::T2 T2; 39222 | typedef typename node_type::T3 T3; 39223 | 39224 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39225 | const details::operator_type& operation, 39226 | expression_node_ptr (&branch)[2]) 39227 | { 39228 | // v0 o0 (c o1 (v1 o2 v2)) 39229 | typedef typename synthesize_covov_expression1::node_type lcl_covov_t; 39230 | 39231 | const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[1]); 39232 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39233 | const Type c = covov->t0(); 39234 | const Type& v1 = covov->t1(); 39235 | const Type& v2 = covov->t2(); 39236 | const details::operator_type o0 = operation; 39237 | const details::operator_type o1 = expr_gen.get_operator(covov->f0()); 39238 | const details::operator_type o2 = expr_gen.get_operator(covov->f1()); 39239 | 39240 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39241 | binary_functor_t f1 = covov->f0(); 39242 | binary_functor_t f2 = covov->f1(); 39243 | 39244 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39245 | 39246 | expression_node_ptr result = error_node(); 39247 | 39248 | const bool synthesis_result = 39249 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39250 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result); 39251 | 39252 | if (synthesis_result) 39253 | return result; 39254 | else if (!expr_gen.valid_operator(o0,f0)) 39255 | return error_node(); 39256 | 39257 | exprtk_debug(("v0 o0 (c o1 (v1 o2 v2))\n")); 39258 | 39259 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2); 39260 | } 39261 | 39262 | static inline std::string id(expression_generator<Type>& expr_gen, 39263 | const details::operator_type o0, 39264 | const details::operator_type o1, 39265 | const details::operator_type o2) 39266 | { 39267 | return details::build_string() 39268 | << "t" << expr_gen.to_str(o0) 39269 | << "(t" << expr_gen.to_str(o1) 39270 | << "(t" << expr_gen.to_str(o2) 39271 | << "t))" 39272 | } 39273 | }; 39274 | 39275 | struct synthesize_covovov_expression1 39276 | { 39277 | typedef typename covovov_t::type1 node_type; 39278 | typedef typename covovov_t::sf4_type sf4_type; 39279 | typedef typename node_type::T0 T0; 39280 | typedef typename node_type::T1 T1; 39281 | typedef typename node_type::T2 T2; 39282 | typedef typename node_type::T3 T3; 39283 | 39284 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39285 | const details::operator_type& operation, 39286 | expression_node_ptr (&branch)[2]) 39287 | { 39288 | // c o0 (v0 o1 (v1 o2 v2)) 39289 | typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t; 39290 | 39291 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]); 39292 | const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); 39293 | const Type& v0 = vovov->t0(); 39294 | const Type& v1 = vovov->t1(); 39295 | const Type& v2 = vovov->t2(); 39296 | const details::operator_type o0 = operation; 39297 | const details::operator_type o1 = expr_gen.get_operator(vovov->f0()); 39298 | const details::operator_type o2 = expr_gen.get_operator(vovov->f1()); 39299 | 39300 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39301 | binary_functor_t f1 = vovov->f0(); 39302 | binary_functor_t f2 = vovov->f1(); 39303 | 39304 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39305 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39306 | 39307 | expression_node_ptr result = error_node(); 39308 | 39309 | const bool synthesis_result = 39310 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39311 | (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result); 39312 | 39313 | if (synthesis_result) 39314 | return result; 39315 | if (!expr_gen.valid_operator(o0,f0)) 39316 | return error_node(); 39317 | 39318 | exprtk_debug(("c o0 (v0 o1 (v1 o2 v2))\n")); 39319 | 39320 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2); 39321 | } 39322 | 39323 | static inline std::string id(expression_generator<Type>& expr_gen, 39324 | const details::operator_type o0, 39325 | const details::operator_type o1, 39326 | const details::operator_type o2) 39327 | { 39328 | return details::build_string() 39329 | << "t" << expr_gen.to_str(o0) 39330 | << "(t" << expr_gen.to_str(o1) 39331 | << "(t" << expr_gen.to_str(o2) 39332 | << "t))" 39333 | } 39334 | }; 39335 | 39336 | struct synthesize_covocov_expression1 39337 | { 39338 | typedef typename covocov_t::type1 node_type; 39339 | typedef typename covocov_t::sf4_type sf4_type; 39340 | typedef typename node_type::T0 T0; 39341 | typedef typename node_type::T1 T1; 39342 | typedef typename node_type::T2 T2; 39343 | typedef typename node_type::T3 T3; 39344 | 39345 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39346 | const details::operator_type& operation, 39347 | expression_node_ptr (&branch)[2]) 39348 | { 39349 | // c0 o0 (v0 o1 (c1 o2 v1)) 39350 | typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t; 39351 | 39352 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]); 39353 | const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); 39354 | const Type& v0 = vocov->t0(); 39355 | const Type c1 = vocov->t1(); 39356 | const Type& v1 = vocov->t2(); 39357 | const details::operator_type o0 = operation; 39358 | const details::operator_type o1 = expr_gen.get_operator(vocov->f0()); 39359 | const details::operator_type o2 = expr_gen.get_operator(vocov->f1()); 39360 | 39361 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39362 | binary_functor_t f1 = vocov->f0(); 39363 | binary_functor_t f2 = vocov->f1(); 39364 | 39365 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39366 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39367 | 39368 | expression_node_ptr result = error_node(); 39369 | 39370 | const bool synthesis_result = 39371 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39372 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result); 39373 | 39374 | if (synthesis_result) 39375 | return result; 39376 | else if (!expr_gen.valid_operator(o0,f0)) 39377 | return error_node(); 39378 | 39379 | exprtk_debug(("c0 o0 (v0 o1 (c1 o2 v1))\n")); 39380 | 39381 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2); 39382 | } 39383 | 39384 | static inline std::string id(expression_generator<Type>& expr_gen, 39385 | const details::operator_type o0, 39386 | const details::operator_type o1, 39387 | const details::operator_type o2) 39388 | { 39389 | return details::build_string() 39390 | << "t" << expr_gen.to_str(o0) 39391 | << "(t" << expr_gen.to_str(o1) 39392 | << "(t" << expr_gen.to_str(o2) 39393 | << "t))" 39394 | } 39395 | }; 39396 | 39397 | struct synthesize_vocovoc_expression1 39398 | { 39399 | typedef typename vocovoc_t::type1 node_type; 39400 | typedef typename vocovoc_t::sf4_type sf4_type; 39401 | typedef typename node_type::T0 T0; 39402 | typedef typename node_type::T1 T1; 39403 | typedef typename node_type::T2 T2; 39404 | typedef typename node_type::T3 T3; 39405 | 39406 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39407 | const details::operator_type& operation, 39408 | expression_node_ptr (&branch)[2]) 39409 | { 39410 | // v0 o0 (c0 o1 (v1 o2 c2)) 39411 | typedef typename synthesize_covoc_expression1::node_type lcl_covoc_t; 39412 | 39413 | const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[1]); 39414 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39415 | const Type c0 = covoc->t0(); 39416 | const Type& v1 = covoc->t1(); 39417 | const Type c1 = covoc->t2(); 39418 | const details::operator_type o0 = operation; 39419 | const details::operator_type o1 = expr_gen.get_operator(covoc->f0()); 39420 | const details::operator_type o2 = expr_gen.get_operator(covoc->f1()); 39421 | 39422 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39423 | binary_functor_t f1 = covoc->f0(); 39424 | binary_functor_t f2 = covoc->f1(); 39425 | 39426 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39427 | 39428 | expression_node_ptr result = error_node(); 39429 | 39430 | const bool synthesis_result = 39431 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39432 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result); 39433 | 39434 | if (synthesis_result) 39435 | return result; 39436 | else if (!expr_gen.valid_operator(o0,f0)) 39437 | return error_node(); 39438 | 39439 | exprtk_debug(("v0 o0 (c0 o1 (v1 o2 c2))\n")); 39440 | 39441 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2); 39442 | } 39443 | 39444 | static inline std::string id(expression_generator<Type>& expr_gen, 39445 | const details::operator_type o0, 39446 | const details::operator_type o1, 39447 | const details::operator_type o2) 39448 | { 39449 | return details::build_string() 39450 | << "t" << expr_gen.to_str(o0) 39451 | << "(t" << expr_gen.to_str(o1) 39452 | << "(t" << expr_gen.to_str(o2) 39453 | << "t))" 39454 | } 39455 | }; 39456 | 39457 | struct synthesize_covovoc_expression1 39458 | { 39459 | typedef typename covovoc_t::type1 node_type; 39460 | typedef typename covovoc_t::sf4_type sf4_type; 39461 | typedef typename node_type::T0 T0; 39462 | typedef typename node_type::T1 T1; 39463 | typedef typename node_type::T2 T2; 39464 | typedef typename node_type::T3 T3; 39465 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39466 | const details::operator_type& operation, 39467 | expression_node_ptr (&branch)[2]) 39468 | { 39469 | // c0 o0 (v0 o1 (v1 o2 c1)) 39470 | typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t; 39471 | 39472 | const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]); 39473 | const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); 39474 | const Type& v0 = vovoc->t0(); 39475 | const Type& v1 = vovoc->t1(); 39476 | const Type c1 = vovoc->t2(); 39477 | const details::operator_type o0 = operation; 39478 | const details::operator_type o1 = expr_gen.get_operator(vovoc->f0()); 39479 | const details::operator_type o2 = expr_gen.get_operator(vovoc->f1()); 39480 | 39481 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39482 | binary_functor_t f1 = vovoc->f0(); 39483 | binary_functor_t f2 = vovoc->f1(); 39484 | 39485 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39486 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39487 | 39488 | expression_node_ptr result = error_node(); 39489 | 39490 | const bool synthesis_result = 39491 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39492 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result); 39493 | 39494 | if (synthesis_result) 39495 | return result; 39496 | else if (!expr_gen.valid_operator(o0,f0)) 39497 | return error_node(); 39498 | 39499 | exprtk_debug(("c0 o0 (v0 o1 (v1 o2 c1))\n")); 39500 | 39501 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2); 39502 | } 39503 | 39504 | static inline std::string id(expression_generator<Type>& expr_gen, 39505 | const details::operator_type o0, 39506 | const details::operator_type o1, 39507 | const details::operator_type o2) 39508 | { 39509 | return details::build_string() 39510 | << "t" << expr_gen.to_str(o0) 39511 | << "(t" << expr_gen.to_str(o1) 39512 | << "(t" << expr_gen.to_str(o2) 39513 | << "t))" 39514 | } 39515 | }; 39516 | 39517 | struct synthesize_vococov_expression1 39518 | { 39519 | typedef typename vococov_t::type1 node_type; 39520 | typedef typename vococov_t::sf4_type sf4_type; 39521 | typedef typename node_type::T0 T0; 39522 | typedef typename node_type::T1 T1; 39523 | typedef typename node_type::T2 T2; 39524 | typedef typename node_type::T3 T3; 39525 | 39526 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39527 | const details::operator_type& operation, 39528 | expression_node_ptr (&branch)[2]) 39529 | { 39530 | // v0 o0 (c0 o1 (c1 o2 v1)) 39531 | typedef typename synthesize_cocov_expression1::node_type lcl_cocov_t; 39532 | 39533 | const lcl_cocov_t* cocov = static_cast<const lcl_cocov_t*>(branch[1]); 39534 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39535 | const Type c0 = cocov->t0(); 39536 | const Type c1 = cocov->t1(); 39537 | const Type& v1 = cocov->t2(); 39538 | const details::operator_type o0 = operation; 39539 | const details::operator_type o1 = expr_gen.get_operator(cocov->f0()); 39540 | const details::operator_type o2 = expr_gen.get_operator(cocov->f1()); 39541 | 39542 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39543 | binary_functor_t f1 = cocov->f0(); 39544 | binary_functor_t f2 = cocov->f1(); 39545 | 39546 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39547 | 39548 | expression_node_ptr result = error_node(); 39549 | 39550 | const bool synthesis_result = 39551 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39552 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result); 39553 | 39554 | if (synthesis_result) 39555 | return result; 39556 | else if (!expr_gen.valid_operator(o0,f0)) 39557 | return error_node(); 39558 | 39559 | exprtk_debug(("v0 o0 (c0 o1 (c1 o2 v1))\n")); 39560 | 39561 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2); 39562 | } 39563 | 39564 | static inline std::string id(expression_generator<Type>& expr_gen, 39565 | const details::operator_type o0, 39566 | const details::operator_type o1, 39567 | const details::operator_type o2) 39568 | { 39569 | return details::build_string() 39570 | << "t" << expr_gen.to_str(o0) 39571 | << "(t" << expr_gen.to_str(o1) 39572 | << "(t" << expr_gen.to_str(o2) 39573 | << "t))" 39574 | } 39575 | }; 39576 | 39577 | struct synthesize_vovovov_expression2 39578 | { 39579 | typedef typename vovovov_t::type2 node_type; 39580 | typedef typename vovovov_t::sf4_type sf4_type; 39581 | typedef typename node_type::T0 T0; 39582 | typedef typename node_type::T1 T1; 39583 | typedef typename node_type::T2 T2; 39584 | typedef typename node_type::T3 T3; 39585 | 39586 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39587 | const details::operator_type& operation, 39588 | expression_node_ptr (&branch)[2]) 39589 | { 39590 | // v0 o0 ((v1 o1 v2) o2 v3) 39591 | typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t; 39592 | 39593 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]); 39594 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39595 | const Type& v1 = vovov->t0(); 39596 | const Type& v2 = vovov->t1(); 39597 | const Type& v3 = vovov->t2(); 39598 | const details::operator_type o0 = operation; 39599 | const details::operator_type o1 = expr_gen.get_operator(vovov->f0()); 39600 | const details::operator_type o2 = expr_gen.get_operator(vovov->f1()); 39601 | 39602 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39603 | binary_functor_t f1 = vovov->f0(); 39604 | binary_functor_t f2 = vovov->f1(); 39605 | 39606 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39607 | 39608 | expression_node_ptr result = error_node(); 39609 | 39610 | const bool synthesis_result = 39611 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39612 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result); 39613 | 39614 | if (synthesis_result) 39615 | return result; 39616 | else if (!expr_gen.valid_operator(o0,f0)) 39617 | return error_node(); 39618 | 39619 | exprtk_debug(("v0 o0 ((v1 o1 v2) o2 v3)\n")); 39620 | 39621 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2); 39622 | } 39623 | 39624 | static inline std::string id(expression_generator<Type>& expr_gen, 39625 | const details::operator_type o0, 39626 | const details::operator_type o1, 39627 | const details::operator_type o2) 39628 | { 39629 | return details::build_string() 39630 | << "t" << expr_gen.to_str(o0) 39631 | << "((t" << expr_gen.to_str(o1) 39632 | << "t)" << expr_gen.to_str(o2) 39633 | << "t)" 39634 | } 39635 | }; 39636 | 39637 | struct synthesize_vovovoc_expression2 39638 | { 39639 | typedef typename vovovoc_t::type2 node_type; 39640 | typedef typename vovovoc_t::sf4_type sf4_type; 39641 | typedef typename node_type::T0 T0; 39642 | typedef typename node_type::T1 T1; 39643 | typedef typename node_type::T2 T2; 39644 | typedef typename node_type::T3 T3; 39645 | 39646 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39647 | const details::operator_type& operation, 39648 | expression_node_ptr (&branch)[2]) 39649 | { 39650 | // v0 o0 ((v1 o1 v2) o2 c) 39651 | typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t; 39652 | 39653 | const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]); 39654 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39655 | const Type& v1 = vovoc->t0(); 39656 | const Type& v2 = vovoc->t1(); 39657 | const Type c = vovoc->t2(); 39658 | const details::operator_type o0 = operation; 39659 | const details::operator_type o1 = expr_gen.get_operator(vovoc->f0()); 39660 | const details::operator_type o2 = expr_gen.get_operator(vovoc->f1()); 39661 | 39662 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39663 | binary_functor_t f1 = vovoc->f0(); 39664 | binary_functor_t f2 = vovoc->f1(); 39665 | 39666 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39667 | 39668 | expression_node_ptr result = error_node(); 39669 | 39670 | const bool synthesis_result = 39671 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39672 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result); 39673 | 39674 | if (synthesis_result) 39675 | return result; 39676 | else if (!expr_gen.valid_operator(o0,f0)) 39677 | return error_node(); 39678 | 39679 | exprtk_debug(("v0 o0 ((v1 o1 v2) o2 c)\n")); 39680 | 39681 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2); 39682 | } 39683 | 39684 | static inline std::string id(expression_generator<Type>& expr_gen, 39685 | const details::operator_type o0, 39686 | const details::operator_type o1, 39687 | const details::operator_type o2) 39688 | { 39689 | return details::build_string() 39690 | << "t" << expr_gen.to_str(o0) 39691 | << "((t" << expr_gen.to_str(o1) 39692 | << "t)" << expr_gen.to_str(o2) 39693 | << "t)" 39694 | } 39695 | }; 39696 | 39697 | struct synthesize_vovocov_expression2 39698 | { 39699 | typedef typename vovocov_t::type2 node_type; 39700 | typedef typename vovocov_t::sf4_type sf4_type; 39701 | typedef typename node_type::T0 T0; 39702 | typedef typename node_type::T1 T1; 39703 | typedef typename node_type::T2 T2; 39704 | typedef typename node_type::T3 T3; 39705 | 39706 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39707 | const details::operator_type& operation, 39708 | expression_node_ptr (&branch)[2]) 39709 | { 39710 | // v0 o0 ((v1 o1 c) o2 v2) 39711 | typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t; 39712 | 39713 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]); 39714 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39715 | const Type& v1 = vocov->t0(); 39716 | const Type c = vocov->t1(); 39717 | const Type& v2 = vocov->t2(); 39718 | const details::operator_type o0 = operation; 39719 | const details::operator_type o1 = expr_gen.get_operator(vocov->f0()); 39720 | const details::operator_type o2 = expr_gen.get_operator(vocov->f1()); 39721 | 39722 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39723 | binary_functor_t f1 = vocov->f0(); 39724 | binary_functor_t f2 = vocov->f1(); 39725 | 39726 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39727 | 39728 | expression_node_ptr result = error_node(); 39729 | 39730 | const bool synthesis_result = 39731 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39732 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result); 39733 | 39734 | if (synthesis_result) 39735 | return result; 39736 | else if (!expr_gen.valid_operator(o0,f0)) 39737 | return error_node(); 39738 | 39739 | exprtk_debug(("v0 o0 ((v1 o1 c) o2 v2)\n")); 39740 | 39741 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2); 39742 | } 39743 | 39744 | static inline std::string id(expression_generator<Type>& expr_gen, 39745 | const details::operator_type o0, 39746 | const details::operator_type o1, 39747 | const details::operator_type o2) 39748 | { 39749 | return details::build_string() 39750 | << "t" << expr_gen.to_str(o0) 39751 | << "((t" << expr_gen.to_str(o1) 39752 | << "t)" << expr_gen.to_str(o2) 39753 | << "t)" 39754 | } 39755 | }; 39756 | 39757 | struct synthesize_vocovov_expression2 39758 | { 39759 | typedef typename vocovov_t::type2 node_type; 39760 | typedef typename vocovov_t::sf4_type sf4_type; 39761 | typedef typename node_type::T0 T0; 39762 | typedef typename node_type::T1 T1; 39763 | typedef typename node_type::T2 T2; 39764 | typedef typename node_type::T3 T3; 39765 | 39766 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39767 | const details::operator_type& operation, 39768 | expression_node_ptr (&branch)[2]) 39769 | { 39770 | // v0 o0 ((c o1 v1) o2 v2) 39771 | typedef typename synthesize_covov_expression0::node_type lcl_covov_t; 39772 | 39773 | const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[1]); 39774 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39775 | const Type c = covov->t0(); 39776 | const Type& v1 = covov->t1(); 39777 | const Type& v2 = covov->t2(); 39778 | const details::operator_type o0 = operation; 39779 | const details::operator_type o1 = expr_gen.get_operator(covov->f0()); 39780 | const details::operator_type o2 = expr_gen.get_operator(covov->f1()); 39781 | 39782 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39783 | binary_functor_t f1 = covov->f0(); 39784 | binary_functor_t f2 = covov->f1(); 39785 | 39786 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39787 | 39788 | expression_node_ptr result = error_node(); 39789 | 39790 | const bool synthesis_result = 39791 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39792 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result); 39793 | 39794 | if (synthesis_result) 39795 | return result; 39796 | else if (!expr_gen.valid_operator(o0,f0)) 39797 | return error_node(); 39798 | 39799 | exprtk_debug(("v0 o0 ((c o1 v1) o2 v2)\n")); 39800 | 39801 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2); 39802 | } 39803 | 39804 | static inline std::string id(expression_generator<Type>& expr_gen, 39805 | const details::operator_type o0, 39806 | const details::operator_type o1, 39807 | const details::operator_type o2) 39808 | { 39809 | return details::build_string() 39810 | << "t" << expr_gen.to_str(o0) 39811 | << "((t" << expr_gen.to_str(o1) 39812 | << "t)" << expr_gen.to_str(o2) 39813 | << "t)" 39814 | } 39815 | }; 39816 | 39817 | struct synthesize_covovov_expression2 39818 | { 39819 | typedef typename covovov_t::type2 node_type; 39820 | typedef typename covovov_t::sf4_type sf4_type; 39821 | typedef typename node_type::T0 T0; 39822 | typedef typename node_type::T1 T1; 39823 | typedef typename node_type::T2 T2; 39824 | typedef typename node_type::T3 T3; 39825 | 39826 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39827 | const details::operator_type& operation, 39828 | expression_node_ptr (&branch)[2]) 39829 | { 39830 | // c o0 ((v1 o1 v2) o2 v3) 39831 | typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t; 39832 | 39833 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]); 39834 | const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); 39835 | const Type& v0 = vovov->t0(); 39836 | const Type& v1 = vovov->t1(); 39837 | const Type& v2 = vovov->t2(); 39838 | const details::operator_type o0 = operation; 39839 | const details::operator_type o1 = expr_gen.get_operator(vovov->f0()); 39840 | const details::operator_type o2 = expr_gen.get_operator(vovov->f1()); 39841 | 39842 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39843 | binary_functor_t f1 = vovov->f0(); 39844 | binary_functor_t f2 = vovov->f1(); 39845 | 39846 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39847 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39848 | 39849 | expression_node_ptr result = error_node(); 39850 | 39851 | const bool synthesis_result = 39852 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39853 | (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result); 39854 | 39855 | if (synthesis_result) 39856 | return result; 39857 | else if (!expr_gen.valid_operator(o0,f0)) 39858 | return error_node(); 39859 | 39860 | exprtk_debug(("c o0 ((v1 o1 v2) o2 v3)\n")); 39861 | 39862 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2); 39863 | } 39864 | 39865 | static inline std::string id(expression_generator<Type>& expr_gen, 39866 | const details::operator_type o0, 39867 | const details::operator_type o1, 39868 | const details::operator_type o2) 39869 | { 39870 | return details::build_string() 39871 | << "t" << expr_gen.to_str(o0) 39872 | << "((t" << expr_gen.to_str(o1) 39873 | << "t)" << expr_gen.to_str(o2) 39874 | << "t)" 39875 | } 39876 | }; 39877 | 39878 | struct synthesize_covocov_expression2 39879 | { 39880 | typedef typename covocov_t::type2 node_type; 39881 | typedef typename covocov_t::sf4_type sf4_type; 39882 | typedef typename node_type::T0 T0; 39883 | typedef typename node_type::T1 T1; 39884 | typedef typename node_type::T2 T2; 39885 | typedef typename node_type::T3 T3; 39886 | 39887 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39888 | const details::operator_type& operation, 39889 | expression_node_ptr (&branch)[2]) 39890 | { 39891 | // c0 o0 ((v0 o1 c1) o2 v1) 39892 | typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t; 39893 | 39894 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]); 39895 | const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); 39896 | const Type& v0 = vocov->t0(); 39897 | const Type c1 = vocov->t1(); 39898 | const Type& v1 = vocov->t2(); 39899 | const details::operator_type o0 = operation; 39900 | const details::operator_type o1 = expr_gen.get_operator(vocov->f0()); 39901 | const details::operator_type o2 = expr_gen.get_operator(vocov->f1()); 39902 | 39903 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39904 | binary_functor_t f1 = vocov->f0(); 39905 | binary_functor_t f2 = vocov->f1(); 39906 | 39907 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39908 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39909 | 39910 | expression_node_ptr result = error_node(); 39911 | 39912 | const bool synthesis_result = 39913 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39914 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result); 39915 | 39916 | if (synthesis_result) 39917 | return result; 39918 | else if (!expr_gen.valid_operator(o0,f0)) 39919 | return error_node(); 39920 | 39921 | exprtk_debug(("c0 o0 ((v0 o1 c1) o2 v1)\n")); 39922 | 39923 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2); 39924 | } 39925 | 39926 | static inline std::string id(expression_generator<Type>& expr_gen, 39927 | const details::operator_type o0, 39928 | const details::operator_type o1, 39929 | const details::operator_type o2) 39930 | { 39931 | return details::build_string() 39932 | << "t" << expr_gen.to_str(o0) 39933 | << "((t" << expr_gen.to_str(o1) 39934 | << "t)" << expr_gen.to_str(o2) 39935 | << "t)" 39936 | } 39937 | }; 39938 | 39939 | struct synthesize_vocovoc_expression2 39940 | { 39941 | typedef typename vocovoc_t::type2 node_type; 39942 | typedef typename vocovoc_t::sf4_type sf4_type; 39943 | typedef typename node_type::T0 T0; 39944 | typedef typename node_type::T1 T1; 39945 | typedef typename node_type::T2 T2; 39946 | typedef typename node_type::T3 T3; 39947 | 39948 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39949 | const details::operator_type& operation, 39950 | expression_node_ptr (&branch)[2]) 39951 | { 39952 | // v0 o0 ((c0 o1 v1) o2 c1) 39953 | typedef typename synthesize_covoc_expression0::node_type lcl_covoc_t; 39954 | 39955 | const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[1]); 39956 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39957 | const Type c0 = covoc->t0(); 39958 | const Type& v1 = covoc->t1(); 39959 | const Type c1 = covoc->t2(); 39960 | const details::operator_type o0 = operation; 39961 | const details::operator_type o1 = expr_gen.get_operator(covoc->f0()); 39962 | const details::operator_type o2 = expr_gen.get_operator(covoc->f1()); 39963 | 39964 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39965 | binary_functor_t f1 = covoc->f0(); 39966 | binary_functor_t f2 = covoc->f1(); 39967 | 39968 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39969 | 39970 | expression_node_ptr result = error_node(); 39971 | 39972 | const bool synthesis_result = 39973 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39974 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result); 39975 | 39976 | if (synthesis_result) 39977 | return result; 39978 | else if (!expr_gen.valid_operator(o0,f0)) 39979 | return error_node(); 39980 | 39981 | exprtk_debug(("v0 o0 ((c0 o1 v1) o2 c1)\n")); 39982 | 39983 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2); 39984 | } 39985 | 39986 | static inline std::string id(expression_generator<Type>& expr_gen, 39987 | const details::operator_type o0, 39988 | const details::operator_type o1, 39989 | const details::operator_type o2) 39990 | { 39991 | return details::build_string() 39992 | << "t" << expr_gen.to_str(o0) 39993 | << "((t" << expr_gen.to_str(o1) 39994 | << "t)" << expr_gen.to_str(o2) 39995 | << "t)" 39996 | } 39997 | }; 39998 | 39999 | struct synthesize_covovoc_expression2 40000 | { 40001 | typedef typename covovoc_t::type2 node_type; 40002 | typedef typename covovoc_t::sf4_type sf4_type; 40003 | typedef typename node_type::T0 T0; 40004 | typedef typename node_type::T1 T1; 40005 | typedef typename node_type::T2 T2; 40006 | typedef typename node_type::T3 T3; 40007 | 40008 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40009 | const details::operator_type& operation, 40010 | expression_node_ptr (&branch)[2]) 40011 | { 40012 | // c0 o0 ((v0 o1 v1) o2 c1) 40013 | typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t; 40014 | 40015 | const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]); 40016 | const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); 40017 | const Type& v0 = vovoc->t0(); 40018 | const Type& v1 = vovoc->t1(); 40019 | const Type c1 = vovoc->t2(); 40020 | const details::operator_type o0 = operation; 40021 | const details::operator_type o1 = expr_gen.get_operator(vovoc->f0()); 40022 | const details::operator_type o2 = expr_gen.get_operator(vovoc->f1()); 40023 | 40024 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 40025 | binary_functor_t f1 = vovoc->f0(); 40026 | binary_functor_t f2 = vovoc->f1(); 40027 | 40028 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40029 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 40030 | 40031 | expression_node_ptr result = error_node(); 40032 | 40033 | const bool synthesis_result = 40034 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40035 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result); 40036 | 40037 | if (synthesis_result) 40038 | return result; 40039 | else if (!expr_gen.valid_operator(o0,f0)) 40040 | return error_node(); 40041 | 40042 | exprtk_debug(("c0 o0 ((v0 o1 v1) o2 c1)\n")); 40043 | 40044 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2); 40045 | } 40046 | 40047 | static inline std::string id(expression_generator<Type>& expr_gen, 40048 | const details::operator_type o0, 40049 | const details::operator_type o1, 40050 | const details::operator_type o2) 40051 | { 40052 | return details::build_string() 40053 | << "t" << expr_gen.to_str(o0) 40054 | << "((t" << expr_gen.to_str(o1) 40055 | << "t)" << expr_gen.to_str(o2) 40056 | << "t)" 40057 | } 40058 | }; 40059 | 40060 | struct synthesize_vococov_expression2 40061 | { 40062 | typedef typename vococov_t::type2 node_type; 40063 | static inline expression_node_ptr process(expression_generator<Type>&, 40064 | const details::operator_type&, 40065 | expression_node_ptr (&)[2]) 40066 | { 40067 | // v0 o0 ((c0 o1 c1) o2 v1) - Not possible 40068 | exprtk_debug(("v0 o0 ((c0 o1 c1) o2 v1) - Not possible\n")); 40069 | return error_node(); 40070 | } 40071 | 40072 | static inline std::string id(expression_generator<Type>&, 40073 | const details::operator_type, 40074 | const details::operator_type, 40075 | const details::operator_type) 40076 | { 40077 | return "INVALID" 40078 | } 40079 | }; 40080 | 40081 | struct synthesize_vovovov_expression3 40082 | { 40083 | typedef typename vovovov_t::type3 node_type; 40084 | typedef typename vovovov_t::sf4_type sf4_type; 40085 | typedef typename node_type::T0 T0; 40086 | typedef typename node_type::T1 T1; 40087 | typedef typename node_type::T2 T2; 40088 | typedef typename node_type::T3 T3; 40089 | 40090 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40091 | const details::operator_type& operation, 40092 | expression_node_ptr (&branch)[2]) 40093 | { 40094 | // ((v0 o0 v1) o1 v2) o2 v3 40095 | typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t; 40096 | 40097 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]); 40098 | const Type& v0 = vovov->t0(); 40099 | const Type& v1 = vovov->t1(); 40100 | const Type& v2 = vovov->t2(); 40101 | const Type& v3 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40102 | const details::operator_type o0 = expr_gen.get_operator(vovov->f0()); 40103 | const details::operator_type o1 = expr_gen.get_operator(vovov->f1()); 40104 | const details::operator_type o2 = operation; 40105 | 40106 | binary_functor_t f0 = vovov->f0(); 40107 | binary_functor_t f1 = vovov->f1(); 40108 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40109 | 40110 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40111 | 40112 | expression_node_ptr result = error_node(); 40113 | 40114 | const bool synthesis_result = 40115 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40116 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result); 40117 | 40118 | if (synthesis_result) 40119 | return result; 40120 | else if (!expr_gen.valid_operator(o2,f2)) 40121 | return error_node(); 40122 | 40123 | exprtk_debug(("((v0 o0 v1) o1 v2) o2 v3\n")); 40124 | 40125 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2); 40126 | } 40127 | 40128 | static inline std::string id(expression_generator<Type>& expr_gen, 40129 | const details::operator_type o0, 40130 | const details::operator_type o1, 40131 | const details::operator_type o2) 40132 | { 40133 | return details::build_string() 40134 | << "((t" << expr_gen.to_str(o0) 40135 | << "t)" << expr_gen.to_str(o1) 40136 | << "t)" << expr_gen.to_str(o2) 40137 | << "t" 40138 | } 40139 | }; 40140 | 40141 | struct synthesize_vovovoc_expression3 40142 | { 40143 | typedef typename vovovoc_t::type3 node_type; 40144 | typedef typename vovovoc_t::sf4_type sf4_type; 40145 | typedef typename node_type::T0 T0; 40146 | typedef typename node_type::T1 T1; 40147 | typedef typename node_type::T2 T2; 40148 | typedef typename node_type::T3 T3; 40149 | 40150 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40151 | const details::operator_type& operation, 40152 | expression_node_ptr (&branch)[2]) 40153 | { 40154 | // ((v0 o0 v1) o1 v2) o2 c 40155 | typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t; 40156 | 40157 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]); 40158 | const Type& v0 = vovov->t0(); 40159 | const Type& v1 = vovov->t1(); 40160 | const Type& v2 = vovov->t2(); 40161 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 40162 | const details::operator_type o0 = expr_gen.get_operator(vovov->f0()); 40163 | const details::operator_type o1 = expr_gen.get_operator(vovov->f1()); 40164 | const details::operator_type o2 = operation; 40165 | 40166 | binary_functor_t f0 = vovov->f0(); 40167 | binary_functor_t f1 = vovov->f1(); 40168 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40169 | 40170 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40171 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 40172 | 40173 | expression_node_ptr result = error_node(); 40174 | 40175 | const bool synthesis_result = 40176 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40177 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result); 40178 | 40179 | if (synthesis_result) 40180 | return result; 40181 | else if (!expr_gen.valid_operator(o2,f2)) 40182 | return error_node(); 40183 | 40184 | exprtk_debug(("((v0 o0 v1) o1 v2) o2 c\n")); 40185 | 40186 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2); 40187 | } 40188 | 40189 | static inline std::string id(expression_generator<Type>& expr_gen, 40190 | const details::operator_type o0, 40191 | const details::operator_type o1, 40192 | const details::operator_type o2) 40193 | { 40194 | return details::build_string() 40195 | << "((t" << expr_gen.to_str(o0) 40196 | << "t)" << expr_gen.to_str(o1) 40197 | << "t)" << expr_gen.to_str(o2) 40198 | << "t" 40199 | } 40200 | }; 40201 | 40202 | struct synthesize_vovocov_expression3 40203 | { 40204 | typedef typename vovocov_t::type3 node_type; 40205 | typedef typename vovocov_t::sf4_type sf4_type; 40206 | typedef typename node_type::T0 T0; 40207 | typedef typename node_type::T1 T1; 40208 | typedef typename node_type::T2 T2; 40209 | typedef typename node_type::T3 T3; 40210 | 40211 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40212 | const details::operator_type& operation, 40213 | expression_node_ptr (&branch)[2]) 40214 | { 40215 | // ((v0 o0 v1) o1 c) o2 v2 40216 | typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t; 40217 | 40218 | const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[0]); 40219 | const Type& v0 = vovoc->t0(); 40220 | const Type& v1 = vovoc->t1(); 40221 | const Type c = vovoc->t2(); 40222 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40223 | const details::operator_type o0 = expr_gen.get_operator(vovoc->f0()); 40224 | const details::operator_type o1 = expr_gen.get_operator(vovoc->f1()); 40225 | const details::operator_type o2 = operation; 40226 | 40227 | binary_functor_t f0 = vovoc->f0(); 40228 | binary_functor_t f1 = vovoc->f1(); 40229 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40230 | 40231 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40232 | 40233 | expression_node_ptr result = error_node(); 40234 | 40235 | const bool synthesis_result = 40236 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40237 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result); 40238 | 40239 | if (synthesis_result) 40240 | return result; 40241 | else if (!expr_gen.valid_operator(o2,f2)) 40242 | return error_node(); 40243 | 40244 | exprtk_debug(("((v0 o0 v1) o1 c) o2 v2\n")); 40245 | 40246 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2); 40247 | } 40248 | 40249 | static inline std::string id(expression_generator<Type>& expr_gen, 40250 | const details::operator_type o0, 40251 | const details::operator_type o1, 40252 | const details::operator_type o2) 40253 | { 40254 | return details::build_string() 40255 | << "((t" << expr_gen.to_str(o0) 40256 | << "t)" << expr_gen.to_str(o1) 40257 | << "t)" << expr_gen.to_str(o2) 40258 | << "t" 40259 | } 40260 | }; 40261 | 40262 | struct synthesize_vocovov_expression3 40263 | { 40264 | typedef typename vocovov_t::type3 node_type; 40265 | typedef typename vocovov_t::sf4_type sf4_type; 40266 | typedef typename node_type::T0 T0; 40267 | typedef typename node_type::T1 T1; 40268 | typedef typename node_type::T2 T2; 40269 | typedef typename node_type::T3 T3; 40270 | 40271 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40272 | const details::operator_type& operation, 40273 | expression_node_ptr (&branch)[2]) 40274 | { 40275 | // ((v0 o0 c) o1 v1) o2 v2 40276 | typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t; 40277 | 40278 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]); 40279 | const Type& v0 = vocov->t0(); 40280 | const Type c = vocov->t1(); 40281 | const Type& v1 = vocov->t2(); 40282 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40283 | const details::operator_type o0 = expr_gen.get_operator(vocov->f0()); 40284 | const details::operator_type o1 = expr_gen.get_operator(vocov->f1()); 40285 | const details::operator_type o2 = operation; 40286 | 40287 | binary_functor_t f0 = vocov->f0(); 40288 | binary_functor_t f1 = vocov->f1(); 40289 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40290 | 40291 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40292 | 40293 | expression_node_ptr result = error_node(); 40294 | 40295 | const bool synthesis_result = 40296 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40297 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result); 40298 | 40299 | if (synthesis_result) 40300 | return result; 40301 | else if (!expr_gen.valid_operator(o2,f2)) 40302 | return error_node(); 40303 | 40304 | exprtk_debug(("((v0 o0 c) o1 v1) o2 v2\n")); 40305 | 40306 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2); 40307 | } 40308 | 40309 | static inline std::string id(expression_generator<Type>& expr_gen, 40310 | const details::operator_type o0, 40311 | const details::operator_type o1, 40312 | const details::operator_type o2) 40313 | { 40314 | return details::build_string() 40315 | << "((t" << expr_gen.to_str(o0) 40316 | << "t)" << expr_gen.to_str(o1) 40317 | << "t)" << expr_gen.to_str(o2) 40318 | << "t" 40319 | } 40320 | }; 40321 | 40322 | struct synthesize_covovov_expression3 40323 | { 40324 | typedef typename covovov_t::type3 node_type; 40325 | typedef typename covovov_t::sf4_type sf4_type; 40326 | typedef typename node_type::T0 T0; 40327 | typedef typename node_type::T1 T1; 40328 | typedef typename node_type::T2 T2; 40329 | typedef typename node_type::T3 T3; 40330 | 40331 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40332 | const details::operator_type& operation, 40333 | expression_node_ptr (&branch)[2]) 40334 | { 40335 | // ((c o0 v0) o1 v1) o2 v2 40336 | typedef typename synthesize_covov_expression0::node_type lcl_covov_t; 40337 | 40338 | const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]); 40339 | const Type c = covov->t0(); 40340 | const Type& v0 = covov->t1(); 40341 | const Type& v1 = covov->t2(); 40342 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40343 | const details::operator_type o0 = expr_gen.get_operator(covov->f0()); 40344 | const details::operator_type o1 = expr_gen.get_operator(covov->f1()); 40345 | const details::operator_type o2 = operation; 40346 | 40347 | binary_functor_t f0 = covov->f0(); 40348 | binary_functor_t f1 = covov->f1(); 40349 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40350 | 40351 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40352 | 40353 | expression_node_ptr result = error_node(); 40354 | 40355 | const bool synthesis_result = 40356 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40357 | (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result); 40358 | 40359 | if (synthesis_result) 40360 | return result; 40361 | else if (!expr_gen.valid_operator(o2,f2)) 40362 | return error_node(); 40363 | 40364 | exprtk_debug(("((c o0 v0) o1 v1) o2 v2\n")); 40365 | 40366 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2); 40367 | } 40368 | 40369 | static inline std::string id(expression_generator<Type>& expr_gen, 40370 | const details::operator_type o0, 40371 | const details::operator_type o1, 40372 | const details::operator_type o2) 40373 | { 40374 | return details::build_string() 40375 | << "((t" << expr_gen.to_str(o0) 40376 | << "t)" << expr_gen.to_str(o1) 40377 | << "t)" << expr_gen.to_str(o2) 40378 | << "t" 40379 | } 40380 | }; 40381 | 40382 | struct synthesize_covocov_expression3 40383 | { 40384 | typedef typename covocov_t::type3 node_type; 40385 | typedef typename covocov_t::sf4_type sf4_type; 40386 | typedef typename node_type::T0 T0; 40387 | typedef typename node_type::T1 T1; 40388 | typedef typename node_type::T2 T2; 40389 | typedef typename node_type::T3 T3; 40390 | 40391 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40392 | const details::operator_type& operation, 40393 | expression_node_ptr (&branch)[2]) 40394 | { 40395 | // ((c0 o0 v0) o1 c1) o2 v1 40396 | typedef typename synthesize_covoc_expression0::node_type lcl_covoc_t; 40397 | 40398 | const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[0]); 40399 | const Type c0 = covoc->t0(); 40400 | const Type& v0 = covoc->t1(); 40401 | const Type c1 = covoc->t2(); 40402 | const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40403 | const details::operator_type o0 = expr_gen.get_operator(covoc->f0()); 40404 | const details::operator_type o1 = expr_gen.get_operator(covoc->f1()); 40405 | const details::operator_type o2 = operation; 40406 | 40407 | binary_functor_t f0 = covoc->f0(); 40408 | binary_functor_t f1 = covoc->f1(); 40409 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40410 | 40411 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40412 | 40413 | expression_node_ptr result = error_node(); 40414 | 40415 | const bool synthesis_result = 40416 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40417 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result); 40418 | 40419 | if (synthesis_result) 40420 | return result; 40421 | else if (!expr_gen.valid_operator(o2,f2)) 40422 | return error_node(); 40423 | 40424 | exprtk_debug(("((c0 o0 v0) o1 c1) o2 v1\n")); 40425 | 40426 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2); 40427 | } 40428 | 40429 | static inline std::string id(expression_generator<Type>& expr_gen, 40430 | const details::operator_type o0, 40431 | const details::operator_type o1, 40432 | const details::operator_type o2) 40433 | { 40434 | return details::build_string() 40435 | << "((t" << expr_gen.to_str(o0) 40436 | << "t)" << expr_gen.to_str(o1) 40437 | << "t)" << expr_gen.to_str(o2) 40438 | << "t" 40439 | } 40440 | }; 40441 | 40442 | struct synthesize_vocovoc_expression3 40443 | { 40444 | typedef typename vocovoc_t::type3 node_type; 40445 | typedef typename vocovoc_t::sf4_type sf4_type; 40446 | typedef typename node_type::T0 T0; 40447 | typedef typename node_type::T1 T1; 40448 | typedef typename node_type::T2 T2; 40449 | typedef typename node_type::T3 T3; 40450 | 40451 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40452 | const details::operator_type& operation, 40453 | expression_node_ptr (&branch)[2]) 40454 | { 40455 | // ((v0 o0 c0) o1 v1) o2 c1 40456 | typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t; 40457 | 40458 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]); 40459 | const Type& v0 = vocov->t0(); 40460 | const Type c0 = vocov->t1(); 40461 | const Type& v1 = vocov->t2(); 40462 | const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); 40463 | const details::operator_type o0 = expr_gen.get_operator(vocov->f0()); 40464 | const details::operator_type o1 = expr_gen.get_operator(vocov->f1()); 40465 | const details::operator_type o2 = operation; 40466 | 40467 | binary_functor_t f0 = vocov->f0(); 40468 | binary_functor_t f1 = vocov->f1(); 40469 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40470 | 40471 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40472 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 40473 | 40474 | expression_node_ptr result = error_node(); 40475 | 40476 | const bool synthesis_result = 40477 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40478 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result); 40479 | 40480 | if (synthesis_result) 40481 | return result; 40482 | else if (!expr_gen.valid_operator(o2,f2)) 40483 | return error_node(); 40484 | 40485 | exprtk_debug(("((v0 o0 c0) o1 v1) o2 c1\n")); 40486 | 40487 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2); 40488 | } 40489 | 40490 | static inline std::string id(expression_generator<Type>& expr_gen, 40491 | const details::operator_type o0, 40492 | const details::operator_type o1, 40493 | const details::operator_type o2) 40494 | { 40495 | return details::build_string() 40496 | << "((t" << expr_gen.to_str(o0) 40497 | << "t)" << expr_gen.to_str(o1) 40498 | << "t)" << expr_gen.to_str(o2) 40499 | << "t" 40500 | } 40501 | }; 40502 | 40503 | struct synthesize_covovoc_expression3 40504 | { 40505 | typedef typename covovoc_t::type3 node_type; 40506 | typedef typename covovoc_t::sf4_type sf4_type; 40507 | typedef typename node_type::T0 T0; 40508 | typedef typename node_type::T1 T1; 40509 | typedef typename node_type::T2 T2; 40510 | typedef typename node_type::T3 T3; 40511 | 40512 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40513 | const details::operator_type& operation, 40514 | expression_node_ptr (&branch)[2]) 40515 | { 40516 | // ((c0 o0 v0) o1 v1) o2 c1 40517 | typedef typename synthesize_covov_expression0::node_type lcl_covov_t; 40518 | 40519 | const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]); 40520 | const Type c0 = covov->t0(); 40521 | const Type& v0 = covov->t1(); 40522 | const Type& v1 = covov->t2(); 40523 | const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); 40524 | const details::operator_type o0 = expr_gen.get_operator(covov->f0()); 40525 | const details::operator_type o1 = expr_gen.get_operator(covov->f1()); 40526 | const details::operator_type o2 = operation; 40527 | 40528 | binary_functor_t f0 = covov->f0(); 40529 | binary_functor_t f1 = covov->f1(); 40530 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40531 | 40532 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40533 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 40534 | 40535 | expression_node_ptr result = error_node(); 40536 | 40537 | const bool synthesis_result = 40538 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40539 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result); 40540 | 40541 | if (synthesis_result) 40542 | return result; 40543 | else if (!expr_gen.valid_operator(o2,f2)) 40544 | return error_node(); 40545 | 40546 | exprtk_debug(("((c0 o0 v0) o1 v1) o2 c1\n")); 40547 | 40548 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2); 40549 | } 40550 | 40551 | static inline std::string id(expression_generator<Type>& expr_gen, 40552 | const details::operator_type o0, 40553 | const details::operator_type o1, 40554 | const details::operator_type o2) 40555 | { 40556 | return details::build_string() 40557 | << "((t" << expr_gen.to_str(o0) 40558 | << "t)" << expr_gen.to_str(o1) 40559 | << "t)" << expr_gen.to_str(o2) 40560 | << "t" 40561 | } 40562 | }; 40563 | 40564 | struct synthesize_vococov_expression3 40565 | { 40566 | typedef typename vococov_t::type3 node_type; 40567 | typedef typename vococov_t::sf4_type sf4_type; 40568 | typedef typename node_type::T0 T0; 40569 | typedef typename node_type::T1 T1; 40570 | typedef typename node_type::T2 T2; 40571 | typedef typename node_type::T3 T3; 40572 | 40573 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40574 | const details::operator_type& operation, 40575 | expression_node_ptr (&branch)[2]) 40576 | { 40577 | // ((v0 o0 c0) o1 c1) o2 v1 40578 | typedef typename synthesize_vococ_expression0::node_type lcl_vococ_t; 40579 | 40580 | const lcl_vococ_t* vococ = static_cast<const lcl_vococ_t*>(branch[0]); 40581 | const Type& v0 = vococ->t0(); 40582 | const Type c0 = vococ->t1(); 40583 | const Type c1 = vococ->t2(); 40584 | const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40585 | const details::operator_type o0 = expr_gen.get_operator(vococ->f0()); 40586 | const details::operator_type o1 = expr_gen.get_operator(vococ->f1()); 40587 | const details::operator_type o2 = operation; 40588 | 40589 | binary_functor_t f0 = vococ->f0(); 40590 | binary_functor_t f1 = vococ->f1(); 40591 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40592 | 40593 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40594 | 40595 | expression_node_ptr result = error_node(); 40596 | 40597 | const bool synthesis_result = 40598 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40599 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result); 40600 | 40601 | if (synthesis_result) 40602 | return result; 40603 | else if (!expr_gen.valid_operator(o2,f2)) 40604 | return error_node(); 40605 | 40606 | exprtk_debug(("((v0 o0 c0) o1 c1) o2 v1\n")); 40607 | 40608 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2); 40609 | } 40610 | 40611 | static inline std::string id(expression_generator<Type>& expr_gen, 40612 | const details::operator_type o0, 40613 | const details::operator_type o1, 40614 | const details::operator_type o2) 40615 | { 40616 | return details::build_string() 40617 | << "((t" << expr_gen.to_str(o0) 40618 | << "t)" << expr_gen.to_str(o1) 40619 | << "t)" << expr_gen.to_str(o2) 40620 | << "t" 40621 | } 40622 | }; 40623 | 40624 | struct synthesize_vovovov_expression4 40625 | { 40626 | typedef typename vovovov_t::type4 node_type; 40627 | typedef typename vovovov_t::sf4_type sf4_type; 40628 | typedef typename node_type::T0 T0; 40629 | typedef typename node_type::T1 T1; 40630 | typedef typename node_type::T2 T2; 40631 | typedef typename node_type::T3 T3; 40632 | 40633 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40634 | const details::operator_type& operation, 40635 | expression_node_ptr (&branch)[2]) 40636 | { 40637 | // (v0 o0 (v1 o1 v2)) o2 v3 40638 | typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t; 40639 | 40640 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]); 40641 | const Type& v0 = vovov->t0(); 40642 | const Type& v1 = vovov->t1(); 40643 | const Type& v2 = vovov->t2(); 40644 | const Type& v3 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40645 | const details::operator_type o0 = expr_gen.get_operator(vovov->f0()); 40646 | const details::operator_type o1 = expr_gen.get_operator(vovov->f1()); 40647 | const details::operator_type o2 = operation; 40648 | 40649 | binary_functor_t f0 = vovov->f0(); 40650 | binary_functor_t f1 = vovov->f1(); 40651 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40652 | 40653 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40654 | 40655 | expression_node_ptr result = error_node(); 40656 | 40657 | const bool synthesis_result = 40658 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40659 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result); 40660 | 40661 | if (synthesis_result) 40662 | return result; 40663 | else if (!expr_gen.valid_operator(o2,f2)) 40664 | return error_node(); 40665 | 40666 | exprtk_debug(("(v0 o0 (v1 o1 v2)) o2 v3\n")); 40667 | 40668 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2); 40669 | } 40670 | 40671 | static inline std::string id(expression_generator<Type>& expr_gen, 40672 | const details::operator_type o0, 40673 | const details::operator_type o1, 40674 | const details::operator_type o2) 40675 | { 40676 | return details::build_string() 40677 | << "(t" << expr_gen.to_str(o0) 40678 | << "(t" << expr_gen.to_str(o1) 40679 | << "t)" << expr_gen.to_str(o2) 40680 | << "t" 40681 | } 40682 | }; 40683 | 40684 | struct synthesize_vovovoc_expression4 40685 | { 40686 | typedef typename vovovoc_t::type4 node_type; 40687 | typedef typename vovovoc_t::sf4_type sf4_type; 40688 | typedef typename node_type::T0 T0; 40689 | typedef typename node_type::T1 T1; 40690 | typedef typename node_type::T2 T2; 40691 | typedef typename node_type::T3 T3; 40692 | 40693 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40694 | const details::operator_type& operation, 40695 | expression_node_ptr (&branch)[2]) 40696 | { 40697 | // ((v0 o0 (v1 o1 v2)) o2 c) 40698 | typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t; 40699 | 40700 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]); 40701 | const Type& v0 = vovov->t0(); 40702 | const Type& v1 = vovov->t1(); 40703 | const Type& v2 = vovov->t2(); 40704 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 40705 | const details::operator_type o0 = expr_gen.get_operator(vovov->f0()); 40706 | const details::operator_type o1 = expr_gen.get_operator(vovov->f1()); 40707 | const details::operator_type o2 = operation; 40708 | 40709 | binary_functor_t f0 = vovov->f0(); 40710 | binary_functor_t f1 = vovov->f1(); 40711 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40712 | 40713 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40714 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 40715 | 40716 | expression_node_ptr result = error_node(); 40717 | 40718 | const bool synthesis_result = 40719 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40720 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result); 40721 | 40722 | if (synthesis_result) 40723 | return result; 40724 | else if (!expr_gen.valid_operator(o2,f2)) 40725 | return error_node(); 40726 | 40727 | exprtk_debug(("((v0 o0 (v1 o1 v2)) o2 c)\n")); 40728 | 40729 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2); 40730 | } 40731 | 40732 | static inline std::string id(expression_generator<Type>& expr_gen, 40733 | const details::operator_type o0, 40734 | const details::operator_type o1, 40735 | const details::operator_type o2) 40736 | { 40737 | return details::build_string() 40738 | << "(t" << expr_gen.to_str(o0) 40739 | << "(t" << expr_gen.to_str(o1) 40740 | << "t)" << expr_gen.to_str(o2) 40741 | << "t" 40742 | } 40743 | }; 40744 | 40745 | struct synthesize_vovocov_expression4 40746 | { 40747 | typedef typename vovocov_t::type4 node_type; 40748 | typedef typename vovocov_t::sf4_type sf4_type; 40749 | typedef typename node_type::T0 T0; 40750 | typedef typename node_type::T1 T1; 40751 | typedef typename node_type::T2 T2; 40752 | typedef typename node_type::T3 T3; 40753 | 40754 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40755 | const details::operator_type& operation, 40756 | expression_node_ptr (&branch)[2]) 40757 | { 40758 | // ((v0 o0 (v1 o1 c)) o2 v1) 40759 | typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t; 40760 | 40761 | const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[0]); 40762 | const Type& v0 = vovoc->t0(); 40763 | const Type& v1 = vovoc->t1(); 40764 | const Type c = vovoc->t2(); 40765 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40766 | const details::operator_type o0 = expr_gen.get_operator(vovoc->f0()); 40767 | const details::operator_type o1 = expr_gen.get_operator(vovoc->f1()); 40768 | const details::operator_type o2 = operation; 40769 | 40770 | binary_functor_t f0 = vovoc->f0(); 40771 | binary_functor_t f1 = vovoc->f1(); 40772 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40773 | 40774 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40775 | 40776 | expression_node_ptr result = error_node(); 40777 | 40778 | const bool synthesis_result = 40779 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40780 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result); 40781 | 40782 | if (synthesis_result) 40783 | return result; 40784 | else if (!expr_gen.valid_operator(o2,f2)) 40785 | return error_node(); 40786 | 40787 | exprtk_debug(("((v0 o0 (v1 o1 c)) o2 v1)\n")); 40788 | 40789 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2); 40790 | } 40791 | 40792 | static inline std::string id(expression_generator<Type>& expr_gen, 40793 | const details::operator_type o0, 40794 | const details::operator_type o1, 40795 | const details::operator_type o2) 40796 | { 40797 | return details::build_string() 40798 | << "(t" << expr_gen.to_str(o0) 40799 | << "(t" << expr_gen.to_str(o1) 40800 | << "t)" << expr_gen.to_str(o2) 40801 | << "t" 40802 | } 40803 | }; 40804 | 40805 | struct synthesize_vocovov_expression4 40806 | { 40807 | typedef typename vocovov_t::type4 node_type; 40808 | typedef typename vocovov_t::sf4_type sf4_type; 40809 | typedef typename node_type::T0 T0; 40810 | typedef typename node_type::T1 T1; 40811 | typedef typename node_type::T2 T2; 40812 | typedef typename node_type::T3 T3; 40813 | 40814 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40815 | const details::operator_type& operation, 40816 | expression_node_ptr (&branch)[2]) 40817 | { 40818 | // ((v0 o0 (c o1 v1)) o2 v2) 40819 | typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t; 40820 | 40821 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]); 40822 | const Type& v0 = vocov->t0(); 40823 | const Type c = vocov->t1(); 40824 | const Type& v1 = vocov->t2(); 40825 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40826 | const details::operator_type o0 = expr_gen.get_operator(vocov->f0()); 40827 | const details::operator_type o1 = expr_gen.get_operator(vocov->f1()); 40828 | const details::operator_type o2 = operation; 40829 | 40830 | binary_functor_t f0 = vocov->f0(); 40831 | binary_functor_t f1 = vocov->f1(); 40832 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40833 | 40834 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40835 | expression_node_ptr result = error_node(); 40836 | 40837 | const bool synthesis_result = 40838 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40839 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result); 40840 | 40841 | if (synthesis_result) 40842 | return result; 40843 | else if (!expr_gen.valid_operator(o2,f2)) 40844 | return error_node(); 40845 | 40846 | exprtk_debug(("((v0 o0 (c o1 v1)) o2 v2)\n")); 40847 | 40848 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2); 40849 | } 40850 | 40851 | static inline std::string id(expression_generator<Type>& expr_gen, 40852 | const details::operator_type o0, 40853 | const details::operator_type o1, 40854 | const details::operator_type o2) 40855 | { 40856 | return details::build_string() 40857 | << "(t" << expr_gen.to_str(o0) 40858 | << "(t" << expr_gen.to_str(o1) 40859 | << "t)" << expr_gen.to_str(o2) 40860 | << "t" 40861 | } 40862 | }; 40863 | 40864 | struct synthesize_covovov_expression4 40865 | { 40866 | typedef typename covovov_t::type4 node_type; 40867 | typedef typename covovov_t::sf4_type sf4_type; 40868 | typedef typename node_type::T0 T0; 40869 | typedef typename node_type::T1 T1; 40870 | typedef typename node_type::T2 T2; 40871 | typedef typename node_type::T3 T3; 40872 | 40873 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40874 | const details::operator_type& operation, 40875 | expression_node_ptr (&branch)[2]) 40876 | { 40877 | // ((c o0 (v0 o1 v1)) o2 v2) 40878 | typedef typename synthesize_covov_expression1::node_type lcl_covov_t; 40879 | 40880 | const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]); 40881 | const Type c = covov->t0(); 40882 | const Type& v0 = covov->t1(); 40883 | const Type& v1 = covov->t2(); 40884 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40885 | const details::operator_type o0 = expr_gen.get_operator(covov->f0()); 40886 | const details::operator_type o1 = expr_gen.get_operator(covov->f1()); 40887 | const details::operator_type o2 = operation; 40888 | 40889 | binary_functor_t f0 = covov->f0(); 40890 | binary_functor_t f1 = covov->f1(); 40891 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40892 | 40893 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40894 | 40895 | expression_node_ptr result = error_node(); 40896 | 40897 | const bool synthesis_result = 40898 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40899 | (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result); 40900 | 40901 | if (synthesis_result) 40902 | return result; 40903 | else if (!expr_gen.valid_operator(o2,f2)) 40904 | return error_node(); 40905 | 40906 | exprtk_debug(("((c o0 (v0 o1 v1)) o2 v2)\n")); 40907 | 40908 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2); 40909 | } 40910 | 40911 | static inline std::string id(expression_generator<Type>& expr_gen, 40912 | const details::operator_type o0, 40913 | const details::operator_type o1, 40914 | const details::operator_type o2) 40915 | { 40916 | return details::build_string() 40917 | << "(t" << expr_gen.to_str(o0) 40918 | << "(t" << expr_gen.to_str(o1) 40919 | << "t)" << expr_gen.to_str(o2) 40920 | << "t" 40921 | } 40922 | }; 40923 | 40924 | struct synthesize_covocov_expression4 40925 | { 40926 | typedef typename covocov_t::type4 node_type; 40927 | typedef typename covocov_t::sf4_type sf4_type; 40928 | typedef typename node_type::T0 T0; 40929 | typedef typename node_type::T1 T1; 40930 | typedef typename node_type::T2 T2; 40931 | typedef typename node_type::T3 T3; 40932 | 40933 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40934 | const details::operator_type& operation, 40935 | expression_node_ptr (&branch)[2]) 40936 | { 40937 | // ((c0 o0 (v0 o1 c1)) o2 v1) 40938 | typedef typename synthesize_covoc_expression1::node_type lcl_covoc_t; 40939 | 40940 | const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[0]); 40941 | const Type c0 = covoc->t0(); 40942 | const Type& v0 = covoc->t1(); 40943 | const Type c1 = covoc->t2(); 40944 | const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40945 | const details::operator_type o0 = expr_gen.get_operator(covoc->f0()); 40946 | const details::operator_type o1 = expr_gen.get_operator(covoc->f1()); 40947 | const details::operator_type o2 = operation; 40948 | 40949 | binary_functor_t f0 = covoc->f0(); 40950 | binary_functor_t f1 = covoc->f1(); 40951 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40952 | 40953 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40954 | 40955 | expression_node_ptr result = error_node(); 40956 | 40957 | const bool synthesis_result = 40958 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40959 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result); 40960 | 40961 | if (synthesis_result) 40962 | return result; 40963 | else if (!expr_gen.valid_operator(o2,f2)) 40964 | return error_node(); 40965 | 40966 | exprtk_debug(("((c0 o0 (v0 o1 c1)) o2 v1)\n")); 40967 | 40968 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2); 40969 | } 40970 | 40971 | static inline std::string id(expression_generator<Type>& expr_gen, 40972 | const details::operator_type o0, 40973 | const details::operator_type o1, 40974 | const details::operator_type o2) 40975 | { 40976 | return details::build_string() 40977 | << "(t" << expr_gen.to_str(o0) 40978 | << "(t" << expr_gen.to_str(o1) 40979 | << "t)" << expr_gen.to_str(o2) 40980 | << "t" 40981 | } 40982 | }; 40983 | 40984 | struct synthesize_vocovoc_expression4 40985 | { 40986 | typedef typename vocovoc_t::type4 node_type; 40987 | typedef typename vocovoc_t::sf4_type sf4_type; 40988 | typedef typename node_type::T0 T0; 40989 | typedef typename node_type::T1 T1; 40990 | typedef typename node_type::T2 T2; 40991 | typedef typename node_type::T3 T3; 40992 | 40993 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40994 | const details::operator_type& operation, 40995 | expression_node_ptr (&branch)[2]) 40996 | { 40997 | // ((v0 o0 (c0 o1 v1)) o2 c1) 40998 | typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t; 40999 | 41000 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]); 41001 | const Type& v0 = vocov->t0(); 41002 | const Type c0 = vocov->t1(); 41003 | const Type& v1 = vocov->t2(); 41004 | const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); 41005 | const details::operator_type o0 = expr_gen.get_operator(vocov->f0()); 41006 | const details::operator_type o1 = expr_gen.get_operator(vocov->f1()); 41007 | const details::operator_type o2 = operation; 41008 | 41009 | binary_functor_t f0 = vocov->f0(); 41010 | binary_functor_t f1 = vocov->f1(); 41011 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 41012 | 41013 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 41014 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 41015 | 41016 | expression_node_ptr result = error_node(); 41017 | 41018 | const bool synthesis_result = 41019 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 41020 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result); 41021 | 41022 | if (synthesis_result) 41023 | return result; 41024 | else if (!expr_gen.valid_operator(o2,f2)) 41025 | return error_node(); 41026 | 41027 | exprtk_debug(("((v0 o0 (c0 o1 v1)) o2 c1)\n")); 41028 | 41029 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2); 41030 | } 41031 | 41032 | static inline std::string id(expression_generator<Type>& expr_gen, 41033 | const details::operator_type o0, 41034 | const details::operator_type o1, 41035 | const details::operator_type o2) 41036 | { 41037 | return details::build_string() 41038 | << "(t" << expr_gen.to_str(o0) 41039 | << "(t" << expr_gen.to_str(o1) 41040 | << "t)" << expr_gen.to_str(o2) 41041 | << "t" 41042 | } 41043 | }; 41044 | 41045 | struct synthesize_covovoc_expression4 41046 | { 41047 | typedef typename covovoc_t::type4 node_type; 41048 | typedef typename covovoc_t::sf4_type sf4_type; 41049 | typedef typename node_type::T0 T0; 41050 | typedef typename node_type::T1 T1; 41051 | typedef typename node_type::T2 T2; 41052 | typedef typename node_type::T3 T3; 41053 | 41054 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 41055 | const details::operator_type& operation, 41056 | expression_node_ptr (&branch)[2]) 41057 | { 41058 | // ((c0 o0 (v0 o1 v1)) o2 c1) 41059 | typedef typename synthesize_covov_expression1::node_type lcl_covov_t; 41060 | 41061 | const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]); 41062 | const Type c0 = covov->t0(); 41063 | const Type& v0 = covov->t1(); 41064 | const Type& v1 = covov->t2(); 41065 | const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); 41066 | const details::operator_type o0 = expr_gen.get_operator(covov->f0()); 41067 | const details::operator_type o1 = expr_gen.get_operator(covov->f1()); 41068 | const details::operator_type o2 = operation; 41069 | 41070 | binary_functor_t f0 = covov->f0(); 41071 | binary_functor_t f1 = covov->f1(); 41072 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 41073 | 41074 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 41075 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 41076 | 41077 | expression_node_ptr result = error_node(); 41078 | 41079 | const bool synthesis_result = 41080 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 41081 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result); 41082 | 41083 | if (synthesis_result) 41084 | return result; 41085 | else if (!expr_gen.valid_operator(o2,f2)) 41086 | return error_node(); 41087 | 41088 | exprtk_debug(("((c0 o0 (v0 o1 v1)) o2 c1)\n")); 41089 | 41090 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2); 41091 | } 41092 | 41093 | static inline std::string id(expression_generator<Type>& expr_gen, 41094 | const details::operator_type o0, 41095 | const details::operator_type o1, 41096 | const details::operator_type o2) 41097 | { 41098 | return details::build_string() 41099 | << "(t" << expr_gen.to_str(o0) 41100 | << "(t" << expr_gen.to_str(o1) 41101 | << "t)" << expr_gen.to_str(o2) 41102 | << "t" 41103 | } 41104 | }; 41105 | 41106 | struct synthesize_vococov_expression4 41107 | { 41108 | typedef typename vococov_t::type4 node_type; 41109 | static inline expression_node_ptr process(expression_generator<Type>&, 41110 | const details::operator_type&, 41111 | expression_node_ptr (&)[2]) 41112 | { 41113 | // ((v0 o0 (c0 o1 c1)) o2 v1) - Not possible 41114 | exprtk_debug(("((v0 o0 (c0 o1 c1)) o2 v1) - Not possible\n")); 41115 | return error_node(); 41116 | } 41117 | 41118 | static inline std::string id(expression_generator<Type>&, 41119 | const details::operator_type, 41120 | const details::operator_type, 41121 | const details::operator_type) 41122 | { 41123 | return "INVALID" 41124 | } 41125 | }; 41126 | #endif 41127 | 41128 | inline expression_node_ptr synthesize_uvouv_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2]) 41129 | { 41130 | // Definition: uv o uv 41131 | details::operator_type o0 = static_cast<details::uv_base_node<Type>*>(branch[0])->operation(); 41132 | details::operator_type o1 = static_cast<details::uv_base_node<Type>*>(branch[1])->operation(); 41133 | const Type& v0 = static_cast<details::uv_base_node<Type>*>(branch[0])->v(); 41134 | const Type& v1 = static_cast<details::uv_base_node<Type>*>(branch[1])->v(); 41135 | unary_functor_t u0 = reinterpret_cast<unary_functor_t> (0); 41136 | unary_functor_t u1 = reinterpret_cast<unary_functor_t> (0); 41137 | binary_functor_t f = reinterpret_cast<binary_functor_t>(0); 41138 | 41139 | if (!valid_operator(o0,u0)) 41140 | return error_node(); 41141 | else if (!valid_operator(o1,u1)) 41142 | return error_node(); 41143 | else if (!valid_operator(operation,f)) 41144 | return error_node(); 41145 | 41146 | expression_node_ptr result = error_node(); 41147 | 41148 | if ( 41149 | (details::e_neg == o0) && 41150 | (details::e_neg == o1) 41151 | ) 41152 | { 41153 | switch (operation) 41154 | { 41155 | // (-v0 + -v1) --> -(v0 + v1) 41156 | case details::e_add : result = (*this)(details::e_neg, 41157 | node_allocator_-> 41158 | allocate_rr<typename details:: 41159 | vov_node<Type,details::add_op<Type> > >(v0, v1)); 41160 | exprtk_debug(("(-v0 + -v1) --> -(v0 + v1)\n")); 41161 | break; 41162 | 41163 | // (-v0 - -v1) --> (v1 - v0) 41164 | case details::e_sub : result = node_allocator_-> 41165 | allocate_rr<typename details:: 41166 | vov_node<Type,details::sub_op<Type> > >(v1, v0); 41167 | exprtk_debug(("(-v0 - -v1) --> (v1 - v0)\n")); 41168 | break; 41169 | 41170 | // (-v0 * -v1) --> (v0 * v1) 41171 | case details::e_mul : result = node_allocator_-> 41172 | allocate_rr<typename details:: 41173 | vov_node<Type,details::mul_op<Type> > >(v0, v1); 41174 | exprtk_debug(("(-v0 * -v1) --> (v0 * v1)\n")); 41175 | break; 41176 | 41177 | // (-v0 / -v1) --> (v0 / v1) 41178 | case details::e_div : result = node_allocator_-> 41179 | allocate_rr<typename details:: 41180 | vov_node<Type,details::div_op<Type> > >(v0, v1); 41181 | exprtk_debug(("(-v0 / -v1) --> (v0 / v1)\n")); 41182 | break; 41183 | 41184 | default : break; 41185 | } 41186 | } 41187 | 41188 | if (0 == result) 41189 | { 41190 | result = node_allocator_-> 41191 | allocate_rrrrr<typename details::uvouv_node<Type> >(v0, v1, u0, u1, f); 41192 | } 41193 | 41194 | details::free_all_nodes(*node_allocator_,branch); 41195 | return result; 41196 | } 41197 | 41198 | #undef basic_opr_switch_statements 41199 | #undef extended_opr_switch_statements 41200 | #undef unary_opr_switch_statements 41201 | 41202 | #ifndef exprtk_disable_string_capabilities 41203 | 41204 | #define string_opr_switch_statements \ 41205 | case_stmt(details::e_lt , details::lt_op ) \ 41206 | case_stmt(details::e_lte , details::lte_op ) \ 41207 | case_stmt(details::e_gt , details::gt_op ) \ 41208 | case_stmt(details::e_gte , details::gte_op ) \ 41209 | case_stmt(details::e_eq , details::eq_op ) \ 41210 | case_stmt(details::e_ne , details::ne_op ) \ 41211 | case_stmt(details::e_in , details::in_op ) \ 41212 | case_stmt(details::e_like , details::like_op ) \ 41213 | case_stmt(details::e_ilike , details::ilike_op) \ 41214 | 41215 | template <typename T0, typename T1> 41216 | inline expression_node_ptr synthesize_str_xrox_expression_impl(const details::operator_type& opr, 41217 | T0 s0, T1 s1, 41218 | range_t rp0) 41219 | { 41220 | switch (opr) 41221 | { 41222 | #define case_stmt(op0, op1) \ 41223 | case op0 : return node_allocator_-> \ 41224 | allocate_ttt<typename details::str_xrox_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \ 41225 | (s0, s1, rp0); \ 41226 | 41227 | string_opr_switch_statements 41228 | #undef case_stmt 41229 | default : return error_node(); 41230 | } 41231 | } 41232 | 41233 | template <typename T0, typename T1> 41234 | inline expression_node_ptr synthesize_str_xoxr_expression_impl(const details::operator_type& opr, 41235 | T0 s0, T1 s1, 41236 | range_t rp1) 41237 | { 41238 | switch (opr) 41239 | { 41240 | #define case_stmt(op0, op1) \ 41241 | case op0 : return node_allocator_-> \ 41242 | allocate_ttt<typename details::str_xoxr_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \ 41243 | (s0, s1, rp1); \ 41244 | 41245 | string_opr_switch_statements 41246 | #undef case_stmt 41247 | default : return error_node(); 41248 | } 41249 | } 41250 | 41251 | template <typename T0, typename T1> 41252 | inline expression_node_ptr synthesize_str_xroxr_expression_impl(const details::operator_type& opr, 41253 | T0 s0, T1 s1, 41254 | range_t rp0, range_t rp1) 41255 | { 41256 | switch (opr) 41257 | { 41258 | #define case_stmt(op0, op1) \ 41259 | case op0 : return node_allocator_-> \ 41260 | allocate_tttt<typename details::str_xroxr_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \ 41261 | (s0, s1, rp0, rp1); \ 41262 | 41263 | string_opr_switch_statements 41264 | #undef case_stmt 41265 | default : return error_node(); 41266 | } 41267 | } 41268 | 41269 | template <typename T0, typename T1> 41270 | inline expression_node_ptr synthesize_sos_expression_impl(const details::operator_type& opr, T0 s0, T1 s1) 41271 | { 41272 | switch (opr) 41273 | { 41274 | #define case_stmt(op0, op1) \ 41275 | case op0 : return node_allocator_-> \ 41276 | allocate_tt<typename details::sos_node<Type,T0,T1,op1<Type> >,T0,T1>(s0, s1); \ 41277 | 41278 | string_opr_switch_statements 41279 | #undef case_stmt 41280 | default : return error_node(); 41281 | } 41282 | } 41283 | 41284 | inline expression_node_ptr synthesize_sos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41285 | { 41286 | std::string& s0 = static_cast<details::stringvar_node<Type>*>(branch[0])->ref(); 41287 | std::string& s1 = static_cast<details::stringvar_node<Type>*>(branch[1])->ref(); 41288 | 41289 | return synthesize_sos_expression_impl<std::string&,std::string&>(opr, s0, s1); 41290 | } 41291 | 41292 | inline expression_node_ptr synthesize_sros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41293 | { 41294 | std::string& s0 = static_cast<details::string_range_node<Type>*>(branch[0])->ref (); 41295 | std::string& s1 = static_cast<details::stringvar_node<Type>*> (branch[1])->ref (); 41296 | range_t rp0 = static_cast<details::string_range_node<Type>*>(branch[0])->range(); 41297 | 41298 | static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear(); 41299 | 41300 | details::free_node(*node_allocator_,branch[0]); 41301 | 41302 | return synthesize_str_xrox_expression_impl<std::string&,std::string&>(opr, s0, s1, rp0); 41303 | } 41304 | 41305 | inline expression_node_ptr synthesize_sosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41306 | { 41307 | std::string& s0 = static_cast<details::stringvar_node<Type>*> (branch[0])->ref (); 41308 | std::string& s1 = static_cast<details::string_range_node<Type>*>(branch[1])->ref (); 41309 | range_t rp1 = static_cast<details::string_range_node<Type>*>(branch[1])->range(); 41310 | 41311 | static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear(); 41312 | 41313 | details::free_node(*node_allocator_,branch[1]); 41314 | 41315 | return synthesize_str_xoxr_expression_impl<std::string&,std::string&>(opr, s0, s1, rp1); 41316 | } 41317 | 41318 | inline expression_node_ptr synthesize_socsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41319 | { 41320 | std::string& s0 = static_cast<details::stringvar_node<Type>*> (branch[0])->ref (); 41321 | std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str (); 41322 | range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range(); 41323 | 41324 | static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear(); 41325 | 41326 | details::free_node(*node_allocator_,branch[1]); 41327 | 41328 | return synthesize_str_xoxr_expression_impl<std::string&, const std::string>(opr, s0, s1, rp1); 41329 | } 41330 | 41331 | inline expression_node_ptr synthesize_srosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41332 | { 41333 | std::string& s0 = static_cast<details::string_range_node<Type>*>(branch[0])->ref (); 41334 | std::string& s1 = static_cast<details::string_range_node<Type>*>(branch[1])->ref (); 41335 | range_t rp0 = static_cast<details::string_range_node<Type>*>(branch[0])->range(); 41336 | range_t rp1 = static_cast<details::string_range_node<Type>*>(branch[1])->range(); 41337 | 41338 | static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear(); 41339 | static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear(); 41340 | 41341 | details::free_node(*node_allocator_,branch[0]); 41342 | details::free_node(*node_allocator_,branch[1]); 41343 | 41344 | return synthesize_str_xroxr_expression_impl<std::string&,std::string&>(opr, s0, s1, rp0, rp1); 41345 | } 41346 | 41347 | inline expression_node_ptr synthesize_socs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41348 | { 41349 | std::string& s0 = static_cast< details::stringvar_node<Type>*>(branch[0])->ref(); 41350 | std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str(); 41351 | 41352 | details::free_node(*node_allocator_,branch[1]); 41353 | 41354 | return synthesize_sos_expression_impl<std::string&, const std::string>(opr, s0, s1); 41355 | } 41356 | 41357 | inline expression_node_ptr synthesize_csos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41358 | { 41359 | std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str(); 41360 | std::string& s1 = static_cast<details::stringvar_node<Type>* >(branch[1])->ref(); 41361 | 41362 | details::free_node(*node_allocator_,branch[0]); 41363 | 41364 | return synthesize_sos_expression_impl<const std::string,std::string&>(opr, s0, s1); 41365 | } 41366 | 41367 | inline expression_node_ptr synthesize_csosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41368 | { 41369 | std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str (); 41370 | std::string& s1 = static_cast<details::string_range_node<Type>* >(branch[1])->ref (); 41371 | range_t rp1 = static_cast<details::string_range_node<Type>* >(branch[1])->range(); 41372 | 41373 | static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear(); 41374 | 41375 | details::free_node(*node_allocator_,branch[0]); 41376 | details::free_node(*node_allocator_,branch[1]); 41377 | 41378 | return synthesize_str_xoxr_expression_impl<const std::string,std::string&>(opr, s0, s1, rp1); 41379 | } 41380 | 41381 | inline expression_node_ptr synthesize_srocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41382 | { 41383 | std::string& s0 = static_cast<details::string_range_node<Type>* >(branch[0])->ref (); 41384 | std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str (); 41385 | range_t rp0 = static_cast<details::string_range_node<Type>* >(branch[0])->range(); 41386 | 41387 | static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear(); 41388 | 41389 | details::free_node(*node_allocator_,branch[0]); 41390 | details::free_node(*node_allocator_,branch[1]); 41391 | 41392 | return synthesize_str_xrox_expression_impl<std::string&, const std::string>(opr, s0, s1, rp0); 41393 | } 41394 | 41395 | inline expression_node_ptr synthesize_srocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41396 | { 41397 | std::string& s0 = static_cast<details::string_range_node<Type>* >(branch[0])->ref (); 41398 | std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str (); 41399 | range_t rp0 = static_cast<details::string_range_node<Type>* >(branch[0])->range(); 41400 | range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range(); 41401 | 41402 | static_cast<details::string_range_node<Type>*> (branch[0])->range_ref().clear(); 41403 | static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear(); 41404 | 41405 | details::free_node(*node_allocator_,branch[0]); 41406 | details::free_node(*node_allocator_,branch[1]); 41407 | 41408 | return synthesize_str_xroxr_expression_impl<std::string&, const std::string>(opr, s0, s1, rp0, rp1); 41409 | } 41410 | 41411 | inline expression_node_ptr synthesize_csocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41412 | { 41413 | const std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str(); 41414 | const std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str(); 41415 | 41416 | expression_node_ptr result = error_node(); 41417 | 41418 | if (details::e_add == opr) 41419 | result = node_allocator_->allocate_c<details::string_literal_node<Type> >(s0 + s1); 41420 | else if (details::e_in == opr) 41421 | result = node_allocator_->allocate_c<details::literal_node<Type> >(details::in_op <Type>::process(s0,s1)); 41422 | else if (details::e_like == opr) 41423 | result = node_allocator_->allocate_c<details::literal_node<Type> >(details::like_op <Type>::process(s0,s1)); 41424 | else if (details::e_ilike == opr) 41425 | result = node_allocator_->allocate_c<details::literal_node<Type> >(details::ilike_op<Type>::process(s0,s1)); 41426 | else 41427 | { 41428 | expression_node_ptr temp = synthesize_sos_expression_impl<const std::string, const std::string>(opr, s0, s1); 41429 | 41430 | const Type v = temp->value(); 41431 | 41432 | details::free_node(*node_allocator_,temp); 41433 | 41434 | result = node_allocator_->allocate<literal_node_t>(v); 41435 | } 41436 | 41437 | details::free_all_nodes(*node_allocator_,branch); 41438 | 41439 | return result; 41440 | } 41441 | 41442 | inline expression_node_ptr synthesize_csocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41443 | { 41444 | const std::string s0 = static_cast<details::string_literal_node<Type>* >(branch[0])->str (); 41445 | std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str (); 41446 | range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range(); 41447 | 41448 | static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear(); 41449 | 41450 | details::free_node(*node_allocator_,branch[0]); 41451 | details::free_node(*node_allocator_,branch[1]); 41452 | 41453 | return synthesize_str_xoxr_expression_impl<const std::string, const std::string>(opr, s0, s1, rp1); 41454 | } 41455 | 41456 | inline expression_node_ptr synthesize_csros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41457 | { 41458 | std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str (); 41459 | std::string& s1 = static_cast<details::stringvar_node<Type>* >(branch[1])->ref (); 41460 | range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range(); 41461 | 41462 | static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear(); 41463 | 41464 | details::free_node(*node_allocator_,branch[0]); 41465 | 41466 | return synthesize_str_xrox_expression_impl<const std::string,std::string&>(opr, s0, s1, rp0); 41467 | } 41468 | 41469 | inline expression_node_ptr synthesize_csrosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41470 | { 41471 | const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str (); 41472 | std::string& s1 = static_cast<details::string_range_node<Type>* >(branch[1])->ref (); 41473 | const range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range(); 41474 | const range_t rp1 = static_cast<details::string_range_node<Type>* >(branch[1])->range(); 41475 | 41476 | static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear(); 41477 | static_cast<details::string_range_node<Type>*> (branch[1])->range_ref().clear(); 41478 | 41479 | details::free_node(*node_allocator_,branch[0]); 41480 | details::free_node(*node_allocator_,branch[1]); 41481 | 41482 | return synthesize_str_xroxr_expression_impl<const std::string,std::string&>(opr, s0, s1, rp0, rp1); 41483 | } 41484 | 41485 | inline expression_node_ptr synthesize_csrocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41486 | { 41487 | const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str (); 41488 | const std::string s1 = static_cast<details::string_literal_node<Type>* >(branch[1])->str (); 41489 | const range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range(); 41490 | 41491 | static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear(); 41492 | 41493 | details::free_all_nodes(*node_allocator_,branch); 41494 | 41495 | return synthesize_str_xrox_expression_impl<const std::string,std::string>(opr, s0, s1, rp0); 41496 | } 41497 | 41498 | inline expression_node_ptr synthesize_csrocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41499 | { 41500 | const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str (); 41501 | const std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str (); 41502 | const range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range(); 41503 | const range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range(); 41504 | 41505 | static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear(); 41506 | static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear(); 41507 | 41508 | details::free_all_nodes(*node_allocator_,branch); 41509 | 41510 | return synthesize_str_xroxr_expression_impl<const std::string, const std::string>(opr, s0, s1, rp0, rp1); 41511 | } 41512 | 41513 | inline expression_node_ptr synthesize_strogen_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41514 | { 41515 | switch (opr) 41516 | { 41517 | #define case_stmt(op0, op1) \ 41518 | case op0 : return node_allocator_-> \ 41519 | allocate_ttt<typename details::str_sogens_node<Type,op1<Type> > > \ 41520 | (opr, branch[0], branch[1]); \ 41521 | 41522 | string_opr_switch_statements 41523 | #undef case_stmt 41524 | default : return error_node(); 41525 | } 41526 | } 41527 | 41528 | #undef string_opr_switch_statements 41529 | #endif 41530 | 41531 | #ifndef exprtk_disable_string_capabilities 41532 | inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41533 | { 41534 | if ((0 == branch[0]) || (0 == branch[1])) 41535 | { 41536 | details::free_all_nodes(*node_allocator_,branch); 41537 | 41538 | return error_node(); 41539 | } 41540 | 41541 | const bool b0_is_s = details::is_string_node (branch[0]); 41542 | const bool b0_is_cs = details::is_const_string_node (branch[0]); 41543 | const bool b0_is_sr = details::is_string_range_node (branch[0]); 41544 | const bool b0_is_csr = details::is_const_string_range_node(branch[0]); 41545 | 41546 | const bool b1_is_s = details::is_string_node (branch[1]); 41547 | const bool b1_is_cs = details::is_const_string_node (branch[1]); 41548 | const bool b1_is_sr = details::is_string_range_node (branch[1]); 41549 | const bool b1_is_csr = details::is_const_string_range_node(branch[1]); 41550 | 41551 | const bool b0_is_gen = details::is_string_assignment_node (branch[0]) || 41552 | details::is_genricstring_range_node(branch[0]) || 41553 | details::is_string_concat_node (branch[0]) || 41554 | details::is_string_function_node (branch[0]) || 41555 | details::is_string_condition_node (branch[0]) || 41556 | details::is_string_ccondition_node (branch[0]) || 41557 | details::is_string_vararg_node (branch[0]) ; 41558 | 41559 | const bool b1_is_gen = details::is_string_assignment_node (branch[1]) || 41560 | details::is_genricstring_range_node(branch[1]) || 41561 | details::is_string_concat_node (branch[1]) || 41562 | details::is_string_function_node (branch[1]) || 41563 | details::is_string_condition_node (branch[1]) || 41564 | details::is_string_ccondition_node (branch[1]) || 41565 | details::is_string_vararg_node (branch[1]) ; 41566 | 41567 | if (details::e_add == opr) 41568 | { 41569 | if (!b0_is_cs || !b1_is_cs) 41570 | { 41571 | return synthesize_expression<string_concat_node_t,2>(opr,branch); 41572 | } 41573 | } 41574 | 41575 | if (b0_is_gen || b1_is_gen) 41576 | { 41577 | return synthesize_strogen_expression(opr,branch); 41578 | } 41579 | else if (b0_is_s) 41580 | { 41581 | if (b1_is_s ) return synthesize_sos_expression (opr,branch); 41582 | else if (b1_is_cs ) return synthesize_socs_expression (opr,branch); 41583 | else if (b1_is_sr ) return synthesize_sosr_expression (opr,branch); 41584 | else if (b1_is_csr) return synthesize_socsr_expression (opr,branch); 41585 | } 41586 | else if (b0_is_cs) 41587 | { 41588 | if (b1_is_s ) return synthesize_csos_expression (opr,branch); 41589 | else if (b1_is_cs ) return synthesize_csocs_expression (opr,branch); 41590 | else if (b1_is_sr ) return synthesize_csosr_expression (opr,branch); 41591 | else if (b1_is_csr) return synthesize_csocsr_expression(opr,branch); 41592 | } 41593 | else if (b0_is_sr) 41594 | { 41595 | if (b1_is_s ) return synthesize_sros_expression (opr,branch); 41596 | else if (b1_is_sr ) return synthesize_srosr_expression (opr,branch); 41597 | else if (b1_is_cs ) return synthesize_srocs_expression (opr,branch); 41598 | else if (b1_is_csr) return synthesize_srocsr_expression(opr,branch); 41599 | } 41600 | else if (b0_is_csr) 41601 | { 41602 | if (b1_is_s ) return synthesize_csros_expression (opr,branch); 41603 | else if (b1_is_sr ) return synthesize_csrosr_expression (opr,branch); 41604 | else if (b1_is_cs ) return synthesize_csrocs_expression (opr,branch); 41605 | else if (b1_is_csr) return synthesize_csrocsr_expression(opr,branch); 41606 | } 41607 | 41608 | return error_node(); 41609 | } 41610 | #else 41611 | inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&branch)[2]) 41612 | { 41613 | details::free_all_nodes(*node_allocator_,branch); 41614 | return error_node(); 41615 | } 41616 | #endif 41617 | 41618 | #ifndef exprtk_disable_string_capabilities 41619 | inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[3]) 41620 | { 41621 | if (details::e_inrange != opr) 41622 | return error_node(); 41623 | else if ((0 == branch[0]) || (0 == branch[1]) || (0 == branch[2])) 41624 | { 41625 | details::free_all_nodes(*node_allocator_,branch); 41626 | 41627 | return error_node(); 41628 | } 41629 | else if ( 41630 | details::is_const_string_node(branch[0]) && 41631 | details::is_const_string_node(branch[1]) && 41632 | details::is_const_string_node(branch[2]) 41633 | ) 41634 | { 41635 | const std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str(); 41636 | const std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str(); 41637 | const std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str(); 41638 | 41639 | const Type v = (((s0 <= s1) && (s1 <= s2)) ? Type(1) : Type(0)); 41640 | 41641 | details::free_all_nodes(*node_allocator_,branch); 41642 | 41643 | return node_allocator_->allocate_c<details::literal_node<Type> >(v); 41644 | } 41645 | else if ( 41646 | details::is_string_node(branch[0]) && 41647 | details::is_string_node(branch[1]) && 41648 | details::is_string_node(branch[2]) 41649 | ) 41650 | { 41651 | std::string& s0 = static_cast<details::stringvar_node<Type>*>(branch[0])->ref(); 41652 | std::string& s1 = static_cast<details::stringvar_node<Type>*>(branch[1])->ref(); 41653 | std::string& s2 = static_cast<details::stringvar_node<Type>*>(branch[2])->ref(); 41654 | 41655 | typedef typename details::sosos_node<Type, std::string&, std::string&, std::string&, details::inrange_op<Type> > inrange_t; 41656 | 41657 | return node_allocator_->allocate_type<inrange_t, std::string&, std::string&, std::string&>(s0, s1, s2); 41658 | } 41659 | else if ( 41660 | details::is_const_string_node(branch[0]) && 41661 | details::is_string_node(branch[1]) && 41662 | details::is_const_string_node(branch[2]) 41663 | ) 41664 | { 41665 | std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str(); 41666 | std::string& s1 = static_cast<details::stringvar_node<Type>* >(branch[1])->ref(); 41667 | std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str(); 41668 | 41669 | typedef typename details::sosos_node<Type, std::string, std::string&, std::string, details::inrange_op<Type> > inrange_t; 41670 | 41671 | details::free_node(*node_allocator_,branch[0]); 41672 | details::free_node(*node_allocator_,branch[2]); 41673 | 41674 | return node_allocator_->allocate_type<inrange_t, std::string, std::string&, std::string>(s0, s1, s2); 41675 | } 41676 | else if ( 41677 | details::is_string_node(branch[0]) && 41678 | details::is_const_string_node(branch[1]) && 41679 | details::is_string_node(branch[2]) 41680 | ) 41681 | { 41682 | std::string& s0 = static_cast<details::stringvar_node<Type>* >(branch[0])->ref(); 41683 | std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str(); 41684 | std::string& s2 = static_cast<details::stringvar_node<Type>* >(branch[2])->ref(); 41685 | 41686 | typedef typename details::sosos_node<Type, std::string&, std::string, std::string&, details::inrange_op<Type> > inrange_t; 41687 | 41688 | details::free_node(*node_allocator_,branch[1]); 41689 | 41690 | return node_allocator_->allocate_type<inrange_t, std::string&, std::string, std::string&>(s0, s1, s2); 41691 | } 41692 | else if ( 41693 | details::is_string_node(branch[0]) && 41694 | details::is_string_node(branch[1]) && 41695 | details::is_const_string_node(branch[2]) 41696 | ) 41697 | { 41698 | std::string& s0 = static_cast<details::stringvar_node<Type>* >(branch[0])->ref(); 41699 | std::string& s1 = static_cast<details::stringvar_node<Type>* >(branch[1])->ref(); 41700 | std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str(); 41701 | 41702 | typedef typename details::sosos_node<Type, std::string&, std::string&, std::string, details::inrange_op<Type> > inrange_t; 41703 | 41704 | details::free_node(*node_allocator_,branch[2]); 41705 | 41706 | return node_allocator_->allocate_type<inrange_t, std::string&, std::string&, std::string>(s0, s1, s2); 41707 | } 41708 | else if ( 41709 | details::is_const_string_node(branch[0]) && 41710 | details:: is_string_node(branch[1]) && 41711 | details:: is_string_node(branch[2]) 41712 | ) 41713 | { 41714 | std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str(); 41715 | std::string& s1 = static_cast<details::stringvar_node<Type>* >(branch[1])->ref(); 41716 | std::string& s2 = static_cast<details::stringvar_node<Type>* >(branch[2])->ref(); 41717 | 41718 | typedef typename details::sosos_node<Type, std::string, std::string&, std::string&, details::inrange_op<Type> > inrange_t; 41719 | 41720 | details::free_node(*node_allocator_,branch[0]); 41721 | 41722 | return node_allocator_->allocate_type<inrange_t, std::string, std::string&, std::string&>(s0, s1, s2); 41723 | } 41724 | else 41725 | { 41726 | details::free_all_nodes(*node_allocator_,branch); 41727 | return error_node(); 41728 | } 41729 | } 41730 | #else 41731 | inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&branch)[3]) 41732 | { 41733 | details::free_all_nodes(*node_allocator_,branch); 41734 | return error_node(); 41735 | } 41736 | #endif 41737 | 41738 | inline expression_node_ptr synthesize_null_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2]) 41739 | { 41740 | /* 41741 | Note: The following are the type promotion rules 41742 | that relate to operations that include 'null': 41743 | 0. null ==/!= null --> true false 41744 | 1. null operation null --> null 41745 | 2. x ==/!= null --> true/false 41746 | 3. null ==/!= x --> true/false 41747 | 4. x operation null --> x 41748 | 5. null operation x --> x 41749 | */ 41750 | 41751 | typedef typename details::null_eq_node<T> nulleq_node_t; 41752 | 41753 | const bool b0_null = details::is_null_node(branch[0]); 41754 | const bool b1_null = details::is_null_node(branch[1]); 41755 | 41756 | if (b0_null && b1_null) 41757 | { 41758 | expression_node_ptr result = error_node(); 41759 | 41760 | if (details::e_eq == operation) 41761 | result = node_allocator_->allocate_c<literal_node_t>(T(1)); 41762 | else if (details::e_ne == operation) 41763 | result = node_allocator_->allocate_c<literal_node_t>(T(0)); 41764 | 41765 | if (result) 41766 | { 41767 | details::free_node(*node_allocator_,branch[0]); 41768 | details::free_node(*node_allocator_,branch[1]); 41769 | 41770 | return result; 41771 | } 41772 | 41773 | details::free_node(*node_allocator_,branch[1]); 41774 | 41775 | return branch[0]; 41776 | } 41777 | else if (details::e_eq == operation) 41778 | { 41779 | expression_node_ptr result = node_allocator_-> 41780 | allocate_rc<nulleq_node_t>(branch[b0_null ? 0 : 1],true); 41781 | 41782 | details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]); 41783 | 41784 | return result; 41785 | } 41786 | else if (details::e_ne == operation) 41787 | { 41788 | expression_node_ptr result = node_allocator_-> 41789 | allocate_rc<nulleq_node_t>(branch[b0_null ? 0 : 1],false); 41790 | 41791 | details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]); 41792 | 41793 | return result; 41794 | } 41795 | else if (b0_null) 41796 | { 41797 | details::free_node(*node_allocator_,branch[0]); 41798 | branch[0] = branch[1]; 41799 | branch[1] = error_node(); 41800 | } 41801 | else if (b1_null) 41802 | { 41803 | details::free_node(*node_allocator_,branch[1]); 41804 | branch[1] = error_node(); 41805 | } 41806 | 41807 | if ( 41808 | (details::e_add == operation) || (details::e_sub == operation) || 41809 | (details::e_mul == operation) || (details::e_div == operation) || 41810 | (details::e_mod == operation) || (details::e_pow == operation) 41811 | ) 41812 | { 41813 | return branch[0]; 41814 | } 41815 | 41816 | details::free_node(*node_allocator_, branch[0]); 41817 | 41818 | if ( 41819 | (details::e_lt == operation) || (details::e_lte == operation) || 41820 | (details::e_gt == operation) || (details::e_gte == operation) || 41821 | (details::e_and == operation) || (details::e_nand == operation) || 41822 | (details::e_or == operation) || (details::e_nor == operation) || 41823 | (details::e_xor == operation) || (details::e_xnor == operation) || 41824 | (details::e_in == operation) || (details::e_like == operation) || 41825 | (details::e_ilike == operation) 41826 | ) 41827 | { 41828 | return node_allocator_->allocate_c<literal_node_t>(T(0)); 41829 | } 41830 | 41831 | return node_allocator_->allocate<details::null_node<Type> >(); 41832 | } 41833 | 41834 | template <typename NodeType, std::size_t N> 41835 | inline expression_node_ptr synthesize_expression(const details::operator_type& operation, expression_node_ptr (&branch)[N]) 41836 | { 41837 | if ( 41838 | (details::e_in == operation) || 41839 | (details::e_like == operation) || 41840 | (details::e_ilike == operation) 41841 | ) 41842 | { 41843 | free_all_nodes(*node_allocator_,branch); 41844 | 41845 | return error_node(); 41846 | } 41847 | else if (!details::all_nodes_valid<N>(branch)) 41848 | { 41849 | free_all_nodes(*node_allocator_,branch); 41850 | 41851 | return error_node(); 41852 | } 41853 | else if ((details::e_default != operation)) 41854 | { 41855 | // Attempt simple constant folding optimisation. 41856 | expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(operation,branch); 41857 | 41858 | if (is_constant_foldable<N>(branch)) 41859 | { 41860 | const Type v = expression_point->value(); 41861 | details::free_node(*node_allocator_,expression_point); 41862 | 41863 | return node_allocator_->allocate<literal_node_t>(v); 41864 | } 41865 | 41866 | if (expression_point && expression_point->valid()) 41867 | { 41868 | return expression_point; 41869 | } 41870 | 41871 | parser_->set_error(parser_error::make_error( 41872 | parser_error::e_parser, 41873 | token_t(), 41874 | "ERR283 - Failed to synthesize node: NodeType", 41875 | exprtk_error_location)); 41876 | 41877 | details::free_node(*node_allocator_, expression_point); 41878 | } 41879 | 41880 | return error_node(); 41881 | } 41882 | 41883 | template <typename NodeType, std::size_t N> 41884 | inline expression_node_ptr synthesize_expression(F* f, expression_node_ptr (&branch)[N]) 41885 | { 41886 | if (!details::all_nodes_valid<N>(branch)) 41887 | { 41888 | free_all_nodes(*node_allocator_,branch); 41889 | 41890 | return error_node(); 41891 | } 41892 | 41893 | typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t; 41894 | 41895 | // Attempt simple constant folding optimisation. 41896 | 41897 | expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(f); 41898 | function_N_node_t* func_node_ptr = dynamic_cast<function_N_node_t*>(expression_point); 41899 | 41900 | if (0 == func_node_ptr) 41901 | { 41902 | free_all_nodes(*node_allocator_,branch); 41903 | 41904 | return error_node(); 41905 | } 41906 | else 41907 | func_node_ptr->init_branches(branch); 41908 | 41909 | if (is_constant_foldable<N>(branch) && !f->has_side_effects()) 41910 | { 41911 | Type v = expression_point->value(); 41912 | details::free_node(*node_allocator_,expression_point); 41913 | 41914 | return node_allocator_->allocate<literal_node_t>(v); 41915 | } 41916 | 41917 | parser_->state_.activate_side_effect("synthesize_expression(function<NT,N>)"); 41918 | 41919 | return expression_point; 41920 | } 41921 | 41922 | bool strength_reduction_enabled_; 41923 | details::node_allocator* node_allocator_; 41924 | synthesize_map_t synthesize_map_; 41925 | unary_op_map_t* unary_op_map_; 41926 | binary_op_map_t* binary_op_map_; 41927 | inv_binary_op_map_t* inv_binary_op_map_; 41928 | sf3_map_t* sf3_map_; 41929 | sf4_map_t* sf4_map_; 41930 | parser_t* parser_; 41931 | }; // class expression_generator 41932 | 41933 | inline void set_error(const parser_error::type& error_type) 41934 | { 41935 | error_list_.push_back(error_type); 41936 | } 41937 | 41938 | inline void remove_last_error() 41939 | { 41940 | if (!error_list_.empty()) 41941 | { 41942 | error_list_.pop_back(); 41943 | } 41944 | } 41945 | 41946 | inline void set_synthesis_error(const std::string& synthesis_error_message) 41947 | { 41948 | if (synthesis_error_.empty()) 41949 | { 41950 | synthesis_error_ = synthesis_error_message; 41951 | } 41952 | } 41953 | 41954 | inline void register_local_vars(expression<T>& e) 41955 | { 41956 | for (std::size_t i = 0; i < sem_.size(); ++i) 41957 | { 41958 | scope_element& se = sem_.get_element(i); 41959 | 41960 | exprtk_debug(("register_local_vars() - se[%s]\n", se.name.c_str())); 41961 | 41962 | if ( 41963 | (scope_element::e_variable == se.type) || 41964 | (scope_element::e_literal == se.type) || 41965 | (scope_element::e_vecelem == se.type) 41966 | ) 41967 | { 41968 | if (se.var_node) 41969 | { 41970 | e.register_local_var(se.var_node); 41971 | } 41972 | 41973 | if (se.data) 41974 | { 41975 | e.register_local_data(se.data, 1, 0); 41976 | } 41977 | } 41978 | else if (scope_element::e_vector == se.type) 41979 | { 41980 | if (se.vec_node) 41981 | { 41982 | e.register_local_var(se.vec_node); 41983 | } 41984 | 41985 | if (se.data) 41986 | { 41987 | e.register_local_data(se.data, se.size, 1); 41988 | } 41989 | } 41990 | #ifndef exprtk_disable_string_capabilities 41991 | else if (scope_element::e_string == se.type) 41992 | { 41993 | if (se.str_node) 41994 | { 41995 | e.register_local_var(se.str_node); 41996 | } 41997 | 41998 | if (se.data) 41999 | { 42000 | e.register_local_data(se.data, se.size, 2); 42001 | } 42002 | } 42003 | #endif 42004 | 42005 | se.var_node = 0; 42006 | se.vec_node = 0; 42007 | #ifndef exprtk_disable_string_capabilities 42008 | se.str_node = 0; 42009 | #endif 42010 | se.data = 0; 42011 | se.ref_count = 0; 42012 | se.active = false; 42013 | } 42014 | } 42015 | 42016 | inline void register_return_results(expression<T>& e) 42017 | { 42018 | e.register_return_results(results_context_); 42019 | results_context_ = 0; 42020 | } 42021 | 42022 | inline void load_unary_operations_map(unary_op_map_t& m) 42023 | { 42024 | #define register_unary_op(Op, UnaryFunctor) \ 42025 | m.insert(std::make_pair(Op,UnaryFunctor<T>::process)); \ 42026 | 42027 | register_unary_op(details::e_abs , details::abs_op ) 42028 | register_unary_op(details::e_acos , details::acos_op ) 42029 | register_unary_op(details::e_acosh , details::acosh_op) 42030 | register_unary_op(details::e_asin , details::asin_op ) 42031 | register_unary_op(details::e_asinh , details::asinh_op) 42032 | register_unary_op(details::e_atan , details::atan_op ) 42033 | register_unary_op(details::e_atanh , details::atanh_op) 42034 | register_unary_op(details::e_ceil , details::ceil_op ) 42035 | register_unary_op(details::e_cos , details::cos_op ) 42036 | register_unary_op(details::e_cosh , details::cosh_op ) 42037 | register_unary_op(details::e_exp , details::exp_op ) 42038 | register_unary_op(details::e_expm1 , details::expm1_op) 42039 | register_unary_op(details::e_floor , details::floor_op) 42040 | register_unary_op(details::e_log , details::log_op ) 42041 | register_unary_op(details::e_log10 , details::log10_op) 42042 | register_unary_op(details::e_log2 , details::log2_op ) 42043 | register_unary_op(details::e_log1p , details::log1p_op) 42044 | register_unary_op(details::e_neg , details::neg_op ) 42045 | register_unary_op(details::e_pos , details::pos_op ) 42046 | register_unary_op(details::e_round , details::round_op) 42047 | register_unary_op(details::e_sin , details::sin_op ) 42048 | register_unary_op(details::e_sinc , details::sinc_op ) 42049 | register_unary_op(details::e_sinh , details::sinh_op ) 42050 | register_unary_op(details::e_sqrt , details::sqrt_op ) 42051 | register_unary_op(details::e_tan , details::tan_op ) 42052 | register_unary_op(details::e_tanh , details::tanh_op ) 42053 | register_unary_op(details::e_cot , details::cot_op ) 42054 | register_unary_op(details::e_sec , details::sec_op ) 42055 | register_unary_op(details::e_csc , details::csc_op ) 42056 | register_unary_op(details::e_r2d , details::r2d_op ) 42057 | register_unary_op(details::e_d2r , details::d2r_op ) 42058 | register_unary_op(details::e_d2g , details::d2g_op ) 42059 | register_unary_op(details::e_g2d , details::g2d_op ) 42060 | register_unary_op(details::e_notl , details::notl_op ) 42061 | register_unary_op(details::e_sgn , details::sgn_op ) 42062 | register_unary_op(details::e_erf , details::erf_op ) 42063 | register_unary_op(details::e_erfc , details::erfc_op ) 42064 | register_unary_op(details::e_ncdf , details::ncdf_op ) 42065 | register_unary_op(details::e_frac , details::frac_op ) 42066 | register_unary_op(details::e_trunc , details::trunc_op) 42067 | #undef register_unary_op 42068 | } 42069 | 42070 | inline void load_binary_operations_map(binary_op_map_t& m) 42071 | { 42072 | typedef typename binary_op_map_t::value_type value_type; 42073 | 42074 | #define register_binary_op(Op, BinaryFunctor) \ 42075 | m.insert(value_type(Op,BinaryFunctor<T>::process)); \ 42076 | 42077 | register_binary_op(details::e_add , details::add_op ) 42078 | register_binary_op(details::e_sub , details::sub_op ) 42079 | register_binary_op(details::e_mul , details::mul_op ) 42080 | register_binary_op(details::e_div , details::div_op ) 42081 | register_binary_op(details::e_mod , details::mod_op ) 42082 | register_binary_op(details::e_pow , details::pow_op ) 42083 | register_binary_op(details::e_lt , details::lt_op ) 42084 | register_binary_op(details::e_lte , details::lte_op ) 42085 | register_binary_op(details::e_gt , details::gt_op ) 42086 | register_binary_op(details::e_gte , details::gte_op ) 42087 | register_binary_op(details::e_eq , details::eq_op ) 42088 | register_binary_op(details::e_ne , details::ne_op ) 42089 | register_binary_op(details::e_and , details::and_op ) 42090 | register_binary_op(details::e_nand , details::nand_op) 42091 | register_binary_op(details::e_or , details::or_op ) 42092 | register_binary_op(details::e_nor , details::nor_op ) 42093 | register_binary_op(details::e_xor , details::xor_op ) 42094 | register_binary_op(details::e_xnor , details::xnor_op) 42095 | #undef register_binary_op 42096 | } 42097 | 42098 | inline void load_inv_binary_operations_map(inv_binary_op_map_t& m) 42099 | { 42100 | typedef typename inv_binary_op_map_t::value_type value_type; 42101 | 42102 | #define register_binary_op(Op, BinaryFunctor) \ 42103 | m.insert(value_type(BinaryFunctor<T>::process,Op)); \ 42104 | 42105 | register_binary_op(details::e_add , details::add_op ) 42106 | register_binary_op(details::e_sub , details::sub_op ) 42107 | register_binary_op(details::e_mul , details::mul_op ) 42108 | register_binary_op(details::e_div , details::div_op ) 42109 | register_binary_op(details::e_mod , details::mod_op ) 42110 | register_binary_op(details::e_pow , details::pow_op ) 42111 | register_binary_op(details::e_lt , details::lt_op ) 42112 | register_binary_op(details::e_lte , details::lte_op ) 42113 | register_binary_op(details::e_gt , details::gt_op ) 42114 | register_binary_op(details::e_gte , details::gte_op ) 42115 | register_binary_op(details::e_eq , details::eq_op ) 42116 | register_binary_op(details::e_ne , details::ne_op ) 42117 | register_binary_op(details::e_and , details::and_op ) 42118 | register_binary_op(details::e_nand , details::nand_op) 42119 | register_binary_op(details::e_or , details::or_op ) 42120 | register_binary_op(details::e_nor , details::nor_op ) 42121 | register_binary_op(details::e_xor , details::xor_op ) 42122 | register_binary_op(details::e_xnor , details::xnor_op) 42123 | #undef register_binary_op 42124 | } 42125 | 42126 | inline void load_sf3_map(sf3_map_t& sf3_map) 42127 | { 42128 | typedef std::pair<trinary_functor_t,details::operator_type> pair_t; 42129 | 42130 | #define register_sf3(Op) \ 42131 | sf3_map[details::sf##Op##_op<T>::id()] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \ 42132 | 42133 | register_sf3(00) register_sf3(01) register_sf3(02) register_sf3(03) 42134 | register_sf3(04) register_sf3(05) register_sf3(06) register_sf3(07) 42135 | register_sf3(08) register_sf3(09) register_sf3(10) register_sf3(11) 42136 | register_sf3(12) register_sf3(13) register_sf3(14) register_sf3(15) 42137 | register_sf3(16) register_sf3(17) register_sf3(18) register_sf3(19) 42138 | register_sf3(20) register_sf3(21) register_sf3(22) register_sf3(23) 42139 | register_sf3(24) register_sf3(25) register_sf3(26) register_sf3(27) 42140 | register_sf3(28) register_sf3(29) register_sf3(30) 42141 | #undef register_sf3 42142 | 42143 | #define register_sf3_extid(Id, Op) \ 42144 | sf3_map[Id] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \ 42145 | 42146 | register_sf3_extid("(t-t)-t",23) // (t-t)-t --> t-(t+t) 42147 | #undef register_sf3_extid 42148 | } 42149 | 42150 | inline void load_sf4_map(sf4_map_t& sf4_map) 42151 | { 42152 | typedef std::pair<quaternary_functor_t,details::operator_type> pair_t; 42153 | 42154 | #define register_sf4(Op) \ 42155 | sf4_map[details::sf##Op##_op<T>::id()] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \ 42156 | 42157 | register_sf4(48) register_sf4(49) register_sf4(50) register_sf4(51) 42158 | register_sf4(52) register_sf4(53) register_sf4(54) register_sf4(55) 42159 | register_sf4(56) register_sf4(57) register_sf4(58) register_sf4(59) 42160 | register_sf4(60) register_sf4(61) register_sf4(62) register_sf4(63) 42161 | register_sf4(64) register_sf4(65) register_sf4(66) register_sf4(67) 42162 | register_sf4(68) register_sf4(69) register_sf4(70) register_sf4(71) 42163 | register_sf4(72) register_sf4(73) register_sf4(74) register_sf4(75) 42164 | register_sf4(76) register_sf4(77) register_sf4(78) register_sf4(79) 42165 | register_sf4(80) register_sf4(81) register_sf4(82) register_sf4(83) 42166 | #undef register_sf4 42167 | 42168 | #define register_sf4ext(Op) \ 42169 | sf4_map[details::sfext##Op##_op<T>::id()] = pair_t(details::sfext##Op##_op<T>::process,details::e_sf4ext##Op); \ 42170 | 42171 | register_sf4ext(00) register_sf4ext(01) register_sf4ext(02) register_sf4ext(03) 42172 | register_sf4ext(04) register_sf4ext(05) register_sf4ext(06) register_sf4ext(07) 42173 | register_sf4ext(08) register_sf4ext(09) register_sf4ext(10) register_sf4ext(11) 42174 | register_sf4ext(12) register_sf4ext(13) register_sf4ext(14) register_sf4ext(15) 42175 | register_sf4ext(16) register_sf4ext(17) register_sf4ext(18) register_sf4ext(19) 42176 | register_sf4ext(20) register_sf4ext(21) register_sf4ext(22) register_sf4ext(23) 42177 | register_sf4ext(24) register_sf4ext(25) register_sf4ext(26) register_sf4ext(27) 42178 | register_sf4ext(28) register_sf4ext(29) register_sf4ext(30) register_sf4ext(31) 42179 | register_sf4ext(32) register_sf4ext(33) register_sf4ext(34) register_sf4ext(35) 42180 | register_sf4ext(36) register_sf4ext(37) register_sf4ext(38) register_sf4ext(39) 42181 | register_sf4ext(40) register_sf4ext(41) register_sf4ext(42) register_sf4ext(43) 42182 | register_sf4ext(44) register_sf4ext(45) register_sf4ext(46) register_sf4ext(47) 42183 | register_sf4ext(48) register_sf4ext(49) register_sf4ext(50) register_sf4ext(51) 42184 | register_sf4ext(52) register_sf4ext(53) register_sf4ext(54) register_sf4ext(55) 42185 | register_sf4ext(56) register_sf4ext(57) register_sf4ext(58) register_sf4ext(59) 42186 | register_sf4ext(60) register_sf4ext(61) 42187 | #undef register_sf4ext 42188 | } 42189 | 42190 | inline results_context_t& results_ctx() 42191 | { 42192 | if (0 == results_context_) 42193 | { 42194 | results_context_ = new results_context_t(); 42195 | } 42196 | 42197 | return (*results_context_); 42198 | } 42199 | 42200 | inline void return_cleanup() 42201 | { 42202 | #ifndef exprtk_disable_return_statement 42203 | if (results_context_) 42204 | { 42205 | delete results_context_; 42206 | results_context_ = 0; 42207 | } 42208 | 42209 | state_.return_stmt_present = false; 42210 | #endif 42211 | } 42212 | 42213 | inline bool valid_settings() 42214 | { 42215 | const std::size_t max_local_vector_size_bytes = sizeof(T) * settings_.max_local_vector_size(); 42216 | 42217 | if (max_local_vector_size_bytes > settings_.max_total_local_symbol_size_bytes()) 42218 | { 42219 | set_error(make_error( 42220 | parser_error::e_parser, 42221 | "ERR284 - Max local vector size of " + details::to_str(max_local_vector_size_bytes) + " bytes " 42222 | "is larger than max total local symbol size of " + details::to_str(settings_.max_total_local_symbol_size_bytes()) + " bytes", 42223 | exprtk_error_location)); 42224 | 42225 | return false; 42226 | } 42227 | 42228 | return true; 42229 | } 42230 | 42231 | private: 42232 | 42233 | parser(const parser<T>&) exprtk_delete; 42234 | parser<T>& operator=(const parser<T>&) exprtk_delete; 42235 | 42236 | settings_store settings_; 42237 | expression_generator<T> expression_generator_; 42238 | details::node_allocator node_allocator_; 42239 | symtab_store symtab_store_; 42240 | dependent_entity_collector dec_; 42241 | std::deque<parser_error::type> error_list_; 42242 | std::deque<bool> brkcnt_list_; 42243 | parser_state state_; 42244 | bool resolve_unknown_symbol_; 42245 | results_context_t* results_context_; 42246 | unknown_symbol_resolver* unknown_symbol_resolver_; 42247 | unknown_symbol_resolver default_usr_; 42248 | base_ops_map_t base_ops_map_; 42249 | unary_op_map_t unary_op_map_; 42250 | binary_op_map_t binary_op_map_; 42251 | inv_binary_op_map_t inv_binary_op_map_; 42252 | sf3_map_t sf3_map_; 42253 | sf4_map_t sf4_map_; 42254 | std::string synthesis_error_; 42255 | scope_element_manager sem_; 42256 | std::vector<state_t> current_state_stack_; 42257 | 42258 | immutable_memory_map_t immutable_memory_map_; 42259 | immutable_symtok_map_t immutable_symtok_map_; 42260 | 42261 | lexer::helper::helper_assembly helper_assembly_; 42262 | 42263 | lexer::helper::commutative_inserter commutative_inserter_; 42264 | lexer::helper::operator_joiner operator_joiner_2_; 42265 | lexer::helper::operator_joiner operator_joiner_3_; 42266 | lexer::helper::symbol_replacer symbol_replacer_; 42267 | lexer::helper::bracket_checker bracket_checker_; 42268 | lexer::helper::numeric_checker<T> numeric_checker_; 42269 | lexer::helper::sequence_validator sequence_validator_; 42270 | lexer::helper::sequence_validator_3tokens sequence_validator_3tkns_; 42271 | 42272 | loop_runtime_check_ptr loop_runtime_check_; 42273 | vector_access_runtime_check_ptr vector_access_runtime_check_; 42274 | compilation_check_ptr compilation_check_ptr_; 42275 | assert_check_ptr assert_check_; 42276 | std::set<std::string> assert_ids_; 42277 | 42278 | template <typename ParserType> 42279 | friend void details::disable_type_checking(ParserType& p); 42280 | }; // class parser 42281 | 42282 | namespace details 42283 | { 42284 | template <typename T> 42285 | struct collector_helper 42286 | { 42287 | typedef exprtk::symbol_table<T> symbol_table_t; 42288 | typedef exprtk::expression<T> expression_t; 42289 | typedef exprtk::parser<T> parser_t; 42290 | typedef typename parser_t::dependent_entity_collector::symbol_t symbol_t; 42291 | typedef typename parser_t::unknown_symbol_resolver usr_t; 42292 | 42293 | struct resolve_as_vector : public usr_t 42294 | { 42295 | typedef exprtk::parser<T> parser_t; 42296 | 42297 | using usr_t::process; 42298 | 42299 | resolve_as_vector() 42300 | : usr_t(usr_t::e_usrmode_extended) 42301 | {} 42302 | 42303 | virtual bool process(const std::string& unknown_symbol, 42304 | symbol_table_t& symbol_table, 42305 | std::string&) exprtk_override 42306 | { 42307 | static T v[1]; 42308 | symbol_table.add_vector(unknown_symbol,v); 42309 | return true; 42310 | } 42311 | }; 42312 | 42313 | static inline bool collection_pass(const std::string& expression_string, 42314 | std::set<std::string>& symbol_set, 42315 | const bool collect_variables, 42316 | const bool collect_functions, 42317 | const bool vector_pass, 42318 | symbol_table_t& ext_symbol_table) 42319 | { 42320 | symbol_table_t symbol_table; 42321 | expression_t expression; 42322 | parser_t parser; 42323 | 42324 | resolve_as_vector vect_resolver; 42325 | 42326 | expression.register_symbol_table(symbol_table ); 42327 | expression.register_symbol_table(ext_symbol_table); 42328 | 42329 | if (vector_pass) 42330 | parser.enable_unknown_symbol_resolver(&vect_resolver); 42331 | else 42332 | parser.enable_unknown_symbol_resolver(); 42333 | 42334 | if (collect_variables) 42335 | parser.dec().collect_variables() = true; 42336 | 42337 | if (collect_functions) 42338 | parser.dec().collect_functions() = true; 42339 | 42340 | bool pass_result = false; 42341 | 42342 | details::disable_type_checking(parser); 42343 | 42344 | if (parser.compile(expression_string, expression)) 42345 | { 42346 | pass_result = true; 42347 | 42348 | std::deque<symbol_t> symb_list; 42349 | parser.dec().symbols(symb_list); 42350 | 42351 | for (std::size_t i = 0; i < symb_list.size(); ++i) 42352 | { 42353 | symbol_set.insert(symb_list[i].first); 42354 | } 42355 | } 42356 | 42357 | return pass_result; 42358 | } 42359 | }; 42360 | } 42361 | 42362 | template <typename Allocator, 42363 | template <typename, typename> class Sequence> 42364 | inline bool collect_variables(const std::string& expression, 42365 | Sequence<std::string, Allocator>& symbol_list) 42366 | { 42367 | typedef double T; 42368 | typedef details::collector_helper<T> collect_t; 42369 | 42370 | collect_t::symbol_table_t null_symbol_table; 42371 | 42372 | std::set<std::string> symbol_set; 42373 | 42374 | const bool variable_pass = collect_t::collection_pass 42375 | (expression, symbol_set, true, false, false, null_symbol_table); 42376 | const bool vector_pass = collect_t::collection_pass 42377 | (expression, symbol_set, true, false, true, null_symbol_table); 42378 | 42379 | if (!variable_pass && !vector_pass) 42380 | return false; 42381 | 42382 | std::set<std::string>::iterator itr = symbol_set.begin(); 42383 | 42384 | while (symbol_set.end() != itr) 42385 | { 42386 | symbol_list.push_back(*itr); 42387 | ++itr; 42388 | } 42389 | 42390 | return true; 42391 | } 42392 | 42393 | template <typename T, 42394 | typename Allocator, 42395 | template <typename, typename> class Sequence> 42396 | inline bool collect_variables(const std::string& expression, 42397 | exprtk::symbol_table<T>& extrnl_symbol_table, 42398 | Sequence<std::string, Allocator>& symbol_list) 42399 | { 42400 | typedef details::collector_helper<T> collect_t; 42401 | 42402 | std::set<std::string> symbol_set; 42403 | 42404 | const bool variable_pass = collect_t::collection_pass 42405 | (expression, symbol_set, true, false, false, extrnl_symbol_table); 42406 | const bool vector_pass = collect_t::collection_pass 42407 | (expression, symbol_set, true, false, true, extrnl_symbol_table); 42408 | 42409 | if (!variable_pass && !vector_pass) 42410 | return false; 42411 | 42412 | std::set<std::string>::iterator itr = symbol_set.begin(); 42413 | 42414 | while (symbol_set.end() != itr) 42415 | { 42416 | symbol_list.push_back(*itr); 42417 | ++itr; 42418 | } 42419 | 42420 | return true; 42421 | } 42422 | 42423 | template <typename Allocator, 42424 | template <typename, typename> class Sequence> 42425 | inline bool collect_functions(const std::string& expression, 42426 | Sequence<std::string, Allocator>& symbol_list) 42427 | { 42428 | typedef double T; 42429 | typedef details::collector_helper<T> collect_t; 42430 | 42431 | collect_t::symbol_table_t null_symbol_table; 42432 | 42433 | std::set<std::string> symbol_set; 42434 | 42435 | const bool variable_pass = collect_t::collection_pass 42436 | (expression, symbol_set, false, true, false, null_symbol_table); 42437 | const bool vector_pass = collect_t::collection_pass 42438 | (expression, symbol_set, false, true, true, null_symbol_table); 42439 | 42440 | if (!variable_pass && !vector_pass) 42441 | return false; 42442 | 42443 | std::set<std::string>::iterator itr = symbol_set.begin(); 42444 | 42445 | while (symbol_set.end() != itr) 42446 | { 42447 | symbol_list.push_back(*itr); 42448 | ++itr; 42449 | } 42450 | 42451 | return true; 42452 | } 42453 | 42454 | template <typename T, 42455 | typename Allocator, 42456 | template <typename, typename> class Sequence> 42457 | inline bool collect_functions(const std::string& expression, 42458 | exprtk::symbol_table<T>& extrnl_symbol_table, 42459 | Sequence<std::string, Allocator>& symbol_list) 42460 | { 42461 | typedef details::collector_helper<T> collect_t; 42462 | 42463 | std::set<std::string> symbol_set; 42464 | 42465 | const bool variable_pass = collect_t::collection_pass 42466 | (expression, symbol_set, false, true, false, extrnl_symbol_table); 42467 | const bool vector_pass = collect_t::collection_pass 42468 | (expression, symbol_set, false, true, true, extrnl_symbol_table); 42469 | 42470 | if (!variable_pass && !vector_pass) 42471 | return false; 42472 | 42473 | std::set<std::string>::iterator itr = symbol_set.begin(); 42474 | 42475 | while (symbol_set.end() != itr) 42476 | { 42477 | symbol_list.push_back(*itr); 42478 | ++itr; 42479 | } 42480 | 42481 | return true; 42482 | } 42483 | 42484 | template <typename T> 42485 | inline T integrate(const expression<T>& e, 42486 | T& x, 42487 | const T& r0, const T& r1, 42488 | const std::size_t number_of_intervals = 1000000) 42489 | { 42490 | if (r0 > r1) 42491 | return T(0); 42492 | 42493 | const T h = (r1 - r0) / (T(2) * number_of_intervals); 42494 | T total_area = T(0); 42495 | 42496 | for (std::size_t i = 0; i < number_of_intervals; ++i) 42497 | { 42498 | x = r0 + T(2) * i * h; 42499 | const T y0 = e.value(); x += h; 42500 | const T y1 = e.value(); x += h; 42501 | const T y2 = e.value(); x += h; 42502 | total_area += h * (y0 + T(4) * y1 + y2) / T(3); 42503 | } 42504 | 42505 | return total_area; 42506 | } 42507 | 42508 | template <typename T> 42509 | inline T integrate(const expression<T>& e, 42510 | const std::string& variable_name, 42511 | const T& r0, const T& r1, 42512 | const std::size_t number_of_intervals = 1000000) 42513 | { 42514 | const symbol_table<T>& sym_table = e.get_symbol_table(); 42515 | 42516 | if (!sym_table.valid()) 42517 | { 42518 | return std::numeric_limits<T>::quiet_NaN(); 42519 | } 42520 | 42521 | details::variable_node<T>* var = sym_table.get_variable(variable_name); 42522 | 42523 | if (var) 42524 | { 42525 | T& x = var->ref(); 42526 | const T x_original = x; 42527 | const T result = integrate(e, x, r0, r1, number_of_intervals); 42528 | x = x_original; 42529 | 42530 | return result; 42531 | } 42532 | 42533 | return std::numeric_limits<T>::quiet_NaN(); 42534 | } 42535 | 42536 | template <typename T> 42537 | inline T derivative(const expression<T>& e, 42538 | T& x, 42539 | const T& h = T(0.00000001)) 42540 | { 42541 | const T x_init = x; 42542 | const T _2h = T(2) * h; 42543 | 42544 | x = x_init + _2h; 42545 | const T y0 = e.value(); 42546 | x = x_init + h; 42547 | const T y1 = e.value(); 42548 | x = x_init - h; 42549 | const T y2 = e.value(); 42550 | x = x_init - _2h; 42551 | const T y3 = e.value(); 42552 | x = x_init; 42553 | 42554 | return (-y0 + T(8) * (y1 - y2) + y3) / (T(12) * h); 42555 | } 42556 | 42557 | template <typename T> 42558 | inline T second_derivative(const expression<T>& e, 42559 | T& x, 42560 | const T& h = T(0.00001)) 42561 | { 42562 | const T x_init = x; 42563 | const T _2h = T(2) * h; 42564 | 42565 | const T y = e.value(); 42566 | x = x_init + _2h; 42567 | const T y0 = e.value(); 42568 | x = x_init + h; 42569 | const T y1 = e.value(); 42570 | x = x_init - h; 42571 | const T y2 = e.value(); 42572 | x = x_init - _2h; 42573 | const T y3 = e.value(); 42574 | x = x_init; 42575 | 42576 | return (-y0 + T(16) * (y1 + y2) - T(30) * y - y3) / (T(12) * h * h); 42577 | } 42578 | 42579 | template <typename T> 42580 | inline T third_derivative(const expression<T>& e, 42581 | T& x, 42582 | const T& h = T(0.0001)) 42583 | { 42584 | const T x_init = x; 42585 | const T _2h = T(2) * h; 42586 | 42587 | x = x_init + _2h; 42588 | const T y0 = e.value(); 42589 | x = x_init + h; 42590 | const T y1 = e.value(); 42591 | x = x_init - h; 42592 | const T y2 = e.value(); 42593 | x = x_init - _2h; 42594 | const T y3 = e.value(); 42595 | x = x_init; 42596 | 42597 | return (y0 + T(2) * (y2 - y1) - y3) / (T(2) * h * h * h); 42598 | } 42599 | 42600 | template <typename T> 42601 | inline T derivative(const expression<T>& e, 42602 | const std::string& variable_name, 42603 | const T& h = T(0.00000001)) 42604 | { 42605 | const symbol_table<T>& sym_table = e.get_symbol_table(); 42606 | 42607 | if (!sym_table.valid()) 42608 | { 42609 | return std::numeric_limits<T>::quiet_NaN(); 42610 | } 42611 | 42612 | details::variable_node<T>* var = sym_table.get_variable(variable_name); 42613 | 42614 | if (var) 42615 | { 42616 | T& x = var->ref(); 42617 | const T x_original = x; 42618 | const T result = derivative(e, x, h); 42619 | x = x_original; 42620 | 42621 | return result; 42622 | } 42623 | 42624 | return std::numeric_limits<T>::quiet_NaN(); 42625 | } 42626 | 42627 | template <typename T> 42628 | inline T second_derivative(const expression<T>& e, 42629 | const std::string& variable_name, 42630 | const T& h = T(0.00001)) 42631 | { 42632 | const symbol_table<T>& sym_table = e.get_symbol_table(); 42633 | 42634 | if (!sym_table.valid()) 42635 | { 42636 | return std::numeric_limits<T>::quiet_NaN(); 42637 | } 42638 | 42639 | details::variable_node<T>* var = sym_table.get_variable(variable_name); 42640 | 42641 | if (var) 42642 | { 42643 | T& x = var->ref(); 42644 | const T x_original = x; 42645 | const T result = second_derivative(e, x, h); 42646 | x = x_original; 42647 | 42648 | return result; 42649 | } 42650 | 42651 | return std::numeric_limits<T>::quiet_NaN(); 42652 | } 42653 | 42654 | template <typename T> 42655 | inline T third_derivative(const expression<T>& e, 42656 | const std::string& variable_name, 42657 | const T& h = T(0.0001)) 42658 | { 42659 | const symbol_table<T>& sym_table = e.get_symbol_table(); 42660 | 42661 | if (!sym_table.valid()) 42662 | { 42663 | return std::numeric_limits<T>::quiet_NaN(); 42664 | } 42665 | 42666 | details::variable_node<T>* var = sym_table.get_variable(variable_name); 42667 | 42668 | if (var) 42669 | { 42670 | T& x = var->ref(); 42671 | const T x_original = x; 42672 | const T result = third_derivative(e, x, h); 42673 | x = x_original; 42674 | 42675 | return result; 42676 | } 42677 | 42678 | return std::numeric_limits<T>::quiet_NaN(); 42679 | } 42680 | 42681 | /* 42682 | Note: The following 'compute' routines are simple helpers, 42683 | for quickly setting up the required pieces of code in order 42684 | to evaluate an expression. By virtue of how they operate 42685 | there will be an overhead with regards to their setup and 42686 | teardown and hence should not be used in time critical 42687 | sections of code. 42688 | Furthermore they only assume a small sub set of variables, 42689 | no string variables or user defined functions. 42690 | */ 42691 | template <typename T> 42692 | inline bool compute(const std::string& expression_string, T& result) 42693 | { 42694 | // No variables 42695 | symbol_table<T> symbol_table; 42696 | symbol_table.add_constants(); 42697 | 42698 | expression<T> expression; 42699 | expression.register_symbol_table(symbol_table); 42700 | 42701 | parser<T> parser; 42702 | 42703 | if (parser.compile(expression_string,expression)) 42704 | { 42705 | result = expression.value(); 42706 | 42707 | return true; 42708 | } 42709 | else 42710 | return false; 42711 | } 42712 | 42713 | template <typename T> 42714 | inline bool compute(const std::string& expression_string, 42715 | const T& x, 42716 | T& result) 42717 | { 42718 | // Only 'x' 42719 | static const std::string x_var("x"); 42720 | 42721 | symbol_table<T> symbol_table; 42722 | symbol_table.add_constants(); 42723 | symbol_table.add_constant(x_var,x); 42724 | 42725 | expression<T> expression; 42726 | expression.register_symbol_table(symbol_table); 42727 | 42728 | parser<T> parser; 42729 | 42730 | if (parser.compile(expression_string,expression)) 42731 | { 42732 | result = expression.value(); 42733 | 42734 | return true; 42735 | } 42736 | else 42737 | return false; 42738 | } 42739 | 42740 | template <typename T> 42741 | inline bool compute(const std::string& expression_string, 42742 | const T&x, const T& y, 42743 | T& result) 42744 | { 42745 | // Only 'x' and 'y' 42746 | static const std::string x_var("x"); 42747 | static const std::string y_var("y"); 42748 | 42749 | symbol_table<T> symbol_table; 42750 | symbol_table.add_constants(); 42751 | symbol_table.add_constant(x_var,x); 42752 | symbol_table.add_constant(y_var,y); 42753 | 42754 | expression<T> expression; 42755 | expression.register_symbol_table(symbol_table); 42756 | 42757 | parser<T> parser; 42758 | 42759 | if (parser.compile(expression_string,expression)) 42760 | { 42761 | result = expression.value(); 42762 | 42763 | return true; 42764 | } 42765 | else 42766 | return false; 42767 | } 42768 | 42769 | template <typename T> 42770 | inline bool compute(const std::string& expression_string, 42771 | const T& x, const T& y, const T& z, 42772 | T& result) 42773 | { 42774 | // Only 'x', 'y' or 'z' 42775 | static const std::string x_var("x"); 42776 | static const std::string y_var("y"); 42777 | static const std::string z_var("z"); 42778 | 42779 | symbol_table<T> symbol_table; 42780 | symbol_table.add_constants(); 42781 | symbol_table.add_constant(x_var,x); 42782 | symbol_table.add_constant(y_var,y); 42783 | symbol_table.add_constant(z_var,z); 42784 | 42785 | expression<T> expression; 42786 | expression.register_symbol_table(symbol_table); 42787 | 42788 | parser<T> parser; 42789 | 42790 | if (parser.compile(expression_string,expression)) 42791 | { 42792 | result = expression.value(); 42793 | 42794 | return true; 42795 | } 42796 | else 42797 | return false; 42798 | } 42799 | 42800 | template <typename T, std::size_t N> 42801 | class polynomial : public ifunction<T> 42802 | { 42803 | private: 42804 | 42805 | template <typename Type, std::size_t NumberOfCoefficients> 42806 | struct poly_impl { }; 42807 | 42808 | template <typename Type> 42809 | struct poly_impl <Type,12> 42810 | { 42811 | static inline T evaluate(const Type x, 42812 | const Type c12, const Type c11, const Type c10, const Type c9, const Type c8, 42813 | const Type c7, const Type c6, const Type c5, const Type c4, const Type c3, 42814 | const Type c2, const Type c1, const Type c0) 42815 | { 42816 | // 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 42817 | 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); 42818 | } 42819 | }; 42820 | 42821 | template <typename Type> 42822 | struct poly_impl <Type,11> 42823 | { 42824 | static inline T evaluate(const Type x, 42825 | const Type c11, const Type c10, const Type c9, const Type c8, const Type c7, 42826 | const Type c6, const Type c5, const Type c4, const Type c3, const Type c2, 42827 | const Type c1, const Type c0) 42828 | { 42829 | // 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 42830 | return (((((((((((c11 * x + c10) * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42831 | } 42832 | }; 42833 | 42834 | template <typename Type> 42835 | struct poly_impl <Type,10> 42836 | { 42837 | static inline T evaluate(const Type x, 42838 | const Type c10, const Type c9, const Type c8, const Type c7, const Type c6, 42839 | const Type c5, const Type c4, const Type c3, const Type c2, const Type c1, 42840 | const Type c0) 42841 | { 42842 | // 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 42843 | return ((((((((((c10 * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42844 | } 42845 | }; 42846 | 42847 | template <typename Type> 42848 | struct poly_impl <Type,9> 42849 | { 42850 | static inline T evaluate(const Type x, 42851 | const Type c9, const Type c8, const Type c7, const Type c6, const Type c5, 42852 | const Type c4, const Type c3, const Type c2, const Type c1, const Type c0) 42853 | { 42854 | // 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 42855 | return (((((((((c9 * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42856 | } 42857 | }; 42858 | 42859 | template <typename Type> 42860 | struct poly_impl <Type,8> 42861 | { 42862 | static inline T evaluate(const Type x, 42863 | const Type c8, const Type c7, const Type c6, const Type c5, const Type c4, 42864 | const Type c3, const Type c2, const Type c1, const Type c0) 42865 | { 42866 | // 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 42867 | return ((((((((c8 * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42868 | } 42869 | }; 42870 | 42871 | template <typename Type> 42872 | struct poly_impl <Type,7> 42873 | { 42874 | static inline T evaluate(const Type x, 42875 | const Type c7, const Type c6, const Type c5, const Type c4, const Type c3, 42876 | const Type c2, const Type c1, const Type c0) 42877 | { 42878 | // 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 42879 | return (((((((c7 * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42880 | } 42881 | }; 42882 | 42883 | template <typename Type> 42884 | struct poly_impl <Type,6> 42885 | { 42886 | static inline T evaluate(const Type x, 42887 | const Type c6, const Type c5, const Type c4, const Type c3, const Type c2, 42888 | const Type c1, const Type c0) 42889 | { 42890 | // p(x) = c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 42891 | return ((((((c6 * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42892 | } 42893 | }; 42894 | 42895 | template <typename Type> 42896 | struct poly_impl <Type,5> 42897 | { 42898 | static inline T evaluate(const Type x, 42899 | const Type c5, const Type c4, const Type c3, const Type c2, 42900 | const Type c1, const Type c0) 42901 | { 42902 | // p(x) = c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 42903 | return (((((c5 * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42904 | } 42905 | }; 42906 | 42907 | template <typename Type> 42908 | struct poly_impl <Type,4> 42909 | { 42910 | static inline T evaluate(const Type x, const Type c4, const Type c3, const Type c2, const Type c1, const Type c0) 42911 | { 42912 | // p(x) = c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 42913 | return ((((c4 * x + c3) * x + c2) * x + c1) * x + c0); 42914 | } 42915 | }; 42916 | 42917 | template <typename Type> 42918 | struct poly_impl <Type,3> 42919 | { 42920 | static inline T evaluate(const Type x, const Type c3, const Type c2, const Type c1, const Type c0) 42921 | { 42922 | // p(x) = c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 42923 | return (((c3 * x + c2) * x + c1) * x + c0); 42924 | } 42925 | }; 42926 | 42927 | template <typename Type> 42928 | struct poly_impl <Type,2> 42929 | { 42930 | static inline T evaluate(const Type x, const Type c2, const Type c1, const Type c0) 42931 | { 42932 | // p(x) = c_2x^2 + c_1x^1 + c_0x^0 42933 | return ((c2 * x + c1) * x + c0); 42934 | } 42935 | }; 42936 | 42937 | template <typename Type> 42938 | struct poly_impl <Type,1> 42939 | { 42940 | static inline T evaluate(const Type x, const Type c1, const Type c0) 42941 | { 42942 | // p(x) = c_1x^1 + c_0x^0 42943 | return (c1 * x + c0); 42944 | } 42945 | }; 42946 | 42947 | public: 42948 | 42949 | using ifunction<T>::operator(); 42950 | 42951 | polynomial() 42952 | : ifunction<T>((N+2 <= 20) ? (N + 2) : std::numeric_limits<std::size_t>::max()) 42953 | { 42954 | disable_has_side_effects(*this); 42955 | } 42956 | 42957 | virtual ~polynomial() exprtk_override 42958 | {} 42959 | 42960 | #define poly_rtrn(NN) \ 42961 | return (NN != N) ? std::numeric_limits<T>::quiet_NaN() : 42962 | 42963 | inline virtual T operator() (const T& x, const T& c1, const T& c0) exprtk_override 42964 | { 42965 | poly_rtrn(1) (poly_impl<T,1>::evaluate(x, c1, c0)); 42966 | } 42967 | 42968 | inline virtual T operator() (const T& x, const T& c2, const T& c1, const T& c0) exprtk_override 42969 | { 42970 | poly_rtrn(2) (poly_impl<T,2>::evaluate(x, c2, c1, c0)); 42971 | } 42972 | 42973 | inline virtual T operator() (const T& x, const T& c3, const T& c2, const T& c1, const T& c0) exprtk_override 42974 | { 42975 | poly_rtrn(3) (poly_impl<T,3>::evaluate(x, c3, c2, c1, c0)); 42976 | } 42977 | 42978 | inline virtual T operator() (const T& x, const T& c4, const T& c3, const T& c2, const T& c1, 42979 | const T& c0) exprtk_override 42980 | { 42981 | poly_rtrn(4) (poly_impl<T,4>::evaluate(x, c4, c3, c2, c1, c0)); 42982 | } 42983 | 42984 | inline virtual T operator() (const T& x, const T& c5, const T& c4, const T& c3, const T& c2, 42985 | const T& c1, const T& c0) exprtk_override 42986 | { 42987 | poly_rtrn(5) (poly_impl<T,5>::evaluate(x, c5, c4, c3, c2, c1, c0)); 42988 | } 42989 | 42990 | inline virtual T operator() (const T& x, const T& c6, const T& c5, const T& c4, const T& c3, 42991 | const T& c2, const T& c1, const T& c0) exprtk_override 42992 | { 42993 | poly_rtrn(6) (poly_impl<T,6>::evaluate(x, c6, c5, c4, c3, c2, c1, c0)); 42994 | } 42995 | 42996 | inline virtual T operator() (const T& x, const T& c7, const T& c6, const T& c5, const T& c4, 42997 | const T& c3, const T& c2, const T& c1, const T& c0) exprtk_override 42998 | { 42999 | poly_rtrn(7) (poly_impl<T,7>::evaluate(x, c7, c6, c5, c4, c3, c2, c1, c0)); 43000 | } 43001 | 43002 | inline virtual T operator() (const T& x, const T& c8, const T& c7, const T& c6, const T& c5, 43003 | const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) exprtk_override 43004 | { 43005 | poly_rtrn(8) (poly_impl<T,8>::evaluate(x, c8, c7, c6, c5, c4, c3, c2, c1, c0)); 43006 | } 43007 | 43008 | inline virtual T operator() (const T& x, const T& c9, const T& c8, const T& c7, const T& c6, 43009 | const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, 43010 | const T& c0) exprtk_override 43011 | { 43012 | poly_rtrn(9) (poly_impl<T,9>::evaluate(x, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0)); 43013 | } 43014 | 43015 | inline virtual T operator() (const T& x, const T& c10, const T& c9, const T& c8, const T& c7, 43016 | const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, 43017 | const T& c1, const T& c0) exprtk_override 43018 | { 43019 | poly_rtrn(10) (poly_impl<T,10>::evaluate(x, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0)); 43020 | } 43021 | 43022 | inline virtual T operator() (const T& x, const T& c11, const T& c10, const T& c9, const T& c8, 43023 | const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, 43024 | const T& c2, const T& c1, const T& c0) exprtk_override 43025 | { 43026 | poly_rtrn(11) (poly_impl<T,11>::evaluate(x, c11, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0)); 43027 | } 43028 | 43029 | inline virtual T operator() (const T& x, const T& c12, const T& c11, const T& c10, const T& c9, 43030 | const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, 43031 | const T& c3, const T& c2, const T& c1, const T& c0) exprtk_override 43032 | { 43033 | poly_rtrn(12) (poly_impl<T,12>::evaluate(x, c12, c11, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0)); 43034 | } 43035 | 43036 | #undef poly_rtrn 43037 | 43038 | inline virtual T operator() () exprtk_override 43039 | { 43040 | return std::numeric_limits<T>::quiet_NaN(); 43041 | } 43042 | 43043 | inline virtual T operator() (const T&) exprtk_override 43044 | { 43045 | return std::numeric_limits<T>::quiet_NaN(); 43046 | } 43047 | 43048 | inline virtual T operator() (const T&, const T&) exprtk_override 43049 | { 43050 | return std::numeric_limits<T>::quiet_NaN(); 43051 | } 43052 | }; 43053 | 43054 | template <typename T> 43055 | class function_compositor 43056 | { 43057 | public: 43058 | 43059 | typedef exprtk::expression<T> expression_t; 43060 | typedef exprtk::symbol_table<T> symbol_table_t; 43061 | typedef exprtk::parser<T> parser_t; 43062 | typedef typename parser_t::settings_store settings_t; 43063 | 43064 | struct function 43065 | { 43066 | function() 43067 | {} 43068 | 43069 | explicit function(const std::string& n) 43070 | : name_(n) 43071 | {} 43072 | 43073 | function(const std::string& name, 43074 | const std::string& expression) 43075 | : name_(name) 43076 | , expression_(expression) 43077 | {} 43078 | 43079 | function(const std::string& name, 43080 | const std::string& expression, 43081 | const std::string& v0) 43082 | : name_(name) 43083 | , expression_(expression) 43084 | { 43085 | v_.push_back(v0); 43086 | } 43087 | 43088 | function(const std::string& name, 43089 | const std::string& expression, 43090 | const std::string& v0, const std::string& v1) 43091 | : name_(name) 43092 | , expression_(expression) 43093 | { 43094 | v_.push_back(v0); v_.push_back(v1); 43095 | } 43096 | 43097 | function(const std::string& name, 43098 | const std::string& expression, 43099 | const std::string& v0, const std::string& v1, 43100 | const std::string& v2) 43101 | : name_(name) 43102 | , expression_(expression) 43103 | { 43104 | v_.push_back(v0); v_.push_back(v1); 43105 | v_.push_back(v2); 43106 | } 43107 | 43108 | function(const std::string& name, 43109 | const std::string& expression, 43110 | const std::string& v0, const std::string& v1, 43111 | const std::string& v2, const std::string& v3) 43112 | : name_(name) 43113 | , expression_(expression) 43114 | { 43115 | v_.push_back(v0); v_.push_back(v1); 43116 | v_.push_back(v2); v_.push_back(v3); 43117 | } 43118 | 43119 | function(const std::string& name, 43120 | const std::string& expression, 43121 | const std::string& v0, const std::string& v1, 43122 | const std::string& v2, const std::string& v3, 43123 | const std::string& v4) 43124 | : name_(name) 43125 | , expression_(expression) 43126 | { 43127 | v_.push_back(v0); v_.push_back(v1); 43128 | v_.push_back(v2); v_.push_back(v3); 43129 | v_.push_back(v4); 43130 | } 43131 | 43132 | inline function& name(const std::string& n) 43133 | { 43134 | name_ = n; 43135 | return (*this); 43136 | } 43137 | 43138 | inline function& expression(const std::string& e) 43139 | { 43140 | expression_ = e; 43141 | return (*this); 43142 | } 43143 | 43144 | inline function& var(const std::string& v) 43145 | { 43146 | v_.push_back(v); 43147 | return (*this); 43148 | } 43149 | 43150 | inline function& vars(const std::string& v0, 43151 | const std::string& v1) 43152 | { 43153 | v_.push_back(v0); 43154 | v_.push_back(v1); 43155 | return (*this); 43156 | } 43157 | 43158 | inline function& vars(const std::string& v0, 43159 | const std::string& v1, 43160 | const std::string& v2) 43161 | { 43162 | v_.push_back(v0); 43163 | v_.push_back(v1); 43164 | v_.push_back(v2); 43165 | return (*this); 43166 | } 43167 | 43168 | inline function& vars(const std::string& v0, 43169 | const std::string& v1, 43170 | const std::string& v2, 43171 | const std::string& v3) 43172 | { 43173 | v_.push_back(v0); 43174 | v_.push_back(v1); 43175 | v_.push_back(v2); 43176 | v_.push_back(v3); 43177 | return (*this); 43178 | } 43179 | 43180 | inline function& vars(const std::string& v0, 43181 | const std::string& v1, 43182 | const std::string& v2, 43183 | const std::string& v3, 43184 | const std::string& v4) 43185 | { 43186 | v_.push_back(v0); 43187 | v_.push_back(v1); 43188 | v_.push_back(v2); 43189 | v_.push_back(v3); 43190 | v_.push_back(v4); 43191 | return (*this); 43192 | } 43193 | 43194 | std::string name_; 43195 | std::string expression_; 43196 | std::deque<std::string> v_; 43197 | }; 43198 | 43199 | private: 43200 | 43201 | struct base_func : public exprtk::ifunction<T> 43202 | { 43203 | typedef const T& type; 43204 | typedef exprtk::ifunction<T> function_t; 43205 | typedef std::vector<T*> varref_t; 43206 | typedef std::vector<T> var_t; 43207 | typedef std::vector<std::string> str_t; 43208 | typedef std::pair<T*,std::size_t> lvarref_t; 43209 | typedef std::vector<lvarref_t> lvr_vec_t; 43210 | typedef std::vector<std::string*> lstr_vec_t; 43211 | 43212 | using exprtk::ifunction<T>::operator(); 43213 | 43214 | explicit base_func(const std::size_t& pc = 0) 43215 | : exprtk::ifunction<T>(pc) 43216 | , local_var_stack_size(0) 43217 | , stack_depth(0) 43218 | { 43219 | v.resize(pc); 43220 | } 43221 | 43222 | virtual ~base_func() 43223 | {} 43224 | 43225 | #define exprtk_assign(Index) \ 43226 | (*v[Index]) = v##Index; \ 43227 | 43228 | inline void update(const T& v0) 43229 | { 43230 | exprtk_assign(0) 43231 | } 43232 | 43233 | inline void update(const T& v0, const T& v1) 43234 | { 43235 | exprtk_assign(0) exprtk_assign(1) 43236 | } 43237 | 43238 | inline void update(const T& v0, const T& v1, const T& v2) 43239 | { 43240 | exprtk_assign(0) exprtk_assign(1) 43241 | exprtk_assign(2) 43242 | } 43243 | 43244 | inline void update(const T& v0, const T& v1, const T& v2, const T& v3) 43245 | { 43246 | exprtk_assign(0) exprtk_assign(1) 43247 | exprtk_assign(2) exprtk_assign(3) 43248 | } 43249 | 43250 | inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4) 43251 | { 43252 | exprtk_assign(0) exprtk_assign(1) 43253 | exprtk_assign(2) exprtk_assign(3) 43254 | exprtk_assign(4) 43255 | } 43256 | 43257 | inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5) 43258 | { 43259 | exprtk_assign(0) exprtk_assign(1) 43260 | exprtk_assign(2) exprtk_assign(3) 43261 | exprtk_assign(4) exprtk_assign(5) 43262 | } 43263 | 43264 | #ifdef exprtk_assign 43265 | #undef exprtk_assign 43266 | #endif 43267 | 43268 | inline function_t& setup(expression_t& expr) 43269 | { 43270 | expression = expr; 43271 | 43272 | typedef typename expression_t::control_block ctrlblk_t; 43273 | typedef typename ctrlblk_t::local_data_list_t ldl_t; 43274 | typedef typename ctrlblk_t::data_type data_t; 43275 | typedef typename ldl_t::value_type ldl_value_type; 43276 | 43277 | const ldl_t ldl = expr.local_data_list(); 43278 | 43279 | std::vector<std::pair<std::size_t,data_t> > index_list; 43280 | 43281 | for (std::size_t i = 0; i < ldl.size(); ++i) 43282 | { 43283 | exprtk_debug(("base_func::setup() - element[%02d] type: %s size: %d\n", 43284 | static_cast<int>(i), 43285 | expression_t::control_block::to_str(ldl[i].type).c_str(), 43286 | static_cast<int>(ldl[i].size))); 43287 | 43288 | switch (ldl[i].type) 43289 | { 43290 | case ctrlblk_t::e_unknown : continue; 43291 | case ctrlblk_t::e_expr : continue; 43292 | case ctrlblk_t::e_vecholder : continue; 43293 | default : break; 43294 | } 43295 | 43296 | if (ldl[i].size) 43297 | { 43298 | index_list.push_back(std::make_pair(i,ldl[i].type)); 43299 | } 43300 | } 43301 | 43302 | std::size_t input_param_count = 0; 43303 | 43304 | for (std::size_t i = 0; i < index_list.size(); ++i) 43305 | { 43306 | const std::size_t index = index_list[i].first; 43307 | const ldl_value_type& local_var = ldl[index]; 43308 | 43309 | assert(local_var.pointer); 43310 | 43311 | if (i < (index_list.size() - v.size())) 43312 | { 43313 | if (local_var.type == ctrlblk_t::e_string) 43314 | { 43315 | local_str_vars.push_back( 43316 | reinterpret_cast<std::string*>(local_var.pointer)); 43317 | } 43318 | else if ( 43319 | (local_var.type == ctrlblk_t::e_data ) || 43320 | (local_var.type == ctrlblk_t::e_vecdata) 43321 | ) 43322 | { 43323 | local_vars.push_back(std::make_pair( 43324 | reinterpret_cast<T*>(local_var.pointer), 43325 | local_var.size)); 43326 | 43327 | local_var_stack_size += local_var.size; 43328 | } 43329 | } 43330 | else 43331 | { 43332 | v[input_param_count++] = reinterpret_cast<T*>(local_var.pointer); 43333 | } 43334 | } 43335 | 43336 | clear_stack(); 43337 | 43338 | return (*this); 43339 | } 43340 | 43341 | inline void pre() 43342 | { 43343 | if (stack_depth++) 43344 | { 43345 | if (!v.empty()) 43346 | { 43347 | var_t var_stack(v.size(),T(0)); 43348 | copy(v,var_stack); 43349 | input_params_stack.push_back(var_stack); 43350 | } 43351 | 43352 | if (!local_vars.empty()) 43353 | { 43354 | var_t local_vec_frame(local_var_stack_size,T(0)); 43355 | copy(local_vars,local_vec_frame); 43356 | local_var_stack.push_back(local_vec_frame); 43357 | } 43358 | 43359 | if (!local_str_vars.empty()) 43360 | { 43361 | str_t local_str_frame(local_str_vars.size()); 43362 | copy(local_str_vars,local_str_frame); 43363 | local_str_stack.push_back(local_str_frame); 43364 | } 43365 | } 43366 | } 43367 | 43368 | inline void post() 43369 | { 43370 | if (--stack_depth) 43371 | { 43372 | if (!v.empty()) 43373 | { 43374 | copy(input_params_stack.back(), v); 43375 | input_params_stack.pop_back(); 43376 | } 43377 | 43378 | if (!local_vars.empty()) 43379 | { 43380 | copy(local_var_stack.back(), local_vars); 43381 | local_var_stack.pop_back(); 43382 | } 43383 | 43384 | if (!local_str_vars.empty()) 43385 | { 43386 | copy(local_str_stack.back(), local_str_vars); 43387 | local_str_stack.pop_back(); 43388 | } 43389 | } 43390 | } 43391 | 43392 | void copy(const varref_t& src_v, var_t& dest_v) 43393 | { 43394 | for (std::size_t i = 0; i < src_v.size(); ++i) 43395 | { 43396 | dest_v[i] = (*src_v[i]); 43397 | } 43398 | } 43399 | 43400 | void copy(const lstr_vec_t& src_v, str_t& dest_v) 43401 | { 43402 | for (std::size_t i = 0; i < src_v.size(); ++i) 43403 | { 43404 | dest_v[i] = (*src_v[i]); 43405 | } 43406 | } 43407 | 43408 | void copy(const var_t& src_v, varref_t& dest_v) 43409 | { 43410 | for (std::size_t i = 0; i < src_v.size(); ++i) 43411 | { 43412 | (*dest_v[i]) = src_v[i]; 43413 | } 43414 | } 43415 | 43416 | void copy(const lvr_vec_t& src_v, var_t& dest_v) 43417 | { 43418 | typename var_t::iterator itr = dest_v.begin(); 43419 | typedef typename std::iterator_traits<typename var_t::iterator>::difference_type diff_t; 43420 | 43421 | for (std::size_t i = 0; i < src_v.size(); ++i) 43422 | { 43423 | lvarref_t vr = src_v[i]; 43424 | 43425 | if (1 == vr.second) 43426 | *itr++ = (*vr.first); 43427 | else 43428 | { 43429 | std::copy(vr.first, vr.first + vr.second, itr); 43430 | itr += static_cast<diff_t>(vr.second); 43431 | } 43432 | } 43433 | } 43434 | 43435 | void copy(const var_t& src_v, lvr_vec_t& dest_v) 43436 | { 43437 | typename var_t::const_iterator itr = src_v.begin(); 43438 | typedef typename std::iterator_traits<typename var_t::iterator>::difference_type diff_t; 43439 | 43440 | for (std::size_t i = 0; i < dest_v.size(); ++i) 43441 | { 43442 | lvarref_t& vr = dest_v[i]; 43443 | 43444 | assert(vr.first != 0); 43445 | assert(vr.second > 0); 43446 | 43447 | if (1 == vr.second) 43448 | (*vr.first) = *itr++; 43449 | else 43450 | { 43451 | std::copy(itr, itr + static_cast<diff_t>(vr.second), vr.first); 43452 | itr += static_cast<diff_t>(vr.second); 43453 | } 43454 | } 43455 | } 43456 | 43457 | void copy(const str_t& src_str, lstr_vec_t& dest_str) 43458 | { 43459 | assert(src_str.size() == dest_str.size()); 43460 | 43461 | for (std::size_t i = 0; i < dest_str.size(); ++i) 43462 | { 43463 | *dest_str[i] = src_str[i]; 43464 | } 43465 | } 43466 | 43467 | inline void clear_stack() 43468 | { 43469 | for (std::size_t i = 0; i < v.size(); ++i) 43470 | { 43471 | (*v[i]) = 0; 43472 | } 43473 | } 43474 | 43475 | inline virtual T value(expression_t& e) 43476 | { 43477 | return e.value(); 43478 | } 43479 | 43480 | expression_t expression; 43481 | varref_t v; 43482 | lvr_vec_t local_vars; 43483 | lstr_vec_t local_str_vars; 43484 | std::size_t local_var_stack_size; 43485 | std::size_t stack_depth; 43486 | std::deque<var_t> input_params_stack; 43487 | std::deque<var_t> local_var_stack; 43488 | std::deque<str_t> local_str_stack; 43489 | }; 43490 | 43491 | typedef std::map<std::string,base_func*> funcparam_t; 43492 | 43493 | typedef const T& type; 43494 | 43495 | template <typename BaseFuncType> 43496 | struct scoped_bft 43497 | { 43498 | explicit scoped_bft(BaseFuncType& bft) 43499 | : bft_(bft) 43500 | { 43501 | bft_.pre (); 43502 | } 43503 | 43504 | ~scoped_bft() 43505 | { 43506 | bft_.post(); 43507 | } 43508 | 43509 | BaseFuncType& bft_; 43510 | 43511 | private: 43512 | 43513 | scoped_bft(const scoped_bft&) exprtk_delete; 43514 | scoped_bft& operator=(const scoped_bft&) exprtk_delete; 43515 | }; 43516 | 43517 | struct func_0param : public base_func 43518 | { 43519 | using exprtk::ifunction<T>::operator(); 43520 | 43521 | func_0param() : base_func(0) {} 43522 | 43523 | inline T operator() () exprtk_override 43524 | { 43525 | scoped_bft<func_0param> sb(*this); 43526 | return this->value(base_func::expression); 43527 | } 43528 | }; 43529 | 43530 | struct func_1param : public base_func 43531 | { 43532 | using exprtk::ifunction<T>::operator(); 43533 | 43534 | func_1param() : base_func(1) {} 43535 | 43536 | inline T operator() (type v0) exprtk_override 43537 | { 43538 | scoped_bft<func_1param> sb(*this); 43539 | base_func::update(v0); 43540 | return this->value(base_func::expression); 43541 | } 43542 | }; 43543 | 43544 | struct func_2param : public base_func 43545 | { 43546 | using exprtk::ifunction<T>::operator(); 43547 | 43548 | func_2param() : base_func(2) {} 43549 | 43550 | inline T operator() (type v0, type v1) exprtk_override 43551 | { 43552 | scoped_bft<func_2param> sb(*this); 43553 | base_func::update(v0, v1); 43554 | return this->value(base_func::expression); 43555 | } 43556 | }; 43557 | 43558 | struct func_3param : public base_func 43559 | { 43560 | using exprtk::ifunction<T>::operator(); 43561 | 43562 | func_3param() : base_func(3) {} 43563 | 43564 | inline T operator() (type v0, type v1, type v2) exprtk_override 43565 | { 43566 | scoped_bft<func_3param> sb(*this); 43567 | base_func::update(v0, v1, v2); 43568 | return this->value(base_func::expression); 43569 | } 43570 | }; 43571 | 43572 | struct func_4param : public base_func 43573 | { 43574 | using exprtk::ifunction<T>::operator(); 43575 | 43576 | func_4param() : base_func(4) {} 43577 | 43578 | inline T operator() (type v0, type v1, type v2, type v3) exprtk_override 43579 | { 43580 | scoped_bft<func_4param> sb(*this); 43581 | base_func::update(v0, v1, v2, v3); 43582 | return this->value(base_func::expression); 43583 | } 43584 | }; 43585 | 43586 | struct func_5param : public base_func 43587 | { 43588 | using exprtk::ifunction<T>::operator(); 43589 | 43590 | func_5param() : base_func(5) {} 43591 | 43592 | inline T operator() (type v0, type v1, type v2, type v3, type v4) exprtk_override 43593 | { 43594 | scoped_bft<func_5param> sb(*this); 43595 | base_func::update(v0, v1, v2, v3, v4); 43596 | return this->value(base_func::expression); 43597 | } 43598 | }; 43599 | 43600 | struct func_6param : public base_func 43601 | { 43602 | using exprtk::ifunction<T>::operator(); 43603 | 43604 | func_6param() : base_func(6) {} 43605 | 43606 | inline T operator() (type v0, type v1, type v2, type v3, type v4, type v5) exprtk_override 43607 | { 43608 | scoped_bft<func_6param> sb(*this); 43609 | base_func::update(v0, v1, v2, v3, v4, v5); 43610 | return this->value(base_func::expression); 43611 | } 43612 | }; 43613 | 43614 | static T return_value(expression_t& e) 43615 | { 43616 | typedef exprtk::results_context<T> results_context_t; 43617 | typedef typename results_context_t::type_store_t type_t; 43618 | typedef typename type_t::scalar_view scalar_t; 43619 | 43620 | const T result = e.value(); 43621 | 43622 | if (e.return_invoked()) 43623 | { 43624 | // Due to the post compilation checks, it can be safely 43625 | // assumed that there will be at least one parameter 43626 | // and that the first parameter will always be scalar. 43627 | return scalar_t(e.results()[0])(); 43628 | } 43629 | 43630 | return result; 43631 | } 43632 | 43633 | #define def_fp_retval(N) \ 43634 | struct func_##N##param_retval exprtk_final : public func_##N##param \ 43635 | { \ 43636 | inline T value(expression_t& e) exprtk_override \ 43637 | { \ 43638 | return return_value(e); \ 43639 | } \ 43640 | }; \ 43641 | 43642 | def_fp_retval(0) 43643 | def_fp_retval(1) 43644 | def_fp_retval(2) 43645 | def_fp_retval(3) 43646 | def_fp_retval(4) 43647 | def_fp_retval(5) 43648 | def_fp_retval(6) 43649 | 43650 | #undef def_fp_retval 43651 | 43652 | template <typename Allocator, 43653 | template <typename, typename> class Sequence> 43654 | inline bool add(const std::string& name, 43655 | const std::string& expression, 43656 | const Sequence<std::string,Allocator>& var_list, 43657 | const bool override = false) 43658 | { 43659 | const typename std::map<std::string,expression_t>::iterator itr = expr_map_.find(name); 43660 | 43661 | if (expr_map_.end() != itr) 43662 | { 43663 | if (!override) 43664 | { 43665 | exprtk_debug(("Compositor error(add): function '%s' already defined\n", 43666 | name.c_str())); 43667 | 43668 | return false; 43669 | } 43670 | 43671 | remove(name, var_list.size()); 43672 | } 43673 | 43674 | if (compile_expression(name, expression, var_list)) 43675 | { 43676 | const std::size_t n = var_list.size(); 43677 | 43678 | fp_map_[n][name]->setup(expr_map_[name]); 43679 | 43680 | return true; 43681 | } 43682 | else 43683 | { 43684 | exprtk_debug(("Compositor error(add): Failed to compile function '%s'\n", 43685 | name.c_str())); 43686 | 43687 | return false; 43688 | } 43689 | } 43690 | 43691 | public: 43692 | 43693 | function_compositor() 43694 | : parser_(settings_t::default_compile_all_opts + 43695 | settings_t::e_disable_zero_return) 43696 | , fp_map_(7) 43697 | , load_variables_(false) 43698 | , load_vectors_(false) 43699 | {} 43700 | 43701 | explicit function_compositor(const symbol_table_t& st) 43702 | : symbol_table_(st) 43703 | , parser_(settings_t::default_compile_all_opts + 43704 | settings_t::e_disable_zero_return) 43705 | , fp_map_(7) 43706 | , load_variables_(false) 43707 | , load_vectors_(false) 43708 | {} 43709 | 43710 | ~function_compositor() 43711 | { 43712 | clear(); 43713 | } 43714 | 43715 | inline symbol_table_t& symbol_table() 43716 | { 43717 | return symbol_table_; 43718 | } 43719 | 43720 | inline const symbol_table_t& symbol_table() const 43721 | { 43722 | return symbol_table_; 43723 | } 43724 | 43725 | inline void add_auxiliary_symtab(symbol_table_t& symtab) 43726 | { 43727 | auxiliary_symtab_list_.push_back(&symtab); 43728 | } 43729 | 43730 | void load_variables(const bool load = true) 43731 | { 43732 | load_variables_ = load; 43733 | } 43734 | 43735 | void load_vectors(const bool load = true) 43736 | { 43737 | load_vectors_ = load; 43738 | } 43739 | 43740 | inline void register_loop_runtime_check(loop_runtime_check& lrtchk) 43741 | { 43742 | parser_.register_loop_runtime_check(lrtchk); 43743 | } 43744 | 43745 | inline void register_vector_access_runtime_check(vector_access_runtime_check& vartchk) 43746 | { 43747 | parser_.register_vector_access_runtime_check(vartchk); 43748 | } 43749 | 43750 | inline void register_compilation_timeout_check(compilation_check& compchk) 43751 | { 43752 | parser_.register_compilation_timeout_check(compchk); 43753 | } 43754 | 43755 | inline void clear_loop_runtime_check() 43756 | { 43757 | parser_.clear_loop_runtime_check(); 43758 | } 43759 | 43760 | inline void clear_vector_access_runtime_check() 43761 | { 43762 | parser_.clear_vector_access_runtime_check(); 43763 | } 43764 | 43765 | inline void clear_compilation_timeout_check() 43766 | { 43767 | parser_.clear_compilation_timeout_check(); 43768 | } 43769 | 43770 | void clear() 43771 | { 43772 | symbol_table_.clear(); 43773 | expr_map_ .clear(); 43774 | 43775 | for (std::size_t i = 0; i < fp_map_.size(); ++i) 43776 | { 43777 | typename funcparam_t::iterator itr = fp_map_[i].begin(); 43778 | typename funcparam_t::iterator end = fp_map_[i].end (); 43779 | 43780 | while (itr != end) 43781 | { 43782 | delete itr->second; 43783 | ++itr; 43784 | } 43785 | 43786 | fp_map_[i].clear(); 43787 | } 43788 | 43789 | clear_loop_runtime_check (); 43790 | clear_vector_access_runtime_check(); 43791 | clear_compilation_timeout_check (); 43792 | } 43793 | 43794 | inline bool add(const function& f, const bool override = false) 43795 | { 43796 | return add(f.name_, f.expression_, f.v_,override); 43797 | } 43798 | 43799 | inline std::string error() const 43800 | { 43801 | if (!error_list_.empty()) 43802 | { 43803 | return error_list_[0].diagnostic; 43804 | } 43805 | else 43806 | return std::string("No Error"); 43807 | } 43808 | 43809 | inline std::size_t error_count() const 43810 | { 43811 | return error_list_.size(); 43812 | } 43813 | 43814 | inline parser_error::type get_error(const std::size_t& index) const 43815 | { 43816 | if (index < error_list_.size()) 43817 | { 43818 | return error_list_[index]; 43819 | } 43820 | 43821 | throw std::invalid_argument("compositor::get_error() - Invalid error index specified"); 43822 | } 43823 | 43824 | private: 43825 | 43826 | template <typename Allocator, 43827 | template <typename, typename> class Sequence> 43828 | bool compile_expression(const std::string& name, 43829 | const std::string& expression, 43830 | const Sequence<std::string,Allocator>& input_var_list, 43831 | bool return_present = false) 43832 | { 43833 | expression_t compiled_expression; 43834 | symbol_table_t local_symbol_table; 43835 | 43836 | local_symbol_table.load_from(symbol_table_); 43837 | local_symbol_table.add_constants(); 43838 | 43839 | if (load_variables_) 43840 | { 43841 | local_symbol_table.load_variables_from(symbol_table_); 43842 | } 43843 | 43844 | if (load_vectors_) 43845 | { 43846 | local_symbol_table.load_vectors_from(symbol_table_); 43847 | } 43848 | 43849 | error_list_.clear(); 43850 | 43851 | if (!valid(name,input_var_list.size())) 43852 | { 43853 | parser_error::type error = 43854 | parser_error::make_error( 43855 | parser_error::e_parser, 43856 | lexer::token(), 43857 | "ERR285 - Function '" + name + "' is an invalid overload", 43858 | exprtk_error_location); 43859 | 43860 | error_list_.push_back(error); 43861 | return false; 43862 | } 43863 | 43864 | if (!forward(name, 43865 | input_var_list.size(), 43866 | local_symbol_table, 43867 | return_present)) 43868 | return false; 43869 | 43870 | compiled_expression.register_symbol_table(local_symbol_table); 43871 | 43872 | for (std::size_t i = 0; i < auxiliary_symtab_list_.size(); ++i) 43873 | { 43874 | compiled_expression.register_symbol_table((*auxiliary_symtab_list_[i])); 43875 | } 43876 | 43877 | std::string mod_expression; 43878 | 43879 | for (std::size_t i = 0; i < input_var_list.size(); ++i) 43880 | { 43881 | mod_expression += " var " + input_var_list[i] + "{};\n" 43882 | } 43883 | 43884 | if ( 43885 | ('{' == details::front(expression)) && 43886 | ('}' == details::back (expression)) 43887 | ) 43888 | mod_expression += "~" + expression + "" 43889 | else 43890 | mod_expression += "~{" + expression + "};" 43891 | 43892 | if (!parser_.compile(mod_expression,compiled_expression)) 43893 | { 43894 | exprtk_debug(("Compositor Error: %s\n", parser_.error().c_str())); 43895 | exprtk_debug(("Compositor modified expression: \n%s\n", mod_expression.c_str())); 43896 | 43897 | remove(name,input_var_list.size()); 43898 | 43899 | for (std::size_t err_index = 0; err_index < parser_.error_count(); ++err_index) 43900 | { 43901 | error_list_.push_back(parser_.get_error(err_index)); 43902 | } 43903 | 43904 | return false; 43905 | } 43906 | 43907 | if (!return_present && parser_.dec().return_present()) 43908 | { 43909 | remove(name,input_var_list.size()); 43910 | return compile_expression(name, expression, input_var_list, true); 43911 | } 43912 | 43913 | // Make sure every return point has a scalar as its first parameter 43914 | if (parser_.dec().return_present()) 43915 | { 43916 | typedef std::vector<std::string> str_list_t; 43917 | 43918 | str_list_t ret_param_list = parser_.dec().return_param_type_list(); 43919 | 43920 | for (std::size_t i = 0; i < ret_param_list.size(); ++i) 43921 | { 43922 | const std::string& params = ret_param_list[i]; 43923 | 43924 | if (params.empty() || ('T' != params[0])) 43925 | { 43926 | exprtk_debug(("Compositor Error: Return statement in function '%s' is invalid\n", 43927 | name.c_str())); 43928 | 43929 | remove(name,input_var_list.size()); 43930 | 43931 | return false; 43932 | } 43933 | } 43934 | } 43935 | 43936 | expr_map_[name] = compiled_expression; 43937 | 43938 | exprtk::ifunction<T>& ifunc = (*(fp_map_[input_var_list.size()])[name]); 43939 | 43940 | if (symbol_table_.add_function(name,ifunc)) 43941 | return true; 43942 | else 43943 | { 43944 | exprtk_debug(("Compositor Error: Failed to add function '%s' to symbol table\n", 43945 | name.c_str())); 43946 | return false; 43947 | } 43948 | } 43949 | 43950 | inline bool symbol_used(const std::string& symbol) const 43951 | { 43952 | return ( 43953 | symbol_table_.is_variable (symbol) || 43954 | symbol_table_.is_stringvar (symbol) || 43955 | symbol_table_.is_function (symbol) || 43956 | symbol_table_.is_vector (symbol) || 43957 | symbol_table_.is_vararg_function(symbol) 43958 | ); 43959 | } 43960 | 43961 | inline bool valid(const std::string& name, 43962 | const std::size_t& arg_count) const 43963 | { 43964 | if (arg_count > 6) 43965 | return false; 43966 | else if (symbol_used(name)) 43967 | return false; 43968 | else if (fp_map_[arg_count].end() != fp_map_[arg_count].find(name)) 43969 | return false; 43970 | else 43971 | return true; 43972 | } 43973 | 43974 | inline bool forward(const std::string& name, 43975 | const std::size_t& arg_count, 43976 | symbol_table_t& sym_table, 43977 | const bool ret_present = false) 43978 | { 43979 | switch (arg_count) 43980 | { 43981 | #define case_stmt(N) \ 43982 | case N : (fp_map_[arg_count])[name] = \ 43983 | (!ret_present) ? static_cast<base_func*> \ 43984 | (new func_##N##param) : \ 43985 | static_cast<base_func*> \ 43986 | (new func_##N##param_retval) ; \ 43987 | break; \ 43988 | 43989 | case_stmt(0) case_stmt(1) case_stmt(2) 43990 | case_stmt(3) case_stmt(4) case_stmt(5) 43991 | case_stmt(6) 43992 | #undef case_stmt 43993 | } 43994 | 43995 | exprtk::ifunction<T>& ifunc = (*(fp_map_[arg_count])[name]); 43996 | 43997 | return sym_table.add_function(name,ifunc); 43998 | } 43999 | 44000 | inline void remove(const std::string& name, const std::size_t& arg_count) 44001 | { 44002 | if (arg_count > 6) 44003 | return; 44004 | 44005 | const typename std::map<std::string,expression_t>::iterator em_itr = expr_map_.find(name); 44006 | 44007 | if (expr_map_.end() != em_itr) 44008 | { 44009 | expr_map_.erase(em_itr); 44010 | } 44011 | 44012 | const typename funcparam_t::iterator fp_itr = fp_map_[arg_count].find(name); 44013 | 44014 | if (fp_map_[arg_count].end() != fp_itr) 44015 | { 44016 | delete fp_itr->second; 44017 | fp_map_[arg_count].erase(fp_itr); 44018 | } 44019 | 44020 | symbol_table_.remove_function(name); 44021 | } 44022 | 44023 | private: 44024 | 44025 | symbol_table_t symbol_table_; 44026 | parser_t parser_; 44027 | std::map<std::string,expression_t> expr_map_; 44028 | std::vector<funcparam_t> fp_map_; 44029 | std::vector<symbol_table_t*> auxiliary_symtab_list_; 44030 | std::deque<parser_error::type> error_list_; 44031 | bool load_variables_; 44032 | bool load_vectors_; 44033 | }; // class function_compositor 44034 | 44035 | } // namespace exprtk 44036 | 44037 | #if defined(_MSC_VER) || defined(_WIN32) || defined(__WIN32__) || defined(WIN32) 44038 | # ifndef NOMINMAX 44039 | # define NOMINMAX 44040 | # endif 44041 | # ifndef WIN32_LEAN_AND_MEAN 44042 | # define WIN32_LEAN_AND_MEAN 44043 | # endif 44044 | # include 44045 | # include 44046 | #else 44047 | # include 44048 | # include 44049 | # include 44050 | #endif 44051 | 44052 | namespace exprtk 44053 | { 44054 | class timer 44055 | { 44056 | public: 44057 | 44058 | #if defined(_MSC_VER) || defined(_WIN32) || defined(__WIN32__) || defined(WIN32) 44059 | timer() 44060 | : in_use_(false) 44061 | , start_time_{ {0, 0} } 44062 | , stop_time_ { {0, 0} } 44063 | { 44064 | QueryPerformanceFrequency(&clock_frequency_); 44065 | } 44066 | 44067 | inline void start() 44068 | { 44069 | in_use_ = true; 44070 | QueryPerformanceCounter(&start_time_); 44071 | } 44072 | 44073 | inline void stop() 44074 | { 44075 | QueryPerformanceCounter(&stop_time_); 44076 | in_use_ = false; 44077 | } 44078 | 44079 | inline double time() const 44080 | { 44081 | return (1.0 * (stop_time_.QuadPart - start_time_.QuadPart)) / (1.0 * clock_frequency_.QuadPart); 44082 | } 44083 | 44084 | #else 44085 | 44086 | timer() 44087 | : in_use_(false) 44088 | { 44089 | start_time_.tv_sec = 0; 44090 | start_time_.tv_usec = 0; 44091 | 44092 | stop_time_.tv_sec = 0; 44093 | stop_time_.tv_usec = 0; 44094 | } 44095 | 44096 | inline void start() 44097 | { 44098 | in_use_ = true; 44099 | gettimeofday(&start_time_,0); 44100 | } 44101 | 44102 | inline void stop() 44103 | { 44104 | gettimeofday(&stop_time_, 0); 44105 | in_use_ = false; 44106 | } 44107 | 44108 | inline unsigned long long int usec_time() const 44109 | { 44110 | if (!in_use_) 44111 | { 44112 | if (stop_time_.tv_sec >= start_time_.tv_sec) 44113 | { 44114 | return 1000000LLU * static_cast<details::_uint64_t>(stop_time_.tv_sec - start_time_.tv_sec ) + 44115 | static_cast<details::_uint64_t>(stop_time_.tv_usec - start_time_.tv_usec) ; 44116 | } 44117 | else 44118 | return std::numeric_limits<details::_uint64_t>::max(); 44119 | } 44120 | else 44121 | return std::numeric_limits<details::_uint64_t>::max(); 44122 | } 44123 | 44124 | inline double time() const 44125 | { 44126 | return usec_time() * 0.000001; 44127 | } 44128 | 44129 | #endif 44130 | 44131 | inline bool in_use() const 44132 | { 44133 | return in_use_; 44134 | } 44135 | 44136 | private: 44137 | 44138 | bool in_use_; 44139 | 44140 | #if defined(_MSC_VER) || defined(_WIN32) || defined(__WIN32__) || defined(WIN32) 44141 | LARGE_INTEGER start_time_; 44142 | LARGE_INTEGER stop_time_; 44143 | LARGE_INTEGER clock_frequency_; 44144 | #else 44145 | struct timeval start_time_; 44146 | struct timeval stop_time_; 44147 | #endif 44148 | }; 44149 | 44150 | template <typename T> 44151 | struct type_defs 44152 | { 44153 | typedef symbol_table<T> symbol_table_t; 44154 | typedef expression<T> expression_t; 44155 | typedef parser<T> parser_t; 44156 | typedef parser_error::type error_t; 44157 | typedef function_compositor<T> compositor_t; 44158 | typedef typename compositor_t::function function_t; 44159 | }; 44160 | 44161 | } // namespace exprtk 44162 | 44163 | #ifndef exprtk_disable_rtl_io 44164 | namespace exprtk 44165 | { 44166 | namespace rtl { namespace io { namespace details 44167 | { 44168 | template <typename T> 44169 | inline void print_type(const std::string& fmt, 44170 | const T v, 44171 | exprtk::details::numeric::details::real_type_tag) 44172 | { 44173 | #if defined(__clang__) 44174 | #pragma clang diagnostic push 44175 | #pragma clang diagnostic ignored "-Wformat-nonliteral" 44176 | #elif defined(__GNUC__) || defined(__GNUG__) 44177 | #pragma GCC diagnostic push 44178 | #pragma GCC diagnostic ignored "-Wformat-nonliteral" 44179 | #elif defined(_MSC_VER) 44180 | #endif 44181 | 44182 | printf(fmt.c_str(), v); 44183 | 44184 | #if defined(__clang__) 44185 | #pragma clang diagnostic pop 44186 | #elif defined(__GNUC__) || defined(__GNUG__) 44187 | #pragma GCC diagnostic pop 44188 | #elif defined(_MSC_VER) 44189 | #endif 44190 | } 44191 | 44192 | template <typename T> 44193 | struct print_impl 44194 | { 44195 | typedef typename igeneric_function<T>::generic_type generic_type; 44196 | typedef typename igeneric_function<T>::parameter_list_t parameter_list_t; 44197 | typedef typename generic_type::scalar_view scalar_t; 44198 | typedef typename generic_type::vector_view vector_t; 44199 | typedef typename generic_type::string_view string_t; 44200 | typedef typename exprtk::details::numeric::details::number_type<T>::type num_type; 44201 | 44202 | static void process(const std::string& scalar_format, parameter_list_t parameters) 44203 | { 44204 | for (std::size_t i = 0; i < parameters.size(); ++i) 44205 | { 44206 | generic_type& gt = parameters[i]; 44207 | 44208 | switch (gt.type) 44209 | { 44210 | case generic_type::e_scalar : print(scalar_format,scalar_t(gt)); 44211 | break; 44212 | 44213 | case generic_type::e_vector : print(scalar_format,vector_t(gt)); 44214 | break; 44215 | 44216 | case generic_type::e_string : print(string_t(gt)); 44217 | break; 44218 | 44219 | default : continue; 44220 | } 44221 | } 44222 | } 44223 | 44224 | static inline void print(const std::string& scalar_format, const scalar_t& s) 44225 | { 44226 | print_type(scalar_format,s(),num_type()); 44227 | } 44228 | 44229 | static inline void print(const std::string& scalar_format, const vector_t& v) 44230 | { 44231 | for (std::size_t i = 0; i < v.size(); ++i) 44232 | { 44233 | print_type(scalar_format,v[i],num_type()); 44234 | 44235 | if ((i + 1) < v.size()) 44236 | printf(" "); 44237 | } 44238 | } 44239 | 44240 | static inline void print(const string_t& s) 44241 | { 44242 | printf("%s",to_str(s).c_str()); 44243 | } 44244 | }; 44245 | 44246 | } // namespace exprtk::rtl::io::details 44247 | 44248 | template <typename T> 44249 | struct print exprtk_final : public exprtk::igeneric_function<T> 44250 | { 44251 | typedef typename igeneric_function<T>::parameter_list_t parameter_list_t; 44252 | 44253 | using exprtk::igeneric_function<T>::operator(); 44254 | 44255 | explicit print(const std::string& scalar_format = "%10.5f") 44256 | : scalar_format_(scalar_format) 44257 | { 44258 | exprtk::enable_zero_parameters(*this); 44259 | } 44260 | 44261 | inline T operator() (parameter_list_t parameters) exprtk_override 44262 | { 44263 | details::print_impl<T>::process(scalar_format_,parameters); 44264 | return T(0); 44265 | } 44266 | 44267 | std::string scalar_format_; 44268 | }; 44269 | 44270 | template <typename T> 44271 | struct println exprtk_final : public exprtk::igeneric_function<T> 44272 | { 44273 | typedef typename igeneric_function<T>::parameter_list_t parameter_list_t; 44274 | 44275 | using exprtk::igeneric_function<T>::operator(); 44276 | 44277 | explicit println(const std::string& scalar_format = "%10.5f") 44278 | : scalar_format_(scalar_format) 44279 | { 44280 | exprtk::enable_zero_parameters(*this); 44281 | } 44282 | 44283 | inline T operator() (parameter_list_t parameters) exprtk_override 44284 | { 44285 | details::print_impl<T>::process(scalar_format_,parameters); 44286 | printf("\n"); 44287 | return T(0); 44288 | } 44289 | 44290 | std::string scalar_format_; 44291 | }; 44292 | 44293 | template <typename T> 44294 | struct package 44295 | { 44296 | print <T> p; 44297 | println<T> pl; 44298 | 44299 | bool register_package(exprtk::symbol_table<T>& symtab) 44300 | { 44301 | #define exprtk_register_function(FunctionName, FunctionType) \ 44302 | if (!symtab.add_function(FunctionName,FunctionType)) \ 44303 | { \ 44304 | exprtk_debug(( \ 44305 | "exprtk::rtl::io::register_package - Failed to add function: %s\n", \ 44306 | FunctionName)); \ 44307 | return false; \ 44308 | } \ 44309 | 44310 | exprtk_register_function("print" , p ) 44311 | exprtk_register_function("println", pl) 44312 | #undef exprtk_register_function 44313 | 44314 | return true; 44315 | } 44316 | }; 44317 | 44318 | } // namespace exprtk::rtl::io 44319 | } // namespace exprtk::rtl 44320 | } // namespace exprtk 44321 | #endif 44322 | 44323 | #ifndef exprtk_disable_rtl_io_file 44324 | #include 44325 | namespace exprtk 44326 | { 44327 | namespace rtl { namespace io { namespace file { namespace details 44328 | { 44329 | using ::exprtk::details::char_ptr; 44330 | using ::exprtk::details::char_cptr; 44331 | 44332 | enum file_mode 44333 | { 44334 | e_error = 0, 44335 | e_read = 1, 44336 | e_write = 2, 44337 | e_rdwrt = 4 44338 | }; 44339 | 44340 | struct file_descriptor 44341 | { 44342 | file_descriptor(const std::string& fname, const std::string& access) 44343 | : stream_ptr(0) 44344 | , mode(get_file_mode(access)) 44345 | , file_name(fname) 44346 | {} 44347 | 44348 | void* stream_ptr; 44349 | file_mode mode; 44350 | std::string file_name; 44351 | 44352 | bool open() 44353 | { 44354 | if (e_read == mode) 44355 | { 44356 | std::ifstream* stream = new std::ifstream(file_name.c_str(),std::ios::binary); 44357 | 44358 | if (!(*stream)) 44359 | { 44360 | file_name.clear(); 44361 | delete stream; 44362 | 44363 | return false; 44364 | } 44365 | 44366 | stream_ptr = stream; 44367 | 44368 | return true; 44369 | } 44370 | else if (e_write == mode) 44371 | { 44372 | std::ofstream* stream = new std::ofstream(file_name.c_str(),std::ios::binary); 44373 | 44374 | if (!(*stream)) 44375 | { 44376 | file_name.clear(); 44377 | delete stream; 44378 | 44379 | return false; 44380 | } 44381 | 44382 | stream_ptr = stream; 44383 | 44384 | return true; 44385 | } 44386 | else if (e_rdwrt == mode) 44387 | { 44388 | std::fstream* stream = new std::fstream(file_name.c_str(),std::ios::binary); 44389 | 44390 | if (!(*stream)) 44391 | { 44392 | file_name.clear(); 44393 | delete stream; 44394 | 44395 | return false; 44396 | } 44397 | 44398 | stream_ptr = stream; 44399 | 44400 | return true; 44401 | } 44402 | 44403 | return false; 44404 | } 44405 | 44406 | template <typename Stream, typename Ptr> 44407 | void close(Ptr& p) 44408 | { 44409 | Stream* stream = reinterpret_cast<Stream*>(p); 44410 | stream->close(); 44411 | delete stream; 44412 | p = reinterpret_cast<Ptr>(0); 44413 | } 44414 | 44415 | bool close() 44416 | { 44417 | switch (mode) 44418 | { 44419 | case e_read : close<std::ifstream>(stream_ptr); 44420 | break; 44421 | 44422 | case e_write : close<std::ofstream>(stream_ptr); 44423 | break; 44424 | 44425 | case e_rdwrt : close<std::fstream> (stream_ptr); 44426 | break; 44427 | 44428 | default : return false; 44429 | } 44430 | 44431 | return true; 44432 | } 44433 | 44434 | template <typename View> 44435 | bool write(const View& view, const std::size_t amount, const std::size_t offset = 0) 44436 | { 44437 | switch (mode) 44438 | { 44439 | case e_write : reinterpret_cast<std::ofstream*>(stream_ptr)-> 44440 | write(reinterpret_cast<char_cptr>(view.begin() + offset), amount * sizeof(typename View::value_t)); 44441 | break; 44442 | 44443 | case e_rdwrt : reinterpret_cast<std::fstream*>(stream_ptr)-> 44444 | write(reinterpret_cast<char_cptr>(view.begin() + offset) , amount * sizeof(typename View::value_t)); 44445 | break; 44446 | 44447 | default : return false; 44448 | } 44449 | 44450 | return true; 44451 | } 44452 | 44453 | template <typename View> 44454 | bool read(View& view, const std::size_t amount, const std::size_t offset = 0) 44455 | { 44456 | switch (mode) 44457 | { 44458 | case e_read : reinterpret_cast<std::ifstream*>(stream_ptr)-> 44459 | read(reinterpret_cast<char_ptr>(view.begin() + offset), amount * sizeof(typename View::value_t)); 44460 | break; 44461 | 44462 | case e_rdwrt : reinterpret_cast<std::fstream*>(stream_ptr)-> 44463 | read(reinterpret_cast<char_ptr>(view.begin() + offset) , amount * sizeof(typename View::value_t)); 44464 | break; 44465 | 44466 | default : return false; 44467 | } 44468 | 44469 | return true; 44470 | } 44471 | 44472 | bool getline(std::string& s) 44473 | { 44474 | switch (mode) 44475 | { 44476 | case e_read : return (!!std::getline(*reinterpret_cast<std::ifstream*>(stream_ptr),s)); 44477 | case e_rdwrt : return (!!std::getline(*reinterpret_cast<std::fstream* >(stream_ptr),s)); 44478 | default : return false; 44479 | } 44480 | } 44481 | 44482 | bool eof() const 44483 | { 44484 | switch (mode) 44485 | { 44486 | case e_read : return reinterpret_cast<std::ifstream*>(stream_ptr)->eof(); 44487 | case e_write : return reinterpret_cast<std::ofstream*>(stream_ptr)->eof(); 44488 | case e_rdwrt : return reinterpret_cast<std::fstream* >(stream_ptr)->eof(); 44489 | default : return true; 44490 | } 44491 | } 44492 | 44493 | file_mode get_file_mode(const std::string& access) const 44494 | { 44495 | if (access.empty() || access.size() > 2) 44496 | return e_error; 44497 | 44498 | std::size_t w_cnt = 0; 44499 | std::size_t r_cnt = 0; 44500 | 44501 | for (std::size_t i = 0; i < access.size(); ++i) 44502 | { 44503 | switch (std::tolower(access[i])) 44504 | { 44505 | case 'r' : r_cnt++; break; 44506 | case 'w' : w_cnt++; break; 44507 | default : return e_error; 44508 | } 44509 | } 44510 | 44511 | if ((0 == r_cnt) && (0 == w_cnt)) 44512 | return e_error; 44513 | else if ((r_cnt > 1) || (w_cnt > 1)) 44514 | return e_error; 44515 | else if ((1 == r_cnt) && (1 == w_cnt)) 44516 | return e_rdwrt; 44517 | else if (1 == r_cnt) 44518 | return e_read; 44519 | else 44520 | return e_write; 44521 | } 44522 | }; 44523 | 44524 | template <typename T> 44525 | file_descriptor* make_handle(T v) 44526 | { 44527 | const std::size_t fd_size = sizeof(details::file_descriptor*); 44528 | details::file_descriptor* fd = reinterpret_cast<file_descriptor*>(0); 44529 | 44530 | std::memcpy(reinterpret_cast<char_ptr >(&fd), 44531 | reinterpret_cast<char_cptr>(&v ), 44532 | fd_size); 44533 | return fd; 44534 | } 44535 | 44536 | template <typename T> 44537 | void perform_check() 44538 | { 44539 | #ifdef _MSC_VER 44540 | #pragma warning(push) 44541 | #pragma warning(disable: 4127) 44542 | #endif 44543 | if (sizeof(T) < sizeof(void*)) 44544 | { 44545 | throw std::runtime_error("exprtk::rtl::io::file - Error - pointer size larger than holder."); 44546 | } 44547 | #ifdef _MSC_VER 44548 | #pragma warning(pop) 44549 | #endif 44550 | assert(sizeof(T) >= sizeof(void*)); 44551 | } 44552 | 44553 | } // namespace exprtk::rtl::io::file::details 44554 | 44555 | template <typename T> 44556 | class open exprtk_final : public exprtk::igeneric_function<T> 44557 | { 44558 | public: 44559 | 44560 | typedef typename exprtk::igeneric_function<T> igfun_t; 44561 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44562 | typedef typename igfun_t::generic_type generic_type; 44563 | typedef typename generic_type::string_view string_t; 44564 | 44565 | using igfun_t::operator(); 44566 | 44567 | open() 44568 | : exprtk::igeneric_function<T>("S|SS") 44569 | { details::perform_check<T>(); } 44570 | 44571 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44572 | { 44573 | const std::string file_name = to_str(string_t(parameters[0])); 44574 | 44575 | if (file_name.empty()) 44576 | { 44577 | return T(0); 44578 | } 44579 | 44580 | if ((1 == ps_index) && (0 == string_t(parameters[1]).size())) 44581 | { 44582 | return T(0); 44583 | } 44584 | 44585 | const std::string access = 44586 | (0 == ps_index) ? "r" : to_str(string_t(parameters[1])); 44587 | 44588 | details::file_descriptor* fd = new details::file_descriptor(file_name,access); 44589 | 44590 | if (fd->open()) 44591 | { 44592 | T t = T(0); 44593 | 44594 | const std::size_t fd_size = sizeof(details::file_descriptor*); 44595 | 44596 | std::memcpy(reinterpret_cast<char*>(&t ), 44597 | reinterpret_cast<char*>(&fd), 44598 | fd_size); 44599 | return t; 44600 | } 44601 | else 44602 | { 44603 | delete fd; 44604 | return T(0); 44605 | } 44606 | } 44607 | }; 44608 | 44609 | template <typename T> 44610 | struct close exprtk_final : public exprtk::ifunction<T> 44611 | { 44612 | using exprtk::ifunction<T>::operator(); 44613 | 44614 | close() 44615 | : exprtk::ifunction<T>(1) 44616 | { details::perform_check<T>(); } 44617 | 44618 | inline T operator() (const T& v) exprtk_override 44619 | { 44620 | details::file_descriptor* fd = details::make_handle(v); 44621 | 44622 | if (!fd->close()) 44623 | return T(0); 44624 | 44625 | delete fd; 44626 | 44627 | return T(1); 44628 | } 44629 | }; 44630 | 44631 | template <typename T> 44632 | class write exprtk_final : public exprtk::igeneric_function<T> 44633 | { 44634 | public: 44635 | 44636 | typedef typename exprtk::igeneric_function<T> igfun_t; 44637 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44638 | typedef typename igfun_t::generic_type generic_type; 44639 | typedef typename generic_type::string_view string_t; 44640 | typedef typename generic_type::scalar_view scalar_t; 44641 | typedef typename generic_type::vector_view vector_t; 44642 | 44643 | using igfun_t::operator(); 44644 | 44645 | write() 44646 | : igfun_t("TS|TST|TV|TVT") 44647 | { details::perform_check<T>(); } 44648 | 44649 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44650 | { 44651 | details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])()); 44652 | 44653 | switch (ps_index) 44654 | { 44655 | case 0 : { 44656 | const string_t buffer(parameters[1]); 44657 | const std::size_t amount = buffer.size(); 44658 | return T(fd->write(buffer, amount) ? 1 : 0); 44659 | } 44660 | 44661 | case 1 : { 44662 | const string_t buffer(parameters[1]); 44663 | const std::size_t amount = 44664 | std::min(buffer.size(), 44665 | static_cast<std::size_t>(scalar_t(parameters[2])())); 44666 | return T(fd->write(buffer, amount) ? 1 : 0); 44667 | } 44668 | 44669 | case 2 : { 44670 | const vector_t vec(parameters[1]); 44671 | const std::size_t amount = vec.size(); 44672 | return T(fd->write(vec, amount) ? 1 : 0); 44673 | } 44674 | 44675 | case 3 : { 44676 | const vector_t vec(parameters[1]); 44677 | const std::size_t amount = 44678 | std::min(vec.size(), 44679 | static_cast<std::size_t>(scalar_t(parameters[2])())); 44680 | return T(fd->write(vec, amount) ? 1 : 0); 44681 | } 44682 | } 44683 | 44684 | return T(0); 44685 | } 44686 | }; 44687 | 44688 | template <typename T> 44689 | class read exprtk_final : public exprtk::igeneric_function<T> 44690 | { 44691 | public: 44692 | 44693 | typedef typename exprtk::igeneric_function<T> igfun_t; 44694 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44695 | typedef typename igfun_t::generic_type generic_type; 44696 | typedef typename generic_type::string_view string_t; 44697 | typedef typename generic_type::scalar_view scalar_t; 44698 | typedef typename generic_type::vector_view vector_t; 44699 | 44700 | using igfun_t::operator(); 44701 | 44702 | read() 44703 | : igfun_t("TS|TST|TV|TVT") 44704 | { details::perform_check<T>(); } 44705 | 44706 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44707 | { 44708 | details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])()); 44709 | 44710 | switch (ps_index) 44711 | { 44712 | case 0 : { 44713 | string_t buffer(parameters[1]); 44714 | const std::size_t amount = buffer.size(); 44715 | return T(fd->read(buffer,amount) ? 1 : 0); 44716 | } 44717 | 44718 | case 1 : { 44719 | string_t buffer(parameters[1]); 44720 | const std::size_t amount = 44721 | std::min(buffer.size(), 44722 | static_cast<std::size_t>(scalar_t(parameters[2])())); 44723 | return T(fd->read(buffer,amount) ? 1 : 0); 44724 | } 44725 | 44726 | case 2 : { 44727 | vector_t vec(parameters[1]); 44728 | const std::size_t amount = vec.size(); 44729 | return T(fd->read(vec,amount) ? 1 : 0); 44730 | } 44731 | 44732 | case 3 : { 44733 | vector_t vec(parameters[1]); 44734 | const std::size_t amount = 44735 | std::min(vec.size(), 44736 | static_cast<std::size_t>(scalar_t(parameters[2])())); 44737 | return T(fd->read(vec,amount) ? 1 : 0); 44738 | } 44739 | } 44740 | 44741 | return T(0); 44742 | } 44743 | }; 44744 | 44745 | template <typename T> 44746 | class getline exprtk_final : public exprtk::igeneric_function<T> 44747 | { 44748 | public: 44749 | 44750 | typedef typename exprtk::igeneric_function<T> igfun_t; 44751 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44752 | typedef typename igfun_t::generic_type generic_type; 44753 | typedef typename generic_type::string_view string_t; 44754 | typedef typename generic_type::scalar_view scalar_t; 44755 | 44756 | using igfun_t::operator(); 44757 | 44758 | getline() 44759 | : igfun_t("T",igfun_t::e_rtrn_string) 44760 | { details::perform_check<T>(); } 44761 | 44762 | inline T operator() (std::string& result, parameter_list_t parameters) exprtk_override 44763 | { 44764 | details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])()); 44765 | return T(fd->getline(result) ? 1 : 0); 44766 | } 44767 | }; 44768 | 44769 | template <typename T> 44770 | struct eof exprtk_final : public exprtk::ifunction<T> 44771 | { 44772 | using exprtk::ifunction<T>::operator(); 44773 | 44774 | eof() 44775 | : exprtk::ifunction<T>(1) 44776 | { details::perform_check<T>(); } 44777 | 44778 | inline T operator() (const T& v) exprtk_override 44779 | { 44780 | details::file_descriptor* fd = details::make_handle(v); 44781 | return (fd->eof() ? T(1) : T(0)); 44782 | } 44783 | }; 44784 | 44785 | template <typename T> 44786 | struct package 44787 | { 44788 | open <T> o; 44789 | close <T> c; 44790 | write <T> w; 44791 | read <T> r; 44792 | getline<T> g; 44793 | eof <T> e; 44794 | 44795 | bool register_package(exprtk::symbol_table<T>& symtab) 44796 | { 44797 | #define exprtk_register_function(FunctionName, FunctionType) \ 44798 | if (!symtab.add_function(FunctionName,FunctionType)) \ 44799 | { \ 44800 | exprtk_debug(( \ 44801 | "exprtk::rtl::io::file::register_package - Failed to add function: %s\n", \ 44802 | FunctionName)); \ 44803 | return false; \ 44804 | } \ 44805 | 44806 | exprtk_register_function("open" , o) 44807 | exprtk_register_function("close" , c) 44808 | exprtk_register_function("write" , w) 44809 | exprtk_register_function("read" , r) 44810 | exprtk_register_function("getline" , g) 44811 | exprtk_register_function("eof" , e) 44812 | #undef exprtk_register_function 44813 | 44814 | return true; 44815 | } 44816 | }; 44817 | 44818 | } // namespace exprtk::rtl::io::file 44819 | } // namespace exprtk::rtl::io 44820 | } // namespace exprtk::rtl 44821 | } // namespace exprtk 44822 | #endif 44823 | 44824 | #ifndef exprtk_disable_rtl_vecops 44825 | namespace exprtk 44826 | { 44827 | namespace rtl { namespace vecops { 44828 | 44829 | namespace helper 44830 | { 44831 | template <typename Vector> 44832 | inline bool invalid_range(const Vector& v, const std::size_t r0, const std::size_t r1) 44833 | { 44834 | if (r0 > (v.size() - 1)) 44835 | return true; 44836 | else if (r1 > (v.size() - 1)) 44837 | return true; 44838 | else if (r1 < r0) 44839 | return true; 44840 | else 44841 | return false; 44842 | } 44843 | 44844 | template <typename Vector> 44845 | inline bool invalid_shift(const Vector& v, const std::size_t& r1, const std::size_t& s) 44846 | { 44847 | return s >= (v.size() - r1); 44848 | } 44849 | 44850 | inline bool invalid_stride(const std::size_t& stride) 44851 | { 44852 | return 0 == stride; 44853 | } 44854 | 44855 | template <typename T> 44856 | struct load_vector_range 44857 | { 44858 | typedef typename exprtk::igeneric_function<T> igfun_t; 44859 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44860 | typedef typename igfun_t::generic_type generic_type; 44861 | typedef typename generic_type::scalar_view scalar_t; 44862 | typedef typename generic_type::vector_view vector_t; 44863 | 44864 | static inline bool process(parameter_list_t& parameters, 44865 | std::size_t& r0, std::size_t& r1, 44866 | const std::size_t& r0_prmidx, 44867 | const std::size_t& r1_prmidx, 44868 | const std::size_t vec_idx = 0) 44869 | { 44870 | if (r0_prmidx >= parameters.size()) 44871 | return false; 44872 | 44873 | if (r1_prmidx >= parameters.size()) 44874 | return false; 44875 | 44876 | if (!scalar_t(parameters[r0_prmidx]).to_uint(r0)) 44877 | return false; 44878 | 44879 | if (!scalar_t(parameters[r1_prmidx]).to_uint(r1)) 44880 | return false; 44881 | 44882 | return !invalid_range(vector_t(parameters[vec_idx]), r0, r1); 44883 | } 44884 | }; 44885 | } 44886 | 44887 | namespace details 44888 | { 44889 | template <typename T> 44890 | inline void kahan_sum(T& sum, T& error, const T v) 44891 | { 44892 | const T x = v - error; 44893 | const T y = sum + x; 44894 | error = (y - sum) - x; 44895 | sum = y; 44896 | } 44897 | 44898 | } // namespace exprtk::rtl::details 44899 | 44900 | template <typename T> 44901 | class all_true exprtk_final : public exprtk::igeneric_function<T> 44902 | { 44903 | public: 44904 | 44905 | typedef typename exprtk::igeneric_function<T> igfun_t; 44906 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44907 | typedef typename igfun_t::generic_type generic_type; 44908 | typedef typename generic_type::scalar_view scalar_t; 44909 | typedef typename generic_type::vector_view vector_t; 44910 | 44911 | using igfun_t::operator(); 44912 | 44913 | all_true() 44914 | : exprtk::igeneric_function<T>("V|VTT|T*") 44915 | /* 44916 | Overloads: 44917 | 0. V - vector 44918 | 1. VTT - vector, r0, r1 44919 | 2. T* - T....T 44920 | */ 44921 | {} 44922 | 44923 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44924 | { 44925 | if (2 == ps_index) 44926 | { 44927 | for (std::size_t i = 0; i < parameters.size(); ++i) 44928 | { 44929 | if (scalar_t(parameters[i])() == T(0)) 44930 | { 44931 | return T(0); 44932 | } 44933 | } 44934 | } 44935 | else 44936 | { 44937 | const vector_t vec(parameters[0]); 44938 | 44939 | std::size_t r0 = 0; 44940 | std::size_t r1 = vec.size() - 1; 44941 | 44942 | if ( 44943 | (1 == ps_index) && 44944 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 44945 | ) 44946 | { 44947 | return std::numeric_limits<T>::quiet_NaN(); 44948 | } 44949 | 44950 | for (std::size_t i = r0; i <= r1; ++i) 44951 | { 44952 | if (vec[i] == T(0)) 44953 | { 44954 | return T(0); 44955 | } 44956 | } 44957 | } 44958 | 44959 | return T(1); 44960 | } 44961 | }; 44962 | 44963 | template <typename T> 44964 | class all_false exprtk_final : public exprtk::igeneric_function<T> 44965 | { 44966 | public: 44967 | 44968 | typedef typename exprtk::igeneric_function<T> igfun_t; 44969 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44970 | typedef typename igfun_t::generic_type generic_type; 44971 | typedef typename generic_type::scalar_view scalar_t; 44972 | typedef typename generic_type::vector_view vector_t; 44973 | 44974 | using igfun_t::operator(); 44975 | 44976 | all_false() 44977 | : exprtk::igeneric_function<T>("V|VTT|T*") 44978 | /* 44979 | Overloads: 44980 | 0. V - vector 44981 | 1. VTT - vector, r0, r1 44982 | 2. T* - T....T 44983 | */ 44984 | {} 44985 | 44986 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44987 | { 44988 | if (2 == ps_index) 44989 | { 44990 | for (std::size_t i = 0; i < parameters.size(); ++i) 44991 | { 44992 | if (scalar_t(parameters[i])() != T(0)) 44993 | { 44994 | return T(0); 44995 | } 44996 | } 44997 | } 44998 | else 44999 | { 45000 | const vector_t vec(parameters[0]); 45001 | 45002 | std::size_t r0 = 0; 45003 | std::size_t r1 = vec.size() - 1; 45004 | 45005 | if ( 45006 | (1 == ps_index) && 45007 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 45008 | ) 45009 | { 45010 | return std::numeric_limits<T>::quiet_NaN(); 45011 | } 45012 | 45013 | for (std::size_t i = r0; i <= r1; ++i) 45014 | { 45015 | if (vec[i] != T(0)) 45016 | { 45017 | return T(0); 45018 | } 45019 | } 45020 | } 45021 | 45022 | return T(1); 45023 | } 45024 | }; 45025 | 45026 | template <typename T> 45027 | class any_true exprtk_final : public exprtk::igeneric_function<T> 45028 | { 45029 | public: 45030 | 45031 | typedef typename exprtk::igeneric_function<T> igfun_t; 45032 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45033 | typedef typename igfun_t::generic_type generic_type; 45034 | typedef typename generic_type::scalar_view scalar_t; 45035 | typedef typename generic_type::vector_view vector_t; 45036 | 45037 | using igfun_t::operator(); 45038 | 45039 | any_true() 45040 | : exprtk::igeneric_function<T>("V|VTT|T*") 45041 | /* 45042 | Overloads: 45043 | 0. V - vector 45044 | 1. VTT - vector, r0, r1 45045 | 2. T* - T....T 45046 | */ 45047 | {} 45048 | 45049 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 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)) 45056 | { 45057 | return T(1); 45058 | } 45059 | } 45060 | } 45061 | else 45062 | { 45063 | const vector_t vec(parameters[0]); 45064 | 45065 | std::size_t r0 = 0; 45066 | std::size_t r1 = vec.size() - 1; 45067 | 45068 | if ( 45069 | (1 == ps_index) && 45070 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 45071 | ) 45072 | { 45073 | return std::numeric_limits<T>::quiet_NaN(); 45074 | } 45075 | 45076 | for (std::size_t i = r0; i <= r1; ++i) 45077 | { 45078 | if (vec[i] != T(0)) 45079 | { 45080 | return T(1); 45081 | } 45082 | } 45083 | } 45084 | 45085 | return T(0); 45086 | } 45087 | }; 45088 | 45089 | template <typename T> 45090 | class any_false exprtk_final : public exprtk::igeneric_function<T> 45091 | { 45092 | public: 45093 | 45094 | typedef typename exprtk::igeneric_function<T> igfun_t; 45095 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45096 | typedef typename igfun_t::generic_type generic_type; 45097 | typedef typename generic_type::scalar_view scalar_t; 45098 | typedef typename generic_type::vector_view vector_t; 45099 | 45100 | using igfun_t::operator(); 45101 | 45102 | any_false() 45103 | : exprtk::igeneric_function<T>("V|VTT|T*") 45104 | /* 45105 | Overloads: 45106 | 0. V - vector 45107 | 1. VTT - vector, r0, r1 45108 | 2. T* - T....T 45109 | */ 45110 | {} 45111 | 45112 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45113 | { 45114 | if (2 == ps_index) 45115 | { 45116 | for (std::size_t i = 0; i < parameters.size(); ++i) 45117 | { 45118 | if (scalar_t(parameters[i])() == T(0)) 45119 | { 45120 | return T(1); 45121 | } 45122 | } 45123 | } 45124 | else 45125 | { 45126 | const vector_t vec(parameters[0]); 45127 | 45128 | std::size_t r0 = 0; 45129 | std::size_t r1 = vec.size() - 1; 45130 | 45131 | if ( 45132 | (1 == ps_index) && 45133 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 45134 | ) 45135 | { 45136 | return std::numeric_limits<T>::quiet_NaN(); 45137 | } 45138 | 45139 | for (std::size_t i = r0; i <= r1; ++i) 45140 | { 45141 | if (vec[i] == T(0)) 45142 | { 45143 | return T(1); 45144 | } 45145 | } 45146 | } 45147 | 45148 | return T(0); 45149 | } 45150 | }; 45151 | 45152 | template <typename T> 45153 | class count exprtk_final : public exprtk::igeneric_function<T> 45154 | { 45155 | public: 45156 | 45157 | typedef typename exprtk::igeneric_function<T> igfun_t; 45158 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45159 | typedef typename igfun_t::generic_type generic_type; 45160 | typedef typename generic_type::scalar_view scalar_t; 45161 | typedef typename generic_type::vector_view vector_t; 45162 | 45163 | using igfun_t::operator(); 45164 | 45165 | count() 45166 | : exprtk::igeneric_function<T>("V|VTT|T*") 45167 | /* 45168 | Overloads: 45169 | 0. V - vector 45170 | 1. VTT - vector, r0, r1 45171 | 2. T* - T....T 45172 | */ 45173 | {} 45174 | 45175 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45176 | { 45177 | std::size_t cnt = 0; 45178 | 45179 | if (2 == ps_index) 45180 | { 45181 | for (std::size_t i = 0; i < parameters.size(); ++i) 45182 | { 45183 | if (scalar_t(parameters[i])() != T(0)) ++cnt; 45184 | } 45185 | } 45186 | else 45187 | { 45188 | const vector_t vec(parameters[0]); 45189 | 45190 | std::size_t r0 = 0; 45191 | std::size_t r1 = vec.size() - 1; 45192 | 45193 | if ( 45194 | (1 == ps_index) && 45195 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 45196 | ) 45197 | { 45198 | return std::numeric_limits<T>::quiet_NaN(); 45199 | } 45200 | 45201 | for (std::size_t i = r0; i <= r1; ++i) 45202 | { 45203 | if (vec[i] != T(0)) ++cnt; 45204 | } 45205 | } 45206 | 45207 | return T(cnt); 45208 | } 45209 | }; 45210 | 45211 | template <typename T> 45212 | class copy exprtk_final : public exprtk::igeneric_function<T> 45213 | { 45214 | public: 45215 | 45216 | typedef typename exprtk::igeneric_function<T> igfun_t; 45217 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45218 | typedef typename igfun_t::generic_type generic_type; 45219 | typedef typename generic_type::scalar_view scalar_t; 45220 | typedef typename generic_type::vector_view vector_t; 45221 | 45222 | using igfun_t::operator(); 45223 | 45224 | copy() 45225 | : exprtk::igeneric_function<T>("VV|VTTVTT") 45226 | /* 45227 | Overloads: 45228 | 0. VV - x(vector), y(vector) 45229 | 1. VTTVTT - x(vector), xr0, xr1, y(vector), yr0, yr1, 45230 | */ 45231 | {} 45232 | 45233 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45234 | { 45235 | const vector_t x(parameters[0]); 45236 | vector_t y(parameters[(0 == ps_index) ? 1 : 3]); 45237 | 45238 | std::size_t xr0 = 0; 45239 | std::size_t xr1 = x.size() - 1; 45240 | 45241 | std::size_t yr0 = 0; 45242 | std::size_t yr1 = y.size() - 1; 45243 | 45244 | if (1 == ps_index) 45245 | { 45246 | if ( 45247 | !helper::load_vector_range<T>::process(parameters, xr0, xr1, 1, 2, 0) || 45248 | !helper::load_vector_range<T>::process(parameters, yr0, yr1, 4, 5, 3) 45249 | ) 45250 | return T(0); 45251 | } 45252 | 45253 | const std::size_t n = std::min(xr1 - xr0 + 1, yr1 - yr0 + 1); 45254 | 45255 | std::copy( 45256 | x.begin() + xr0, 45257 | x.begin() + xr0 + n, 45258 | y.begin() + yr0); 45259 | 45260 | return T(n); 45261 | } 45262 | }; 45263 | 45264 | template <typename T> 45265 | class rol exprtk_final : public exprtk::igeneric_function<T> 45266 | { 45267 | public: 45268 | 45269 | typedef typename exprtk::igeneric_function<T> igfun_t; 45270 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45271 | typedef typename igfun_t::generic_type generic_type; 45272 | typedef typename generic_type::scalar_view scalar_t; 45273 | typedef typename generic_type::vector_view vector_t; 45274 | 45275 | using igfun_t::operator(); 45276 | 45277 | rol() 45278 | : exprtk::igeneric_function<T>("VT|VTTT") 45279 | /* 45280 | Overloads: 45281 | 0. VT - vector, N 45282 | 1. VTTT - vector, N, r0, r1 45283 | */ 45284 | {} 45285 | 45286 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45287 | { 45288 | vector_t vec(parameters[0]); 45289 | 45290 | std::size_t n = 0; 45291 | std::size_t r0 = 0; 45292 | std::size_t r1 = vec.size() - 1; 45293 | 45294 | if (!scalar_t(parameters[1]).to_uint(n)) 45295 | return T(0); 45296 | 45297 | if ( 45298 | (1 == ps_index) && 45299 | !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0) 45300 | ) 45301 | return T(0); 45302 | 45303 | const std::size_t dist = r1 - r0 + 1; 45304 | const std::size_t shift = n % dist; 45305 | 45306 | std::rotate( 45307 | vec.begin() + r0, 45308 | vec.begin() + r0 + shift, 45309 | vec.begin() + r1 + 1); 45310 | 45311 | return T(1); 45312 | } 45313 | }; 45314 | 45315 | template <typename T> 45316 | class ror exprtk_final : public exprtk::igeneric_function<T> 45317 | { 45318 | public: 45319 | 45320 | typedef typename exprtk::igeneric_function<T> igfun_t; 45321 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45322 | typedef typename igfun_t::generic_type generic_type; 45323 | typedef typename generic_type::scalar_view scalar_t; 45324 | typedef typename generic_type::vector_view vector_t; 45325 | 45326 | using igfun_t::operator(); 45327 | 45328 | ror() 45329 | : exprtk::igeneric_function<T>("VT|VTTT") 45330 | /* 45331 | Overloads: 45332 | 0. VT - vector, N 45333 | 1. VTTT - vector, N, r0, r1 45334 | */ 45335 | {} 45336 | 45337 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45338 | { 45339 | vector_t vec(parameters[0]); 45340 | 45341 | std::size_t n = 0; 45342 | std::size_t r0 = 0; 45343 | std::size_t r1 = vec.size() - 1; 45344 | 45345 | if (!scalar_t(parameters[1]).to_uint(n)) 45346 | return T(0); 45347 | 45348 | if ( 45349 | (1 == ps_index) && 45350 | !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0) 45351 | ) 45352 | return T(0); 45353 | 45354 | const std::size_t dist = r1 - r0 + 1; 45355 | const std::size_t shift = (dist - (n % dist)) % dist; 45356 | 45357 | std::rotate( 45358 | vec.begin() + r0, 45359 | vec.begin() + r0 + shift, 45360 | vec.begin() + r1 + 1); 45361 | 45362 | return T(1); 45363 | } 45364 | }; 45365 | 45366 | template <typename T> 45367 | class reverse exprtk_final : public exprtk::igeneric_function<T> 45368 | { 45369 | public: 45370 | 45371 | typedef typename exprtk::igeneric_function<T> igfun_t; 45372 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45373 | typedef typename igfun_t::generic_type generic_type; 45374 | typedef typename generic_type::scalar_view scalar_t; 45375 | typedef typename generic_type::vector_view vector_t; 45376 | 45377 | using igfun_t::operator(); 45378 | 45379 | reverse() 45380 | : exprtk::igeneric_function<T>("V|VTT") 45381 | /* 45382 | Overloads: 45383 | 0. V - vector 45384 | 1. VTT - vector, r0, r1 45385 | */ 45386 | {} 45387 | 45388 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45389 | { 45390 | vector_t vec(parameters[0]); 45391 | 45392 | std::size_t r0 = 0; 45393 | std::size_t r1 = vec.size() - 1; 45394 | 45395 | if ( 45396 | (1 == ps_index) && 45397 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 45398 | ) 45399 | return T(0); 45400 | 45401 | std::reverse(vec.begin() + r0, vec.begin() + r1 + 1); 45402 | 45403 | return T(1); 45404 | } 45405 | }; 45406 | 45407 | template <typename T> 45408 | class shift_left exprtk_final : public exprtk::igeneric_function<T> 45409 | { 45410 | public: 45411 | 45412 | typedef typename exprtk::igeneric_function<T> igfun_t; 45413 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45414 | typedef typename igfun_t::generic_type generic_type; 45415 | typedef typename generic_type::scalar_view scalar_t; 45416 | typedef typename generic_type::vector_view vector_t; 45417 | 45418 | using igfun_t::operator(); 45419 | 45420 | shift_left() 45421 | : exprtk::igeneric_function<T>("VT|VTTT") 45422 | /* 45423 | Overloads: 45424 | 0. VT - vector, N 45425 | 1. VTTT - vector, N, r0, r1 45426 | */ 45427 | {} 45428 | 45429 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45430 | { 45431 | vector_t vec(parameters[0]); 45432 | 45433 | std::size_t n = 0; 45434 | std::size_t r0 = 0; 45435 | std::size_t r1 = vec.size() - 1; 45436 | 45437 | if (!scalar_t(parameters[1]).to_uint(n)) 45438 | return T(0); 45439 | 45440 | if ( 45441 | (1 == ps_index) && 45442 | !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0) 45443 | ) 45444 | return T(0); 45445 | 45446 | const std::size_t dist = r1 - r0 + 1; 45447 | 45448 | if (n > dist) 45449 | return T(0); 45450 | 45451 | std::rotate( 45452 | vec.begin() + r0, 45453 | vec.begin() + r0 + n, 45454 | vec.begin() + r1 + 1); 45455 | 45456 | for (std::size_t i = r1 - n + 1ULL; i <= r1; ++i) 45457 | { 45458 | vec[i] = T(0); 45459 | } 45460 | 45461 | return T(1); 45462 | } 45463 | }; 45464 | 45465 | template <typename T> 45466 | class shift_right exprtk_final : public exprtk::igeneric_function<T> 45467 | { 45468 | public: 45469 | 45470 | typedef typename exprtk::igeneric_function<T> igfun_t; 45471 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45472 | typedef typename igfun_t::generic_type generic_type; 45473 | typedef typename generic_type::scalar_view scalar_t; 45474 | typedef typename generic_type::vector_view vector_t; 45475 | 45476 | using igfun_t::operator(); 45477 | 45478 | shift_right() 45479 | : exprtk::igeneric_function<T>("VT|VTTT") 45480 | /* 45481 | Overloads: 45482 | 0. VT - vector, N 45483 | 1. VTTT - vector, N, r0, r1 45484 | */ 45485 | {} 45486 | 45487 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45488 | { 45489 | vector_t vec(parameters[0]); 45490 | 45491 | std::size_t n = 0; 45492 | std::size_t r0 = 0; 45493 | std::size_t r1 = vec.size() - 1; 45494 | 45495 | if (!scalar_t(parameters[1]).to_uint(n)) 45496 | return T(0); 45497 | 45498 | if ( 45499 | (1 == ps_index) && 45500 | !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0) 45501 | ) 45502 | return T(0); 45503 | 45504 | const std::size_t dist = r1 - r0 + 1; 45505 | 45506 | if (n > dist) 45507 | return T(0); 45508 | 45509 | const std::size_t shift = (dist - (n % dist)) % dist; 45510 | 45511 | std::rotate( 45512 | vec.begin() + r0, 45513 | vec.begin() + r0 + shift, 45514 | vec.begin() + r1 + 1); 45515 | 45516 | for (std::size_t i = r0; i < r0 + n; ++i) 45517 | { 45518 | vec[i] = T(0); 45519 | } 45520 | 45521 | return T(1); 45522 | } 45523 | }; 45524 | 45525 | template <typename T> 45526 | class sort exprtk_final : public exprtk::igeneric_function<T> 45527 | { 45528 | public: 45529 | 45530 | typedef typename exprtk::igeneric_function<T> igfun_t; 45531 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45532 | typedef typename igfun_t::generic_type generic_type; 45533 | typedef typename generic_type::string_view string_t; 45534 | typedef typename generic_type::vector_view vector_t; 45535 | 45536 | using igfun_t::operator(); 45537 | 45538 | sort() 45539 | : exprtk::igeneric_function<T>("V|VTT|VS|VSTT") 45540 | /* 45541 | Overloads: 45542 | 0. V - vector 45543 | 1. VTT - vector, r0, r1 45544 | 2. VS - vector, string 45545 | 3. VSTT - vector, string, r0, r1 45546 | */ 45547 | {} 45548 | 45549 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45550 | { 45551 | vector_t vec(parameters[0]); 45552 | 45553 | std::size_t r0 = 0; 45554 | std::size_t r1 = vec.size() - 1; 45555 | 45556 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)) 45557 | return T(0); 45558 | if ((3 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)) 45559 | return T(0); 45560 | 45561 | bool ascending = true; 45562 | 45563 | if ((2 == ps_index) || (3 == ps_index)) 45564 | { 45565 | if (exprtk::details::imatch(to_str(string_t(parameters[1])),"ascending")) 45566 | ascending = true; 45567 | else if (exprtk::details::imatch(to_str(string_t(parameters[1])),"descending")) 45568 | ascending = false; 45569 | else 45570 | return T(0); 45571 | } 45572 | 45573 | if (ascending) 45574 | std::sort( 45575 | vec.begin() + r0, 45576 | vec.begin() + r1 + 1, 45577 | std::less<T>()); 45578 | else 45579 | std::sort( 45580 | vec.begin() + r0, 45581 | vec.begin() + r1 + 1, 45582 | std::greater<T>()); 45583 | 45584 | return T(1); 45585 | } 45586 | }; 45587 | 45588 | template <typename T> 45589 | class nthelement exprtk_final : public exprtk::igeneric_function<T> 45590 | { 45591 | public: 45592 | 45593 | typedef typename exprtk::igeneric_function<T> igfun_t; 45594 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45595 | typedef typename igfun_t::generic_type generic_type; 45596 | typedef typename generic_type::scalar_view scalar_t; 45597 | typedef typename generic_type::vector_view vector_t; 45598 | 45599 | using igfun_t::operator(); 45600 | 45601 | nthelement() 45602 | : exprtk::igeneric_function<T>("VT|VTTT") 45603 | /* 45604 | Overloads: 45605 | 0. VT - vector, nth-element 45606 | 1. VTTT - vector, nth-element, r0, r1 45607 | */ 45608 | {} 45609 | 45610 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45611 | { 45612 | vector_t vec(parameters[0]); 45613 | 45614 | std::size_t n = 0; 45615 | std::size_t r0 = 0; 45616 | std::size_t r1 = vec.size() - 1; 45617 | 45618 | if (!scalar_t(parameters[1]).to_uint(n)) 45619 | return T(0); 45620 | 45621 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)) 45622 | { 45623 | return std::numeric_limits<T>::quiet_NaN(); 45624 | } 45625 | 45626 | const std::size_t dist = r1 - r0 + 1; 45627 | 45628 | if (n > dist) 45629 | { 45630 | return T(0); 45631 | } 45632 | 45633 | std::nth_element( 45634 | vec.begin() + r0, 45635 | vec.begin() + r0 + n , 45636 | vec.begin() + r1 + 1); 45637 | 45638 | return T(1); 45639 | } 45640 | }; 45641 | 45642 | template <typename T> 45643 | class assign exprtk_final : public exprtk::igeneric_function<T> 45644 | { 45645 | public: 45646 | 45647 | typedef typename exprtk::igeneric_function<T> igfun_t; 45648 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45649 | typedef typename igfun_t::generic_type generic_type; 45650 | typedef typename generic_type::scalar_view scalar_t; 45651 | typedef typename generic_type::vector_view vector_t; 45652 | 45653 | using igfun_t::operator(); 45654 | 45655 | assign() 45656 | : exprtk::igeneric_function<T>("VT|VTTT|VTTTT") 45657 | /* 45658 | Overloads: 45659 | 0. VT - vector, V 45660 | 1. VTTT - vector, V, r0, r1 45661 | 2. VTTTT - vector, V, r0, r1, SS 45662 | */ 45663 | {} 45664 | 45665 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45666 | { 45667 | vector_t vec(parameters[0]); 45668 | 45669 | const T assign_value = scalar_t(parameters[1]); 45670 | 45671 | const std::size_t step_size = (2 != ps_index) ? 1 : 45672 | static_cast<std::size_t>(scalar_t(parameters.back())()); 45673 | 45674 | if (helper::invalid_stride(step_size)) 45675 | { 45676 | return T(0); 45677 | } 45678 | 45679 | std::size_t r0 = 0; 45680 | std::size_t r1 = vec.size() - 1; 45681 | 45682 | if ( 45683 | ((ps_index == 1) || (ps_index == 2)) && 45684 | !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0) 45685 | ) 45686 | { 45687 | return T(0); 45688 | } 45689 | 45690 | for (std::size_t i = r0; i <= r1; i += step_size) 45691 | { 45692 | vec[i] = assign_value; 45693 | } 45694 | 45695 | return T(1); 45696 | } 45697 | }; 45698 | 45699 | template <typename T> 45700 | class iota exprtk_final : public exprtk::igeneric_function<T> 45701 | { 45702 | public: 45703 | 45704 | typedef typename exprtk::igeneric_function<T> igfun_t; 45705 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45706 | typedef typename igfun_t::generic_type generic_type; 45707 | typedef typename generic_type::scalar_view scalar_t; 45708 | typedef typename generic_type::vector_view vector_t; 45709 | 45710 | using igfun_t::operator(); 45711 | 45712 | iota() 45713 | : exprtk::igeneric_function<T>("VTT|VT|VTTTT|VTTT") 45714 | /* 45715 | Overloads: 45716 | 0. VTT - vector, SV, SS 45717 | 1. VT - vector, SV, SS (+1) 45718 | 2. VTTT - vector, r0, r1, SV, SS 45719 | 3. VTT - vector, r0, r1, SV, SS (+1) 45720 | 45721 | Where: 45722 | 1. SV - Start value 45723 | 2. SS - Step size 45724 | */ 45725 | {} 45726 | 45727 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45728 | { 45729 | vector_t vec(parameters[0]); 45730 | 45731 | const T start_value = (ps_index <= 1) ? 45732 | scalar_t(parameters[1]) : 45733 | scalar_t(parameters[3]) ; 45734 | 45735 | const T step_size = ((0 == ps_index) || (2 == ps_index)) ? 45736 | scalar_t(parameters.back())() : 45737 | T(1) ; 45738 | 45739 | std::size_t r0 = 0; 45740 | std::size_t r1 = vec.size() - 1; 45741 | 45742 | if ( 45743 | ((ps_index == 2) || (ps_index == 3)) && 45744 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 45745 | ) 45746 | { 45747 | return T(0); 45748 | } 45749 | 45750 | for (std::size_t i = r0; i <= r1; ++i) 45751 | { 45752 | vec[i] = start_value + ((i - r0) * step_size); 45753 | } 45754 | 45755 | return T(1); 45756 | } 45757 | }; 45758 | 45759 | template <typename T> 45760 | class sumk exprtk_final : public exprtk::igeneric_function<T> 45761 | { 45762 | public: 45763 | 45764 | typedef typename exprtk::igeneric_function<T> igfun_t; 45765 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45766 | typedef typename igfun_t::generic_type generic_type; 45767 | typedef typename generic_type::scalar_view scalar_t; 45768 | typedef typename generic_type::vector_view vector_t; 45769 | 45770 | using igfun_t::operator(); 45771 | 45772 | sumk() 45773 | : exprtk::igeneric_function<T>("V|VTT|VTTT") 45774 | /* 45775 | Overloads: 45776 | 0. V - vector 45777 | 1. VTT - vector, r0, r1 45778 | 2. VTTT - vector, r0, r1, stride 45779 | */ 45780 | {} 45781 | 45782 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45783 | { 45784 | const vector_t vec(parameters[0]); 45785 | 45786 | const std::size_t stride = (2 != ps_index) ? 1 : 45787 | static_cast<std::size_t>(scalar_t(parameters[3])()); 45788 | 45789 | if (helper::invalid_stride(stride)) 45790 | { 45791 | return std::numeric_limits<T>::quiet_NaN(); 45792 | } 45793 | 45794 | std::size_t r0 = 0; 45795 | std::size_t r1 = vec.size() - 1; 45796 | 45797 | if ( 45798 | ((1 == ps_index) || (2 == ps_index)) && 45799 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 45800 | ) 45801 | { 45802 | return std::numeric_limits<T>::quiet_NaN(); 45803 | } 45804 | 45805 | T result = T(0); 45806 | T error = T(0); 45807 | 45808 | for (std::size_t i = r0; i <= r1; i += stride) 45809 | { 45810 | details::kahan_sum(result, error, vec[i]); 45811 | } 45812 | 45813 | return result; 45814 | } 45815 | }; 45816 | 45817 | template <typename T> 45818 | class axpy 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 | axpy() 45831 | : exprtk::igeneric_function<T>("TVV|TVVTT") 45832 | /* 45833 | y <- ax + y 45834 | Overloads: 45835 | 0. TVV - a, x(vector), y(vector) 45836 | 1. TVVTT - a, x(vector), y(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 | vector_t y(parameters[2]); 45844 | 45845 | std::size_t r0 = 0; 45846 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 45847 | 45848 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 3, 4, 1)) 45849 | return std::numeric_limits<T>::quiet_NaN(); 45850 | else if (helper::invalid_range(y, r0, r1)) 45851 | return std::numeric_limits<T>::quiet_NaN(); 45852 | 45853 | const T a = scalar_t(parameters[0])(); 45854 | 45855 | for (std::size_t i = r0; i <= r1; ++i) 45856 | { 45857 | y[i] = (a * x[i]) + y[i]; 45858 | } 45859 | 45860 | return T(1); 45861 | } 45862 | }; 45863 | 45864 | template <typename T> 45865 | class axpby exprtk_final : public exprtk::igeneric_function<T> 45866 | { 45867 | public: 45868 | 45869 | typedef typename exprtk::igeneric_function<T> igfun_t; 45870 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45871 | typedef typename igfun_t::generic_type generic_type; 45872 | typedef typename generic_type::scalar_view scalar_t; 45873 | typedef typename generic_type::vector_view vector_t; 45874 | 45875 | using igfun_t::operator(); 45876 | 45877 | axpby() 45878 | : exprtk::igeneric_function<T>("TVTV|TVTVTT") 45879 | /* 45880 | y <- ax + by 45881 | Overloads: 45882 | 0. TVTV - a, x(vector), b, y(vector) 45883 | 1. TVTVTT - a, x(vector), b, y(vector), r0, r1 45884 | */ 45885 | {} 45886 | 45887 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45888 | { 45889 | const vector_t x(parameters[1]); 45890 | vector_t y(parameters[3]); 45891 | 45892 | std::size_t r0 = 0; 45893 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 45894 | 45895 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1)) 45896 | return std::numeric_limits<T>::quiet_NaN(); 45897 | else if (helper::invalid_range(y, r0, r1)) 45898 | return std::numeric_limits<T>::quiet_NaN(); 45899 | 45900 | const T a = scalar_t(parameters[0])(); 45901 | const T b = scalar_t(parameters[2])(); 45902 | 45903 | for (std::size_t i = r0; i <= r1; ++i) 45904 | { 45905 | y[i] = (a * x[i]) + (b * y[i]); 45906 | } 45907 | 45908 | return T(1); 45909 | } 45910 | }; 45911 | 45912 | template <typename T> 45913 | class axpyz exprtk_final : public exprtk::igeneric_function<T> 45914 | { 45915 | public: 45916 | 45917 | typedef typename exprtk::igeneric_function<T> igfun_t; 45918 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45919 | typedef typename igfun_t::generic_type generic_type; 45920 | typedef typename generic_type::scalar_view scalar_t; 45921 | typedef typename generic_type::vector_view vector_t; 45922 | 45923 | using igfun_t::operator(); 45924 | 45925 | axpyz() 45926 | : exprtk::igeneric_function<T>("TVVV|TVVVTT") 45927 | /* 45928 | z <- ax + y 45929 | Overloads: 45930 | 0. TVVV - a, x(vector), y(vector), z(vector) 45931 | 1. TVVVTT - a, x(vector), y(vector), z(vector), r0, r1 45932 | */ 45933 | {} 45934 | 45935 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45936 | { 45937 | const vector_t x(parameters[1]); 45938 | const vector_t y(parameters[2]); 45939 | vector_t z(parameters[3]); 45940 | 45941 | std::size_t r0 = 0; 45942 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 45943 | 45944 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1)) 45945 | return std::numeric_limits<T>::quiet_NaN(); 45946 | else if (helper::invalid_range(y, r0, r1)) 45947 | return std::numeric_limits<T>::quiet_NaN(); 45948 | else if (helper::invalid_range(z, r0, r1)) 45949 | return std::numeric_limits<T>::quiet_NaN(); 45950 | 45951 | const T a = scalar_t(parameters[0])(); 45952 | 45953 | for (std::size_t i = r0; i <= r1; ++i) 45954 | { 45955 | z[i] = (a * x[i]) + y[i]; 45956 | } 45957 | 45958 | return T(1); 45959 | } 45960 | }; 45961 | 45962 | template <typename T> 45963 | class axpbyz exprtk_final : public exprtk::igeneric_function<T> 45964 | { 45965 | public: 45966 | 45967 | typedef typename exprtk::igeneric_function<T> igfun_t; 45968 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45969 | typedef typename igfun_t::generic_type generic_type; 45970 | typedef typename generic_type::scalar_view scalar_t; 45971 | typedef typename generic_type::vector_view vector_t; 45972 | 45973 | using igfun_t::operator(); 45974 | 45975 | axpbyz() 45976 | : exprtk::igeneric_function<T>("TVTVV|TVTVVTT") 45977 | /* 45978 | z <- ax + by 45979 | Overloads: 45980 | 0. TVTVV - a, x(vector), b, y(vector), z(vector) 45981 | 1. TVTVVTT - a, x(vector), b, y(vector), z(vector), r0, r1 45982 | */ 45983 | {} 45984 | 45985 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45986 | { 45987 | const vector_t x(parameters[1]); 45988 | const vector_t y(parameters[3]); 45989 | vector_t z(parameters[4]); 45990 | 45991 | std::size_t r0 = 0; 45992 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 45993 | 45994 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 5, 6, 1)) 45995 | return std::numeric_limits<T>::quiet_NaN(); 45996 | else if (helper::invalid_range(y, r0, r1)) 45997 | return std::numeric_limits<T>::quiet_NaN(); 45998 | else if (helper::invalid_range(z, r0, r1)) 45999 | return std::numeric_limits<T>::quiet_NaN(); 46000 | 46001 | const T a = scalar_t(parameters[0])(); 46002 | const T b = scalar_t(parameters[2])(); 46003 | 46004 | for (std::size_t i = r0; i <= r1; ++i) 46005 | { 46006 | z[i] = (a * x[i]) + (b * y[i]); 46007 | } 46008 | 46009 | return T(1); 46010 | } 46011 | }; 46012 | 46013 | template <typename T> 46014 | class axpbsy exprtk_final : public exprtk::igeneric_function<T> 46015 | { 46016 | public: 46017 | 46018 | typedef typename exprtk::igeneric_function<T> igfun_t; 46019 | typedef typename igfun_t::parameter_list_t parameter_list_t; 46020 | typedef typename igfun_t::generic_type generic_type; 46021 | typedef typename generic_type::scalar_view scalar_t; 46022 | typedef typename generic_type::vector_view vector_t; 46023 | 46024 | using igfun_t::operator(); 46025 | 46026 | axpbsy() 46027 | : exprtk::igeneric_function<T>("TVTTV|TVTTVTT") 46028 | /* 46029 | y <- ax + by 46030 | Overloads: 46031 | 0. TVTVV - a, x(vector), b, shift, y(vector), z(vector) 46032 | 1. TVTVVTT - a, x(vector), b, shift, y(vector), z(vector), r0, r1 46033 | */ 46034 | {} 46035 | 46036 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 46037 | { 46038 | const vector_t x(parameters[1]); 46039 | vector_t y(parameters[4]); 46040 | 46041 | std::size_t r0 = 0; 46042 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 46043 | 46044 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 5, 6, 1)) 46045 | return std::numeric_limits<T>::quiet_NaN(); 46046 | else if (helper::invalid_range(y, r0, r1)) 46047 | return std::numeric_limits<T>::quiet_NaN(); 46048 | 46049 | const T a = scalar_t(parameters[0])(); 46050 | const T b = scalar_t(parameters[2])(); 46051 | 46052 | const std::size_t s = static_cast<std::size_t>(scalar_t(parameters[3])()); 46053 | 46054 | if (helper::invalid_shift(y, r1, s)) 46055 | { 46056 | return std::numeric_limits<T>::quiet_NaN(); 46057 | } 46058 | 46059 | for (std::size_t i = r0; i <= r1; ++i) 46060 | { 46061 | y[i] = (a * x[i]) + (b * y[i + s]); 46062 | } 46063 | 46064 | return T(1); 46065 | } 46066 | }; 46067 | 46068 | template <typename T> 46069 | class axpbsyz exprtk_final : public exprtk::igeneric_function<T> 46070 | { 46071 | public: 46072 | 46073 | typedef typename exprtk::igeneric_function<T> igfun_t; 46074 | typedef typename igfun_t::parameter_list_t parameter_list_t; 46075 | typedef typename igfun_t::generic_type generic_type; 46076 | typedef typename generic_type::scalar_view scalar_t; 46077 | typedef typename generic_type::vector_view vector_t; 46078 | 46079 | using igfun_t::operator(); 46080 | 46081 | axpbsyz() 46082 | : exprtk::igeneric_function<T>("TVTTVV|TVTTVVTT") 46083 | /* 46084 | z <- ax + by 46085 | Overloads: 46086 | 0. TVTVV - a, x(vector), b, shift, y(vector), z(vector) 46087 | 1. TVTVVTT - a, x(vector), b, shift, y(vector), z(vector), r0, r1 46088 | */ 46089 | {} 46090 | 46091 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 46092 | { 46093 | const vector_t x(parameters[1]); 46094 | const vector_t y(parameters[4]); 46095 | vector_t z(parameters[5]); 46096 | 46097 | std::size_t r0 = 0; 46098 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 46099 | 46100 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 6, 7, 1)) 46101 | return std::numeric_limits<T>::quiet_NaN(); 46102 | else if (helper::invalid_range(y, r0, r1)) 46103 | return std::numeric_limits<T>::quiet_NaN(); 46104 | else if (helper::invalid_range(z, r0, r1)) 46105 | return std::numeric_limits<T>::quiet_NaN(); 46106 | 46107 | const T a = scalar_t(parameters[0])(); 46108 | const T b = scalar_t(parameters[2])(); 46109 | 46110 | const std::size_t s = static_cast<std::size_t>(scalar_t(parameters[3])()); 46111 | 46112 | if (helper::invalid_shift(y, r1, s)) 46113 | { 46114 | return std::numeric_limits<T>::quiet_NaN(); 46115 | } 46116 | 46117 | for (std::size_t i = r0; i <= r1; ++i) 46118 | { 46119 | z[i] = (a * x[i]) + (b * y[i + s]); 46120 | } 46121 | 46122 | return T(1); 46123 | } 46124 | }; 46125 | 46126 | template <typename T> 46127 | class axpbz exprtk_final : public exprtk::igeneric_function<T> 46128 | { 46129 | public: 46130 | 46131 | typedef typename exprtk::igeneric_function<T> igfun_t; 46132 | typedef typename igfun_t::parameter_list_t parameter_list_t; 46133 | typedef typename igfun_t::generic_type generic_type; 46134 | typedef typename generic_type::scalar_view scalar_t; 46135 | typedef typename generic_type::vector_view vector_t; 46136 | 46137 | using igfun_t::operator(); 46138 | 46139 | axpbz() 46140 | : exprtk::igeneric_function<T>("TVTV|TVTVTT") 46141 | /* 46142 | z <- ax + b 46143 | Overloads: 46144 | 0. TVTV - a, x(vector), b, z(vector) 46145 | 1. TVTVTT - a, x(vector), b, z(vector), r0, r1 46146 | */ 46147 | {} 46148 | 46149 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 46150 | { 46151 | const vector_t x(parameters[1]); 46152 | vector_t z(parameters[3]); 46153 | 46154 | std::size_t r0 = 0; 46155 | std::size_t r1 = x.size() - 1; 46156 | 46157 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1)) 46158 | return std::numeric_limits<T>::quiet_NaN(); 46159 | else if (helper::invalid_range(z, r0, r1)) 46160 | return std::numeric_limits<T>::quiet_NaN(); 46161 | 46162 | const T a = scalar_t(parameters[0])(); 46163 | const T b = scalar_t(parameters[2])(); 46164 | 46165 | for (std::size_t i = r0; i <= r1; ++i) 46166 | { 46167 | z[i] = (a * x[i]) + b; 46168 | } 46169 | 46170 | return T(1); 46171 | } 46172 | }; 46173 | 46174 | template <typename T> 46175 | class diff exprtk_final : public exprtk::igeneric_function<T> 46176 | { 46177 | public: 46178 | 46179 | typedef typename exprtk::igeneric_function<T> igfun_t; 46180 | typedef typename igfun_t::parameter_list_t parameter_list_t; 46181 | typedef typename igfun_t::generic_type generic_type; 46182 | typedef typename generic_type::scalar_view scalar_t; 46183 | typedef typename generic_type::vector_view vector_t; 46184 | 46185 | using igfun_t::operator(); 46186 | 46187 | diff() 46188 | : exprtk::igeneric_function<T>("VV|VVT") 46189 | /* 46190 | x_(i - stride) - x_i 46191 | Overloads: 46192 | 0. VV - x(vector), y(vector) 46193 | 1. VVT - x(vector), y(vector), stride 46194 | */ 46195 | {} 46196 | 46197 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 46198 | { 46199 | const vector_t x(parameters[0]); 46200 | vector_t y(parameters[1]); 46201 | 46202 | const std::size_t r0 = 0; 46203 | const std::size_t r1 = std::min(x.size(),y.size()) - 1; 46204 | 46205 | const std::size_t stride = (1 != ps_index) ? 1 : 46206 | std::min(r1,static_cast<std::size_t>(scalar_t(parameters[2])())); 46207 | 46208 | for (std::size_t i = 0; i < stride; ++i) 46209 | { 46210 | y[i] = std::numeric_limits<T>::quiet_NaN(); 46211 | } 46212 | 46213 | for (std::size_t i = (r0 + stride); i <= r1; ++i) 46214 | { 46215 | y[i] = x[i] - x[i - stride]; 46216 | } 46217 | 46218 | return T(1); 46219 | } 46220 | }; 46221 | 46222 | template <typename T> 46223 | class dot exprtk_final : public exprtk::igeneric_function<T> 46224 | { 46225 | public: 46226 | 46227 | typedef typename exprtk::igeneric_function<T> igfun_t; 46228 | typedef typename igfun_t::parameter_list_t parameter_list_t; 46229 | typedef typename igfun_t::generic_type generic_type; 46230 | typedef typename generic_type::scalar_view scalar_t; 46231 | typedef typename generic_type::vector_view vector_t; 46232 | 46233 | using igfun_t::operator(); 46234 | 46235 | dot() 46236 | : exprtk::igeneric_function<T>("VV|VVTT") 46237 | /* 46238 | Overloads: 46239 | 0. VV - x(vector), y(vector) 46240 | 1. VVTT - x(vector), y(vector), r0, r1 46241 | */ 46242 | {} 46243 | 46244 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 46245 | { 46246 | const vector_t x(parameters[0]); 46247 | const vector_t y(parameters[1]); 46248 | 46249 | std::size_t r0 = 0; 46250 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 46251 | 46252 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)) 46253 | return std::numeric_limits<T>::quiet_NaN(); 46254 | else if (helper::invalid_range(y, r0, r1)) 46255 | return std::numeric_limits<T>::quiet_NaN(); 46256 | 46257 | T result = T(0); 46258 | 46259 | for (std::size_t i = r0; i <= r1; ++i) 46260 | { 46261 | result += (x[i] * y[i]); 46262 | } 46263 | 46264 | return result; 46265 | } 46266 | }; 46267 | 46268 | template <typename T> 46269 | class dotk exprtk_final : public exprtk::igeneric_function<T> 46270 | { 46271 | public: 46272 | 46273 | typedef typename exprtk::igeneric_function<T> igfun_t; 46274 | typedef typename igfun_t::parameter_list_t parameter_list_t; 46275 | typedef typename igfun_t::generic_type generic_type; 46276 | typedef typename generic_type::scalar_view scalar_t; 46277 | typedef typename generic_type::vector_view vector_t; 46278 | 46279 | using igfun_t::operator(); 46280 | 46281 | dotk() 46282 | : exprtk::igeneric_function<T>("VV|VVTT") 46283 | /* 46284 | Overloads: 46285 | 0. VV - x(vector), y(vector) 46286 | 1. VVTT - x(vector), y(vector), r0, r1 46287 | */ 46288 | {} 46289 | 46290 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 46291 | { 46292 | const vector_t x(parameters[0]); 46293 | const vector_t y(parameters[1]); 46294 | 46295 | std::size_t r0 = 0; 46296 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 46297 | 46298 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)) 46299 | return std::numeric_limits<T>::quiet_NaN(); 46300 | else if (helper::invalid_range(y, r0, r1)) 46301 | return std::numeric_limits<T>::quiet_NaN(); 46302 | 46303 | T result = T(0); 46304 | T error = T(0); 46305 | 46306 | for (std::size_t i = r0; i <= r1; ++i) 46307 | { 46308 | details::kahan_sum(result, error, (x[i] * y[i])); 46309 | } 46310 | 46311 | return result; 46312 | } 46313 | }; 46314 | 46315 | template <typename T> 46316 | class threshold_below exprtk_final : public exprtk::igeneric_function<T> 46317 | { 46318 | public: 46319 | 46320 | typedef typename exprtk::igeneric_function<T> igfun_t; 46321 | typedef typename igfun_t::parameter_list_t parameter_list_t; 46322 | typedef typename igfun_t::generic_type generic_type; 46323 | typedef typename generic_type::scalar_view scalar_t; 46324 | typedef typename generic_type::vector_view vector_t; 46325 | 46326 | using igfun_t::operator(); 46327 | 46328 | threshold_below() 46329 | : exprtk::igeneric_function<T>("VTT|VTTTT") 46330 | /* 46331 | Overloads: 46332 | 0. VTT - vector, TV, SV 46333 | 1. VTTTT - vector, r0, r1, TV, SV 46334 | 46335 | Where: 46336 | TV - Threshold value 46337 | SV - Snap-to value 46338 | */ 46339 | {} 46340 | 46341 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 46342 | { 46343 | vector_t vec(parameters[0]); 46344 | 46345 | const T threshold_value = (0 == ps_index) ? 46346 | scalar_t(parameters[1]) : 46347 | scalar_t(parameters[3]) ; 46348 | 46349 | const T snap_value = scalar_t(parameters.back()); 46350 | 46351 | std::size_t r0 = 0; 46352 | std::size_t r1 = vec.size() - 1; 46353 | 46354 | if ( 46355 | (1 == ps_index) && 46356 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 46357 | ) 46358 | { 46359 | return T(0); 46360 | } 46361 | 46362 | for (std::size_t i = r0; i <= r1; ++i) 46363 | { 46364 | if (vec[i] < threshold_value) 46365 | { 46366 | vec[i] = snap_value; 46367 | } 46368 | } 46369 | 46370 | return T(1); 46371 | } 46372 | }; 46373 | 46374 | template <typename T> 46375 | class threshold_above exprtk_final : public exprtk::igeneric_function<T> 46376 | { 46377 | public: 46378 | 46379 | typedef typename exprtk::igeneric_function<T> igfun_t; 46380 | typedef typename igfun_t::parameter_list_t parameter_list_t; 46381 | typedef typename igfun_t::generic_type generic_type; 46382 | typedef typename generic_type::scalar_view scalar_t; 46383 | typedef typename generic_type::vector_view vector_t; 46384 | 46385 | using igfun_t::operator(); 46386 | 46387 | threshold_above() 46388 | : exprtk::igeneric_function<T>("VTT|VTTTT") 46389 | /* 46390 | Overloads: 46391 | 0. VTT - vector, TV, SV 46392 | 1. VTTTT - vector, r0, r1, TV, SV 46393 | 46394 | Where: 46395 | TV - Threshold value 46396 | SV - Snap-to value 46397 | */ 46398 | {} 46399 | 46400 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 46401 | { 46402 | vector_t vec(parameters[0]); 46403 | 46404 | const T threshold_value = (0 == ps_index) ? 46405 | scalar_t(parameters[1]) : 46406 | scalar_t(parameters[3]) ; 46407 | 46408 | const T snap_value = scalar_t(parameters.back()); 46409 | 46410 | std::size_t r0 = 0; 46411 | std::size_t r1 = vec.size() - 1; 46412 | 46413 | if ( 46414 | (1 == ps_index) && 46415 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 46416 | ) 46417 | { 46418 | return T(0); 46419 | } 46420 | 46421 | for (std::size_t i = r0; i <= r1; ++i) 46422 | { 46423 | if (vec[i] > threshold_value) 46424 | { 46425 | vec[i] = snap_value; 46426 | } 46427 | } 46428 | 46429 | return T(1); 46430 | } 46431 | }; 46432 | 46433 | template <typename T> 46434 | class min_elemwise exprtk_final : public exprtk::igeneric_function<T> 46435 | { 46436 | public: 46437 | 46438 | typedef typename exprtk::igeneric_function<T> igfun_t; 46439 | typedef typename igfun_t::parameter_list_t parameter_list_t; 46440 | typedef typename igfun_t::generic_type generic_type; 46441 | typedef typename generic_type::scalar_view scalar_t; 46442 | typedef typename generic_type::vector_view vector_t; 46443 | 46444 | using igfun_t::operator(); 46445 | 46446 | min_elemwise() 46447 | : exprtk::igeneric_function<T>("VT|VVT|VTTT|VVTTT") 46448 | /* 46449 | Overloads: 46450 | 0. VT - vector, T 46451 | 0. VVT - vector, vector, T 46452 | 0. VTTT - vector, r0, r1, T 46453 | 0. VVTTT - vector, vector, r0, r1, T 46454 | */ 46455 | {} 46456 | 46457 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 46458 | { 46459 | std::size_t out_vec_index = 0; 46460 | std::size_t in_vec_index = (ps_index & 1) ? 1 : 0; 46461 | std::size_t scalar_index = parameters.size() - 1; 46462 | 46463 | vector_t out_vec(parameters[out_vec_index]); 46464 | vector_t in_vec (parameters[in_vec_index ]); 46465 | 46466 | const T s = scalar_t(parameters[scalar_index ])(); 46467 | 46468 | std::size_t r0 = 0; 46469 | std::size_t r1 = in_vec.size() - 1; 46470 | 46471 | if ((2 == ps_index) || (3 == ps_index)) 46472 | { 46473 | std::size_t rng_idx0 = 0; 46474 | std::size_t rng_idx1 = 0; 46475 | 46476 | switch (ps_index) 46477 | { 46478 | case 2 : { rng_idx0 = 1; rng_idx1 = 2; }; break; 46479 | case 3 : { rng_idx0 = 2; rng_idx1 = 3; }; break; 46480 | } 46481 | 46482 | if (!helper::load_vector_range<T>::process(parameters, r0, r1, rng_idx0, rng_idx1, 0)) 46483 | { 46484 | return T(0); 46485 | } 46486 | } 46487 | 46488 | r1 = std::min(r1, std::min(out_vec.size(), in_vec.size()) - 1); 46489 | 46490 | for (std::size_t i = r0; i <= r1; ++i) 46491 | { 46492 | out_vec[i] = exprtk::details::numeric::min(in_vec[i], s); 46493 | } 46494 | 46495 | return T(1); 46496 | } 46497 | }; 46498 | 46499 | template <typename T> 46500 | class max_elemwise exprtk_final : public exprtk::igeneric_function<T> 46501 | { 46502 | public: 46503 | 46504 | typedef typename exprtk::igeneric_function<T> igfun_t; 46505 | typedef typename igfun_t::parameter_list_t parameter_list_t; 46506 | typedef typename igfun_t::generic_type generic_type; 46507 | typedef typename generic_type::scalar_view scalar_t; 46508 | typedef typename generic_type::vector_view vector_t; 46509 | 46510 | using igfun_t::operator(); 46511 | 46512 | max_elemwise() 46513 | : exprtk::igeneric_function<T>("VT|VVT|VTTT|VVTTT") 46514 | /* 46515 | Overloads: 46516 | 0. VT - vector, T 46517 | 1. VVT - vector, vector, T 46518 | 2. VTTT - vector, r0, r1, T 46519 | 3. VVTTT - vector, vector, r0, r1, T 46520 | */ 46521 | {} 46522 | 46523 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 46524 | { 46525 | std::size_t out_vec_index = 0; 46526 | std::size_t in_vec_index = (ps_index & 1) ? 1 : 0; 46527 | std::size_t scalar_index = parameters.size() - 1; 46528 | 46529 | vector_t out_vec(parameters[out_vec_index]); 46530 | vector_t in_vec (parameters[in_vec_index ]); 46531 | 46532 | const T s = scalar_t(parameters[scalar_index ])(); 46533 | 46534 | std::size_t r0 = 0; 46535 | std::size_t r1 = in_vec.size() - 1; 46536 | 46537 | if ((2 == ps_index) || (3 == ps_index)) 46538 | { 46539 | std::size_t rng_idx0 = 0; 46540 | std::size_t rng_idx1 = 0; 46541 | 46542 | switch (ps_index) 46543 | { 46544 | case 2 : { rng_idx0 = 1; rng_idx1 = 2; }; break; 46545 | case 3 : { rng_idx0 = 2; rng_idx1 = 3; }; break; 46546 | } 46547 | 46548 | if (!helper::load_vector_range<T>::process(parameters, r0, r1, rng_idx0, rng_idx1, 0)) 46549 | { 46550 | return T(0); 46551 | } 46552 | } 46553 | 46554 | r1 = std::min(r1, std::min(out_vec.size(), in_vec.size()) - 1); 46555 | 46556 | for (std::size_t i = r0; i <= r1; ++i) 46557 | { 46558 | out_vec[i] = exprtk::details::numeric::max(in_vec[i], s); 46559 | } 46560 | 46561 | return T(1); 46562 | } 46563 | }; 46564 | 46565 | template <typename T> 46566 | class select exprtk_final : public exprtk::igeneric_function<T> 46567 | { 46568 | public: 46569 | 46570 | typedef typename exprtk::igeneric_function<T> igfun_t; 46571 | typedef typename igfun_t::parameter_list_t parameter_list_t; 46572 | typedef typename igfun_t::generic_type generic_type; 46573 | typedef typename generic_type::vector_view vector_t; 46574 | 46575 | using igfun_t::operator(); 46576 | 46577 | select() 46578 | : exprtk::igeneric_function<T>("VVVV|VVVVTT") 46579 | /* 46580 | Overloads: 46581 | 0. VVVV - out vector, mask, vector 0, vector 1 46582 | 1. VVVV - out vector, mask, vector 0, vector 1, r0, r1 46583 | */ 46584 | {} 46585 | 46586 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 46587 | { 46588 | vector_t out (parameters[0]); 46589 | const vector_t mask(parameters[1]); 46590 | const vector_t vec0(parameters[2]); 46591 | const vector_t vec1(parameters[3]); 46592 | 46593 | std::size_t r0 = 0; 46594 | std::size_t r1 = std::min(out.size(), 46595 | std::min(mask.size(), 46596 | std::min(vec0.size(), vec1.size()))) - 1; 46597 | 46598 | if (1 == ps_index) 46599 | { 46600 | std::size_t rng_idx0 = 4; 46601 | std::size_t rng_idx1 = 5; 46602 | 46603 | if (!helper::load_vector_range<T>::process(parameters, r0, r1, rng_idx0, rng_idx1, 0)) 46604 | { 46605 | return T(0); 46606 | } 46607 | 46608 | if (helper::invalid_range(out , r0, r1)) return T(0); 46609 | if (helper::invalid_range(mask, r0, r1)) return T(0); 46610 | if (helper::invalid_range(vec0, r0, r1)) return T(0); 46611 | if (helper::invalid_range(vec1, r0, r1)) return T(0); 46612 | } 46613 | 46614 | for (std::size_t i = r0; i <= r1; ++i) 46615 | { 46616 | out[i] = (mask[i] != T(0)) ? vec0[i] : vec1[i]; 46617 | } 46618 | 46619 | return T(1); 46620 | } 46621 | }; 46622 | 46623 | template <typename T> 46624 | struct package 46625 | { 46626 | all_true <T> at; 46627 | all_false <T> af; 46628 | any_true <T> nt; 46629 | any_false <T> nf; 46630 | count <T> c; 46631 | copy <T> cp; 46632 | rol <T> rl; 46633 | ror <T> rr; 46634 | reverse <T> rev; 46635 | shift_left <T> sl; 46636 | shift_right <T> sr; 46637 | sort <T> st; 46638 | nthelement <T> ne; 46639 | assign <T> an; 46640 | iota <T> ia; 46641 | sumk <T> sk; 46642 | axpy <T> b1_axpy; 46643 | axpby <T> b1_axpby; 46644 | axpyz <T> b1_axpyz; 46645 | axpbyz <T> b1_axpbyz; 46646 | axpbsy <T> b1_axpbsy; 46647 | axpbsyz <T> b1_axpbsyz; 46648 | axpbz <T> b1_axpbz; 46649 | diff <T> df; 46650 | dot <T> dt; 46651 | dotk <T> dtk; 46652 | threshold_above<T> ta; 46653 | threshold_below<T> tb; 46654 | min_elemwise<T> miew; 46655 | max_elemwise<T> maew; 46656 | select<T> slct; 46657 | 46658 | bool register_package(exprtk::symbol_table<T>& symtab) 46659 | { 46660 | #define exprtk_register_function(FunctionName, FunctionType) \ 46661 | if (!symtab.add_function(FunctionName,FunctionType)) \ 46662 | { \ 46663 | exprtk_debug(( \ 46664 | "exprtk::rtl::vecops::register_package - Failed to add function: %s\n", \ 46665 | FunctionName)); \ 46666 | return false; \ 46667 | } \ 46668 | 46669 | exprtk_register_function("all_true" , at ) 46670 | exprtk_register_function("all_false" , af ) 46671 | exprtk_register_function("any_true" , nt ) 46672 | exprtk_register_function("any_false" , nf ) 46673 | exprtk_register_function("count" , c ) 46674 | exprtk_register_function("copy" , cp ) 46675 | exprtk_register_function("rotate_left" , rl ) 46676 | exprtk_register_function("rol" , rl ) 46677 | exprtk_register_function("rotate_right" , rr ) 46678 | exprtk_register_function("ror" , rr ) 46679 | exprtk_register_function("reverse" , rev ) 46680 | exprtk_register_function("shftl" , sl ) 46681 | exprtk_register_function("shftr" , sr ) 46682 | exprtk_register_function("sort" , st ) 46683 | exprtk_register_function("nth_element" , ne ) 46684 | exprtk_register_function("assign" , an ) 46685 | exprtk_register_function("iota" , ia ) 46686 | exprtk_register_function("sumk" , sk ) 46687 | exprtk_register_function("axpy" , b1_axpy ) 46688 | exprtk_register_function("axpby" , b1_axpby ) 46689 | exprtk_register_function("axpyz" , b1_axpyz ) 46690 | exprtk_register_function("axpbyz" , b1_axpbyz ) 46691 | exprtk_register_function("axpbsy" , b1_axpbsy ) 46692 | exprtk_register_function("axpbsyz" , b1_axpbsyz) 46693 | exprtk_register_function("axpbz" , b1_axpbz ) 46694 | exprtk_register_function("diff" , df ) 46695 | exprtk_register_function("dot" , dt ) 46696 | exprtk_register_function("dotk" , dtk ) 46697 | exprtk_register_function("threshold_above" , ta ) 46698 | exprtk_register_function("threshold_below" , tb ) 46699 | exprtk_register_function("min_elemwise" , miew ) 46700 | exprtk_register_function("max_elemwise" , maew ) 46701 | exprtk_register_function("select" , slct ) 46702 | 46703 | #undef exprtk_register_function 46704 | 46705 | return true; 46706 | } 46707 | }; 46708 | 46709 | } // namespace exprtk::rtl::vecops 46710 | } // namespace exprtk::rtl 46711 | } // namespace exprtk 46712 | #endif 46713 | 46714 | namespace exprtk 46715 | { 46716 | namespace information 46717 | { 46718 | using ::exprtk::details::char_cptr; 46719 | 46720 | static char_cptr library = "Mathematical Expression Toolkit" 46721 | static char_cptr version = "2.71828182845904523536028747135266249775724" 46722 | "7093699959574966967627724076630353547594571" 46723 | "3821785251664274274663919320030599218174135" 46724 | "9662904357290033429526059563073813232862794" 46725 | static char_cptr date = "20250101" 46726 | static char_cptr min_cpp = "199711L" 46727 | 46728 | static inline std::string data() 46729 | { 46730 | static const std::string info_str = std::string(library) + 46731 | std::string(" v") + std::string(version) + 46732 | std::string(" (") + date + std::string(")") + 46733 | std::string(" (") + min_cpp + std::string(")"); 46734 | return info_str; 46735 | } 46736 | 46737 | } // namespace information 46738 | 46739 | #ifdef exprtk_debug 46740 | #undef exprtk_debug 46741 | #endif 46742 | 46743 | #ifdef exprtk_error_location 46744 | #undef exprtk_error_location 46745 | #endif 46746 | 46747 | #ifdef exprtk_fallthrough 46748 | #undef exprtk_fallthrough 46749 | #endif 46750 | 46751 | #ifdef exprtk_override 46752 | #undef exprtk_override 46753 | #endif 46754 | 46755 | #ifdef exprtk_final 46756 | #undef exprtk_final 46757 | #endif 46758 | 46759 | #ifdef exprtk_delete 46760 | #undef exprtk_delete 46761 | #endif 46762 | 46763 | } // namespace exprtk 46764 | 46765 | #endif