00000 | /* 00001 | ****************************************************************** 00002 | * C++ Mathematical Expression Toolkit Library * 00003 | * * 00004 | * Author: Arash Partow (1999-2024) * 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 ((1 == mode) && test::comment_end(*s_itr_, 0, mode)) 02694 | { 02695 | ++s_itr_; 02696 | return; 02697 | } 02698 | 02699 | if ((2 == mode)) 02700 | { 02701 | if (!is_end((s_itr_ + 1)) && test::comment_end(*s_itr_, *(s_itr_ + 1), mode)) 02702 | { 02703 | s_itr_ += 2; 02704 | return; 02705 | } 02706 | } 02707 | 02708 | ++s_itr_; 02709 | } 02710 | 02711 | if (2 == mode) 02712 | { 02713 | token_t t; 02714 | t.set_error(token::e_error, cmt_start, cmt_start + mode, base_itr_); 02715 | token_list_.push_back(t); 02716 | } 02717 | #endif 02718 | } 02719 | 02720 | inline bool next_is_digit(const details::char_cptr itr) const 02721 | { 02722 | return ((itr + 1) != s_end_) && 02723 | details::is_digit(*(itr + 1)); 02724 | } 02725 | 02726 | inline void scan_token() 02727 | { 02728 | const char_t c = *s_itr_; 02729 | 02730 | if (details::is_whitespace(c)) 02731 | { 02732 | skip_whitespace(); 02733 | return; 02734 | } 02735 | else if (is_comment_start(s_itr_)) 02736 | { 02737 | skip_comments(); 02738 | return; 02739 | } 02740 | else if (details::is_operator_char(c)) 02741 | { 02742 | scan_operator(); 02743 | return; 02744 | } 02745 | else if (details::is_letter(c)) 02746 | { 02747 | scan_symbol(); 02748 | return; 02749 | } 02750 | else if (('.' == c) && !next_is_digit(s_itr_)) 02751 | { 02752 | scan_operator(); 02753 | return; 02754 | } 02755 | else if (details::is_digit(c) || ('.' == c)) 02756 | { 02757 | scan_number(); 02758 | return; 02759 | } 02760 | else if ('$' == c) 02761 | { 02762 | scan_special_function(); 02763 | return; 02764 | } 02765 | #ifndef exprtk_disable_string_capabilities 02766 | else if ('\'' == c) 02767 | { 02768 | scan_string(); 02769 | return; 02770 | } 02771 | #endif 02772 | else if ('~' == c) 02773 | { 02774 | token_t t; 02775 | t.set_symbol(s_itr_, s_itr_ + 1, base_itr_); 02776 | token_list_.push_back(t); 02777 | ++s_itr_; 02778 | return; 02779 | } 02780 | else 02781 | { 02782 | token_t t; 02783 | t.set_error(token::e_error, s_itr_, s_itr_ + 2, base_itr_); 02784 | token_list_.push_back(t); 02785 | ++s_itr_; 02786 | } 02787 | } 02788 | 02789 | inline void scan_operator() 02790 | { 02791 | token_t t; 02792 | 02793 | const char_t c0 = s_itr_[0]; 02794 | 02795 | if (!is_end(s_itr_ + 1)) 02796 | { 02797 | const char_t c1 = s_itr_[1]; 02798 | 02799 | if (!is_end(s_itr_ + 2)) 02800 | { 02801 | const char_t c2 = s_itr_[2]; 02802 | 02803 | if ((c0 == '<') && (c1 == '=') && (c2 == '>')) 02804 | { 02805 | t.set_operator(token_t::e_swap, s_itr_, s_itr_ + 3, base_itr_); 02806 | token_list_.push_back(t); 02807 | s_itr_ += 3; 02808 | return; 02809 | } 02810 | } 02811 | 02812 | token_t::token_type ttype = token_t::e_none; 02813 | 02814 | if ((c0 == '<') && (c1 == '=')) ttype = token_t::e_lte; 02815 | else if ((c0 == '>') && (c1 == '=')) ttype = token_t::e_gte; 02816 | else if ((c0 == '<') && (c1 == '>')) ttype = token_t::e_ne; 02817 | else if ((c0 == '!') && (c1 == '=')) ttype = token_t::e_ne; 02818 | else if ((c0 == '=') && (c1 == '=')) ttype = token_t::e_eq; 02819 | else if ((c0 == ':') && (c1 == '=')) ttype = token_t::e_assign; 02820 | else if ((c0 == '<') && (c1 == '<')) ttype = token_t::e_shl; 02821 | else if ((c0 == '>') && (c1 == '>')) ttype = token_t::e_shr; 02822 | else if ((c0 == '+') && (c1 == '=')) ttype = token_t::e_addass; 02823 | else if ((c0 == '-') && (c1 == '=')) ttype = token_t::e_subass; 02824 | else if ((c0 == '*') && (c1 == '=')) ttype = token_t::e_mulass; 02825 | else if ((c0 == '/') && (c1 == '=')) ttype = token_t::e_divass; 02826 | else if ((c0 == '%') && (c1 == '=')) ttype = token_t::e_modass; 02827 | 02828 | if (token_t::e_none != ttype) 02829 | { 02830 | t.set_operator(ttype, s_itr_, s_itr_ + 2, base_itr_); 02831 | token_list_.push_back(t); 02832 | s_itr_ += 2; 02833 | return; 02834 | } 02835 | } 02836 | 02837 | if ('<' == c0) 02838 | t.set_operator(token_t::e_lt , s_itr_, s_itr_ + 1, base_itr_); 02839 | else if ('>' == c0) 02840 | t.set_operator(token_t::e_gt , s_itr_, s_itr_ + 1, base_itr_); 02841 | else if (';' == c0) 02842 | t.set_operator(token_t::e_eof, s_itr_, s_itr_ + 1, base_itr_); 02843 | else if ('&' == c0) 02844 | t.set_symbol(s_itr_, s_itr_ + 1, base_itr_); 02845 | else if ('|' == c0) 02846 | t.set_symbol(s_itr_, s_itr_ + 1, base_itr_); 02847 | else 02848 | t.set_operator(token_t::token_type(c0), s_itr_, s_itr_ + 1, base_itr_); 02849 | 02850 | token_list_.push_back(t); 02851 | ++s_itr_; 02852 | } 02853 | 02854 | inline void scan_symbol() 02855 | { 02856 | details::char_cptr initial_itr = s_itr_; 02857 | 02858 | while (!is_end(s_itr_)) 02859 | { 02860 | if (!details::is_letter_or_digit(*s_itr_) && ('_' != (*s_itr_))) 02861 | { 02862 | if ('.' != (*s_itr_)) 02863 | break; 02864 | /* 02865 | Permit symbols that contain a 'dot' 02866 | Allowed : abc.xyz, a123.xyz, abc.123, abc_.xyz a123_.xyz abc._123 02867 | Disallowed: .abc, abc.<white-space>, abc.<eof>, abc.<operator +,-,*,/...> 02868 | */ 02869 | if ( 02870 | (s_itr_ != initial_itr) && 02871 | !is_end(s_itr_ + 1) && 02872 | !details::is_letter_or_digit(*(s_itr_ + 1)) && 02873 | ('_' != (*(s_itr_ + 1))) 02874 | ) 02875 | break; 02876 | } 02877 | 02878 | ++s_itr_; 02879 | } 02880 | 02881 | token_t t; 02882 | t.set_symbol(initial_itr, s_itr_, base_itr_); 02883 | token_list_.push_back(t); 02884 | } 02885 | 02886 | inline void scan_number() 02887 | { 02888 | /* 02889 | Attempt to match a valid numeric value in one of the following formats: 02890 | (01) 123456 02891 | (02) 123456. 02892 | (03) 123.456 02893 | (04) 123.456e3 02894 | (05) 123.456E3 02895 | (06) 123.456e+3 02896 | (07) 123.456E+3 02897 | (08) 123.456e-3 02898 | (09) 123.456E-3 02899 | (00) .1234 02900 | (11) .1234e3 02901 | (12) .1234E+3 02902 | (13) .1234e+3 02903 | (14) .1234E-3 02904 | (15) .1234e-3 02905 | */ 02906 | 02907 | details::char_cptr initial_itr = s_itr_; 02908 | bool dot_found = false; 02909 | bool e_found = false; 02910 | bool post_e_sign_found = false; 02911 | bool post_e_digit_found = false; 02912 | token_t t; 02913 | 02914 | while (!is_end(s_itr_)) 02915 | { 02916 | if ('.' == (*s_itr_)) 02917 | { 02918 | if (dot_found) 02919 | { 02920 | t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_); 02921 | token_list_.push_back(t); 02922 | 02923 | return; 02924 | } 02925 | 02926 | dot_found = true; 02927 | ++s_itr_; 02928 | 02929 | continue; 02930 | } 02931 | else if ('e' == std::tolower(*s_itr_)) 02932 | { 02933 | const char_t& c = *(s_itr_ + 1); 02934 | 02935 | if (is_end(s_itr_ + 1)) 02936 | { 02937 | t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_); 02938 | token_list_.push_back(t); 02939 | 02940 | return; 02941 | } 02942 | else if ( 02943 | ('+' != c) && 02944 | ('-' != c) && 02945 | !details::is_digit(c) 02946 | ) 02947 | { 02948 | t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_); 02949 | token_list_.push_back(t); 02950 | 02951 | return; 02952 | } 02953 | 02954 | e_found = true; 02955 | ++s_itr_; 02956 | 02957 | continue; 02958 | } 02959 | else if (e_found && details::is_sign(*s_itr_) && !post_e_digit_found) 02960 | { 02961 | if (post_e_sign_found) 02962 | { 02963 | t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_); 02964 | token_list_.push_back(t); 02965 | 02966 | return; 02967 | } 02968 | 02969 | post_e_sign_found = true; 02970 | ++s_itr_; 02971 | 02972 | continue; 02973 | } 02974 | else if (e_found && details::is_digit(*s_itr_)) 02975 | { 02976 | post_e_digit_found = true; 02977 | ++s_itr_; 02978 | 02979 | continue; 02980 | } 02981 | else if (('.' != (*s_itr_)) && !details::is_digit(*s_itr_)) 02982 | break; 02983 | else 02984 | ++s_itr_; 02985 | } 02986 | 02987 | t.set_numeric(initial_itr, s_itr_, base_itr_); 02988 | token_list_.push_back(t); 02989 | 02990 | return; 02991 | } 02992 | 02993 | inline void scan_special_function() 02994 | { 02995 | details::char_cptr initial_itr = s_itr_; 02996 | token_t t; 02997 | 02998 | // $fdd(x,x,x) = at least 11 chars 02999 | if (std::distance(s_itr_,s_end_) < 11) 03000 | { 03001 | t.set_error( 03002 | token::e_err_sfunc, 03003 | initial_itr, std::min(initial_itr + 11, s_end_), 03004 | base_itr_); 03005 | token_list_.push_back(t); 03006 | 03007 | return; 03008 | } 03009 | 03010 | if ( 03011 | !(('$' == *s_itr_) && 03012 | (details::imatch ('f',*(s_itr_ + 1))) && 03013 | (details::is_digit(*(s_itr_ + 2))) && 03014 | (details::is_digit(*(s_itr_ + 3)))) 03015 | ) 03016 | { 03017 | t.set_error( 03018 | token::e_err_sfunc, 03019 | initial_itr, std::min(initial_itr + 4, s_end_), 03020 | base_itr_); 03021 | token_list_.push_back(t); 03022 | 03023 | return; 03024 | } 03025 | 03026 | s_itr_ += 4; // $fdd = 4chars 03027 | 03028 | t.set_symbol(initial_itr, s_itr_, base_itr_); 03029 | token_list_.push_back(t); 03030 | 03031 | return; 03032 | } 03033 | 03034 | #ifndef exprtk_disable_string_capabilities 03035 | inline void scan_string() 03036 | { 03037 | details::char_cptr initial_itr = s_itr_ + 1; 03038 | token_t t; 03039 | 03040 | if (std::distance(s_itr_,s_end_) < 2) 03041 | { 03042 | t.set_error(token::e_err_string, s_itr_, s_end_, base_itr_); 03043 | token_list_.push_back(t); 03044 | 03045 | return; 03046 | } 03047 | 03048 | ++s_itr_; 03049 | 03050 | bool escaped_found = false; 03051 | bool escaped = false; 03052 | 03053 | while (!is_end(s_itr_)) 03054 | { 03055 | if (!details::is_valid_string_char(*s_itr_)) 03056 | { 03057 | t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_); 03058 | token_list_.push_back(t); 03059 | 03060 | return; 03061 | } 03062 | else if (!escaped && ('\\' == *s_itr_)) 03063 | { 03064 | escaped_found = true; 03065 | escaped = true; 03066 | ++s_itr_; 03067 | 03068 | continue; 03069 | } 03070 | else if (!escaped) 03071 | { 03072 | if ('\'' == *s_itr_) 03073 | break; 03074 | } 03075 | else if (escaped) 03076 | { 03077 | if ( 03078 | !is_end(s_itr_) && ('0' == *(s_itr_)) && 03079 | ((s_itr_ + 4) <= s_end_) 03080 | ) 03081 | { 03082 | const bool x_separator = ('X' == std::toupper(*(s_itr_ + 1))); 03083 | 03084 | const bool both_digits = details::is_hex_digit(*(s_itr_ + 2)) && 03085 | details::is_hex_digit(*(s_itr_ + 3)) ; 03086 | 03087 | if (!(x_separator && both_digits)) 03088 | { 03089 | t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_); 03090 | token_list_.push_back(t); 03091 | 03092 | return; 03093 | } 03094 | else 03095 | s_itr_ += 3; 03096 | } 03097 | 03098 | escaped = false; 03099 | } 03100 | 03101 | ++s_itr_; 03102 | } 03103 | 03104 | if (is_end(s_itr_)) 03105 | { 03106 | t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_); 03107 | token_list_.push_back(t); 03108 | 03109 | return; 03110 | } 03111 | 03112 | if (!escaped_found) 03113 | t.set_string(initial_itr, s_itr_, base_itr_); 03114 | else 03115 | { 03116 | std::string parsed_string(initial_itr,s_itr_); 03117 | 03118 | if (!details::cleanup_escapes(parsed_string)) 03119 | { 03120 | t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_); 03121 | token_list_.push_back(t); 03122 | 03123 | return; 03124 | } 03125 | 03126 | t.set_string( 03127 | parsed_string, 03128 | static_cast<std::size_t>(std::distance(base_itr_,initial_itr))); 03129 | } 03130 | 03131 | token_list_.push_back(t); 03132 | ++s_itr_; 03133 | 03134 | return; 03135 | } 03136 | #endif 03137 | 03138 | private: 03139 | 03140 | token_list_t token_list_; 03141 | token_list_itr_t token_itr_; 03142 | token_list_itr_t store_token_itr_; 03143 | token_t eof_token_; 03144 | details::char_cptr base_itr_; 03145 | details::char_cptr s_itr_; 03146 | details::char_cptr s_end_; 03147 | 03148 | friend class token_scanner; 03149 | friend class token_modifier; 03150 | friend class token_inserter; 03151 | friend class token_joiner; 03152 | }; // class generator 03153 | 03154 | class helper_interface 03155 | { 03156 | public: 03157 | 03158 | virtual void init() { } 03159 | virtual void reset() { } 03160 | virtual bool result() { return true; } 03161 | virtual std::size_t process(generator&) { return 0; } 03162 | virtual ~helper_interface() { } 03163 | }; 03164 | 03165 | class token_scanner : public helper_interface 03166 | { 03167 | public: 03168 | 03169 | virtual ~token_scanner() exprtk_override 03170 | {} 03171 | 03172 | explicit token_scanner(const std::size_t& stride) 03173 | : stride_(stride) 03174 | { 03175 | if (stride > 4) 03176 | { 03177 | throw std::invalid_argument("token_scanner() - Invalid stride value"); 03178 | } 03179 | } 03180 | 03181 | inline std::size_t process(generator& g) exprtk_override 03182 | { 03183 | if (g.token_list_.size() >= stride_) 03184 | { 03185 | for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i) 03186 | { 03187 | token t; 03188 | 03189 | switch (stride_) 03190 | { 03191 | case 1 : 03192 | { 03193 | const token& t0 = g.token_list_[i]; 03194 | 03195 | if (!operator()(t0)) 03196 | { 03197 | return 0; 03198 | } 03199 | } 03200 | break; 03201 | 03202 | case 2 : 03203 | { 03204 | const token& t0 = g.token_list_[i ]; 03205 | const token& t1 = g.token_list_[i + 1]; 03206 | 03207 | if (!operator()(t0, t1)) 03208 | { 03209 | return 0; 03210 | } 03211 | } 03212 | break; 03213 | 03214 | case 3 : 03215 | { 03216 | const token& t0 = g.token_list_[i ]; 03217 | const token& t1 = g.token_list_[i + 1]; 03218 | const token& t2 = g.token_list_[i + 2]; 03219 | 03220 | if (!operator()(t0, t1, t2)) 03221 | { 03222 | return 0; 03223 | } 03224 | } 03225 | break; 03226 | 03227 | case 4 : 03228 | { 03229 | const token& t0 = g.token_list_[i ]; 03230 | const token& t1 = g.token_list_[i + 1]; 03231 | const token& t2 = g.token_list_[i + 2]; 03232 | const token& t3 = g.token_list_[i + 3]; 03233 | 03234 | if (!operator()(t0, t1, t2, t3)) 03235 | { 03236 | return 0; 03237 | } 03238 | } 03239 | break; 03240 | 03241 | default: continue; 03242 | } 03243 | } 03244 | } 03245 | 03246 | return 0; 03247 | } 03248 | 03249 | virtual bool operator() (const token&) 03250 | { 03251 | return false; 03252 | } 03253 | 03254 | virtual bool operator() (const token&, const token&) 03255 | { 03256 | return false; 03257 | } 03258 | 03259 | virtual bool operator() (const token&, const token&, const token&) 03260 | { 03261 | return false; 03262 | } 03263 | 03264 | virtual bool operator() (const token&, const token&, const token&, const token&) 03265 | { 03266 | return false; 03267 | } 03268 | 03269 | private: 03270 | 03271 | const std::size_t stride_; 03272 | }; // class token_scanner 03273 | 03274 | class token_modifier : public helper_interface 03275 | { 03276 | public: 03277 | 03278 | inline std::size_t process(generator& g) exprtk_override 03279 | { 03280 | std::size_t changes = 0; 03281 | 03282 | for (std::size_t i = 0; i < g.token_list_.size(); ++i) 03283 | { 03284 | if (modify(g.token_list_[i])) changes++; 03285 | } 03286 | 03287 | return changes; 03288 | } 03289 | 03290 | virtual bool modify(token& t) = 0; 03291 | }; 03292 | 03293 | class token_inserter : public helper_interface 03294 | { 03295 | public: 03296 | 03297 | explicit token_inserter(const std::size_t& stride) 03298 | : stride_(stride) 03299 | { 03300 | if (stride > 5) 03301 | { 03302 | throw std::invalid_argument("token_inserter() - Invalid stride value"); 03303 | } 03304 | } 03305 | 03306 | inline std::size_t process(generator& g) exprtk_override 03307 | { 03308 | if (g.token_list_.empty()) 03309 | return 0; 03310 | else if (g.token_list_.size() < stride_) 03311 | return 0; 03312 | 03313 | std::size_t changes = 0; 03314 | 03315 | typedef std::pair<std::size_t, token> insert_t; 03316 | std::vector<insert_t> insert_list; 03317 | insert_list.reserve(10000); 03318 | 03319 | for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i) 03320 | { 03321 | int insert_index = -1; 03322 | token t; 03323 | 03324 | switch (stride_) 03325 | { 03326 | case 1 : insert_index = insert(g.token_list_[i],t); 03327 | break; 03328 | 03329 | case 2 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], t); 03330 | break; 03331 | 03332 | case 3 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], g.token_list_[i + 2], t); 03333 | break; 03334 | 03335 | 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); 03336 | break; 03337 | 03338 | 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); 03339 | break; 03340 | } 03341 | 03342 | if ((insert_index >= 0) && (insert_index <= (static_cast<int>(stride_) + 1))) 03343 | { 03344 | insert_list.push_back(insert_t(i, t)); 03345 | changes++; 03346 | } 03347 | } 03348 | 03349 | if (!insert_list.empty()) 03350 | { 03351 | generator::token_list_t token_list; 03352 | 03353 | std::size_t insert_index = 0; 03354 | 03355 | for (std::size_t i = 0; i < g.token_list_.size(); ++i) 03356 | { 03357 | token_list.push_back(g.token_list_[i]); 03358 | 03359 | if ( 03360 | (insert_index < insert_list.size()) && 03361 | (insert_list[insert_index].first == i) 03362 | ) 03363 | { 03364 | token_list.push_back(insert_list[insert_index].second); 03365 | insert_index++; 03366 | } 03367 | } 03368 | 03369 | std::swap(g.token_list_,token_list); 03370 | } 03371 | 03372 | return changes; 03373 | } 03374 | 03375 | #define token_inserter_empty_body \ 03376 | { \ 03377 | return -1; \ 03378 | } \ 03379 | 03380 | inline virtual int insert(const token&, token&) 03381 | token_inserter_empty_body 03382 | 03383 | inline virtual int insert(const token&, const token&, token&) 03384 | token_inserter_empty_body 03385 | 03386 | inline virtual int insert(const token&, const token&, const token&, token&) 03387 | token_inserter_empty_body 03388 | 03389 | inline virtual int insert(const token&, const token&, const token&, const token&, token&) 03390 | token_inserter_empty_body 03391 | 03392 | inline virtual int insert(const token&, const token&, const token&, const token&, const token&, token&) 03393 | token_inserter_empty_body 03394 | 03395 | #undef token_inserter_empty_body 03396 | 03397 | private: 03398 | 03399 | const std::size_t stride_; 03400 | }; 03401 | 03402 | class token_joiner : public helper_interface 03403 | { 03404 | public: 03405 | 03406 | explicit token_joiner(const std::size_t& stride) 03407 | : stride_(stride) 03408 | {} 03409 | 03410 | inline std::size_t process(generator& g) exprtk_override 03411 | { 03412 | if (g.token_list_.empty()) 03413 | return 0; 03414 | 03415 | switch (stride_) 03416 | { 03417 | case 2 : return process_stride_2(g); 03418 | case 3 : return process_stride_3(g); 03419 | default : return 0; 03420 | } 03421 | } 03422 | 03423 | virtual bool join(const token&, const token&, token&) { return false; } 03424 | virtual bool join(const token&, const token&, const token&, token&) { return false; } 03425 | 03426 | private: 03427 | 03428 | inline std::size_t process_stride_2(generator& g) 03429 | { 03430 | if (g.token_list_.size() < 2) 03431 | return 0; 03432 | 03433 | std::size_t changes = 0; 03434 | 03435 | generator::token_list_t token_list; 03436 | token_list.reserve(10000); 03437 | 03438 | for (int i = 0; i < static_cast<int>(g.token_list_.size() - 1); ++i) 03439 | { 03440 | token t; 03441 | 03442 | for ( ; ; ) 03443 | { 03444 | if (!join(g[i], g[i + 1], t)) 03445 | { 03446 | token_list.push_back(g[i]); 03447 | break; 03448 | } 03449 | 03450 | token_list.push_back(t); 03451 | 03452 | ++changes; 03453 | 03454 | i += 2; 03455 | 03456 | if (static_cast<std::size_t>(i) >= (g.token_list_.size() - 1)) 03457 | break; 03458 | } 03459 | } 03460 | 03461 | token_list.push_back(g.token_list_.back()); 03462 | 03463 | assert(token_list.size() <= g.token_list_.size()); 03464 | 03465 | std::swap(token_list, g.token_list_); 03466 | 03467 | return changes; 03468 | } 03469 | 03470 | inline std::size_t process_stride_3(generator& g) 03471 | { 03472 | if (g.token_list_.size() < 3) 03473 | return 0; 03474 | 03475 | std::size_t changes = 0; 03476 | 03477 | generator::token_list_t token_list; 03478 | token_list.reserve(10000); 03479 | 03480 | for (int i = 0; i < static_cast<int>(g.token_list_.size() - 2); ++i) 03481 | { 03482 | token t; 03483 | 03484 | for ( ; ; ) 03485 | { 03486 | if (!join(g[i], g[i + 1], g[i + 2], t)) 03487 | { 03488 | token_list.push_back(g[i]); 03489 | break; 03490 | } 03491 | 03492 | token_list.push_back(t); 03493 | 03494 | ++changes; 03495 | 03496 | i += 3; 03497 | 03498 | if (static_cast<std::size_t>(i) >= (g.token_list_.size() - 2)) 03499 | break; 03500 | } 03501 | } 03502 | 03503 | token_list.push_back(*(g.token_list_.begin() + g.token_list_.size() - 2)); 03504 | token_list.push_back(*(g.token_list_.begin() + g.token_list_.size() - 1)); 03505 | 03506 | assert(token_list.size() <= g.token_list_.size()); 03507 | 03508 | std::swap(token_list, g.token_list_); 03509 | 03510 | return changes; 03511 | } 03512 | 03513 | const std::size_t stride_; 03514 | }; 03515 | 03516 | namespace helper 03517 | { 03518 | 03519 | inline void dump(const lexer::generator& generator) 03520 | { 03521 | for (std::size_t i = 0; i < generator.size(); ++i) 03522 | { 03523 | const lexer::token& t = generator[i]; 03524 | printf("Token[%02d] @ %03d %6s --> '%s'\n", 03525 | static_cast<int>(i), 03526 | static_cast<int>(t.position), 03527 | t.to_str(t.type).c_str(), 03528 | t.value.c_str()); 03529 | } 03530 | } 03531 | 03532 | class commutative_inserter : public lexer::token_inserter 03533 | { 03534 | public: 03535 | 03536 | using lexer::token_inserter::insert; 03537 | 03538 | commutative_inserter() 03539 | : lexer::token_inserter(2) 03540 | {} 03541 | 03542 | inline void ignore_symbol(const std::string& symbol) 03543 | { 03544 | ignore_set_.insert(symbol); 03545 | } 03546 | 03547 | inline int insert(const lexer::token& t0, const lexer::token& t1, lexer::token& new_token) exprtk_override 03548 | { 03549 | bool match = false; 03550 | new_token.type = lexer::token::e_mul; 03551 | new_token.value = "*" 03552 | new_token.position = t1.position; 03553 | 03554 | if (t0.type == lexer::token::e_symbol) 03555 | { 03556 | if (ignore_set_.end() != ignore_set_.find(t0.value)) 03557 | { 03558 | return -1; 03559 | } 03560 | else if (!t0.value.empty() && ('$' == t0.value[0])) 03561 | { 03562 | return -1; 03563 | } 03564 | } 03565 | 03566 | if (t1.type == lexer::token::e_symbol) 03567 | { 03568 | if (ignore_set_.end() != ignore_set_.find(t1.value)) 03569 | { 03570 | return -1; 03571 | } 03572 | } 03573 | if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_symbol )) match = true; 03574 | else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lbracket )) match = true; 03575 | else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lcrlbracket)) match = true; 03576 | else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lsqrbracket)) match = true; 03577 | else if ((t0.type == lexer::token::e_symbol ) && (t1.type == lexer::token::e_number )) match = true; 03578 | else if ((t0.type == lexer::token::e_rbracket ) && (t1.type == lexer::token::e_number )) match = true; 03579 | else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_number )) match = true; 03580 | else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_number )) match = true; 03581 | else if ((t0.type == lexer::token::e_rbracket ) && (t1.type == lexer::token::e_symbol )) match = true; 03582 | else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_symbol )) match = true; 03583 | else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_symbol )) match = true; 03584 | else if ((t0.type == lexer::token::e_symbol ) && (t1.type == lexer::token::e_symbol )) match = true; 03585 | 03586 | return (match) ? 1 : -1; 03587 | } 03588 | 03589 | private: 03590 | 03591 | std::set<std::string,details::ilesscompare> ignore_set_; 03592 | }; 03593 | 03594 | class operator_joiner exprtk_final : public token_joiner 03595 | { 03596 | public: 03597 | 03598 | explicit operator_joiner(const std::size_t& stride) 03599 | : token_joiner(stride) 03600 | {} 03601 | 03602 | inline bool join(const lexer::token& t0, const lexer::token& t1, lexer::token& t) exprtk_override 03603 | { 03604 | // ': =' --> ':=' 03605 | if ((t0.type == lexer::token::e_colon) && (t1.type == lexer::token::e_eq)) 03606 | { 03607 | t.type = lexer::token::e_assign; 03608 | t.value = ":=" 03609 | t.position = t0.position; 03610 | 03611 | return true; 03612 | } 03613 | // '+ =' --> '+=' 03614 | else if ((t0.type == lexer::token::e_add) && (t1.type == lexer::token::e_eq)) 03615 | { 03616 | t.type = lexer::token::e_addass; 03617 | t.value = "+=" 03618 | t.position = t0.position; 03619 | 03620 | return true; 03621 | } 03622 | // '- =' --> '-=' 03623 | else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_eq)) 03624 | { 03625 | t.type = lexer::token::e_subass; 03626 | t.value = "-=" 03627 | t.position = t0.position; 03628 | 03629 | return true; 03630 | } 03631 | // '* =' --> '*=' 03632 | else if ((t0.type == lexer::token::e_mul) && (t1.type == lexer::token::e_eq)) 03633 | { 03634 | t.type = lexer::token::e_mulass; 03635 | t.value = "*=" 03636 | t.position = t0.position; 03637 | 03638 | return true; 03639 | } 03640 | // '/ =' --> '/=' 03641 | else if ((t0.type == lexer::token::e_div) && (t1.type == lexer::token::e_eq)) 03642 | { 03643 | t.type = lexer::token::e_divass; 03644 | t.value = "/=" 03645 | t.position = t0.position; 03646 | 03647 | return true; 03648 | } 03649 | // '% =' --> '%=' 03650 | else if ((t0.type == lexer::token::e_mod) && (t1.type == lexer::token::e_eq)) 03651 | { 03652 | t.type = lexer::token::e_modass; 03653 | t.value = "%=" 03654 | t.position = t0.position; 03655 | 03656 | return true; 03657 | } 03658 | // '> =' --> '>=' 03659 | else if ((t0.type == lexer::token::e_gt) && (t1.type == lexer::token::e_eq)) 03660 | { 03661 | t.type = lexer::token::e_gte; 03662 | t.value = ">=" 03663 | t.position = t0.position; 03664 | 03665 | return true; 03666 | } 03667 | // '< =' --> '<=' 03668 | else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_eq)) 03669 | { 03670 | t.type = lexer::token::e_lte; 03671 | t.value = "<=" 03672 | t.position = t0.position; 03673 | 03674 | return true; 03675 | } 03676 | // '= =' --> '==' 03677 | else if ((t0.type == lexer::token::e_eq) && (t1.type == lexer::token::e_eq)) 03678 | { 03679 | t.type = lexer::token::e_eq; 03680 | t.value = "==" 03681 | t.position = t0.position; 03682 | 03683 | return true; 03684 | } 03685 | // '! =' --> '!=' 03686 | else if ((static_cast<details::char_t>(t0.type) == '!') && (t1.type == lexer::token::e_eq)) 03687 | { 03688 | t.type = lexer::token::e_ne; 03689 | t.value = "!=" 03690 | t.position = t0.position; 03691 | 03692 | return true; 03693 | } 03694 | // '< >' --> '<>' 03695 | else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_gt)) 03696 | { 03697 | t.type = lexer::token::e_ne; 03698 | t.value = "<>" 03699 | t.position = t0.position; 03700 | 03701 | return true; 03702 | } 03703 | // '<= >' --> '<=>' 03704 | else if ((t0.type == lexer::token::e_lte) && (t1.type == lexer::token::e_gt)) 03705 | { 03706 | t.type = lexer::token::e_swap; 03707 | t.value = "<=>" 03708 | t.position = t0.position; 03709 | 03710 | return true; 03711 | } 03712 | // '+ -' --> '-' 03713 | else if ((t0.type == lexer::token::e_add) && (t1.type == lexer::token::e_sub)) 03714 | { 03715 | t.type = lexer::token::e_sub; 03716 | t.value = "-" 03717 | t.position = t0.position; 03718 | 03719 | return true; 03720 | } 03721 | // '- +' --> '-' 03722 | else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_add)) 03723 | { 03724 | t.type = lexer::token::e_sub; 03725 | t.value = "-" 03726 | t.position = t0.position; 03727 | 03728 | return true; 03729 | } 03730 | // '- -' --> '+' 03731 | else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_sub)) 03732 | { 03733 | /* 03734 | Note: May need to reconsider this when wanting to implement 03735 | pre/postfix decrement operator 03736 | */ 03737 | t.type = lexer::token::e_add; 03738 | t.value = "+" 03739 | t.position = t0.position; 03740 | 03741 | return true; 03742 | } 03743 | else 03744 | return false; 03745 | } 03746 | 03747 | inline bool join(const lexer::token& t0, 03748 | const lexer::token& t1, 03749 | const lexer::token& t2, 03750 | lexer::token& t) exprtk_override 03751 | { 03752 | // '[ * ]' --> '[*]' 03753 | if ( 03754 | (t0.type == lexer::token::e_lsqrbracket) && 03755 | (t1.type == lexer::token::e_mul ) && 03756 | (t2.type == lexer::token::e_rsqrbracket) 03757 | ) 03758 | { 03759 | t.type = lexer::token::e_symbol; 03760 | t.value = "[*]" 03761 | t.position = t0.position; 03762 | 03763 | return true; 03764 | } 03765 | else 03766 | return false; 03767 | } 03768 | }; 03769 | 03770 | class bracket_checker exprtk_final : public lexer::token_scanner 03771 | { 03772 | public: 03773 | 03774 | using lexer::token_scanner::operator(); 03775 | 03776 | bracket_checker() 03777 | : token_scanner(1) 03778 | , state_(true) 03779 | {} 03780 | 03781 | bool result() exprtk_override 03782 | { 03783 | if (!stack_.empty()) 03784 | { 03785 | lexer::token t; 03786 | t.value = stack_.top().first; 03787 | t.position = stack_.top().second; 03788 | error_token_ = t; 03789 | state_ = false; 03790 | 03791 | return false; 03792 | } 03793 | else 03794 | return state_; 03795 | } 03796 | 03797 | lexer::token error_token() const 03798 | { 03799 | return error_token_; 03800 | } 03801 | 03802 | void reset() exprtk_override 03803 | { 03804 | // Why? because msvc doesn't support swap properly. 03805 | stack_ = std::stack<std::pair<char,std::size_t> >(); 03806 | state_ = true; 03807 | error_token_.clear(); 03808 | } 03809 | 03810 | bool operator() (const lexer::token& t) exprtk_override 03811 | { 03812 | if ( 03813 | !t.value.empty() && 03814 | (lexer::token::e_string != t.type) && 03815 | (lexer::token::e_symbol != t.type) && 03816 | exprtk::details::is_bracket(t.value[0]) 03817 | ) 03818 | { 03819 | details::char_t c = t.value[0]; 03820 | 03821 | if (t.type == lexer::token::e_lbracket ) stack_.push(std::make_pair(')',t.position)); 03822 | else if (t.type == lexer::token::e_lcrlbracket) stack_.push(std::make_pair('}',t.position)); 03823 | else if (t.type == lexer::token::e_lsqrbracket) stack_.push(std::make_pair(']',t.position)); 03824 | else if (exprtk::details::is_right_bracket(c)) 03825 | { 03826 | if (stack_.empty()) 03827 | { 03828 | state_ = false; 03829 | error_token_ = t; 03830 | 03831 | return false; 03832 | } 03833 | else if (c != stack_.top().first) 03834 | { 03835 | state_ = false; 03836 | error_token_ = t; 03837 | 03838 | return false; 03839 | } 03840 | else 03841 | stack_.pop(); 03842 | } 03843 | } 03844 | 03845 | return true; 03846 | } 03847 | 03848 | private: 03849 | 03850 | bool state_; 03851 | std::stack<std::pair<char,std::size_t> > stack_; 03852 | lexer::token error_token_; 03853 | }; 03854 | 03855 | template <typename T> 03856 | class numeric_checker exprtk_final : public lexer::token_scanner 03857 | { 03858 | public: 03859 | 03860 | using lexer::token_scanner::operator(); 03861 | 03862 | numeric_checker() 03863 | : token_scanner (1) 03864 | , current_index_(0) 03865 | {} 03866 | 03867 | bool result() exprtk_override 03868 | { 03869 | return error_list_.empty(); 03870 | } 03871 | 03872 | void reset() exprtk_override 03873 | { 03874 | error_list_.clear(); 03875 | current_index_ = 0; 03876 | } 03877 | 03878 | bool operator() (const lexer::token& t) exprtk_override 03879 | { 03880 | if (token::e_number == t.type) 03881 | { 03882 | T v; 03883 | 03884 | if (!exprtk::details::string_to_real(t.value,v)) 03885 | { 03886 | error_list_.push_back(current_index_); 03887 | } 03888 | } 03889 | 03890 | ++current_index_; 03891 | 03892 | return true; 03893 | } 03894 | 03895 | std::size_t error_count() const 03896 | { 03897 | return error_list_.size(); 03898 | } 03899 | 03900 | std::size_t error_index(const std::size_t& i) const 03901 | { 03902 | if (i < error_list_.size()) 03903 | return error_list_[i]; 03904 | else 03905 | return std::numeric_limits<std::size_t>::max(); 03906 | } 03907 | 03908 | void clear_errors() 03909 | { 03910 | error_list_.clear(); 03911 | } 03912 | 03913 | private: 03914 | 03915 | std::size_t current_index_; 03916 | std::vector<std::size_t> error_list_; 03917 | }; 03918 | 03919 | class symbol_replacer exprtk_final : public lexer::token_modifier 03920 | { 03921 | private: 03922 | 03923 | typedef std::map<std::string,std::pair<std::string,token::token_type>,details::ilesscompare> replace_map_t; 03924 | 03925 | public: 03926 | 03927 | bool remove(const std::string& target_symbol) 03928 | { 03929 | const replace_map_t::iterator itr = replace_map_.find(target_symbol); 03930 | 03931 | if (replace_map_.end() == itr) 03932 | return false; 03933 | 03934 | replace_map_.erase(itr); 03935 | 03936 | return true; 03937 | } 03938 | 03939 | bool add_replace(const std::string& target_symbol, 03940 | const std::string& replace_symbol, 03941 | const lexer::token::token_type token_type = lexer::token::e_symbol) 03942 | { 03943 | const replace_map_t::iterator itr = replace_map_.find(target_symbol); 03944 | 03945 | if (replace_map_.end() != itr) 03946 | { 03947 | return false; 03948 | } 03949 | 03950 | replace_map_[target_symbol] = std::make_pair(replace_symbol,token_type); 03951 | 03952 | return true; 03953 | } 03954 | 03955 | void clear() 03956 | { 03957 | replace_map_.clear(); 03958 | } 03959 | 03960 | private: 03961 | 03962 | bool modify(lexer::token& t) exprtk_override 03963 | { 03964 | if (lexer::token::e_symbol == t.type) 03965 | { 03966 | if (replace_map_.empty()) 03967 | return false; 03968 | 03969 | const replace_map_t::iterator itr = replace_map_.find(t.value); 03970 | 03971 | if (replace_map_.end() != itr) 03972 | { 03973 | t.value = itr->second.first; 03974 | t.type = itr->second.second; 03975 | 03976 | return true; 03977 | } 03978 | } 03979 | 03980 | return false; 03981 | } 03982 | 03983 | replace_map_t replace_map_; 03984 | }; 03985 | 03986 | class sequence_validator exprtk_final : public lexer::token_scanner 03987 | { 03988 | private: 03989 | 03990 | typedef std::pair<lexer::token::token_type,lexer::token::token_type> token_pair_t; 03991 | typedef std::set<token_pair_t> set_t; 03992 | 03993 | public: 03994 | 03995 | using lexer::token_scanner::operator(); 03996 | 03997 | sequence_validator() 03998 | : lexer::token_scanner(2) 03999 | { 04000 | add_invalid(lexer::token::e_number, lexer::token::e_number); 04001 | add_invalid(lexer::token::e_string, lexer::token::e_string); 04002 | add_invalid(lexer::token::e_number, lexer::token::e_string); 04003 | add_invalid(lexer::token::e_string, lexer::token::e_number); 04004 | 04005 | add_invalid_set1(lexer::token::e_assign ); 04006 | add_invalid_set1(lexer::token::e_shr ); 04007 | add_invalid_set1(lexer::token::e_shl ); 04008 | add_invalid_set1(lexer::token::e_lte ); 04009 | add_invalid_set1(lexer::token::e_ne ); 04010 | add_invalid_set1(lexer::token::e_gte ); 04011 | add_invalid_set1(lexer::token::e_lt ); 04012 | add_invalid_set1(lexer::token::e_gt ); 04013 | add_invalid_set1(lexer::token::e_eq ); 04014 | add_invalid_set1(lexer::token::e_comma ); 04015 | add_invalid_set1(lexer::token::e_add ); 04016 | add_invalid_set1(lexer::token::e_sub ); 04017 | add_invalid_set1(lexer::token::e_div ); 04018 | add_invalid_set1(lexer::token::e_mul ); 04019 | add_invalid_set1(lexer::token::e_mod ); 04020 | add_invalid_set1(lexer::token::e_pow ); 04021 | add_invalid_set1(lexer::token::e_colon ); 04022 | add_invalid_set1(lexer::token::e_ternary); 04023 | } 04024 | 04025 | bool result() exprtk_override 04026 | { 04027 | return error_list_.empty(); 04028 | } 04029 | 04030 | bool operator() (const lexer::token& t0, const lexer::token& t1) exprtk_override 04031 | { 04032 | const set_t::value_type p = std::make_pair(t0.type,t1.type); 04033 | 04034 | if (invalid_bracket_check(t0.type,t1.type)) 04035 | { 04036 | error_list_.push_back(std::make_pair(t0,t1)); 04037 | } 04038 | else if (invalid_comb_.find(p) != invalid_comb_.end()) 04039 | { 04040 | error_list_.push_back(std::make_pair(t0,t1)); 04041 | } 04042 | 04043 | return true; 04044 | } 04045 | 04046 | std::size_t error_count() const 04047 | { 04048 | return error_list_.size(); 04049 | } 04050 | 04051 | std::pair<lexer::token,lexer::token> error(const std::size_t index) 04052 | { 04053 | if (index < error_list_.size()) 04054 | { 04055 | return error_list_[index]; 04056 | } 04057 | else 04058 | { 04059 | static const lexer::token error_token; 04060 | return std::make_pair(error_token,error_token); 04061 | } 04062 | } 04063 | 04064 | void clear_errors() 04065 | { 04066 | error_list_.clear(); 04067 | } 04068 | 04069 | private: 04070 | 04071 | void add_invalid(const lexer::token::token_type base, const lexer::token::token_type t) 04072 | { 04073 | invalid_comb_.insert(std::make_pair(base,t)); 04074 | } 04075 | 04076 | void add_invalid_set1(const lexer::token::token_type t) 04077 | { 04078 | add_invalid(t, lexer::token::e_assign); 04079 | add_invalid(t, lexer::token::e_shr ); 04080 | add_invalid(t, lexer::token::e_shl ); 04081 | add_invalid(t, lexer::token::e_lte ); 04082 | add_invalid(t, lexer::token::e_ne ); 04083 | add_invalid(t, lexer::token::e_gte ); 04084 | add_invalid(t, lexer::token::e_lt ); 04085 | add_invalid(t, lexer::token::e_gt ); 04086 | add_invalid(t, lexer::token::e_eq ); 04087 | add_invalid(t, lexer::token::e_comma ); 04088 | add_invalid(t, lexer::token::e_div ); 04089 | add_invalid(t, lexer::token::e_mul ); 04090 | add_invalid(t, lexer::token::e_mod ); 04091 | add_invalid(t, lexer::token::e_pow ); 04092 | add_invalid(t, lexer::token::e_colon ); 04093 | } 04094 | 04095 | bool invalid_bracket_check(const lexer::token::token_type base, const lexer::token::token_type t) 04096 | { 04097 | if (details::is_right_bracket(static_cast<details::char_t>(base))) 04098 | { 04099 | switch (t) 04100 | { 04101 | case lexer::token::e_assign : return (']' != base); 04102 | case lexer::token::e_string : return (')' != base); 04103 | default : return false; 04104 | } 04105 | } 04106 | else if (details::is_left_bracket(static_cast<details::char_t>(base))) 04107 | { 04108 | if (details::is_right_bracket(static_cast<details::char_t>(t))) 04109 | return false; 04110 | else if (details::is_left_bracket(static_cast<details::char_t>(t))) 04111 | return false; 04112 | else 04113 | { 04114 | switch (t) 04115 | { 04116 | case lexer::token::e_number : return false; 04117 | case lexer::token::e_symbol : return false; 04118 | case lexer::token::e_string : return false; 04119 | case lexer::token::e_add : return false; 04120 | case lexer::token::e_sub : return false; 04121 | case lexer::token::e_colon : return false; 04122 | case lexer::token::e_ternary : return false; 04123 | default : return true ; 04124 | } 04125 | } 04126 | } 04127 | else if (details::is_right_bracket(static_cast<details::char_t>(t))) 04128 | { 04129 | switch (base) 04130 | { 04131 | case lexer::token::e_number : return false; 04132 | case lexer::token::e_symbol : return false; 04133 | case lexer::token::e_string : return false; 04134 | case lexer::token::e_eof : return false; 04135 | case lexer::token::e_colon : return false; 04136 | case lexer::token::e_ternary : return false; 04137 | default : return true ; 04138 | } 04139 | } 04140 | else if (details::is_left_bracket(static_cast<details::char_t>(t))) 04141 | { 04142 | switch (base) 04143 | { 04144 | case lexer::token::e_rbracket : return true; 04145 | case lexer::token::e_rsqrbracket : return true; 04146 | case lexer::token::e_rcrlbracket : return true; 04147 | default : return false; 04148 | } 04149 | } 04150 | 04151 | return false; 04152 | } 04153 | 04154 | set_t invalid_comb_; 04155 | std::vector<std::pair<lexer::token,lexer::token> > error_list_; 04156 | }; 04157 | 04158 | class sequence_validator_3tokens exprtk_final : public lexer::token_scanner 04159 | { 04160 | private: 04161 | 04162 | typedef lexer::token::token_type token_t; 04163 | typedef std::pair<token_t,std::pair<token_t,token_t> > token_triplet_t; 04164 | typedef std::set<token_triplet_t> set_t; 04165 | 04166 | public: 04167 | 04168 | using lexer::token_scanner::operator(); 04169 | 04170 | sequence_validator_3tokens() 04171 | : lexer::token_scanner(3) 04172 | { 04173 | add_invalid(lexer::token::e_number , lexer::token::e_number , lexer::token::e_number); 04174 | add_invalid(lexer::token::e_string , lexer::token::e_string , lexer::token::e_string); 04175 | add_invalid(lexer::token::e_comma , lexer::token::e_comma , lexer::token::e_comma ); 04176 | 04177 | add_invalid(lexer::token::e_add , lexer::token::e_add , lexer::token::e_add ); 04178 | add_invalid(lexer::token::e_sub , lexer::token::e_sub , lexer::token::e_sub ); 04179 | add_invalid(lexer::token::e_div , lexer::token::e_div , lexer::token::e_div ); 04180 | add_invalid(lexer::token::e_mul , lexer::token::e_mul , lexer::token::e_mul ); 04181 | add_invalid(lexer::token::e_mod , lexer::token::e_mod , lexer::token::e_mod ); 04182 | add_invalid(lexer::token::e_pow , lexer::token::e_pow , lexer::token::e_pow ); 04183 | 04184 | add_invalid(lexer::token::e_add , lexer::token::e_sub , lexer::token::e_add ); 04185 | add_invalid(lexer::token::e_sub , lexer::token::e_add , lexer::token::e_sub ); 04186 | add_invalid(lexer::token::e_div , lexer::token::e_mul , lexer::token::e_div ); 04187 | add_invalid(lexer::token::e_mul , lexer::token::e_div , lexer::token::e_mul ); 04188 | add_invalid(lexer::token::e_mod , lexer::token::e_pow , lexer::token::e_mod ); 04189 | add_invalid(lexer::token::e_pow , lexer::token::e_mod , lexer::token::e_pow ); 04190 | } 04191 | 04192 | bool result() exprtk_override 04193 | { 04194 | return error_list_.empty(); 04195 | } 04196 | 04197 | bool operator() (const lexer::token& t0, const lexer::token& t1, const lexer::token& t2) exprtk_override 04198 | { 04199 | const set_t::value_type p = std::make_pair(t0.type,std::make_pair(t1.type,t2.type)); 04200 | 04201 | if (invalid_comb_.find(p) != invalid_comb_.end()) 04202 | { 04203 | error_list_.push_back(std::make_pair(t0,t1)); 04204 | } 04205 | 04206 | return true; 04207 | } 04208 | 04209 | std::size_t error_count() const 04210 | { 04211 | return error_list_.size(); 04212 | } 04213 | 04214 | std::pair<lexer::token,lexer::token> error(const std::size_t index) 04215 | { 04216 | if (index < error_list_.size()) 04217 | { 04218 | return error_list_[index]; 04219 | } 04220 | else 04221 | { 04222 | static const lexer::token error_token; 04223 | return std::make_pair(error_token,error_token); 04224 | } 04225 | } 04226 | 04227 | void clear_errors() 04228 | { 04229 | error_list_.clear(); 04230 | } 04231 | 04232 | private: 04233 | 04234 | void add_invalid(const token_t t0, const token_t t1, const token_t t2) 04235 | { 04236 | invalid_comb_.insert(std::make_pair(t0,std::make_pair(t1,t2))); 04237 | } 04238 | 04239 | set_t invalid_comb_; 04240 | std::vector<std::pair<lexer::token,lexer::token> > error_list_; 04241 | }; 04242 | 04243 | struct helper_assembly 04244 | { 04245 | inline bool register_scanner(lexer::token_scanner* scanner) 04246 | { 04247 | if (token_scanner_list.end() != std::find(token_scanner_list.begin(), 04248 | token_scanner_list.end (), 04249 | scanner)) 04250 | { 04251 | return false; 04252 | } 04253 | 04254 | token_scanner_list.push_back(scanner); 04255 | 04256 | return true; 04257 | } 04258 | 04259 | inline bool register_modifier(lexer::token_modifier* modifier) 04260 | { 04261 | if (token_modifier_list.end() != std::find(token_modifier_list.begin(), 04262 | token_modifier_list.end (), 04263 | modifier)) 04264 | { 04265 | return false; 04266 | } 04267 | 04268 | token_modifier_list.push_back(modifier); 04269 | 04270 | return true; 04271 | } 04272 | 04273 | inline bool register_joiner(lexer::token_joiner* joiner) 04274 | { 04275 | if (token_joiner_list.end() != std::find(token_joiner_list.begin(), 04276 | token_joiner_list.end (), 04277 | joiner)) 04278 | { 04279 | return false; 04280 | } 04281 | 04282 | token_joiner_list.push_back(joiner); 04283 | 04284 | return true; 04285 | } 04286 | 04287 | inline bool register_inserter(lexer::token_inserter* inserter) 04288 | { 04289 | if (token_inserter_list.end() != std::find(token_inserter_list.begin(), 04290 | token_inserter_list.end (), 04291 | inserter)) 04292 | { 04293 | return false; 04294 | } 04295 | 04296 | token_inserter_list.push_back(inserter); 04297 | 04298 | return true; 04299 | } 04300 | 04301 | inline bool run_modifiers(lexer::generator& g) 04302 | { 04303 | error_token_modifier = reinterpret_cast<lexer::token_modifier*>(0); 04304 | 04305 | for (std::size_t i = 0; i < token_modifier_list.size(); ++i) 04306 | { 04307 | lexer::token_modifier& modifier = (*token_modifier_list[i]); 04308 | 04309 | modifier.reset(); 04310 | modifier.process(g); 04311 | 04312 | if (!modifier.result()) 04313 | { 04314 | error_token_modifier = token_modifier_list[i]; 04315 | 04316 | return false; 04317 | } 04318 | } 04319 | 04320 | return true; 04321 | } 04322 | 04323 | inline bool run_joiners(lexer::generator& g) 04324 | { 04325 | error_token_joiner = reinterpret_cast<lexer::token_joiner*>(0); 04326 | 04327 | for (std::size_t i = 0; i < token_joiner_list.size(); ++i) 04328 | { 04329 | lexer::token_joiner& joiner = (*token_joiner_list[i]); 04330 | 04331 | joiner.reset(); 04332 | joiner.process(g); 04333 | 04334 | if (!joiner.result()) 04335 | { 04336 | error_token_joiner = token_joiner_list[i]; 04337 | 04338 | return false; 04339 | } 04340 | } 04341 | 04342 | return true; 04343 | } 04344 | 04345 | inline bool run_inserters(lexer::generator& g) 04346 | { 04347 | error_token_inserter = reinterpret_cast<lexer::token_inserter*>(0); 04348 | 04349 | for (std::size_t i = 0; i < token_inserter_list.size(); ++i) 04350 | { 04351 | lexer::token_inserter& inserter = (*token_inserter_list[i]); 04352 | 04353 | inserter.reset(); 04354 | inserter.process(g); 04355 | 04356 | if (!inserter.result()) 04357 | { 04358 | error_token_inserter = token_inserter_list[i]; 04359 | 04360 | return false; 04361 | } 04362 | } 04363 | 04364 | return true; 04365 | } 04366 | 04367 | inline bool run_scanners(lexer::generator& g) 04368 | { 04369 | error_token_scanner = reinterpret_cast<lexer::token_scanner*>(0); 04370 | 04371 | for (std::size_t i = 0; i < token_scanner_list.size(); ++i) 04372 | { 04373 | lexer::token_scanner& scanner = (*token_scanner_list[i]); 04374 | 04375 | scanner.reset(); 04376 | scanner.process(g); 04377 | 04378 | if (!scanner.result()) 04379 | { 04380 | error_token_scanner = token_scanner_list[i]; 04381 | 04382 | return false; 04383 | } 04384 | } 04385 | 04386 | return true; 04387 | } 04388 | 04389 | std::vector<lexer::token_scanner*> token_scanner_list; 04390 | std::vector<lexer::token_modifier*> token_modifier_list; 04391 | std::vector<lexer::token_joiner*> token_joiner_list; 04392 | std::vector<lexer::token_inserter*> token_inserter_list; 04393 | 04394 | lexer::token_scanner* error_token_scanner; 04395 | lexer::token_modifier* error_token_modifier; 04396 | lexer::token_joiner* error_token_joiner; 04397 | lexer::token_inserter* error_token_inserter; 04398 | }; 04399 | } 04400 | 04401 | class parser_helper 04402 | { 04403 | public: 04404 | 04405 | typedef token token_t; 04406 | typedef generator generator_t; 04407 | 04408 | inline bool init(const std::string& str) 04409 | { 04410 | if (!lexer_.process(str)) 04411 | { 04412 | return false; 04413 | } 04414 | 04415 | lexer_.begin(); 04416 | 04417 | next_token(); 04418 | 04419 | return true; 04420 | } 04421 | 04422 | inline generator_t& lexer() 04423 | { 04424 | return lexer_; 04425 | } 04426 | 04427 | inline const generator_t& lexer() const 04428 | { 04429 | return lexer_; 04430 | } 04431 | 04432 | inline void store_token() 04433 | { 04434 | lexer_.store(); 04435 | store_current_token_ = current_token_; 04436 | } 04437 | 04438 | inline void restore_token() 04439 | { 04440 | lexer_.restore(); 04441 | current_token_ = store_current_token_; 04442 | } 04443 | 04444 | inline void next_token() 04445 | { 04446 | current_token_ = lexer_.next_token(); 04447 | } 04448 | 04449 | inline const token_t& current_token() const 04450 | { 04451 | return current_token_; 04452 | } 04453 | 04454 | inline const token_t& peek_next_token() 04455 | { 04456 | return lexer_.peek_next_token(); 04457 | } 04458 | 04459 | enum token_advance_mode 04460 | { 04461 | e_hold = 0, 04462 | e_advance = 1 04463 | }; 04464 | 04465 | inline void advance_token(const token_advance_mode mode) 04466 | { 04467 | if (e_advance == mode) 04468 | { 04469 | next_token(); 04470 | } 04471 | } 04472 | 04473 | inline bool token_is(const token_t::token_type& ttype, const token_advance_mode mode = e_advance) 04474 | { 04475 | if (current_token().type != ttype) 04476 | { 04477 | return false; 04478 | } 04479 | 04480 | advance_token(mode); 04481 | 04482 | return true; 04483 | } 04484 | 04485 | inline bool token_is(const token_t::token_type& ttype, 04486 | const std::string& value, 04487 | const token_advance_mode mode = e_advance) 04488 | { 04489 | if ( 04490 | (current_token().type != ttype) || 04491 | !exprtk::details::imatch(value,current_token().value) 04492 | ) 04493 | { 04494 | return false; 04495 | } 04496 | 04497 | advance_token(mode); 04498 | 04499 | return true; 04500 | } 04501 | 04502 | inline bool token_is(const std::string& value, 04503 | const token_advance_mode mode = e_advance) 04504 | { 04505 | if (!exprtk::details::imatch(value,current_token().value)) 04506 | { 04507 | return false; 04508 | } 04509 | 04510 | advance_token(mode); 04511 | 04512 | return true; 04513 | } 04514 | 04515 | inline bool token_is_arithmetic_opr(const token_advance_mode mode = e_advance) 04516 | { 04517 | switch (current_token().type) 04518 | { 04519 | case token_t::e_add : 04520 | case token_t::e_sub : 04521 | case token_t::e_div : 04522 | case token_t::e_mul : 04523 | case token_t::e_mod : 04524 | case token_t::e_pow : break; 04525 | default : return false; 04526 | } 04527 | 04528 | advance_token(mode); 04529 | 04530 | return true; 04531 | } 04532 | 04533 | inline bool token_is_ineq_opr(const token_advance_mode mode = e_advance) 04534 | { 04535 | switch (current_token().type) 04536 | { 04537 | case token_t::e_eq : 04538 | case token_t::e_lte : 04539 | case token_t::e_ne : 04540 | case token_t::e_gte : 04541 | case token_t::e_lt : 04542 | case token_t::e_gt : break; 04543 | default : return false; 04544 | } 04545 | 04546 | advance_token(mode); 04547 | 04548 | return true; 04549 | } 04550 | 04551 | inline bool token_is_left_bracket(const token_advance_mode mode = e_advance) 04552 | { 04553 | switch (current_token().type) 04554 | { 04555 | case token_t::e_lbracket : 04556 | case token_t::e_lcrlbracket : 04557 | case token_t::e_lsqrbracket : break; 04558 | default : return false; 04559 | } 04560 | 04561 | advance_token(mode); 04562 | 04563 | return true; 04564 | } 04565 | 04566 | inline bool token_is_right_bracket(const token_advance_mode mode = e_advance) 04567 | { 04568 | switch (current_token().type) 04569 | { 04570 | case token_t::e_rbracket : 04571 | case token_t::e_rcrlbracket : 04572 | case token_t::e_rsqrbracket : break; 04573 | default : return false; 04574 | } 04575 | 04576 | advance_token(mode); 04577 | 04578 | return true; 04579 | } 04580 | 04581 | inline bool token_is_bracket(const token_advance_mode mode = e_advance) 04582 | { 04583 | switch (current_token().type) 04584 | { 04585 | case token_t::e_rbracket : 04586 | case token_t::e_rcrlbracket : 04587 | case token_t::e_rsqrbracket : 04588 | case token_t::e_lbracket : 04589 | case token_t::e_lcrlbracket : 04590 | case token_t::e_lsqrbracket : break; 04591 | default : return false; 04592 | } 04593 | 04594 | advance_token(mode); 04595 | 04596 | return true; 04597 | } 04598 | 04599 | inline bool token_is_loop(const token_advance_mode mode = e_advance) 04600 | { 04601 | return token_is("for" , mode) || 04602 | token_is("while" , mode) || 04603 | token_is("repeat", mode) ; 04604 | } 04605 | 04606 | inline bool peek_token_is(const token_t::token_type& ttype) 04607 | { 04608 | return (lexer_.peek_next_token().type == ttype); 04609 | } 04610 | 04611 | inline bool peek_token_is(const std::string& s) 04612 | { 04613 | return (exprtk::details::imatch(lexer_.peek_next_token().value,s)); 04614 | } 04615 | 04616 | private: 04617 | 04618 | generator_t lexer_; 04619 | token_t current_token_; 04620 | token_t store_current_token_; 04621 | }; 04622 | } 04623 | 04624 | template <typename T> 04625 | class vector_view 04626 | { 04627 | public: 04628 | 04629 | typedef T* data_ptr_t; 04630 | 04631 | vector_view(data_ptr_t data, const std::size_t& size) 04632 | : base_size_(size) 04633 | , size_(size) 04634 | , data_(data) 04635 | , data_ref_(0) 04636 | { 04637 | assert(size_ > 0); 04638 | } 04639 | 04640 | vector_view(const vector_view<T>& vv) 04641 | : base_size_(vv.base_size_) 04642 | , size_(vv.size_) 04643 | , data_(vv.data_) 04644 | , data_ref_(0) 04645 | { 04646 | assert(size_ > 0); 04647 | } 04648 | 04649 | inline void rebase(data_ptr_t data) 04650 | { 04651 | data_ = data; 04652 | 04653 | if (!data_ref_.empty()) 04654 | { 04655 | for (std::size_t i = 0; i < data_ref_.size(); ++i) 04656 | { 04657 | (*data_ref_[i]) = data; 04658 | } 04659 | } 04660 | } 04661 | 04662 | inline data_ptr_t data() const 04663 | { 04664 | return data_; 04665 | } 04666 | 04667 | inline std::size_t base_size() const 04668 | { 04669 | return base_size_; 04670 | } 04671 | 04672 | inline std::size_t size() const 04673 | { 04674 | return size_; 04675 | } 04676 | 04677 | inline const T& operator[](const std::size_t index) const 04678 | { 04679 | assert(index < size_); 04680 | return data_[index]; 04681 | } 04682 | 04683 | inline T& operator[](const std::size_t index) 04684 | { 04685 | assert(index < size_); 04686 | return data_[index]; 04687 | } 04688 | 04689 | void set_ref(data_ptr_t* data_ref) 04690 | { 04691 | data_ref_.push_back(data_ref); 04692 | exprtk_debug(("vector_view::set_ref() - data_ref: %p data_ref_.size(): %d\n", 04693 | reinterpret_cast<void*>(data_ref), 04694 | static_cast<int>(data_ref_.size()))); 04695 | } 04696 | 04697 | void set_size_ref(std::size_t* size_ref) 04698 | { 04699 | size_ref_.push_back(size_ref); 04700 | exprtk_debug(("vector_view::set_size_ref() - size_ref: %p size_ref_.size(): %d\n", 04701 | reinterpret_cast<void*>(size_ref), 04702 | static_cast<int>(size_ref_.size()))); 04703 | } 04704 | 04705 | void remove_ref(data_ptr_t* data_ref) 04706 | { 04707 | data_ref_.erase( 04708 | std::remove(data_ref_.begin(), data_ref_.end(), data_ref), 04709 | data_ref_.end()); 04710 | exprtk_debug(("vector_view::remove_ref() - data_ref: %p data_ref_.size(): %d\n", 04711 | reinterpret_cast<void*>(data_ref), 04712 | static_cast<int>(data_ref_.size()))); 04713 | } 04714 | 04715 | void remove_size_ref(std::size_t* size_ref) 04716 | { 04717 | size_ref_.erase( 04718 | std::remove(size_ref_.begin(), size_ref_.end(), size_ref), 04719 | size_ref_.end()); 04720 | exprtk_debug(("vector_view::remove_size_ref() - size_ref: %p size_ref_.size(): %d\n", 04721 | reinterpret_cast<void*>(size_ref), 04722 | static_cast<int>(size_ref_.size()))); 04723 | } 04724 | 04725 | bool set_size(const std::size_t new_size) 04726 | { 04727 | if ((new_size > 0) && (new_size <= base_size_)) 04728 | { 04729 | size_ = new_size; 04730 | exprtk_debug(("vector_view::set_size() - data_: %p size: %lu\n", 04731 | reinterpret_cast<void*>(data_), 04732 | size_)); 04733 | 04734 | if (!size_ref_.empty()) 04735 | { 04736 | for (std::size_t i = 0; i < size_ref_.size(); ++i) 04737 | { 04738 | (*size_ref_[i]) = new_size; 04739 | } 04740 | } 04741 | 04742 | return true; 04743 | } 04744 | 04745 | exprtk_debug(("vector_view::set_size() - error invalid new_size: %lu base_size: %lu\n", 04746 | new_size, 04747 | base_size_)); 04748 | return false; 04749 | } 04750 | 04751 | private: 04752 | 04753 | const std::size_t base_size_; 04754 | std::size_t size_; 04755 | data_ptr_t data_; 04756 | std::vector<data_ptr_t*> data_ref_; 04757 | std::vector<std::size_t*> size_ref_; 04758 | }; 04759 | 04760 | template <typename T> 04761 | inline vector_view<T> make_vector_view(T* data, 04762 | const std::size_t size, const std::size_t offset = 0) 04763 | { 04764 | return vector_view<T>(data + offset, size); 04765 | } 04766 | 04767 | template <typename T> 04768 | inline vector_view<T> make_vector_view(std::vector<T>& v, 04769 | const std::size_t size, const std::size_t offset = 0) 04770 | { 04771 | return vector_view<T>(v.data() + offset, size); 04772 | } 04773 | 04774 | template <typename T> class results_context; 04775 | namespace details { template <typename T> class vector_interface; } 04776 | 04777 | template <typename T> 04778 | struct type_store 04779 | { 04780 | enum store_type 04781 | { 04782 | e_unknown, 04783 | e_scalar , 04784 | e_vector , 04785 | e_string 04786 | }; 04787 | 04788 | type_store() 04789 | : data(0) 04790 | , size(0) 04791 | , type(e_unknown) 04792 | , ivec(0) 04793 | {} 04794 | 04795 | union 04796 | { 04797 | void* data; 04798 | T* vec_data; 04799 | }; 04800 | 04801 | typedef details::vector_interface<T>* ivec_t; 04802 | 04803 | std::size_t size; 04804 | store_type type; 04805 | ivec_t ivec; 04806 | 04807 | class parameter_list 04808 | { 04809 | public: 04810 | 04811 | explicit parameter_list(std::vector<type_store>& pl) 04812 | : parameter_list_(pl) 04813 | {} 04814 | 04815 | inline bool empty() const 04816 | { 04817 | return parameter_list_.empty(); 04818 | } 04819 | 04820 | inline std::size_t size() const 04821 | { 04822 | return parameter_list_.size(); 04823 | } 04824 | 04825 | inline type_store& operator[](const std::size_t& index) 04826 | { 04827 | return parameter_list_[index]; 04828 | } 04829 | 04830 | inline const type_store& operator[](const std::size_t& index) const 04831 | { 04832 | return parameter_list_[index]; 04833 | } 04834 | 04835 | inline type_store& front() 04836 | { 04837 | return parameter_list_[0]; 04838 | } 04839 | 04840 | inline const type_store& front() const 04841 | { 04842 | return parameter_list_[0]; 04843 | } 04844 | 04845 | inline type_store& back() 04846 | { 04847 | return parameter_list_.back(); 04848 | } 04849 | 04850 | inline const type_store& back() const 04851 | { 04852 | return parameter_list_.back(); 04853 | } 04854 | 04855 | inline typename std::vector<type_store>::const_iterator begin() const 04856 | { 04857 | return parameter_list_.begin(); 04858 | } 04859 | 04860 | inline typename std::vector<type_store>::const_iterator end() const 04861 | { 04862 | return parameter_list_.end(); 04863 | } 04864 | 04865 | inline typename std::vector<type_store>::iterator begin() 04866 | { 04867 | return parameter_list_.begin(); 04868 | } 04869 | 04870 | inline typename std::vector<type_store>::iterator end() 04871 | { 04872 | return parameter_list_.end(); 04873 | } 04874 | 04875 | private: 04876 | 04877 | std::vector<type_store>& parameter_list_; 04878 | 04879 | friend class results_context<T>; 04880 | }; 04881 | 04882 | template <typename ViewType> 04883 | struct type_view 04884 | { 04885 | typedef type_store<T> type_store_t; 04886 | typedef ViewType value_t; 04887 | 04888 | explicit type_view(type_store_t& ts) 04889 | : ts_(ts) 04890 | , data_(reinterpret_cast<value_t*>(ts_.data)) 04891 | {} 04892 | 04893 | explicit type_view(const type_store_t& ts) 04894 | : ts_(const_cast<type_store_t&>(ts)) 04895 | , data_(reinterpret_cast<value_t*>(ts_.data)) 04896 | {} 04897 | 04898 | inline std::size_t size() const 04899 | { 04900 | return ts_.size; 04901 | } 04902 | 04903 | inline value_t& operator[](const std::size_t& i) 04904 | { 04905 | return data_[i]; 04906 | } 04907 | 04908 | inline const value_t& operator[](const std::size_t& i) const 04909 | { 04910 | return data_[i]; 04911 | } 04912 | 04913 | inline const value_t* begin() const { return data_; } 04914 | inline value_t* begin() { return data_; } 04915 | 04916 | inline const value_t* end() const 04917 | { 04918 | return static_cast<value_t*>(data_ + ts_.size); 04919 | } 04920 | 04921 | inline value_t* end() 04922 | { 04923 | return static_cast<value_t*>(data_ + ts_.size); 04924 | } 04925 | 04926 | type_store_t& ts_; 04927 | value_t* data_; 04928 | }; 04929 | 04930 | typedef type_view<T> vector_view; 04931 | typedef type_view<char> string_view; 04932 | 04933 | struct scalar_view 04934 | { 04935 | typedef type_store<T> type_store_t; 04936 | typedef T value_t; 04937 | 04938 | explicit scalar_view(type_store_t& ts) 04939 | : v_(*reinterpret_cast<value_t*>(ts.data)) 04940 | {} 04941 | 04942 | explicit scalar_view(const type_store_t& ts) 04943 | : v_(*reinterpret_cast<value_t*>(const_cast<type_store_t&>(ts).data)) 04944 | {} 04945 | 04946 | inline value_t& operator() () 04947 | { 04948 | return v_; 04949 | } 04950 | 04951 | inline const value_t& operator() () const 04952 | { 04953 | return v_; 04954 | } 04955 | 04956 | inline operator value_t() const 04957 | { 04958 | return v_; 04959 | } 04960 | 04961 | inline operator value_t() 04962 | { 04963 | return v_; 04964 | } 04965 | 04966 | template <typename IntType> 04967 | inline bool to_int(IntType& i) const 04968 | { 04969 | if (!exprtk::details::numeric::is_integer(v_)) 04970 | return false; 04971 | 04972 | i = static_cast<IntType>(v_); 04973 | 04974 | return true; 04975 | } 04976 | 04977 | template <typename UIntType> 04978 | inline bool to_uint(UIntType& u) const 04979 | { 04980 | if (v_ < T(0)) 04981 | return false; 04982 | else if (!exprtk::details::numeric::is_integer(v_)) 04983 | return false; 04984 | 04985 | u = static_cast<UIntType>(v_); 04986 | 04987 | return true; 04988 | } 04989 | 04990 | T& v_; 04991 | }; 04992 | }; 04993 | 04994 | template <typename StringView> 04995 | inline std::string to_str(const StringView& view) 04996 | { 04997 | return std::string(view.begin(),view.size()); 04998 | } 04999 | 05000 | #ifndef exprtk_disable_return_statement 05001 | namespace details 05002 | { 05003 | template <typename T> class return_node; 05004 | template <typename T> class return_envelope_node; 05005 | } 05006 | #endif 05007 | 05008 | template <typename T> 05009 | class results_context 05010 | { 05011 | public: 05012 | 05013 | typedef type_store<T> type_store_t; 05014 | typedef typename type_store_t::scalar_view scalar_t; 05015 | typedef typename type_store_t::vector_view vector_t; 05016 | typedef typename type_store_t::string_view string_t; 05017 | 05018 | results_context() 05019 | : results_available_(false) 05020 | {} 05021 | 05022 | inline std::size_t count() const 05023 | { 05024 | if (results_available_) 05025 | return parameter_list_.size(); 05026 | else 05027 | return 0; 05028 | } 05029 | 05030 | inline type_store_t& operator[](const std::size_t& index) 05031 | { 05032 | return parameter_list_[index]; 05033 | } 05034 | 05035 | inline const type_store_t& operator[](const std::size_t& index) const 05036 | { 05037 | return parameter_list_[index]; 05038 | } 05039 | 05040 | inline bool get_scalar(const std::size_t& index, T& out) const 05041 | { 05042 | if ( 05043 | (index < parameter_list_.size()) && 05044 | (parameter_list_[index].type == type_store_t::e_scalar) 05045 | ) 05046 | { 05047 | const scalar_t scalar(parameter_list_[index]); 05048 | out = scalar(); 05049 | return true; 05050 | } 05051 | 05052 | return false; 05053 | } 05054 | 05055 | template <typename OutputIterator> 05056 | inline bool get_vector(const std::size_t& index, OutputIterator out_itr) const 05057 | { 05058 | if ( 05059 | (index < parameter_list_.size()) && 05060 | (parameter_list_[index].type == type_store_t::e_vector) 05061 | ) 05062 | { 05063 | const vector_t vector(parameter_list_[index]); 05064 | for (std::size_t i = 0; i < vector.size(); ++i) 05065 | { 05066 | *(out_itr++) = vector[i]; 05067 | } 05068 | 05069 | return true; 05070 | } 05071 | 05072 | return false; 05073 | } 05074 | 05075 | inline bool get_vector(const std::size_t& index, std::vector<T>& out) const 05076 | { 05077 | return get_vector(index,std::back_inserter(out)); 05078 | } 05079 | 05080 | inline bool get_string(const std::size_t& index, std::string& out) const 05081 | { 05082 | if ( 05083 | (index < parameter_list_.size()) && 05084 | (parameter_list_[index].type == type_store_t::e_string) 05085 | ) 05086 | { 05087 | const string_t str(parameter_list_[index]); 05088 | out.assign(str.begin(),str.size()); 05089 | return true; 05090 | } 05091 | 05092 | return false; 05093 | } 05094 | 05095 | private: 05096 | 05097 | inline void clear() 05098 | { 05099 | results_available_ = false; 05100 | } 05101 | 05102 | typedef std::vector<type_store_t> ts_list_t; 05103 | typedef typename type_store_t::parameter_list parameter_list_t; 05104 | 05105 | inline void assign(const parameter_list_t& pl) 05106 | { 05107 | parameter_list_ = pl.parameter_list_; 05108 | results_available_ = true; 05109 | } 05110 | 05111 | bool results_available_; 05112 | ts_list_t parameter_list_; 05113 | 05114 | #ifndef exprtk_disable_return_statement 05115 | friend class details::return_node<T>; 05116 | friend class details::return_envelope_node<T>; 05117 | #endif 05118 | }; 05119 | 05120 | namespace details 05121 | { 05122 | enum operator_type 05123 | { 05124 | e_default , e_null , e_add , e_sub , 05125 | e_mul , e_div , e_mod , e_pow , 05126 | e_atan2 , e_min , e_max , e_avg , 05127 | e_sum , e_prod , e_lt , e_lte , 05128 | e_eq , e_equal , e_ne , e_nequal , 05129 | e_gte , e_gt , e_and , e_nand , 05130 | e_or , e_nor , e_xor , e_xnor , 05131 | e_mand , e_mor , e_scand , e_scor , 05132 | e_shr , e_shl , e_abs , e_acos , 05133 | e_acosh , e_asin , e_asinh , e_atan , 05134 | e_atanh , e_ceil , e_cos , e_cosh , 05135 | e_exp , e_expm1 , e_floor , e_log , 05136 | e_log10 , e_log2 , e_log1p , e_logn , 05137 | e_neg , e_pos , e_round , e_roundn , 05138 | e_root , e_sqrt , e_sin , e_sinc , 05139 | e_sinh , e_sec , e_csc , e_tan , 05140 | e_tanh , e_cot , e_clamp , e_iclamp , 05141 | e_inrange , e_sgn , e_r2d , e_d2r , 05142 | e_d2g , e_g2d , e_hypot , e_notl , 05143 | e_erf , e_erfc , e_ncdf , e_frac , 05144 | e_trunc , e_assign , e_addass , e_subass , 05145 | e_mulass , e_divass , e_modass , e_in , 05146 | e_like , e_ilike , e_multi , e_smulti , 05147 | e_swap , 05148 | 05149 | // Do not add new functions/operators after this point. 05150 | e_sf00 = 1000, e_sf01 = 1001, e_sf02 = 1002, e_sf03 = 1003, 05151 | e_sf04 = 1004, e_sf05 = 1005, e_sf06 = 1006, e_sf07 = 1007, 05152 | e_sf08 = 1008, e_sf09 = 1009, e_sf10 = 1010, e_sf11 = 1011, 05153 | e_sf12 = 1012, e_sf13 = 1013, e_sf14 = 1014, e_sf15 = 1015, 05154 | e_sf16 = 1016, e_sf17 = 1017, e_sf18 = 1018, e_sf19 = 1019, 05155 | e_sf20 = 1020, e_sf21 = 1021, e_sf22 = 1022, e_sf23 = 1023, 05156 | e_sf24 = 1024, e_sf25 = 1025, e_sf26 = 1026, e_sf27 = 1027, 05157 | e_sf28 = 1028, e_sf29 = 1029, e_sf30 = 1030, e_sf31 = 1031, 05158 | e_sf32 = 1032, e_sf33 = 1033, e_sf34 = 1034, e_sf35 = 1035, 05159 | e_sf36 = 1036, e_sf37 = 1037, e_sf38 = 1038, e_sf39 = 1039, 05160 | e_sf40 = 1040, e_sf41 = 1041, e_sf42 = 1042, e_sf43 = 1043, 05161 | e_sf44 = 1044, e_sf45 = 1045, e_sf46 = 1046, e_sf47 = 1047, 05162 | e_sf48 = 1048, e_sf49 = 1049, e_sf50 = 1050, e_sf51 = 1051, 05163 | e_sf52 = 1052, e_sf53 = 1053, e_sf54 = 1054, e_sf55 = 1055, 05164 | e_sf56 = 1056, e_sf57 = 1057, e_sf58 = 1058, e_sf59 = 1059, 05165 | e_sf60 = 1060, e_sf61 = 1061, e_sf62 = 1062, e_sf63 = 1063, 05166 | e_sf64 = 1064, e_sf65 = 1065, e_sf66 = 1066, e_sf67 = 1067, 05167 | e_sf68 = 1068, e_sf69 = 1069, e_sf70 = 1070, e_sf71 = 1071, 05168 | e_sf72 = 1072, e_sf73 = 1073, e_sf74 = 1074, e_sf75 = 1075, 05169 | e_sf76 = 1076, e_sf77 = 1077, e_sf78 = 1078, e_sf79 = 1079, 05170 | e_sf80 = 1080, e_sf81 = 1081, e_sf82 = 1082, e_sf83 = 1083, 05171 | e_sf84 = 1084, e_sf85 = 1085, e_sf86 = 1086, e_sf87 = 1087, 05172 | e_sf88 = 1088, e_sf89 = 1089, e_sf90 = 1090, e_sf91 = 1091, 05173 | e_sf92 = 1092, e_sf93 = 1093, e_sf94 = 1094, e_sf95 = 1095, 05174 | e_sf96 = 1096, e_sf97 = 1097, e_sf98 = 1098, e_sf99 = 1099, 05175 | e_sffinal = 1100, 05176 | e_sf4ext00 = 2000, e_sf4ext01 = 2001, e_sf4ext02 = 2002, e_sf4ext03 = 2003, 05177 | e_sf4ext04 = 2004, e_sf4ext05 = 2005, e_sf4ext06 = 2006, e_sf4ext07 = 2007, 05178 | e_sf4ext08 = 2008, e_sf4ext09 = 2009, e_sf4ext10 = 2010, e_sf4ext11 = 2011, 05179 | e_sf4ext12 = 2012, e_sf4ext13 = 2013, e_sf4ext14 = 2014, e_sf4ext15 = 2015, 05180 | e_sf4ext16 = 2016, e_sf4ext17 = 2017, e_sf4ext18 = 2018, e_sf4ext19 = 2019, 05181 | e_sf4ext20 = 2020, e_sf4ext21 = 2021, e_sf4ext22 = 2022, e_sf4ext23 = 2023, 05182 | e_sf4ext24 = 2024, e_sf4ext25 = 2025, e_sf4ext26 = 2026, e_sf4ext27 = 2027, 05183 | e_sf4ext28 = 2028, e_sf4ext29 = 2029, e_sf4ext30 = 2030, e_sf4ext31 = 2031, 05184 | e_sf4ext32 = 2032, e_sf4ext33 = 2033, e_sf4ext34 = 2034, e_sf4ext35 = 2035, 05185 | e_sf4ext36 = 2036, e_sf4ext37 = 2037, e_sf4ext38 = 2038, e_sf4ext39 = 2039, 05186 | e_sf4ext40 = 2040, e_sf4ext41 = 2041, e_sf4ext42 = 2042, e_sf4ext43 = 2043, 05187 | e_sf4ext44 = 2044, e_sf4ext45 = 2045, e_sf4ext46 = 2046, e_sf4ext47 = 2047, 05188 | e_sf4ext48 = 2048, e_sf4ext49 = 2049, e_sf4ext50 = 2050, e_sf4ext51 = 2051, 05189 | e_sf4ext52 = 2052, e_sf4ext53 = 2053, e_sf4ext54 = 2054, e_sf4ext55 = 2055, 05190 | e_sf4ext56 = 2056, e_sf4ext57 = 2057, e_sf4ext58 = 2058, e_sf4ext59 = 2059, 05191 | e_sf4ext60 = 2060, e_sf4ext61 = 2061 05192 | }; 05193 | 05194 | inline std::string to_str(const operator_type opr) 05195 | { 05196 | switch (opr) 05197 | { 05198 | case e_add : return "+" ; 05199 | case e_sub : return "-" ; 05200 | case e_mul : return "*" ; 05201 | case e_div : return "/" ; 05202 | case e_mod : return "%" ; 05203 | case e_pow : return "^" ; 05204 | case e_assign : return ":=" ; 05205 | case e_addass : return "+=" ; 05206 | case e_subass : return "-=" ; 05207 | case e_mulass : return "*=" ; 05208 | case e_divass : return "/=" ; 05209 | case e_modass : return "%=" ; 05210 | case e_lt : return "<" ; 05211 | case e_lte : return "<=" ; 05212 | case e_eq : return "==" ; 05213 | case e_equal : return "=" ; 05214 | case e_ne : return "!=" ; 05215 | case e_nequal : return "<>" ; 05216 | case e_gte : return ">=" ; 05217 | case e_gt : return ">" ; 05218 | case e_and : return "and" ; 05219 | case e_or : return "or" ; 05220 | case e_xor : return "xor" ; 05221 | case e_nand : return "nand" 05222 | case e_nor : return "nor" ; 05223 | case e_xnor : return "xnor" 05224 | default : return "N/A" ; 05225 | } 05226 | } 05227 | 05228 | struct base_operation_t 05229 | { 05230 | base_operation_t(const operator_type t, const unsigned int& np) 05231 | : type(t) 05232 | , num_params(np) 05233 | {} 05234 | 05235 | operator_type type; 05236 | unsigned int num_params; 05237 | }; 05238 | 05239 | namespace loop_unroll 05240 | { 05241 | const unsigned int global_loop_batch_size = 05242 | #ifndef exprtk_disable_superscalar_unroll 05243 | 16; 05244 | #else 05245 | 4; 05246 | #endif 05247 | 05248 | struct details 05249 | { 05250 | explicit details(const std::size_t& vsize, 05251 | const unsigned int loop_batch_size = global_loop_batch_size) 05252 | : batch_size(loop_batch_size ) 05253 | , remainder (vsize % batch_size) 05254 | , upper_bound(static_cast<int>(vsize - (remainder ? loop_batch_size : 0))) 05255 | {} 05256 | 05257 | unsigned int batch_size; 05258 | int remainder; 05259 | int upper_bound; 05260 | }; 05261 | } 05262 | 05263 | #ifdef exprtk_enable_debugging 05264 | inline void dump_ptr(const std::string& s, const void* ptr, const std::size_t size = 0) 05265 | { 05266 | if (size) 05267 | exprtk_debug(("%s - addr: %p size: %d\n", 05268 | s.c_str(), 05269 | ptr, 05270 | static_cast<unsigned int>(size))); 05271 | else 05272 | exprtk_debug(("%s - addr: %p\n", s.c_str(), ptr)); 05273 | } 05274 | 05275 | template <typename T> 05276 | inline void dump_vector(const std::string& vec_name, const T* data, const std::size_t size) 05277 | { 05278 | printf("----- %s (%p) -----\n", 05279 | vec_name.c_str(), 05280 | static_cast<const void*>(data)); 05281 | printf("[ "); 05282 | for (std::size_t i = 0; i < size; ++i) 05283 | { 05284 | printf("%8.3f\t", data[i]); 05285 | } 05286 | printf(" ]\n"); 05287 | printf("---------------------\n"); 05288 | } 05289 | #else 05290 | inline void dump_ptr(const std::string&, const void*) {} 05291 | inline void dump_ptr(const std::string&, const void*, const std::size_t) {} 05292 | template <typename T> 05293 | inline void dump_vector(const std::string&, const T*, const std::size_t) {} 05294 | #endif 05295 | 05296 | template <typename T> 05297 | class vec_data_store 05298 | { 05299 | public: 05300 | 05301 | typedef vec_data_store<T> type; 05302 | typedef T* data_t; 05303 | 05304 | private: 05305 | 05306 | struct control_block 05307 | { 05308 | control_block() 05309 | : ref_count(1) 05310 | , size (0) 05311 | , data (0) 05312 | , destruct (true) 05313 | {} 05314 | 05315 | explicit control_block(const std::size_t& dsize) 05316 | : ref_count(1 ) 05317 | , size (dsize) 05318 | , data (0 ) 05319 | , destruct (true ) 05320 | { create_data(); } 05321 | 05322 | control_block(const std::size_t& dsize, data_t dptr, bool dstrct = false) 05323 | : ref_count(1 ) 05324 | , size (dsize ) 05325 | , data (dptr ) 05326 | , destruct (dstrct) 05327 | {} 05328 | 05329 | ~control_block() 05330 | { 05331 | if (data && destruct && (0 == ref_count)) 05332 | { 05333 | dump_ptr("~vec_data_store::control_block() data",data); 05334 | delete[] data; 05335 | data = reinterpret_cast<data_t>(0); 05336 | } 05337 | } 05338 | 05339 | static inline control_block* create(const std::size_t& dsize, data_t data_ptr = data_t(0), bool dstrct = false) 05340 | { 05341 | if (dsize) 05342 | { 05343 | if (0 == data_ptr) 05344 | return (new control_block(dsize)); 05345 | else 05346 | return (new control_block(dsize, data_ptr, dstrct)); 05347 | } 05348 | else 05349 | return (new control_block); 05350 | } 05351 | 05352 | static inline void destroy(control_block*& cntrl_blck) 05353 | { 05354 | if (cntrl_blck) 05355 | { 05356 | if ( 05357 | (0 != cntrl_blck->ref_count) && 05358 | (0 == --cntrl_blck->ref_count) 05359 | ) 05360 | { 05361 | delete cntrl_blck; 05362 | } 05363 | 05364 | cntrl_blck = 0; 05365 | } 05366 | } 05367 | 05368 | std::size_t ref_count; 05369 | std::size_t size; 05370 | data_t data; 05371 | bool destruct; 05372 | 05373 | private: 05374 | 05375 | control_block(const control_block&) exprtk_delete; 05376 | control_block& operator=(const control_block&) exprtk_delete; 05377 | 05378 | inline void create_data() 05379 | { 05380 | destruct = true; 05381 | data = new T[size]; 05382 | std::fill_n(data, size, T(0)); 05383 | dump_ptr("control_block::create_data() - data", data, size); 05384 | } 05385 | }; 05386 | 05387 | public: 05388 | 05389 | vec_data_store() 05390 | : control_block_(control_block::create(0)) 05391 | {} 05392 | 05393 | explicit vec_data_store(const std::size_t& size) 05394 | : control_block_(control_block::create(size,reinterpret_cast<data_t>(0),true)) 05395 | {} 05396 | 05397 | vec_data_store(const std::size_t& size, data_t data, bool dstrct = false) 05398 | : control_block_(control_block::create(size, data, dstrct)) 05399 | {} 05400 | 05401 | vec_data_store(const type& vds) 05402 | { 05403 | control_block_ = vds.control_block_; 05404 | control_block_->ref_count++; 05405 | } 05406 | 05407 | ~vec_data_store() 05408 | { 05409 | control_block::destroy(control_block_); 05410 | } 05411 | 05412 | type& operator=(const type& vds) 05413 | { 05414 | if (this != &vds) 05415 | { 05416 | const std::size_t final_size = min_size(control_block_, vds.control_block_); 05417 | 05418 | vds.control_block_->size = final_size; 05419 | control_block_->size = final_size; 05420 | 05421 | if (control_block_->destruct || (0 == control_block_->data)) 05422 | { 05423 | control_block::destroy(control_block_); 05424 | 05425 | control_block_ = vds.control_block_; 05426 | control_block_->ref_count++; 05427 | } 05428 | } 05429 | 05430 | return (*this); 05431 | } 05432 | 05433 | inline data_t data() 05434 | { 05435 | return control_block_->data; 05436 | } 05437 | 05438 | inline data_t data() const 05439 | { 05440 | return control_block_->data; 05441 | } 05442 | 05443 | inline std::size_t size() const 05444 | { 05445 | return control_block_->size; 05446 | } 05447 | 05448 | inline data_t& ref() 05449 | { 05450 | return control_block_->data; 05451 | } 05452 | 05453 | inline void dump() const 05454 | { 05455 | #ifdef exprtk_enable_debugging 05456 | exprtk_debug(("size: %d\taddress:%p\tdestruct:%c\n", 05457 | size(), 05458 | data(), 05459 | (control_block_->destruct ? 'T' : 'F'))); 05460 | 05461 | for (std::size_t i = 0; i < size(); ++i) 05462 | { 05463 | if (5 == i) 05464 | exprtk_debug(("\n")); 05465 | 05466 | exprtk_debug(("%15.10f ", data()[i])); 05467 | } 05468 | exprtk_debug(("\n")); 05469 | #endif 05470 | } 05471 | 05472 | static inline void match_sizes(type& vds0, type& vds1) 05473 | { 05474 | const std::size_t size = min_size(vds0.control_block_,vds1.control_block_); 05475 | vds0.control_block_->size = size; 05476 | vds1.control_block_->size = size; 05477 | } 05478 | 05479 | private: 05480 | 05481 | static inline std::size_t min_size(const control_block* cb0, const control_block* cb1) 05482 | { 05483 | const std::size_t size0 = cb0->size; 05484 | const std::size_t size1 = cb1->size; 05485 | 05486 | if (size0 && size1) 05487 | return std::min(size0,size1); 05488 | else 05489 | return (size0) ? size0 : size1; 05490 | } 05491 | 05492 | control_block* control_block_; 05493 | }; 05494 | 05495 | namespace numeric 05496 | { 05497 | namespace details 05498 | { 05499 | template <typename T> 05500 | inline T process_impl(const operator_type operation, const T arg) 05501 | { 05502 | switch (operation) 05503 | { 05504 | case e_abs : return numeric::abs (arg); 05505 | case e_acos : return numeric::acos (arg); 05506 | case e_acosh : return numeric::acosh(arg); 05507 | case e_asin : return numeric::asin (arg); 05508 | case e_asinh : return numeric::asinh(arg); 05509 | case e_atan : return numeric::atan (arg); 05510 | case e_atanh : return numeric::atanh(arg); 05511 | case e_ceil : return numeric::ceil (arg); 05512 | case e_cos : return numeric::cos (arg); 05513 | case e_cosh : return numeric::cosh (arg); 05514 | case e_exp : return numeric::exp (arg); 05515 | case e_expm1 : return numeric::expm1(arg); 05516 | case e_floor : return numeric::floor(arg); 05517 | case e_log : return numeric::log (arg); 05518 | case e_log10 : return numeric::log10(arg); 05519 | case e_log2 : return numeric::log2 (arg); 05520 | case e_log1p : return numeric::log1p(arg); 05521 | case e_neg : return numeric::neg (arg); 05522 | case e_pos : return numeric::pos (arg); 05523 | case e_round : return numeric::round(arg); 05524 | case e_sin : return numeric::sin (arg); 05525 | case e_sinc : return numeric::sinc (arg); 05526 | case e_sinh : return numeric::sinh (arg); 05527 | case e_sqrt : return numeric::sqrt (arg); 05528 | case e_tan : return numeric::tan (arg); 05529 | case e_tanh : return numeric::tanh (arg); 05530 | case e_cot : return numeric::cot (arg); 05531 | case e_sec : return numeric::sec (arg); 05532 | case e_csc : return numeric::csc (arg); 05533 | case e_r2d : return numeric::r2d (arg); 05534 | case e_d2r : return numeric::d2r (arg); 05535 | case e_d2g : return numeric::d2g (arg); 05536 | case e_g2d : return numeric::g2d (arg); 05537 | case e_notl : return numeric::notl (arg); 05538 | case e_sgn : return numeric::sgn (arg); 05539 | case e_erf : return numeric::erf (arg); 05540 | case e_erfc : return numeric::erfc (arg); 05541 | case e_ncdf : return numeric::ncdf (arg); 05542 | case e_frac : return numeric::frac (arg); 05543 | case e_trunc : return numeric::trunc(arg); 05544 | 05545 | default : exprtk_debug(("numeric::details::process_impl<T> - Invalid unary operation.\n")); 05546 | return std::numeric_limits<T>::quiet_NaN(); 05547 | } 05548 | } 05549 | 05550 | template <typename T> 05551 | inline T process_impl(const operator_type operation, const T arg0, const T arg1) 05552 | { 05553 | switch (operation) 05554 | { 05555 | case e_add : return (arg0 + arg1); 05556 | case e_sub : return (arg0 - arg1); 05557 | case e_mul : return (arg0 * arg1); 05558 | case e_div : return (arg0 / arg1); 05559 | case e_mod : return modulus<T>(arg0,arg1); 05560 | case e_pow : return pow<T>(arg0,arg1); 05561 | case e_atan2 : return atan2<T>(arg0,arg1); 05562 | case e_min : return std::min<T>(arg0,arg1); 05563 | case e_max : return std::max<T>(arg0,arg1); 05564 | case e_logn : return logn<T>(arg0,arg1); 05565 | case e_lt : return (arg0 < arg1) ? T(1) : T(0); 05566 | case e_lte : return (arg0 <= arg1) ? T(1) : T(0); 05567 | case e_eq : return std::equal_to<T>()(arg0,arg1) ? T(1) : T(0); 05568 | case e_ne : return std::not_equal_to<T>()(arg0,arg1) ? T(1) : T(0); 05569 | case e_gte : return (arg0 >= arg1) ? T(1) : T(0); 05570 | case e_gt : return (arg0 > arg1) ? T(1) : T(0); 05571 | case e_and : return and_opr <T>(arg0,arg1); 05572 | case e_nand : return nand_opr<T>(arg0,arg1); 05573 | case e_or : return or_opr <T>(arg0,arg1); 05574 | case e_nor : return nor_opr <T>(arg0,arg1); 05575 | case e_xor : return xor_opr <T>(arg0,arg1); 05576 | case e_xnor : return xnor_opr<T>(arg0,arg1); 05577 | case e_root : return root <T>(arg0,arg1); 05578 | case e_roundn : return roundn <T>(arg0,arg1); 05579 | case e_equal : return equal <T>(arg0,arg1); 05580 | case e_nequal : return nequal <T>(arg0,arg1); 05581 | case e_hypot : return hypot <T>(arg0,arg1); 05582 | case e_shr : return shr <T>(arg0,arg1); 05583 | case e_shl : return shl <T>(arg0,arg1); 05584 | 05585 | default : exprtk_debug(("numeric::details::process_impl<T> - Invalid binary operation.\n")); 05586 | return std::numeric_limits<T>::quiet_NaN(); 05587 | } 05588 | } 05589 | 05590 | template <typename T> 05591 | inline T process_impl(const operator_type operation, const T arg0, const T arg1, int_type_tag) 05592 | { 05593 | switch (operation) 05594 | { 05595 | case e_add : return (arg0 + arg1); 05596 | case e_sub : return (arg0 - arg1); 05597 | case e_mul : return (arg0 * arg1); 05598 | case e_div : return (arg0 / arg1); 05599 | case e_mod : return arg0 % arg1; 05600 | case e_pow : return pow<T>(arg0,arg1); 05601 | case e_min : return std::min<T>(arg0,arg1); 05602 | case e_max : return std::max<T>(arg0,arg1); 05603 | case e_logn : return logn<T>(arg0,arg1); 05604 | case e_lt : return (arg0 < arg1) ? T(1) : T(0); 05605 | case e_lte : return (arg0 <= arg1) ? T(1) : T(0); 05606 | case e_eq : return (arg0 == arg1) ? T(1) : T(0); 05607 | case e_ne : return (arg0 != arg1) ? T(1) : T(0); 05608 | case e_gte : return (arg0 >= arg1) ? T(1) : T(0); 05609 | case e_gt : return (arg0 > arg1) ? T(1) : T(0); 05610 | case e_and : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(1) : T(0); 05611 | case e_nand : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(0) : T(1); 05612 | case e_or : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(1) : T(0); 05613 | case e_nor : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(0) : T(1); 05614 | case e_xor : return arg0 ^ arg1; 05615 | case e_xnor : return !(arg0 ^ arg1); 05616 | case e_root : return root<T>(arg0,arg1); 05617 | case e_equal : return arg0 == arg1; 05618 | case e_nequal : return arg0 != arg1; 05619 | case e_hypot : return hypot<T>(arg0,arg1); 05620 | case e_shr : return arg0 >> arg1; 05621 | case e_shl : return arg0 << arg1; 05622 | 05623 | default : exprtk_debug(("numeric::details::process_impl<IntType> - Invalid binary operation.\n")); 05624 | return std::numeric_limits<T>::quiet_NaN(); 05625 | } 05626 | } 05627 | } 05628 | 05629 | template <typename T> 05630 | inline T process(const operator_type operation, const T arg) 05631 | { 05632 | return exprtk::details::numeric::details::process_impl(operation,arg); 05633 | } 05634 | 05635 | template <typename T> 05636 | inline T process(const operator_type operation, const T arg0, const T arg1) 05637 | { 05638 | return exprtk::details::numeric::details::process_impl(operation, arg0, arg1); 05639 | } 05640 | } 05641 | 05642 | template <typename Node> 05643 | struct node_collector_interface 05644 | { 05645 | typedef Node* node_ptr_t; 05646 | typedef Node** node_pp_t; 05647 | typedef std::vector<node_pp_t> noderef_list_t; 05648 | 05649 | virtual ~node_collector_interface() 05650 | {} 05651 | 05652 | virtual void collect_nodes(noderef_list_t&) 05653 | {} 05654 | }; 05655 | 05656 | template <typename Node> 05657 | struct node_depth_base; 05658 | 05659 | template <typename T> 05660 | class expression_node : public node_collector_interface<expression_node<T> > 05661 | , public node_depth_base<expression_node<T> > 05662 | { 05663 | public: 05664 | 05665 | enum node_type 05666 | { 05667 | e_none , e_null , e_constant , e_unary , 05668 | e_binary , e_binary_ext , e_trinary , e_quaternary , 05669 | e_vararg , e_conditional , e_while , e_repeat , 05670 | e_for , e_switch , e_mswitch , e_return , 05671 | e_retenv , e_variable , e_stringvar , e_stringconst , 05672 | e_stringvarrng , e_cstringvarrng , e_strgenrange , e_strconcat , 05673 | e_stringvarsize , e_strswap , e_stringsize , e_stringvararg , 05674 | e_function , e_vafunction , e_genfunction , e_strfunction , 05675 | e_strcondition , e_strccondition , e_add , e_sub , 05676 | e_mul , e_div , e_mod , e_pow , 05677 | e_lt , e_lte , e_gt , e_gte , 05678 | e_eq , e_ne , e_and , e_nand , 05679 | e_or , e_nor , e_xor , e_xnor , 05680 | e_in , e_like , e_ilike , e_inranges , 05681 | e_ipow , e_ipowinv , e_abs , e_acos , 05682 | e_acosh , e_asin , e_asinh , e_atan , 05683 | e_atanh , e_ceil , e_cos , e_cosh , 05684 | e_exp , e_expm1 , e_floor , e_log , 05685 | e_log10 , e_log2 , e_log1p , e_neg , 05686 | e_pos , e_round , e_sin , e_sinc , 05687 | e_sinh , e_sqrt , e_tan , e_tanh , 05688 | e_cot , e_sec , e_csc , e_r2d , 05689 | e_d2r , e_d2g , e_g2d , e_notl , 05690 | e_sgn , e_erf , e_erfc , e_ncdf , 05691 | e_frac , e_trunc , e_uvouv , e_vov , 05692 | e_cov , e_voc , e_vob , e_bov , 05693 | e_cob , e_boc , e_vovov , e_vovoc , 05694 | e_vocov , e_covov , e_covoc , e_vovovov , 05695 | e_vovovoc , e_vovocov , e_vocovov , e_covovov , 05696 | e_covocov , e_vocovoc , e_covovoc , e_vococov , 05697 | e_sf3ext , e_sf4ext , e_nulleq , e_strass , 05698 | e_vector , e_vecsize , e_vecelem , e_veccelem , 05699 | e_vecelemrtc , e_veccelemrtc , e_rbvecelem , e_rbvecelemrtc , 05700 | e_rbveccelem , e_rbveccelemrtc , e_vecinit , e_vecvalass , 05701 | e_vecvecass , e_vecopvalass , e_vecopvecass , e_vecfunc , 05702 | e_vecvecswap , e_vecvecineq , e_vecvalineq , e_valvecineq , 05703 | e_vecvecarith , e_vecvalarith , e_valvecarith , e_vecunaryop , 05704 | e_vecondition , e_break , e_continue , e_swap , 05705 | e_assert 05706 | }; 05707 | 05708 | typedef T value_type; 05709 | typedef expression_node<T>* expression_ptr; 05710 | typedef node_collector_interface<expression_node<T> > nci_t; 05711 | typedef typename nci_t::noderef_list_t noderef_list_t; 05712 | typedef node_depth_base<expression_node<T> > ndb_t; 05713 | 05714 | virtual ~expression_node() 05715 | {} 05716 | 05717 | inline virtual T value() const 05718 | { 05719 | return std::numeric_limits<T>::quiet_NaN(); 05720 | } 05721 | 05722 | inline virtual expression_node<T>* branch(const std::size_t& index = 0) const 05723 | { 05724 | return reinterpret_cast<expression_ptr>(index * 0); 05725 | } 05726 | 05727 | inline virtual node_type type() const 05728 | { 05729 | return e_none; 05730 | } 05731 | 05732 | inline virtual bool valid() const 05733 | { 05734 | return true; 05735 | } 05736 | }; // class expression_node 05737 | 05738 | template <typename T> 05739 | inline bool is_generally_string_node(const expression_node<T>* node); 05740 | 05741 | inline bool is_true(const double v) 05742 | { 05743 | return std::not_equal_to<double>()(0.0,v); 05744 | } 05745 | 05746 | inline bool is_true(const long double v) 05747 | { 05748 | return std::not_equal_to<long double>()(0.0L,v); 05749 | } 05750 | 05751 | inline bool is_true(const float v) 05752 | { 05753 | return std::not_equal_to<float>()(0.0f,v); 05754 | } 05755 | 05756 | template <typename T> 05757 | inline bool is_true(const expression_node<T>* node) 05758 | { 05759 | return std::not_equal_to<T>()(T(0),node->value()); 05760 | } 05761 | 05762 | template <typename T> 05763 | inline bool is_true(const std::pair<expression_node<T>*,bool>& node) 05764 | { 05765 | return std::not_equal_to<T>()(T(0),node.first->value()); 05766 | } 05767 | 05768 | template <typename T> 05769 | inline bool is_false(const expression_node<T>* node) 05770 | { 05771 | return std::equal_to<T>()(T(0),node->value()); 05772 | } 05773 | 05774 | template <typename T> 05775 | inline bool is_false(const std::pair<expression_node<T>*,bool>& node) 05776 | { 05777 | return std::equal_to<T>()(T(0),node.first->value()); 05778 | } 05779 | 05780 | template <typename T> 05781 | inline bool is_literal_node(const expression_node<T>* node) 05782 | { 05783 | return node && (details::expression_node<T>::e_constant == node->type()); 05784 | } 05785 | 05786 | template <typename T> 05787 | inline bool is_unary_node(const expression_node<T>* node) 05788 | { 05789 | return node && (details::expression_node<T>::e_unary == node->type()); 05790 | } 05791 | 05792 | template <typename T> 05793 | inline bool is_neg_unary_node(const expression_node<T>* node) 05794 | { 05795 | return node && (details::expression_node<T>::e_neg == node->type()); 05796 | } 05797 | 05798 | template <typename T> 05799 | inline bool is_binary_node(const expression_node<T>* node) 05800 | { 05801 | return node && (details::expression_node<T>::e_binary == node->type()); 05802 | } 05803 | 05804 | template <typename T> 05805 | inline bool is_variable_node(const expression_node<T>* node) 05806 | { 05807 | return node && (details::expression_node<T>::e_variable == node->type()); 05808 | } 05809 | 05810 | template <typename T> 05811 | inline bool is_ivariable_node(const expression_node<T>* node) 05812 | { 05813 | return node && 05814 | ( 05815 | details::expression_node<T>::e_variable == node->type() || 05816 | details::expression_node<T>::e_vecelem == node->type() || 05817 | details::expression_node<T>::e_veccelem == node->type() || 05818 | details::expression_node<T>::e_vecelemrtc == node->type() || 05819 | details::expression_node<T>::e_veccelemrtc == node->type() || 05820 | details::expression_node<T>::e_rbvecelem == node->type() || 05821 | details::expression_node<T>::e_rbveccelem == node->type() || 05822 | details::expression_node<T>::e_rbvecelemrtc == node->type() || 05823 | details::expression_node<T>::e_rbveccelemrtc == node->type() 05824 | ); 05825 | } 05826 | 05827 | template <typename T> 05828 | inline bool is_vector_elem_node(const expression_node<T>* node) 05829 | { 05830 | return node && (details::expression_node<T>::e_vecelem == node->type()); 05831 | } 05832 | 05833 | template <typename T> 05834 | inline bool is_vector_celem_node(const expression_node<T>* node) 05835 | { 05836 | return node && (details::expression_node<T>::e_veccelem == node->type()); 05837 | } 05838 | 05839 | template <typename T> 05840 | inline bool is_vector_elem_rtc_node(const expression_node<T>* node) 05841 | { 05842 | return node && (details::expression_node<T>::e_vecelemrtc == node->type()); 05843 | } 05844 | 05845 | template <typename T> 05846 | inline bool is_vector_celem_rtc_node(const expression_node<T>* node) 05847 | { 05848 | return node && (details::expression_node<T>::e_veccelemrtc == node->type()); 05849 | } 05850 | 05851 | template <typename T> 05852 | inline bool is_rebasevector_elem_node(const expression_node<T>* node) 05853 | { 05854 | return node && (details::expression_node<T>::e_rbvecelem == node->type()); 05855 | } 05856 | 05857 | template <typename T> 05858 | inline bool is_rebasevector_elem_rtc_node(const expression_node<T>* node) 05859 | { 05860 | return node && (details::expression_node<T>::e_rbvecelemrtc == node->type()); 05861 | } 05862 | 05863 | template <typename T> 05864 | inline bool is_rebasevector_celem_rtc_node(const expression_node<T>* node) 05865 | { 05866 | return node && (details::expression_node<T>::e_rbveccelemrtc == node->type()); 05867 | } 05868 | 05869 | template <typename T> 05870 | inline bool is_rebasevector_celem_node(const expression_node<T>* node) 05871 | { 05872 | return node && (details::expression_node<T>::e_rbveccelem == node->type()); 05873 | } 05874 | 05875 | template <typename T> 05876 | inline bool is_vector_node(const expression_node<T>* node) 05877 | { 05878 | return node && (details::expression_node<T>::e_vector == node->type()); 05879 | } 05880 | 05881 | template <typename T> 05882 | inline bool is_ivector_node(const expression_node<T>* node) 05883 | { 05884 | if (node) 05885 | { 05886 | switch (node->type()) 05887 | { 05888 | case details::expression_node<T>::e_vector : 05889 | case details::expression_node<T>::e_vecvalass : 05890 | case details::expression_node<T>::e_vecvecass : 05891 | case details::expression_node<T>::e_vecopvalass : 05892 | case details::expression_node<T>::e_vecopvecass : 05893 | case details::expression_node<T>::e_vecvecswap : 05894 | case details::expression_node<T>::e_vecvecarith : 05895 | case details::expression_node<T>::e_vecvalarith : 05896 | case details::expression_node<T>::e_valvecarith : 05897 | case details::expression_node<T>::e_vecunaryop : 05898 | case details::expression_node<T>::e_vecondition : return true; 05899 | default : return false; 05900 | } 05901 | } 05902 | else 05903 | return false; 05904 | } 05905 | 05906 | template <typename T> 05907 | inline bool amalgamated_vecop(const expression_node<T>* node) 05908 | { 05909 | if (node) 05910 | { 05911 | switch (node->type()) 05912 | { 05913 | case details::expression_node<T>::e_vecvecarith : 05914 | case details::expression_node<T>::e_vecvalarith : 05915 | case details::expression_node<T>::e_valvecarith : 05916 | case details::expression_node<T>::e_vecunaryop : return true; 05917 | default : return false; 05918 | } 05919 | } 05920 | else 05921 | return false; 05922 | } 05923 | 05924 | template <typename T> 05925 | inline bool is_constant_node(const expression_node<T>* node) 05926 | { 05927 | return node && 05928 | ( 05929 | details::expression_node<T>::e_constant == node->type() || 05930 | details::expression_node<T>::e_stringconst == node->type() 05931 | ); 05932 | } 05933 | 05934 | template <typename T> 05935 | inline bool is_null_node(const expression_node<T>* node) 05936 | { 05937 | return node && (details::expression_node<T>::e_null == node->type()); 05938 | } 05939 | 05940 | template <typename T> 05941 | inline bool is_break_node(const expression_node<T>* node) 05942 | { 05943 | return node && (details::expression_node<T>::e_break == node->type()); 05944 | } 05945 | 05946 | template <typename T> 05947 | inline bool is_continue_node(const expression_node<T>* node) 05948 | { 05949 | return node && (details::expression_node<T>::e_continue == node->type()); 05950 | } 05951 | 05952 | template <typename T> 05953 | inline bool is_swap_node(const expression_node<T>* node) 05954 | { 05955 | return node && (details::expression_node<T>::e_swap == node->type()); 05956 | } 05957 | 05958 | template <typename T> 05959 | inline bool is_function(const expression_node<T>* node) 05960 | { 05961 | return node && (details::expression_node<T>::e_function == node->type()); 05962 | } 05963 | 05964 | template <typename T> 05965 | inline bool is_vararg_node(const expression_node<T>* node) 05966 | { 05967 | return node && (details::expression_node<T>::e_vararg == node->type()); 05968 | } 05969 | 05970 | template <typename T> 05971 | inline bool is_return_node(const expression_node<T>* node) 05972 | { 05973 | return node && (details::expression_node<T>::e_return == node->type()); 05974 | } 05975 | 05976 | template <typename T> class unary_node; 05977 | 05978 | template <typename T> 05979 | inline bool is_negate_node(const expression_node<T>* node) 05980 | { 05981 | if (node && is_unary_node(node)) 05982 | { 05983 | return (details::e_neg == static_cast<const unary_node<T>*>(node)->operation()); 05984 | } 05985 | else 05986 | return false; 05987 | } 05988 | 05989 | template <typename T> 05990 | inline bool is_assert_node(const expression_node<T>* node) 05991 | { 05992 | return node && (details::expression_node<T>::e_assert == node->type()); 05993 | } 05994 | 05995 | template <typename T> 05996 | inline bool branch_deletable(const expression_node<T>* node) 05997 | { 05998 | return (0 != node) && 05999 | !is_variable_node(node) && 06000 | !is_string_node (node) ; 06001 | } 06002 | 06003 | template <std::size_t N, typename T> 06004 | inline bool all_nodes_valid(expression_node<T>* const (&b)[N]) 06005 | { 06006 | for (std::size_t i = 0; i < N; ++i) 06007 | { 06008 | if (0 == b[i]) return false; 06009 | } 06010 | 06011 | return true; 06012 | } 06013 | 06014 | template <typename T, 06015 | typename Allocator, 06016 | template <typename, typename> class Sequence> 06017 | inline bool all_nodes_valid(const Sequence<expression_node<T>*,Allocator>& b) 06018 | { 06019 | for (std::size_t i = 0; i < b.size(); ++i) 06020 | { 06021 | if (0 == b[i]) return false; 06022 | } 06023 | 06024 | return true; 06025 | } 06026 | 06027 | template <std::size_t N, typename T> 06028 | inline bool all_nodes_variables(expression_node<T>* const (&b)[N]) 06029 | { 06030 | for (std::size_t i = 0; i < N; ++i) 06031 | { 06032 | if (0 == b[i]) 06033 | return false; 06034 | else if (!is_variable_node(b[i])) 06035 | return false; 06036 | } 06037 | 06038 | return true; 06039 | } 06040 | 06041 | template <typename T, 06042 | typename Allocator, 06043 | template <typename, typename> class Sequence> 06044 | inline bool all_nodes_variables(const Sequence<expression_node<T>*,Allocator>& b) 06045 | { 06046 | for (std::size_t i = 0; i < b.size(); ++i) 06047 | { 06048 | if (0 == b[i]) 06049 | return false; 06050 | else if (!is_variable_node(b[i])) 06051 | return false; 06052 | } 06053 | 06054 | return true; 06055 | } 06056 | 06057 | template <typename Node> 06058 | class node_collection_destructor 06059 | { 06060 | public: 06061 | 06062 | typedef node_collector_interface<Node> nci_t; 06063 | 06064 | typedef typename nci_t::node_ptr_t node_ptr_t; 06065 | typedef typename nci_t::node_pp_t node_pp_t; 06066 | typedef typename nci_t::noderef_list_t noderef_list_t; 06067 | 06068 | static void delete_nodes(node_ptr_t& root) 06069 | { 06070 | std::vector<node_pp_t> node_delete_list; 06071 | node_delete_list.reserve(1000); 06072 | 06073 | collect_nodes(root, node_delete_list); 06074 | 06075 | for (std::size_t i = 0; i < node_delete_list.size(); ++i) 06076 | { 06077 | node_ptr_t& node = *node_delete_list[i]; 06078 | exprtk_debug(("ncd::delete_nodes() - deleting: %p\n", reinterpret_cast<void*>(node))); 06079 | delete node; 06080 | node = reinterpret_cast<node_ptr_t>(0); 06081 | } 06082 | } 06083 | 06084 | private: 06085 | 06086 | static void collect_nodes(node_ptr_t& root, noderef_list_t& node_delete_list) 06087 | { 06088 | std::deque<node_ptr_t> node_list; 06089 | node_list.push_back(root); 06090 | node_delete_list.push_back(&root); 06091 | 06092 | noderef_list_t child_node_delete_list; 06093 | child_node_delete_list.reserve(1000); 06094 | 06095 | while (!node_list.empty()) 06096 | { 06097 | node_list.front()->collect_nodes(child_node_delete_list); 06098 | 06099 | if (!child_node_delete_list.empty()) 06100 | { 06101 | for (std::size_t i = 0; i < child_node_delete_list.size(); ++i) 06102 | { 06103 | node_pp_t& node = child_node_delete_list[i]; 06104 | 06105 | if (0 == (*node)) 06106 | { 06107 | exprtk_debug(("ncd::collect_nodes() - null node encountered.\n")); 06108 | } 06109 | 06110 | node_list.push_back(*node); 06111 | } 06112 | 06113 | node_delete_list.insert( 06114 | node_delete_list.end(), 06115 | child_node_delete_list.begin(), child_node_delete_list.end()); 06116 | 06117 | child_node_delete_list.clear(); 06118 | } 06119 | 06120 | node_list.pop_front(); 06121 | } 06122 | 06123 | std::reverse(node_delete_list.begin(), node_delete_list.end()); 06124 | } 06125 | }; 06126 | 06127 | template <typename NodeAllocator, typename T, std::size_t N> 06128 | inline void free_all_nodes(NodeAllocator& node_allocator, expression_node<T>* (&b)[N]) 06129 | { 06130 | for (std::size_t i = 0; i < N; ++i) 06131 | { 06132 | free_node(node_allocator,b[i]); 06133 | } 06134 | } 06135 | 06136 | template <typename NodeAllocator, 06137 | typename T, 06138 | typename Allocator, 06139 | template <typename, typename> class Sequence> 06140 | inline void free_all_nodes(NodeAllocator& node_allocator, Sequence<expression_node<T>*,Allocator>& b) 06141 | { 06142 | for (std::size_t i = 0; i < b.size(); ++i) 06143 | { 06144 | free_node(node_allocator,b[i]); 06145 | } 06146 | 06147 | b.clear(); 06148 | } 06149 | 06150 | template <typename NodeAllocator, typename T> 06151 | inline void free_node(NodeAllocator&, expression_node<T>*& node) 06152 | { 06153 | if ((0 == node) || is_variable_node(node) || is_string_node(node)) 06154 | { 06155 | return; 06156 | } 06157 | 06158 | node_collection_destructor<expression_node<T> > 06159 | ::delete_nodes(node); 06160 | } 06161 | 06162 | template <typename T> 06163 | inline void destroy_node(expression_node<T>*& node) 06164 | { 06165 | if (0 != node) 06166 | { 06167 | node_collection_destructor<expression_node<T> > 06168 | ::delete_nodes(node); 06169 | } 06170 | } 06171 | 06172 | template <typename Node> 06173 | struct node_depth_base 06174 | { 06175 | typedef Node* node_ptr_t; 06176 | typedef std::pair<node_ptr_t,bool> nb_pair_t; 06177 | 06178 | node_depth_base() 06179 | : depth_set(false) 06180 | , depth(0) 06181 | {} 06182 | 06183 | virtual ~node_depth_base() 06184 | {} 06185 | 06186 | virtual std::size_t node_depth() const { return 1; } 06187 | 06188 | std::size_t compute_node_depth(const Node* const& node) const 06189 | { 06190 | if (!depth_set) 06191 | { 06192 | depth = 1 + (node ? node->node_depth() : 0); 06193 | depth_set = true; 06194 | } 06195 | 06196 | return depth; 06197 | } 06198 | 06199 | std::size_t compute_node_depth(const nb_pair_t& branch) const 06200 | { 06201 | if (!depth_set) 06202 | { 06203 | depth = 1 + (branch.first ? branch.first->node_depth() : 0); 06204 | depth_set = true; 06205 | } 06206 | 06207 | return depth; 06208 | } 06209 | 06210 | template <std::size_t N> 06211 | std::size_t compute_node_depth(const nb_pair_t (&branch)[N]) const 06212 | { 06213 | if (!depth_set) 06214 | { 06215 | depth = 0; 06216 | 06217 | for (std::size_t i = 0; i < N; ++i) 06218 | { 06219 | if (branch[i].first) 06220 | { 06221 | depth = std::max(depth,branch[i].first->node_depth()); 06222 | } 06223 | } 06224 | 06225 | depth += 1; 06226 | depth_set = true; 06227 | } 06228 | 06229 | return depth; 06230 | } 06231 | 06232 | template <typename BranchType> 06233 | std::size_t max_node_depth(const BranchType& n0, const BranchType& n1) const 06234 | { 06235 | return std::max(compute_node_depth(n0), compute_node_depth(n1)); 06236 | } 06237 | 06238 | template <typename BranchType> 06239 | std::size_t max_node_depth(const BranchType& n0, const BranchType& n1, const BranchType& n2) const 06240 | { 06241 | return std::max(compute_node_depth(n0), 06242 | std::max(compute_node_depth(n1), compute_node_depth(n2))); 06243 | } 06244 | 06245 | template <typename BranchType> 06246 | std::size_t max_node_depth(const BranchType& n0, const BranchType& n1, 06247 | const BranchType& n2, const BranchType& n3) const 06248 | { 06249 | return std::max( 06250 | std::max(compute_node_depth(n0), compute_node_depth(n1)), 06251 | std::max(compute_node_depth(n2), compute_node_depth(n3))); 06252 | } 06253 | 06254 | template <typename BranchType> 06255 | std::size_t compute_node_depth(const BranchType& n0, const BranchType& n1) const 06256 | { 06257 | if (!depth_set) 06258 | { 06259 | depth = 1 + max_node_depth(n0, n1); 06260 | depth_set = true; 06261 | } 06262 | 06263 | return depth; 06264 | } 06265 | 06266 | template <typename BranchType> 06267 | std::size_t compute_node_depth(const BranchType& n0, const BranchType& n1, 06268 | const BranchType& n2) const 06269 | { 06270 | if (!depth_set) 06271 | { 06272 | depth = 1 + max_node_depth(n0, n1, n2); 06273 | depth_set = true; 06274 | } 06275 | 06276 | return depth; 06277 | } 06278 | 06279 | template <typename BranchType> 06280 | std::size_t compute_node_depth(const BranchType& n0, const BranchType& n1, 06281 | const BranchType& n2, const BranchType& n3) const 06282 | { 06283 | if (!depth_set) 06284 | { 06285 | depth = 1 + max_node_depth(n0, n1, n2, n3); 06286 | depth_set = true; 06287 | } 06288 | 06289 | return depth; 06290 | } 06291 | 06292 | template <typename Allocator, 06293 | template <typename, typename> class Sequence> 06294 | std::size_t compute_node_depth(const Sequence<node_ptr_t, Allocator>& branch_list) const 06295 | { 06296 | if (!depth_set) 06297 | { 06298 | for (std::size_t i = 0; i < branch_list.size(); ++i) 06299 | { 06300 | if (branch_list[i]) 06301 | { 06302 | depth = std::max(depth, compute_node_depth(branch_list[i])); 06303 | } 06304 | } 06305 | 06306 | depth_set = true; 06307 | } 06308 | 06309 | return depth; 06310 | } 06311 | 06312 | template <typename Allocator, 06313 | template <typename, typename> class Sequence> 06314 | std::size_t compute_node_depth(const Sequence<nb_pair_t,Allocator>& branch_list) const 06315 | { 06316 | if (!depth_set) 06317 | { 06318 | for (std::size_t i = 0; i < branch_list.size(); ++i) 06319 | { 06320 | if (branch_list[i].first) 06321 | { 06322 | depth = std::max(depth, compute_node_depth(branch_list[i].first)); 06323 | } 06324 | } 06325 | 06326 | depth_set = true; 06327 | } 06328 | 06329 | return depth; 06330 | } 06331 | 06332 | mutable bool depth_set; 06333 | mutable std::size_t depth; 06334 | 06335 | template <typename NodeSequence> 06336 | void collect(node_ptr_t const& node, 06337 | const bool deletable, 06338 | NodeSequence& delete_node_list) const 06339 | { 06340 | if ((0 != node) && deletable) 06341 | { 06342 | delete_node_list.push_back(const_cast<node_ptr_t*>(&node)); 06343 | } 06344 | } 06345 | 06346 | template <typename NodeSequence> 06347 | void collect(const nb_pair_t& branch, 06348 | NodeSequence& delete_node_list) const 06349 | { 06350 | collect(branch.first, branch.second, delete_node_list); 06351 | } 06352 | 06353 | template <typename NodeSequence> 06354 | void collect(Node*& node, 06355 | NodeSequence& delete_node_list) const 06356 | { 06357 | collect(node, branch_deletable(node), delete_node_list); 06358 | } 06359 | 06360 | template <std::size_t N, typename NodeSequence> 06361 | void collect(const nb_pair_t(&branch)[N], 06362 | NodeSequence& delete_node_list) const 06363 | { 06364 | for (std::size_t i = 0; i < N; ++i) 06365 | { 06366 | collect(branch[i].first, branch[i].second, delete_node_list); 06367 | } 06368 | } 06369 | 06370 | template <typename Allocator, 06371 | template <typename, typename> class Sequence, 06372 | typename NodeSequence> 06373 | void collect(const Sequence<nb_pair_t, Allocator>& branch, 06374 | NodeSequence& delete_node_list) const 06375 | { 06376 | for (std::size_t i = 0; i < branch.size(); ++i) 06377 | { 06378 | collect(branch[i].first, branch[i].second, delete_node_list); 06379 | } 06380 | } 06381 | 06382 | template <typename Allocator, 06383 | template <typename, typename> class Sequence, 06384 | typename NodeSequence> 06385 | void collect(const Sequence<node_ptr_t, Allocator>& branch_list, 06386 | NodeSequence& delete_node_list) const 06387 | { 06388 | for (std::size_t i = 0; i < branch_list.size(); ++i) 06389 | { 06390 | collect(branch_list[i], branch_deletable(branch_list[i]), delete_node_list); 06391 | } 06392 | } 06393 | 06394 | template <typename Boolean, 06395 | typename AllocatorT, 06396 | typename AllocatorB, 06397 | template <typename, typename> class Sequence, 06398 | typename NodeSequence> 06399 | void collect(const Sequence<node_ptr_t, AllocatorT>& branch_list, 06400 | const Sequence<Boolean, AllocatorB>& branch_deletable_list, 06401 | NodeSequence& delete_node_list) const 06402 | { 06403 | for (std::size_t i = 0; i < branch_list.size(); ++i) 06404 | { 06405 | collect(branch_list[i], branch_deletable_list[i], delete_node_list); 06406 | } 06407 | } 06408 | }; 06409 | 06410 | template <typename Type> 06411 | class vector_holder 06412 | { 06413 | private: 06414 | 06415 | typedef Type value_type; 06416 | typedef value_type* value_ptr; 06417 | typedef const value_ptr const_value_ptr; 06418 | typedef vector_holder<Type> vector_holder_t; 06419 | 06420 | class vector_holder_base 06421 | { 06422 | public: 06423 | 06424 | virtual ~vector_holder_base() 06425 | {} 06426 | 06427 | inline value_ptr operator[](const std::size_t& index) const 06428 | { 06429 | return value_at(index); 06430 | } 06431 | 06432 | inline std::size_t size() const 06433 | { 06434 | return vector_size(); 06435 | } 06436 | 06437 | inline std::size_t base_size() const 06438 | { 06439 | return vector_base_size(); 06440 | } 06441 | 06442 | inline value_ptr data() const 06443 | { 06444 | return value_at(0); 06445 | } 06446 | 06447 | virtual inline bool rebaseable() const 06448 | { 06449 | return false; 06450 | } 06451 | 06452 | virtual void set_ref(value_ptr*) 06453 | {} 06454 | 06455 | virtual void remove_ref(value_ptr*) 06456 | {} 06457 | 06458 | virtual void set_size_ref(std::size_t*) 06459 | {} 06460 | 06461 | virtual void remove_size_ref(std::size_t*) 06462 | {} 06463 | 06464 | virtual vector_view<Type>* rebaseable_instance() 06465 | { 06466 | return reinterpret_cast<vector_view<Type>*>(0); 06467 | } 06468 | 06469 | protected: 06470 | 06471 | virtual value_ptr value_at(const std::size_t&) const = 0; 06472 | virtual std::size_t vector_size() const = 0; 06473 | virtual std::size_t vector_base_size() const = 0; 06474 | }; 06475 | 06476 | class array_vector_impl exprtk_final : public vector_holder_base 06477 | { 06478 | public: 06479 | 06480 | array_vector_impl(const Type* vec, const std::size_t& vec_size) 06481 | : vec_(vec) 06482 | , size_(vec_size) 06483 | {} 06484 | 06485 | protected: 06486 | 06487 | value_ptr value_at(const std::size_t& index) const exprtk_override 06488 | { 06489 | assert(index < size_); 06490 | return const_cast<const_value_ptr>(vec_ + index); 06491 | } 06492 | 06493 | std::size_t vector_size() const exprtk_override 06494 | { 06495 | return size_; 06496 | } 06497 | 06498 | std::size_t vector_base_size() const exprtk_override 06499 | { 06500 | return vector_size(); 06501 | } 06502 | 06503 | private: 06504 | 06505 | array_vector_impl(const array_vector_impl&) exprtk_delete; 06506 | array_vector_impl& operator=(const array_vector_impl&) exprtk_delete; 06507 | 06508 | const Type* vec_; 06509 | const std::size_t size_; 06510 | }; 06511 | 06512 | template <typename Allocator, 06513 | template <typename, typename> class Sequence> 06514 | class sequence_vector_impl exprtk_final : public vector_holder_base 06515 | { 06516 | public: 06517 | 06518 | typedef Sequence<Type,Allocator> sequence_t; 06519 | 06520 | explicit sequence_vector_impl(sequence_t& seq) 06521 | : sequence_(seq) 06522 | {} 06523 | 06524 | protected: 06525 | 06526 | value_ptr value_at(const std::size_t& index) const exprtk_override 06527 | { 06528 | assert(index < sequence_.size()); 06529 | return (&sequence_[index]); 06530 | } 06531 | 06532 | std::size_t vector_size() const exprtk_override 06533 | { 06534 | return sequence_.size(); 06535 | } 06536 | 06537 | std::size_t vector_base_size() const exprtk_override 06538 | { 06539 | return vector_size(); 06540 | } 06541 | 06542 | private: 06543 | 06544 | sequence_vector_impl(const sequence_vector_impl&) exprtk_delete; 06545 | sequence_vector_impl& operator=(const sequence_vector_impl&) exprtk_delete; 06546 | 06547 | sequence_t& sequence_; 06548 | }; 06549 | 06550 | class vector_view_impl exprtk_final : public vector_holder_base 06551 | { 06552 | public: 06553 | 06554 | typedef exprtk::vector_view<Type> vector_view_t; 06555 | 06556 | explicit vector_view_impl(vector_view_t& vec_view) 06557 | : vec_view_(vec_view) 06558 | { 06559 | assert(vec_view_.size() > 0); 06560 | } 06561 | 06562 | void set_ref(value_ptr* ref) exprtk_override 06563 | { 06564 | vec_view_.set_ref(ref); 06565 | } 06566 | 06567 | void remove_ref(value_ptr* ref) exprtk_override 06568 | { 06569 | vec_view_.remove_ref(ref); 06570 | } 06571 | 06572 | bool rebaseable() const exprtk_override 06573 | { 06574 | return true; 06575 | } 06576 | 06577 | vector_view<Type>* rebaseable_instance() exprtk_override 06578 | { 06579 | return &vec_view_; 06580 | } 06581 | 06582 | protected: 06583 | 06584 | value_ptr value_at(const std::size_t& index) const exprtk_override 06585 | { 06586 | assert(index < vec_view_.size()); 06587 | return (&vec_view_[index]); 06588 | } 06589 | 06590 | std::size_t vector_size() const exprtk_override 06591 | { 06592 | return vec_view_.size(); 06593 | } 06594 | 06595 | std::size_t vector_base_size() const exprtk_override 06596 | { 06597 | return vec_view_.base_size(); 06598 | } 06599 | 06600 | private: 06601 | 06602 | vector_view_impl(const vector_view_impl&) exprtk_delete; 06603 | vector_view_impl& operator=(const vector_view_impl&) exprtk_delete; 06604 | 06605 | vector_view_t& vec_view_; 06606 | }; 06607 | 06608 | class resizable_vector_impl exprtk_final : public vector_holder_base 06609 | { 06610 | public: 06611 | 06612 | resizable_vector_impl(vector_holder& vec_view_holder, 06613 | const Type* vec, 06614 | const std::size_t& vec_size) 06615 | : vec_(vec) 06616 | , size_(vec_size) 06617 | , vec_view_holder_(*vec_view_holder.rebaseable_instance()) 06618 | { 06619 | assert(vec_view_holder.rebaseable_instance()); 06620 | assert(size_ <= vector_base_size()); 06621 | } 06622 | 06623 | virtual ~resizable_vector_impl() exprtk_override 06624 | {} 06625 | 06626 | protected: 06627 | 06628 | value_ptr value_at(const std::size_t& index) const exprtk_override 06629 | { 06630 | assert(index < vector_size()); 06631 | return const_cast<const_value_ptr>(vec_ + index); 06632 | } 06633 | 06634 | std::size_t vector_size() const exprtk_override 06635 | { 06636 | return vec_view_holder_.size(); 06637 | } 06638 | 06639 | std::size_t vector_base_size() const exprtk_override 06640 | { 06641 | return vec_view_holder_.base_size(); 06642 | } 06643 | 06644 | bool rebaseable() const exprtk_override 06645 | { 06646 | return true; 06647 | } 06648 | 06649 | virtual vector_view<Type>* rebaseable_instance() exprtk_override 06650 | { 06651 | return &vec_view_holder_; 06652 | } 06653 | 06654 | private: 06655 | 06656 | resizable_vector_impl(const resizable_vector_impl&) exprtk_delete; 06657 | resizable_vector_impl& operator=(const resizable_vector_impl&) exprtk_delete; 06658 | 06659 | const Type* vec_; 06660 | const std::size_t size_; 06661 | vector_view<Type>& vec_view_holder_; 06662 | }; 06663 | 06664 | public: 06665 | 06666 | typedef typename details::vec_data_store<Type> vds_t; 06667 | 06668 | vector_holder(Type* vec, const std::size_t& vec_size) 06669 | : vector_holder_base_(new(buffer)array_vector_impl(vec,vec_size)) 06670 | {} 06671 | 06672 | explicit vector_holder(const vds_t& vds) 06673 | : vector_holder_base_(new(buffer)array_vector_impl(vds.data(),vds.size())) 06674 | {} 06675 | 06676 | template <typename Allocator> 06677 | explicit vector_holder(std::vector<Type,Allocator>& vec) 06678 | : vector_holder_base_(new(buffer)sequence_vector_impl<Allocator,std::vector>(vec)) 06679 | {} 06680 | 06681 | explicit vector_holder(exprtk::vector_view<Type>& vec) 06682 | : vector_holder_base_(new(buffer)vector_view_impl(vec)) 06683 | {} 06684 | 06685 | explicit vector_holder(vector_holder_t& vec_holder, const vds_t& vds) 06686 | : vector_holder_base_(new(buffer)resizable_vector_impl(vec_holder, vds.data(), vds.size())) 06687 | {} 06688 | 06689 | inline value_ptr operator[](const std::size_t& index) const 06690 | { 06691 | return (*vector_holder_base_)[index]; 06692 | } 06693 | 06694 | inline std::size_t size() const 06695 | { 06696 | return vector_holder_base_->size(); 06697 | } 06698 | 06699 | inline std::size_t base_size() const 06700 | { 06701 | return vector_holder_base_->base_size(); 06702 | } 06703 | 06704 | inline value_ptr data() const 06705 | { 06706 | return vector_holder_base_->data(); 06707 | } 06708 | 06709 | void set_ref(value_ptr* ref) 06710 | { 06711 | if (rebaseable()) 06712 | { 06713 | vector_holder_base_->set_ref(ref); 06714 | } 06715 | } 06716 | 06717 | void set_size_ref(std::size_t* ref) 06718 | { 06719 | if (rebaseable()) 06720 | { 06721 | vector_holder_base_->set_size_ref(ref); 06722 | } 06723 | } 06724 | 06725 | void remove_ref(value_ptr* ref) 06726 | { 06727 | if (rebaseable()) 06728 | { 06729 | vector_holder_base_->remove_ref(ref); 06730 | } 06731 | } 06732 | 06733 | void remove_size_ref(std::size_t* ref) 06734 | { 06735 | if (rebaseable()) 06736 | { 06737 | vector_holder_base_->remove_size_ref(ref); 06738 | } 06739 | } 06740 | 06741 | bool rebaseable() const 06742 | { 06743 | return vector_holder_base_->rebaseable(); 06744 | } 06745 | 06746 | vector_view<Type>* rebaseable_instance() 06747 | { 06748 | return vector_holder_base_->rebaseable_instance(); 06749 | } 06750 | 06751 | private: 06752 | 06753 | vector_holder(const vector_holder<Type>&) exprtk_delete; 06754 | vector_holder<Type>& operator=(const vector_holder<Type>&) exprtk_delete; 06755 | 06756 | mutable vector_holder_base* vector_holder_base_; 06757 | uchar_t buffer[64]; 06758 | }; 06759 | 06760 | template <typename T> 06761 | class null_node exprtk_final : public expression_node<T> 06762 | { 06763 | public: 06764 | 06765 | inline T value() const exprtk_override 06766 | { 06767 | return std::numeric_limits<T>::quiet_NaN(); 06768 | } 06769 | 06770 | inline typename expression_node<T>::node_type type() const exprtk_override 06771 | { 06772 | return expression_node<T>::e_null; 06773 | } 06774 | }; 06775 | 06776 | template <typename T, std::size_t N> 06777 | inline void construct_branch_pair(std::pair<expression_node<T>*,bool> (&branch)[N], 06778 | expression_node<T>* b, 06779 | const std::size_t& index) 06780 | { 06781 | if (b && (index < N)) 06782 | { 06783 | branch[index] = std::make_pair(b,branch_deletable(b)); 06784 | } 06785 | } 06786 | 06787 | template <typename T> 06788 | inline void construct_branch_pair(std::pair<expression_node<T>*,bool>& branch, expression_node<T>* b) 06789 | { 06790 | if (b) 06791 | { 06792 | branch = std::make_pair(b,branch_deletable(b)); 06793 | } 06794 | } 06795 | 06796 | template <std::size_t N, typename T> 06797 | inline void init_branches(std::pair<expression_node<T>*,bool> (&branch)[N], 06798 | expression_node<T>* b0, 06799 | expression_node<T>* b1 = reinterpret_cast<expression_node<T>*>(0), 06800 | expression_node<T>* b2 = reinterpret_cast<expression_node<T>*>(0), 06801 | expression_node<T>* b3 = reinterpret_cast<expression_node<T>*>(0), 06802 | expression_node<T>* b4 = reinterpret_cast<expression_node<T>*>(0), 06803 | expression_node<T>* b5 = reinterpret_cast<expression_node<T>*>(0), 06804 | expression_node<T>* b6 = reinterpret_cast<expression_node<T>*>(0), 06805 | expression_node<T>* b7 = reinterpret_cast<expression_node<T>*>(0), 06806 | expression_node<T>* b8 = reinterpret_cast<expression_node<T>*>(0), 06807 | expression_node<T>* b9 = reinterpret_cast<expression_node<T>*>(0)) 06808 | { 06809 | construct_branch_pair(branch, b0, 0); 06810 | construct_branch_pair(branch, b1, 1); 06811 | construct_branch_pair(branch, b2, 2); 06812 | construct_branch_pair(branch, b3, 3); 06813 | construct_branch_pair(branch, b4, 4); 06814 | construct_branch_pair(branch, b5, 5); 06815 | construct_branch_pair(branch, b6, 6); 06816 | construct_branch_pair(branch, b7, 7); 06817 | construct_branch_pair(branch, b8, 8); 06818 | construct_branch_pair(branch, b9, 9); 06819 | } 06820 | 06821 | template <typename T> 06822 | class null_eq_node exprtk_final : public expression_node<T> 06823 | { 06824 | public: 06825 | 06826 | typedef expression_node<T>* expression_ptr; 06827 | typedef std::pair<expression_ptr,bool> branch_t; 06828 | 06829 | explicit null_eq_node(expression_ptr branch, const bool equality = true) 06830 | : equality_(equality) 06831 | { 06832 | construct_branch_pair(branch_, branch); 06833 | assert(valid()); 06834 | } 06835 | 06836 | inline T value() const exprtk_override 06837 | { 06838 | const T v = branch_.first->value(); 06839 | const bool result = details::numeric::is_nan(v); 06840 | 06841 | if (result) 06842 | return equality_ ? T(1) : T(0); 06843 | else 06844 | return equality_ ? T(0) : T(1); 06845 | } 06846 | 06847 | inline typename expression_node<T>::node_type type() const exprtk_override 06848 | { 06849 | return expression_node<T>::e_nulleq; 06850 | } 06851 | 06852 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 06853 | { 06854 | return branch_.first; 06855 | } 06856 | 06857 | inline bool valid() const exprtk_override 06858 | { 06859 | return branch_.first; 06860 | } 06861 | 06862 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 06863 | { 06864 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 06865 | } 06866 | 06867 | std::size_t node_depth() const exprtk_override 06868 | { 06869 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 06870 | } 06871 | 06872 | private: 06873 | 06874 | bool equality_; 06875 | branch_t branch_; 06876 | }; 06877 | 06878 | template <typename T> 06879 | class literal_node exprtk_final : public expression_node<T> 06880 | { 06881 | public: 06882 | 06883 | explicit literal_node(const T& v) 06884 | : value_(v) 06885 | {} 06886 | 06887 | inline T value() const exprtk_override 06888 | { 06889 | return value_; 06890 | } 06891 | 06892 | inline typename expression_node<T>::node_type type() const exprtk_override 06893 | { 06894 | return expression_node<T>::e_constant; 06895 | } 06896 | 06897 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 06898 | { 06899 | return reinterpret_cast<expression_node<T>*>(0); 06900 | } 06901 | 06902 | private: 06903 | 06904 | literal_node(const literal_node<T>&) exprtk_delete; 06905 | literal_node<T>& operator=(const literal_node<T>&) exprtk_delete; 06906 | 06907 | const T value_; 06908 | }; 06909 | 06910 | template <typename T> 06911 | struct range_pack; 06912 | 06913 | template <typename T> 06914 | struct range_data_type; 06915 | 06916 | template <typename T> 06917 | class range_interface 06918 | { 06919 | public: 06920 | 06921 | typedef range_pack<T> range_t; 06922 | 06923 | virtual ~range_interface() 06924 | {} 06925 | 06926 | virtual range_t& range_ref() = 0; 06927 | 06928 | virtual const range_t& range_ref() const = 0; 06929 | }; 06930 | 06931 | #ifndef exprtk_disable_string_capabilities 06932 | template <typename T> 06933 | class string_base_node 06934 | { 06935 | public: 06936 | 06937 | typedef range_data_type<T> range_data_type_t; 06938 | 06939 | virtual ~string_base_node() 06940 | {} 06941 | 06942 | virtual std::string str () const = 0; 06943 | 06944 | virtual char_cptr base() const = 0; 06945 | 06946 | virtual std::size_t size() const = 0; 06947 | }; 06948 | 06949 | template <typename T> 06950 | class string_literal_node exprtk_final 06951 | : public expression_node <T> 06952 | , public string_base_node<T> 06953 | , public range_interface <T> 06954 | { 06955 | public: 06956 | 06957 | typedef range_pack<T> range_t; 06958 | 06959 | explicit string_literal_node(const std::string& v) 06960 | : value_(v) 06961 | { 06962 | rp_.n0_c = std::make_pair<bool,std::size_t>(true, 0); 06963 | rp_.n1_c = std::make_pair<bool,std::size_t>(true, v.size()); 06964 | rp_.cache.first = rp_.n0_c.second; 06965 | rp_.cache.second = rp_.n1_c.second; 06966 | } 06967 | 06968 | inline T value() const exprtk_override 06969 | { 06970 | return std::numeric_limits<T>::quiet_NaN(); 06971 | } 06972 | 06973 | inline typename expression_node<T>::node_type type() const exprtk_override 06974 | { 06975 | return expression_node<T>::e_stringconst; 06976 | } 06977 | 06978 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 06979 | { 06980 | return reinterpret_cast<expression_node<T>*>(0); 06981 | } 06982 | 06983 | std::string str() const exprtk_override 06984 | { 06985 | return value_; 06986 | } 06987 | 06988 | char_cptr base() const exprtk_override 06989 | { 06990 | return value_.data(); 06991 | } 06992 | 06993 | std::size_t size() const exprtk_override 06994 | { 06995 | return value_.size(); 06996 | } 06997 | 06998 | range_t& range_ref() exprtk_override 06999 | { 07000 | return rp_; 07001 | } 07002 | 07003 | const range_t& range_ref() const exprtk_override 07004 | { 07005 | return rp_; 07006 | } 07007 | 07008 | private: 07009 | 07010 | string_literal_node(const string_literal_node<T>&) exprtk_delete; 07011 | string_literal_node<T>& operator=(const string_literal_node<T>&) exprtk_delete; 07012 | 07013 | const std::string value_; 07014 | range_t rp_; 07015 | }; 07016 | #endif 07017 | 07018 | template <typename T> 07019 | class unary_node : public expression_node<T> 07020 | { 07021 | public: 07022 | 07023 | typedef expression_node<T>* expression_ptr; 07024 | typedef std::pair<expression_ptr,bool> branch_t; 07025 | 07026 | unary_node(const operator_type& opr, expression_ptr branch) 07027 | : operation_(opr) 07028 | { 07029 | construct_branch_pair(branch_,branch); 07030 | assert(valid()); 07031 | } 07032 | 07033 | inline T value() const exprtk_override 07034 | { 07035 | return numeric::process<T> 07036 | (operation_,branch_.first->value()); 07037 | } 07038 | 07039 | inline typename expression_node<T>::node_type type() const exprtk_override 07040 | { 07041 | return expression_node<T>::e_unary; 07042 | } 07043 | 07044 | inline operator_type operation() 07045 | { 07046 | return operation_; 07047 | } 07048 | 07049 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 07050 | { 07051 | return branch_.first; 07052 | } 07053 | 07054 | inline bool valid() const exprtk_override 07055 | { 07056 | return branch_.first && branch_.first->valid(); 07057 | } 07058 | 07059 | inline void release() 07060 | { 07061 | branch_.second = false; 07062 | } 07063 | 07064 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07065 | { 07066 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 07067 | } 07068 | 07069 | std::size_t node_depth() const exprtk_final 07070 | { 07071 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 07072 | } 07073 | 07074 | private: 07075 | 07076 | operator_type operation_; 07077 | branch_t branch_; 07078 | }; 07079 | 07080 | template <typename T> 07081 | class binary_node : public expression_node<T> 07082 | { 07083 | public: 07084 | 07085 | typedef expression_node<T>* expression_ptr; 07086 | typedef std::pair<expression_ptr,bool> branch_t; 07087 | 07088 | binary_node(const operator_type& opr, 07089 | expression_ptr branch0, 07090 | expression_ptr branch1) 07091 | : operation_(opr) 07092 | { 07093 | init_branches<2>(branch_, branch0, branch1); 07094 | assert(valid()); 07095 | } 07096 | 07097 | inline T value() const exprtk_override 07098 | { 07099 | return numeric::process<T> 07100 | ( 07101 | operation_, 07102 | branch_[0].first->value(), 07103 | branch_[1].first->value() 07104 | ); 07105 | } 07106 | 07107 | inline typename expression_node<T>::node_type type() const exprtk_override 07108 | { 07109 | return expression_node<T>::e_binary; 07110 | } 07111 | 07112 | inline operator_type operation() 07113 | { 07114 | return operation_; 07115 | } 07116 | 07117 | inline expression_node<T>* branch(const std::size_t& index = 0) const exprtk_override 07118 | { 07119 | assert(index < 2); 07120 | return branch_[index].first; 07121 | } 07122 | 07123 | inline bool valid() const exprtk_override 07124 | { 07125 | return 07126 | branch_[0].first && branch_[0].first->valid() && 07127 | branch_[1].first && branch_[1].first->valid() ; 07128 | } 07129 | 07130 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07131 | { 07132 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 07133 | } 07134 | 07135 | std::size_t node_depth() const exprtk_final 07136 | { 07137 | return expression_node<T>::ndb_t::template compute_node_depth<2>(branch_); 07138 | } 07139 | 07140 | private: 07141 | 07142 | operator_type operation_; 07143 | branch_t branch_[2]; 07144 | }; 07145 | 07146 | template <typename T, typename Operation> 07147 | class binary_ext_node exprtk_final : public expression_node<T> 07148 | { 07149 | public: 07150 | 07151 | typedef expression_node<T>* expression_ptr; 07152 | typedef std::pair<expression_ptr,bool> branch_t; 07153 | 07154 | binary_ext_node(expression_ptr branch0, expression_ptr branch1) 07155 | { 07156 | init_branches<2>(branch_, branch0, branch1); 07157 | assert(valid()); 07158 | } 07159 | 07160 | inline T value() const exprtk_override 07161 | { 07162 | const T arg0 = branch_[0].first->value(); 07163 | const T arg1 = branch_[1].first->value(); 07164 | return Operation::process(arg0,arg1); 07165 | } 07166 | 07167 | inline typename expression_node<T>::node_type type() const exprtk_override 07168 | { 07169 | return expression_node<T>::e_binary_ext; 07170 | } 07171 | 07172 | inline operator_type operation() 07173 | { 07174 | return Operation::operation(); 07175 | } 07176 | 07177 | inline expression_node<T>* branch(const std::size_t& index = 0) const exprtk_override 07178 | { 07179 | assert(index < 2); 07180 | return branch_[index].first; 07181 | } 07182 | 07183 | inline bool valid() const exprtk_override 07184 | { 07185 | return 07186 | branch_[0].first && branch_[0].first->valid() && 07187 | branch_[1].first && branch_[1].first->valid() ; 07188 | } 07189 | 07190 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07191 | { 07192 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 07193 | } 07194 | 07195 | std::size_t node_depth() const exprtk_override 07196 | { 07197 | return expression_node<T>::ndb_t::template compute_node_depth<2>(branch_); 07198 | } 07199 | 07200 | protected: 07201 | 07202 | branch_t branch_[2]; 07203 | }; 07204 | 07205 | template <typename T> 07206 | class trinary_node : public expression_node<T> 07207 | { 07208 | public: 07209 | 07210 | typedef expression_node<T>* expression_ptr; 07211 | typedef std::pair<expression_ptr,bool> branch_t; 07212 | 07213 | trinary_node(const operator_type& opr, 07214 | expression_ptr branch0, 07215 | expression_ptr branch1, 07216 | expression_ptr branch2) 07217 | : operation_(opr) 07218 | { 07219 | init_branches<3>(branch_, branch0, branch1, branch2); 07220 | assert(valid()); 07221 | } 07222 | 07223 | inline T value() const exprtk_override 07224 | { 07225 | const T arg0 = branch_[0].first->value(); 07226 | const T arg1 = branch_[1].first->value(); 07227 | const T arg2 = branch_[2].first->value(); 07228 | 07229 | switch (operation_) 07230 | { 07231 | case e_inrange : return (arg1 < arg0) ? T(0) : ((arg1 > arg2) ? T(0) : T(1)); 07232 | 07233 | case e_clamp : return (arg1 < arg0) ? arg0 : (arg1 > arg2 ? arg2 : arg1); 07234 | 07235 | case e_iclamp : if ((arg1 <= arg0) || (arg1 >= arg2)) 07236 | return arg1; 07237 | else 07238 | return ((T(2) * arg1 <= (arg2 + arg0)) ? arg0 : arg2); 07239 | 07240 | default : exprtk_debug(("trinary_node::value() - Error: Invalid operation\n")); 07241 | return std::numeric_limits<T>::quiet_NaN(); 07242 | } 07243 | } 07244 | 07245 | inline typename expression_node<T>::node_type type() const exprtk_override 07246 | { 07247 | return expression_node<T>::e_trinary; 07248 | } 07249 | 07250 | inline bool valid() const exprtk_override 07251 | { 07252 | return 07253 | branch_[0].first && branch_[0].first->valid() && 07254 | branch_[1].first && branch_[1].first->valid() && 07255 | branch_[2].first && branch_[2].first->valid() ; 07256 | } 07257 | 07258 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07259 | { 07260 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 07261 | } 07262 | 07263 | std::size_t node_depth() const exprtk_override exprtk_final 07264 | { 07265 | return expression_node<T>::ndb_t::template compute_node_depth<3>(branch_); 07266 | } 07267 | 07268 | protected: 07269 | 07270 | operator_type operation_; 07271 | branch_t branch_[3]; 07272 | }; 07273 | 07274 | template <typename T> 07275 | class quaternary_node : public expression_node<T> 07276 | { 07277 | public: 07278 | 07279 | typedef expression_node<T>* expression_ptr; 07280 | typedef std::pair<expression_ptr,bool> branch_t; 07281 | 07282 | quaternary_node(const operator_type& opr, 07283 | expression_ptr branch0, 07284 | expression_ptr branch1, 07285 | expression_ptr branch2, 07286 | expression_ptr branch3) 07287 | : operation_(opr) 07288 | { 07289 | init_branches<4>(branch_, branch0, branch1, branch2, branch3); 07290 | } 07291 | 07292 | inline T value() const exprtk_override 07293 | { 07294 | return std::numeric_limits<T>::quiet_NaN(); 07295 | } 07296 | 07297 | inline typename expression_node<T>::node_type type() const exprtk_override 07298 | { 07299 | return expression_node<T>::e_quaternary; 07300 | } 07301 | 07302 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07303 | { 07304 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 07305 | } 07306 | 07307 | std::size_t node_depth() const exprtk_override exprtk_final 07308 | { 07309 | return expression_node<T>::ndb_t::template compute_node_depth<4>(branch_); 07310 | } 07311 | 07312 | inline bool valid() const exprtk_override 07313 | { 07314 | return 07315 | branch_[0].first && branch_[0].first->valid() && 07316 | branch_[1].first && branch_[1].first->valid() && 07317 | branch_[2].first && branch_[2].first->valid() && 07318 | branch_[3].first && branch_[3].first->valid() ; 07319 | } 07320 | 07321 | protected: 07322 | 07323 | operator_type operation_; 07324 | branch_t branch_[4]; 07325 | }; 07326 | 07327 | template <typename T> 07328 | class conditional_node exprtk_final : public expression_node<T> 07329 | { 07330 | public: 07331 | 07332 | typedef expression_node<T>* expression_ptr; 07333 | typedef std::pair<expression_ptr,bool> branch_t; 07334 | 07335 | conditional_node(expression_ptr condition, 07336 | expression_ptr consequent, 07337 | expression_ptr alternative) 07338 | { 07339 | construct_branch_pair(condition_ , condition ); 07340 | construct_branch_pair(consequent_ , consequent ); 07341 | construct_branch_pair(alternative_, alternative); 07342 | assert(valid()); 07343 | } 07344 | 07345 | inline T value() const exprtk_override 07346 | { 07347 | if (is_true(condition_)) 07348 | return consequent_.first->value(); 07349 | else 07350 | return alternative_.first->value(); 07351 | } 07352 | 07353 | inline typename expression_node<T>::node_type type() const exprtk_override 07354 | { 07355 | return expression_node<T>::e_conditional; 07356 | } 07357 | 07358 | inline bool valid() const exprtk_override 07359 | { 07360 | return 07361 | condition_ .first && condition_ .first->valid() && 07362 | consequent_ .first && consequent_ .first->valid() && 07363 | alternative_.first && alternative_.first->valid() ; 07364 | } 07365 | 07366 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07367 | { 07368 | expression_node<T>::ndb_t::collect(condition_ , node_delete_list); 07369 | expression_node<T>::ndb_t::collect(consequent_ , node_delete_list); 07370 | expression_node<T>::ndb_t::collect(alternative_ , node_delete_list); 07371 | } 07372 | 07373 | std::size_t node_depth() const exprtk_override 07374 | { 07375 | return expression_node<T>::ndb_t::compute_node_depth 07376 | (condition_, consequent_, alternative_); 07377 | } 07378 | 07379 | private: 07380 | 07381 | branch_t condition_; 07382 | branch_t consequent_; 07383 | branch_t alternative_; 07384 | }; 07385 | 07386 | template <typename T> 07387 | class cons_conditional_node exprtk_final : public expression_node<T> 07388 | { 07389 | public: 07390 | 07391 | // Consequent only conditional statement node 07392 | typedef expression_node<T>* expression_ptr; 07393 | typedef std::pair<expression_ptr,bool> branch_t; 07394 | 07395 | cons_conditional_node(expression_ptr condition, 07396 | expression_ptr consequent) 07397 | { 07398 | construct_branch_pair(condition_ , condition ); 07399 | construct_branch_pair(consequent_, consequent); 07400 | assert(valid()); 07401 | } 07402 | 07403 | inline T value() const exprtk_override 07404 | { 07405 | if (is_true(condition_)) 07406 | return consequent_.first->value(); 07407 | else 07408 | return std::numeric_limits<T>::quiet_NaN(); 07409 | } 07410 | 07411 | inline typename expression_node<T>::node_type type() const exprtk_override 07412 | { 07413 | return expression_node<T>::e_conditional; 07414 | } 07415 | 07416 | inline bool valid() const exprtk_override 07417 | { 07418 | return 07419 | condition_ .first && condition_ .first->valid() && 07420 | consequent_.first && consequent_.first->valid() ; 07421 | } 07422 | 07423 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07424 | { 07425 | expression_node<T>::ndb_t::collect(condition_ , node_delete_list); 07426 | expression_node<T>::ndb_t::collect(consequent_ , node_delete_list); 07427 | } 07428 | 07429 | std::size_t node_depth() const exprtk_override 07430 | { 07431 | return expression_node<T>::ndb_t:: 07432 | compute_node_depth(condition_, consequent_); 07433 | } 07434 | 07435 | private: 07436 | 07437 | branch_t condition_; 07438 | branch_t consequent_; 07439 | }; 07440 | 07441 | #ifndef exprtk_disable_break_continue 07442 | template <typename T> 07443 | class break_exception 07444 | { 07445 | public: 07446 | 07447 | explicit break_exception(const T& v) 07448 | : value(v) 07449 | {} 07450 | 07451 | T value; 07452 | }; 07453 | 07454 | class continue_exception {}; 07455 | 07456 | template <typename T> 07457 | class break_node exprtk_final : public expression_node<T> 07458 | { 07459 | public: 07460 | 07461 | typedef expression_node<T>* expression_ptr; 07462 | typedef std::pair<expression_ptr,bool> branch_t; 07463 | 07464 | explicit break_node(expression_ptr ret = expression_ptr(0)) 07465 | { 07466 | construct_branch_pair(return_, ret); 07467 | } 07468 | 07469 | inline T value() const exprtk_override 07470 | { 07471 | const T result = return_.first ? 07472 | return_.first->value() : 07473 | std::numeric_limits<T>::quiet_NaN(); 07474 | 07475 | throw break_exception<T>(result); 07476 | 07477 | #if !defined(_MSC_VER) && !defined(__NVCOMPILER) 07478 | return std::numeric_limits<T>::quiet_NaN(); 07479 | #endif 07480 | } 07481 | 07482 | inline typename expression_node<T>::node_type type() const exprtk_override 07483 | { 07484 | return expression_node<T>::e_break; 07485 | } 07486 | 07487 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07488 | { 07489 | expression_node<T>::ndb_t::collect(return_, node_delete_list); 07490 | } 07491 | 07492 | std::size_t node_depth() const exprtk_override 07493 | { 07494 | return expression_node<T>::ndb_t::compute_node_depth(return_); 07495 | } 07496 | 07497 | private: 07498 | 07499 | branch_t return_; 07500 | }; 07501 | 07502 | template <typename T> 07503 | class continue_node exprtk_final : public expression_node<T> 07504 | { 07505 | public: 07506 | 07507 | inline T value() const exprtk_override 07508 | { 07509 | throw continue_exception(); 07510 | #if !defined(_MSC_VER) && !defined(__NVCOMPILER) 07511 | return std::numeric_limits<T>::quiet_NaN(); 07512 | #endif 07513 | } 07514 | 07515 | inline typename expression_node<T>::node_type type() const exprtk_override 07516 | { 07517 | return expression_node<T>::e_break; 07518 | } 07519 | }; 07520 | #endif 07521 | 07522 | struct loop_runtime_checker 07523 | { 07524 | loop_runtime_checker(loop_runtime_check_ptr loop_runtime_check, 07525 | loop_runtime_check::loop_types lp_typ = loop_runtime_check::e_invalid) 07526 | : iteration_count_(0) 07527 | , loop_runtime_check_(loop_runtime_check) 07528 | , max_loop_iterations_(loop_runtime_check_->max_loop_iterations) 07529 | , loop_type_(lp_typ) 07530 | { 07531 | assert(loop_runtime_check_); 07532 | } 07533 | 07534 | inline void reset(const _uint64_t initial_value = 0) const 07535 | { 07536 | iteration_count_ = initial_value; 07537 | } 07538 | 07539 | inline bool check() const 07540 | { 07541 | assert(loop_runtime_check_); 07542 | 07543 | if ( 07544 | (++iteration_count_ <= max_loop_iterations_) && 07545 | loop_runtime_check_->check() 07546 | ) 07547 | { 07548 | return true; 07549 | } 07550 | 07551 | loop_runtime_check::violation_context ctxt; 07552 | ctxt.loop = loop_type_; 07553 | ctxt.violation = loop_runtime_check::e_iteration_count; 07554 | 07555 | loop_runtime_check_->handle_runtime_violation(ctxt); 07556 | 07557 | return false; 07558 | } 07559 | 07560 | bool valid() const 07561 | { 07562 | return 0 != loop_runtime_check_; 07563 | } 07564 | 07565 | mutable _uint64_t iteration_count_; 07566 | mutable loop_runtime_check_ptr loop_runtime_check_; 07567 | const details::_uint64_t& max_loop_iterations_; 07568 | loop_runtime_check::loop_types loop_type_; 07569 | }; 07570 | 07571 | template <typename T> 07572 | class while_loop_node : public expression_node<T> 07573 | { 07574 | public: 07575 | 07576 | typedef expression_node<T>* expression_ptr; 07577 | typedef std::pair<expression_ptr,bool> branch_t; 07578 | 07579 | while_loop_node(expression_ptr condition, 07580 | expression_ptr loop_body) 07581 | { 07582 | construct_branch_pair(condition_, condition); 07583 | construct_branch_pair(loop_body_, loop_body); 07584 | assert(valid()); 07585 | } 07586 | 07587 | inline T value() const exprtk_override 07588 | { 07589 | T result = T(0); 07590 | 07591 | while (is_true(condition_)) 07592 | { 07593 | result = loop_body_.first->value(); 07594 | } 07595 | 07596 | return result; 07597 | } 07598 | 07599 | inline typename expression_node<T>::node_type type() const exprtk_override 07600 | { 07601 | return expression_node<T>::e_while; 07602 | } 07603 | 07604 | inline bool valid() const exprtk_override 07605 | { 07606 | return 07607 | condition_.first && condition_.first->valid() && 07608 | loop_body_.first && loop_body_.first->valid() ; 07609 | } 07610 | 07611 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07612 | { 07613 | expression_node<T>::ndb_t::collect(condition_ , node_delete_list); 07614 | expression_node<T>::ndb_t::collect(loop_body_ , node_delete_list); 07615 | } 07616 | 07617 | std::size_t node_depth() const exprtk_override 07618 | { 07619 | return expression_node<T>::ndb_t::compute_node_depth(condition_, loop_body_); 07620 | } 07621 | 07622 | protected: 07623 | 07624 | branch_t condition_; 07625 | branch_t loop_body_; 07626 | }; 07627 | 07628 | template <typename T> 07629 | class while_loop_rtc_node exprtk_final 07630 | : public while_loop_node<T> 07631 | , public loop_runtime_checker 07632 | { 07633 | public: 07634 | 07635 | typedef while_loop_node<T> parent_t; 07636 | typedef expression_node<T>* expression_ptr; 07637 | 07638 | while_loop_rtc_node(expression_ptr condition, 07639 | expression_ptr loop_body, 07640 | loop_runtime_check_ptr loop_rt_chk) 07641 | : parent_t(condition, loop_body) 07642 | , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_while_loop) 07643 | { 07644 | assert(valid()); 07645 | } 07646 | 07647 | inline T value() const exprtk_override 07648 | { 07649 | 07650 | T result = T(0); 07651 | 07652 | loop_runtime_checker::reset(); 07653 | 07654 | while (is_true(parent_t::condition_) && loop_runtime_checker::check()) 07655 | { 07656 | result = parent_t::loop_body_.first->value(); 07657 | } 07658 | 07659 | return result; 07660 | } 07661 | 07662 | using parent_t::valid; 07663 | 07664 | bool valid() const exprtk_override exprtk_final 07665 | { 07666 | return parent_t::valid() && 07667 | loop_runtime_checker::valid(); 07668 | } 07669 | }; 07670 | 07671 | template <typename T> 07672 | class repeat_until_loop_node : public expression_node<T> 07673 | { 07674 | public: 07675 | 07676 | typedef expression_node<T>* expression_ptr; 07677 | typedef std::pair<expression_ptr,bool> branch_t; 07678 | 07679 | repeat_until_loop_node(expression_ptr condition, 07680 | expression_ptr loop_body) 07681 | { 07682 | construct_branch_pair(condition_, condition); 07683 | construct_branch_pair(loop_body_, loop_body); 07684 | assert(valid()); 07685 | } 07686 | 07687 | inline T value() const exprtk_override 07688 | { 07689 | T result = T(0); 07690 | 07691 | do 07692 | { 07693 | result = loop_body_.first->value(); 07694 | } 07695 | while (is_false(condition_.first)); 07696 | 07697 | return result; 07698 | } 07699 | 07700 | inline typename expression_node<T>::node_type type() const exprtk_override 07701 | { 07702 | return expression_node<T>::e_repeat; 07703 | } 07704 | 07705 | inline bool valid() const exprtk_override 07706 | { 07707 | return 07708 | condition_.first && condition_.first->valid() && 07709 | loop_body_.first && loop_body_.first->valid() ; 07710 | } 07711 | 07712 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07713 | { 07714 | expression_node<T>::ndb_t::collect(condition_ , node_delete_list); 07715 | expression_node<T>::ndb_t::collect(loop_body_ , node_delete_list); 07716 | } 07717 | 07718 | std::size_t node_depth() const exprtk_override 07719 | { 07720 | return expression_node<T>::ndb_t::compute_node_depth(condition_, loop_body_); 07721 | } 07722 | 07723 | protected: 07724 | 07725 | branch_t condition_; 07726 | branch_t loop_body_; 07727 | }; 07728 | 07729 | template <typename T> 07730 | class repeat_until_loop_rtc_node exprtk_final 07731 | : public repeat_until_loop_node<T> 07732 | , public loop_runtime_checker 07733 | { 07734 | public: 07735 | 07736 | typedef repeat_until_loop_node<T> parent_t; 07737 | typedef expression_node<T>* expression_ptr; 07738 | 07739 | repeat_until_loop_rtc_node(expression_ptr condition, 07740 | expression_ptr loop_body, 07741 | loop_runtime_check_ptr loop_rt_chk) 07742 | : parent_t(condition, loop_body) 07743 | , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_repeat_until_loop) 07744 | { 07745 | assert(valid()); 07746 | } 07747 | 07748 | inline T value() const exprtk_override 07749 | { 07750 | T result = T(0); 07751 | 07752 | loop_runtime_checker::reset(1); 07753 | 07754 | do 07755 | { 07756 | result = parent_t::loop_body_.first->value(); 07757 | } 07758 | while (is_false(parent_t::condition_.first) && loop_runtime_checker::check()); 07759 | 07760 | return result; 07761 | } 07762 | 07763 | using parent_t::valid; 07764 | 07765 | inline bool valid() const exprtk_override exprtk_final 07766 | { 07767 | return parent_t::valid() && 07768 | loop_runtime_checker::valid(); 07769 | } 07770 | }; 07771 | 07772 | template <typename T> 07773 | class for_loop_node : public expression_node<T> 07774 | { 07775 | public: 07776 | 07777 | typedef expression_node<T>* expression_ptr; 07778 | typedef std::pair<expression_ptr,bool> branch_t; 07779 | 07780 | for_loop_node(expression_ptr initialiser, 07781 | expression_ptr condition, 07782 | expression_ptr incrementor, 07783 | expression_ptr loop_body) 07784 | { 07785 | construct_branch_pair(initialiser_, initialiser); 07786 | construct_branch_pair(condition_ , condition ); 07787 | construct_branch_pair(incrementor_, incrementor); 07788 | construct_branch_pair(loop_body_ , loop_body ); 07789 | assert(valid()); 07790 | } 07791 | 07792 | inline T value() const exprtk_override 07793 | { 07794 | T result = T(0); 07795 | 07796 | if (initialiser_.first) 07797 | initialiser_.first->value(); 07798 | 07799 | if (incrementor_.first) 07800 | { 07801 | while (is_true(condition_)) 07802 | { 07803 | result = loop_body_.first->value(); 07804 | incrementor_.first->value(); 07805 | } 07806 | } 07807 | else 07808 | { 07809 | while (is_true(condition_)) 07810 | { 07811 | result = loop_body_.first->value(); 07812 | } 07813 | } 07814 | 07815 | return result; 07816 | } 07817 | 07818 | inline typename expression_node<T>::node_type type() const exprtk_override 07819 | { 07820 | return expression_node<T>::e_for; 07821 | } 07822 | 07823 | inline bool valid() const exprtk_override 07824 | { 07825 | return condition_.first && loop_body_.first; 07826 | } 07827 | 07828 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07829 | { 07830 | expression_node<T>::ndb_t::collect(initialiser_ , node_delete_list); 07831 | expression_node<T>::ndb_t::collect(condition_ , node_delete_list); 07832 | expression_node<T>::ndb_t::collect(incrementor_ , node_delete_list); 07833 | expression_node<T>::ndb_t::collect(loop_body_ , node_delete_list); 07834 | } 07835 | 07836 | std::size_t node_depth() const exprtk_override 07837 | { 07838 | return expression_node<T>::ndb_t::compute_node_depth 07839 | (initialiser_, condition_, incrementor_, loop_body_); 07840 | } 07841 | 07842 | protected: 07843 | 07844 | branch_t initialiser_; 07845 | branch_t condition_ ; 07846 | branch_t incrementor_; 07847 | branch_t loop_body_ ; 07848 | }; 07849 | 07850 | template <typename T> 07851 | class for_loop_rtc_node exprtk_final 07852 | : public for_loop_node<T> 07853 | , public loop_runtime_checker 07854 | { 07855 | public: 07856 | 07857 | typedef for_loop_node<T> parent_t; 07858 | typedef expression_node<T>* expression_ptr; 07859 | 07860 | for_loop_rtc_node(expression_ptr initialiser, 07861 | expression_ptr condition, 07862 | expression_ptr incrementor, 07863 | expression_ptr loop_body, 07864 | loop_runtime_check_ptr loop_rt_chk) 07865 | : parent_t(initialiser, condition, incrementor, loop_body) 07866 | , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_for_loop) 07867 | { 07868 | assert(valid()); 07869 | } 07870 | 07871 | inline T value() const exprtk_override 07872 | { 07873 | T result = T(0); 07874 | 07875 | loop_runtime_checker::reset(); 07876 | 07877 | if (parent_t::initialiser_.first) 07878 | parent_t::initialiser_.first->value(); 07879 | 07880 | if (parent_t::incrementor_.first) 07881 | { 07882 | while (is_true(parent_t::condition_) && loop_runtime_checker::check()) 07883 | { 07884 | result = parent_t::loop_body_.first->value(); 07885 | parent_t::incrementor_.first->value(); 07886 | } 07887 | } 07888 | else 07889 | { 07890 | while (is_true(parent_t::condition_) && loop_runtime_checker::check()) 07891 | { 07892 | result = parent_t::loop_body_.first->value(); 07893 | } 07894 | } 07895 | 07896 | return result; 07897 | } 07898 | 07899 | using parent_t::valid; 07900 | 07901 | inline bool valid() const exprtk_override exprtk_final 07902 | { 07903 | return parent_t::valid() && 07904 | loop_runtime_checker::valid(); 07905 | } 07906 | }; 07907 | 07908 | #ifndef exprtk_disable_break_continue 07909 | template <typename T> 07910 | class while_loop_bc_node : public while_loop_node<T> 07911 | { 07912 | public: 07913 | 07914 | typedef while_loop_node<T> parent_t; 07915 | typedef expression_node<T>* expression_ptr; 07916 | 07917 | while_loop_bc_node(expression_ptr condition, 07918 | expression_ptr loop_body) 07919 | : parent_t(condition, loop_body) 07920 | { 07921 | assert(parent_t::valid()); 07922 | } 07923 | 07924 | inline T value() const exprtk_override 07925 | { 07926 | T result = T(0); 07927 | 07928 | while (is_true(parent_t::condition_)) 07929 | { 07930 | try 07931 | { 07932 | result = parent_t::loop_body_.first->value(); 07933 | } 07934 | catch(const break_exception<T>& e) 07935 | { 07936 | return e.value; 07937 | } 07938 | catch(const continue_exception&) 07939 | {} 07940 | } 07941 | 07942 | return result; 07943 | } 07944 | }; 07945 | 07946 | template <typename T> 07947 | class while_loop_bc_rtc_node exprtk_final 07948 | : public while_loop_bc_node<T> 07949 | , public loop_runtime_checker 07950 | { 07951 | public: 07952 | 07953 | typedef while_loop_bc_node<T> parent_t; 07954 | typedef expression_node<T>* expression_ptr; 07955 | 07956 | while_loop_bc_rtc_node(expression_ptr condition, 07957 | expression_ptr loop_body, 07958 | loop_runtime_check_ptr loop_rt_chk) 07959 | : parent_t(condition, loop_body) 07960 | , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_while_loop) 07961 | { 07962 | assert(valid()); 07963 | } 07964 | 07965 | inline T value() const exprtk_override 07966 | { 07967 | T result = T(0); 07968 | 07969 | loop_runtime_checker::reset(); 07970 | 07971 | while (is_true(parent_t::condition_) && loop_runtime_checker::check()) 07972 | { 07973 | try 07974 | { 07975 | result = parent_t::loop_body_.first->value(); 07976 | } 07977 | catch(const break_exception<T>& e) 07978 | { 07979 | return e.value; 07980 | } 07981 | catch(const continue_exception&) 07982 | {} 07983 | } 07984 | 07985 | return result; 07986 | } 07987 | 07988 | using parent_t::valid; 07989 | 07990 | inline bool valid() const exprtk_override exprtk_final 07991 | { 07992 | return parent_t::valid() && 07993 | loop_runtime_checker::valid(); 07994 | } 07995 | }; 07996 | 07997 | template <typename T> 07998 | class repeat_until_loop_bc_node : public repeat_until_loop_node<T> 07999 | { 08000 | public: 08001 | 08002 | typedef repeat_until_loop_node<T> parent_t; 08003 | typedef expression_node<T>* expression_ptr; 08004 | 08005 | repeat_until_loop_bc_node(expression_ptr condition, 08006 | expression_ptr loop_body) 08007 | : parent_t(condition, loop_body) 08008 | { 08009 | assert(parent_t::valid()); 08010 | } 08011 | 08012 | inline T value() const exprtk_override 08013 | { 08014 | T result = T(0); 08015 | 08016 | do 08017 | { 08018 | try 08019 | { 08020 | result = parent_t::loop_body_.first->value(); 08021 | } 08022 | catch(const break_exception<T>& e) 08023 | { 08024 | return e.value; 08025 | } 08026 | catch(const continue_exception&) 08027 | {} 08028 | } 08029 | while (is_false(parent_t::condition_.first)); 08030 | 08031 | return result; 08032 | } 08033 | }; 08034 | 08035 | template <typename T> 08036 | class repeat_until_loop_bc_rtc_node exprtk_final 08037 | : public repeat_until_loop_bc_node<T> 08038 | , public loop_runtime_checker 08039 | { 08040 | public: 08041 | 08042 | typedef repeat_until_loop_bc_node<T> parent_t; 08043 | typedef expression_node<T>* expression_ptr; 08044 | 08045 | repeat_until_loop_bc_rtc_node(expression_ptr condition, 08046 | expression_ptr loop_body, 08047 | loop_runtime_check_ptr loop_rt_chk) 08048 | : parent_t(condition, loop_body) 08049 | , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_repeat_until_loop) 08050 | { 08051 | assert(valid()); 08052 | } 08053 | 08054 | inline T value() const exprtk_override 08055 | { 08056 | T result = T(0); 08057 | 08058 | loop_runtime_checker::reset(); 08059 | 08060 | do 08061 | { 08062 | try 08063 | { 08064 | result = parent_t::loop_body_.first->value(); 08065 | } 08066 | catch(const break_exception<T>& e) 08067 | { 08068 | return e.value; 08069 | } 08070 | catch(const continue_exception&) 08071 | {} 08072 | } 08073 | while (is_false(parent_t::condition_.first) && loop_runtime_checker::check()); 08074 | 08075 | return result; 08076 | } 08077 | 08078 | using parent_t::valid; 08079 | 08080 | inline bool valid() const exprtk_override exprtk_final 08081 | { 08082 | return parent_t::valid() && 08083 | loop_runtime_checker::valid(); 08084 | } 08085 | }; 08086 | 08087 | template <typename T> 08088 | class for_loop_bc_node : public for_loop_node<T> 08089 | { 08090 | public: 08091 | 08092 | typedef for_loop_node<T> parent_t; 08093 | typedef expression_node<T>* expression_ptr; 08094 | 08095 | for_loop_bc_node(expression_ptr initialiser, 08096 | expression_ptr condition, 08097 | expression_ptr incrementor, 08098 | expression_ptr loop_body) 08099 | : parent_t(initialiser, condition, incrementor, loop_body) 08100 | { 08101 | assert(parent_t::valid()); 08102 | } 08103 | 08104 | inline T value() const exprtk_override 08105 | { 08106 | T result = T(0); 08107 | 08108 | if (parent_t::initialiser_.first) 08109 | parent_t::initialiser_.first->value(); 08110 | 08111 | if (parent_t::incrementor_.first) 08112 | { 08113 | while (is_true(parent_t::condition_)) 08114 | { 08115 | try 08116 | { 08117 | result = parent_t::loop_body_.first->value(); 08118 | } 08119 | catch(const break_exception<T>& e) 08120 | { 08121 | return e.value; 08122 | } 08123 | catch(const continue_exception&) 08124 | {} 08125 | 08126 | parent_t::incrementor_.first->value(); 08127 | } 08128 | } 08129 | else 08130 | { 08131 | while (is_true(parent_t::condition_)) 08132 | { 08133 | try 08134 | { 08135 | result = parent_t::loop_body_.first->value(); 08136 | } 08137 | catch(const break_exception<T>& e) 08138 | { 08139 | return e.value; 08140 | } 08141 | catch(const continue_exception&) 08142 | {} 08143 | } 08144 | } 08145 | 08146 | return result; 08147 | } 08148 | }; 08149 | 08150 | template <typename T> 08151 | class for_loop_bc_rtc_node exprtk_final 08152 | : public for_loop_bc_node<T> 08153 | , public loop_runtime_checker 08154 | { 08155 | public: 08156 | 08157 | typedef for_loop_bc_node<T> parent_t; 08158 | typedef expression_node<T>* expression_ptr; 08159 | 08160 | for_loop_bc_rtc_node(expression_ptr initialiser, 08161 | expression_ptr condition, 08162 | expression_ptr incrementor, 08163 | expression_ptr loop_body, 08164 | loop_runtime_check_ptr loop_rt_chk) 08165 | : parent_t(initialiser, condition, incrementor, loop_body) 08166 | , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_for_loop) 08167 | { 08168 | assert(valid()); 08169 | } 08170 | 08171 | inline T value() const exprtk_override 08172 | { 08173 | T result = T(0); 08174 | 08175 | loop_runtime_checker::reset(); 08176 | 08177 | if (parent_t::initialiser_.first) 08178 | parent_t::initialiser_.first->value(); 08179 | 08180 | if (parent_t::incrementor_.first) 08181 | { 08182 | while (is_true(parent_t::condition_) && loop_runtime_checker::check()) 08183 | { 08184 | try 08185 | { 08186 | result = parent_t::loop_body_.first->value(); 08187 | } 08188 | catch(const break_exception<T>& e) 08189 | { 08190 | return e.value; 08191 | } 08192 | catch(const continue_exception&) 08193 | {} 08194 | 08195 | parent_t::incrementor_.first->value(); 08196 | } 08197 | } 08198 | else 08199 | { 08200 | while (is_true(parent_t::condition_) && loop_runtime_checker::check()) 08201 | { 08202 | try 08203 | { 08204 | result = parent_t::loop_body_.first->value(); 08205 | } 08206 | catch(const break_exception<T>& e) 08207 | { 08208 | return e.value; 08209 | } 08210 | catch(const continue_exception&) 08211 | {} 08212 | } 08213 | } 08214 | 08215 | return result; 08216 | } 08217 | 08218 | using parent_t::valid; 08219 | 08220 | inline bool valid() const exprtk_override exprtk_final 08221 | { 08222 | return parent_t::valid() && 08223 | loop_runtime_checker::valid(); 08224 | } 08225 | }; 08226 | #endif 08227 | 08228 | template <typename T> 08229 | class switch_node : public expression_node<T> 08230 | { 08231 | public: 08232 | 08233 | typedef expression_node<T>* expression_ptr; 08234 | typedef std::pair<expression_ptr,bool> branch_t; 08235 | 08236 | template <typename Allocator, 08237 | template <typename, typename> class Sequence> 08238 | explicit switch_node(const Sequence<expression_ptr,Allocator>& arg_list) 08239 | { 08240 | if (1 != (arg_list.size() & 1)) 08241 | return; 08242 | 08243 | arg_list_.resize(arg_list.size()); 08244 | 08245 | for (std::size_t i = 0; i < arg_list.size(); ++i) 08246 | { 08247 | if (arg_list[i] && arg_list[i]->valid()) 08248 | { 08249 | construct_branch_pair(arg_list_[i], arg_list[i]); 08250 | } 08251 | else 08252 | { 08253 | arg_list_.clear(); 08254 | return; 08255 | } 08256 | } 08257 | 08258 | assert(valid()); 08259 | } 08260 | 08261 | inline T value() const exprtk_override 08262 | { 08263 | const std::size_t upper_bound = (arg_list_.size() - 1); 08264 | 08265 | for (std::size_t i = 0; i < upper_bound; i += 2) 08266 | { 08267 | expression_ptr condition = arg_list_[i ].first; 08268 | expression_ptr consequent = arg_list_[i + 1].first; 08269 | 08270 | if (is_true(condition)) 08271 | { 08272 | return consequent->value(); 08273 | } 08274 | } 08275 | 08276 | return arg_list_[upper_bound].first->value(); 08277 | } 08278 | 08279 | inline typename expression_node<T>::node_type type() const exprtk_override exprtk_final 08280 | { 08281 | return expression_node<T>::e_switch; 08282 | } 08283 | 08284 | inline bool valid() const exprtk_override 08285 | { 08286 | return !arg_list_.empty(); 08287 | } 08288 | 08289 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 08290 | { 08291 | expression_node<T>::ndb_t::collect(arg_list_, node_delete_list); 08292 | } 08293 | 08294 | std::size_t node_depth() const exprtk_override exprtk_final 08295 | { 08296 | return expression_node<T>::ndb_t::compute_node_depth(arg_list_); 08297 | } 08298 | 08299 | protected: 08300 | 08301 | std::vector<branch_t> arg_list_; 08302 | }; 08303 | 08304 | template <typename T, typename Switch_N> 08305 | class switch_n_node exprtk_final : public switch_node<T> 08306 | { 08307 | public: 08308 | 08309 | typedef expression_node<T>* expression_ptr; 08310 | 08311 | template <typename Allocator, 08312 | template <typename, typename> class Sequence> 08313 | explicit switch_n_node(const Sequence<expression_ptr,Allocator>& arg_list) 08314 | : switch_node<T>(arg_list) 08315 | {} 08316 | 08317 | inline T value() const exprtk_override 08318 | { 08319 | return Switch_N::process(switch_node<T>::arg_list_); 08320 | } 08321 | }; 08322 | 08323 | template <typename T> 08324 | class multi_switch_node exprtk_final : public expression_node<T> 08325 | { 08326 | public: 08327 | 08328 | typedef expression_node<T>* expression_ptr; 08329 | typedef std::pair<expression_ptr,bool> branch_t; 08330 | 08331 | template <typename Allocator, 08332 | template <typename, typename> class Sequence> 08333 | explicit multi_switch_node(const Sequence<expression_ptr,Allocator>& arg_list) 08334 | { 08335 | if (0 != (arg_list.size() & 1)) 08336 | return; 08337 | 08338 | arg_list_.resize(arg_list.size()); 08339 | 08340 | for (std::size_t i = 0; i < arg_list.size(); ++i) 08341 | { 08342 | if (arg_list[i] && arg_list[i]->valid()) 08343 | { 08344 | construct_branch_pair(arg_list_[i], arg_list[i]); 08345 | } 08346 | else 08347 | { 08348 | arg_list_.clear(); 08349 | return; 08350 | } 08351 | } 08352 | 08353 | assert(valid()); 08354 | } 08355 | 08356 | inline T value() const exprtk_override 08357 | { 08358 | const std::size_t upper_bound = (arg_list_.size() - 1); 08359 | 08360 | T result = T(0); 08361 | 08362 | for (std::size_t i = 0; i < upper_bound; i += 2) 08363 | { 08364 | expression_ptr condition = arg_list_[i ].first; 08365 | expression_ptr consequent = arg_list_[i + 1].first; 08366 | 08367 | if (is_true(condition)) 08368 | { 08369 | result = consequent->value(); 08370 | } 08371 | } 08372 | 08373 | return result; 08374 | } 08375 | 08376 | inline typename expression_node<T>::node_type type() const exprtk_override 08377 | { 08378 | return expression_node<T>::e_mswitch; 08379 | } 08380 | 08381 | inline bool valid() const exprtk_override 08382 | { 08383 | return !arg_list_.empty() && (0 == (arg_list_.size() % 2)); 08384 | } 08385 | 08386 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 08387 | { 08388 | expression_node<T>::ndb_t::collect(arg_list_, node_delete_list); 08389 | } 08390 | 08391 | std::size_t node_depth() const exprtk_override exprtk_final 08392 | { 08393 | return expression_node<T>::ndb_t::compute_node_depth(arg_list_); 08394 | } 08395 | 08396 | private: 08397 | 08398 | std::vector<branch_t> arg_list_; 08399 | }; 08400 | 08401 | template <typename T> 08402 | class ivariable 08403 | { 08404 | public: 08405 | 08406 | virtual ~ivariable() 08407 | {} 08408 | 08409 | virtual T& ref() = 0; 08410 | virtual const T& ref() const = 0; 08411 | }; 08412 | 08413 | template <typename T> 08414 | class variable_node exprtk_final 08415 | : public expression_node<T> 08416 | , public ivariable <T> 08417 | { 08418 | public: 08419 | 08420 | static T null_value; 08421 | 08422 | explicit variable_node() 08423 | : value_(&null_value) 08424 | {} 08425 | 08426 | explicit variable_node(T& v) 08427 | : value_(&v) 08428 | {} 08429 | 08430 | inline bool operator <(const variable_node<T>& v) const 08431 | { 08432 | return this < (&v); 08433 | } 08434 | 08435 | inline T value() const exprtk_override 08436 | { 08437 | return (*value_); 08438 | } 08439 | 08440 | inline T& ref() exprtk_override 08441 | { 08442 | return (*value_); 08443 | } 08444 | 08445 | inline const T& ref() const exprtk_override 08446 | { 08447 | return (*value_); 08448 | } 08449 | 08450 | inline typename expression_node<T>::node_type type() const exprtk_override 08451 | { 08452 | return expression_node<T>::e_variable; 08453 | } 08454 | 08455 | private: 08456 | 08457 | T* value_; 08458 | }; 08459 | 08460 | template <typename T> 08461 | T variable_node<T>::null_value = T(std::numeric_limits<T>::quiet_NaN()); 08462 | 08463 | template <typename T> 08464 | struct range_pack 08465 | { 08466 | typedef expression_node<T>* expression_node_ptr; 08467 | typedef std::pair<std::size_t,std::size_t> cached_range_t; 08468 | 08469 | range_pack() 08470 | : n0_e (std::make_pair(false,expression_node_ptr(0))) 08471 | , n1_e (std::make_pair(false,expression_node_ptr(0))) 08472 | , n0_c (std::make_pair(false,0)) 08473 | , n1_c (std::make_pair(false,0)) 08474 | , cache(std::make_pair(0,0)) 08475 | {} 08476 | 08477 | void clear() 08478 | { 08479 | n0_e = std::make_pair(false,expression_node_ptr(0)); 08480 | n1_e = std::make_pair(false,expression_node_ptr(0)); 08481 | n0_c = std::make_pair(false,0); 08482 | n1_c = std::make_pair(false,0); 08483 | cache = std::make_pair(0,0); 08484 | } 08485 | 08486 | void free() 08487 | { 08488 | if (n0_e.first && n0_e.second) 08489 | { 08490 | n0_e.first = false; 08491 | 08492 | if ( 08493 | !is_variable_node(n0_e.second) && 08494 | !is_string_node (n0_e.second) 08495 | ) 08496 | { 08497 | destroy_node(n0_e.second); 08498 | } 08499 | } 08500 | 08501 | if (n1_e.first && n1_e.second) 08502 | { 08503 | n1_e.first = false; 08504 | 08505 | if ( 08506 | !is_variable_node(n1_e.second) && 08507 | !is_string_node (n1_e.second) 08508 | ) 08509 | { 08510 | destroy_node(n1_e.second); 08511 | } 08512 | } 08513 | } 08514 | 08515 | bool const_range() const 08516 | { 08517 | return ( n0_c.first && n1_c.first) && 08518 | (!n0_e.first && !n1_e.first); 08519 | } 08520 | 08521 | bool var_range() const 08522 | { 08523 | return ( n0_e.first && n1_e.first) && 08524 | (!n0_c.first && !n1_c.first); 08525 | } 08526 | 08527 | bool operator() (std::size_t& r0, std::size_t& r1, 08528 | const std::size_t& size = std::numeric_limits<std::size_t>::max()) const 08529 | { 08530 | if (n0_c.first) 08531 | r0 = n0_c.second; 08532 | else if (n0_e.first) 08533 | { 08534 | r0 = static_cast<std::size_t>(details::numeric::to_int64(n0_e.second->value())); 08535 | } 08536 | else 08537 | return false; 08538 | 08539 | if (n1_c.first) 08540 | r1 = n1_c.second; 08541 | else if (n1_e.first) 08542 | { 08543 | r1 = static_cast<std::size_t>(details::numeric::to_int64(n1_e.second->value())); 08544 | } 08545 | else 08546 | return false; 08547 | 08548 | if ( 08549 | (std::numeric_limits<std::size_t>::max() != size) && 08550 | (std::numeric_limits<std::size_t>::max() == r1 ) 08551 | ) 08552 | { 08553 | r1 = size; 08554 | } 08555 | 08556 | cache.first = r0; 08557 | cache.second = r1; 08558 | 08559 | #ifndef exprtk_enable_range_runtime_checks 08560 | return (r0 <= r1); 08561 | #else 08562 | return range_runtime_check(r0, r1, size); 08563 | #endif 08564 | } 08565 | 08566 | inline std::size_t const_size() const 08567 | { 08568 | return (n1_c.second - n0_c.second); 08569 | } 08570 | 08571 | inline std::size_t cache_size() const 08572 | { 08573 | return (cache.second - cache.first); 08574 | } 08575 | 08576 | std::pair<bool,expression_node_ptr> n0_e; 08577 | std::pair<bool,expression_node_ptr> n1_e; 08578 | std::pair<bool,std::size_t > n0_c; 08579 | std::pair<bool,std::size_t > n1_c; 08580 | mutable cached_range_t cache; 08581 | 08582 | #ifdef exprtk_enable_range_runtime_checks 08583 | bool range_runtime_check(const std::size_t r0, 08584 | const std::size_t r1, 08585 | const std::size_t size) const 08586 | { 08587 | if (r0 > size) 08588 | { 08589 | throw std::runtime_error("range error: (r0 < 0) || (r0 > size)"); 08590 | #if !defined(_MSC_VER) && !defined(__NVCOMPILER) 08591 | return false; 08592 | #endif 08593 | } 08594 | 08595 | if (r1 > size) 08596 | { 08597 | throw std::runtime_error("range error: (r1 < 0) || (r1 > size)"); 08598 | #if !defined(_MSC_VER) && !defined(__NVCOMPILER) 08599 | return false; 08600 | #endif 08601 | } 08602 | 08603 | return (r0 <= r1); 08604 | } 08605 | #endif 08606 | }; 08607 | 08608 | template <typename T> 08609 | class string_base_node; 08610 | 08611 | template <typename T> 08612 | struct range_data_type 08613 | { 08614 | typedef range_pack<T> range_t; 08615 | typedef string_base_node<T>* strbase_ptr_t; 08616 | 08617 | range_data_type() 08618 | : range(0) 08619 | , data (0) 08620 | , size (0) 08621 | , type_size(0) 08622 | , str_node (0) 08623 | {} 08624 | 08625 | range_t* range; 08626 | void* data; 08627 | std::size_t size; 08628 | std::size_t type_size; 08629 | strbase_ptr_t str_node; 08630 | }; 08631 | 08632 | template <typename T> class vector_node; 08633 | 08634 | template <typename T> 08635 | class vector_interface 08636 | { 08637 | public: 08638 | 08639 | typedef vector_node<T>* vector_node_ptr; 08640 | typedef vec_data_store<T> vds_t; 08641 | 08642 | virtual ~vector_interface() 08643 | {} 08644 | 08645 | virtual std::size_t size () const = 0; 08646 | 08647 | virtual std::size_t base_size() const = 0; 08648 | 08649 | virtual vector_node_ptr vec () const = 0; 08650 | 08651 | virtual vector_node_ptr vec () = 0; 08652 | 08653 | virtual vds_t& vds () = 0; 08654 | 08655 | virtual const vds_t& vds () const = 0; 08656 | 08657 | virtual bool side_effect () const { return false; } 08658 | }; 08659 | 08660 | template <typename T> 08661 | class vector_node exprtk_final 08662 | : public expression_node <T> 08663 | , public vector_interface<T> 08664 | { 08665 | public: 08666 | 08667 | typedef expression_node<T>* expression_ptr; 08668 | typedef vector_holder<T> vector_holder_t; 08669 | typedef vector_node<T>* vector_node_ptr; 08670 | typedef vec_data_store<T> vds_t; 08671 | 08672 | explicit vector_node(vector_holder_t* vh) 08673 | : vector_holder_(vh) 08674 | , vds_((*vector_holder_).size(),(*vector_holder_)[0]) 08675 | { 08676 | vector_holder_->set_ref(&vds_.ref()); 08677 | } 08678 | 08679 | vector_node(const vds_t& vds, vector_holder_t* vh) 08680 | : vector_holder_(vh) 08681 | , vds_(vds) 08682 | {} 08683 | 08684 | ~vector_node() exprtk_override 08685 | { 08686 | assert(valid()); 08687 | vector_holder_->remove_ref(&vds_.ref()); 08688 | } 08689 | 08690 | inline T value() const exprtk_override 08691 | { 08692 | return vds().data()[0]; 08693 | } 08694 | 08695 | vector_node_ptr vec() const exprtk_override 08696 | { 08697 | return const_cast<vector_node_ptr>(this); 08698 | } 08699 | 08700 | vector_node_ptr vec() exprtk_override 08701 | { 08702 | return this; 08703 | } 08704 | 08705 | inline typename expression_node<T>::node_type type() const exprtk_override 08706 | { 08707 | return expression_node<T>::e_vector; 08708 | } 08709 | 08710 | inline bool valid() const exprtk_override 08711 | { 08712 | return vector_holder_; 08713 | } 08714 | 08715 | std::size_t size() const exprtk_override 08716 | { 08717 | return vec_holder().size(); 08718 | } 08719 | 08720 | std::size_t base_size() const exprtk_override 08721 | { 08722 | return vec_holder().base_size(); 08723 | } 08724 | 08725 | vds_t& vds() exprtk_override 08726 | { 08727 | return vds_; 08728 | } 08729 | 08730 | const vds_t& vds() const exprtk_override 08731 | { 08732 | return vds_; 08733 | } 08734 | 08735 | inline vector_holder_t& vec_holder() 08736 | { 08737 | return (*vector_holder_); 08738 | } 08739 | 08740 | inline vector_holder_t& vec_holder() const 08741 | { 08742 | return (*vector_holder_); 08743 | } 08744 | 08745 | private: 08746 | 08747 | vector_holder_t* vector_holder_; 08748 | vds_t vds_; 08749 | }; 08750 | 08751 | template <typename T> 08752 | class vector_size_node exprtk_final 08753 | : public expression_node <T> 08754 | { 08755 | public: 08756 | 08757 | typedef expression_node<T>* expression_ptr; 08758 | typedef vector_holder<T> vector_holder_t; 08759 | 08760 | explicit vector_size_node(vector_holder_t* vh) 08761 | : vector_holder_(vh) 08762 | {} 08763 | 08764 | ~vector_size_node() exprtk_override 08765 | { 08766 | assert(valid()); 08767 | } 08768 | 08769 | inline T value() const exprtk_override 08770 | { 08771 | assert(vector_holder_); 08772 | return static_cast<T>(vector_holder_->size()); 08773 | } 08774 | 08775 | inline typename expression_node<T>::node_type type() const exprtk_override 08776 | { 08777 | return expression_node<T>::e_vecsize; 08778 | } 08779 | 08780 | inline bool valid() const exprtk_override 08781 | { 08782 | return vector_holder_ && vector_holder_->size(); 08783 | } 08784 | 08785 | inline vector_holder_t* vec_holder() 08786 | { 08787 | return vector_holder_; 08788 | } 08789 | 08790 | private: 08791 | 08792 | vector_holder_t* vector_holder_; 08793 | }; 08794 | 08795 | template <typename T> 08796 | class vector_elem_node exprtk_final 08797 | : public expression_node<T> 08798 | , public ivariable <T> 08799 | { 08800 | public: 08801 | 08802 | typedef expression_node<T>* expression_ptr; 08803 | typedef vector_holder<T> vector_holder_t; 08804 | typedef vector_holder_t* vector_holder_ptr; 08805 | typedef std::pair<expression_ptr,bool> branch_t; 08806 | 08807 | vector_elem_node(expression_ptr vec_node, 08808 | expression_ptr index, 08809 | vector_holder_ptr vec_holder) 08810 | : vector_holder_(vec_holder) 08811 | , vector_base_((*vec_holder)[0]) 08812 | { 08813 | construct_branch_pair(vector_node_, vec_node); 08814 | construct_branch_pair(index_ , index ); 08815 | assert(valid()); 08816 | } 08817 | 08818 | inline T value() const exprtk_override 08819 | { 08820 | return *access_vector(); 08821 | } 08822 | 08823 | inline T& ref() exprtk_override 08824 | { 08825 | return *access_vector(); 08826 | } 08827 | 08828 | inline const T& ref() const exprtk_override 08829 | { 08830 | return *access_vector(); 08831 | } 08832 | 08833 | inline typename expression_node<T>::node_type type() const exprtk_override 08834 | { 08835 | return expression_node<T>::e_vecelem; 08836 | } 08837 | 08838 | inline bool valid() const exprtk_override 08839 | { 08840 | return 08841 | vector_holder_ && 08842 | index_.first && 08843 | vector_node_.first && 08844 | index_.first->valid() && 08845 | vector_node_.first->valid(); 08846 | } 08847 | 08848 | inline vector_holder_t& vec_holder() 08849 | { 08850 | return (*vector_holder_); 08851 | } 08852 | 08853 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 08854 | { 08855 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 08856 | expression_node<T>::ndb_t::collect(index_ , node_delete_list); 08857 | } 08858 | 08859 | std::size_t node_depth() const exprtk_override 08860 | { 08861 | return expression_node<T>::ndb_t::compute_node_depth 08862 | (vector_node_, index_); 08863 | } 08864 | 08865 | private: 08866 | 08867 | inline T* access_vector() const 08868 | { 08869 | vector_node_.first->value(); 08870 | return (vector_base_ + details::numeric::to_uint64(index_.first->value())); 08871 | } 08872 | 08873 | vector_holder_ptr vector_holder_; 08874 | T* vector_base_; 08875 | branch_t vector_node_; 08876 | branch_t index_; 08877 | }; 08878 | 08879 | template <typename T> 08880 | class vector_celem_node exprtk_final 08881 | : public expression_node<T> 08882 | , public ivariable <T> 08883 | { 08884 | public: 08885 | 08886 | typedef expression_node<T>* expression_ptr; 08887 | typedef vector_holder<T> vector_holder_t; 08888 | typedef vector_holder_t* vector_holder_ptr; 08889 | typedef std::pair<expression_ptr,bool> branch_t; 08890 | 08891 | vector_celem_node(expression_ptr vec_node, 08892 | const std::size_t index, 08893 | vector_holder_ptr vec_holder) 08894 | : index_(index) 08895 | , vector_holder_(vec_holder) 08896 | , vector_base_((*vec_holder)[0]) 08897 | { 08898 | construct_branch_pair(vector_node_, vec_node); 08899 | assert(valid()); 08900 | } 08901 | 08902 | inline T value() const exprtk_override 08903 | { 08904 | return *access_vector(); 08905 | } 08906 | 08907 | inline T& ref() exprtk_override 08908 | { 08909 | return *access_vector(); 08910 | } 08911 | 08912 | inline const T& ref() const exprtk_override 08913 | { 08914 | return *access_vector(); 08915 | } 08916 | 08917 | inline typename expression_node<T>::node_type type() const exprtk_override 08918 | { 08919 | return expression_node<T>::e_veccelem; 08920 | } 08921 | 08922 | inline bool valid() const exprtk_override 08923 | { 08924 | return 08925 | vector_holder_ && 08926 | vector_node_.first && 08927 | vector_node_.first->valid(); 08928 | } 08929 | 08930 | inline vector_holder_t& vec_holder() 08931 | { 08932 | return (*vector_holder_); 08933 | } 08934 | 08935 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 08936 | { 08937 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 08938 | } 08939 | 08940 | std::size_t node_depth() const exprtk_override 08941 | { 08942 | return expression_node<T>::ndb_t::compute_node_depth(vector_node_); 08943 | } 08944 | 08945 | private: 08946 | 08947 | inline T* access_vector() const 08948 | { 08949 | vector_node_.first->value(); 08950 | return (vector_base_ + index_); 08951 | } 08952 | 08953 | const std::size_t index_; 08954 | vector_holder_ptr vector_holder_; 08955 | T* vector_base_; 08956 | branch_t vector_node_; 08957 | }; 08958 | 08959 | template <typename T> 08960 | class vector_elem_rtc_node exprtk_final 08961 | : public expression_node<T> 08962 | , public ivariable <T> 08963 | { 08964 | public: 08965 | 08966 | typedef expression_node<T>* expression_ptr; 08967 | typedef vector_holder<T> vector_holder_t; 08968 | typedef vector_holder_t* vector_holder_ptr; 08969 | typedef std::pair<expression_ptr,bool> branch_t; 08970 | 08971 | vector_elem_rtc_node(expression_ptr vec_node, 08972 | expression_ptr index, 08973 | vector_holder_ptr vec_holder, 08974 | vector_access_runtime_check_ptr vec_rt_chk) 08975 | : vector_holder_(vec_holder) 08976 | , vector_base_((*vec_holder)[0]) 08977 | , vec_rt_chk_(vec_rt_chk) 08978 | , max_vector_index_(vector_holder_->size() - 1) 08979 | { 08980 | construct_branch_pair(vector_node_, vec_node); 08981 | construct_branch_pair(index_ , index ); 08982 | assert(valid()); 08983 | } 08984 | 08985 | inline T value() const exprtk_override 08986 | { 08987 | return *access_vector(); 08988 | } 08989 | 08990 | inline T& ref() exprtk_override 08991 | { 08992 | return *access_vector(); 08993 | } 08994 | 08995 | inline const T& ref() const exprtk_override 08996 | { 08997 | return *access_vector(); 08998 | } 08999 | 09000 | inline typename expression_node<T>::node_type type() const exprtk_override 09001 | { 09002 | return expression_node<T>::e_vecelemrtc; 09003 | } 09004 | 09005 | inline bool valid() const exprtk_override 09006 | { 09007 | return 09008 | vector_holder_ && 09009 | index_.first && 09010 | vector_node_.first && 09011 | index_.first->valid() && 09012 | vector_node_.first->valid(); 09013 | } 09014 | 09015 | inline vector_holder_t& vec_holder() 09016 | { 09017 | return (*vector_holder_); 09018 | } 09019 | 09020 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09021 | { 09022 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 09023 | expression_node<T>::ndb_t::collect(index_, node_delete_list); 09024 | } 09025 | 09026 | std::size_t node_depth() const exprtk_override 09027 | { 09028 | return expression_node<T>::ndb_t::compute_node_depth 09029 | (vector_node_, index_); 09030 | } 09031 | 09032 | private: 09033 | 09034 | inline T* access_vector() const 09035 | { 09036 | const _uint64_t index = details::numeric::to_uint64(index_.first->value()); 09037 | vector_node_.first->value(); 09038 | 09039 | if (index <= max_vector_index_) 09040 | { 09041 | return (vector_holder_->data() + index); 09042 | } 09043 | 09044 | assert(vec_rt_chk_); 09045 | 09046 | vector_access_runtime_check::violation_context context; 09047 | context.base_ptr = reinterpret_cast<void*>(vector_base_); 09048 | context.end_ptr = reinterpret_cast<void*>(vector_base_ + vector_holder_->size()); 09049 | context.access_ptr = reinterpret_cast<void*>(vector_base_ + index); 09050 | context.type_size = sizeof(T); 09051 | 09052 | return vec_rt_chk_->handle_runtime_violation(context) ? 09053 | reinterpret_cast<T*>(context.access_ptr) : 09054 | vector_base_ ; 09055 | } 09056 | 09057 | vector_holder_ptr vector_holder_; 09058 | T* vector_base_; 09059 | branch_t vector_node_; 09060 | branch_t index_; 09061 | vector_access_runtime_check_ptr vec_rt_chk_; 09062 | const std::size_t max_vector_index_; 09063 | }; 09064 | 09065 | template <typename T> 09066 | class vector_celem_rtc_node exprtk_final 09067 | : public expression_node<T> 09068 | , public ivariable <T> 09069 | { 09070 | public: 09071 | 09072 | typedef expression_node<T>* expression_ptr; 09073 | typedef vector_holder<T> vector_holder_t; 09074 | typedef vector_holder_t* vector_holder_ptr; 09075 | typedef std::pair<expression_ptr,bool> branch_t; 09076 | 09077 | vector_celem_rtc_node(expression_ptr vec_node, 09078 | const std::size_t index, 09079 | vector_holder_ptr vec_holder, 09080 | vector_access_runtime_check_ptr vec_rt_chk) 09081 | : index_(index) 09082 | , max_vector_index_(vec_holder->size() - 1) 09083 | , vector_holder_(vec_holder) 09084 | , vector_base_((*vec_holder)[0]) 09085 | , vec_rt_chk_(vec_rt_chk) 09086 | { 09087 | construct_branch_pair(vector_node_, vec_node); 09088 | assert(valid()); 09089 | } 09090 | 09091 | inline T value() const exprtk_override 09092 | { 09093 | return *access_vector(); 09094 | } 09095 | 09096 | inline T& ref() exprtk_override 09097 | { 09098 | return *access_vector(); 09099 | } 09100 | 09101 | inline const T& ref() const exprtk_override 09102 | { 09103 | return *access_vector(); 09104 | } 09105 | 09106 | inline typename expression_node<T>::node_type type() const exprtk_override 09107 | { 09108 | return expression_node<T>::e_veccelemrtc; 09109 | } 09110 | 09111 | inline bool valid() const exprtk_override 09112 | { 09113 | return 09114 | vector_holder_ && 09115 | vector_node_.first && 09116 | vector_node_.first->valid(); 09117 | } 09118 | 09119 | inline vector_holder_t& vec_holder() 09120 | { 09121 | return (*vector_holder_); 09122 | } 09123 | 09124 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09125 | { 09126 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 09127 | } 09128 | 09129 | std::size_t node_depth() const exprtk_override 09130 | { 09131 | return expression_node<T>::ndb_t::compute_node_depth(vector_node_); 09132 | } 09133 | 09134 | private: 09135 | 09136 | inline T* access_vector() const 09137 | { 09138 | vector_node_.first->value(); 09139 | 09140 | if (index_ <= max_vector_index_) 09141 | { 09142 | return (vector_holder_->data() + index_); 09143 | } 09144 | 09145 | assert(vec_rt_chk_); 09146 | 09147 | vector_access_runtime_check::violation_context context; 09148 | context.base_ptr = reinterpret_cast<void*>(vector_base_); 09149 | context.end_ptr = reinterpret_cast<void*>(vector_base_ + vector_holder_->size()); 09150 | context.access_ptr = reinterpret_cast<void*>(vector_base_ + index_); 09151 | context.type_size = sizeof(T); 09152 | 09153 | return vec_rt_chk_->handle_runtime_violation(context) ? 09154 | reinterpret_cast<T*>(context.access_ptr) : 09155 | vector_base_ ; 09156 | } 09157 | 09158 | const std::size_t index_; 09159 | const std::size_t max_vector_index_; 09160 | vector_holder_ptr vector_holder_; 09161 | T* vector_base_; 09162 | branch_t vector_node_; 09163 | vector_access_runtime_check_ptr vec_rt_chk_; 09164 | }; 09165 | 09166 | template <typename T> 09167 | class rebasevector_elem_node exprtk_final 09168 | : public expression_node<T> 09169 | , public ivariable <T> 09170 | { 09171 | public: 09172 | 09173 | typedef expression_node<T>* expression_ptr; 09174 | typedef vector_holder<T> vector_holder_t; 09175 | typedef vector_holder_t* vector_holder_ptr; 09176 | typedef vec_data_store<T> vds_t; 09177 | typedef std::pair<expression_ptr,bool> branch_t; 09178 | 09179 | rebasevector_elem_node(expression_ptr vec_node, 09180 | expression_ptr index, 09181 | vector_holder_ptr vec_holder) 09182 | : vector_holder_(vec_holder) 09183 | { 09184 | construct_branch_pair(vector_node_, vec_node); 09185 | construct_branch_pair(index_ , index ); 09186 | assert(valid()); 09187 | } 09188 | 09189 | inline T value() const exprtk_override 09190 | { 09191 | return *access_vector(); 09192 | } 09193 | 09194 | inline T& ref() exprtk_override 09195 | { 09196 | return *access_vector(); 09197 | } 09198 | 09199 | inline const T& ref() const exprtk_override 09200 | { 09201 | return *access_vector(); 09202 | } 09203 | 09204 | inline typename expression_node<T>::node_type type() const exprtk_override 09205 | { 09206 | return expression_node<T>::e_rbvecelem; 09207 | } 09208 | 09209 | inline bool valid() const exprtk_override 09210 | { 09211 | return 09212 | vector_holder_ && 09213 | index_.first && 09214 | vector_node_.first && 09215 | index_.first->valid() && 09216 | vector_node_.first->valid(); 09217 | } 09218 | 09219 | inline vector_holder_t& vec_holder() 09220 | { 09221 | return (*vector_holder_); 09222 | } 09223 | 09224 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09225 | { 09226 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 09227 | expression_node<T>::ndb_t::collect(index_, node_delete_list); 09228 | } 09229 | 09230 | std::size_t node_depth() const exprtk_override 09231 | { 09232 | return expression_node<T>::ndb_t::compute_node_depth 09233 | (vector_node_, index_); 09234 | } 09235 | 09236 | private: 09237 | 09238 | inline T* access_vector() const 09239 | { 09240 | vector_node_.first->value(); 09241 | return (vector_holder_->data() + details::numeric::to_uint64(index_.first->value())); 09242 | } 09243 | 09244 | vector_holder_ptr vector_holder_; 09245 | branch_t vector_node_; 09246 | branch_t index_; 09247 | }; 09248 | 09249 | template <typename T> 09250 | class rebasevector_celem_node exprtk_final 09251 | : public expression_node<T> 09252 | , public ivariable <T> 09253 | { 09254 | public: 09255 | 09256 | typedef expression_node<T>* expression_ptr; 09257 | typedef vector_holder<T> vector_holder_t; 09258 | typedef vector_holder_t* vector_holder_ptr; 09259 | typedef std::pair<expression_ptr,bool> branch_t; 09260 | 09261 | rebasevector_celem_node(expression_ptr vec_node, 09262 | const std::size_t index, 09263 | vector_holder_ptr vec_holder) 09264 | : index_(index) 09265 | , vector_holder_(vec_holder) 09266 | { 09267 | construct_branch_pair(vector_node_, vec_node); 09268 | assert(valid()); 09269 | } 09270 | 09271 | inline T value() const exprtk_override 09272 | { 09273 | vector_node_.first->value(); 09274 | return ref(); 09275 | } 09276 | 09277 | inline T& ref() exprtk_override 09278 | { 09279 | return *(vector_holder_->data() + index_); 09280 | } 09281 | 09282 | inline const T& ref() const exprtk_override 09283 | { 09284 | return *(vector_holder_->data() + index_); 09285 | } 09286 | 09287 | inline typename expression_node<T>::node_type type() const exprtk_override 09288 | { 09289 | return expression_node<T>::e_rbveccelem; 09290 | } 09291 | 09292 | inline bool valid() const exprtk_override 09293 | { 09294 | return 09295 | vector_holder_ && 09296 | vector_node_.first && 09297 | vector_node_.first->valid(); 09298 | } 09299 | 09300 | inline vector_holder_t& vec_holder() 09301 | { 09302 | return (*vector_holder_); 09303 | } 09304 | 09305 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09306 | { 09307 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 09308 | } 09309 | 09310 | std::size_t node_depth() const exprtk_override 09311 | { 09312 | return expression_node<T>::ndb_t::compute_node_depth(vector_node_); 09313 | } 09314 | 09315 | private: 09316 | 09317 | const std::size_t index_; 09318 | vector_holder_ptr vector_holder_; 09319 | branch_t vector_node_; 09320 | }; 09321 | 09322 | template <typename T> 09323 | class rebasevector_elem_rtc_node exprtk_final 09324 | : public expression_node<T> 09325 | , public ivariable <T> 09326 | { 09327 | public: 09328 | 09329 | typedef expression_node<T>* expression_ptr; 09330 | typedef vector_holder<T> vector_holder_t; 09331 | typedef vector_holder_t* vector_holder_ptr; 09332 | typedef std::pair<expression_ptr,bool> branch_t; 09333 | 09334 | rebasevector_elem_rtc_node(expression_ptr vec_node, 09335 | expression_ptr index, 09336 | vector_holder_ptr vec_holder, 09337 | vector_access_runtime_check_ptr vec_rt_chk) 09338 | : vector_holder_(vec_holder) 09339 | , vec_rt_chk_(vec_rt_chk) 09340 | { 09341 | construct_branch_pair(vector_node_, vec_node); 09342 | construct_branch_pair(index_ , index ); 09343 | assert(valid()); 09344 | } 09345 | 09346 | inline T value() const exprtk_override 09347 | { 09348 | return *access_vector(); 09349 | } 09350 | 09351 | inline T& ref() exprtk_override 09352 | { 09353 | return *access_vector(); 09354 | } 09355 | 09356 | inline const T& ref() const exprtk_override 09357 | { 09358 | return *access_vector(); 09359 | } 09360 | 09361 | inline typename expression_node<T>::node_type type() const exprtk_override 09362 | { 09363 | return expression_node<T>::e_rbvecelemrtc; 09364 | } 09365 | 09366 | inline bool valid() const exprtk_override 09367 | { 09368 | return 09369 | vector_holder_ && 09370 | index_.first && 09371 | vector_node_.first && 09372 | index_.first->valid() && 09373 | vector_node_.first->valid(); 09374 | } 09375 | 09376 | inline vector_holder_t& vec_holder() 09377 | { 09378 | return (*vector_holder_); 09379 | } 09380 | 09381 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09382 | { 09383 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 09384 | expression_node<T>::ndb_t::collect(index_ , node_delete_list); 09385 | } 09386 | 09387 | std::size_t node_depth() const exprtk_override 09388 | { 09389 | return expression_node<T>::ndb_t::compute_node_depth 09390 | (vector_node_, index_); 09391 | } 09392 | 09393 | private: 09394 | 09395 | inline T* access_vector() const 09396 | { 09397 | vector_node_.first->value(); 09398 | const _uint64_t index = details::numeric::to_uint64(index_.first->value()); 09399 | 09400 | if (index <= (vector_holder_->size() - 1)) 09401 | { 09402 | return (vector_holder_->data() + index); 09403 | } 09404 | 09405 | assert(vec_rt_chk_); 09406 | 09407 | vector_access_runtime_check::violation_context context; 09408 | context.base_ptr = reinterpret_cast<void*>(vector_holder_->data()); 09409 | context.end_ptr = reinterpret_cast<void*>(vector_holder_->data() + vector_holder_->size()); 09410 | context.access_ptr = reinterpret_cast<void*>(vector_holder_->data() + index); 09411 | context.type_size = sizeof(T); 09412 | 09413 | return vec_rt_chk_->handle_runtime_violation(context) ? 09414 | reinterpret_cast<T*>(context.access_ptr) : 09415 | vector_holder_->data() ; 09416 | } 09417 | 09418 | vector_holder_ptr vector_holder_; 09419 | branch_t vector_node_; 09420 | branch_t index_; 09421 | vector_access_runtime_check_ptr vec_rt_chk_; 09422 | }; 09423 | 09424 | template <typename T> 09425 | class rebasevector_celem_rtc_node exprtk_final 09426 | : public expression_node<T> 09427 | , public ivariable <T> 09428 | { 09429 | public: 09430 | 09431 | typedef expression_node<T>* expression_ptr; 09432 | typedef vector_holder<T> vector_holder_t; 09433 | typedef vector_holder_t* vector_holder_ptr; 09434 | typedef std::pair<expression_ptr,bool> branch_t; 09435 | 09436 | rebasevector_celem_rtc_node(expression_ptr vec_node, 09437 | const std::size_t index, 09438 | vector_holder_ptr vec_holder, 09439 | vector_access_runtime_check_ptr vec_rt_chk) 09440 | : index_(index) 09441 | , vector_holder_(vec_holder) 09442 | , vector_base_((*vec_holder)[0]) 09443 | , vec_rt_chk_(vec_rt_chk) 09444 | { 09445 | construct_branch_pair(vector_node_, vec_node); 09446 | assert(valid()); 09447 | } 09448 | 09449 | inline T value() const exprtk_override 09450 | { 09451 | return *access_vector(); 09452 | } 09453 | 09454 | inline T& ref() exprtk_override 09455 | { 09456 | return *access_vector(); 09457 | } 09458 | 09459 | inline const T& ref() const exprtk_override 09460 | { 09461 | return *access_vector(); 09462 | } 09463 | 09464 | inline typename expression_node<T>::node_type type() const exprtk_override 09465 | { 09466 | return expression_node<T>::e_rbveccelemrtc; 09467 | } 09468 | 09469 | inline bool valid() const exprtk_override 09470 | { 09471 | return 09472 | vector_holder_ && 09473 | vector_node_.first && 09474 | vector_node_.first->valid(); 09475 | } 09476 | 09477 | inline vector_holder_t& vec_holder() 09478 | { 09479 | return (*vector_holder_); 09480 | } 09481 | 09482 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09483 | { 09484 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 09485 | } 09486 | 09487 | std::size_t node_depth() const exprtk_override 09488 | { 09489 | return expression_node<T>::ndb_t::compute_node_depth(vector_node_); 09490 | } 09491 | 09492 | private: 09493 | 09494 | inline T* access_vector() const 09495 | { 09496 | vector_node_.first->value(); 09497 | 09498 | if (index_ <= vector_holder_->size() - 1) 09499 | { 09500 | return (vector_holder_->data() + index_); 09501 | } 09502 | 09503 | assert(vec_rt_chk_); 09504 | 09505 | vector_access_runtime_check::violation_context context; 09506 | context.base_ptr = reinterpret_cast<void*>(vector_base_); 09507 | context.end_ptr = reinterpret_cast<void*>(vector_base_ + vector_holder_->size()); 09508 | context.access_ptr = reinterpret_cast<void*>(vector_base_ + index_); 09509 | context.type_size = sizeof(T); 09510 | 09511 | return vec_rt_chk_->handle_runtime_violation(context) ? 09512 | reinterpret_cast<T*>(context.access_ptr) : 09513 | vector_base_ ; 09514 | } 09515 | 09516 | const std::size_t index_; 09517 | vector_holder_ptr vector_holder_; 09518 | T* vector_base_; 09519 | branch_t vector_node_; 09520 | vector_access_runtime_check_ptr vec_rt_chk_; 09521 | }; 09522 | 09523 | template <typename T> 09524 | class vector_initialisation_node exprtk_final : public expression_node<T> 09525 | { 09526 | public: 09527 | 09528 | typedef expression_node<T>* expression_ptr; 09529 | 09530 | vector_initialisation_node(T* vector_base, 09531 | const std::size_t& size, 09532 | const std::vector<expression_ptr>& initialiser_list, 09533 | const bool single_value_initialse) 09534 | : vector_base_(vector_base) 09535 | , initialiser_list_(initialiser_list) 09536 | , size_(size) 09537 | , single_value_initialse_(single_value_initialse) 09538 | , zero_value_initialse_(false) 09539 | , const_nonzero_literal_value_initialse_(false) 09540 | , single_initialiser_value_(T(0)) 09541 | { 09542 | if (single_value_initialse_) 09543 | { 09544 | if (initialiser_list_.empty()) 09545 | zero_value_initialse_ = true; 09546 | else if ( 09547 | (initialiser_list_.size() == 1) && 09548 | details::is_constant_node(initialiser_list_[0]) && 09549 | (T(0) == initialiser_list_[0]->value()) 09550 | ) 09551 | { 09552 | zero_value_initialse_ = true; 09553 | } 09554 | else 09555 | { 09556 | assert(initialiser_list_.size() == 1); 09557 | 09558 | if (details::is_constant_node(initialiser_list_[0])) 09559 | { 09560 | const_nonzero_literal_value_initialse_ = true; 09561 | single_initialiser_value_ = initialiser_list_[0]->value(); 09562 | assert(T(0) != single_initialiser_value_); 09563 | } 09564 | } 09565 | } 09566 | } 09567 | 09568 | inline T value() const exprtk_override 09569 | { 09570 | if (single_value_initialse_) 09571 | { 09572 | if (zero_value_initialse_) 09573 | { 09574 | details::set_zero_value(vector_base_, size_); 09575 | } 09576 | else if (const_nonzero_literal_value_initialse_) 09577 | { 09578 | for (std::size_t i = 0; i < size_; ++i) 09579 | { 09580 | *(vector_base_ + i) = single_initialiser_value_; 09581 | } 09582 | } 09583 | else 09584 | { 09585 | for (std::size_t i = 0; i < size_; ++i) 09586 | { 09587 | *(vector_base_ + i) = initialiser_list_[0]->value(); 09588 | } 09589 | } 09590 | } 09591 | else 09592 | { 09593 | const std::size_t initialiser_list_size = initialiser_list_.size(); 09594 | 09595 | for (std::size_t i = 0; i < initialiser_list_size; ++i) 09596 | { 09597 | *(vector_base_ + i) = initialiser_list_[i]->value(); 09598 | } 09599 | 09600 | if (initialiser_list_size < size_) 09601 | { 09602 | details::set_zero_value( 09603 | vector_base_ + initialiser_list_size, 09604 | (size_ - initialiser_list_size)); 09605 | } 09606 | } 09607 | 09608 | return *(vector_base_); 09609 | } 09610 | 09611 | inline typename expression_node<T>::node_type type() const exprtk_override 09612 | { 09613 | return expression_node<T>::e_vecinit; 09614 | } 09615 | 09616 | inline bool valid() const exprtk_override 09617 | { 09618 | return vector_base_; 09619 | } 09620 | 09621 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09622 | { 09623 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09624 | } 09625 | 09626 | std::size_t node_depth() const exprtk_override 09627 | { 09628 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09629 | } 09630 | 09631 | private: 09632 | 09633 | vector_initialisation_node(const vector_initialisation_node<T>&) exprtk_delete; 09634 | vector_initialisation_node<T>& operator=(const vector_initialisation_node<T>&) exprtk_delete; 09635 | 09636 | mutable T* vector_base_; 09637 | std::vector<expression_ptr> initialiser_list_; 09638 | const std::size_t size_; 09639 | const bool single_value_initialse_; 09640 | bool zero_value_initialse_; 09641 | bool const_nonzero_literal_value_initialse_; 09642 | T single_initialiser_value_; 09643 | }; 09644 | 09645 | template <typename T> 09646 | class vector_init_zero_value_node exprtk_final : public expression_node<T> 09647 | { 09648 | public: 09649 | 09650 | typedef expression_node<T>* expression_ptr; 09651 | 09652 | vector_init_zero_value_node(T* vector_base, 09653 | const std::size_t& size, 09654 | const std::vector<expression_ptr>& initialiser_list) 09655 | : vector_base_(vector_base) 09656 | , size_(size) 09657 | , initialiser_list_(initialiser_list) 09658 | {} 09659 | 09660 | inline T value() const exprtk_override 09661 | { 09662 | details::set_zero_value(vector_base_, size_); 09663 | return *(vector_base_); 09664 | } 09665 | 09666 | inline typename expression_node<T>::node_type type() const exprtk_override 09667 | { 09668 | return expression_node<T>::e_vecinit; 09669 | } 09670 | 09671 | inline bool valid() const exprtk_override 09672 | { 09673 | return vector_base_; 09674 | } 09675 | 09676 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09677 | { 09678 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09679 | } 09680 | 09681 | std::size_t node_depth() const exprtk_override 09682 | { 09683 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09684 | } 09685 | 09686 | private: 09687 | 09688 | vector_init_zero_value_node(const vector_init_zero_value_node<T>&) exprtk_delete; 09689 | vector_init_zero_value_node<T>& operator=(const vector_init_zero_value_node<T>&) exprtk_delete; 09690 | 09691 | mutable T* vector_base_; 09692 | const std::size_t size_; 09693 | std::vector<expression_ptr> initialiser_list_; 09694 | }; 09695 | 09696 | template <typename T> 09697 | class vector_init_single_constvalue_node exprtk_final : public expression_node<T> 09698 | { 09699 | public: 09700 | 09701 | typedef expression_node<T>* expression_ptr; 09702 | 09703 | vector_init_single_constvalue_node(T* vector_base, 09704 | const std::size_t& size, 09705 | const std::vector<expression_ptr>& initialiser_list) 09706 | : vector_base_(vector_base) 09707 | , size_(size) 09708 | , initialiser_list_(initialiser_list) 09709 | { 09710 | single_initialiser_value_ = initialiser_list_[0]->value(); 09711 | assert(valid()); 09712 | } 09713 | 09714 | inline T value() const exprtk_override 09715 | { 09716 | for (std::size_t i = 0; i < size_; ++i) 09717 | { 09718 | *(vector_base_ + i) = single_initialiser_value_; 09719 | } 09720 | 09721 | return *(vector_base_); 09722 | } 09723 | 09724 | inline typename expression_node<T>::node_type type() const exprtk_override 09725 | { 09726 | return expression_node<T>::e_vecinit; 09727 | } 09728 | 09729 | inline bool valid() const exprtk_override 09730 | { 09731 | return vector_base_ && 09732 | (initialiser_list_.size() == 1) && 09733 | (details::is_constant_node(initialiser_list_[0])) && 09734 | (single_initialiser_value_ != T(0)); 09735 | } 09736 | 09737 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09738 | { 09739 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09740 | } 09741 | 09742 | std::size_t node_depth() const exprtk_override 09743 | { 09744 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09745 | } 09746 | 09747 | private: 09748 | 09749 | vector_init_single_constvalue_node(const vector_init_single_constvalue_node<T>&) exprtk_delete; 09750 | vector_init_single_constvalue_node<T>& operator=(const vector_init_single_constvalue_node<T>&) exprtk_delete; 09751 | 09752 | mutable T* vector_base_; 09753 | const std::size_t size_; 09754 | std::vector<expression_ptr> initialiser_list_; 09755 | T single_initialiser_value_; 09756 | }; 09757 | 09758 | template <typename T> 09759 | class vector_init_single_value_node exprtk_final : public expression_node<T> 09760 | { 09761 | public: 09762 | 09763 | typedef expression_node<T>* expression_ptr; 09764 | 09765 | vector_init_single_value_node(T* vector_base, 09766 | const std::size_t& size, 09767 | const std::vector<expression_ptr>& initialiser_list) 09768 | : vector_base_(vector_base) 09769 | , size_(size) 09770 | , initialiser_list_(initialiser_list) 09771 | { 09772 | assert(valid()); 09773 | } 09774 | 09775 | inline T value() const exprtk_override 09776 | { 09777 | expression_node<T>& node = *initialiser_list_[0]; 09778 | 09779 | for (std::size_t i = 0; i < size_; ++i) 09780 | { 09781 | *(vector_base_ + i) = node.value(); 09782 | } 09783 | 09784 | return *(vector_base_); 09785 | } 09786 | 09787 | inline typename expression_node<T>::node_type type() const exprtk_override 09788 | { 09789 | return expression_node<T>::e_vecinit; 09790 | } 09791 | 09792 | inline bool valid() const exprtk_override 09793 | { 09794 | return vector_base_ && 09795 | (initialiser_list_.size() == 1) && 09796 | !details::is_constant_node(initialiser_list_[0]); 09797 | } 09798 | 09799 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09800 | { 09801 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09802 | } 09803 | 09804 | std::size_t node_depth() const exprtk_override 09805 | { 09806 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09807 | } 09808 | 09809 | private: 09810 | 09811 | vector_init_single_value_node(const vector_init_single_value_node<T>&) exprtk_delete; 09812 | vector_init_single_value_node<T>& operator=(const vector_init_single_value_node<T>&) exprtk_delete; 09813 | 09814 | mutable T* vector_base_; 09815 | const std::size_t size_; 09816 | std::vector<expression_ptr> initialiser_list_; 09817 | }; 09818 | 09819 | template <typename T> 09820 | class vector_init_iota_constconst_node exprtk_final : public expression_node<T> 09821 | { 09822 | public: 09823 | 09824 | typedef expression_node<T>* expression_ptr; 09825 | 09826 | vector_init_iota_constconst_node(T* vector_base, 09827 | const std::size_t& size, 09828 | const std::vector<expression_ptr>& initialiser_list) 09829 | : vector_base_(vector_base) 09830 | , size_(size) 09831 | , initialiser_list_(initialiser_list) 09832 | { 09833 | base_value_ = initialiser_list_[0]->value(); 09834 | increment_value_ = initialiser_list_[1]->value(); 09835 | 09836 | assert(valid()); 09837 | } 09838 | 09839 | inline T value() const exprtk_override 09840 | { 09841 | T value = base_value_; 09842 | 09843 | for (std::size_t i = 0; i < size_; ++i, value += increment_value_) 09844 | { 09845 | *(vector_base_ + i) = value; 09846 | } 09847 | 09848 | return *(vector_base_); 09849 | } 09850 | 09851 | inline typename expression_node<T>::node_type type() const exprtk_override 09852 | { 09853 | return expression_node<T>::e_vecinit; 09854 | } 09855 | 09856 | inline bool valid() const exprtk_override 09857 | { 09858 | return vector_base_ && 09859 | (initialiser_list_.size() == 2) && 09860 | (details::is_constant_node(initialiser_list_[0])) && 09861 | (details::is_constant_node(initialiser_list_[1])) ; 09862 | } 09863 | 09864 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09865 | { 09866 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09867 | } 09868 | 09869 | std::size_t node_depth() const exprtk_override 09870 | { 09871 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09872 | } 09873 | 09874 | private: 09875 | 09876 | vector_init_iota_constconst_node(const vector_init_iota_constconst_node<T>&) exprtk_delete; 09877 | vector_init_iota_constconst_node<T>& operator=(const vector_init_iota_constconst_node<T>&) exprtk_delete; 09878 | 09879 | mutable T* vector_base_; 09880 | const std::size_t size_; 09881 | std::vector<expression_ptr> initialiser_list_; 09882 | T base_value_; 09883 | T increment_value_; 09884 | }; 09885 | 09886 | template <typename T> 09887 | class vector_init_iota_constnconst_node exprtk_final : public expression_node<T> 09888 | { 09889 | public: 09890 | 09891 | typedef expression_node<T>* expression_ptr; 09892 | 09893 | vector_init_iota_constnconst_node(T* vector_base, 09894 | const std::size_t& size, 09895 | const std::vector<expression_ptr>& initialiser_list) 09896 | : vector_base_(vector_base) 09897 | , size_(size) 09898 | , initialiser_list_(initialiser_list) 09899 | { 09900 | assert(valid()); 09901 | base_value_ = initialiser_list_[0]->value(); 09902 | } 09903 | 09904 | inline T value() const exprtk_override 09905 | { 09906 | T value = base_value_; 09907 | expression_node<T>& increment = *initialiser_list_[1]; 09908 | 09909 | for (std::size_t i = 0; i < size_; ++i, value += increment.value()) 09910 | { 09911 | *(vector_base_ + i) = value; 09912 | } 09913 | 09914 | return *(vector_base_); 09915 | } 09916 | 09917 | inline typename expression_node<T>::node_type type() const exprtk_override 09918 | { 09919 | return expression_node<T>::e_vecinit; 09920 | } 09921 | 09922 | inline bool valid() const exprtk_override 09923 | { 09924 | return vector_base_ && 09925 | (initialiser_list_.size() == 2) && 09926 | ( details::is_constant_node(initialiser_list_[0])) && 09927 | (!details::is_constant_node(initialiser_list_[1])); 09928 | } 09929 | 09930 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09931 | { 09932 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09933 | } 09934 | 09935 | std::size_t node_depth() const exprtk_override 09936 | { 09937 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09938 | } 09939 | 09940 | private: 09941 | 09942 | vector_init_iota_constnconst_node(const vector_init_iota_constnconst_node<T>&) exprtk_delete; 09943 | vector_init_iota_constnconst_node<T>& operator=(const vector_init_iota_constnconst_node<T>&) exprtk_delete; 09944 | 09945 | mutable T* vector_base_; 09946 | const std::size_t size_; 09947 | std::vector<expression_ptr> initialiser_list_; 09948 | T base_value_; 09949 | }; 09950 | 09951 | template <typename T> 09952 | class vector_init_iota_nconstconst_node exprtk_final : public expression_node<T> 09953 | { 09954 | public: 09955 | 09956 | typedef expression_node<T>* expression_ptr; 09957 | 09958 | vector_init_iota_nconstconst_node(T* vector_base, 09959 | const std::size_t& size, 09960 | const std::vector<expression_ptr>& initialiser_list) 09961 | : vector_base_(vector_base) 09962 | , size_(size) 09963 | , initialiser_list_(initialiser_list) 09964 | { 09965 | assert(valid()); 09966 | } 09967 | 09968 | inline T value() const exprtk_override 09969 | { 09970 | T value = initialiser_list_[0]->value(); 09971 | const T increment = initialiser_list_[1]->value(); 09972 | 09973 | for (std::size_t i = 0; i < size_; ++i, value += increment) 09974 | { 09975 | *(vector_base_ + i) = value; 09976 | } 09977 | 09978 | return *(vector_base_); 09979 | } 09980 | 09981 | inline typename expression_node<T>::node_type type() const exprtk_override 09982 | { 09983 | return expression_node<T>::e_vecinit; 09984 | } 09985 | 09986 | inline bool valid() const exprtk_override 09987 | { 09988 | return vector_base_ && 09989 | (initialiser_list_.size() == 2) && 09990 | (!details::is_constant_node(initialiser_list_[0])) && 09991 | (details::is_constant_node(initialiser_list_[1])); 09992 | } 09993 | 09994 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09995 | { 09996 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09997 | } 09998 | 09999 | std::size_t node_depth() const exprtk_override 10000 | { 10001 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 10002 | } 10003 | 10004 | private: 10005 | 10006 | vector_init_iota_nconstconst_node(const vector_init_iota_nconstconst_node<T>&) exprtk_delete; 10007 | vector_init_iota_nconstconst_node<T>& operator=(const vector_init_iota_nconstconst_node<T>&) exprtk_delete; 10008 | 10009 | mutable T* vector_base_; 10010 | const std::size_t size_; 10011 | std::vector<expression_ptr> initialiser_list_; 10012 | }; 10013 | 10014 | template <typename T> 10015 | class vector_init_iota_nconstnconst_node exprtk_final : public expression_node<T> 10016 | { 10017 | public: 10018 | 10019 | typedef expression_node<T>* expression_ptr; 10020 | 10021 | vector_init_iota_nconstnconst_node(T* vector_base, 10022 | const std::size_t& size, 10023 | const std::vector<expression_ptr>& initialiser_list) 10024 | : vector_base_(vector_base) 10025 | , size_(size) 10026 | , initialiser_list_(initialiser_list) 10027 | { 10028 | assert(valid()); 10029 | } 10030 | 10031 | inline T value() const exprtk_override 10032 | { 10033 | T value = initialiser_list_[0]->value(); 10034 | expression_node<T>& increment = *initialiser_list_[1]; 10035 | 10036 | for (std::size_t i = 0; i < size_; ++i, value += increment.value()) 10037 | { 10038 | *(vector_base_ + i) = value; 10039 | } 10040 | 10041 | return *(vector_base_); 10042 | } 10043 | 10044 | inline typename expression_node<T>::node_type type() const exprtk_override 10045 | { 10046 | return expression_node<T>::e_vecinit; 10047 | } 10048 | 10049 | inline bool valid() const exprtk_override 10050 | { 10051 | return vector_base_ && 10052 | (initialiser_list_.size() == 2) && 10053 | (!details::is_constant_node(initialiser_list_[0])) && 10054 | (!details::is_constant_node(initialiser_list_[1])); 10055 | } 10056 | 10057 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 10058 | { 10059 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 10060 | } 10061 | 10062 | std::size_t node_depth() const exprtk_override 10063 | { 10064 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 10065 | } 10066 | 10067 | private: 10068 | 10069 | vector_init_iota_nconstnconst_node(const vector_init_iota_nconstnconst_node<T>&) exprtk_delete; 10070 | vector_init_iota_nconstnconst_node<T>& operator=(const vector_init_iota_nconstnconst_node<T>&) exprtk_delete; 10071 | 10072 | mutable T* vector_base_; 10073 | const std::size_t size_; 10074 | std::vector<expression_ptr> initialiser_list_; 10075 | }; 10076 | 10077 | template <typename T> 10078 | class swap_node exprtk_final : public expression_node<T> 10079 | { 10080 | public: 10081 | 10082 | typedef expression_node<T>* expression_ptr; 10083 | typedef variable_node<T>* variable_node_ptr; 10084 | 10085 | swap_node(variable_node_ptr var0, variable_node_ptr var1) 10086 | : var0_(var0) 10087 | , var1_(var1) 10088 | {} 10089 | 10090 | inline T value() const exprtk_override 10091 | { 10092 | std::swap(var0_->ref(),var1_->ref()); 10093 | return var1_->ref(); 10094 | } 10095 | 10096 | inline typename expression_node<T>::node_type type() const exprtk_override 10097 | { 10098 | return expression_node<T>::e_swap; 10099 | } 10100 | 10101 | private: 10102 | 10103 | variable_node_ptr var0_; 10104 | variable_node_ptr var1_; 10105 | }; 10106 | 10107 | template <typename T> 10108 | class swap_generic_node exprtk_final : public binary_node<T> 10109 | { 10110 | public: 10111 | 10112 | typedef expression_node<T>* expression_ptr; 10113 | typedef ivariable<T>* ivariable_ptr; 10114 | 10115 | swap_generic_node(expression_ptr var0, expression_ptr var1) 10116 | : binary_node<T>(details::e_swap, var0, var1) 10117 | , var0_(dynamic_cast<ivariable_ptr>(var0)) 10118 | , var1_(dynamic_cast<ivariable_ptr>(var1)) 10119 | {} 10120 | 10121 | inline T value() const exprtk_override 10122 | { 10123 | std::swap(var0_->ref(),var1_->ref()); 10124 | return var1_->ref(); 10125 | } 10126 | 10127 | inline typename expression_node<T>::node_type type() const exprtk_override 10128 | { 10129 | return expression_node<T>::e_swap; 10130 | } 10131 | 10132 | private: 10133 | 10134 | ivariable_ptr var0_; 10135 | ivariable_ptr var1_; 10136 | }; 10137 | 10138 | template <typename T> 10139 | class swap_vecvec_node exprtk_final 10140 | : public binary_node <T> 10141 | , public vector_interface<T> 10142 | { 10143 | public: 10144 | 10145 | typedef expression_node<T>* expression_ptr; 10146 | typedef vector_node <T>* vector_node_ptr; 10147 | typedef vec_data_store <T> vds_t; 10148 | 10149 | using binary_node<T>::branch; 10150 | 10151 | swap_vecvec_node(expression_ptr branch0, 10152 | expression_ptr branch1) 10153 | : binary_node<T>(details::e_swap, branch0, branch1) 10154 | , vec0_node_ptr_(0) 10155 | , vec1_node_ptr_(0) 10156 | , initialised_ (false) 10157 | { 10158 | if (is_ivector_node(branch(0))) 10159 | { 10160 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 10161 | 10162 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(0)))) 10163 | { 10164 | vec0_node_ptr_ = vi->vec(); 10165 | vds() = vi->vds(); 10166 | } 10167 | } 10168 | 10169 | if (is_ivector_node(branch(1))) 10170 | { 10171 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 10172 | 10173 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1)))) 10174 | { 10175 | vec1_node_ptr_ = vi->vec(); 10176 | } 10177 | } 10178 | 10179 | if (vec0_node_ptr_ && vec1_node_ptr_) 10180 | { 10181 | initialised_ = size() <= base_size(); 10182 | } 10183 | 10184 | assert(valid()); 10185 | } 10186 | 10187 | inline T value() const exprtk_override 10188 | { 10189 | binary_node<T>::branch(0)->value(); 10190 | binary_node<T>::branch(1)->value(); 10191 | 10192 | T* vec0 = vec0_node_ptr_->vds().data(); 10193 | T* vec1 = vec1_node_ptr_->vds().data(); 10194 | 10195 | assert(size() <= base_size()); 10196 | const std::size_t n = size(); 10197 | 10198 | for (std::size_t i = 0; i < n; ++i) 10199 | { 10200 | std::swap(vec0[i],vec1[i]); 10201 | } 10202 | 10203 | return vec1_node_ptr_->value(); 10204 | } 10205 | 10206 | vector_node_ptr vec() const exprtk_override 10207 | { 10208 | return vec0_node_ptr_; 10209 | } 10210 | 10211 | vector_node_ptr vec() exprtk_override 10212 | { 10213 | return vec0_node_ptr_; 10214 | } 10215 | 10216 | inline typename expression_node<T>::node_type type() const exprtk_override 10217 | { 10218 | return expression_node<T>::e_vecvecswap; 10219 | } 10220 | 10221 | inline bool valid() const exprtk_override 10222 | { 10223 | return initialised_ && binary_node<T>::valid(); 10224 | } 10225 | 10226 | std::size_t size() const exprtk_override 10227 | { 10228 | return std::min( 10229 | vec0_node_ptr_->vec_holder().size(), 10230 | vec1_node_ptr_->vec_holder().size()); 10231 | } 10232 | 10233 | std::size_t base_size() const exprtk_override 10234 | { 10235 | return std::min( 10236 | vec0_node_ptr_->vec_holder().base_size(), 10237 | vec1_node_ptr_->vec_holder().base_size()); 10238 | } 10239 | 10240 | vds_t& vds() exprtk_override 10241 | { 10242 | return vds_; 10243 | } 10244 | 10245 | const vds_t& vds() const exprtk_override 10246 | { 10247 | return vds_; 10248 | } 10249 | 10250 | private: 10251 | 10252 | vector_node<T>* vec0_node_ptr_; 10253 | vector_node<T>* vec1_node_ptr_; 10254 | bool initialised_; 10255 | vds_t vds_; 10256 | }; 10257 | 10258 | #ifndef exprtk_disable_string_capabilities 10259 | template <typename T> 10260 | class stringvar_node exprtk_final 10261 | : public expression_node <T> 10262 | , public string_base_node<T> 10263 | , public range_interface <T> 10264 | { 10265 | public: 10266 | 10267 | typedef typename range_interface<T>::range_t range_t; 10268 | 10269 | static std::string null_value; 10270 | 10271 | explicit stringvar_node() 10272 | : value_(&null_value) 10273 | {} 10274 | 10275 | explicit stringvar_node(std::string& v) 10276 | : value_(&v) 10277 | { 10278 | rp_.n0_c = std::make_pair<bool,std::size_t>(true,0); 10279 | rp_.n1_c = std::make_pair<bool,std::size_t>(true,v.size()); 10280 | rp_.cache.first = rp_.n0_c.second; 10281 | rp_.cache.second = rp_.n1_c.second; 10282 | } 10283 | 10284 | inline bool operator <(const stringvar_node<T>& v) const 10285 | { 10286 | return this < (&v); 10287 | } 10288 | 10289 | inline T value() const exprtk_override 10290 | { 10291 | rp_.n1_c.second = (*value_).size(); 10292 | rp_.cache.second = rp_.n1_c.second; 10293 | 10294 | return std::numeric_limits<T>::quiet_NaN(); 10295 | } 10296 | 10297 | std::string str() const exprtk_override 10298 | { 10299 | return ref(); 10300 | } 10301 | 10302 | char_cptr base() const exprtk_override 10303 | { 10304 | return &(*value_)[0]; 10305 | } 10306 | 10307 | std::size_t size() const exprtk_override 10308 | { 10309 | return ref().size(); 10310 | } 10311 | 10312 | std::string& ref() 10313 | { 10314 | return (*value_); 10315 | } 10316 | 10317 | const std::string& ref() const 10318 | { 10319 | return (*value_); 10320 | } 10321 | 10322 | range_t& range_ref() exprtk_override 10323 | { 10324 | return rp_; 10325 | } 10326 | 10327 | const range_t& range_ref() const exprtk_override 10328 | { 10329 | return rp_; 10330 | } 10331 | 10332 | inline typename expression_node<T>::node_type type() const exprtk_override 10333 | { 10334 | return expression_node<T>::e_stringvar; 10335 | } 10336 | 10337 | void rebase(std::string& s) 10338 | { 10339 | value_ = &s; 10340 | rp_.n0_c = std::make_pair<bool,std::size_t>(true,0); 10341 | rp_.n1_c = std::make_pair<bool,std::size_t>(true,value_->size() - 1); 10342 | rp_.cache.first = rp_.n0_c.second; 10343 | rp_.cache.second = rp_.n1_c.second; 10344 | } 10345 | 10346 | private: 10347 | 10348 | std::string* value_; 10349 | mutable range_t rp_; 10350 | }; 10351 | 10352 | template <typename T> 10353 | std::string stringvar_node<T>::null_value = std::string(""); 10354 | 10355 | template <typename T> 10356 | class string_range_node exprtk_final 10357 | : public expression_node <T> 10358 | , public string_base_node<T> 10359 | , public range_interface <T> 10360 | { 10361 | public: 10362 | 10363 | typedef typename range_interface<T>::range_t range_t; 10364 | 10365 | static std::string null_value; 10366 | 10367 | explicit string_range_node(std::string& v, const range_t& rp) 10368 | : value_(&v) 10369 | , rp_(rp) 10370 | {} 10371 | 10372 | virtual ~string_range_node() 10373 | { 10374 | rp_.free(); 10375 | } 10376 | 10377 | inline bool operator <(const string_range_node<T>& v) const 10378 | { 10379 | return this < (&v); 10380 | } 10381 | 10382 | inline T value() const exprtk_override 10383 | { 10384 | return std::numeric_limits<T>::quiet_NaN(); 10385 | } 10386 | 10387 | inline std::string str() const exprtk_override 10388 | { 10389 | return (*value_); 10390 | } 10391 | 10392 | char_cptr base() const exprtk_override 10393 | { 10394 | return &(*value_)[0]; 10395 | } 10396 | 10397 | std::size_t size() const exprtk_override 10398 | { 10399 | return ref().size(); 10400 | } 10401 | 10402 | inline range_t range() const 10403 | { 10404 | return rp_; 10405 | } 10406 | 10407 | inline std::string& ref() 10408 | { 10409 | return (*value_); 10410 | } 10411 | 10412 | inline const std::string& ref() const 10413 | { 10414 | return (*value_); 10415 | } 10416 | 10417 | inline range_t& range_ref() exprtk_override 10418 | { 10419 | return rp_; 10420 | } 10421 | 10422 | inline const range_t& range_ref() const exprtk_override 10423 | { 10424 | return rp_; 10425 | } 10426 | 10427 | inline typename expression_node<T>::node_type type() const exprtk_override 10428 | { 10429 | return expression_node<T>::e_stringvarrng; 10430 | } 10431 | 10432 | private: 10433 | 10434 | std::string* value_; 10435 | range_t rp_; 10436 | }; 10437 | 10438 | template <typename T> 10439 | std::string string_range_node<T>::null_value = std::string(""); 10440 | 10441 | template <typename T> 10442 | class const_string_range_node exprtk_final 10443 | : public expression_node <T> 10444 | , public string_base_node<T> 10445 | , public range_interface <T> 10446 | { 10447 | public: 10448 | 10449 | typedef typename range_interface<T>::range_t range_t; 10450 | 10451 | explicit const_string_range_node(const std::string& v, const range_t& rp) 10452 | : value_(v) 10453 | , rp_(rp) 10454 | {} 10455 | 10456 | ~const_string_range_node() exprtk_override 10457 | { 10458 | rp_.free(); 10459 | } 10460 | 10461 | inline T value() const exprtk_override 10462 | { 10463 | return std::numeric_limits<T>::quiet_NaN(); 10464 | } 10465 | 10466 | std::string str() const exprtk_override 10467 | { 10468 | return value_; 10469 | } 10470 | 10471 | char_cptr base() const exprtk_override 10472 | { 10473 | return value_.data(); 10474 | } 10475 | 10476 | std::size_t size() const exprtk_override 10477 | { 10478 | return value_.size(); 10479 | } 10480 | 10481 | range_t range() const 10482 | { 10483 | return rp_; 10484 | } 10485 | 10486 | range_t& range_ref() exprtk_override 10487 | { 10488 | return rp_; 10489 | } 10490 | 10491 | const range_t& range_ref() const exprtk_override 10492 | { 10493 | return rp_; 10494 | } 10495 | 10496 | inline typename expression_node<T>::node_type type() const exprtk_override 10497 | { 10498 | return expression_node<T>::e_cstringvarrng; 10499 | } 10500 | 10501 | private: 10502 | 10503 | const_string_range_node(const const_string_range_node<T>&) exprtk_delete; 10504 | const_string_range_node<T>& operator=(const const_string_range_node<T>&) exprtk_delete; 10505 | 10506 | const std::string value_; 10507 | range_t rp_; 10508 | }; 10509 | 10510 | template <typename T> 10511 | class generic_string_range_node exprtk_final 10512 | : public expression_node <T> 10513 | , public string_base_node<T> 10514 | , public range_interface <T> 10515 | { 10516 | public: 10517 | 10518 | typedef expression_node <T>* expression_ptr; 10519 | typedef stringvar_node <T>* strvar_node_ptr; 10520 | typedef string_base_node<T>* str_base_ptr; 10521 | typedef typename range_interface<T>::range_t range_t; 10522 | typedef range_t* range_ptr; 10523 | typedef range_interface<T> irange_t; 10524 | typedef irange_t* irange_ptr; 10525 | typedef std::pair<expression_ptr,bool> branch_t; 10526 | 10527 | generic_string_range_node(expression_ptr str_branch, const range_t& brange) 10528 | : initialised_(false) 10529 | , str_base_ptr_ (0) 10530 | , str_range_ptr_(0) 10531 | , base_range_(brange) 10532 | { 10533 | range_.n0_c = std::make_pair<bool,std::size_t>(true,0); 10534 | range_.n1_c = std::make_pair<bool,std::size_t>(true,0); 10535 | range_.cache.first = range_.n0_c.second; 10536 | range_.cache.second = range_.n1_c.second; 10537 | 10538 | construct_branch_pair(branch_, str_branch); 10539 | 10540 | if (is_generally_string_node(branch_.first)) 10541 | { 10542 | str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_.first); 10543 | 10544 | if (0 == str_base_ptr_) 10545 | return; 10546 | 10547 | str_range_ptr_ = dynamic_cast<irange_ptr>(branch_.first); 10548 | 10549 | if (0 == str_range_ptr_) 10550 | return; 10551 | } 10552 | 10553 | initialised_ = (str_base_ptr_ && str_range_ptr_); 10554 | assert(valid()); 10555 | } 10556 | 10557 | ~generic_string_range_node() exprtk_override 10558 | { 10559 | base_range_.free(); 10560 | } 10561 | 10562 | inline T value() const exprtk_override 10563 | { 10564 | branch_.first->value(); 10565 | 10566 | std::size_t str_r0 = 0; 10567 | std::size_t str_r1 = 0; 10568 | 10569 | std::size_t r0 = 0; 10570 | std::size_t r1 = 0; 10571 | 10572 | const range_t& range = str_range_ptr_->range_ref(); 10573 | 10574 | const std::size_t base_str_size = str_base_ptr_->size(); 10575 | 10576 | if ( 10577 | range (str_r0, str_r1, base_str_size ) && 10578 | base_range_(r0 , r1 , base_str_size - str_r0) 10579 | ) 10580 | { 10581 | const std::size_t size = r1 - r0; 10582 | 10583 | range_.n1_c.second = size; 10584 | range_.cache.second = range_.n1_c.second; 10585 | 10586 | value_.assign(str_base_ptr_->base() + str_r0 + r0, size); 10587 | } 10588 | 10589 | return std::numeric_limits<T>::quiet_NaN(); 10590 | } 10591 | 10592 | std::string str() const exprtk_override 10593 | { 10594 | return value_; 10595 | } 10596 | 10597 | char_cptr base() const exprtk_override 10598 | { 10599 | return &value_[0]; 10600 | } 10601 | 10602 | std::size_t size() const exprtk_override 10603 | { 10604 | return value_.size(); 10605 | } 10606 | 10607 | range_t& range_ref() exprtk_override 10608 | { 10609 | return range_; 10610 | } 10611 | 10612 | const range_t& range_ref() const exprtk_override 10613 | { 10614 | return range_; 10615 | } 10616 | 10617 | inline typename expression_node<T>::node_type type() const exprtk_override 10618 | { 10619 | return expression_node<T>::e_strgenrange; 10620 | } 10621 | 10622 | inline bool valid() const exprtk_override 10623 | { 10624 | return initialised_ && branch_.first; 10625 | } 10626 | 10627 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 10628 | { 10629 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 10630 | } 10631 | 10632 | std::size_t node_depth() const exprtk_override 10633 | { 10634 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 10635 | } 10636 | 10637 | private: 10638 | 10639 | bool initialised_; 10640 | branch_t branch_; 10641 | str_base_ptr str_base_ptr_; 10642 | irange_ptr str_range_ptr_; 10643 | mutable range_t base_range_; 10644 | mutable range_t range_; 10645 | mutable std::string value_; 10646 | }; 10647 | 10648 | template <typename T> 10649 | class string_concat_node exprtk_final 10650 | : public binary_node <T> 10651 | , public string_base_node<T> 10652 | , public range_interface <T> 10653 | { 10654 | public: 10655 | 10656 | typedef typename range_interface<T>::range_t range_t; 10657 | typedef range_interface<T> irange_t; 10658 | typedef irange_t* irange_ptr; 10659 | typedef range_t* range_ptr; 10660 | typedef expression_node <T>* expression_ptr; 10661 | typedef string_base_node<T>* str_base_ptr; 10662 | 10663 | using binary_node<T>::branch; 10664 | 10665 | string_concat_node(const operator_type& opr, 10666 | expression_ptr branch0, 10667 | expression_ptr branch1) 10668 | : binary_node<T>(opr, branch0, branch1) 10669 | , initialised_(false) 10670 | , str0_base_ptr_ (0) 10671 | , str1_base_ptr_ (0) 10672 | , str0_range_ptr_(0) 10673 | , str1_range_ptr_(0) 10674 | { 10675 | range_.n0_c = std::make_pair<bool,std::size_t>(true,0); 10676 | range_.n1_c = std::make_pair<bool,std::size_t>(true,0); 10677 | 10678 | range_.cache.first = range_.n0_c.second; 10679 | range_.cache.second = range_.n1_c.second; 10680 | 10681 | if (is_generally_string_node(branch(0))) 10682 | { 10683 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0)); 10684 | 10685 | if (0 == str0_base_ptr_) 10686 | return; 10687 | 10688 | str0_range_ptr_ = dynamic_cast<irange_ptr>(branch(0)); 10689 | 10690 | if (0 == str0_range_ptr_) 10691 | return; 10692 | } 10693 | 10694 | if (is_generally_string_node(branch(1))) 10695 | { 10696 | str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1)); 10697 | 10698 | if (0 == str1_base_ptr_) 10699 | return; 10700 | 10701 | str1_range_ptr_ = dynamic_cast<irange_ptr>(branch(1)); 10702 | 10703 | if (0 == str1_range_ptr_) 10704 | return; 10705 | } 10706 | 10707 | initialised_ = str0_base_ptr_ && 10708 | str1_base_ptr_ && 10709 | str0_range_ptr_ && 10710 | str1_range_ptr_ ; 10711 | 10712 | assert(valid()); 10713 | } 10714 | 10715 | inline T value() const exprtk_override 10716 | { 10717 | branch(0)->value(); 10718 | branch(1)->value(); 10719 | 10720 | std::size_t str0_r0 = 0; 10721 | std::size_t str0_r1 = 0; 10722 | 10723 | std::size_t str1_r0 = 0; 10724 | std::size_t str1_r1 = 0; 10725 | 10726 | const range_t& range0 = str0_range_ptr_->range_ref(); 10727 | const range_t& range1 = str1_range_ptr_->range_ref(); 10728 | 10729 | if ( 10730 | range0(str0_r0, str0_r1, str0_base_ptr_->size()) && 10731 | range1(str1_r0, str1_r1, str1_base_ptr_->size()) 10732 | ) 10733 | { 10734 | const std::size_t size0 = (str0_r1 - str0_r0); 10735 | const std::size_t size1 = (str1_r1 - str1_r0); 10736 | 10737 | value_.assign(str0_base_ptr_->base() + str0_r0, size0); 10738 | value_.append(str1_base_ptr_->base() + str1_r0, size1); 10739 | 10740 | range_.n1_c.second = value_.size(); 10741 | range_.cache.second = range_.n1_c.second; 10742 | } 10743 | 10744 | return std::numeric_limits<T>::quiet_NaN(); 10745 | } 10746 | 10747 | std::string str() const exprtk_override 10748 | { 10749 | return value_; 10750 | } 10751 | 10752 | char_cptr base() const exprtk_override 10753 | { 10754 | return &value_[0]; 10755 | } 10756 | 10757 | std::size_t size() const exprtk_override 10758 | { 10759 | return value_.size(); 10760 | } 10761 | 10762 | range_t& range_ref() exprtk_override 10763 | { 10764 | return range_; 10765 | } 10766 | 10767 | const range_t& range_ref() const exprtk_override 10768 | { 10769 | return range_; 10770 | } 10771 | 10772 | inline typename expression_node<T>::node_type type() const exprtk_override 10773 | { 10774 | return expression_node<T>::e_strconcat; 10775 | } 10776 | 10777 | inline bool valid() const exprtk_override 10778 | { 10779 | return initialised_ && binary_node<T>::valid(); 10780 | } 10781 | 10782 | private: 10783 | 10784 | bool initialised_; 10785 | str_base_ptr str0_base_ptr_; 10786 | str_base_ptr str1_base_ptr_; 10787 | irange_ptr str0_range_ptr_; 10788 | irange_ptr str1_range_ptr_; 10789 | mutable range_t range_; 10790 | mutable std::string value_; 10791 | }; 10792 | 10793 | template <typename T> 10794 | class swap_string_node exprtk_final 10795 | : public binary_node <T> 10796 | , public string_base_node<T> 10797 | , public range_interface <T> 10798 | { 10799 | public: 10800 | 10801 | typedef typename range_interface<T>::range_t range_t; 10802 | typedef range_t* range_ptr; 10803 | typedef range_interface<T> irange_t; 10804 | typedef irange_t* irange_ptr; 10805 | typedef expression_node <T>* expression_ptr; 10806 | typedef stringvar_node <T>* strvar_node_ptr; 10807 | typedef string_base_node<T>* str_base_ptr; 10808 | 10809 | using binary_node<T>::branch; 10810 | 10811 | swap_string_node(expression_ptr branch0, expression_ptr branch1) 10812 | : binary_node<T>(details::e_swap, branch0, branch1) 10813 | , initialised_(false) 10814 | , str0_node_ptr_(0) 10815 | , str1_node_ptr_(0) 10816 | { 10817 | if (is_string_node(branch(0))) 10818 | { 10819 | str0_node_ptr_ = static_cast<strvar_node_ptr>(branch(0)); 10820 | } 10821 | 10822 | if (is_string_node(branch(1))) 10823 | { 10824 | str1_node_ptr_ = static_cast<strvar_node_ptr>(branch(1)); 10825 | } 10826 | 10827 | initialised_ = (str0_node_ptr_ && str1_node_ptr_); 10828 | assert(valid()); 10829 | } 10830 | 10831 | inline T value() const exprtk_override 10832 | { 10833 | branch(0)->value(); 10834 | branch(1)->value(); 10835 | 10836 | std::swap(str0_node_ptr_->ref(), str1_node_ptr_->ref()); 10837 | 10838 | return std::numeric_limits<T>::quiet_NaN(); 10839 | } 10840 | 10841 | std::string str() const exprtk_override 10842 | { 10843 | return str0_node_ptr_->str(); 10844 | } 10845 | 10846 | char_cptr base() const exprtk_override 10847 | { 10848 | return str0_node_ptr_->base(); 10849 | } 10850 | 10851 | std::size_t size() const exprtk_override 10852 | { 10853 | return str0_node_ptr_->size(); 10854 | } 10855 | 10856 | range_t& range_ref() exprtk_override 10857 | { 10858 | return str0_node_ptr_->range_ref(); 10859 | } 10860 | 10861 | const range_t& range_ref() const exprtk_override 10862 | { 10863 | return str0_node_ptr_->range_ref(); 10864 | } 10865 | 10866 | inline typename expression_node<T>::node_type type() const exprtk_override 10867 | { 10868 | return expression_node<T>::e_strswap; 10869 | } 10870 | 10871 | inline bool valid() const exprtk_override 10872 | { 10873 | return initialised_ && binary_node<T>::valid(); 10874 | } 10875 | 10876 | private: 10877 | 10878 | bool initialised_; 10879 | strvar_node_ptr str0_node_ptr_; 10880 | strvar_node_ptr str1_node_ptr_; 10881 | }; 10882 | 10883 | template <typename T> 10884 | class swap_genstrings_node exprtk_final : public binary_node<T> 10885 | { 10886 | public: 10887 | 10888 | typedef typename range_interface<T>::range_t range_t; 10889 | typedef range_t* range_ptr; 10890 | typedef range_interface<T> irange_t; 10891 | typedef irange_t* irange_ptr; 10892 | typedef expression_node <T>* expression_ptr; 10893 | typedef string_base_node<T>* str_base_ptr; 10894 | 10895 | using binary_node<T>::branch; 10896 | 10897 | swap_genstrings_node(expression_ptr branch0, 10898 | expression_ptr branch1) 10899 | : binary_node<T>(details::e_default, branch0, branch1) 10900 | , str0_base_ptr_ (0) 10901 | , str1_base_ptr_ (0) 10902 | , str0_range_ptr_(0) 10903 | , str1_range_ptr_(0) 10904 | , initialised_(false) 10905 | { 10906 | if (is_generally_string_node(branch(0))) 10907 | { 10908 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0)); 10909 | 10910 | if (0 == str0_base_ptr_) 10911 | return; 10912 | 10913 | irange_ptr range = dynamic_cast<irange_ptr>(branch(0)); 10914 | 10915 | if (0 == range) 10916 | return; 10917 | 10918 | str0_range_ptr_ = &(range->range_ref()); 10919 | } 10920 | 10921 | if (is_generally_string_node(branch(1))) 10922 | { 10923 | str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1)); 10924 | 10925 | if (0 == str1_base_ptr_) 10926 | return; 10927 | 10928 | irange_ptr range = dynamic_cast<irange_ptr>(branch(1)); 10929 | 10930 | if (0 == range) 10931 | return; 10932 | 10933 | str1_range_ptr_ = &(range->range_ref()); 10934 | } 10935 | 10936 | initialised_ = str0_base_ptr_ && 10937 | str1_base_ptr_ && 10938 | str0_range_ptr_ && 10939 | str1_range_ptr_ ; 10940 | 10941 | assert(valid()); 10942 | } 10943 | 10944 | inline T value() const exprtk_override 10945 | { 10946 | branch(0)->value(); 10947 | branch(1)->value(); 10948 | 10949 | std::size_t str0_r0 = 0; 10950 | std::size_t str0_r1 = 0; 10951 | 10952 | std::size_t str1_r0 = 0; 10953 | std::size_t str1_r1 = 0; 10954 | 10955 | const range_t& range0 = (*str0_range_ptr_); 10956 | const range_t& range1 = (*str1_range_ptr_); 10957 | 10958 | if ( 10959 | range0(str0_r0, str0_r1, str0_base_ptr_->size()) && 10960 | range1(str1_r0, str1_r1, str1_base_ptr_->size()) 10961 | ) 10962 | { 10963 | const std::size_t size0 = range0.cache_size(); 10964 | const std::size_t size1 = range1.cache_size(); 10965 | const std::size_t max_size = std::min(size0,size1); 10966 | 10967 | char_ptr s0 = const_cast<char_ptr>(str0_base_ptr_->base() + str0_r0); 10968 | char_ptr s1 = const_cast<char_ptr>(str1_base_ptr_->base() + str1_r0); 10969 | 10970 | loop_unroll::details lud(max_size); 10971 | char_cptr upper_bound = s0 + lud.upper_bound; 10972 | 10973 | while (s0 < upper_bound) 10974 | { 10975 | #define exprtk_loop(N) \ 10976 | std::swap(s0[N], s1[N]); \ 10977 | 10978 | exprtk_loop( 0) exprtk_loop( 1) 10979 | exprtk_loop( 2) exprtk_loop( 3) 10980 | #ifndef exprtk_disable_superscalar_unroll 10981 | exprtk_loop( 4) exprtk_loop( 5) 10982 | exprtk_loop( 6) exprtk_loop( 7) 10983 | exprtk_loop( 8) exprtk_loop( 9) 10984 | exprtk_loop(10) exprtk_loop(11) 10985 | exprtk_loop(12) exprtk_loop(13) 10986 | exprtk_loop(14) exprtk_loop(15) 10987 | #endif 10988 | 10989 | s0 += lud.batch_size; 10990 | s1 += lud.batch_size; 10991 | } 10992 | 10993 | int i = 0; 10994 | 10995 | switch (lud.remainder) 10996 | { 10997 | #define case_stmt(N) \ 10998 | case N : { std::swap(s0[i], s1[i]); ++i; } \ 10999 | exprtk_fallthrough \ 11000 | 11001 | #ifndef exprtk_disable_superscalar_unroll 11002 | case_stmt(15) case_stmt(14) 11003 | case_stmt(13) case_stmt(12) 11004 | case_stmt(11) case_stmt(10) 11005 | case_stmt( 9) case_stmt( 8) 11006 | case_stmt( 7) case_stmt( 6) 11007 | case_stmt( 5) case_stmt( 4) 11008 | #endif 11009 | case_stmt( 3) case_stmt( 2) 11010 | case_stmt( 1) 11011 | default: break; 11012 | } 11013 | 11014 | #undef exprtk_loop 11015 | #undef case_stmt 11016 | } 11017 | 11018 | return std::numeric_limits<T>::quiet_NaN(); 11019 | } 11020 | 11021 | inline typename expression_node<T>::node_type type() const exprtk_override 11022 | { 11023 | return expression_node<T>::e_strswap; 11024 | } 11025 | 11026 | inline bool valid() const exprtk_override 11027 | { 11028 | return initialised_ && binary_node<T>::valid(); 11029 | } 11030 | 11031 | private: 11032 | 11033 | swap_genstrings_node(const swap_genstrings_node<T>&) exprtk_delete; 11034 | swap_genstrings_node<T>& operator=(const swap_genstrings_node<T>&) exprtk_delete; 11035 | 11036 | str_base_ptr str0_base_ptr_; 11037 | str_base_ptr str1_base_ptr_; 11038 | range_ptr str0_range_ptr_; 11039 | range_ptr str1_range_ptr_; 11040 | bool initialised_; 11041 | }; 11042 | 11043 | template <typename T> 11044 | class stringvar_size_node exprtk_final : public expression_node<T> 11045 | { 11046 | public: 11047 | 11048 | static const std::string null_value; 11049 | 11050 | explicit stringvar_size_node() 11051 | : value_(&null_value) 11052 | {} 11053 | 11054 | explicit stringvar_size_node(std::string& v) 11055 | : value_(&v) 11056 | {} 11057 | 11058 | inline T value() const exprtk_override 11059 | { 11060 | return T((*value_).size()); 11061 | } 11062 | 11063 | inline typename expression_node<T>::node_type type() const exprtk_override 11064 | { 11065 | return expression_node<T>::e_stringvarsize; 11066 | } 11067 | 11068 | private: 11069 | 11070 | const std::string* value_; 11071 | }; 11072 | 11073 | template <typename T> 11074 | const std::string stringvar_size_node<T>::null_value = std::string(""); 11075 | 11076 | template <typename T> 11077 | class string_size_node exprtk_final : public expression_node<T> 11078 | { 11079 | public: 11080 | 11081 | typedef expression_node <T>* expression_ptr; 11082 | typedef string_base_node<T>* str_base_ptr; 11083 | typedef std::pair<expression_ptr,bool> branch_t; 11084 | 11085 | explicit string_size_node(expression_ptr branch) 11086 | : str_base_ptr_(0) 11087 | { 11088 | construct_branch_pair(branch_, branch); 11089 | 11090 | if (is_generally_string_node(branch_.first)) 11091 | { 11092 | str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_.first); 11093 | } 11094 | 11095 | assert(valid()); 11096 | } 11097 | 11098 | inline T value() const exprtk_override 11099 | { 11100 | branch_.first->value(); 11101 | return T(str_base_ptr_->size()); 11102 | } 11103 | 11104 | inline typename expression_node<T>::node_type type() const exprtk_override 11105 | { 11106 | return expression_node<T>::e_stringsize; 11107 | } 11108 | 11109 | inline bool valid() const exprtk_override 11110 | { 11111 | return str_base_ptr_; 11112 | } 11113 | 11114 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 11115 | { 11116 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 11117 | } 11118 | 11119 | std::size_t node_depth() const exprtk_override 11120 | { 11121 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 11122 | } 11123 | 11124 | private: 11125 | 11126 | branch_t branch_; 11127 | str_base_ptr str_base_ptr_; 11128 | }; 11129 | 11130 | struct asn_assignment 11131 | { 11132 | static inline void execute(std::string& s, char_cptr data, const std::size_t size) 11133 | { s.assign(data,size); } 11134 | }; 11135 | 11136 | struct asn_addassignment 11137 | { 11138 | static inline void execute(std::string& s, char_cptr data, const std::size_t size) 11139 | { s.append(data,size); } 11140 | }; 11141 | 11142 | template <typename T, typename AssignmentProcess = asn_assignment> 11143 | class assignment_string_node exprtk_final 11144 | : public binary_node <T> 11145 | , public string_base_node<T> 11146 | , public range_interface <T> 11147 | { 11148 | public: 11149 | 11150 | typedef typename range_interface<T>::range_t range_t; 11151 | typedef range_t* range_ptr; 11152 | typedef range_interface <T> irange_t; 11153 | typedef irange_t* irange_ptr; 11154 | typedef expression_node <T>* expression_ptr; 11155 | typedef stringvar_node <T>* strvar_node_ptr; 11156 | typedef string_base_node<T>* str_base_ptr; 11157 | 11158 | using binary_node<T>::branch; 11159 | 11160 | assignment_string_node(const operator_type& opr, 11161 | expression_ptr branch0, 11162 | expression_ptr branch1) 11163 | : binary_node<T>(opr, branch0, branch1) 11164 | , initialised_(false) 11165 | , str0_base_ptr_ (0) 11166 | , str1_base_ptr_ (0) 11167 | , str0_node_ptr_ (0) 11168 | , str1_range_ptr_(0) 11169 | { 11170 | if (is_string_node(branch(0))) 11171 | { 11172 | str0_node_ptr_ = static_cast<strvar_node_ptr>(branch(0)); 11173 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0)); 11174 | } 11175 | 11176 | if (is_generally_string_node(branch(1))) 11177 | { 11178 | str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1)); 11179 | 11180 | if (0 == str1_base_ptr_) 11181 | return; 11182 | 11183 | irange_ptr range = dynamic_cast<irange_ptr>(branch(1)); 11184 | 11185 | if (0 == range) 11186 | return; 11187 | 11188 | str1_range_ptr_ = &(range->range_ref()); 11189 | } 11190 | 11191 | initialised_ = str0_base_ptr_ && 11192 | str1_base_ptr_ && 11193 | str0_node_ptr_ && 11194 | str1_range_ptr_ ; 11195 | 11196 | assert(valid()); 11197 | } 11198 | 11199 | inline T value() const exprtk_override 11200 | { 11201 | branch(1)->value(); 11202 | 11203 | std::size_t r0 = 0; 11204 | std::size_t r1 = 0; 11205 | 11206 | const range_t& range = (*str1_range_ptr_); 11207 | 11208 | if (range(r0, r1, str1_base_ptr_->size())) 11209 | { 11210 | AssignmentProcess::execute( 11211 | str0_node_ptr_->ref(), 11212 | str1_base_ptr_->base() + r0, (r1 - r0)); 11213 | 11214 | branch(0)->value(); 11215 | } 11216 | 11217 | return std::numeric_limits<T>::quiet_NaN(); 11218 | } 11219 | 11220 | std::string str() const exprtk_override 11221 | { 11222 | return str0_node_ptr_->str(); 11223 | } 11224 | 11225 | char_cptr base() const exprtk_override 11226 | { 11227 | return str0_node_ptr_->base(); 11228 | } 11229 | 11230 | std::size_t size() const exprtk_override 11231 | { 11232 | return str0_node_ptr_->size(); 11233 | } 11234 | 11235 | range_t& range_ref() exprtk_override 11236 | { 11237 | return str0_node_ptr_->range_ref(); 11238 | } 11239 | 11240 | const range_t& range_ref() const exprtk_override 11241 | { 11242 | return str0_node_ptr_->range_ref(); 11243 | } 11244 | 11245 | inline typename expression_node<T>::node_type type() const exprtk_override 11246 | { 11247 | return expression_node<T>::e_strass; 11248 | } 11249 | 11250 | inline bool valid() const exprtk_override 11251 | { 11252 | return initialised_ && binary_node<T>::valid(); 11253 | } 11254 | 11255 | private: 11256 | 11257 | bool initialised_; 11258 | str_base_ptr str0_base_ptr_; 11259 | str_base_ptr str1_base_ptr_; 11260 | strvar_node_ptr str0_node_ptr_; 11261 | range_ptr str1_range_ptr_; 11262 | }; 11263 | 11264 | template <typename T, typename AssignmentProcess = asn_assignment> 11265 | class assignment_string_range_node exprtk_final 11266 | : public binary_node <T> 11267 | , public string_base_node<T> 11268 | , public range_interface <T> 11269 | { 11270 | public: 11271 | 11272 | typedef typename range_interface<T>::range_t range_t; 11273 | typedef range_t* range_ptr; 11274 | typedef range_interface <T> irange_t; 11275 | typedef irange_t* irange_ptr; 11276 | typedef expression_node <T>* expression_ptr; 11277 | typedef stringvar_node <T>* strvar_node_ptr; 11278 | typedef string_range_node<T>* str_rng_node_ptr; 11279 | typedef string_base_node <T>* str_base_ptr; 11280 | 11281 | using binary_node<T>::branch; 11282 | 11283 | assignment_string_range_node(const operator_type& opr, 11284 | expression_ptr branch0, 11285 | expression_ptr branch1) 11286 | : binary_node<T>(opr, branch0, branch1) 11287 | , initialised_(false) 11288 | , str0_base_ptr_ (0) 11289 | , str1_base_ptr_ (0) 11290 | , str0_rng_node_ptr_(0) 11291 | , str0_range_ptr_ (0) 11292 | , str1_range_ptr_ (0) 11293 | { 11294 | if (is_string_range_node(branch(0))) 11295 | { 11296 | str0_rng_node_ptr_ = static_cast<str_rng_node_ptr>(branch(0)); 11297 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0)); 11298 | irange_ptr range = dynamic_cast<irange_ptr>(branch(0)); 11299 | 11300 | if (0 == range) 11301 | return; 11302 | 11303 | str0_range_ptr_ = &(range->range_ref()); 11304 | } 11305 | 11306 | if (is_generally_string_node(branch(1))) 11307 | { 11308 | str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1)); 11309 | 11310 | if (0 == str1_base_ptr_) 11311 | return; 11312 | 11313 | irange_ptr range = dynamic_cast<irange_ptr>(branch(1)); 11314 | 11315 | if (0 == range) 11316 | return; 11317 | 11318 | str1_range_ptr_ = &(range->range_ref()); 11319 | } 11320 | 11321 | initialised_ = str0_base_ptr_ && 11322 | str1_base_ptr_ && 11323 | str0_rng_node_ptr_ && 11324 | str0_range_ptr_ && 11325 | str1_range_ptr_ ; 11326 | 11327 | assert(valid()); 11328 | } 11329 | 11330 | inline T value() const exprtk_override 11331 | { 11332 | branch(0)->value(); 11333 | branch(1)->value(); 11334 | 11335 | std::size_t s0_r0 = 0; 11336 | std::size_t s0_r1 = 0; 11337 | 11338 | std::size_t s1_r0 = 0; 11339 | std::size_t s1_r1 = 0; 11340 | 11341 | const range_t& range0 = (*str0_range_ptr_); 11342 | const range_t& range1 = (*str1_range_ptr_); 11343 | 11344 | if ( 11345 | range0(s0_r0, s0_r1, str0_base_ptr_->size()) && 11346 | range1(s1_r0, s1_r1, str1_base_ptr_->size()) 11347 | ) 11348 | { 11349 | const std::size_t size = std::min((s0_r1 - s0_r0), (s1_r1 - s1_r0)); 11350 | 11351 | std::copy( 11352 | str1_base_ptr_->base() + s1_r0, 11353 | str1_base_ptr_->base() + s1_r0 + size, 11354 | const_cast<char_ptr>(base() + s0_r0)); 11355 | } 11356 | 11357 | return std::numeric_limits<T>::quiet_NaN(); 11358 | } 11359 | 11360 | std::string str() const exprtk_override 11361 | { 11362 | return str0_base_ptr_->str(); 11363 | } 11364 | 11365 | char_cptr base() const exprtk_override 11366 | { 11367 | return str0_base_ptr_->base(); 11368 | } 11369 | 11370 | std::size_t size() const exprtk_override 11371 | { 11372 | return str0_base_ptr_->size(); 11373 | } 11374 | 11375 | range_t& range_ref() exprtk_override 11376 | { 11377 | return str0_rng_node_ptr_->range_ref(); 11378 | } 11379 | 11380 | const range_t& range_ref() const exprtk_override 11381 | { 11382 | return str0_rng_node_ptr_->range_ref(); 11383 | } 11384 | 11385 | inline typename expression_node<T>::node_type type() const exprtk_override 11386 | { 11387 | return expression_node<T>::e_strass; 11388 | } 11389 | 11390 | inline bool valid() const exprtk_override 11391 | { 11392 | return initialised_ && binary_node<T>::valid(); 11393 | } 11394 | 11395 | private: 11396 | 11397 | bool initialised_; 11398 | str_base_ptr str0_base_ptr_; 11399 | str_base_ptr str1_base_ptr_; 11400 | str_rng_node_ptr str0_rng_node_ptr_; 11401 | range_ptr str0_range_ptr_; 11402 | range_ptr str1_range_ptr_; 11403 | }; 11404 | 11405 | template <typename T> 11406 | class conditional_string_node exprtk_final 11407 | : public trinary_node <T> 11408 | , public string_base_node<T> 11409 | , public range_interface <T> 11410 | { 11411 | public: 11412 | 11413 | typedef typename range_interface<T>::range_t range_t; 11414 | typedef range_t* range_ptr; 11415 | typedef range_interface <T> irange_t; 11416 | typedef irange_t* irange_ptr; 11417 | typedef expression_node <T>* expression_ptr; 11418 | typedef string_base_node<T>* str_base_ptr; 11419 | 11420 | conditional_string_node(expression_ptr condition, 11421 | expression_ptr consequent, 11422 | expression_ptr alternative) 11423 | : trinary_node<T>(details::e_default, consequent, alternative, condition) 11424 | , initialised_(false) 11425 | , str0_base_ptr_ (0) 11426 | , str1_base_ptr_ (0) 11427 | , str0_range_ptr_(0) 11428 | , str1_range_ptr_(0) 11429 | , condition_ (condition ) 11430 | , consequent_ (consequent ) 11431 | , alternative_(alternative) 11432 | { 11433 | range_.n0_c = std::make_pair<bool,std::size_t>(true,0); 11434 | range_.n1_c = std::make_pair<bool,std::size_t>(true,0); 11435 | 11436 | range_.cache.first = range_.n0_c.second; 11437 | range_.cache.second = range_.n1_c.second; 11438 | 11439 | if (is_generally_string_node(trinary_node<T>::branch_[0].first)) 11440 | { 11441 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(trinary_node<T>::branch_[0].first); 11442 | 11443 | if (0 == str0_base_ptr_) 11444 | return; 11445 | 11446 | str0_range_ptr_ = dynamic_cast<irange_ptr>(trinary_node<T>::branch_[0].first); 11447 | 11448 | if (0 == str0_range_ptr_) 11449 | return; 11450 | } 11451 | 11452 | if (is_generally_string_node(trinary_node<T>::branch_[1].first)) 11453 | { 11454 | str1_base_ptr_ = dynamic_cast<str_base_ptr>(trinary_node<T>::branch_[1].first); 11455 | 11456 | if (0 == str1_base_ptr_) 11457 | return; 11458 | 11459 | str1_range_ptr_ = dynamic_cast<irange_ptr>(trinary_node<T>::branch_[1].first); 11460 | 11461 | if (0 == str1_range_ptr_) 11462 | return; 11463 | } 11464 | 11465 | initialised_ = str0_base_ptr_ && 11466 | str1_base_ptr_ && 11467 | str0_range_ptr_ && 11468 | str1_range_ptr_ ; 11469 | 11470 | assert(valid()); 11471 | } 11472 | 11473 | inline T value() const exprtk_override 11474 | { 11475 | std::size_t r0 = 0; 11476 | std::size_t r1 = 0; 11477 | 11478 | if (is_true(condition_)) 11479 | { 11480 | consequent_->value(); 11481 | 11482 | const range_t& range = str0_range_ptr_->range_ref(); 11483 | 11484 | if (range(r0, r1, str0_base_ptr_->size())) 11485 | { 11486 | const std::size_t size = (r1 - r0); 11487 | 11488 | value_.assign(str0_base_ptr_->base() + r0, size); 11489 | 11490 | range_.n1_c.second = value_.size(); 11491 | range_.cache.second = range_.n1_c.second; 11492 | 11493 | return T(1); 11494 | } 11495 | } 11496 | else 11497 | { 11498 | alternative_->value(); 11499 | 11500 | const range_t& range = str1_range_ptr_->range_ref(); 11501 | 11502 | if (range(r0, r1, str1_base_ptr_->size())) 11503 | { 11504 | const std::size_t size = (r1 - r0); 11505 | 11506 | value_.assign(str1_base_ptr_->base() + r0, size); 11507 | 11508 | range_.n1_c.second = value_.size(); 11509 | range_.cache.second = range_.n1_c.second; 11510 | 11511 | return T(0); 11512 | } 11513 | } 11514 | 11515 | return std::numeric_limits<T>::quiet_NaN(); 11516 | } 11517 | 11518 | std::string str() const exprtk_override 11519 | { 11520 | return value_; 11521 | } 11522 | 11523 | char_cptr base() const exprtk_override 11524 | { 11525 | return &value_[0]; 11526 | } 11527 | 11528 | std::size_t size() const exprtk_override 11529 | { 11530 | return value_.size(); 11531 | } 11532 | 11533 | range_t& range_ref() exprtk_override 11534 | { 11535 | return range_; 11536 | } 11537 | 11538 | const range_t& range_ref() const exprtk_override 11539 | { 11540 | return range_; 11541 | } 11542 | 11543 | inline typename expression_node<T>::node_type type() const exprtk_override 11544 | { 11545 | return expression_node<T>::e_strcondition; 11546 | } 11547 | 11548 | inline bool valid() const exprtk_override 11549 | { 11550 | return 11551 | initialised_ && 11552 | condition_ && condition_ ->valid() && 11553 | consequent_ && consequent_ ->valid() && 11554 | alternative_&& alternative_->valid() ; 11555 | } 11556 | 11557 | private: 11558 | 11559 | bool initialised_; 11560 | str_base_ptr str0_base_ptr_; 11561 | str_base_ptr str1_base_ptr_; 11562 | irange_ptr str0_range_ptr_; 11563 | irange_ptr str1_range_ptr_; 11564 | mutable range_t range_; 11565 | mutable std::string value_; 11566 | 11567 | expression_ptr condition_; 11568 | expression_ptr consequent_; 11569 | expression_ptr alternative_; 11570 | }; 11571 | 11572 | template <typename T> 11573 | class cons_conditional_str_node exprtk_final 11574 | : public binary_node <T> 11575 | , public string_base_node<T> 11576 | , public range_interface <T> 11577 | { 11578 | public: 11579 | 11580 | typedef typename range_interface<T>::range_t range_t; 11581 | typedef range_t* range_ptr; 11582 | typedef range_interface <T> irange_t; 11583 | typedef irange_t* irange_ptr; 11584 | typedef expression_node <T>* expression_ptr; 11585 | typedef string_base_node<T>* str_base_ptr; 11586 | 11587 | using binary_node<T>::branch; 11588 | 11589 | cons_conditional_str_node(expression_ptr condition, 11590 | expression_ptr consequent) 11591 | : binary_node<T>(details::e_default, consequent, condition) 11592 | , initialised_(false) 11593 | , str0_base_ptr_ (0) 11594 | , str0_range_ptr_(0) 11595 | , condition_ (condition ) 11596 | , consequent_(consequent) 11597 | { 11598 | range_.n0_c = std::make_pair<bool,std::size_t>(true,0); 11599 | range_.n1_c = std::make_pair<bool,std::size_t>(true,0); 11600 | 11601 | range_.cache.first = range_.n0_c.second; 11602 | range_.cache.second = range_.n1_c.second; 11603 | 11604 | if (is_generally_string_node(branch(0))) 11605 | { 11606 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0)); 11607 | 11608 | if (0 == str0_base_ptr_) 11609 | return; 11610 | 11611 | str0_range_ptr_ = dynamic_cast<irange_ptr>(branch(0)); 11612 | 11613 | if (0 == str0_range_ptr_) 11614 | return; 11615 | } 11616 | 11617 | initialised_ = str0_base_ptr_ && str0_range_ptr_ ; 11618 | assert(valid()); 11619 | } 11620 | 11621 | inline T value() const exprtk_override 11622 | { 11623 | if (is_true(condition_)) 11624 | { 11625 | consequent_->value(); 11626 | 11627 | const range_t& range = str0_range_ptr_->range_ref(); 11628 | 11629 | std::size_t r0 = 0; 11630 | std::size_t r1 = 0; 11631 | 11632 | if (range(r0, r1, str0_base_ptr_->size())) 11633 | { 11634 | const std::size_t size = (r1 - r0); 11635 | 11636 | value_.assign(str0_base_ptr_->base() + r0, size); 11637 | 11638 | range_.n1_c.second = value_.size(); 11639 | range_.cache.second = range_.n1_c.second; 11640 | 11641 | return T(1); 11642 | } 11643 | } 11644 | 11645 | return std::numeric_limits<T>::quiet_NaN(); 11646 | } 11647 | 11648 | std::string str() const 11649 | { 11650 | return value_; 11651 | } 11652 | 11653 | char_cptr base() const 11654 | { 11655 | return &value_[0]; 11656 | } 11657 | 11658 | std::size_t size() const 11659 | { 11660 | return value_.size(); 11661 | } 11662 | 11663 | range_t& range_ref() 11664 | { 11665 | return range_; 11666 | } 11667 | 11668 | const range_t& range_ref() const 11669 | { 11670 | return range_; 11671 | } 11672 | 11673 | inline typename expression_node<T>::node_type type() const exprtk_override 11674 | { 11675 | return expression_node<T>::e_strccondition; 11676 | } 11677 | 11678 | inline bool valid() const exprtk_override 11679 | { 11680 | return 11681 | initialised_ && 11682 | condition_ && condition_ ->valid() && 11683 | consequent_ && consequent_ ->valid() ; 11684 | } 11685 | 11686 | private: 11687 | 11688 | bool initialised_; 11689 | str_base_ptr str0_base_ptr_; 11690 | irange_ptr str0_range_ptr_; 11691 | mutable range_t range_; 11692 | mutable std::string value_; 11693 | 11694 | expression_ptr condition_; 11695 | expression_ptr consequent_; 11696 | }; 11697 | 11698 | template <typename T, typename VarArgFunction> 11699 | class str_vararg_node exprtk_final 11700 | : public expression_node <T> 11701 | , public string_base_node<T> 11702 | , public range_interface <T> 11703 | { 11704 | public: 11705 | 11706 | typedef typename range_interface<T>::range_t range_t; 11707 | typedef range_t* range_ptr; 11708 | typedef range_interface <T> irange_t; 11709 | typedef irange_t* irange_ptr; 11710 | typedef expression_node <T>* expression_ptr; 11711 | typedef string_base_node<T>* str_base_ptr; 11712 | typedef std::pair<expression_ptr,bool> branch_t; 11713 | 11714 | template <typename Allocator, 11715 | template <typename, typename> class Sequence> 11716 | explicit str_vararg_node(const Sequence<expression_ptr,Allocator>& arg_list) 11717 | : initialised_(false) 11718 | , str_base_ptr_ (0) 11719 | , str_range_ptr_(0) 11720 | { 11721 | construct_branch_pair(final_node_, const_cast<expression_ptr>(arg_list.back())); 11722 | 11723 | if (0 == final_node_.first) 11724 | return; 11725 | else if (!is_generally_string_node(final_node_.first)) 11726 | return; 11727 | 11728 | str_base_ptr_ = dynamic_cast<str_base_ptr>(final_node_.first); 11729 | 11730 | if (0 == str_base_ptr_) 11731 | return; 11732 | 11733 | str_range_ptr_ = dynamic_cast<irange_ptr>(final_node_.first); 11734 | 11735 | if (0 == str_range_ptr_) 11736 | return; 11737 | 11738 | if (arg_list.size() > 1) 11739 | { 11740 | const std::size_t arg_list_size = arg_list.size() - 1; 11741 | 11742 | arg_list_.resize(arg_list_size); 11743 | 11744 | for (std::size_t i = 0; i < arg_list_size; ++i) 11745 | { 11746 | if (arg_list[i] && arg_list[i]->valid()) 11747 | { 11748 | construct_branch_pair(arg_list_[i], arg_list[i]); 11749 | } 11750 | else 11751 | { 11752 | arg_list_.clear(); 11753 | return; 11754 | } 11755 | } 11756 | 11757 | initialised_ = true; 11758 | } 11759 | 11760 | initialised_ &= str_base_ptr_ && str_range_ptr_; 11761 | assert(valid()); 11762 | } 11763 | 11764 | inline T value() const exprtk_override 11765 | { 11766 | if (!arg_list_.empty()) 11767 | { 11768 | VarArgFunction::process(arg_list_); 11769 | } 11770 | 11771 | final_node_.first->value(); 11772 | 11773 | return std::numeric_limits<T>::quiet_NaN(); 11774 | } 11775 | 11776 | std::string str() const exprtk_override 11777 | { 11778 | return str_base_ptr_->str(); 11779 | } 11780 | 11781 | char_cptr base() const exprtk_override 11782 | { 11783 | return str_base_ptr_->base(); 11784 | } 11785 | 11786 | std::size_t size() const exprtk_override 11787 | { 11788 | return str_base_ptr_->size(); 11789 | } 11790 | 11791 | range_t& range_ref() exprtk_override 11792 | { 11793 | return str_range_ptr_->range_ref(); 11794 | } 11795 | 11796 | const range_t& range_ref() const exprtk_override 11797 | { 11798 | return str_range_ptr_->range_ref(); 11799 | } 11800 | 11801 | inline typename expression_node<T>::node_type type() const exprtk_override 11802 | { 11803 | return expression_node<T>::e_stringvararg; 11804 | } 11805 | 11806 | inline bool valid() const exprtk_override 11807 | { 11808 | return 11809 | initialised_ && 11810 | final_node_.first && final_node_.first->valid(); 11811 | } 11812 | 11813 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 11814 | { 11815 | expression_node<T>::ndb_t::collect(final_node_ , node_delete_list); 11816 | expression_node<T>::ndb_t::collect(arg_list_ , node_delete_list); 11817 | } 11818 | 11819 | std::size_t node_depth() const exprtk_override 11820 | { 11821 | return std::max( 11822 | expression_node<T>::ndb_t::compute_node_depth(final_node_), 11823 | expression_node<T>::ndb_t::compute_node_depth(arg_list_ )); 11824 | } 11825 | 11826 | private: 11827 | 11828 | bool initialised_; 11829 | branch_t final_node_; 11830 | str_base_ptr str_base_ptr_; 11831 | irange_ptr str_range_ptr_; 11832 | std::vector<branch_t> arg_list_; 11833 | }; 11834 | #endif 11835 | 11836 | template <typename T> 11837 | class assert_node exprtk_final : public expression_node<T> 11838 | { 11839 | public: 11840 | 11841 | typedef expression_node<T>* expression_ptr; 11842 | typedef std::pair<expression_ptr,bool> branch_t; 11843 | typedef string_base_node<T>* str_base_ptr; 11844 | typedef assert_check::assert_context assert_context_t; 11845 | 11846 | assert_node(expression_ptr assert_condition_node, 11847 | expression_ptr assert_message_node, 11848 | assert_check_ptr assert_check, 11849 | const assert_context_t& context) 11850 | : assert_message_str_base_(0) 11851 | , assert_check_(assert_check) 11852 | , context_(context) 11853 | { 11854 | construct_branch_pair(assert_condition_node_, assert_condition_node); 11855 | construct_branch_pair(assert_message_node_ , assert_message_node ); 11856 | 11857 | #ifndef exprtk_disable_string_capabilities 11858 | if ( 11859 | assert_message_node_.first && 11860 | details::is_generally_string_node(assert_message_node_.first) 11861 | ) 11862 | { 11863 | assert_message_str_base_ = dynamic_cast<str_base_ptr>(assert_message_node_.first); 11864 | } 11865 | #endif 11866 | 11867 | assert(valid()); 11868 | } 11869 | 11870 | inline T value() const exprtk_override 11871 | { 11872 | if (details::is_true(assert_condition_node_.first->value())) 11873 | { 11874 | return T(1); 11875 | } 11876 | 11877 | #ifndef exprtk_disable_string_capabilities 11878 | if (assert_message_node_.first) 11879 | { 11880 | assert_message_node_.first->value(); 11881 | assert(assert_message_str_base_); 11882 | context_.message = assert_message_str_base_->str(); 11883 | } 11884 | #endif 11885 | 11886 | assert_check_->handle_assert(context_); 11887 | return T(0); 11888 | } 11889 | 11890 | inline typename expression_node<T>::node_type type() const exprtk_override 11891 | { 11892 | return expression_node<T>::e_assert; 11893 | } 11894 | 11895 | inline bool valid() const exprtk_override 11896 | { 11897 | return ( 11898 | assert_check_ && 11899 | assert_condition_node_.first && 11900 | assert_condition_node_.first->valid() 11901 | ) && 11902 | ( 11903 | (0 == assert_message_node_.first) || 11904 | ( 11905 | assert_message_node_.first && 11906 | assert_message_str_base_ && 11907 | assert_message_node_.first->valid() && 11908 | details::is_generally_string_node(assert_message_node_.first) 11909 | ) 11910 | ); 11911 | } 11912 | 11913 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 11914 | { 11915 | expression_node<T>::ndb_t::collect(assert_condition_node_, node_delete_list); 11916 | expression_node<T>::ndb_t::collect(assert_message_node_ , node_delete_list); 11917 | } 11918 | 11919 | std::size_t node_depth() const exprtk_override 11920 | { 11921 | return expression_node<T>::ndb_t::compute_node_depth 11922 | (assert_condition_node_, assert_message_node_); 11923 | } 11924 | 11925 | private: 11926 | 11927 | branch_t assert_condition_node_; 11928 | branch_t assert_message_node_; 11929 | str_base_ptr assert_message_str_base_; 11930 | assert_check_ptr assert_check_; 11931 | mutable assert_context_t context_; 11932 | }; 11933 | 11934 | template <typename T, std::size_t N> 11935 | inline T axn(const T a, const T x) 11936 | { 11937 | // a*x^n 11938 | return a * exprtk::details::numeric::fast_exp<T,N>::result(x); 11939 | } 11940 | 11941 | template <typename T, std::size_t N> 11942 | inline T axnb(const T a, const T x, const T b) 11943 | { 11944 | // a*x^n+b 11945 | return a * exprtk::details::numeric::fast_exp<T,N>::result(x) + b; 11946 | } 11947 | 11948 | template <typename T> 11949 | struct sf_base 11950 | { 11951 | typedef typename details::functor_t<T>::Type Type; 11952 | typedef typename details::functor_t<T> functor_t; 11953 | typedef typename functor_t::qfunc_t quaternary_functor_t; 11954 | typedef typename functor_t::tfunc_t trinary_functor_t; 11955 | typedef typename functor_t::bfunc_t binary_functor_t; 11956 | typedef typename functor_t::ufunc_t unary_functor_t; 11957 | }; 11958 | 11959 | #define define_sfop3(NN, OP0, OP1) \ 11960 | template <typename T> \ 11961 | struct sf##NN##_op : public sf_base<T> \ 11962 | { \ 11963 | typedef typename sf_base<T>::Type const Type; \ 11964 | static inline T process(Type x, Type y, Type z) \ 11965 | { \ 11966 | return (OP0); \ 11967 | } \ 11968 | static inline std::string id() \ 11969 | { \ 11970 | return (OP1); \ 11971 | } \ 11972 | }; \ 11973 | 11974 | define_sfop3(00,(x + y) / z ,"(t+t)/t") 11975 | define_sfop3(01,(x + y) * z ,"(t+t)*t") 11976 | define_sfop3(02,(x + y) - z ,"(t+t)-t") 11977 | define_sfop3(03,(x + y) + z ,"(t+t)+t") 11978 | define_sfop3(04,(x - y) + z ,"(t-t)+t") 11979 | define_sfop3(05,(x - y) / z ,"(t-t)/t") 11980 | define_sfop3(06,(x - y) * z ,"(t-t)*t") 11981 | define_sfop3(07,(x * y) + z ,"(t*t)+t") 11982 | define_sfop3(08,(x * y) - z ,"(t*t)-t") 11983 | define_sfop3(09,(x * y) / z ,"(t*t)/t") 11984 | define_sfop3(10,(x * y) * z ,"(t*t)*t") 11985 | define_sfop3(11,(x / y) + z ,"(t/t)+t") 11986 | define_sfop3(12,(x / y) - z ,"(t/t)-t") 11987 | define_sfop3(13,(x / y) / z ,"(t/t)/t") 11988 | define_sfop3(14,(x / y) * z ,"(t/t)*t") 11989 | define_sfop3(15,x / (y + z) ,"t/(t+t)") 11990 | define_sfop3(16,x / (y - z) ,"t/(t-t)") 11991 | define_sfop3(17,x / (y * z) ,"t/(t*t)") 11992 | define_sfop3(18,x / (y / z) ,"t/(t/t)") 11993 | define_sfop3(19,x * (y + z) ,"t*(t+t)") 11994 | define_sfop3(20,x * (y - z) ,"t*(t-t)") 11995 | define_sfop3(21,x * (y * z) ,"t*(t*t)") 11996 | define_sfop3(22,x * (y / z) ,"t*(t/t)") 11997 | define_sfop3(23,x - (y + z) ,"t-(t+t)") 11998 | define_sfop3(24,x - (y - z) ,"t-(t-t)") 11999 | define_sfop3(25,x - (y / z) ,"t-(t/t)") 12000 | define_sfop3(26,x - (y * z) ,"t-(t*t)") 12001 | define_sfop3(27,x + (y * z) ,"t+(t*t)") 12002 | define_sfop3(28,x + (y / z) ,"t+(t/t)") 12003 | define_sfop3(29,x + (y + z) ,"t+(t+t)") 12004 | define_sfop3(30,x + (y - z) ,"t+(t-t)") 12005 | define_sfop3(31,(axnb<T,2>(x,y,z))," ") 12006 | define_sfop3(32,(axnb<T,3>(x,y,z))," ") 12007 | define_sfop3(33,(axnb<T,4>(x,y,z))," ") 12008 | define_sfop3(34,(axnb<T,5>(x,y,z))," ") 12009 | define_sfop3(35,(axnb<T,6>(x,y,z))," ") 12010 | define_sfop3(36,(axnb<T,7>(x,y,z))," ") 12011 | define_sfop3(37,(axnb<T,8>(x,y,z))," ") 12012 | define_sfop3(38,(axnb<T,9>(x,y,z))," ") 12013 | define_sfop3(39,x * numeric::log(y) + z,"") 12014 | define_sfop3(40,x * numeric::log(y) - z,"") 12015 | define_sfop3(41,x * numeric::log10(y) + z,"") 12016 | define_sfop3(42,x * numeric::log10(y) - z,"") 12017 | define_sfop3(43,x * numeric::sin(y) + z ,"") 12018 | define_sfop3(44,x * numeric::sin(y) - z ,"") 12019 | define_sfop3(45,x * numeric::cos(y) + z ,"") 12020 | define_sfop3(46,x * numeric::cos(y) - z ,"") 12021 | define_sfop3(47,details::is_true(x) ? y : z,"") 12022 | 12023 | #define define_sfop4(NN, OP0, OP1) \ 12024 | template <typename T> \ 12025 | struct sf##NN##_op : public sf_base<T> \ 12026 | { \ 12027 | typedef typename sf_base<T>::Type const Type; \ 12028 | static inline T process(Type x, Type y, Type z, Type w) \ 12029 | { \ 12030 | return (OP0); \ 12031 | } \ 12032 | static inline std::string id() \ 12033 | { \ 12034 | return (OP1); \ 12035 | } \ 12036 | }; \ 12037 | 12038 | define_sfop4(48,(x + ((y + z) / w)),"t+((t+t)/t)") 12039 | define_sfop4(49,(x + ((y + z) * w)),"t+((t+t)*t)") 12040 | define_sfop4(50,(x + ((y - z) / w)),"t+((t-t)/t)") 12041 | define_sfop4(51,(x + ((y - z) * w)),"t+((t-t)*t)") 12042 | define_sfop4(52,(x + ((y * z) / w)),"t+((t*t)/t)") 12043 | define_sfop4(53,(x + ((y * z) * w)),"t+((t*t)*t)") 12044 | define_sfop4(54,(x + ((y / z) + w)),"t+((t/t)+t)") 12045 | define_sfop4(55,(x + ((y / z) / w)),"t+((t/t)/t)") 12046 | define_sfop4(56,(x + ((y / z) * w)),"t+((t/t)*t)") 12047 | define_sfop4(57,(x - ((y + z) / w)),"t-((t+t)/t)") 12048 | define_sfop4(58,(x - ((y + z) * w)),"t-((t+t)*t)") 12049 | define_sfop4(59,(x - ((y - z) / w)),"t-((t-t)/t)") 12050 | define_sfop4(60,(x - ((y - z) * w)),"t-((t-t)*t)") 12051 | define_sfop4(61,(x - ((y * z) / w)),"t-((t*t)/t)") 12052 | define_sfop4(62,(x - ((y * z) * w)),"t-((t*t)*t)") 12053 | define_sfop4(63,(x - ((y / z) / w)),"t-((t/t)/t)") 12054 | define_sfop4(64,(x - ((y / z) * w)),"t-((t/t)*t)") 12055 | define_sfop4(65,(((x + y) * z) - w),"((t+t)*t)-t") 12056 | define_sfop4(66,(((x - y) * z) - w),"((t-t)*t)-t") 12057 | define_sfop4(67,(((x * y) * z) - w),"((t*t)*t)-t") 12058 | define_sfop4(68,(((x / y) * z) - w),"((t/t)*t)-t") 12059 | define_sfop4(69,(((x + y) / z) - w),"((t+t)/t)-t") 12060 | define_sfop4(70,(((x - y) / z) - w),"((t-t)/t)-t") 12061 | define_sfop4(71,(((x * y) / z) - w),"((t*t)/t)-t") 12062 | define_sfop4(72,(((x / y) / z) - w),"((t/t)/t)-t") 12063 | define_sfop4(73,((x * y) + (z * w)),"(t*t)+(t*t)") 12064 | define_sfop4(74,((x * y) - (z * w)),"(t*t)-(t*t)") 12065 | define_sfop4(75,((x * y) + (z / w)),"(t*t)+(t/t)") 12066 | define_sfop4(76,((x * y) - (z / w)),"(t*t)-(t/t)") 12067 | define_sfop4(77,((x / y) + (z / w)),"(t/t)+(t/t)") 12068 | define_sfop4(78,((x / y) - (z / w)),"(t/t)-(t/t)") 12069 | define_sfop4(79,((x / y) - (z * w)),"(t/t)-(t*t)") 12070 | define_sfop4(80,(x / (y + (z * w))),"t/(t+(t*t))") 12071 | define_sfop4(81,(x / (y - (z * w))),"t/(t-(t*t))") 12072 | define_sfop4(82,(x * (y + (z * w))),"t*(t+(t*t))") 12073 | define_sfop4(83,(x * (y - (z * w))),"t*(t-(t*t))") 12074 | 12075 | define_sfop4(84,(axn<T,2>(x,y) + axn<T,2>(z,w)),"") 12076 | define_sfop4(85,(axn<T,3>(x,y) + axn<T,3>(z,w)),"") 12077 | define_sfop4(86,(axn<T,4>(x,y) + axn<T,4>(z,w)),"") 12078 | define_sfop4(87,(axn<T,5>(x,y) + axn<T,5>(z,w)),"") 12079 | define_sfop4(88,(axn<T,6>(x,y) + axn<T,6>(z,w)),"") 12080 | define_sfop4(89,(axn<T,7>(x,y) + axn<T,7>(z,w)),"") 12081 | define_sfop4(90,(axn<T,8>(x,y) + axn<T,8>(z,w)),"") 12082 | define_sfop4(91,(axn<T,9>(x,y) + axn<T,9>(z,w)),"") 12083 | define_sfop4(92,((details::is_true(x) && details::is_true(y)) ? z : w),"") 12084 | define_sfop4(93,((details::is_true(x) || details::is_true(y)) ? z : w),"") 12085 | define_sfop4(94,((x < y) ? z : w),"") 12086 | define_sfop4(95,((x <= y) ? z : w),"") 12087 | define_sfop4(96,((x > y) ? z : w),"") 12088 | define_sfop4(97,((x >= y) ? z : w),"") 12089 | define_sfop4(98,(details::is_true(numeric::equal(x,y)) ? z : w),"") 12090 | define_sfop4(99,(x * numeric::sin(y) + z * numeric::cos(w)),"") 12091 | 12092 | define_sfop4(ext00,((x + y) - (z * w)),"(t+t)-(t*t)") 12093 | define_sfop4(ext01,((x + y) - (z / w)),"(t+t)-(t/t)") 12094 | define_sfop4(ext02,((x + y) + (z * w)),"(t+t)+(t*t)") 12095 | define_sfop4(ext03,((x + y) + (z / w)),"(t+t)+(t/t)") 12096 | define_sfop4(ext04,((x - y) + (z * w)),"(t-t)+(t*t)") 12097 | define_sfop4(ext05,((x - y) + (z / w)),"(t-t)+(t/t)") 12098 | define_sfop4(ext06,((x - y) - (z * w)),"(t-t)-(t*t)") 12099 | define_sfop4(ext07,((x - y) - (z / w)),"(t-t)-(t/t)") 12100 | define_sfop4(ext08,((x + y) - (z - w)),"(t+t)-(t-t)") 12101 | define_sfop4(ext09,((x + y) + (z - w)),"(t+t)+(t-t)") 12102 | define_sfop4(ext10,((x + y) + (z + w)),"(t+t)+(t+t)") 12103 | define_sfop4(ext11,((x + y) * (z - w)),"(t+t)*(t-t)") 12104 | define_sfop4(ext12,((x + y) / (z - w)),"(t+t)/(t-t)") 12105 | define_sfop4(ext13,((x - y) - (z + w)),"(t-t)-(t+t)") 12106 | define_sfop4(ext14,((x - y) + (z + w)),"(t-t)+(t+t)") 12107 | define_sfop4(ext15,((x - y) * (z + w)),"(t-t)*(t+t)") 12108 | define_sfop4(ext16,((x - y) / (z + w)),"(t-t)/(t+t)") 12109 | define_sfop4(ext17,((x * y) - (z + w)),"(t*t)-(t+t)") 12110 | define_sfop4(ext18,((x / y) - (z + w)),"(t/t)-(t+t)") 12111 | define_sfop4(ext19,((x * y) + (z + w)),"(t*t)+(t+t)") 12112 | define_sfop4(ext20,((x / y) + (z + w)),"(t/t)+(t+t)") 12113 | define_sfop4(ext21,((x * y) + (z - w)),"(t*t)+(t-t)") 12114 | define_sfop4(ext22,((x / y) + (z - w)),"(t/t)+(t-t)") 12115 | define_sfop4(ext23,((x * y) - (z - w)),"(t*t)-(t-t)") 12116 | define_sfop4(ext24,((x / y) - (z - w)),"(t/t)-(t-t)") 12117 | define_sfop4(ext25,((x + y) * (z * w)),"(t+t)*(t*t)") 12118 | define_sfop4(ext26,((x + y) * (z / w)),"(t+t)*(t/t)") 12119 | define_sfop4(ext27,((x + y) / (z * w)),"(t+t)/(t*t)") 12120 | define_sfop4(ext28,((x + y) / (z / w)),"(t+t)/(t/t)") 12121 | define_sfop4(ext29,((x - y) / (z * w)),"(t-t)/(t*t)") 12122 | define_sfop4(ext30,((x - y) / (z / w)),"(t-t)/(t/t)") 12123 | define_sfop4(ext31,((x - y) * (z * w)),"(t-t)*(t*t)") 12124 | define_sfop4(ext32,((x - y) * (z / w)),"(t-t)*(t/t)") 12125 | define_sfop4(ext33,((x * y) * (z + w)),"(t*t)*(t+t)") 12126 | define_sfop4(ext34,((x / y) * (z + w)),"(t/t)*(t+t)") 12127 | define_sfop4(ext35,((x * y) / (z + w)),"(t*t)/(t+t)") 12128 | define_sfop4(ext36,((x / y) / (z + w)),"(t/t)/(t+t)") 12129 | define_sfop4(ext37,((x * y) / (z - w)),"(t*t)/(t-t)") 12130 | define_sfop4(ext38,((x / y) / (z - w)),"(t/t)/(t-t)") 12131 | define_sfop4(ext39,((x * y) * (z - w)),"(t*t)*(t-t)") 12132 | define_sfop4(ext40,((x * y) / (z * w)),"(t*t)/(t*t)") 12133 | define_sfop4(ext41,((x / y) * (z / w)),"(t/t)*(t/t)") 12134 | define_sfop4(ext42,((x / y) * (z - w)),"(t/t)*(t-t)") 12135 | define_sfop4(ext43,((x * y) * (z * w)),"(t*t)*(t*t)") 12136 | define_sfop4(ext44,(x + (y * (z / w))),"t+(t*(t/t))") 12137 | define_sfop4(ext45,(x - (y * (z / w))),"t-(t*(t/t))") 12138 | define_sfop4(ext46,(x + (y / (z * w))),"t+(t/(t*t))") 12139 | define_sfop4(ext47,(x - (y / (z * w))),"t-(t/(t*t))") 12140 | define_sfop4(ext48,(((x - y) - z) * w),"((t-t)-t)*t") 12141 | define_sfop4(ext49,(((x - y) - z) / w),"((t-t)-t)/t") 12142 | define_sfop4(ext50,(((x - y) + z) * w),"((t-t)+t)*t") 12143 | define_sfop4(ext51,(((x - y) + z) / w),"((t-t)+t)/t") 12144 | define_sfop4(ext52,((x + (y - z)) * w),"(t+(t-t))*t") 12145 | define_sfop4(ext53,((x + (y - z)) / w),"(t+(t-t))/t") 12146 | define_sfop4(ext54,((x + y) / (z + w)),"(t+t)/(t+t)") 12147 | define_sfop4(ext55,((x - y) / (z - w)),"(t-t)/(t-t)") 12148 | define_sfop4(ext56,((x + y) * (z + w)),"(t+t)*(t+t)") 12149 | define_sfop4(ext57,((x - y) * (z - w)),"(t-t)*(t-t)") 12150 | define_sfop4(ext58,((x - y) + (z - w)),"(t-t)+(t-t)") 12151 | define_sfop4(ext59,((x - y) - (z - w)),"(t-t)-(t-t)") 12152 | define_sfop4(ext60,((x / y) + (z * w)),"(t/t)+(t*t)") 12153 | define_sfop4(ext61,(((x * y) * z) / w),"((t*t)*t)/t") 12154 | 12155 | #undef define_sfop3 12156 | #undef define_sfop4 12157 | 12158 | template <typename T, typename SpecialFunction> 12159 | class sf3_node exprtk_final : public trinary_node<T> 12160 | { 12161 | public: 12162 | 12163 | typedef expression_node<T>* expression_ptr; 12164 | 12165 | sf3_node(const operator_type& opr, 12166 | expression_ptr branch0, 12167 | expression_ptr branch1, 12168 | expression_ptr branch2) 12169 | : trinary_node<T>(opr, branch0, branch1, branch2) 12170 | {} 12171 | 12172 | inline T value() const exprtk_override 12173 | { 12174 | const T x = trinary_node<T>::branch_[0].first->value(); 12175 | const T y = trinary_node<T>::branch_[1].first->value(); 12176 | const T z = trinary_node<T>::branch_[2].first->value(); 12177 | 12178 | return SpecialFunction::process(x, y, z); 12179 | } 12180 | }; 12181 | 12182 | template <typename T, typename SpecialFunction> 12183 | class sf4_node exprtk_final : public quaternary_node<T> 12184 | { 12185 | public: 12186 | 12187 | typedef expression_node<T>* expression_ptr; 12188 | 12189 | sf4_node(const operator_type& opr, 12190 | expression_ptr branch0, 12191 | expression_ptr branch1, 12192 | expression_ptr branch2, 12193 | expression_ptr branch3) 12194 | : quaternary_node<T>(opr, branch0, branch1, branch2, branch3) 12195 | {} 12196 | 12197 | inline T value() const exprtk_override 12198 | { 12199 | const T x = quaternary_node<T>::branch_[0].first->value(); 12200 | const T y = quaternary_node<T>::branch_[1].first->value(); 12201 | const T z = quaternary_node<T>::branch_[2].first->value(); 12202 | const T w = quaternary_node<T>::branch_[3].first->value(); 12203 | 12204 | return SpecialFunction::process(x, y, z, w); 12205 | } 12206 | }; 12207 | 12208 | template <typename T, typename SpecialFunction> 12209 | class sf3_var_node exprtk_final : public expression_node<T> 12210 | { 12211 | public: 12212 | 12213 | typedef expression_node<T>* expression_ptr; 12214 | 12215 | sf3_var_node(const T& v0, const T& v1, const T& v2) 12216 | : v0_(v0) 12217 | , v1_(v1) 12218 | , v2_(v2) 12219 | {} 12220 | 12221 | inline T value() const exprtk_override 12222 | { 12223 | return SpecialFunction::process(v0_, v1_, v2_); 12224 | } 12225 | 12226 | inline typename expression_node<T>::node_type type() const exprtk_override 12227 | { 12228 | return expression_node<T>::e_trinary; 12229 | } 12230 | 12231 | private: 12232 | 12233 | sf3_var_node(const sf3_var_node<T,SpecialFunction>&) exprtk_delete; 12234 | sf3_var_node<T,SpecialFunction>& operator=(const sf3_var_node<T,SpecialFunction>&) exprtk_delete; 12235 | 12236 | const T& v0_; 12237 | const T& v1_; 12238 | const T& v2_; 12239 | }; 12240 | 12241 | template <typename T, typename SpecialFunction> 12242 | class sf4_var_node exprtk_final : public expression_node<T> 12243 | { 12244 | public: 12245 | 12246 | typedef expression_node<T>* expression_ptr; 12247 | 12248 | sf4_var_node(const T& v0, const T& v1, const T& v2, const T& v3) 12249 | : v0_(v0) 12250 | , v1_(v1) 12251 | , v2_(v2) 12252 | , v3_(v3) 12253 | {} 12254 | 12255 | inline T value() const exprtk_override 12256 | { 12257 | return SpecialFunction::process(v0_, v1_, v2_, v3_); 12258 | } 12259 | 12260 | inline typename expression_node<T>::node_type type() const exprtk_override 12261 | { 12262 | return expression_node<T>::e_trinary; 12263 | } 12264 | 12265 | private: 12266 | 12267 | sf4_var_node(const sf4_var_node<T,SpecialFunction>&) exprtk_delete; 12268 | sf4_var_node<T,SpecialFunction>& operator=(const sf4_var_node<T,SpecialFunction>&) exprtk_delete; 12269 | 12270 | const T& v0_; 12271 | const T& v1_; 12272 | const T& v2_; 12273 | const T& v3_; 12274 | }; 12275 | 12276 | template <typename T, typename VarArgFunction> 12277 | class vararg_node exprtk_final : public expression_node<T> 12278 | { 12279 | public: 12280 | 12281 | typedef expression_node<T>* expression_ptr; 12282 | typedef std::pair<expression_ptr,bool> branch_t; 12283 | 12284 | template <typename Allocator, 12285 | template <typename, typename> class Sequence> 12286 | explicit vararg_node(const Sequence<expression_ptr,Allocator>& arg_list) 12287 | : initialised_(false) 12288 | { 12289 | arg_list_.resize(arg_list.size()); 12290 | 12291 | for (std::size_t i = 0; i < arg_list.size(); ++i) 12292 | { 12293 | if (arg_list[i] && arg_list[i]->valid()) 12294 | { 12295 | construct_branch_pair(arg_list_[i],arg_list[i]); 12296 | } 12297 | else 12298 | { 12299 | arg_list_.clear(); 12300 | return; 12301 | } 12302 | } 12303 | 12304 | initialised_ = (arg_list_.size() == arg_list.size()); 12305 | assert(valid()); 12306 | } 12307 | 12308 | inline T value() const exprtk_override 12309 | { 12310 | return VarArgFunction::process(arg_list_); 12311 | } 12312 | 12313 | inline typename expression_node<T>::node_type type() const exprtk_override 12314 | { 12315 | return expression_node<T>::e_vararg; 12316 | } 12317 | 12318 | inline bool valid() const exprtk_override 12319 | { 12320 | return initialised_; 12321 | } 12322 | 12323 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 12324 | { 12325 | expression_node<T>::ndb_t::collect(arg_list_, node_delete_list); 12326 | } 12327 | 12328 | std::size_t node_depth() const exprtk_override 12329 | { 12330 | return expression_node<T>::ndb_t::compute_node_depth(arg_list_); 12331 | } 12332 | 12333 | std::size_t size() const 12334 | { 12335 | return arg_list_.size(); 12336 | } 12337 | 12338 | expression_ptr operator[](const std::size_t& index) const 12339 | { 12340 | return arg_list_[index].first; 12341 | } 12342 | 12343 | private: 12344 | 12345 | std::vector<branch_t> arg_list_; 12346 | bool initialised_; 12347 | }; 12348 | 12349 | template <typename T, typename VarArgFunction> 12350 | class vararg_varnode exprtk_final : public expression_node<T> 12351 | { 12352 | public: 12353 | 12354 | typedef expression_node<T>* expression_ptr; 12355 | 12356 | template <typename Allocator, 12357 | template <typename, typename> class Sequence> 12358 | explicit vararg_varnode(const Sequence<expression_ptr,Allocator>& arg_list) 12359 | : initialised_(false) 12360 | { 12361 | arg_list_.resize(arg_list.size()); 12362 | 12363 | for (std::size_t i = 0; i < arg_list.size(); ++i) 12364 | { 12365 | if (arg_list[i] && arg_list[i]->valid() && is_variable_node(arg_list[i])) 12366 | { 12367 | variable_node<T>* var_node_ptr = static_cast<variable_node<T>*>(arg_list[i]); 12368 | arg_list_[i] = (&var_node_ptr->ref()); 12369 | } 12370 | else 12371 | { 12372 | arg_list_.clear(); 12373 | return; 12374 | } 12375 | } 12376 | 12377 | initialised_ = (arg_list.size() == arg_list_.size()); 12378 | assert(valid()); 12379 | } 12380 | 12381 | inline T value() const exprtk_override 12382 | { 12383 | return VarArgFunction::process(arg_list_); 12384 | } 12385 | 12386 | inline typename expression_node<T>::node_type type() const exprtk_override 12387 | { 12388 | return expression_node<T>::e_vararg; 12389 | } 12390 | 12391 | inline bool valid() const exprtk_override 12392 | { 12393 | return initialised_; 12394 | } 12395 | 12396 | private: 12397 | 12398 | std::vector<const T*> arg_list_; 12399 | bool initialised_; 12400 | }; 12401 | 12402 | template <typename T, typename VecFunction> 12403 | class vectorize_node exprtk_final : public expression_node<T> 12404 | { 12405 | public: 12406 | 12407 | typedef expression_node<T>* expression_ptr; 12408 | typedef std::pair<expression_ptr,bool> branch_t; 12409 | 12410 | explicit vectorize_node(const expression_ptr v) 12411 | : ivec_ptr_(0) 12412 | { 12413 | construct_branch_pair(v_, v); 12414 | 12415 | if (is_ivector_node(v_.first)) 12416 | { 12417 | ivec_ptr_ = dynamic_cast<vector_interface<T>*>(v_.first); 12418 | } 12419 | } 12420 | 12421 | inline T value() const exprtk_override 12422 | { 12423 | v_.first->value(); 12424 | return VecFunction::process(ivec_ptr_); 12425 | } 12426 | 12427 | inline typename expression_node<T>::node_type type() const exprtk_override 12428 | { 12429 | return expression_node<T>::e_vecfunc; 12430 | } 12431 | 12432 | inline bool valid() const exprtk_override 12433 | { 12434 | return ivec_ptr_ && v_.first && v_.first->valid(); 12435 | } 12436 | 12437 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 12438 | { 12439 | expression_node<T>::ndb_t::collect(v_, node_delete_list); 12440 | } 12441 | 12442 | std::size_t node_depth() const exprtk_override 12443 | { 12444 | return expression_node<T>::ndb_t::compute_node_depth(v_); 12445 | } 12446 | 12447 | private: 12448 | 12449 | vector_interface<T>* ivec_ptr_; 12450 | branch_t v_; 12451 | }; 12452 | 12453 | template <typename T> 12454 | class assignment_node exprtk_final : public binary_node<T> 12455 | { 12456 | public: 12457 | 12458 | typedef expression_node<T>* expression_ptr; 12459 | using binary_node<T>::branch; 12460 | 12461 | assignment_node(const operator_type& opr, 12462 | expression_ptr branch0, 12463 | expression_ptr branch1) 12464 | : binary_node<T>(opr, branch0, branch1) 12465 | , var_node_ptr_(0) 12466 | { 12467 | if (is_variable_node(branch(0))) 12468 | { 12469 | var_node_ptr_ = static_cast<variable_node<T>*>(branch(0)); 12470 | } 12471 | } 12472 | 12473 | inline T value() const exprtk_override 12474 | { 12475 | T& result = var_node_ptr_->ref(); 12476 | result = branch(1)->value(); 12477 | 12478 | return result; 12479 | } 12480 | 12481 | inline bool valid() const exprtk_override 12482 | { 12483 | return var_node_ptr_ && binary_node<T>::valid(); 12484 | } 12485 | 12486 | private: 12487 | 12488 | variable_node<T>* var_node_ptr_; 12489 | }; 12490 | 12491 | template <typename T> 12492 | class assignment_vec_elem_node exprtk_final : public binary_node<T> 12493 | { 12494 | public: 12495 | 12496 | typedef expression_node<T>* expression_ptr; 12497 | using binary_node<T>::branch; 12498 | 12499 | assignment_vec_elem_node(const operator_type& opr, 12500 | expression_ptr branch0, 12501 | expression_ptr branch1) 12502 | : binary_node<T>(opr, branch0, branch1) 12503 | , vec_node_ptr_(0) 12504 | { 12505 | if (is_vector_elem_node(branch(0))) 12506 | { 12507 | vec_node_ptr_ = static_cast<vector_elem_node<T>*>(branch(0)); 12508 | } 12509 | 12510 | assert(valid()); 12511 | } 12512 | 12513 | inline T value() const exprtk_override 12514 | { 12515 | T& result = vec_node_ptr_->ref(); 12516 | result = branch(1)->value(); 12517 | 12518 | return result; 12519 | } 12520 | 12521 | inline bool valid() const exprtk_override 12522 | { 12523 | return vec_node_ptr_ && binary_node<T>::valid(); 12524 | } 12525 | 12526 | private: 12527 | 12528 | vector_elem_node<T>* vec_node_ptr_; 12529 | }; 12530 | 12531 | template <typename T> 12532 | class assignment_vec_elem_rtc_node exprtk_final : public binary_node<T> 12533 | { 12534 | public: 12535 | 12536 | typedef expression_node<T>* expression_ptr; 12537 | using binary_node<T>::branch; 12538 | 12539 | assignment_vec_elem_rtc_node(const operator_type& opr, 12540 | expression_ptr branch0, 12541 | expression_ptr branch1) 12542 | : binary_node<T>(opr, branch0, branch1) 12543 | , vec_node_ptr_(0) 12544 | { 12545 | if (is_vector_elem_rtc_node(branch(0))) 12546 | { 12547 | vec_node_ptr_ = static_cast<vector_elem_rtc_node<T>*>(branch(0)); 12548 | } 12549 | 12550 | assert(valid()); 12551 | } 12552 | 12553 | inline T value() const exprtk_override 12554 | { 12555 | T& result = vec_node_ptr_->ref(); 12556 | result = branch(1)->value(); 12557 | 12558 | return result; 12559 | } 12560 | 12561 | inline bool valid() const exprtk_override 12562 | { 12563 | return vec_node_ptr_ && binary_node<T>::valid(); 12564 | } 12565 | 12566 | private: 12567 | 12568 | vector_elem_rtc_node<T>* vec_node_ptr_; 12569 | }; 12570 | 12571 | template <typename T> 12572 | class assignment_rebasevec_elem_node exprtk_final : public binary_node<T> 12573 | { 12574 | public: 12575 | 12576 | typedef expression_node<T>* expression_ptr; 12577 | using expression_node<T>::branch; 12578 | 12579 | assignment_rebasevec_elem_node(const operator_type& opr, 12580 | expression_ptr branch0, 12581 | expression_ptr branch1) 12582 | : binary_node<T>(opr, branch0, branch1) 12583 | , rbvec_node_ptr_(0) 12584 | { 12585 | if (is_rebasevector_elem_node(branch(0))) 12586 | { 12587 | rbvec_node_ptr_ = static_cast<rebasevector_elem_node<T>*>(branch(0)); 12588 | } 12589 | 12590 | assert(valid()); 12591 | } 12592 | 12593 | inline T value() const exprtk_override 12594 | { 12595 | T& result = rbvec_node_ptr_->ref(); 12596 | result = branch(1)->value(); 12597 | 12598 | return result; 12599 | } 12600 | 12601 | inline bool valid() const exprtk_override 12602 | { 12603 | return rbvec_node_ptr_ && binary_node<T>::valid(); 12604 | } 12605 | 12606 | private: 12607 | 12608 | rebasevector_elem_node<T>* rbvec_node_ptr_; 12609 | }; 12610 | 12611 | template <typename T> 12612 | class assignment_rebasevec_elem_rtc_node exprtk_final : public binary_node<T> 12613 | { 12614 | public: 12615 | 12616 | typedef expression_node<T>* expression_ptr; 12617 | using expression_node<T>::branch; 12618 | 12619 | assignment_rebasevec_elem_rtc_node(const operator_type& opr, 12620 | expression_ptr branch0, 12621 | expression_ptr branch1) 12622 | : binary_node<T>(opr, branch0, branch1) 12623 | , rbvec_node_ptr_(0) 12624 | { 12625 | if (is_rebasevector_elem_rtc_node(branch(0))) 12626 | { 12627 | rbvec_node_ptr_ = static_cast<rebasevector_elem_rtc_node<T>*>(branch(0)); 12628 | } 12629 | 12630 | assert(valid()); 12631 | } 12632 | 12633 | inline T value() const exprtk_override 12634 | { 12635 | T& result = rbvec_node_ptr_->ref(); 12636 | result = branch(1)->value(); 12637 | 12638 | return result; 12639 | } 12640 | 12641 | inline bool valid() const exprtk_override 12642 | { 12643 | return rbvec_node_ptr_ && binary_node<T>::valid(); 12644 | } 12645 | 12646 | private: 12647 | 12648 | rebasevector_elem_rtc_node<T>* rbvec_node_ptr_; 12649 | }; 12650 | 12651 | template <typename T> 12652 | class assignment_rebasevec_celem_node exprtk_final : public binary_node<T> 12653 | { 12654 | public: 12655 | 12656 | typedef expression_node<T>* expression_ptr; 12657 | using binary_node<T>::branch; 12658 | 12659 | assignment_rebasevec_celem_node(const operator_type& opr, 12660 | expression_ptr branch0, 12661 | expression_ptr branch1) 12662 | : binary_node<T>(opr, branch0, branch1) 12663 | , rbvec_node_ptr_(0) 12664 | { 12665 | if (is_rebasevector_celem_node(branch(0))) 12666 | { 12667 | rbvec_node_ptr_ = static_cast<rebasevector_celem_node<T>*>(branch(0)); 12668 | } 12669 | 12670 | assert(valid()); 12671 | } 12672 | 12673 | inline T value() const exprtk_override 12674 | { 12675 | T& result = rbvec_node_ptr_->ref(); 12676 | result = branch(1)->value(); 12677 | 12678 | return result; 12679 | } 12680 | 12681 | inline bool valid() const exprtk_override 12682 | { 12683 | return rbvec_node_ptr_ && binary_node<T>::valid(); 12684 | } 12685 | 12686 | private: 12687 | 12688 | rebasevector_celem_node<T>* rbvec_node_ptr_; 12689 | }; 12690 | 12691 | template <typename T> 12692 | class assignment_vec_node exprtk_final 12693 | : public binary_node <T> 12694 | , public vector_interface<T> 12695 | { 12696 | public: 12697 | 12698 | typedef expression_node<T>* expression_ptr; 12699 | typedef vector_node<T>* vector_node_ptr; 12700 | typedef vec_data_store<T> vds_t; 12701 | 12702 | using binary_node<T>::branch; 12703 | 12704 | assignment_vec_node(const operator_type& opr, 12705 | expression_ptr branch0, 12706 | expression_ptr branch1) 12707 | : binary_node<T>(opr, branch0, branch1) 12708 | , vec_node_ptr_(0) 12709 | { 12710 | if (is_vector_node(branch(0))) 12711 | { 12712 | vec_node_ptr_ = static_cast<vector_node<T>*>(branch(0)); 12713 | vds() = vec_node_ptr_->vds(); 12714 | } 12715 | 12716 | assert(valid()); 12717 | } 12718 | 12719 | inline T value() const exprtk_override 12720 | { 12721 | const T v = branch(1)->value(); 12722 | 12723 | T* vec = vds().data(); 12724 | 12725 | loop_unroll::details lud(size()); 12726 | const T* upper_bound = vec + lud.upper_bound; 12727 | 12728 | while (vec < upper_bound) 12729 | { 12730 | #define exprtk_loop(N) \ 12731 | vec[N] = v; \ 12732 | 12733 | exprtk_loop( 0) exprtk_loop( 1) 12734 | exprtk_loop( 2) exprtk_loop( 3) 12735 | #ifndef exprtk_disable_superscalar_unroll 12736 | exprtk_loop( 4) exprtk_loop( 5) 12737 | exprtk_loop( 6) exprtk_loop( 7) 12738 | exprtk_loop( 8) exprtk_loop( 9) 12739 | exprtk_loop(10) exprtk_loop(11) 12740 | exprtk_loop(12) exprtk_loop(13) 12741 | exprtk_loop(14) exprtk_loop(15) 12742 | #endif 12743 | 12744 | vec += lud.batch_size; 12745 | } 12746 | 12747 | switch (lud.remainder) 12748 | { 12749 | #define case_stmt(N) \ 12750 | case N : *vec++ = v; \ 12751 | exprtk_fallthrough \ 12752 | 12753 | #ifndef exprtk_disable_superscalar_unroll 12754 | case_stmt(15) case_stmt(14) 12755 | case_stmt(13) case_stmt(12) 12756 | case_stmt(11) case_stmt(10) 12757 | case_stmt( 9) case_stmt( 8) 12758 | case_stmt( 7) case_stmt( 6) 12759 | case_stmt( 5) case_stmt( 4) 12760 | #endif 12761 | case_stmt( 3) case_stmt( 2) 12762 | case 1 : *vec++ = v; 12763 | } 12764 | 12765 | #undef exprtk_loop 12766 | #undef case_stmt 12767 | 12768 | return vec_node_ptr_->value(); 12769 | } 12770 | 12771 | vector_node_ptr vec() const exprtk_override 12772 | { 12773 | return vec_node_ptr_; 12774 | } 12775 | 12776 | vector_node_ptr vec() exprtk_override 12777 | { 12778 | return vec_node_ptr_; 12779 | } 12780 | 12781 | inline typename expression_node<T>::node_type type() const exprtk_override 12782 | { 12783 | return expression_node<T>::e_vecvalass; 12784 | } 12785 | 12786 | inline bool valid() const exprtk_override 12787 | { 12788 | return 12789 | vec_node_ptr_ && 12790 | (vds().size() <= vec_node_ptr_->vec_holder().base_size()) && 12791 | binary_node<T>::valid(); 12792 | } 12793 | 12794 | std::size_t size() const exprtk_override 12795 | { 12796 | return vec_node_ptr_->vec_holder().size(); 12797 | } 12798 | 12799 | std::size_t base_size() const exprtk_override 12800 | { 12801 | return vec_node_ptr_->vec_holder().base_size(); 12802 | } 12803 | 12804 | vds_t& vds() exprtk_override 12805 | { 12806 | return vds_; 12807 | } 12808 | 12809 | const vds_t& vds() const exprtk_override 12810 | { 12811 | return vds_; 12812 | } 12813 | 12814 | private: 12815 | 12816 | vector_node<T>* vec_node_ptr_; 12817 | vds_t vds_; 12818 | }; 12819 | 12820 | template <typename T> 12821 | class assignment_vecvec_node exprtk_final 12822 | : public binary_node <T> 12823 | , public vector_interface<T> 12824 | { 12825 | public: 12826 | 12827 | typedef expression_node<T>* expression_ptr; 12828 | typedef vector_node<T>* vector_node_ptr; 12829 | typedef vec_data_store<T> vds_t; 12830 | 12831 | using binary_node<T>::branch; 12832 | 12833 | assignment_vecvec_node(const operator_type& opr, 12834 | expression_ptr branch0, 12835 | expression_ptr branch1) 12836 | : binary_node<T>(opr, branch0, branch1) 12837 | , vec0_node_ptr_(0) 12838 | , vec1_node_ptr_(0) 12839 | , initialised_(false) 12840 | , src_is_ivec_(false) 12841 | { 12842 | if (is_vector_node(branch(0))) 12843 | { 12844 | vec0_node_ptr_ = static_cast<vector_node<T>*>(branch(0)); 12845 | vds() = vec0_node_ptr_->vds(); 12846 | } 12847 | 12848 | if (is_vector_node(branch(1))) 12849 | { 12850 | vec1_node_ptr_ = static_cast<vector_node<T>*>(branch(1)); 12851 | vds_t::match_sizes(vds(),vec1_node_ptr_->vds()); 12852 | } 12853 | else if (is_ivector_node(branch(1))) 12854 | { 12855 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 12856 | 12857 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1)))) 12858 | { 12859 | vec1_node_ptr_ = vi->vec(); 12860 | 12861 | if (!vi->side_effect()) 12862 | { 12863 | vi->vds() = vds(); 12864 | src_is_ivec_ = true; 12865 | } 12866 | else 12867 | vds_t::match_sizes(vds(),vi->vds()); 12868 | } 12869 | } 12870 | 12871 | initialised_ = 12872 | vec0_node_ptr_ && 12873 | vec1_node_ptr_ && 12874 | (size() <= base_size()) && 12875 | (vds_.size() <= base_size()) && 12876 | binary_node<T>::valid(); 12877 | 12878 | assert(valid()); 12879 | } 12880 | 12881 | inline T value() const exprtk_override 12882 | { 12883 | branch(1)->value(); 12884 | 12885 | if (src_is_ivec_) 12886 | return vec0_node_ptr_->value(); 12887 | 12888 | T* vec0 = vec0_node_ptr_->vds().data(); 12889 | T* vec1 = vec1_node_ptr_->vds().data(); 12890 | 12891 | loop_unroll::details lud(size()); 12892 | const T* upper_bound = vec0 + lud.upper_bound; 12893 | 12894 | while (vec0 < upper_bound) 12895 | { 12896 | #define exprtk_loop(N) \ 12897 | vec0[N] = vec1[N]; \ 12898 | 12899 | exprtk_loop( 0) exprtk_loop( 1) 12900 | exprtk_loop( 2) exprtk_loop( 3) 12901 | #ifndef exprtk_disable_superscalar_unroll 12902 | exprtk_loop( 4) exprtk_loop( 5) 12903 | exprtk_loop( 6) exprtk_loop( 7) 12904 | exprtk_loop( 8) exprtk_loop( 9) 12905 | exprtk_loop(10) exprtk_loop(11) 12906 | exprtk_loop(12) exprtk_loop(13) 12907 | exprtk_loop(14) exprtk_loop(15) 12908 | #endif 12909 | 12910 | vec0 += lud.batch_size; 12911 | vec1 += lud.batch_size; 12912 | } 12913 | 12914 | switch (lud.remainder) 12915 | { 12916 | #define case_stmt(N,fall_through) \ 12917 | case N : *vec0++ = *vec1++; \ 12918 | fall_through \ 12919 | 12920 | #ifndef exprtk_disable_superscalar_unroll 12921 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 12922 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 12923 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 12924 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 12925 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 12926 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 12927 | #endif 12928 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 12929 | case_stmt( 1, (void)0;) 12930 | } 12931 | 12932 | #undef exprtk_loop 12933 | #undef case_stmt 12934 | 12935 | return vec0_node_ptr_->value(); 12936 | } 12937 | 12938 | vector_node_ptr vec() exprtk_override 12939 | { 12940 | return vec0_node_ptr_; 12941 | } 12942 | 12943 | vector_node_ptr vec() const exprtk_override 12944 | { 12945 | return vec0_node_ptr_; 12946 | } 12947 | 12948 | inline typename expression_node<T>::node_type type() const exprtk_override 12949 | { 12950 | return expression_node<T>::e_vecvecass; 12951 | } 12952 | 12953 | inline bool valid() const exprtk_override 12954 | { 12955 | return initialised_; 12956 | } 12957 | 12958 | std::size_t size() const exprtk_override 12959 | { 12960 | return std::min( 12961 | vec0_node_ptr_->vec_holder().size(), 12962 | vec1_node_ptr_->vec_holder().size()); 12963 | } 12964 | 12965 | std::size_t base_size() const exprtk_override 12966 | { 12967 | return std::min( 12968 | vec0_node_ptr_->vec_holder().base_size(), 12969 | vec1_node_ptr_->vec_holder().base_size()); 12970 | } 12971 | 12972 | vds_t& vds() exprtk_override 12973 | { 12974 | return vds_; 12975 | } 12976 | 12977 | const vds_t& vds() const exprtk_override 12978 | { 12979 | return vds_; 12980 | } 12981 | 12982 | private: 12983 | 12984 | vector_node<T>* vec0_node_ptr_; 12985 | vector_node<T>* vec1_node_ptr_; 12986 | bool initialised_; 12987 | bool src_is_ivec_; 12988 | vds_t vds_; 12989 | }; 12990 | 12991 | template <typename T, typename Operation> 12992 | class assignment_op_node exprtk_final : public binary_node<T> 12993 | { 12994 | public: 12995 | 12996 | typedef expression_node<T>* expression_ptr; 12997 | using binary_node<T>::branch; 12998 | 12999 | assignment_op_node(const operator_type& opr, 13000 | expression_ptr branch0, 13001 | expression_ptr branch1) 13002 | : binary_node<T>(opr, branch0, branch1) 13003 | , var_node_ptr_(0) 13004 | { 13005 | if (is_variable_node(branch(0))) 13006 | { 13007 | var_node_ptr_ = static_cast<variable_node<T>*>(branch(0)); 13008 | } 13009 | 13010 | assert(valid()); 13011 | } 13012 | 13013 | inline T value() const exprtk_override 13014 | { 13015 | T& v = var_node_ptr_->ref(); 13016 | v = Operation::process(v,branch(1)->value()); 13017 | 13018 | return v; 13019 | } 13020 | 13021 | inline bool valid() const exprtk_override 13022 | { 13023 | return var_node_ptr_ && binary_node<T>::valid(); 13024 | } 13025 | 13026 | private: 13027 | 13028 | variable_node<T>* var_node_ptr_; 13029 | }; 13030 | 13031 | template <typename T, typename Operation> 13032 | class assignment_vec_elem_op_node exprtk_final : public binary_node<T> 13033 | { 13034 | public: 13035 | 13036 | typedef expression_node<T>* expression_ptr; 13037 | using binary_node<T>::branch; 13038 | 13039 | assignment_vec_elem_op_node(const operator_type& opr, 13040 | expression_ptr branch0, 13041 | expression_ptr branch1) 13042 | : binary_node<T>(opr, branch0, branch1) 13043 | , vec_node_ptr_(0) 13044 | { 13045 | if (is_vector_elem_node(branch(0))) 13046 | { 13047 | vec_node_ptr_ = static_cast<vector_elem_node<T>*>(branch(0)); 13048 | } 13049 | 13050 | assert(valid()); 13051 | } 13052 | 13053 | inline T value() const exprtk_override 13054 | { 13055 | T& v = vec_node_ptr_->ref(); 13056 | v = Operation::process(v,branch(1)->value()); 13057 | 13058 | return v; 13059 | } 13060 | 13061 | inline bool valid() const exprtk_override 13062 | { 13063 | return vec_node_ptr_ && binary_node<T>::valid(); 13064 | } 13065 | 13066 | private: 13067 | 13068 | vector_elem_node<T>* vec_node_ptr_; 13069 | }; 13070 | 13071 | template <typename T, typename Operation> 13072 | class assignment_vec_elem_op_rtc_node exprtk_final : public binary_node<T> 13073 | { 13074 | public: 13075 | 13076 | typedef expression_node<T>* expression_ptr; 13077 | using binary_node<T>::branch; 13078 | 13079 | assignment_vec_elem_op_rtc_node(const operator_type& opr, 13080 | expression_ptr branch0, 13081 | expression_ptr branch1) 13082 | : binary_node<T>(opr, branch0, branch1) 13083 | , vec_node_ptr_(0) 13084 | { 13085 | if (is_vector_elem_rtc_node(branch(0))) 13086 | { 13087 | vec_node_ptr_ = static_cast<vector_elem_rtc_node<T>*>(branch(0)); 13088 | } 13089 | 13090 | assert(valid()); 13091 | } 13092 | 13093 | inline T value() const exprtk_override 13094 | { 13095 | T& v = vec_node_ptr_->ref(); 13096 | v = Operation::process(v,branch(1)->value()); 13097 | 13098 | return v; 13099 | } 13100 | 13101 | inline bool valid() const exprtk_override 13102 | { 13103 | return vec_node_ptr_ && binary_node<T>::valid(); 13104 | } 13105 | 13106 | private: 13107 | 13108 | vector_elem_rtc_node<T>* vec_node_ptr_; 13109 | }; 13110 | 13111 | template <typename T, typename Operation> 13112 | class assignment_vec_celem_op_rtc_node exprtk_final : public binary_node<T> 13113 | { 13114 | public: 13115 | 13116 | typedef expression_node<T>* expression_ptr; 13117 | using binary_node<T>::branch; 13118 | 13119 | assignment_vec_celem_op_rtc_node(const operator_type& opr, 13120 | expression_ptr branch0, 13121 | expression_ptr branch1) 13122 | : binary_node<T>(opr, branch0, branch1) 13123 | , vec_node_ptr_(0) 13124 | { 13125 | if (is_vector_celem_rtc_node(branch(0))) 13126 | { 13127 | vec_node_ptr_ = static_cast<vector_celem_rtc_node<T>*>(branch(0)); 13128 | } 13129 | 13130 | assert(valid()); 13131 | } 13132 | 13133 | inline T value() const exprtk_override 13134 | { 13135 | T& v = vec_node_ptr_->ref(); 13136 | v = Operation::process(v,branch(1)->value()); 13137 | 13138 | return v; 13139 | } 13140 | 13141 | inline bool valid() const exprtk_override 13142 | { 13143 | return vec_node_ptr_ && binary_node<T>::valid(); 13144 | } 13145 | 13146 | private: 13147 | 13148 | vector_celem_rtc_node<T>* vec_node_ptr_; 13149 | }; 13150 | 13151 | template <typename T, typename Operation> 13152 | class assignment_rebasevec_elem_op_node exprtk_final : public binary_node<T> 13153 | { 13154 | public: 13155 | 13156 | typedef expression_node<T>* expression_ptr; 13157 | using binary_node<T>::branch; 13158 | 13159 | assignment_rebasevec_elem_op_node(const operator_type& opr, 13160 | expression_ptr branch0, 13161 | expression_ptr branch1) 13162 | : binary_node<T>(opr, branch0, branch1) 13163 | , rbvec_node_ptr_(0) 13164 | { 13165 | if (is_rebasevector_elem_node(branch(0))) 13166 | { 13167 | rbvec_node_ptr_ = static_cast<rebasevector_elem_node<T>*>(branch(0)); 13168 | } 13169 | 13170 | assert(valid()); 13171 | } 13172 | 13173 | inline T value() const exprtk_override 13174 | { 13175 | T& v = rbvec_node_ptr_->ref(); 13176 | v = Operation::process(v,branch(1)->value()); 13177 | 13178 | return v; 13179 | } 13180 | 13181 | inline bool valid() const exprtk_override 13182 | { 13183 | return rbvec_node_ptr_ && binary_node<T>::valid(); 13184 | } 13185 | 13186 | private: 13187 | 13188 | rebasevector_elem_node<T>* rbvec_node_ptr_; 13189 | }; 13190 | 13191 | template <typename T, typename Operation> 13192 | class assignment_rebasevec_celem_op_node exprtk_final : public binary_node<T> 13193 | { 13194 | public: 13195 | 13196 | typedef expression_node<T>* expression_ptr; 13197 | using binary_node<T>::branch; 13198 | 13199 | assignment_rebasevec_celem_op_node(const operator_type& opr, 13200 | expression_ptr branch0, 13201 | expression_ptr branch1) 13202 | : binary_node<T>(opr, branch0, branch1) 13203 | , rbvec_node_ptr_(0) 13204 | { 13205 | if (is_rebasevector_celem_node(branch(0))) 13206 | { 13207 | rbvec_node_ptr_ = static_cast<rebasevector_celem_node<T>*>(branch(0)); 13208 | } 13209 | 13210 | assert(valid()); 13211 | } 13212 | 13213 | inline T value() const exprtk_override 13214 | { 13215 | T& v = rbvec_node_ptr_->ref(); 13216 | v = Operation::process(v,branch(1)->value()); 13217 | 13218 | return v; 13219 | } 13220 | 13221 | inline bool valid() const exprtk_override 13222 | { 13223 | return rbvec_node_ptr_ && binary_node<T>::valid(); 13224 | } 13225 | 13226 | private: 13227 | 13228 | rebasevector_celem_node<T>* rbvec_node_ptr_; 13229 | }; 13230 | 13231 | template <typename T, typename Operation> 13232 | class assignment_rebasevec_elem_op_rtc_node exprtk_final : public binary_node<T> 13233 | { 13234 | public: 13235 | 13236 | typedef expression_node<T>* expression_ptr; 13237 | using binary_node<T>::branch; 13238 | 13239 | assignment_rebasevec_elem_op_rtc_node(const operator_type& opr, 13240 | expression_ptr branch0, 13241 | expression_ptr branch1) 13242 | : binary_node<T>(opr, branch0, branch1) 13243 | , rbvec_node_ptr_(0) 13244 | { 13245 | if (is_rebasevector_elem_rtc_node(branch(0))) 13246 | { 13247 | rbvec_node_ptr_ = static_cast<rebasevector_elem_rtc_node<T>*>(branch(0)); 13248 | } 13249 | 13250 | assert(valid()); 13251 | } 13252 | 13253 | inline T value() const exprtk_override 13254 | { 13255 | T& v = rbvec_node_ptr_->ref(); 13256 | v = Operation::process(v,branch(1)->value()); 13257 | 13258 | return v; 13259 | } 13260 | 13261 | inline bool valid() const exprtk_override 13262 | { 13263 | return rbvec_node_ptr_ && binary_node<T>::valid(); 13264 | } 13265 | 13266 | private: 13267 | 13268 | rebasevector_elem_rtc_node<T>* rbvec_node_ptr_; 13269 | }; 13270 | 13271 | template <typename T, typename Operation> 13272 | class assignment_rebasevec_celem_op_rtc_node exprtk_final : public binary_node<T> 13273 | { 13274 | public: 13275 | 13276 | typedef expression_node<T>* expression_ptr; 13277 | using binary_node<T>::branch; 13278 | 13279 | assignment_rebasevec_celem_op_rtc_node(const operator_type& opr, 13280 | expression_ptr branch0, 13281 | expression_ptr branch1) 13282 | : binary_node<T>(opr, branch0, branch1) 13283 | , rbvec_node_ptr_(0) 13284 | { 13285 | if (is_rebasevector_celem_rtc_node(branch(0))) 13286 | { 13287 | rbvec_node_ptr_ = static_cast<rebasevector_celem_rtc_node<T>*>(branch(0)); 13288 | } 13289 | 13290 | assert(valid()); 13291 | } 13292 | 13293 | inline T value() const exprtk_override 13294 | { 13295 | T& v = rbvec_node_ptr_->ref(); 13296 | v = Operation::process(v,branch(1)->value()); 13297 | 13298 | return v; 13299 | } 13300 | 13301 | inline bool valid() const exprtk_override 13302 | { 13303 | return rbvec_node_ptr_ && binary_node<T>::valid(); 13304 | } 13305 | 13306 | private: 13307 | 13308 | rebasevector_celem_rtc_node<T>* rbvec_node_ptr_; 13309 | }; 13310 | 13311 | template <typename T, typename Operation> 13312 | class assignment_vec_op_node exprtk_final 13313 | : public binary_node <T> 13314 | , public vector_interface<T> 13315 | { 13316 | public: 13317 | 13318 | typedef expression_node<T>* expression_ptr; 13319 | typedef vector_node<T>* vector_node_ptr; 13320 | typedef vec_data_store<T> vds_t; 13321 | 13322 | using binary_node<T>::branch; 13323 | 13324 | assignment_vec_op_node(const operator_type& opr, 13325 | expression_ptr branch0, 13326 | expression_ptr branch1) 13327 | : binary_node<T>(opr, branch0, branch1) 13328 | , vec_node_ptr_(0) 13329 | { 13330 | if (is_vector_node(branch(0))) 13331 | { 13332 | vec_node_ptr_ = static_cast<vector_node<T>*>(branch(0)); 13333 | vds() = vec_node_ptr_->vds(); 13334 | } 13335 | 13336 | assert(valid()); 13337 | } 13338 | 13339 | inline T value() const exprtk_override 13340 | { 13341 | const T v = branch(1)->value(); 13342 | 13343 | T* vec = vds().data(); 13344 | 13345 | loop_unroll::details lud(size()); 13346 | const T* upper_bound = vec + lud.upper_bound; 13347 | 13348 | while (vec < upper_bound) 13349 | { 13350 | #define exprtk_loop(N) \ 13351 | Operation::assign(vec[N],v); \ 13352 | 13353 | exprtk_loop( 0) exprtk_loop( 1) 13354 | exprtk_loop( 2) exprtk_loop( 3) 13355 | #ifndef exprtk_disable_superscalar_unroll 13356 | exprtk_loop( 4) exprtk_loop( 5) 13357 | exprtk_loop( 6) exprtk_loop( 7) 13358 | exprtk_loop( 8) exprtk_loop( 9) 13359 | exprtk_loop(10) exprtk_loop(11) 13360 | exprtk_loop(12) exprtk_loop(13) 13361 | exprtk_loop(14) exprtk_loop(15) 13362 | #endif 13363 | 13364 | vec += lud.batch_size; 13365 | } 13366 | 13367 | switch (lud.remainder) 13368 | { 13369 | #define case_stmt(N,fall_through) \ 13370 | case N : Operation::assign(*vec++,v); \ 13371 | fall_through \ 13372 | 13373 | #ifndef exprtk_disable_superscalar_unroll 13374 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 13375 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 13376 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 13377 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 13378 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 13379 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 13380 | #endif 13381 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 13382 | case_stmt( 1, (void)0;) 13383 | } 13384 | 13385 | #undef exprtk_loop 13386 | #undef case_stmt 13387 | 13388 | return vec_node_ptr_->value(); 13389 | } 13390 | 13391 | vector_node_ptr vec() const exprtk_override 13392 | { 13393 | return vec_node_ptr_; 13394 | } 13395 | 13396 | vector_node_ptr vec() exprtk_override 13397 | { 13398 | return vec_node_ptr_; 13399 | } 13400 | 13401 | inline typename expression_node<T>::node_type type() const exprtk_override 13402 | { 13403 | return expression_node<T>::e_vecopvalass; 13404 | } 13405 | 13406 | inline bool valid() const exprtk_override 13407 | { 13408 | return 13409 | vec_node_ptr_ && 13410 | (size() <= base_size()) && 13411 | binary_node<T>::valid() ; 13412 | } 13413 | 13414 | std::size_t size() const exprtk_override 13415 | { 13416 | return vec_node_ptr_->vec_holder().size(); 13417 | } 13418 | 13419 | std::size_t base_size() const exprtk_override 13420 | { 13421 | return vec_node_ptr_->vec_holder().base_size(); 13422 | } 13423 | 13424 | vds_t& vds() exprtk_override 13425 | { 13426 | return vds_; 13427 | } 13428 | 13429 | const vds_t& vds() const exprtk_override 13430 | { 13431 | return vds_; 13432 | } 13433 | 13434 | bool side_effect() const exprtk_override 13435 | { 13436 | return true; 13437 | } 13438 | 13439 | private: 13440 | 13441 | vector_node<T>* vec_node_ptr_; 13442 | vds_t vds_; 13443 | }; 13444 | 13445 | template <typename T, typename Operation> 13446 | class assignment_vecvec_op_node exprtk_final 13447 | : public binary_node <T> 13448 | , public vector_interface<T> 13449 | { 13450 | public: 13451 | 13452 | typedef expression_node<T>* expression_ptr; 13453 | typedef vector_node<T>* vector_node_ptr; 13454 | typedef vec_data_store<T> vds_t; 13455 | 13456 | using binary_node<T>::branch; 13457 | 13458 | assignment_vecvec_op_node(const operator_type& opr, 13459 | expression_ptr branch0, 13460 | expression_ptr branch1) 13461 | : binary_node<T>(opr, branch0, branch1) 13462 | , vec0_node_ptr_(0) 13463 | , vec1_node_ptr_(0) 13464 | , initialised_(false) 13465 | { 13466 | if (is_vector_node(branch(0))) 13467 | { 13468 | vec0_node_ptr_ = static_cast<vector_node<T>*>(branch(0)); 13469 | vds() = vec0_node_ptr_->vds(); 13470 | } 13471 | 13472 | if (is_vector_node(branch(1))) 13473 | { 13474 | vec1_node_ptr_ = static_cast<vector_node<T>*>(branch(1)); 13475 | vec1_node_ptr_->vds() = vds(); 13476 | } 13477 | else if (is_ivector_node(branch(1))) 13478 | { 13479 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 13480 | 13481 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1)))) 13482 | { 13483 | vec1_node_ptr_ = vi->vec(); 13484 | vec1_node_ptr_->vds() = vi->vds(); 13485 | } 13486 | else 13487 | vds_t::match_sizes(vds(),vec1_node_ptr_->vds()); 13488 | } 13489 | 13490 | initialised_ = 13491 | vec0_node_ptr_ && 13492 | vec1_node_ptr_ && 13493 | (size() <= base_size()) && 13494 | binary_node<T>::valid(); 13495 | 13496 | assert(valid()); 13497 | } 13498 | 13499 | inline T value() const exprtk_override 13500 | { 13501 | branch(0)->value(); 13502 | branch(1)->value(); 13503 | 13504 | T* vec0 = vec0_node_ptr_->vds().data(); 13505 | const T* vec1 = vec1_node_ptr_->vds().data(); 13506 | 13507 | loop_unroll::details lud(size()); 13508 | const T* upper_bound = vec0 + lud.upper_bound; 13509 | 13510 | while (vec0 < upper_bound) 13511 | { 13512 | #define exprtk_loop(N) \ 13513 | vec0[N] = Operation::process(vec0[N], vec1[N]); \ 13514 | 13515 | exprtk_loop( 0) exprtk_loop( 1) 13516 | exprtk_loop( 2) exprtk_loop( 3) 13517 | #ifndef exprtk_disable_superscalar_unroll 13518 | exprtk_loop( 4) exprtk_loop( 5) 13519 | exprtk_loop( 6) exprtk_loop( 7) 13520 | exprtk_loop( 8) exprtk_loop( 9) 13521 | exprtk_loop(10) exprtk_loop(11) 13522 | exprtk_loop(12) exprtk_loop(13) 13523 | exprtk_loop(14) exprtk_loop(15) 13524 | #endif 13525 | 13526 | vec0 += lud.batch_size; 13527 | vec1 += lud.batch_size; 13528 | } 13529 | 13530 | int i = 0; 13531 | 13532 | switch (lud.remainder) 13533 | { 13534 | #define case_stmt(N,fall_through) \ 13535 | case N : { vec0[i] = Operation::process(vec0[i], vec1[i]); ++i; } \ 13536 | fall_through \ 13537 | 13538 | #ifndef exprtk_disable_superscalar_unroll 13539 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 13540 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 13541 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 13542 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 13543 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 13544 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 13545 | #endif 13546 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 13547 | case_stmt( 1, (void)0;) 13548 | } 13549 | 13550 | #undef exprtk_loop 13551 | #undef case_stmt 13552 | 13553 | return vec0_node_ptr_->value(); 13554 | } 13555 | 13556 | vector_node_ptr vec() const exprtk_override 13557 | { 13558 | return vec0_node_ptr_; 13559 | } 13560 | 13561 | vector_node_ptr vec() exprtk_override 13562 | { 13563 | return vec0_node_ptr_; 13564 | } 13565 | 13566 | inline typename expression_node<T>::node_type type() const exprtk_override 13567 | { 13568 | return expression_node<T>::e_vecopvecass; 13569 | } 13570 | 13571 | inline bool valid() const exprtk_override 13572 | { 13573 | return initialised_; 13574 | } 13575 | 13576 | std::size_t size() const exprtk_override 13577 | { 13578 | return std::min( 13579 | vec0_node_ptr_->vec_holder().size(), 13580 | vec1_node_ptr_->vec_holder().size()); 13581 | } 13582 | 13583 | std::size_t base_size() const exprtk_override 13584 | { 13585 | return std::min( 13586 | vec0_node_ptr_->vec_holder().base_size(), 13587 | vec1_node_ptr_->vec_holder().base_size()); 13588 | } 13589 | 13590 | vds_t& vds() exprtk_override 13591 | { 13592 | return vds_; 13593 | } 13594 | 13595 | const vds_t& vds() const exprtk_override 13596 | { 13597 | return vds_; 13598 | } 13599 | 13600 | bool side_effect() const exprtk_override 13601 | { 13602 | return true; 13603 | } 13604 | 13605 | private: 13606 | 13607 | vector_node<T>* vec0_node_ptr_; 13608 | vector_node<T>* vec1_node_ptr_; 13609 | bool initialised_; 13610 | vds_t vds_; 13611 | }; 13612 | 13613 | template <typename T> 13614 | struct memory_context_t 13615 | { 13616 | typedef vector_node<T>* vector_node_ptr; 13617 | typedef vector_holder<T> vector_holder_t; 13618 | typedef vector_holder_t* vector_holder_ptr; 13619 | 13620 | memory_context_t() 13621 | : temp_(0) 13622 | , temp_vec_node_(0) 13623 | {} 13624 | 13625 | void clear() 13626 | { 13627 | delete temp_vec_node_; 13628 | delete temp_; 13629 | } 13630 | 13631 | vector_holder_ptr temp_; 13632 | vector_node_ptr temp_vec_node_; 13633 | }; 13634 | 13635 | template <typename T> 13636 | inline memory_context_t<T> make_memory_context(vector_holder<T>& vec_holder, 13637 | vec_data_store<T>& vds) 13638 | { 13639 | memory_context_t<T> result_ctxt; 13640 | 13641 | result_ctxt.temp_ = (vec_holder.rebaseable()) ? 13642 | new vector_holder<T>(vec_holder,vds) : 13643 | new vector_holder<T>(vds) ; 13644 | 13645 | result_ctxt.temp_vec_node_ = new vector_node<T>(vds,result_ctxt.temp_); 13646 | 13647 | return result_ctxt; 13648 | } 13649 | 13650 | template <typename T> 13651 | inline memory_context_t<T> make_memory_context(vector_holder<T>& vec_holder0, 13652 | vector_holder<T>& vec_holder1, 13653 | vec_data_store<T>& vds) 13654 | { 13655 | memory_context_t<T> result_ctxt; 13656 | 13657 | if (!vec_holder0.rebaseable() && !vec_holder1.rebaseable()) 13658 | result_ctxt.temp_ = new vector_holder<T>(vds); 13659 | else if (vec_holder0.rebaseable() && !vec_holder1.rebaseable()) 13660 | result_ctxt.temp_ = new vector_holder<T>(vec_holder0,vds); 13661 | else if (!vec_holder0.rebaseable() && vec_holder1.rebaseable()) 13662 | result_ctxt.temp_ = new vector_holder<T>(vec_holder1,vds); 13663 | else 13664 | { 13665 | result_ctxt.temp_ = (vec_holder0.base_size() >= vec_holder1.base_size()) ? 13666 | new vector_holder<T>(vec_holder0, vds) : 13667 | new vector_holder<T>(vec_holder1, vds) ; 13668 | } 13669 | 13670 | result_ctxt.temp_vec_node_ = new vector_node<T>(vds,result_ctxt.temp_); 13671 | 13672 | return result_ctxt; 13673 | } 13674 | 13675 | template <typename T, typename Operation> 13676 | class vec_binop_vecvec_node exprtk_final 13677 | : public binary_node <T> 13678 | , public vector_interface<T> 13679 | { 13680 | public: 13681 | 13682 | typedef expression_node<T>* expression_ptr; 13683 | typedef vector_node<T>* vector_node_ptr; 13684 | typedef vector_holder<T> vector_holder_t; 13685 | typedef vector_holder_t* vector_holder_ptr; 13686 | typedef vec_data_store<T> vds_t; 13687 | typedef memory_context_t<T> memory_context; 13688 | 13689 | using binary_node<T>::branch; 13690 | 13691 | vec_binop_vecvec_node(const operator_type& opr, 13692 | expression_ptr branch0, 13693 | expression_ptr branch1) 13694 | : binary_node<T>(opr, branch0, branch1) 13695 | , vec0_node_ptr_(0) 13696 | , vec1_node_ptr_(0) 13697 | , initialised_(false) 13698 | { 13699 | bool v0_is_ivec = false; 13700 | bool v1_is_ivec = false; 13701 | 13702 | if (is_vector_node(branch(0))) 13703 | { 13704 | vec0_node_ptr_ = static_cast<vector_node_ptr>(branch(0)); 13705 | } 13706 | else if (is_ivector_node(branch(0))) 13707 | { 13708 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 13709 | 13710 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(0)))) 13711 | { 13712 | vec0_node_ptr_ = vi->vec(); 13713 | v0_is_ivec = true; 13714 | } 13715 | } 13716 | 13717 | if (is_vector_node(branch(1))) 13718 | { 13719 | vec1_node_ptr_ = static_cast<vector_node_ptr>(branch(1)); 13720 | } 13721 | else if (is_ivector_node(branch(1))) 13722 | { 13723 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 13724 | 13725 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1)))) 13726 | { 13727 | vec1_node_ptr_ = vi->vec(); 13728 | v1_is_ivec = true; 13729 | } 13730 | } 13731 | 13732 | if (vec0_node_ptr_ && vec1_node_ptr_) 13733 | { 13734 | vector_holder<T>& vec0 = vec0_node_ptr_->vec_holder(); 13735 | vector_holder<T>& vec1 = vec1_node_ptr_->vec_holder(); 13736 | 13737 | if (v0_is_ivec && (vec0.base_size() <= vec1.base_size())) 13738 | { 13739 | vds_ = vds_t(vec0_node_ptr_->vds()); 13740 | } 13741 | else if (v1_is_ivec && (vec1.base_size() <= vec0.base_size())) 13742 | { 13743 | vds_ = vds_t(vec1_node_ptr_->vds()); 13744 | } 13745 | else 13746 | { 13747 | vds_ = vds_t(std::min(vec0.base_size(),vec1.base_size())); 13748 | } 13749 | 13750 | memory_context_ = make_memory_context(vec0, vec1, vds()); 13751 | 13752 | initialised_ = 13753 | (size() <= base_size()) && 13754 | binary_node<T>::valid(); 13755 | } 13756 | 13757 | assert(valid()); 13758 | } 13759 | 13760 | ~vec_binop_vecvec_node() 13761 | { 13762 | memory_context_.clear(); 13763 | } 13764 | 13765 | inline T value() const exprtk_override 13766 | { 13767 | branch(0)->value(); 13768 | branch(1)->value(); 13769 | 13770 | const T* vec0 = vec0_node_ptr_->vds().data(); 13771 | const T* vec1 = vec1_node_ptr_->vds().data(); 13772 | T* vec2 = vds().data(); 13773 | 13774 | loop_unroll::details lud(size()); 13775 | const T* upper_bound = vec2 + lud.upper_bound; 13776 | 13777 | while (vec2 < upper_bound) 13778 | { 13779 | #define exprtk_loop(N) \ 13780 | vec2[N] = Operation::process(vec0[N], vec1[N]); \ 13781 | 13782 | exprtk_loop( 0) exprtk_loop( 1) 13783 | exprtk_loop( 2) exprtk_loop( 3) 13784 | #ifndef exprtk_disable_superscalar_unroll 13785 | exprtk_loop( 4) exprtk_loop( 5) 13786 | exprtk_loop( 6) exprtk_loop( 7) 13787 | exprtk_loop( 8) exprtk_loop( 9) 13788 | exprtk_loop(10) exprtk_loop(11) 13789 | exprtk_loop(12) exprtk_loop(13) 13790 | exprtk_loop(14) exprtk_loop(15) 13791 | #endif 13792 | 13793 | vec0 += lud.batch_size; 13794 | vec1 += lud.batch_size; 13795 | vec2 += lud.batch_size; 13796 | } 13797 | 13798 | int i = 0; 13799 | 13800 | switch (lud.remainder) 13801 | { 13802 | #define case_stmt(N) \ 13803 | case N : { vec2[i] = Operation::process(vec0[i], vec1[i]); ++i; } \ 13804 | exprtk_fallthrough \ 13805 | 13806 | #ifndef exprtk_disable_superscalar_unroll 13807 | case_stmt(15) case_stmt(14) 13808 | case_stmt(13) case_stmt(12) 13809 | case_stmt(11) case_stmt(10) 13810 | case_stmt( 9) case_stmt( 8) 13811 | case_stmt( 7) case_stmt( 6) 13812 | case_stmt( 5) case_stmt( 4) 13813 | #endif 13814 | case_stmt( 3) case_stmt( 2) 13815 | case_stmt( 1) 13816 | default: break; 13817 | } 13818 | 13819 | #undef exprtk_loop 13820 | #undef case_stmt 13821 | 13822 | return (vds().data())[0]; 13823 | } 13824 | 13825 | vector_node_ptr vec() const exprtk_override 13826 | { 13827 | return memory_context_.temp_vec_node_; 13828 | } 13829 | 13830 | vector_node_ptr vec() exprtk_override 13831 | { 13832 | return memory_context_.temp_vec_node_; 13833 | } 13834 | 13835 | inline typename expression_node<T>::node_type type() const exprtk_override 13836 | { 13837 | return expression_node<T>::e_vecvecarith; 13838 | } 13839 | 13840 | inline bool valid() const exprtk_override 13841 | { 13842 | return initialised_; 13843 | } 13844 | 13845 | std::size_t size() const exprtk_override 13846 | { 13847 | return std::min( 13848 | vec0_node_ptr_->vec_holder().size(), 13849 | vec1_node_ptr_->vec_holder().size()); 13850 | } 13851 | 13852 | std::size_t base_size() const exprtk_override 13853 | { 13854 | return std::min( 13855 | vec0_node_ptr_->vec_holder().base_size(), 13856 | vec1_node_ptr_->vec_holder().base_size()); 13857 | } 13858 | 13859 | vds_t& vds() exprtk_override 13860 | { 13861 | return vds_; 13862 | } 13863 | 13864 | const vds_t& vds() const exprtk_override 13865 | { 13866 | return vds_; 13867 | } 13868 | 13869 | private: 13870 | 13871 | vector_node_ptr vec0_node_ptr_; 13872 | vector_node_ptr vec1_node_ptr_; 13873 | bool initialised_; 13874 | vds_t vds_; 13875 | memory_context memory_context_; 13876 | }; 13877 | 13878 | template <typename T, typename Operation> 13879 | class vec_binop_vecval_node exprtk_final 13880 | : public binary_node <T> 13881 | , public vector_interface<T> 13882 | { 13883 | public: 13884 | 13885 | typedef expression_node<T>* expression_ptr; 13886 | typedef vector_node<T>* vector_node_ptr; 13887 | typedef vector_holder<T> vector_holder_t; 13888 | typedef vector_holder_t* vector_holder_ptr; 13889 | typedef vec_data_store<T> vds_t; 13890 | typedef memory_context_t<T> memory_context; 13891 | 13892 | using binary_node<T>::branch; 13893 | 13894 | vec_binop_vecval_node(const operator_type& opr, 13895 | expression_ptr branch0, 13896 | expression_ptr branch1) 13897 | : binary_node<T>(opr, branch0, branch1) 13898 | , vec0_node_ptr_(0) 13899 | { 13900 | bool v0_is_ivec = false; 13901 | 13902 | if (is_vector_node(branch(0))) 13903 | { 13904 | vec0_node_ptr_ = static_cast<vector_node_ptr>(branch(0)); 13905 | } 13906 | else if (is_ivector_node(branch(0))) 13907 | { 13908 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 13909 | 13910 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(0)))) 13911 | { 13912 | vec0_node_ptr_ = vi->vec(); 13913 | v0_is_ivec = true; 13914 | } 13915 | } 13916 | 13917 | if (vec0_node_ptr_) 13918 | { 13919 | if (v0_is_ivec) 13920 | vds() = vec0_node_ptr_->vds(); 13921 | else 13922 | vds() = vds_t(vec0_node_ptr_->base_size()); 13923 | 13924 | memory_context_ = make_memory_context(vec0_node_ptr_->vec_holder(), vds()); 13925 | } 13926 | 13927 | assert(valid()); 13928 | } 13929 | 13930 | ~vec_binop_vecval_node() 13931 | { 13932 | memory_context_.clear(); 13933 | } 13934 | 13935 | inline T value() const exprtk_override 13936 | { 13937 | branch(0)->value(); 13938 | const T v = branch(1)->value(); 13939 | 13940 | const T* vec0 = vec0_node_ptr_->vds().data(); 13941 | T* vec1 = vds().data(); 13942 | 13943 | loop_unroll::details lud(size()); 13944 | const T* upper_bound = vec0 + lud.upper_bound; 13945 | 13946 | while (vec0 < upper_bound) 13947 | { 13948 | #define exprtk_loop(N) \ 13949 | vec1[N] = Operation::process(vec0[N], v); \ 13950 | 13951 | exprtk_loop( 0) exprtk_loop( 1) 13952 | exprtk_loop( 2) exprtk_loop( 3) 13953 | #ifndef exprtk_disable_superscalar_unroll 13954 | exprtk_loop( 4) exprtk_loop( 5) 13955 | exprtk_loop( 6) exprtk_loop( 7) 13956 | exprtk_loop( 8) exprtk_loop( 9) 13957 | exprtk_loop(10) exprtk_loop(11) 13958 | exprtk_loop(12) exprtk_loop(13) 13959 | exprtk_loop(14) exprtk_loop(15) 13960 | #endif 13961 | 13962 | vec0 += lud.batch_size; 13963 | vec1 += lud.batch_size; 13964 | } 13965 | 13966 | int i = 0; 13967 | 13968 | switch (lud.remainder) 13969 | { 13970 | #define case_stmt(N,fall_through) \ 13971 | case N : { vec1[i] = Operation::process(vec0[i], v); ++i; } \ 13972 | fall_through \ 13973 | 13974 | #ifndef exprtk_disable_superscalar_unroll 13975 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 13976 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 13977 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 13978 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 13979 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 13980 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 13981 | #endif 13982 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 13983 | case_stmt( 1, (void)0;) 13984 | } 13985 | 13986 | #undef exprtk_loop 13987 | #undef case_stmt 13988 | 13989 | return (vds().data())[0]; 13990 | } 13991 | 13992 | vector_node_ptr vec() const exprtk_override 13993 | { 13994 | return memory_context_.temp_vec_node_; 13995 | } 13996 | 13997 | vector_node_ptr vec() exprtk_override 13998 | { 13999 | return memory_context_.temp_vec_node_; 14000 | } 14001 | 14002 | inline typename expression_node<T>::node_type type() const exprtk_override 14003 | { 14004 | return expression_node<T>::e_vecvalarith; 14005 | } 14006 | 14007 | inline bool valid() const exprtk_override 14008 | { 14009 | return 14010 | vec0_node_ptr_ && 14011 | (size() <= base_size()) && 14012 | binary_node<T>::valid(); 14013 | } 14014 | 14015 | std::size_t size() const exprtk_override 14016 | { 14017 | return vec0_node_ptr_->size(); 14018 | } 14019 | 14020 | std::size_t base_size() const exprtk_override 14021 | { 14022 | return vec0_node_ptr_->vec_holder().base_size(); 14023 | } 14024 | 14025 | vds_t& vds() exprtk_override 14026 | { 14027 | return vds_; 14028 | } 14029 | 14030 | const vds_t& vds() const exprtk_override 14031 | { 14032 | return vds_; 14033 | } 14034 | 14035 | private: 14036 | 14037 | vector_node_ptr vec0_node_ptr_; 14038 | vds_t vds_; 14039 | memory_context memory_context_; 14040 | }; 14041 | 14042 | template <typename T, typename Operation> 14043 | class vec_binop_valvec_node exprtk_final 14044 | : public binary_node <T> 14045 | , public vector_interface<T> 14046 | { 14047 | public: 14048 | 14049 | typedef expression_node<T>* expression_ptr; 14050 | typedef vector_node<T>* vector_node_ptr; 14051 | typedef vector_holder<T> vector_holder_t; 14052 | typedef vector_holder_t* vector_holder_ptr; 14053 | typedef vec_data_store<T> vds_t; 14054 | typedef memory_context_t<T> memory_context; 14055 | 14056 | using binary_node<T>::branch; 14057 | 14058 | vec_binop_valvec_node(const operator_type& opr, 14059 | expression_ptr branch0, 14060 | expression_ptr branch1) 14061 | : binary_node<T>(opr, branch0, branch1) 14062 | , vec1_node_ptr_(0) 14063 | { 14064 | bool v1_is_ivec = false; 14065 | 14066 | if (is_vector_node(branch(1))) 14067 | { 14068 | vec1_node_ptr_ = static_cast<vector_node_ptr>(branch(1)); 14069 | } 14070 | else if (is_ivector_node(branch(1))) 14071 | { 14072 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 14073 | 14074 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1)))) 14075 | { 14076 | vec1_node_ptr_ = vi->vec(); 14077 | v1_is_ivec = true; 14078 | } 14079 | } 14080 | 14081 | if (vec1_node_ptr_) 14082 | { 14083 | if (v1_is_ivec) 14084 | vds() = vec1_node_ptr_->vds(); 14085 | else 14086 | vds() = vds_t(vec1_node_ptr_->base_size()); 14087 | 14088 | memory_context_ = make_memory_context(vec1_node_ptr_->vec_holder(), vds()); 14089 | } 14090 | 14091 | assert(valid()); 14092 | } 14093 | 14094 | ~vec_binop_valvec_node() 14095 | { 14096 | memory_context_.clear(); 14097 | } 14098 | 14099 | inline T value() const exprtk_override 14100 | { 14101 | const T v = branch(0)->value(); 14102 | branch(1)->value(); 14103 | 14104 | T* vec0 = vds().data(); 14105 | const T* vec1 = vec1_node_ptr_->vds().data(); 14106 | 14107 | loop_unroll::details lud(size()); 14108 | const T* upper_bound = vec0 + lud.upper_bound; 14109 | 14110 | while (vec0 < upper_bound) 14111 | { 14112 | #define exprtk_loop(N) \ 14113 | vec0[N] = Operation::process(v, vec1[N]); \ 14114 | 14115 | exprtk_loop( 0) exprtk_loop( 1) 14116 | exprtk_loop( 2) exprtk_loop( 3) 14117 | #ifndef exprtk_disable_superscalar_unroll 14118 | exprtk_loop( 4) exprtk_loop( 5) 14119 | exprtk_loop( 6) exprtk_loop( 7) 14120 | exprtk_loop( 8) exprtk_loop( 9) 14121 | exprtk_loop(10) exprtk_loop(11) 14122 | exprtk_loop(12) exprtk_loop(13) 14123 | exprtk_loop(14) exprtk_loop(15) 14124 | #endif 14125 | 14126 | vec0 += lud.batch_size; 14127 | vec1 += lud.batch_size; 14128 | } 14129 | 14130 | int i = 0; 14131 | 14132 | switch (lud.remainder) 14133 | { 14134 | #define case_stmt(N,fall_through) \ 14135 | case N : { vec0[i] = Operation::process(v, vec1[i]); ++i; } \ 14136 | fall_through \ 14137 | 14138 | #ifndef exprtk_disable_superscalar_unroll 14139 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 14140 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 14141 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 14142 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 14143 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 14144 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 14145 | #endif 14146 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 14147 | case_stmt( 1, (void)0;) 14148 | } 14149 | 14150 | #undef exprtk_loop 14151 | #undef case_stmt 14152 | 14153 | return (vds().data())[0]; 14154 | } 14155 | 14156 | vector_node_ptr vec() const exprtk_override 14157 | { 14158 | return memory_context_.temp_vec_node_; 14159 | } 14160 | 14161 | vector_node_ptr vec() exprtk_override 14162 | { 14163 | return memory_context_.temp_vec_node_; 14164 | } 14165 | 14166 | inline typename expression_node<T>::node_type type() const exprtk_override 14167 | { 14168 | return expression_node<T>::e_vecvalarith; 14169 | } 14170 | 14171 | inline bool valid() const exprtk_override 14172 | { 14173 | return 14174 | vec1_node_ptr_ && 14175 | (size() <= base_size()) && 14176 | (vds_.size() <= base_size()) && 14177 | binary_node<T>::valid(); 14178 | } 14179 | 14180 | std::size_t size() const exprtk_override 14181 | { 14182 | return vec1_node_ptr_->vec_holder().size(); 14183 | } 14184 | 14185 | std::size_t base_size() const exprtk_override 14186 | { 14187 | return vec1_node_ptr_->vec_holder().base_size(); 14188 | } 14189 | 14190 | vds_t& vds() exprtk_override 14191 | { 14192 | return vds_; 14193 | } 14194 | 14195 | const vds_t& vds() const exprtk_override 14196 | { 14197 | return vds_; 14198 | } 14199 | 14200 | private: 14201 | 14202 | vector_node_ptr vec1_node_ptr_; 14203 | vds_t vds_; 14204 | memory_context memory_context_; 14205 | }; 14206 | 14207 | template <typename T, typename Operation> 14208 | class unary_vector_node exprtk_final 14209 | : public unary_node <T> 14210 | , public vector_interface<T> 14211 | { 14212 | public: 14213 | 14214 | typedef expression_node<T>* expression_ptr; 14215 | typedef vector_node<T>* vector_node_ptr; 14216 | typedef vector_holder<T> vector_holder_t; 14217 | typedef vector_holder_t* vector_holder_ptr; 14218 | typedef vec_data_store<T> vds_t; 14219 | typedef memory_context_t<T> memory_context; 14220 | 14221 | using expression_node<T>::branch; 14222 | 14223 | unary_vector_node(const operator_type& opr, expression_ptr branch0) 14224 | : unary_node<T>(opr, branch0) 14225 | , vec0_node_ptr_(0) 14226 | { 14227 | bool vec0_is_ivec = false; 14228 | 14229 | if (is_vector_node(branch(0))) 14230 | { 14231 | vec0_node_ptr_ = static_cast<vector_node_ptr>(branch(0)); 14232 | } 14233 | else if (is_ivector_node(branch(0))) 14234 | { 14235 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 14236 | 14237 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(0)))) 14238 | { 14239 | vec0_node_ptr_ = vi->vec(); 14240 | vec0_is_ivec = true; 14241 | } 14242 | } 14243 | 14244 | if (vec0_node_ptr_) 14245 | { 14246 | if (vec0_is_ivec) 14247 | vds_ = vec0_node_ptr_->vds(); 14248 | else 14249 | vds_ = vds_t(vec0_node_ptr_->base_size()); 14250 | 14251 | memory_context_ = make_memory_context(vec0_node_ptr_->vec_holder(), vds()); 14252 | } 14253 | 14254 | assert(valid()); 14255 | } 14256 | 14257 | ~unary_vector_node() 14258 | { 14259 | memory_context_.clear(); 14260 | } 14261 | 14262 | inline T value() const exprtk_override 14263 | { 14264 | branch()->value(); 14265 | 14266 | const T* vec0 = vec0_node_ptr_->vds().data(); 14267 | T* vec1 = vds().data(); 14268 | 14269 | loop_unroll::details lud(size()); 14270 | const T* upper_bound = vec0 + lud.upper_bound; 14271 | 14272 | while (vec0 < upper_bound) 14273 | { 14274 | #define exprtk_loop(N) \ 14275 | vec1[N] = Operation::process(vec0[N]); \ 14276 | 14277 | exprtk_loop( 0) exprtk_loop( 1) 14278 | exprtk_loop( 2) exprtk_loop( 3) 14279 | #ifndef exprtk_disable_superscalar_unroll 14280 | exprtk_loop( 4) exprtk_loop( 5) 14281 | exprtk_loop( 6) exprtk_loop( 7) 14282 | exprtk_loop( 8) exprtk_loop( 9) 14283 | exprtk_loop(10) exprtk_loop(11) 14284 | exprtk_loop(12) exprtk_loop(13) 14285 | exprtk_loop(14) exprtk_loop(15) 14286 | #endif 14287 | 14288 | vec0 += lud.batch_size; 14289 | vec1 += lud.batch_size; 14290 | } 14291 | 14292 | int i = 0; 14293 | 14294 | switch (lud.remainder) 14295 | { 14296 | #define case_stmt(N) \ 14297 | case N : { vec1[i] = Operation::process(vec0[i]); ++i; } \ 14298 | exprtk_fallthrough \ 14299 | 14300 | #ifndef exprtk_disable_superscalar_unroll 14301 | case_stmt(15) case_stmt(14) 14302 | case_stmt(13) case_stmt(12) 14303 | case_stmt(11) case_stmt(10) 14304 | case_stmt( 9) case_stmt( 8) 14305 | case_stmt( 7) case_stmt( 6) 14306 | case_stmt( 5) case_stmt( 4) 14307 | #endif 14308 | case_stmt( 3) case_stmt( 2) 14309 | case_stmt( 1) 14310 | default: break; 14311 | } 14312 | 14313 | #undef exprtk_loop 14314 | #undef case_stmt 14315 | 14316 | return (vds().data())[0]; 14317 | } 14318 | 14319 | vector_node_ptr vec() const exprtk_override 14320 | { 14321 | return memory_context_.temp_vec_node_; 14322 | } 14323 | 14324 | vector_node_ptr vec() exprtk_override 14325 | { 14326 | return memory_context_.temp_vec_node_; 14327 | } 14328 | 14329 | inline typename expression_node<T>::node_type type() const exprtk_override 14330 | { 14331 | return expression_node<T>::e_vecunaryop; 14332 | } 14333 | 14334 | inline bool valid() const exprtk_override 14335 | { 14336 | return vec0_node_ptr_ && unary_node<T>::valid(); 14337 | } 14338 | 14339 | std::size_t size() const exprtk_override 14340 | { 14341 | return vec0_node_ptr_->vec_holder().size(); 14342 | } 14343 | 14344 | std::size_t base_size() const exprtk_override 14345 | { 14346 | return vec0_node_ptr_->vec_holder().base_size(); 14347 | } 14348 | 14349 | vds_t& vds() exprtk_override 14350 | { 14351 | return vds_; 14352 | } 14353 | 14354 | const vds_t& vds() const exprtk_override 14355 | { 14356 | return vds_; 14357 | } 14358 | 14359 | private: 14360 | 14361 | vector_node_ptr vec0_node_ptr_; 14362 | vds_t vds_; 14363 | memory_context memory_context_; 14364 | }; 14365 | 14366 | template <typename T> 14367 | class conditional_vector_node exprtk_final 14368 | : public expression_node <T> 14369 | , public vector_interface<T> 14370 | { 14371 | public: 14372 | 14373 | typedef expression_node <T>* expression_ptr; 14374 | typedef vector_interface<T>* vec_interface_ptr; 14375 | typedef vector_node <T>* vector_node_ptr; 14376 | typedef vector_holder <T> vector_holder_t; 14377 | typedef vector_holder_t* vector_holder_ptr; 14378 | typedef vec_data_store <T> vds_t; 14379 | typedef memory_context_t<T> memory_context; 14380 | typedef std::pair<expression_ptr,bool> branch_t; 14381 | 14382 | conditional_vector_node(expression_ptr condition, 14383 | expression_ptr consequent, 14384 | expression_ptr alternative) 14385 | : consequent_node_ptr_ (0) 14386 | , alternative_node_ptr_(0) 14387 | , temp_vec_node_ (0) 14388 | , temp_ (0) 14389 | , result_vec_size_ (0) 14390 | , initialised_ (false) 14391 | { 14392 | construct_branch_pair(condition_ , condition ); 14393 | construct_branch_pair(consequent_ , consequent ); 14394 | construct_branch_pair(alternative_, alternative); 14395 | 14396 | if (details::is_ivector_node(consequent_.first)) 14397 | { 14398 | vec_interface_ptr ivec_ptr = dynamic_cast<vec_interface_ptr>(consequent_.first); 14399 | 14400 | if (0 != ivec_ptr) 14401 | { 14402 | consequent_node_ptr_ = ivec_ptr->vec(); 14403 | } 14404 | } 14405 | 14406 | if (details::is_ivector_node(alternative_.first)) 14407 | { 14408 | vec_interface_ptr ivec_ptr = dynamic_cast<vec_interface_ptr>(alternative_.first); 14409 | 14410 | if (0 != ivec_ptr) 14411 | { 14412 | alternative_node_ptr_ = ivec_ptr->vec(); 14413 | } 14414 | } 14415 | 14416 | if (consequent_node_ptr_ && alternative_node_ptr_) 14417 | { 14418 | const std::size_t vec_size = 14419 | std::max(consequent_node_ptr_ ->vec_holder().base_size(), 14420 | alternative_node_ptr_->vec_holder().base_size()); 14421 | 14422 | vds_ = vds_t(vec_size); 14423 | memory_context_ = make_memory_context( 14424 | consequent_node_ptr_ ->vec_holder(), 14425 | alternative_node_ptr_->vec_holder(), 14426 | vds()); 14427 | 14428 | initialised_ = (vec_size > 0); 14429 | } 14430 | 14431 | assert(initialised_); 14432 | } 14433 | 14434 | ~conditional_vector_node() 14435 | { 14436 | memory_context_.clear(); 14437 | } 14438 | 14439 | inline T value() const exprtk_override 14440 | { 14441 | T result = T(0); 14442 | T* source_vector = 0; 14443 | T* result_vector = vds().data(); 14444 | 14445 | if (is_true(condition_)) 14446 | { 14447 | result = consequent_.first->value(); 14448 | source_vector = consequent_node_ptr_->vds().data(); 14449 | result_vec_size_ = consequent_node_ptr_->size(); 14450 | } 14451 | else 14452 | { 14453 | result = alternative_.first->value(); 14454 | source_vector = alternative_node_ptr_->vds().data(); 14455 | result_vec_size_ = alternative_node_ptr_->size(); 14456 | } 14457 | 14458 | for (std::size_t i = 0; i < result_vec_size_; ++i) 14459 | { 14460 | result_vector[i] = source_vector[i]; 14461 | } 14462 | 14463 | return result; 14464 | } 14465 | 14466 | vector_node_ptr vec() const exprtk_override 14467 | { 14468 | return memory_context_.temp_vec_node_; 14469 | } 14470 | 14471 | vector_node_ptr vec() exprtk_override 14472 | { 14473 | return memory_context_.temp_vec_node_; 14474 | } 14475 | 14476 | inline typename expression_node<T>::node_type type() const exprtk_override 14477 | { 14478 | return expression_node<T>::e_vecondition; 14479 | } 14480 | 14481 | inline bool valid() const exprtk_override 14482 | { 14483 | return 14484 | initialised_ && 14485 | condition_ .first && condition_ .first->valid() && 14486 | consequent_ .first && consequent_ .first->valid() && 14487 | alternative_.first && alternative_.first->valid() && 14488 | size() <= base_size(); 14489 | } 14490 | 14491 | std::size_t size() const exprtk_override 14492 | { 14493 | return result_vec_size_; 14494 | } 14495 | 14496 | std::size_t base_size() const exprtk_override 14497 | { 14498 | return std::min( 14499 | consequent_node_ptr_ ->vec_holder().base_size(), 14500 | alternative_node_ptr_->vec_holder().base_size()); 14501 | } 14502 | 14503 | vds_t& vds() exprtk_override 14504 | { 14505 | return vds_; 14506 | } 14507 | 14508 | const vds_t& vds() const exprtk_override 14509 | { 14510 | return vds_; 14511 | } 14512 | 14513 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 14514 | { 14515 | expression_node<T>::ndb_t::collect(condition_ , node_delete_list); 14516 | expression_node<T>::ndb_t::collect(consequent_ , node_delete_list); 14517 | expression_node<T>::ndb_t::collect(alternative_ , node_delete_list); 14518 | } 14519 | 14520 | std::size_t node_depth() const exprtk_override 14521 | { 14522 | return expression_node<T>::ndb_t::compute_node_depth 14523 | (condition_, consequent_, alternative_); 14524 | } 14525 | 14526 | private: 14527 | 14528 | branch_t condition_; 14529 | branch_t consequent_; 14530 | branch_t alternative_; 14531 | vector_node_ptr consequent_node_ptr_; 14532 | vector_node_ptr alternative_node_ptr_; 14533 | vector_node_ptr temp_vec_node_; 14534 | vector_holder_ptr temp_; 14535 | vds_t vds_; 14536 | mutable std::size_t result_vec_size_; 14537 | bool initialised_; 14538 | memory_context memory_context_; 14539 | }; 14540 | 14541 | template <typename T> 14542 | class scand_node exprtk_final : public binary_node<T> 14543 | { 14544 | public: 14545 | 14546 | typedef expression_node<T>* expression_ptr; 14547 | using binary_node<T>::branch; 14548 | 14549 | scand_node(const operator_type& opr, 14550 | expression_ptr branch0, 14551 | expression_ptr branch1) 14552 | : binary_node<T>(opr, branch0, branch1) 14553 | { 14554 | assert(binary_node<T>::valid()); 14555 | } 14556 | 14557 | inline T value() const exprtk_override 14558 | { 14559 | return ( 14560 | std::not_equal_to<T>() 14561 | (T(0),branch(0)->value()) && 14562 | std::not_equal_to<T>() 14563 | (T(0),branch(1)->value()) 14564 | ) ? T(1) : T(0); 14565 | } 14566 | }; 14567 | 14568 | template <typename T> 14569 | class scor_node exprtk_final : public binary_node<T> 14570 | { 14571 | public: 14572 | 14573 | typedef expression_node<T>* expression_ptr; 14574 | using binary_node<T>::branch; 14575 | 14576 | scor_node(const operator_type& opr, 14577 | expression_ptr branch0, 14578 | expression_ptr branch1) 14579 | : binary_node<T>(opr, branch0, branch1) 14580 | { 14581 | assert(binary_node<T>::valid()); 14582 | } 14583 | 14584 | inline T value() const exprtk_override 14585 | { 14586 | return ( 14587 | std::not_equal_to<T>() 14588 | (T(0),branch(0)->value()) || 14589 | std::not_equal_to<T>() 14590 | (T(0),branch(1)->value()) 14591 | ) ? T(1) : T(0); 14592 | } 14593 | }; 14594 | 14595 | template <typename T, typename IFunction, std::size_t N> 14596 | class function_N_node exprtk_final : public expression_node<T> 14597 | { 14598 | public: 14599 | 14600 | // Function of N parameters. 14601 | typedef expression_node<T>* expression_ptr; 14602 | typedef std::pair<expression_ptr,bool> branch_t; 14603 | typedef IFunction ifunction; 14604 | 14605 | explicit function_N_node(ifunction* func) 14606 | : function_((N == func->param_count) ? func : reinterpret_cast<ifunction*>(0)) 14607 | , parameter_count_(func->param_count) 14608 | , initialised_(false) 14609 | {} 14610 | 14611 | template <std::size_t NumBranches> 14612 | bool init_branches(expression_ptr (&b)[NumBranches]) 14613 | { 14614 | // Needed for incompetent and broken msvc compiler versions 14615 | #ifdef _MSC_VER 14616 | #pragma warning(push) 14617 | #pragma warning(disable: 4127) 14618 | #endif 14619 | 14620 | if (N != NumBranches) 14621 | { 14622 | return false; 14623 | } 14624 | 14625 | for (std::size_t i = 0; i < NumBranches; ++i) 14626 | { 14627 | if (b[i] && b[i]->valid()) 14628 | branch_[i] = std::make_pair(b[i],branch_deletable(b[i])); 14629 | else 14630 | return false; 14631 | } 14632 | 14633 | initialised_ = function_; 14634 | assert(valid()); 14635 | return initialised_; 14636 | 14637 | #ifdef _MSC_VER 14638 | #pragma warning(pop) 14639 | #endif 14640 | } 14641 | 14642 | inline bool operator <(const function_N_node<T,IFunction,N>& fn) const 14643 | { 14644 | return this < (&fn); 14645 | } 14646 | 14647 | inline T value() const exprtk_override 14648 | { 14649 | // Needed for incompetent and broken msvc compiler versions 14650 | #ifdef _MSC_VER 14651 | #pragma warning(push) 14652 | #pragma warning(disable: 4127) 14653 | #endif 14654 | 14655 | T v[N]; 14656 | evaluate_branches<T,N>::execute(v,branch_); 14657 | return invoke<T,N>::execute(*function_,v); 14658 | 14659 | #ifdef _MSC_VER 14660 | #pragma warning(pop) 14661 | #endif 14662 | } 14663 | 14664 | inline typename expression_node<T>::node_type type() const exprtk_override 14665 | { 14666 | return expression_node<T>::e_function; 14667 | } 14668 | 14669 | inline bool valid() const exprtk_override 14670 | { 14671 | return initialised_; 14672 | } 14673 | 14674 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 14675 | { 14676 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 14677 | } 14678 | 14679 | std::size_t node_depth() const exprtk_override 14680 | { 14681 | return expression_node<T>::ndb_t::template compute_node_depth<N>(branch_); 14682 | } 14683 | 14684 | template <typename T_, std::size_t BranchCount> 14685 | struct evaluate_branches 14686 | { 14687 | static inline void execute(T_ (&v)[BranchCount], const branch_t (&b)[BranchCount]) 14688 | { 14689 | for (std::size_t i = 0; i < BranchCount; ++i) 14690 | { 14691 | v[i] = b[i].first->value(); 14692 | } 14693 | } 14694 | }; 14695 | 14696 | template <typename T_> 14697 | struct evaluate_branches <T_,6> 14698 | { 14699 | static inline void execute(T_ (&v)[6], const branch_t (&b)[6]) 14700 | { 14701 | v[0] = b[0].first->value(); 14702 | v[1] = b[1].first->value(); 14703 | v[2] = b[2].first->value(); 14704 | v[3] = b[3].first->value(); 14705 | v[4] = b[4].first->value(); 14706 | v[5] = b[5].first->value(); 14707 | } 14708 | }; 14709 | 14710 | template <typename T_> 14711 | struct evaluate_branches <T_,5> 14712 | { 14713 | static inline void execute(T_ (&v)[5], const branch_t (&b)[5]) 14714 | { 14715 | v[0] = b[0].first->value(); 14716 | v[1] = b[1].first->value(); 14717 | v[2] = b[2].first->value(); 14718 | v[3] = b[3].first->value(); 14719 | v[4] = b[4].first->value(); 14720 | } 14721 | }; 14722 | 14723 | template <typename T_> 14724 | struct evaluate_branches <T_,4> 14725 | { 14726 | static inline void execute(T_ (&v)[4], const branch_t (&b)[4]) 14727 | { 14728 | v[0] = b[0].first->value(); 14729 | v[1] = b[1].first->value(); 14730 | v[2] = b[2].first->value(); 14731 | v[3] = b[3].first->value(); 14732 | } 14733 | }; 14734 | 14735 | template <typename T_> 14736 | struct evaluate_branches <T_,3> 14737 | { 14738 | static inline void execute(T_ (&v)[3], const branch_t (&b)[3]) 14739 | { 14740 | v[0] = b[0].first->value(); 14741 | v[1] = b[1].first->value(); 14742 | v[2] = b[2].first->value(); 14743 | } 14744 | }; 14745 | 14746 | template <typename T_> 14747 | struct evaluate_branches <T_,2> 14748 | { 14749 | static inline void execute(T_ (&v)[2], const branch_t (&b)[2]) 14750 | { 14751 | v[0] = b[0].first->value(); 14752 | v[1] = b[1].first->value(); 14753 | } 14754 | }; 14755 | 14756 | template <typename T_> 14757 | struct evaluate_branches <T_,1> 14758 | { 14759 | static inline void execute(T_ (&v)[1], const branch_t (&b)[1]) 14760 | { 14761 | v[0] = b[0].first->value(); 14762 | } 14763 | }; 14764 | 14765 | template <typename T_, std::size_t ParamCount> 14766 | struct invoke { static inline T execute(ifunction&, branch_t (&)[ParamCount]) { return std::numeric_limits<T_>::quiet_NaN(); } }; 14767 | 14768 | template <typename T_> 14769 | struct invoke<T_,20> 14770 | { 14771 | static inline T_ execute(ifunction& f, T_ (&v)[20]) 14772 | { 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]); } 14773 | }; 14774 | 14775 | template <typename T_> 14776 | struct invoke<T_,19> 14777 | { 14778 | static inline T_ execute(ifunction& f, T_ (&v)[19]) 14779 | { 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]); } 14780 | }; 14781 | 14782 | template <typename T_> 14783 | struct invoke<T_,18> 14784 | { 14785 | static inline T_ execute(ifunction& f, T_ (&v)[18]) 14786 | { 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]); } 14787 | }; 14788 | 14789 | template <typename T_> 14790 | struct invoke<T_,17> 14791 | { 14792 | static inline T_ execute(ifunction& f, T_ (&v)[17]) 14793 | { 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]); } 14794 | }; 14795 | 14796 | template <typename T_> 14797 | struct invoke<T_,16> 14798 | { 14799 | static inline T_ execute(ifunction& f, T_ (&v)[16]) 14800 | { 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]); } 14801 | }; 14802 | 14803 | template <typename T_> 14804 | struct invoke<T_,15> 14805 | { 14806 | static inline T_ execute(ifunction& f, T_ (&v)[15]) 14807 | { 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]); } 14808 | }; 14809 | 14810 | template <typename T_> 14811 | struct invoke<T_,14> 14812 | { 14813 | static inline T_ execute(ifunction& f, T_ (&v)[14]) 14814 | { 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]); } 14815 | }; 14816 | 14817 | template <typename T_> 14818 | struct invoke<T_,13> 14819 | { 14820 | static inline T_ execute(ifunction& f, T_ (&v)[13]) 14821 | { 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]); } 14822 | }; 14823 | 14824 | template <typename T_> 14825 | struct invoke<T_,12> 14826 | { 14827 | static inline T_ execute(ifunction& f, T_ (&v)[12]) 14828 | { 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]); } 14829 | }; 14830 | 14831 | template <typename T_> 14832 | struct invoke<T_,11> 14833 | { 14834 | static inline T_ execute(ifunction& f, T_ (&v)[11]) 14835 | { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9], v[10]); } 14836 | }; 14837 | 14838 | template <typename T_> 14839 | struct invoke<T_,10> 14840 | { 14841 | static inline T_ execute(ifunction& f, T_ (&v)[10]) 14842 | { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9]); } 14843 | }; 14844 | 14845 | template <typename T_> 14846 | struct invoke<T_,9> 14847 | { 14848 | static inline T_ execute(ifunction& f, T_ (&v)[9]) 14849 | { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8]); } 14850 | }; 14851 | 14852 | template <typename T_> 14853 | struct invoke<T_,8> 14854 | { 14855 | static inline T_ execute(ifunction& f, T_ (&v)[8]) 14856 | { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]); } 14857 | }; 14858 | 14859 | template <typename T_> 14860 | struct invoke<T_,7> 14861 | { 14862 | static inline T_ execute(ifunction& f, T_ (&v)[7]) 14863 | { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6]); } 14864 | }; 14865 | 14866 | template <typename T_> 14867 | struct invoke<T_,6> 14868 | { 14869 | static inline T_ execute(ifunction& f, T_ (&v)[6]) 14870 | { return f(v[0], v[1], v[2], v[3], v[4], v[5]); } 14871 | }; 14872 | 14873 | template <typename T_> 14874 | struct invoke<T_,5> 14875 | { 14876 | static inline T_ execute(ifunction& f, T_ (&v)[5]) 14877 | { return f(v[0], v[1], v[2], v[3], v[4]); } 14878 | }; 14879 | 14880 | template <typename T_> 14881 | struct invoke<T_,4> 14882 | { 14883 | static inline T_ execute(ifunction& f, T_ (&v)[4]) 14884 | { return f(v[0], v[1], v[2], v[3]); } 14885 | }; 14886 | 14887 | template <typename T_> 14888 | struct invoke<T_,3> 14889 | { 14890 | static inline T_ execute(ifunction& f, T_ (&v)[3]) 14891 | { return f(v[0], v[1], v[2]); } 14892 | }; 14893 | 14894 | template <typename T_> 14895 | struct invoke<T_,2> 14896 | { 14897 | static inline T_ execute(ifunction& f, T_ (&v)[2]) 14898 | { return f(v[0], v[1]); } 14899 | }; 14900 | 14901 | template <typename T_> 14902 | struct invoke<T_,1> 14903 | { 14904 | static inline T_ execute(ifunction& f, T_ (&v)[1]) 14905 | { return f(v[0]); } 14906 | }; 14907 | 14908 | private: 14909 | 14910 | ifunction* function_; 14911 | std::size_t parameter_count_; 14912 | branch_t branch_[N]; 14913 | bool initialised_; 14914 | }; 14915 | 14916 | template <typename T, typename IFunction> 14917 | class function_N_node<T,IFunction,0> exprtk_final : public expression_node<T> 14918 | { 14919 | public: 14920 | 14921 | typedef expression_node<T>* expression_ptr; 14922 | typedef IFunction ifunction; 14923 | 14924 | explicit function_N_node(ifunction* func) 14925 | : function_((0 == func->param_count) ? func : reinterpret_cast<ifunction*>(0)) 14926 | { 14927 | assert(valid()); 14928 | } 14929 | 14930 | inline bool operator <(const function_N_node<T,IFunction,0>& fn) const 14931 | { 14932 | return this < (&fn); 14933 | } 14934 | 14935 | inline T value() const exprtk_override 14936 | { 14937 | return (*function_)(); 14938 | } 14939 | 14940 | inline typename expression_node<T>::node_type type() const exprtk_override 14941 | { 14942 | return expression_node<T>::e_function; 14943 | } 14944 | 14945 | inline bool valid() const exprtk_override 14946 | { 14947 | return function_; 14948 | } 14949 | 14950 | private: 14951 | 14952 | ifunction* function_; 14953 | }; 14954 | 14955 | template <typename T, typename VarArgFunction> 14956 | class vararg_function_node exprtk_final : public expression_node<T> 14957 | { 14958 | public: 14959 | 14960 | typedef expression_node<T>* expression_ptr; 14961 | 14962 | vararg_function_node(VarArgFunction* func, 14963 | const std::vector<expression_ptr>& arg_list) 14964 | : function_(func) 14965 | , arg_list_(arg_list) 14966 | { 14967 | value_list_.resize(arg_list.size(),std::numeric_limits<T>::quiet_NaN()); 14968 | assert(valid()); 14969 | } 14970 | 14971 | inline bool operator <(const vararg_function_node<T,VarArgFunction>& fn) const 14972 | { 14973 | return this < (&fn); 14974 | } 14975 | 14976 | inline T value() const exprtk_override 14977 | { 14978 | populate_value_list(); 14979 | return (*function_)(value_list_); 14980 | } 14981 | 14982 | inline typename expression_node<T>::node_type type() const exprtk_override 14983 | { 14984 | return expression_node<T>::e_vafunction; 14985 | } 14986 | 14987 | inline bool valid() const exprtk_override 14988 | { 14989 | return function_; 14990 | } 14991 | 14992 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 14993 | { 14994 | for (std::size_t i = 0; i < arg_list_.size(); ++i) 14995 | { 14996 | if (arg_list_[i] && !details::is_variable_node(arg_list_[i])) 14997 | { 14998 | node_delete_list.push_back(&arg_list_[i]); 14999 | } 15000 | } 15001 | } 15002 | 15003 | std::size_t node_depth() const exprtk_override 15004 | { 15005 | return expression_node<T>::ndb_t::compute_node_depth(arg_list_); 15006 | } 15007 | 15008 | private: 15009 | 15010 | inline void populate_value_list() const 15011 | { 15012 | for (std::size_t i = 0; i < arg_list_.size(); ++i) 15013 | { 15014 | value_list_[i] = arg_list_[i]->value(); 15015 | } 15016 | } 15017 | 15018 | VarArgFunction* function_; 15019 | std::vector<expression_ptr> arg_list_; 15020 | mutable std::vector<T> value_list_; 15021 | }; 15022 | 15023 | template <typename T, typename GenericFunction> 15024 | class generic_function_node : public expression_node<T> 15025 | { 15026 | public: 15027 | 15028 | typedef type_store<T> type_store_t; 15029 | typedef expression_node<T>* expression_ptr; 15030 | typedef variable_node<T> variable_node_t; 15031 | typedef vector_node<T> vector_node_t; 15032 | typedef variable_node_t* variable_node_ptr_t; 15033 | typedef vector_node_t* vector_node_ptr_t; 15034 | typedef range_interface<T> range_interface_t; 15035 | typedef range_data_type<T> range_data_type_t; 15036 | typedef typename range_interface<T>::range_t range_t; 15037 | 15038 | typedef std::pair<expression_ptr,bool> branch_t; 15039 | typedef vector_holder<T>* vh_t; 15040 | typedef vector_view<T>* vecview_t; 15041 | 15042 | typedef std::vector<T> tmp_vs_t; 15043 | typedef std::vector<type_store_t> typestore_list_t; 15044 | typedef std::vector<range_data_type_t> range_list_t; 15045 | 15046 | explicit generic_function_node(const std::vector<expression_ptr>& arg_list, 15047 | GenericFunction* func = reinterpret_cast<GenericFunction*>(0)) 15048 | : function_(func) 15049 | , arg_list_(arg_list) 15050 | {} 15051 | 15052 | virtual ~generic_function_node() 15053 | { 15054 | for (std::size_t i = 0; i < vv_list_.size(); ++i) 15055 | { 15056 | vecview_t& vv = vv_list_[i]; 15057 | if (vv) 15058 | { 15059 | if (typestore_list_[i].vec_data) 15060 | { 15061 | vv->remove_ref(&typestore_list_[i].vec_data); 15062 | } 15063 | 15064 | vv->remove_size_ref(&typestore_list_[i].size); 15065 | typestore_list_[i].vec_data = 0; 15066 | } 15067 | } 15068 | } 15069 | 15070 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 15071 | { 15072 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 15073 | } 15074 | 15075 | std::size_t node_depth() const exprtk_override exprtk_final 15076 | { 15077 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 15078 | } 15079 | 15080 | virtual bool init_branches() 15081 | { 15082 | expr_as_vec1_store_.resize(arg_list_.size(), T(0) ); 15083 | typestore_list_ .resize(arg_list_.size(), type_store_t() ); 15084 | range_list_ .resize(arg_list_.size(), range_data_type_t()); 15085 | branch_ .resize(arg_list_.size(), branch_t(reinterpret_cast<expression_ptr>(0),false)); 15086 | vv_list_ .resize(arg_list_.size(), vecview_t(0)); 15087 | 15088 | for (std::size_t i = 0; i < arg_list_.size(); ++i) 15089 | { 15090 | type_store_t& ts = typestore_list_[i]; 15091 | 15092 | if (0 == arg_list_[i]) 15093 | return false; 15094 | else if (is_ivector_node(arg_list_[i])) 15095 | { 15096 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 15097 | 15098 | if (0 == (vi = dynamic_cast<vector_interface<T>*>(arg_list_[i]))) 15099 | return false; 15100 | 15101 | ts.size = vi->size(); 15102 | ts.data = vi->vds().data(); 15103 | ts.type = type_store_t::e_vector; 15104 | ts.ivec = vi; 15105 | 15106 | if ( 15107 | vi->vec()->vec_holder().rebaseable() && 15108 | vi->vec()->vec_holder().rebaseable_instance() 15109 | ) 15110 | { 15111 | vv_list_[i] = vi->vec()->vec_holder().rebaseable_instance(); 15112 | vv_list_[i]->set_size_ref(&ts.size); 15113 | 15114 | if (!amalgamated_vecop(arg_list_[i])) 15115 | { 15116 | vv_list_[i]->set_ref(&ts.vec_data); 15117 | } 15118 | } 15119 | } 15120 | #ifndef exprtk_disable_string_capabilities 15121 | else if (is_generally_string_node(arg_list_[i])) 15122 | { 15123 | string_base_node<T>* sbn = reinterpret_cast<string_base_node<T>*>(0); 15124 | 15125 | if (0 == (sbn = dynamic_cast<string_base_node<T>*>(arg_list_[i]))) 15126 | return false; 15127 | 15128 | ts.size = sbn->size(); 15129 | ts.data = reinterpret_cast<void*>(const_cast<char_ptr>(sbn->base())); 15130 | ts.type = type_store_t::e_string; 15131 | 15132 | range_list_[i].data = ts.data; 15133 | range_list_[i].size = ts.size; 15134 | range_list_[i].type_size = sizeof(char); 15135 | range_list_[i].str_node = sbn; 15136 | 15137 | range_interface_t* ri = reinterpret_cast<range_interface_t*>(0); 15138 | 15139 | if (0 == (ri = dynamic_cast<range_interface_t*>(arg_list_[i]))) 15140 | return false; 15141 | 15142 | const range_t& rp = ri->range_ref(); 15143 | 15144 | if ( 15145 | rp.const_range() && 15146 | is_const_string_range_node(arg_list_[i]) 15147 | ) 15148 | { 15149 | ts.size = rp.const_size(); 15150 | ts.data = static_cast<char_ptr>(ts.data) + rp.n0_c.second; 15151 | range_list_[i].range = reinterpret_cast<range_t*>(0); 15152 | } 15153 | else 15154 | { 15155 | range_list_[i].range = &(ri->range_ref()); 15156 | range_param_list_.push_back(i); 15157 | } 15158 | } 15159 | #endif 15160 | else if (is_variable_node(arg_list_[i])) 15161 | { 15162 | variable_node_ptr_t var = variable_node_ptr_t(0); 15163 | 15164 | if (0 == (var = dynamic_cast<variable_node_ptr_t>(arg_list_[i]))) 15165 | return false; 15166 | 15167 | ts.size = 1; 15168 | ts.data = &var->ref(); 15169 | ts.type = type_store_t::e_scalar; 15170 | } 15171 | else 15172 | { 15173 | ts.size = 1; 15174 | ts.data = reinterpret_cast<void*>(&expr_as_vec1_store_[i]); 15175 | ts.type = type_store_t::e_scalar; 15176 | } 15177 | 15178 | branch_[i] = std::make_pair(arg_list_[i],branch_deletable(arg_list_[i])); 15179 | } 15180 | 15181 | return true; 15182 | } 15183 | 15184 | inline bool operator <(const generic_function_node<T,GenericFunction>& fn) const 15185 | { 15186 | return this < (&fn); 15187 | } 15188 | 15189 | inline T value() const exprtk_override 15190 | { 15191 | if (populate_value_list()) 15192 | { 15193 | typedef typename GenericFunction::parameter_list_t parameter_list_t; 15194 | 15195 | return (*function_)(parameter_list_t(typestore_list_)); 15196 | } 15197 | 15198 | return std::numeric_limits<T>::quiet_NaN(); 15199 | } 15200 | 15201 | inline typename expression_node<T>::node_type type() const exprtk_override 15202 | { 15203 | return expression_node<T>::e_genfunction; 15204 | } 15205 | 15206 | inline bool valid() const exprtk_override 15207 | { 15208 | return function_; 15209 | } 15210 | 15211 | protected: 15212 | 15213 | inline virtual bool populate_value_list() const 15214 | { 15215 | assert(branch_.size() == typestore_list_.size()); 15216 | 15217 | for (std::size_t i = 0; i < branch_.size(); ++i) 15218 | { 15219 | expr_as_vec1_store_[i] = branch_[i].first->value(); 15220 | } 15221 | 15222 | if (!range_param_list_.empty()) 15223 | { 15224 | assert(range_param_list_.size() <= branch_.size()); 15225 | 15226 | for (std::size_t i = 0; i < range_param_list_.size(); ++i) 15227 | { 15228 | const std::size_t index = range_param_list_[i]; 15229 | range_data_type_t& rdt = range_list_[index]; 15230 | 15231 | const range_t& rp = (*rdt.range); 15232 | std::size_t r0 = 0; 15233 | std::size_t r1 = 0; 15234 | 15235 | const std::size_t data_size = 15236 | #ifndef exprtk_disable_string_capabilities 15237 | rdt.str_node ? rdt.str_node->size() : rdt.size; 15238 | #else 15239 | rdt.size; 15240 | #endif 15241 | 15242 | if (!rp(r0, r1, data_size)) 15243 | { 15244 | return false; 15245 | } 15246 | 15247 | type_store_t& ts = typestore_list_[index]; 15248 | 15249 | ts.size = rp.cache_size(); 15250 | #ifndef exprtk_disable_string_capabilities 15251 | if (ts.type == type_store_t::e_string) 15252 | ts.data = const_cast<char_ptr>(rdt.str_node->base()) + rp.cache.first; 15253 | else 15254 | #endif 15255 | ts.data = static_cast<char_ptr>(rdt.data) + (rp.cache.first * rdt.type_size); 15256 | } 15257 | } 15258 | 15259 | return true; 15260 | } 15261 | 15262 | GenericFunction* function_; 15263 | mutable typestore_list_t typestore_list_; 15264 | 15265 | private: 15266 | 15267 | std::vector<expression_ptr> arg_list_; 15268 | std::vector<branch_t> branch_; 15269 | std::vector<vecview_t> vv_list_; 15270 | mutable tmp_vs_t expr_as_vec1_store_; 15271 | mutable range_list_t range_list_; 15272 | std::vector<std::size_t> range_param_list_; 15273 | }; 15274 | 15275 | #ifndef exprtk_disable_string_capabilities 15276 | template <typename T, typename StringFunction> 15277 | class string_function_node : public generic_function_node<T,StringFunction> 15278 | , public string_base_node<T> 15279 | , public range_interface <T> 15280 | { 15281 | public: 15282 | 15283 | typedef generic_function_node<T,StringFunction> gen_function_t; 15284 | typedef typename range_interface<T>::range_t range_t; 15285 | 15286 | string_function_node(StringFunction* func, 15287 | const std::vector<typename gen_function_t::expression_ptr>& arg_list) 15288 | : gen_function_t(arg_list,func) 15289 | { 15290 | range_.n0_c = std::make_pair<bool,std::size_t>(true,0); 15291 | range_.n1_c = std::make_pair<bool,std::size_t>(true,0); 15292 | range_.cache.first = range_.n0_c.second; 15293 | range_.cache.second = range_.n1_c.second; 15294 | assert(valid()); 15295 | } 15296 | 15297 | inline bool operator <(const string_function_node<T,StringFunction>& fn) const 15298 | { 15299 | return this < (&fn); 15300 | } 15301 | 15302 | inline T value() const exprtk_override 15303 | { 15304 | if (gen_function_t::populate_value_list()) 15305 | { 15306 | typedef typename StringFunction::parameter_list_t parameter_list_t; 15307 | 15308 | const T result = 15309 | (*gen_function_t::function_) 15310 | ( 15311 | ret_string_, 15312 | parameter_list_t(gen_function_t::typestore_list_) 15313 | ); 15314 | 15315 | range_.n1_c.second = ret_string_.size(); 15316 | range_.cache.second = range_.n1_c.second; 15317 | 15318 | return result; 15319 | } 15320 | 15321 | return std::numeric_limits<T>::quiet_NaN(); 15322 | } 15323 | 15324 | inline typename expression_node<T>::node_type type() const exprtk_override 15325 | { 15326 | return expression_node<T>::e_strfunction; 15327 | } 15328 | 15329 | inline bool valid() const exprtk_override 15330 | { 15331 | return gen_function_t::function_; 15332 | } 15333 | 15334 | std::string str() const exprtk_override 15335 | { 15336 | return ret_string_; 15337 | } 15338 | 15339 | char_cptr base() const exprtk_override 15340 | { 15341 | return &ret_string_[0]; 15342 | } 15343 | 15344 | std::size_t size() const exprtk_override 15345 | { 15346 | return ret_string_.size(); 15347 | } 15348 | 15349 | range_t& range_ref() exprtk_override 15350 | { 15351 | return range_; 15352 | } 15353 | 15354 | const range_t& range_ref() const exprtk_override 15355 | { 15356 | return range_; 15357 | } 15358 | 15359 | protected: 15360 | 15361 | mutable range_t range_; 15362 | mutable std::string ret_string_; 15363 | }; 15364 | #endif 15365 | 15366 | template <typename T, typename GenericFunction> 15367 | class multimode_genfunction_node : public generic_function_node<T,GenericFunction> 15368 | { 15369 | public: 15370 | 15371 | typedef generic_function_node<T,GenericFunction> gen_function_t; 15372 | typedef typename gen_function_t::range_t range_t; 15373 | 15374 | multimode_genfunction_node(GenericFunction* func, 15375 | const std::size_t& param_seq_index, 15376 | const std::vector<typename gen_function_t::expression_ptr>& arg_list) 15377 | : gen_function_t(arg_list,func) 15378 | , param_seq_index_(param_seq_index) 15379 | {} 15380 | 15381 | inline T value() const exprtk_override 15382 | { 15383 | assert(gen_function_t::valid()); 15384 | 15385 | if (gen_function_t::populate_value_list()) 15386 | { 15387 | typedef typename GenericFunction::parameter_list_t parameter_list_t; 15388 | 15389 | return 15390 | (*gen_function_t::function_) 15391 | ( 15392 | param_seq_index_, 15393 | parameter_list_t(gen_function_t::typestore_list_) 15394 | ); 15395 | } 15396 | 15397 | return std::numeric_limits<T>::quiet_NaN(); 15398 | } 15399 | 15400 | inline typename expression_node<T>::node_type type() const exprtk_override exprtk_final 15401 | { 15402 | return expression_node<T>::e_genfunction; 15403 | } 15404 | 15405 | private: 15406 | 15407 | std::size_t param_seq_index_; 15408 | }; 15409 | 15410 | #ifndef exprtk_disable_string_capabilities 15411 | template <typename T, typename StringFunction> 15412 | class multimode_strfunction_node exprtk_final : public string_function_node<T,StringFunction> 15413 | { 15414 | public: 15415 | 15416 | typedef string_function_node<T,StringFunction> str_function_t; 15417 | typedef typename str_function_t::range_t range_t; 15418 | 15419 | multimode_strfunction_node(StringFunction* func, 15420 | const std::size_t& param_seq_index, 15421 | const std::vector<typename str_function_t::expression_ptr>& arg_list) 15422 | : str_function_t(func,arg_list) 15423 | , param_seq_index_(param_seq_index) 15424 | {} 15425 | 15426 | inline T value() const exprtk_override 15427 | { 15428 | if (str_function_t::populate_value_list()) 15429 | { 15430 | typedef typename StringFunction::parameter_list_t parameter_list_t; 15431 | 15432 | const T result = 15433 | (*str_function_t::function_) 15434 | ( 15435 | param_seq_index_, 15436 | str_function_t::ret_string_, 15437 | parameter_list_t(str_function_t::typestore_list_) 15438 | ); 15439 | 15440 | str_function_t::range_.n1_c.second = str_function_t::ret_string_.size(); 15441 | str_function_t::range_.cache.second = str_function_t::range_.n1_c.second; 15442 | 15443 | return result; 15444 | } 15445 | 15446 | return std::numeric_limits<T>::quiet_NaN(); 15447 | } 15448 | 15449 | inline typename expression_node<T>::node_type type() const exprtk_override 15450 | { 15451 | return expression_node<T>::e_strfunction; 15452 | } 15453 | 15454 | private: 15455 | 15456 | const std::size_t param_seq_index_; 15457 | }; 15458 | #endif 15459 | 15460 | class return_exception {}; 15461 | 15462 | template <typename T> 15463 | class null_igenfunc 15464 | { 15465 | public: 15466 | 15467 | virtual ~null_igenfunc() 15468 | {} 15469 | 15470 | typedef type_store<T> generic_type; 15471 | typedef typename generic_type::parameter_list parameter_list_t; 15472 | 15473 | inline virtual T operator() (parameter_list_t) 15474 | { 15475 | return std::numeric_limits<T>::quiet_NaN(); 15476 | } 15477 | }; 15478 | 15479 | #ifndef exprtk_disable_return_statement 15480 | template <typename T> 15481 | class return_node exprtk_final : public generic_function_node<T,null_igenfunc<T> > 15482 | { 15483 | public: 15484 | 15485 | typedef results_context<T> results_context_t; 15486 | typedef null_igenfunc<T> igeneric_function_t; 15487 | typedef igeneric_function_t* igeneric_function_ptr; 15488 | typedef generic_function_node<T,igeneric_function_t> gen_function_t; 15489 | 15490 | return_node(const std::vector<typename gen_function_t::expression_ptr>& arg_list, 15491 | results_context_t& rc) 15492 | : gen_function_t (arg_list) 15493 | , results_context_(&rc) 15494 | { 15495 | assert(valid()); 15496 | } 15497 | 15498 | inline T value() const exprtk_override 15499 | { 15500 | if (gen_function_t::populate_value_list()) 15501 | { 15502 | prepare_typestore_list(); 15503 | 15504 | typedef typename type_store<T>::parameter_list parameter_list_t; 15505 | 15506 | results_context_-> 15507 | assign(parameter_list_t(gen_function_t::typestore_list_)); 15508 | 15509 | throw return_exception(); 15510 | } 15511 | 15512 | return std::numeric_limits<T>::quiet_NaN(); 15513 | } 15514 | 15515 | inline typename expression_node<T>::node_type type() const exprtk_override 15516 | { 15517 | return expression_node<T>::e_return; 15518 | } 15519 | 15520 | inline bool valid() const exprtk_override 15521 | { 15522 | return results_context_; 15523 | } 15524 | 15525 | private: 15526 | 15527 | void prepare_typestore_list() const 15528 | { 15529 | for (std::size_t i = 0; i < gen_function_t::typestore_list_.size(); ++i) 15530 | { 15531 | typename gen_function_t::type_store_t& ts = gen_function_t::typestore_list_[i]; 15532 | 15533 | if (ts.ivec) 15534 | { 15535 | ts.size = ts.ivec->size(); 15536 | } 15537 | } 15538 | } 15539 | 15540 | results_context_t* results_context_; 15541 | }; 15542 | 15543 | template <typename T> 15544 | class return_envelope_node exprtk_final : public expression_node<T> 15545 | { 15546 | public: 15547 | 15548 | typedef expression_node<T>* expression_ptr; 15549 | typedef results_context<T> results_context_t; 15550 | typedef std::pair<expression_ptr,bool> branch_t; 15551 | 15552 | return_envelope_node(expression_ptr body, results_context_t& rc) 15553 | : results_context_(&rc ) 15554 | , return_invoked_ (false) 15555 | { 15556 | construct_branch_pair(body_, body); 15557 | assert(valid()); 15558 | } 15559 | 15560 | inline T value() const exprtk_override 15561 | { 15562 | try 15563 | { 15564 | return_invoked_ = false; 15565 | results_context_->clear(); 15566 | 15567 | return body_.first->value(); 15568 | } 15569 | catch(const return_exception&) 15570 | { 15571 | return_invoked_ = true; 15572 | 15573 | return std::numeric_limits<T>::quiet_NaN(); 15574 | } 15575 | } 15576 | 15577 | inline typename expression_node<T>::node_type type() const exprtk_override 15578 | { 15579 | return expression_node<T>::e_retenv; 15580 | } 15581 | 15582 | inline bool valid() const exprtk_override 15583 | { 15584 | return results_context_ && body_.first; 15585 | } 15586 | 15587 | inline bool* retinvk_ptr() 15588 | { 15589 | return &return_invoked_; 15590 | } 15591 | 15592 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 15593 | { 15594 | expression_node<T>::ndb_t::collect(body_, node_delete_list); 15595 | } 15596 | 15597 | std::size_t node_depth() const exprtk_override 15598 | { 15599 | return expression_node<T>::ndb_t::compute_node_depth(body_); 15600 | } 15601 | 15602 | private: 15603 | 15604 | results_context_t* results_context_; 15605 | mutable bool return_invoked_; 15606 | branch_t body_; 15607 | }; 15608 | #endif 15609 | 15610 | #define exprtk_define_unary_op(OpName) \ 15611 | template <typename T> \ 15612 | struct OpName##_op \ 15613 | { \ 15614 | typedef typename functor_t<T>::Type Type; \ 15615 | typedef typename expression_node<T>::node_type node_t; \ 15616 | \ 15617 | static inline T process(Type v) \ 15618 | { \ 15619 | return numeric:: OpName (v); \ 15620 | } \ 15621 | \ 15622 | static inline node_t type() \ 15623 | { \ 15624 | return expression_node<T>::e_##OpName; \ 15625 | } \ 15626 | \ 15627 | static inline details::operator_type operation() \ 15628 | { \ 15629 | return details::e_##OpName; \ 15630 | } \ 15631 | }; \ 15632 | 15633 | exprtk_define_unary_op(abs ) 15634 | exprtk_define_unary_op(acos ) 15635 | exprtk_define_unary_op(acosh) 15636 | exprtk_define_unary_op(asin ) 15637 | exprtk_define_unary_op(asinh) 15638 | exprtk_define_unary_op(atan ) 15639 | exprtk_define_unary_op(atanh) 15640 | exprtk_define_unary_op(ceil ) 15641 | exprtk_define_unary_op(cos ) 15642 | exprtk_define_unary_op(cosh ) 15643 | exprtk_define_unary_op(cot ) 15644 | exprtk_define_unary_op(csc ) 15645 | exprtk_define_unary_op(d2g ) 15646 | exprtk_define_unary_op(d2r ) 15647 | exprtk_define_unary_op(erf ) 15648 | exprtk_define_unary_op(erfc ) 15649 | exprtk_define_unary_op(exp ) 15650 | exprtk_define_unary_op(expm1) 15651 | exprtk_define_unary_op(floor) 15652 | exprtk_define_unary_op(frac ) 15653 | exprtk_define_unary_op(g2d ) 15654 | exprtk_define_unary_op(log ) 15655 | exprtk_define_unary_op(log10) 15656 | exprtk_define_unary_op(log2 ) 15657 | exprtk_define_unary_op(log1p) 15658 | exprtk_define_unary_op(ncdf ) 15659 | exprtk_define_unary_op(neg ) 15660 | exprtk_define_unary_op(notl ) 15661 | exprtk_define_unary_op(pos ) 15662 | exprtk_define_unary_op(r2d ) 15663 | exprtk_define_unary_op(round) 15664 | exprtk_define_unary_op(sec ) 15665 | exprtk_define_unary_op(sgn ) 15666 | exprtk_define_unary_op(sin ) 15667 | exprtk_define_unary_op(sinc ) 15668 | exprtk_define_unary_op(sinh ) 15669 | exprtk_define_unary_op(sqrt ) 15670 | exprtk_define_unary_op(tan ) 15671 | exprtk_define_unary_op(tanh ) 15672 | exprtk_define_unary_op(trunc) 15673 | #undef exprtk_define_unary_op 15674 | 15675 | template <typename T> 15676 | struct opr_base 15677 | { 15678 | typedef typename details::functor_t<T>::Type Type; 15679 | typedef typename details::functor_t<T>::RefType RefType; 15680 | typedef typename details::functor_t<T> functor_t; 15681 | typedef typename functor_t::qfunc_t quaternary_functor_t; 15682 | typedef typename functor_t::tfunc_t trinary_functor_t; 15683 | typedef typename functor_t::bfunc_t binary_functor_t; 15684 | typedef typename functor_t::ufunc_t unary_functor_t; 15685 | }; 15686 | 15687 | template <typename T> 15688 | struct add_op : public opr_base<T> 15689 | { 15690 | typedef typename opr_base<T>::Type Type; 15691 | typedef typename opr_base<T>::RefType RefType; 15692 | 15693 | static inline T process(Type t1, Type t2) { return t1 + t2; } 15694 | static inline T process(Type t1, Type t2, Type t3) { return t1 + t2 + t3; } 15695 | static inline void assign(RefType t1, Type t2) { t1 += t2; } 15696 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_add; } 15697 | static inline details::operator_type operation() { return details::e_add; } 15698 | }; 15699 | 15700 | template <typename T> 15701 | struct mul_op : public opr_base<T> 15702 | { 15703 | typedef typename opr_base<T>::Type Type; 15704 | typedef typename opr_base<T>::RefType RefType; 15705 | 15706 | static inline T process(Type t1, Type t2) { return t1 * t2; } 15707 | static inline T process(Type t1, Type t2, Type t3) { return t1 * t2 * t3; } 15708 | static inline void assign(RefType t1, Type t2) { t1 *= t2; } 15709 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_mul; } 15710 | static inline details::operator_type operation() { return details::e_mul; } 15711 | }; 15712 | 15713 | template <typename T> 15714 | struct sub_op : public opr_base<T> 15715 | { 15716 | typedef typename opr_base<T>::Type Type; 15717 | typedef typename opr_base<T>::RefType RefType; 15718 | 15719 | static inline T process(Type t1, Type t2) { return t1 - t2; } 15720 | static inline T process(Type t1, Type t2, Type t3) { return t1 - t2 - t3; } 15721 | static inline void assign(RefType t1, Type t2) { t1 -= t2; } 15722 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_sub; } 15723 | static inline details::operator_type operation() { return details::e_sub; } 15724 | }; 15725 | 15726 | template <typename T> 15727 | struct div_op : public opr_base<T> 15728 | { 15729 | typedef typename opr_base<T>::Type Type; 15730 | typedef typename opr_base<T>::RefType RefType; 15731 | 15732 | static inline T process(Type t1, Type t2) { return t1 / t2; } 15733 | static inline T process(Type t1, Type t2, Type t3) { return t1 / t2 / t3; } 15734 | static inline void assign(RefType t1, Type t2) { t1 /= t2; } 15735 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_div; } 15736 | static inline details::operator_type operation() { return details::e_div; } 15737 | }; 15738 | 15739 | template <typename T> 15740 | struct mod_op : public opr_base<T> 15741 | { 15742 | typedef typename opr_base<T>::Type Type; 15743 | typedef typename opr_base<T>::RefType RefType; 15744 | 15745 | static inline T process(Type t1, Type t2) { return numeric::modulus<T>(t1,t2); } 15746 | static inline void assign(RefType t1, Type t2) { t1 = numeric::modulus<T>(t1,t2); } 15747 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_mod; } 15748 | static inline details::operator_type operation() { return details::e_mod; } 15749 | }; 15750 | 15751 | template <typename T> 15752 | struct pow_op : public opr_base<T> 15753 | { 15754 | typedef typename opr_base<T>::Type Type; 15755 | typedef typename opr_base<T>::RefType RefType; 15756 | 15757 | static inline T process(Type t1, Type t2) { return numeric::pow<T>(t1,t2); } 15758 | static inline void assign(RefType t1, Type t2) { t1 = numeric::pow<T>(t1,t2); } 15759 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_pow; } 15760 | static inline details::operator_type operation() { return details::e_pow; } 15761 | }; 15762 | 15763 | template <typename T> 15764 | struct lt_op : public opr_base<T> 15765 | { 15766 | typedef typename opr_base<T>::Type Type; 15767 | 15768 | static inline T process(Type t1, Type t2) { return ((t1 < t2) ? T(1) : T(0)); } 15769 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 < t2) ? T(1) : T(0)); } 15770 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_lt; } 15771 | static inline details::operator_type operation() { return details::e_lt; } 15772 | }; 15773 | 15774 | template <typename T> 15775 | struct lte_op : public opr_base<T> 15776 | { 15777 | typedef typename opr_base<T>::Type Type; 15778 | 15779 | static inline T process(Type t1, Type t2) { return ((t1 <= t2) ? T(1) : T(0)); } 15780 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 <= t2) ? T(1) : T(0)); } 15781 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_lte; } 15782 | static inline details::operator_type operation() { return details::e_lte; } 15783 | }; 15784 | 15785 | template <typename T> 15786 | struct gt_op : public opr_base<T> 15787 | { 15788 | typedef typename opr_base<T>::Type Type; 15789 | 15790 | static inline T process(Type t1, Type t2) { return ((t1 > t2) ? T(1) : T(0)); } 15791 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 > t2) ? T(1) : T(0)); } 15792 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_gt; } 15793 | static inline details::operator_type operation() { return details::e_gt; } 15794 | }; 15795 | 15796 | template <typename T> 15797 | struct gte_op : public opr_base<T> 15798 | { 15799 | typedef typename opr_base<T>::Type Type; 15800 | 15801 | static inline T process(Type t1, Type t2) { return ((t1 >= t2) ? T(1) : T(0)); } 15802 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 >= t2) ? T(1) : T(0)); } 15803 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_gte; } 15804 | static inline details::operator_type operation() { return details::e_gte; } 15805 | }; 15806 | 15807 | template <typename T> 15808 | struct eq_op : public opr_base<T> 15809 | { 15810 | typedef typename opr_base<T>::Type Type; 15811 | static inline T process(Type t1, Type t2) { return (std::equal_to<T>()(t1,t2) ? T(1) : T(0)); } 15812 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 == t2) ? T(1) : T(0)); } 15813 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_eq; } 15814 | static inline details::operator_type operation() { return details::e_eq; } 15815 | }; 15816 | 15817 | template <typename T> 15818 | struct equal_op : public opr_base<T> 15819 | { 15820 | typedef typename opr_base<T>::Type Type; 15821 | 15822 | static inline T process(Type t1, Type t2) { return numeric::equal(t1,t2); } 15823 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 == t2) ? T(1) : T(0)); } 15824 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_eq; } 15825 | static inline details::operator_type operation() { return details::e_equal; } 15826 | }; 15827 | 15828 | template <typename T> 15829 | struct ne_op : public opr_base<T> 15830 | { 15831 | typedef typename opr_base<T>::Type Type; 15832 | 15833 | static inline T process(Type t1, Type t2) { return (std::not_equal_to<T>()(t1,t2) ? T(1) : T(0)); } 15834 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 != t2) ? T(1) : T(0)); } 15835 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_ne; } 15836 | static inline details::operator_type operation() { return details::e_ne; } 15837 | }; 15838 | 15839 | template <typename T> 15840 | struct and_op : public opr_base<T> 15841 | { 15842 | typedef typename opr_base<T>::Type Type; 15843 | 15844 | static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(1) : T(0); } 15845 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_and; } 15846 | static inline details::operator_type operation() { return details::e_and; } 15847 | }; 15848 | 15849 | template <typename T> 15850 | struct nand_op : public opr_base<T> 15851 | { 15852 | typedef typename opr_base<T>::Type Type; 15853 | 15854 | static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(0) : T(1); } 15855 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nand; } 15856 | static inline details::operator_type operation() { return details::e_nand; } 15857 | }; 15858 | 15859 | template <typename T> 15860 | struct or_op : public opr_base<T> 15861 | { 15862 | typedef typename opr_base<T>::Type Type; 15863 | 15864 | static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(1) : T(0); } 15865 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_or; } 15866 | static inline details::operator_type operation() { return details::e_or; } 15867 | }; 15868 | 15869 | template <typename T> 15870 | struct nor_op : public opr_base<T> 15871 | { 15872 | typedef typename opr_base<T>::Type Type; 15873 | 15874 | static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(0) : T(1); } 15875 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; } 15876 | static inline details::operator_type operation() { return details::e_nor; } 15877 | }; 15878 | 15879 | template <typename T> 15880 | struct xor_op : public opr_base<T> 15881 | { 15882 | typedef typename opr_base<T>::Type Type; 15883 | 15884 | static inline T process(Type t1, Type t2) { return numeric::xor_opr<T>(t1,t2); } 15885 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; } 15886 | static inline details::operator_type operation() { return details::e_xor; } 15887 | }; 15888 | 15889 | template <typename T> 15890 | struct xnor_op : public opr_base<T> 15891 | { 15892 | typedef typename opr_base<T>::Type Type; 15893 | 15894 | static inline T process(Type t1, Type t2) { return numeric::xnor_opr<T>(t1,t2); } 15895 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; } 15896 | static inline details::operator_type operation() { return details::e_xnor; } 15897 | }; 15898 | 15899 | template <typename T> 15900 | struct in_op : public opr_base<T> 15901 | { 15902 | typedef typename opr_base<T>::Type Type; 15903 | 15904 | static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); } 15905 | static inline T process(const std::string& t1, const std::string& t2) { return ((std::string::npos != t2.find(t1)) ? T(1) : T(0)); } 15906 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_in; } 15907 | static inline details::operator_type operation() { return details::e_in; } 15908 | }; 15909 | 15910 | template <typename T> 15911 | struct like_op : public opr_base<T> 15912 | { 15913 | typedef typename opr_base<T>::Type Type; 15914 | 15915 | static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); } 15916 | static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_match(t2,t1) ? T(1) : T(0)); } 15917 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_like; } 15918 | static inline details::operator_type operation() { return details::e_like; } 15919 | }; 15920 | 15921 | template <typename T> 15922 | struct ilike_op : public opr_base<T> 15923 | { 15924 | typedef typename opr_base<T>::Type Type; 15925 | 15926 | static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); } 15927 | static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_imatch(t2,t1) ? T(1) : T(0)); } 15928 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_ilike; } 15929 | static inline details::operator_type operation() { return details::e_ilike; } 15930 | }; 15931 | 15932 | template <typename T> 15933 | struct inrange_op : public opr_base<T> 15934 | { 15935 | typedef typename opr_base<T>::Type Type; 15936 | 15937 | static inline T process(const T& t0, const T& t1, const T& t2) { return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0); } 15938 | static inline T process(const std::string& t0, const std::string& t1, const std::string& t2) 15939 | { 15940 | return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0); 15941 | } 15942 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_inranges; } 15943 | static inline details::operator_type operation() { return details::e_inrange; } 15944 | }; 15945 | 15946 | template <typename T> 15947 | inline T value(details::expression_node<T>* n) 15948 | { 15949 | return n->value(); 15950 | } 15951 | 15952 | template <typename T> 15953 | inline T value(std::pair<details::expression_node<T>*,bool> n) 15954 | { 15955 | return n.first->value(); 15956 | } 15957 | 15958 | template <typename T> 15959 | inline T value(const T* t) 15960 | { 15961 | return (*t); 15962 | } 15963 | 15964 | template <typename T> 15965 | inline T value(const T& t) 15966 | { 15967 | return t; 15968 | } 15969 | 15970 | template <typename T> 15971 | struct vararg_add_op exprtk_final : public opr_base<T> 15972 | { 15973 | typedef typename opr_base<T>::Type Type; 15974 | 15975 | template <typename Type, 15976 | typename Allocator, 15977 | template <typename, typename> class Sequence> 15978 | static inline T process(const Sequence<Type,Allocator>& arg_list) 15979 | { 15980 | switch (arg_list.size()) 15981 | { 15982 | case 0 : return T(0); 15983 | case 1 : return process_1(arg_list); 15984 | case 2 : return process_2(arg_list); 15985 | case 3 : return process_3(arg_list); 15986 | case 4 : return process_4(arg_list); 15987 | case 5 : return process_5(arg_list); 15988 | default : 15989 | { 15990 | T result = T(0); 15991 | 15992 | for (std::size_t i = 0; i < arg_list.size(); ++i) 15993 | { 15994 | result += value(arg_list[i]); 15995 | } 15996 | 15997 | return result; 15998 | } 15999 | } 16000 | } 16001 | 16002 | template <typename Sequence> 16003 | static inline T process_1(const Sequence& arg_list) 16004 | { 16005 | return value(arg_list[0]); 16006 | } 16007 | 16008 | template <typename Sequence> 16009 | static inline T process_2(const Sequence& arg_list) 16010 | { 16011 | return value(arg_list[0]) + value(arg_list[1]); 16012 | } 16013 | 16014 | template <typename Sequence> 16015 | static inline T process_3(const Sequence& arg_list) 16016 | { 16017 | return value(arg_list[0]) + value(arg_list[1]) + 16018 | value(arg_list[2]) ; 16019 | } 16020 | 16021 | template <typename Sequence> 16022 | static inline T process_4(const Sequence& arg_list) 16023 | { 16024 | return value(arg_list[0]) + value(arg_list[1]) + 16025 | value(arg_list[2]) + value(arg_list[3]) ; 16026 | } 16027 | 16028 | template <typename Sequence> 16029 | static inline T process_5(const Sequence& arg_list) 16030 | { 16031 | return value(arg_list[0]) + value(arg_list[1]) + 16032 | value(arg_list[2]) + value(arg_list[3]) + 16033 | value(arg_list[4]) ; 16034 | } 16035 | }; 16036 | 16037 | template <typename T> 16038 | struct vararg_mul_op exprtk_final : public opr_base<T> 16039 | { 16040 | typedef typename opr_base<T>::Type Type; 16041 | 16042 | template <typename Type, 16043 | typename Allocator, 16044 | template <typename, typename> class Sequence> 16045 | static inline T process(const Sequence<Type,Allocator>& arg_list) 16046 | { 16047 | switch (arg_list.size()) 16048 | { 16049 | case 0 : return T(0); 16050 | case 1 : return process_1(arg_list); 16051 | case 2 : return process_2(arg_list); 16052 | case 3 : return process_3(arg_list); 16053 | case 4 : return process_4(arg_list); 16054 | case 5 : return process_5(arg_list); 16055 | default : 16056 | { 16057 | T result = T(value(arg_list[0])); 16058 | 16059 | for (std::size_t i = 1; i < arg_list.size(); ++i) 16060 | { 16061 | result *= value(arg_list[i]); 16062 | } 16063 | 16064 | return result; 16065 | } 16066 | } 16067 | } 16068 | 16069 | template <typename Sequence> 16070 | static inline T process_1(const Sequence& arg_list) 16071 | { 16072 | return value(arg_list[0]); 16073 | } 16074 | 16075 | template <typename Sequence> 16076 | static inline T process_2(const Sequence& arg_list) 16077 | { 16078 | return value(arg_list[0]) * value(arg_list[1]); 16079 | } 16080 | 16081 | template <typename Sequence> 16082 | static inline T process_3(const Sequence& arg_list) 16083 | { 16084 | return value(arg_list[0]) * value(arg_list[1]) * 16085 | value(arg_list[2]) ; 16086 | } 16087 | 16088 | template <typename Sequence> 16089 | static inline T process_4(const Sequence& arg_list) 16090 | { 16091 | return value(arg_list[0]) * value(arg_list[1]) * 16092 | value(arg_list[2]) * value(arg_list[3]) ; 16093 | } 16094 | 16095 | template <typename Sequence> 16096 | static inline T process_5(const Sequence& arg_list) 16097 | { 16098 | return value(arg_list[0]) * value(arg_list[1]) * 16099 | value(arg_list[2]) * value(arg_list[3]) * 16100 | value(arg_list[4]) ; 16101 | } 16102 | }; 16103 | 16104 | template <typename T> 16105 | struct vararg_avg_op exprtk_final : public opr_base<T> 16106 | { 16107 | typedef typename opr_base<T>::Type Type; 16108 | 16109 | template <typename Type, 16110 | typename Allocator, 16111 | template <typename, typename> class Sequence> 16112 | static inline T process(const Sequence<Type,Allocator>& arg_list) 16113 | { 16114 | switch (arg_list.size()) 16115 | { 16116 | case 0 : return T(0); 16117 | case 1 : return process_1(arg_list); 16118 | case 2 : return process_2(arg_list); 16119 | case 3 : return process_3(arg_list); 16120 | case 4 : return process_4(arg_list); 16121 | case 5 : return process_5(arg_list); 16122 | default : return vararg_add_op<T>::process(arg_list) / T(arg_list.size()); 16123 | } 16124 | } 16125 | 16126 | template <typename Sequence> 16127 | static inline T process_1(const Sequence& arg_list) 16128 | { 16129 | return value(arg_list[0]); 16130 | } 16131 | 16132 | template <typename Sequence> 16133 | static inline T process_2(const Sequence& arg_list) 16134 | { 16135 | return (value(arg_list[0]) + value(arg_list[1])) / T(2); 16136 | } 16137 | 16138 | template <typename Sequence> 16139 | static inline T process_3(const Sequence& arg_list) 16140 | { 16141 | return (value(arg_list[0]) + value(arg_list[1]) + value(arg_list[2])) / T(3); 16142 | } 16143 | 16144 | template <typename Sequence> 16145 | static inline T process_4(const Sequence& arg_list) 16146 | { 16147 | return (value(arg_list[0]) + value(arg_list[1]) + 16148 | value(arg_list[2]) + value(arg_list[3])) / T(4); 16149 | } 16150 | 16151 | template <typename Sequence> 16152 | static inline T process_5(const Sequence& arg_list) 16153 | { 16154 | return (value(arg_list[0]) + value(arg_list[1]) + 16155 | value(arg_list[2]) + value(arg_list[3]) + 16156 | value(arg_list[4])) / T(5); 16157 | } 16158 | }; 16159 | 16160 | template <typename T> 16161 | struct vararg_min_op exprtk_final : public opr_base<T> 16162 | { 16163 | typedef typename opr_base<T>::Type Type; 16164 | 16165 | template <typename Type, 16166 | typename Allocator, 16167 | template <typename, typename> class Sequence> 16168 | static inline T process(const Sequence<Type,Allocator>& arg_list) 16169 | { 16170 | switch (arg_list.size()) 16171 | { 16172 | case 0 : return T(0); 16173 | case 1 : return process_1(arg_list); 16174 | case 2 : return process_2(arg_list); 16175 | case 3 : return process_3(arg_list); 16176 | case 4 : return process_4(arg_list); 16177 | case 5 : return process_5(arg_list); 16178 | default : 16179 | { 16180 | T result = T(value(arg_list[0])); 16181 | 16182 | for (std::size_t i = 1; i < arg_list.size(); ++i) 16183 | { 16184 | const T v = value(arg_list[i]); 16185 | 16186 | if (v < result) 16187 | result = v; 16188 | } 16189 | 16190 | return result; 16191 | } 16192 | } 16193 | } 16194 | 16195 | template <typename Sequence> 16196 | static inline T process_1(const Sequence& arg_list) 16197 | { 16198 | return value(arg_list[0]); 16199 | } 16200 | 16201 | template <typename Sequence> 16202 | static inline T process_2(const Sequence& arg_list) 16203 | { 16204 | return std::min<T>(value(arg_list[0]),value(arg_list[1])); 16205 | } 16206 | 16207 | template <typename Sequence> 16208 | static inline T process_3(const Sequence& arg_list) 16209 | { 16210 | return std::min<T>(std::min<T>(value(arg_list[0]),value(arg_list[1])),value(arg_list[2])); 16211 | } 16212 | 16213 | template <typename Sequence> 16214 | static inline T process_4(const Sequence& arg_list) 16215 | { 16216 | return std::min<T>( 16217 | std::min<T>(value(arg_list[0]), value(arg_list[1])), 16218 | std::min<T>(value(arg_list[2]), value(arg_list[3]))); 16219 | } 16220 | 16221 | template <typename Sequence> 16222 | static inline T process_5(const Sequence& arg_list) 16223 | { 16224 | return std::min<T>( 16225 | std::min<T>(std::min<T>(value(arg_list[0]), value(arg_list[1])), 16226 | std::min<T>(value(arg_list[2]), value(arg_list[3]))), 16227 | value(arg_list[4])); 16228 | } 16229 | }; 16230 | 16231 | template <typename T> 16232 | struct vararg_max_op exprtk_final : public opr_base<T> 16233 | { 16234 | typedef typename opr_base<T>::Type Type; 16235 | 16236 | template <typename Type, 16237 | typename Allocator, 16238 | template <typename, typename> class Sequence> 16239 | static inline T process(const Sequence<Type,Allocator>& arg_list) 16240 | { 16241 | switch (arg_list.size()) 16242 | { 16243 | case 0 : return T(0); 16244 | case 1 : return process_1(arg_list); 16245 | case 2 : return process_2(arg_list); 16246 | case 3 : return process_3(arg_list); 16247 | case 4 : return process_4(arg_list); 16248 | case 5 : return process_5(arg_list); 16249 | default : 16250 | { 16251 | T result = T(value(arg_list[0])); 16252 | 16253 | for (std::size_t i = 1; i < arg_list.size(); ++i) 16254 | { 16255 | const T v = value(arg_list[i]); 16256 | 16257 | if (v > result) 16258 | result = v; 16259 | } 16260 | 16261 | return result; 16262 | } 16263 | } 16264 | } 16265 | 16266 | template <typename Sequence> 16267 | static inline T process_1(const Sequence& arg_list) 16268 | { 16269 | return value(arg_list[0]); 16270 | } 16271 | 16272 | template <typename Sequence> 16273 | static inline T process_2(const Sequence& arg_list) 16274 | { 16275 | return std::max<T>(value(arg_list[0]),value(arg_list[1])); 16276 | } 16277 | 16278 | template <typename Sequence> 16279 | static inline T process_3(const Sequence& arg_list) 16280 | { 16281 | return std::max<T>(std::max<T>(value(arg_list[0]),value(arg_list[1])),value(arg_list[2])); 16282 | } 16283 | 16284 | template <typename Sequence> 16285 | static inline T process_4(const Sequence& arg_list) 16286 | { 16287 | return std::max<T>( 16288 | std::max<T>(value(arg_list[0]), value(arg_list[1])), 16289 | std::max<T>(value(arg_list[2]), value(arg_list[3]))); 16290 | } 16291 | 16292 | template <typename Sequence> 16293 | static inline T process_5(const Sequence& arg_list) 16294 | { 16295 | return std::max<T>( 16296 | std::max<T>(std::max<T>(value(arg_list[0]), value(arg_list[1])), 16297 | std::max<T>(value(arg_list[2]), value(arg_list[3]))), 16298 | value(arg_list[4])); 16299 | } 16300 | }; 16301 | 16302 | template <typename T> 16303 | struct vararg_mand_op exprtk_final : public opr_base<T> 16304 | { 16305 | typedef typename opr_base<T>::Type Type; 16306 | 16307 | template <typename Type, 16308 | typename Allocator, 16309 | template <typename, typename> class Sequence> 16310 | static inline T process(const Sequence<Type,Allocator>& arg_list) 16311 | { 16312 | switch (arg_list.size()) 16313 | { 16314 | case 1 : return process_1(arg_list); 16315 | case 2 : return process_2(arg_list); 16316 | case 3 : return process_3(arg_list); 16317 | case 4 : return process_4(arg_list); 16318 | case 5 : return process_5(arg_list); 16319 | default : 16320 | { 16321 | for (std::size_t i = 0; i < arg_list.size(); ++i) 16322 | { 16323 | if (std::equal_to<T>()(T(0), value(arg_list[i]))) 16324 | return T(0); 16325 | } 16326 | 16327 | return T(1); 16328 | } 16329 | } 16330 | } 16331 | 16332 | template <typename Sequence> 16333 | static inline T process_1(const Sequence& arg_list) 16334 | { 16335 | return std::not_equal_to<T>() 16336 | (T(0), value(arg_list[0])) ? T(1) : T(0); 16337 | } 16338 | 16339 | template <typename Sequence> 16340 | static inline T process_2(const Sequence& arg_list) 16341 | { 16342 | return ( 16343 | std::not_equal_to<T>()(T(0), value(arg_list[0])) && 16344 | std::not_equal_to<T>()(T(0), value(arg_list[1])) 16345 | ) ? T(1) : T(0); 16346 | } 16347 | 16348 | template <typename Sequence> 16349 | static inline T process_3(const Sequence& arg_list) 16350 | { 16351 | return ( 16352 | std::not_equal_to<T>()(T(0), value(arg_list[0])) && 16353 | std::not_equal_to<T>()(T(0), value(arg_list[1])) && 16354 | std::not_equal_to<T>()(T(0), value(arg_list[2])) 16355 | ) ? T(1) : T(0); 16356 | } 16357 | 16358 | template <typename Sequence> 16359 | static inline T process_4(const Sequence& arg_list) 16360 | { 16361 | return ( 16362 | std::not_equal_to<T>()(T(0), value(arg_list[0])) && 16363 | std::not_equal_to<T>()(T(0), value(arg_list[1])) && 16364 | std::not_equal_to<T>()(T(0), value(arg_list[2])) && 16365 | std::not_equal_to<T>()(T(0), value(arg_list[3])) 16366 | ) ? T(1) : T(0); 16367 | } 16368 | 16369 | template <typename Sequence> 16370 | static inline T process_5(const Sequence& arg_list) 16371 | { 16372 | return ( 16373 | std::not_equal_to<T>()(T(0), value(arg_list[0])) && 16374 | std::not_equal_to<T>()(T(0), value(arg_list[1])) && 16375 | std::not_equal_to<T>()(T(0), value(arg_list[2])) && 16376 | std::not_equal_to<T>()(T(0), value(arg_list[3])) && 16377 | std::not_equal_to<T>()(T(0), value(arg_list[4])) 16378 | ) ? T(1) : T(0); 16379 | } 16380 | }; 16381 | 16382 | template <typename T> 16383 | struct vararg_mor_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::not_equal_to<T>()(T(0), value(arg_list[i]))) 16404 | return T(1); 16405 | } 16406 | 16407 | return T(0); 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_multi_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 0 : return std::numeric_limits<T>::quiet_NaN(); 16475 | case 1 : return process_1(arg_list); 16476 | case 2 : return process_2(arg_list); 16477 | case 3 : return process_3(arg_list); 16478 | case 4 : return process_4(arg_list); 16479 | case 5 : return process_5(arg_list); 16480 | case 6 : return process_6(arg_list); 16481 | case 7 : return process_7(arg_list); 16482 | case 8 : return process_8(arg_list); 16483 | default : 16484 | { 16485 | for (std::size_t i = 0; i < (arg_list.size() - 1); ++i) 16486 | { 16487 | value(arg_list[i]); 16488 | } 16489 | return value(arg_list.back()); 16490 | } 16491 | } 16492 | } 16493 | 16494 | template <typename Sequence> 16495 | static inline T process_1(const Sequence& arg_list) 16496 | { 16497 | return value(arg_list[0]); 16498 | } 16499 | 16500 | template <typename Sequence> 16501 | static inline T process_2(const Sequence& arg_list) 16502 | { 16503 | value(arg_list[0]); 16504 | return value(arg_list[1]); 16505 | } 16506 | 16507 | template <typename Sequence> 16508 | static inline T process_3(const Sequence& arg_list) 16509 | { 16510 | value(arg_list[0]); 16511 | value(arg_list[1]); 16512 | return value(arg_list[2]); 16513 | } 16514 | 16515 | template <typename Sequence> 16516 | static inline T process_4(const Sequence& arg_list) 16517 | { 16518 | value(arg_list[0]); 16519 | value(arg_list[1]); 16520 | value(arg_list[2]); 16521 | return value(arg_list[3]); 16522 | } 16523 | 16524 | template <typename Sequence> 16525 | static inline T process_5(const Sequence& arg_list) 16526 | { 16527 | value(arg_list[0]); 16528 | value(arg_list[1]); 16529 | value(arg_list[2]); 16530 | value(arg_list[3]); 16531 | return value(arg_list[4]); 16532 | } 16533 | 16534 | template <typename Sequence> 16535 | static inline T process_6(const Sequence& arg_list) 16536 | { 16537 | value(arg_list[0]); 16538 | value(arg_list[1]); 16539 | value(arg_list[2]); 16540 | value(arg_list[3]); 16541 | value(arg_list[4]); 16542 | return value(arg_list[5]); 16543 | } 16544 | 16545 | template <typename Sequence> 16546 | static inline T process_7(const Sequence& arg_list) 16547 | { 16548 | value(arg_list[0]); 16549 | value(arg_list[1]); 16550 | value(arg_list[2]); 16551 | value(arg_list[3]); 16552 | value(arg_list[4]); 16553 | value(arg_list[5]); 16554 | return value(arg_list[6]); 16555 | } 16556 | 16557 | template <typename Sequence> 16558 | static inline T process_8(const Sequence& arg_list) 16559 | { 16560 | value(arg_list[0]); 16561 | value(arg_list[1]); 16562 | value(arg_list[2]); 16563 | value(arg_list[3]); 16564 | value(arg_list[4]); 16565 | value(arg_list[5]); 16566 | value(arg_list[6]); 16567 | return value(arg_list[7]); 16568 | } 16569 | }; 16570 | 16571 | template <typename T> 16572 | struct vec_add_op 16573 | { 16574 | typedef vector_interface<T>* ivector_ptr; 16575 | 16576 | static inline T process(const ivector_ptr v) 16577 | { 16578 | const T* vec = v->vec()->vds().data(); 16579 | const std::size_t vec_size = v->size(); 16580 | 16581 | loop_unroll::details lud(vec_size); 16582 | 16583 | if (vec_size <= static_cast<std::size_t>(lud.batch_size)) 16584 | { 16585 | T result = T(0); 16586 | int i = 0; 16587 | 16588 | switch (vec_size) 16589 | { 16590 | #define case_stmt(N,fall_through) \ 16591 | case N : result += vec[i++]; \ 16592 | fall_through \ 16593 | 16594 | #ifndef exprtk_disable_superscalar_unroll 16595 | case_stmt(16, exprtk_fallthrough) case_stmt(15, exprtk_fallthrough) 16596 | case_stmt(14, exprtk_fallthrough) case_stmt(13, exprtk_fallthrough) 16597 | case_stmt(12, exprtk_fallthrough) case_stmt(11, exprtk_fallthrough) 16598 | case_stmt(10, exprtk_fallthrough) case_stmt( 9, exprtk_fallthrough) 16599 | case_stmt( 8, exprtk_fallthrough) case_stmt( 7, exprtk_fallthrough) 16600 | case_stmt( 6, exprtk_fallthrough) case_stmt( 5, exprtk_fallthrough) 16601 | 16602 | #endif 16603 | case_stmt( 4, exprtk_fallthrough) case_stmt( 3, exprtk_fallthrough) 16604 | case_stmt( 2, exprtk_fallthrough) case_stmt( 1, (void)0;) 16605 | } 16606 | 16607 | #undef case_stmt 16608 | 16609 | return result; 16610 | } 16611 | 16612 | T r[] = { 16613 | T(0), T(0), T(0), T(0), T(0), T(0), T(0), T(0), 16614 | T(0), T(0), T(0), T(0), T(0), T(0), T(0), T(0) 16615 | }; 16616 | 16617 | const T* upper_bound = vec + lud.upper_bound; 16618 | 16619 | while (vec < upper_bound) 16620 | { 16621 | #define exprtk_loop(N) \ 16622 | r[N] += vec[N]; \ 16623 | 16624 | exprtk_loop( 0) exprtk_loop( 1) 16625 | exprtk_loop( 2) exprtk_loop( 3) 16626 | #ifndef exprtk_disable_superscalar_unroll 16627 | exprtk_loop( 4) exprtk_loop( 5) 16628 | exprtk_loop( 6) exprtk_loop( 7) 16629 | exprtk_loop( 8) exprtk_loop( 9) 16630 | exprtk_loop(10) exprtk_loop(11) 16631 | exprtk_loop(12) exprtk_loop(13) 16632 | exprtk_loop(14) exprtk_loop(15) 16633 | #endif 16634 | 16635 | vec += lud.batch_size; 16636 | } 16637 | 16638 | int i = 0; 16639 | 16640 | switch (lud.remainder) 16641 | { 16642 | #define case_stmt(N,fall_through) \ 16643 | case N : r[0] += vec[i++]; \ 16644 | fall_through \ 16645 | 16646 | #ifndef exprtk_disable_superscalar_unroll 16647 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 16648 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 16649 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 16650 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 16651 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 16652 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 16653 | #endif 16654 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 16655 | case_stmt( 1, (void)0;) 16656 | } 16657 | 16658 | #undef exprtk_loop 16659 | #undef case_stmt 16660 | 16661 | return (r[ 0] + r[ 1] + r[ 2] + r[ 3]) 16662 | #ifndef exprtk_disable_superscalar_unroll 16663 | + (r[ 4] + r[ 5] + r[ 6] + r[ 7]) 16664 | + (r[ 8] + r[ 9] + r[10] + r[11]) 16665 | + (r[12] + r[13] + r[14] + r[15]) 16666 | #endif 16667 | ; 16668 | } 16669 | }; 16670 | 16671 | template <typename T> 16672 | struct vec_mul_op 16673 | { 16674 | typedef vector_interface<T>* ivector_ptr; 16675 | 16676 | static inline T process(const ivector_ptr v) 16677 | { 16678 | const T* vec = v->vec()->vds().data(); 16679 | const std::size_t vec_size = v->vec()->size(); 16680 | 16681 | loop_unroll::details lud(vec_size); 16682 | 16683 | if (vec_size <= static_cast<std::size_t>(lud.batch_size)) 16684 | { 16685 | T result = T(1); 16686 | int i = 0; 16687 | 16688 | switch (vec_size) 16689 | { 16690 | #define case_stmt(N,fall_through) \ 16691 | case N : result *= vec[i++]; \ 16692 | fall_through \ 16693 | 16694 | #ifndef exprtk_disable_superscalar_unroll 16695 | case_stmt(16, exprtk_fallthrough) case_stmt(15, exprtk_fallthrough) 16696 | case_stmt(14, exprtk_fallthrough) case_stmt(13, exprtk_fallthrough) 16697 | case_stmt(12, exprtk_fallthrough) case_stmt(11, exprtk_fallthrough) 16698 | case_stmt(10, exprtk_fallthrough) case_stmt( 9, exprtk_fallthrough) 16699 | case_stmt( 8, exprtk_fallthrough) case_stmt( 7, exprtk_fallthrough) 16700 | case_stmt( 6, exprtk_fallthrough) case_stmt( 5, exprtk_fallthrough) 16701 | #endif 16702 | case_stmt( 4, exprtk_fallthrough) case_stmt( 3, exprtk_fallthrough) 16703 | case_stmt( 2, exprtk_fallthrough) case_stmt( 1, (void)0;) 16704 | } 16705 | 16706 | #undef case_stmt 16707 | 16708 | return result; 16709 | } 16710 | 16711 | T r[] = { 16712 | T(1), T(1), T(1), T(1), T(1), T(1), T(1), T(1), 16713 | T(1), T(1), T(1), T(1), T(1), T(1), T(1), T(1) 16714 | }; 16715 | 16716 | const T* upper_bound = vec + lud.upper_bound; 16717 | 16718 | while (vec < upper_bound) 16719 | { 16720 | #define exprtk_loop(N) \ 16721 | r[N] *= vec[N]; \ 16722 | 16723 | exprtk_loop( 0) exprtk_loop( 1) 16724 | exprtk_loop( 2) exprtk_loop( 3) 16725 | #ifndef exprtk_disable_superscalar_unroll 16726 | exprtk_loop( 4) exprtk_loop( 5) 16727 | exprtk_loop( 6) exprtk_loop( 7) 16728 | exprtk_loop( 8) exprtk_loop( 9) 16729 | exprtk_loop(10) exprtk_loop(11) 16730 | exprtk_loop(12) exprtk_loop(13) 16731 | exprtk_loop(14) exprtk_loop(15) 16732 | #endif 16733 | 16734 | vec += lud.batch_size; 16735 | } 16736 | 16737 | int i = 0; 16738 | 16739 | switch (lud.remainder) 16740 | { 16741 | #define case_stmt(N,fall_through) \ 16742 | case N : r[0] *= vec[i++]; \ 16743 | fall_through \ 16744 | 16745 | #ifndef exprtk_disable_superscalar_unroll 16746 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 16747 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 16748 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 16749 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 16750 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 16751 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 16752 | #endif 16753 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 16754 | case_stmt( 1, (void)0;) 16755 | } 16756 | 16757 | #undef exprtk_loop 16758 | #undef case_stmt 16759 | 16760 | return (r[ 0] * r[ 1] * r[ 2] * r[ 3]) 16761 | #ifndef exprtk_disable_superscalar_unroll 16762 | * (r[ 4] * r[ 5] * r[ 6] * r[ 7]) 16763 | * (r[ 8] * r[ 9] * r[10] * r[11]) 16764 | * (r[12] * r[13] * r[14] * r[15]) 16765 | #endif 16766 | ; 16767 | } 16768 | }; 16769 | 16770 | template <typename T> 16771 | struct vec_avg_op 16772 | { 16773 | typedef vector_interface<T>* ivector_ptr; 16774 | 16775 | static inline T process(const ivector_ptr v) 16776 | { 16777 | const T vec_size = T(v->vec()->size()); 16778 | return vec_add_op<T>::process(v) / vec_size; 16779 | } 16780 | }; 16781 | 16782 | template <typename T> 16783 | struct vec_min_op 16784 | { 16785 | typedef vector_interface<T>* ivector_ptr; 16786 | 16787 | static inline T process(const ivector_ptr v) 16788 | { 16789 | const T* vec = v->vec()->vds().data(); 16790 | const std::size_t vec_size = v->vec()->size(); 16791 | 16792 | T result = vec[0]; 16793 | 16794 | for (std::size_t i = 1; i < vec_size; ++i) 16795 | { 16796 | const T v_i = vec[i]; 16797 | 16798 | if (v_i < result) 16799 | result = v_i; 16800 | } 16801 | 16802 | return result; 16803 | } 16804 | }; 16805 | 16806 | template <typename T> 16807 | struct vec_max_op 16808 | { 16809 | typedef vector_interface<T>* ivector_ptr; 16810 | 16811 | static inline T process(const ivector_ptr v) 16812 | { 16813 | const T* vec = v->vec()->vds().data(); 16814 | const std::size_t vec_size = v->vec()->size(); 16815 | 16816 | T result = vec[0]; 16817 | 16818 | for (std::size_t i = 1; i < vec_size; ++i) 16819 | { 16820 | const T v_i = vec[i]; 16821 | 16822 | if (v_i > result) 16823 | result = v_i; 16824 | } 16825 | 16826 | return result; 16827 | } 16828 | }; 16829 | 16830 | template <typename T> 16831 | class vov_base_node : public expression_node<T> 16832 | { 16833 | public: 16834 | 16835 | virtual ~vov_base_node() 16836 | {} 16837 | 16838 | inline virtual operator_type operation() const 16839 | { 16840 | return details::e_default; 16841 | } 16842 | 16843 | virtual const T& v0() const = 0; 16844 | 16845 | virtual const T& v1() const = 0; 16846 | }; 16847 | 16848 | template <typename T> 16849 | class cov_base_node : public expression_node<T> 16850 | { 16851 | public: 16852 | 16853 | virtual ~cov_base_node() 16854 | {} 16855 | 16856 | inline virtual operator_type operation() const 16857 | { 16858 | return details::e_default; 16859 | } 16860 | 16861 | virtual const T c() const = 0; 16862 | 16863 | virtual const T& v() const = 0; 16864 | }; 16865 | 16866 | template <typename T> 16867 | class voc_base_node : public expression_node<T> 16868 | { 16869 | public: 16870 | 16871 | virtual ~voc_base_node() 16872 | {} 16873 | 16874 | inline virtual operator_type operation() const 16875 | { 16876 | return details::e_default; 16877 | } 16878 | 16879 | virtual const T c() const = 0; 16880 | 16881 | virtual const T& v() const = 0; 16882 | }; 16883 | 16884 | template <typename T> 16885 | class vob_base_node : public expression_node<T> 16886 | { 16887 | public: 16888 | 16889 | virtual ~vob_base_node() 16890 | {} 16891 | 16892 | virtual const T& v() const = 0; 16893 | }; 16894 | 16895 | template <typename T> 16896 | class bov_base_node : public expression_node<T> 16897 | { 16898 | public: 16899 | 16900 | virtual ~bov_base_node() 16901 | {} 16902 | 16903 | virtual const T& v() const = 0; 16904 | }; 16905 | 16906 | template <typename T> 16907 | class cob_base_node : public expression_node<T> 16908 | { 16909 | public: 16910 | 16911 | virtual ~cob_base_node() 16912 | {} 16913 | 16914 | inline virtual operator_type operation() const 16915 | { 16916 | return details::e_default; 16917 | } 16918 | 16919 | virtual const T c() const = 0; 16920 | 16921 | virtual void set_c(const T) = 0; 16922 | 16923 | virtual expression_node<T>* move_branch(const std::size_t& index) = 0; 16924 | }; 16925 | 16926 | template <typename T> 16927 | class boc_base_node : public expression_node<T> 16928 | { 16929 | public: 16930 | 16931 | virtual ~boc_base_node() 16932 | {} 16933 | 16934 | inline virtual operator_type operation() const 16935 | { 16936 | return details::e_default; 16937 | } 16938 | 16939 | virtual const T c() const = 0; 16940 | 16941 | virtual void set_c(const T) = 0; 16942 | 16943 | virtual expression_node<T>* move_branch(const std::size_t& index) = 0; 16944 | }; 16945 | 16946 | template <typename T> 16947 | class uv_base_node : public expression_node<T> 16948 | { 16949 | public: 16950 | 16951 | virtual ~uv_base_node() 16952 | {} 16953 | 16954 | inline virtual operator_type operation() const 16955 | { 16956 | return details::e_default; 16957 | } 16958 | 16959 | virtual const T& v() const = 0; 16960 | }; 16961 | 16962 | template <typename T> 16963 | class sos_base_node : public expression_node<T> 16964 | { 16965 | public: 16966 | 16967 | virtual ~sos_base_node() 16968 | {} 16969 | 16970 | inline virtual operator_type operation() const 16971 | { 16972 | return details::e_default; 16973 | } 16974 | }; 16975 | 16976 | template <typename T> 16977 | class sosos_base_node : public expression_node<T> 16978 | { 16979 | public: 16980 | 16981 | virtual ~sosos_base_node() 16982 | {} 16983 | 16984 | inline virtual operator_type operation() const 16985 | { 16986 | return details::e_default; 16987 | } 16988 | }; 16989 | 16990 | template <typename T> 16991 | class T0oT1oT2_base_node : public expression_node<T> 16992 | { 16993 | public: 16994 | 16995 | virtual ~T0oT1oT2_base_node() 16996 | {} 16997 | 16998 | virtual std::string type_id() const = 0; 16999 | }; 17000 | 17001 | template <typename T> 17002 | class T0oT1oT2oT3_base_node : public expression_node<T> 17003 | { 17004 | public: 17005 | 17006 | virtual ~T0oT1oT2oT3_base_node() 17007 | {} 17008 | 17009 | virtual std::string type_id() const = 0; 17010 | }; 17011 | 17012 | template <typename T, typename Operation> 17013 | class unary_variable_node exprtk_final : public uv_base_node<T> 17014 | { 17015 | public: 17016 | 17017 | typedef expression_node<T>* expression_ptr; 17018 | typedef Operation operation_t; 17019 | 17020 | explicit unary_variable_node(const T& var) 17021 | : v_(var) 17022 | {} 17023 | 17024 | inline T value() const exprtk_override 17025 | { 17026 | return Operation::process(v_); 17027 | } 17028 | 17029 | inline typename expression_node<T>::node_type type() const exprtk_override 17030 | { 17031 | return Operation::type(); 17032 | } 17033 | 17034 | inline operator_type operation() const exprtk_override 17035 | { 17036 | return Operation::operation(); 17037 | } 17038 | 17039 | inline const T& v() const exprtk_override 17040 | { 17041 | return v_; 17042 | } 17043 | 17044 | private: 17045 | 17046 | unary_variable_node(const unary_variable_node<T,Operation>&) exprtk_delete; 17047 | unary_variable_node<T,Operation>& operator=(const unary_variable_node<T,Operation>&) exprtk_delete; 17048 | 17049 | const T& v_; 17050 | }; 17051 | 17052 | template <typename T> 17053 | class uvouv_node exprtk_final : public expression_node<T> 17054 | { 17055 | public: 17056 | 17057 | // UOpr1(v0) Op UOpr2(v1) 17058 | typedef typename details::functor_t<T> functor_t; 17059 | typedef typename functor_t::bfunc_t bfunc_t; 17060 | typedef typename functor_t::ufunc_t ufunc_t; 17061 | typedef expression_node<T>* expression_ptr; 17062 | 17063 | explicit uvouv_node(const T& var0,const T& var1, 17064 | ufunc_t uf0, ufunc_t uf1, bfunc_t bf) 17065 | : v0_(var0) 17066 | , v1_(var1) 17067 | , u0_(uf0 ) 17068 | , u1_(uf1 ) 17069 | , f_ (bf ) 17070 | {} 17071 | 17072 | inline T value() const exprtk_override 17073 | { 17074 | return f_(u0_(v0_),u1_(v1_)); 17075 | } 17076 | 17077 | inline typename expression_node<T>::node_type type() const exprtk_override 17078 | { 17079 | return expression_node<T>::e_uvouv; 17080 | } 17081 | 17082 | inline const T& v0() 17083 | { 17084 | return v0_; 17085 | } 17086 | 17087 | inline const T& v1() 17088 | { 17089 | return v1_; 17090 | } 17091 | 17092 | inline ufunc_t u0() 17093 | { 17094 | return u0_; 17095 | } 17096 | 17097 | inline ufunc_t u1() 17098 | { 17099 | return u1_; 17100 | } 17101 | 17102 | inline ufunc_t f() 17103 | { 17104 | return f_; 17105 | } 17106 | 17107 | private: 17108 | 17109 | uvouv_node(const uvouv_node<T>&) exprtk_delete; 17110 | uvouv_node<T>& operator=(const uvouv_node<T>&) exprtk_delete; 17111 | 17112 | const T& v0_; 17113 | const T& v1_; 17114 | const ufunc_t u0_; 17115 | const ufunc_t u1_; 17116 | const bfunc_t f_; 17117 | }; 17118 | 17119 | template <typename T, typename Operation> 17120 | class unary_branch_node exprtk_final : public expression_node<T> 17121 | { 17122 | public: 17123 | 17124 | typedef Operation operation_t; 17125 | typedef expression_node<T>* expression_ptr; 17126 | typedef std::pair<expression_ptr,bool> branch_t; 17127 | 17128 | explicit unary_branch_node(expression_ptr branch) 17129 | { 17130 | construct_branch_pair(branch_, branch); 17131 | } 17132 | 17133 | inline T value() const exprtk_override 17134 | { 17135 | return Operation::process(branch_.first->value()); 17136 | } 17137 | 17138 | inline typename expression_node<T>::node_type type() const exprtk_override 17139 | { 17140 | return Operation::type(); 17141 | } 17142 | 17143 | inline bool valid() const exprtk_override 17144 | { 17145 | return branch_.first && branch_.first->valid(); 17146 | } 17147 | 17148 | inline operator_type operation() 17149 | { 17150 | return Operation::operation(); 17151 | } 17152 | 17153 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 17154 | { 17155 | return branch_.first; 17156 | } 17157 | 17158 | inline void release() 17159 | { 17160 | branch_.second = false; 17161 | } 17162 | 17163 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 17164 | { 17165 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 17166 | } 17167 | 17168 | std::size_t node_depth() const exprtk_override 17169 | { 17170 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 17171 | } 17172 | 17173 | private: 17174 | 17175 | unary_branch_node(const unary_branch_node<T,Operation>&) exprtk_delete; 17176 | unary_branch_node<T,Operation>& operator=(const unary_branch_node<T,Operation>&) exprtk_delete; 17177 | 17178 | branch_t branch_; 17179 | }; 17180 | 17181 | template <typename T> struct is_const { enum {result = 0}; }; 17182 | template <typename T> struct is_const <const T> { enum {result = 1}; }; 17183 | template <typename T> struct is_const_ref { enum {result = 0}; }; 17184 | template <typename T> struct is_const_ref <const T&> { enum {result = 1}; }; 17185 | template <typename T> struct is_ref { enum {result = 0}; }; 17186 | template <typename T> struct is_ref<T&> { enum {result = 1}; }; 17187 | template <typename T> struct is_ref<const T&> { enum {result = 0}; }; 17188 | 17189 | template <std::size_t State> 17190 | struct param_to_str { static std::string result() { static const std::string r("v"); return r; } }; 17191 | 17192 | template <> 17193 | struct param_to_str<0> { static std::string result() { static const std::string r("c"); return r; } }; 17194 | 17195 | #define exprtk_crtype(Type) \ 17196 | param_to_str<is_const_ref< Type >::result>::result() \ 17197 | 17198 | template <typename T> 17199 | struct T0oT1oT2process 17200 | { 17201 | typedef typename details::functor_t<T> functor_t; 17202 | typedef typename functor_t::bfunc_t bfunc_t; 17203 | 17204 | struct mode0 17205 | { 17206 | static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1) 17207 | { 17208 | // (T0 o0 T1) o1 T2 17209 | return bf1(bf0(t0,t1),t2); 17210 | } 17211 | 17212 | template <typename T0, typename T1, typename T2> 17213 | static inline std::string id() 17214 | { 17215 | static const std::string result = "(" + exprtk_crtype(T0) + "o" + 17216 | exprtk_crtype(T1) + ")o(" + 17217 | exprtk_crtype(T2) + ")" ; 17218 | return result; 17219 | } 17220 | }; 17221 | 17222 | struct mode1 17223 | { 17224 | static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1) 17225 | { 17226 | // T0 o0 (T1 o1 T2) 17227 | return bf0(t0,bf1(t1,t2)); 17228 | } 17229 | 17230 | template <typename T0, typename T1, typename T2> 17231 | static inline std::string id() 17232 | { 17233 | static const std::string result = "(" + exprtk_crtype(T0) + ")o(" + 17234 | exprtk_crtype(T1) + "o" + 17235 | exprtk_crtype(T2) + ")" ; 17236 | return result; 17237 | } 17238 | }; 17239 | }; 17240 | 17241 | template <typename T> 17242 | struct T0oT1oT20T3process 17243 | { 17244 | typedef typename details::functor_t<T> functor_t; 17245 | typedef typename functor_t::bfunc_t bfunc_t; 17246 | 17247 | struct mode0 17248 | { 17249 | static inline T process(const T& t0, const T& t1, 17250 | const T& t2, const T& t3, 17251 | const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) 17252 | { 17253 | // (T0 o0 T1) o1 (T2 o2 T3) 17254 | return bf1(bf0(t0,t1),bf2(t2,t3)); 17255 | } 17256 | 17257 | template <typename T0, typename T1, typename T2, typename T3> 17258 | static inline std::string id() 17259 | { 17260 | static const std::string result = "(" + exprtk_crtype(T0) + "o" + 17261 | exprtk_crtype(T1) + ")o" + 17262 | "(" + exprtk_crtype(T2) + "o" + 17263 | exprtk_crtype(T3) + ")" ; 17264 | return result; 17265 | } 17266 | }; 17267 | 17268 | struct mode1 17269 | { 17270 | static inline T process(const T& t0, const T& t1, 17271 | const T& t2, const T& t3, 17272 | const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) 17273 | { 17274 | // (T0 o0 (T1 o1 (T2 o2 T3)) 17275 | return bf0(t0,bf1(t1,bf2(t2,t3))); 17276 | } 17277 | template <typename T0, typename T1, typename T2, typename T3> 17278 | static inline std::string id() 17279 | { 17280 | static const std::string result = "(" + exprtk_crtype(T0) + ")o((" + 17281 | exprtk_crtype(T1) + ")o(" + 17282 | exprtk_crtype(T2) + "o" + 17283 | exprtk_crtype(T3) + "))" ; 17284 | return result; 17285 | } 17286 | }; 17287 | 17288 | struct mode2 17289 | { 17290 | static inline T process(const T& t0, const T& t1, 17291 | const T& t2, const T& t3, 17292 | const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) 17293 | { 17294 | // (T0 o0 ((T1 o1 T2) o2 T3) 17295 | return bf0(t0,bf2(bf1(t1,t2),t3)); 17296 | } 17297 | 17298 | template <typename T0, typename T1, typename T2, typename T3> 17299 | static inline std::string id() 17300 | { 17301 | static const std::string result = "(" + exprtk_crtype(T0) + ")o((" + 17302 | exprtk_crtype(T1) + "o" + 17303 | exprtk_crtype(T2) + ")o(" + 17304 | exprtk_crtype(T3) + "))" ; 17305 | return result; 17306 | } 17307 | }; 17308 | 17309 | struct mode3 17310 | { 17311 | static inline T process(const T& t0, const T& t1, 17312 | const T& t2, const T& t3, 17313 | const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) 17314 | { 17315 | // (((T0 o0 T1) o1 T2) o2 T3) 17316 | return bf2(bf1(bf0(t0,t1),t2),t3); 17317 | } 17318 | 17319 | template <typename T0, typename T1, typename T2, typename T3> 17320 | static inline std::string id() 17321 | { 17322 | static const std::string result = "((" + exprtk_crtype(T0) + "o" + 17323 | exprtk_crtype(T1) + ")o(" + 17324 | exprtk_crtype(T2) + "))o(" + 17325 | exprtk_crtype(T3) + ")" 17326 | return result; 17327 | } 17328 | }; 17329 | 17330 | struct mode4 17331 | { 17332 | static inline T process(const T& t0, const T& t1, 17333 | const T& t2, const T& t3, 17334 | const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) 17335 | { 17336 | // ((T0 o0 (T1 o1 T2)) o2 T3 17337 | return bf2(bf0(t0,bf1(t1,t2)),t3); 17338 | } 17339 | 17340 | template <typename T0, typename T1, typename T2, typename T3> 17341 | static inline std::string id() 17342 | { 17343 | static const std::string result = "((" + exprtk_crtype(T0) + ")o(" + 17344 | exprtk_crtype(T1) + "o" + 17345 | exprtk_crtype(T2) + "))o(" + 17346 | exprtk_crtype(T3) + ")" ; 17347 | return result; 17348 | } 17349 | }; 17350 | }; 17351 | 17352 | #undef exprtk_crtype 17353 | 17354 | template <typename T, typename T0, typename T1> 17355 | struct nodetype_T0oT1 { static const typename expression_node<T>::node_type result; }; 17356 | template <typename T, typename T0, typename T1> 17357 | const typename expression_node<T>::node_type nodetype_T0oT1<T,T0,T1>::result = expression_node<T>::e_none; 17358 | 17359 | #define synthesis_node_type_define(T0_, T1_, v_) \ 17360 | template <typename T, typename T0, typename T1> \ 17361 | struct nodetype_T0oT1<T,T0_,T1_> { static const typename expression_node<T>::node_type result; }; \ 17362 | template <typename T, typename T0, typename T1> \ 17363 | const typename expression_node<T>::node_type nodetype_T0oT1<T,T0_,T1_>::result = expression_node<T>:: v_; \ 17364 | 17365 | synthesis_node_type_define(const T0&, const T1&, e_vov) 17366 | synthesis_node_type_define(const T0&, const T1 , e_voc) 17367 | synthesis_node_type_define(const T0 , const T1&, e_cov) 17368 | synthesis_node_type_define( T0&, T1&, e_none) 17369 | synthesis_node_type_define(const T0 , const T1 , e_none) 17370 | synthesis_node_type_define( T0&, const T1 , e_none) 17371 | synthesis_node_type_define(const T0 , T1&, e_none) 17372 | synthesis_node_type_define(const T0&, T1&, e_none) 17373 | synthesis_node_type_define( T0&, const T1&, e_none) 17374 | #undef synthesis_node_type_define 17375 | 17376 | template <typename T, typename T0, typename T1, typename T2> 17377 | struct nodetype_T0oT1oT2 { static const typename expression_node<T>::node_type result; }; 17378 | template <typename T, typename T0, typename T1, typename T2> 17379 | const typename expression_node<T>::node_type nodetype_T0oT1oT2<T,T0,T1,T2>::result = expression_node<T>::e_none; 17380 | 17381 | #define synthesis_node_type_define(T0_, T1_, T2_, v_) \ 17382 | template <typename T, typename T0, typename T1, typename T2> \ 17383 | struct nodetype_T0oT1oT2<T,T0_,T1_,T2_> { static const typename expression_node<T>::node_type result; }; \ 17384 | template <typename T, typename T0, typename T1, typename T2> \ 17385 | const typename expression_node<T>::node_type nodetype_T0oT1oT2<T,T0_,T1_,T2_>::result = expression_node<T>:: v_; \ 17386 | 17387 | synthesis_node_type_define(const T0&, const T1&, const T2&, e_vovov) 17388 | synthesis_node_type_define(const T0&, const T1&, const T2 , e_vovoc) 17389 | synthesis_node_type_define(const T0&, const T1 , const T2&, e_vocov) 17390 | synthesis_node_type_define(const T0 , const T1&, const T2&, e_covov) 17391 | synthesis_node_type_define(const T0 , const T1&, const T2 , e_covoc) 17392 | synthesis_node_type_define(const T0 , const T1 , const T2 , e_none ) 17393 | synthesis_node_type_define(const T0 , const T1 , const T2&, e_none ) 17394 | synthesis_node_type_define(const T0&, const T1 , const T2 , e_none ) 17395 | synthesis_node_type_define( T0&, T1&, T2&, e_none ) 17396 | #undef synthesis_node_type_define 17397 | 17398 | template <typename T, typename T0, typename T1, typename T2, typename T3> 17399 | struct nodetype_T0oT1oT2oT3 { static const typename expression_node<T>::node_type result; }; 17400 | template <typename T, typename T0, typename T1, typename T2, typename T3> 17401 | const typename expression_node<T>::node_type nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result = expression_node<T>::e_none; 17402 | 17403 | #define synthesis_node_type_define(T0_, T1_, T2_, T3_, v_) \ 17404 | template <typename T, typename T0, typename T1, typename T2, typename T3> \ 17405 | struct nodetype_T0oT1oT2oT3<T,T0_,T1_,T2_,T3_> { static const typename expression_node<T>::node_type result; }; \ 17406 | template <typename T, typename T0, typename T1, typename T2, typename T3> \ 17407 | const typename expression_node<T>::node_type nodetype_T0oT1oT2oT3<T,T0_,T1_,T2_,T3_>::result = expression_node<T>:: v_; \ 17408 | 17409 | synthesis_node_type_define(const T0&, const T1&, const T2&, const T3&, e_vovovov) 17410 | synthesis_node_type_define(const T0&, const T1&, const T2&, const T3 , e_vovovoc) 17411 | synthesis_node_type_define(const T0&, const T1&, const T2 , const T3&, e_vovocov) 17412 | synthesis_node_type_define(const T0&, const T1 , const T2&, const T3&, e_vocovov) 17413 | synthesis_node_type_define(const T0 , const T1&, const T2&, const T3&, e_covovov) 17414 | synthesis_node_type_define(const T0 , const T1&, const T2 , const T3&, e_covocov) 17415 | synthesis_node_type_define(const T0&, const T1 , const T2&, const T3 , e_vocovoc) 17416 | synthesis_node_type_define(const T0 , const T1&, const T2&, const T3 , e_covovoc) 17417 | synthesis_node_type_define(const T0&, const T1 , const T2 , const T3&, e_vococov) 17418 | synthesis_node_type_define(const T0 , const T1 , const T2 , const T3 , e_none ) 17419 | synthesis_node_type_define(const T0 , const T1 , const T2 , const T3&, e_none ) 17420 | synthesis_node_type_define(const T0 , const T1 , const T2&, const T3 , e_none ) 17421 | synthesis_node_type_define(const T0 , const T1&, const T2 , const T3 , e_none ) 17422 | synthesis_node_type_define(const T0&, const T1 , const T2 , const T3 , e_none ) 17423 | synthesis_node_type_define(const T0 , const T1 , const T2&, const T3&, e_none ) 17424 | synthesis_node_type_define(const T0&, const T1&, const T2 , const T3 , e_none ) 17425 | #undef synthesis_node_type_define 17426 | 17427 | template <typename T, typename T0, typename T1> 17428 | class T0oT1 exprtk_final : public expression_node<T> 17429 | { 17430 | public: 17431 | 17432 | typedef typename details::functor_t<T> functor_t; 17433 | typedef typename functor_t::bfunc_t bfunc_t; 17434 | typedef T value_type; 17435 | typedef T0oT1<T,T0,T1> node_type; 17436 | 17437 | T0oT1(T0 p0, T1 p1, const bfunc_t p2) 17438 | : t0_(p0) 17439 | , t1_(p1) 17440 | , f_ (p2) 17441 | {} 17442 | 17443 | inline typename expression_node<T>::node_type type() const exprtk_override 17444 | { 17445 | static const typename expression_node<T>::node_type result = nodetype_T0oT1<T,T0,T1>::result; 17446 | return result; 17447 | } 17448 | 17449 | inline operator_type operation() const exprtk_override 17450 | { 17451 | return e_default; 17452 | } 17453 | 17454 | inline T value() const exprtk_override 17455 | { 17456 | return f_(t0_,t1_); 17457 | } 17458 | 17459 | inline T0 t0() const 17460 | { 17461 | return t0_; 17462 | } 17463 | 17464 | inline T1 t1() const 17465 | { 17466 | return t1_; 17467 | } 17468 | 17469 | inline bfunc_t f() const 17470 | { 17471 | return f_; 17472 | } 17473 | 17474 | template <typename Allocator> 17475 | static inline expression_node<T>* allocate(Allocator& allocator, 17476 | T0 p0, T1 p1, 17477 | bfunc_t p2) 17478 | { 17479 | return allocator 17480 | .template allocate_type<node_type, T0, T1, bfunc_t&> 17481 | (p0, p1, p2); 17482 | } 17483 | 17484 | private: 17485 | 17486 | T0oT1(const T0oT1<T,T0,T1>&) exprtk_delete; 17487 | T0oT1<T,T0,T1>& operator=(const T0oT1<T,T0,T1>&) { return (*this); } 17488 | 17489 | T0 t0_; 17490 | T1 t1_; 17491 | const bfunc_t f_; 17492 | }; 17493 | 17494 | template <typename T, typename T0, typename T1, typename T2, typename ProcessMode> 17495 | class T0oT1oT2 exprtk_final : public T0oT1oT2_base_node<T> 17496 | { 17497 | public: 17498 | 17499 | typedef typename details::functor_t<T> functor_t; 17500 | typedef typename functor_t::bfunc_t bfunc_t; 17501 | typedef T value_type; 17502 | typedef T0oT1oT2<T,T0,T1,T2,ProcessMode> node_type; 17503 | typedef ProcessMode process_mode_t; 17504 | 17505 | T0oT1oT2(T0 p0, T1 p1, T2 p2, const bfunc_t p3, const bfunc_t p4) 17506 | : t0_(p0) 17507 | , t1_(p1) 17508 | , t2_(p2) 17509 | , f0_(p3) 17510 | , f1_(p4) 17511 | {} 17512 | 17513 | inline typename expression_node<T>::node_type type() const exprtk_override 17514 | { 17515 | static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result; 17516 | return result; 17517 | } 17518 | 17519 | inline operator_type operation() 17520 | { 17521 | return e_default; 17522 | } 17523 | 17524 | inline T value() const exprtk_override 17525 | { 17526 | return ProcessMode::process(t0_, t1_, t2_, f0_, f1_); 17527 | } 17528 | 17529 | inline T0 t0() const 17530 | { 17531 | return t0_; 17532 | } 17533 | 17534 | inline T1 t1() const 17535 | { 17536 | return t1_; 17537 | } 17538 | 17539 | inline T2 t2() const 17540 | { 17541 | return t2_; 17542 | } 17543 | 17544 | bfunc_t f0() const 17545 | { 17546 | return f0_; 17547 | } 17548 | 17549 | bfunc_t f1() const 17550 | { 17551 | return f1_; 17552 | } 17553 | 17554 | std::string type_id() const exprtk_override 17555 | { 17556 | return id(); 17557 | } 17558 | 17559 | static inline std::string id() 17560 | { 17561 | return process_mode_t::template id<T0,T1,T2>(); 17562 | } 17563 | 17564 | template <typename Allocator> 17565 | static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, bfunc_t p3, bfunc_t p4) 17566 | { 17567 | return allocator 17568 | .template allocate_type<node_type, T0, T1, T2, bfunc_t, bfunc_t> 17569 | (p0, p1, p2, p3, p4); 17570 | } 17571 | 17572 | private: 17573 | 17574 | T0oT1oT2(const node_type&) exprtk_delete; 17575 | node_type& operator=(const node_type&) exprtk_delete; 17576 | 17577 | T0 t0_; 17578 | T1 t1_; 17579 | T2 t2_; 17580 | const bfunc_t f0_; 17581 | const bfunc_t f1_; 17582 | }; 17583 | 17584 | template <typename T, typename T0_, typename T1_, typename T2_, typename T3_, typename ProcessMode> 17585 | class T0oT1oT2oT3 exprtk_final : public T0oT1oT2oT3_base_node<T> 17586 | { 17587 | public: 17588 | 17589 | typedef typename details::functor_t<T> functor_t; 17590 | typedef typename functor_t::bfunc_t bfunc_t; 17591 | typedef T value_type; 17592 | typedef T0_ T0; 17593 | typedef T1_ T1; 17594 | typedef T2_ T2; 17595 | typedef T3_ T3; 17596 | typedef T0oT1oT2oT3<T,T0,T1,T2,T3,ProcessMode> node_type; 17597 | typedef ProcessMode process_mode_t; 17598 | 17599 | T0oT1oT2oT3(T0 p0, T1 p1, T2 p2, T3 p3, bfunc_t p4, bfunc_t p5, bfunc_t p6) 17600 | : t0_(p0) 17601 | , t1_(p1) 17602 | , t2_(p2) 17603 | , t3_(p3) 17604 | , f0_(p4) 17605 | , f1_(p5) 17606 | , f2_(p6) 17607 | {} 17608 | 17609 | inline T value() const exprtk_override 17610 | { 17611 | return ProcessMode::process(t0_, t1_, t2_, t3_, f0_, f1_, f2_); 17612 | } 17613 | 17614 | inline T0 t0() const 17615 | { 17616 | return t0_; 17617 | } 17618 | 17619 | inline T1 t1() const 17620 | { 17621 | return t1_; 17622 | } 17623 | 17624 | inline T2 t2() const 17625 | { 17626 | return t2_; 17627 | } 17628 | 17629 | inline T3 t3() const 17630 | { 17631 | return t3_; 17632 | } 17633 | 17634 | inline bfunc_t f0() const 17635 | { 17636 | return f0_; 17637 | } 17638 | 17639 | inline bfunc_t f1() const 17640 | { 17641 | return f1_; 17642 | } 17643 | 17644 | inline bfunc_t f2() const 17645 | { 17646 | return f2_; 17647 | } 17648 | 17649 | inline std::string type_id() const exprtk_override 17650 | { 17651 | return id(); 17652 | } 17653 | 17654 | static inline std::string id() 17655 | { 17656 | return process_mode_t::template id<T0, T1, T2, T3>(); 17657 | } 17658 | 17659 | template <typename Allocator> 17660 | static inline expression_node<T>* allocate(Allocator& allocator, 17661 | T0 p0, T1 p1, T2 p2, T3 p3, 17662 | bfunc_t p4, bfunc_t p5, bfunc_t p6) 17663 | { 17664 | return allocator 17665 | .template allocate_type<node_type, T0, T1, T2, T3, bfunc_t, bfunc_t> 17666 | (p0, p1, p2, p3, p4, p5, p6); 17667 | } 17668 | 17669 | private: 17670 | 17671 | T0oT1oT2oT3(const node_type&) exprtk_delete; 17672 | node_type& operator=(const node_type&) exprtk_delete; 17673 | 17674 | T0 t0_; 17675 | T1 t1_; 17676 | T2 t2_; 17677 | T3 t3_; 17678 | const bfunc_t f0_; 17679 | const bfunc_t f1_; 17680 | const bfunc_t f2_; 17681 | }; 17682 | 17683 | template <typename T, typename T0, typename T1, typename T2> 17684 | class T0oT1oT2_sf3 exprtk_final : public T0oT1oT2_base_node<T> 17685 | { 17686 | public: 17687 | 17688 | typedef typename details::functor_t<T> functor_t; 17689 | typedef typename functor_t::tfunc_t tfunc_t; 17690 | typedef T value_type; 17691 | typedef T0oT1oT2_sf3<T,T0,T1,T2> node_type; 17692 | 17693 | T0oT1oT2_sf3(T0 p0, T1 p1, T2 p2, const tfunc_t p3) 17694 | : t0_(p0) 17695 | , t1_(p1) 17696 | , t2_(p2) 17697 | , f_ (p3) 17698 | {} 17699 | 17700 | inline typename expression_node<T>::node_type type() const exprtk_override 17701 | { 17702 | static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result; 17703 | return result; 17704 | } 17705 | 17706 | inline operator_type operation() const exprtk_override 17707 | { 17708 | return e_default; 17709 | } 17710 | 17711 | inline T value() const exprtk_override 17712 | { 17713 | return f_(t0_, t1_, t2_); 17714 | } 17715 | 17716 | inline T0 t0() const 17717 | { 17718 | return t0_; 17719 | } 17720 | 17721 | inline T1 t1() const 17722 | { 17723 | return t1_; 17724 | } 17725 | 17726 | inline T2 t2() const 17727 | { 17728 | return t2_; 17729 | } 17730 | 17731 | tfunc_t f() const 17732 | { 17733 | return f_; 17734 | } 17735 | 17736 | std::string type_id() const 17737 | { 17738 | return id(); 17739 | } 17740 | 17741 | static inline std::string id() 17742 | { 17743 | return "sf3" 17744 | } 17745 | 17746 | template <typename Allocator> 17747 | static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, tfunc_t p3) 17748 | { 17749 | return allocator 17750 | .template allocate_type<node_type, T0, T1, T2, tfunc_t> 17751 | (p0, p1, p2, p3); 17752 | } 17753 | 17754 | private: 17755 | 17756 | T0oT1oT2_sf3(const node_type&) exprtk_delete; 17757 | node_type& operator=(const node_type&) exprtk_delete; 17758 | 17759 | T0 t0_; 17760 | T1 t1_; 17761 | T2 t2_; 17762 | const tfunc_t f_; 17763 | }; 17764 | 17765 | template <typename T, typename T0, typename T1, typename T2> 17766 | class sf3ext_type_node : public T0oT1oT2_base_node<T> 17767 | { 17768 | public: 17769 | 17770 | virtual ~sf3ext_type_node() 17771 | {} 17772 | 17773 | virtual T0 t0() const = 0; 17774 | 17775 | virtual T1 t1() const = 0; 17776 | 17777 | virtual T2 t2() const = 0; 17778 | }; 17779 | 17780 | template <typename T, typename T0, typename T1, typename T2, typename SF3Operation> 17781 | class T0oT1oT2_sf3ext exprtk_final : public sf3ext_type_node<T,T0,T1,T2> 17782 | { 17783 | public: 17784 | 17785 | typedef T value_type; 17786 | typedef T0oT1oT2_sf3ext<T, T0, T1, T2, SF3Operation> node_type; 17787 | 17788 | T0oT1oT2_sf3ext(T0 p0, T1 p1, T2 p2) 17789 | : t0_(p0) 17790 | , t1_(p1) 17791 | , t2_(p2) 17792 | {} 17793 | 17794 | inline typename expression_node<T>::node_type type() const exprtk_override 17795 | { 17796 | static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result; 17797 | return result; 17798 | } 17799 | 17800 | inline operator_type operation() 17801 | { 17802 | return e_default; 17803 | } 17804 | 17805 | inline T value() const exprtk_override 17806 | { 17807 | return SF3Operation::process(t0_, t1_, t2_); 17808 | } 17809 | 17810 | T0 t0() const exprtk_override 17811 | { 17812 | return t0_; 17813 | } 17814 | 17815 | T1 t1() const exprtk_override 17816 | { 17817 | return t1_; 17818 | } 17819 | 17820 | T2 t2() const exprtk_override 17821 | { 17822 | return t2_; 17823 | } 17824 | 17825 | std::string type_id() const exprtk_override 17826 | { 17827 | return id(); 17828 | } 17829 | 17830 | static inline std::string id() 17831 | { 17832 | return SF3Operation::id(); 17833 | } 17834 | 17835 | template <typename Allocator> 17836 | static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2) 17837 | { 17838 | return allocator 17839 | .template allocate_type<node_type, T0, T1, T2> 17840 | (p0, p1, p2); 17841 | } 17842 | 17843 | private: 17844 | 17845 | T0oT1oT2_sf3ext(const node_type&) exprtk_delete; 17846 | node_type& operator=(const node_type&) exprtk_delete; 17847 | 17848 | T0 t0_; 17849 | T1 t1_; 17850 | T2 t2_; 17851 | }; 17852 | 17853 | template <typename T> 17854 | inline bool is_sf3ext_node(const expression_node<T>* n) 17855 | { 17856 | switch (n->type()) 17857 | { 17858 | case expression_node<T>::e_vovov : return true; 17859 | case expression_node<T>::e_vovoc : return true; 17860 | case expression_node<T>::e_vocov : return true; 17861 | case expression_node<T>::e_covov : return true; 17862 | case expression_node<T>::e_covoc : return true; 17863 | default : return false; 17864 | } 17865 | } 17866 | 17867 | template <typename T, typename T0, typename T1, typename T2, typename T3> 17868 | class T0oT1oT2oT3_sf4 exprtk_final : public T0oT1oT2_base_node<T> 17869 | { 17870 | public: 17871 | 17872 | typedef typename details::functor_t<T> functor_t; 17873 | typedef typename functor_t::qfunc_t qfunc_t; 17874 | typedef T value_type; 17875 | typedef T0oT1oT2oT3_sf4<T, T0, T1, T2, T3> node_type; 17876 | 17877 | T0oT1oT2oT3_sf4(T0 p0, T1 p1, T2 p2, T3 p3, const qfunc_t p4) 17878 | : t0_(p0) 17879 | , t1_(p1) 17880 | , t2_(p2) 17881 | , t3_(p3) 17882 | , f_ (p4) 17883 | {} 17884 | 17885 | inline typename expression_node<T>::node_type type() const exprtk_override 17886 | { 17887 | static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result; 17888 | return result; 17889 | } 17890 | 17891 | inline operator_type operation() const exprtk_override 17892 | { 17893 | return e_default; 17894 | } 17895 | 17896 | inline T value() const exprtk_override 17897 | { 17898 | return f_(t0_, t1_, t2_, t3_); 17899 | } 17900 | 17901 | inline T0 t0() const 17902 | { 17903 | return t0_; 17904 | } 17905 | 17906 | inline T1 t1() const 17907 | { 17908 | return t1_; 17909 | } 17910 | 17911 | inline T2 t2() const 17912 | { 17913 | return t2_; 17914 | } 17915 | 17916 | inline T3 t3() const 17917 | { 17918 | return t3_; 17919 | } 17920 | 17921 | qfunc_t f() const 17922 | { 17923 | return f_; 17924 | } 17925 | 17926 | std::string type_id() const 17927 | { 17928 | return id(); 17929 | } 17930 | 17931 | static inline std::string id() 17932 | { 17933 | return "sf4" 17934 | } 17935 | 17936 | template <typename Allocator> 17937 | static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, T3 p3, qfunc_t p4) 17938 | { 17939 | return allocator 17940 | .template allocate_type<node_type, T0, T1, T2, T3, qfunc_t> 17941 | (p0, p1, p2, p3, p4); 17942 | } 17943 | 17944 | private: 17945 | 17946 | T0oT1oT2oT3_sf4(const node_type&) exprtk_delete; 17947 | node_type& operator=(const node_type&) exprtk_delete; 17948 | 17949 | T0 t0_; 17950 | T1 t1_; 17951 | T2 t2_; 17952 | T3 t3_; 17953 | const qfunc_t f_; 17954 | }; 17955 | 17956 | template <typename T, typename T0, typename T1, typename T2, typename T3, typename SF4Operation> 17957 | class T0oT1oT2oT3_sf4ext exprtk_final : public T0oT1oT2oT3_base_node<T> 17958 | { 17959 | public: 17960 | 17961 | typedef T value_type; 17962 | typedef T0oT1oT2oT3_sf4ext<T, T0, T1, T2, T3, SF4Operation> node_type; 17963 | 17964 | T0oT1oT2oT3_sf4ext(T0 p0, T1 p1, T2 p2, T3 p3) 17965 | : t0_(p0) 17966 | , t1_(p1) 17967 | , t2_(p2) 17968 | , t3_(p3) 17969 | {} 17970 | 17971 | inline typename expression_node<T>::node_type type() const exprtk_override 17972 | { 17973 | static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result; 17974 | return result; 17975 | } 17976 | 17977 | inline T value() const exprtk_override 17978 | { 17979 | return SF4Operation::process(t0_, t1_, t2_, t3_); 17980 | } 17981 | 17982 | inline T0 t0() const 17983 | { 17984 | return t0_; 17985 | } 17986 | 17987 | inline T1 t1() const 17988 | { 17989 | return t1_; 17990 | } 17991 | 17992 | inline T2 t2() const 17993 | { 17994 | return t2_; 17995 | } 17996 | 17997 | inline T3 t3() const 17998 | { 17999 | return t3_; 18000 | } 18001 | 18002 | std::string type_id() const exprtk_override 18003 | { 18004 | return id(); 18005 | } 18006 | 18007 | static inline std::string id() 18008 | { 18009 | return SF4Operation::id(); 18010 | } 18011 | 18012 | template <typename Allocator> 18013 | static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, T3 p3) 18014 | { 18015 | return allocator 18016 | .template allocate_type<node_type, T0, T1, T2, T3> 18017 | (p0, p1, p2, p3); 18018 | } 18019 | 18020 | private: 18021 | 18022 | T0oT1oT2oT3_sf4ext(const node_type&) exprtk_delete; 18023 | node_type& operator=(const node_type&) exprtk_delete; 18024 | 18025 | T0 t0_; 18026 | T1 t1_; 18027 | T2 t2_; 18028 | T3 t3_; 18029 | }; 18030 | 18031 | template <typename T> 18032 | inline bool is_sf4ext_node(const expression_node<T>* n) 18033 | { 18034 | switch (n->type()) 18035 | { 18036 | case expression_node<T>::e_vovovov : return true; 18037 | case expression_node<T>::e_vovovoc : return true; 18038 | case expression_node<T>::e_vovocov : return true; 18039 | case expression_node<T>::e_vocovov : return true; 18040 | case expression_node<T>::e_covovov : return true; 18041 | case expression_node<T>::e_covocov : return true; 18042 | case expression_node<T>::e_vocovoc : return true; 18043 | case expression_node<T>::e_covovoc : return true; 18044 | case expression_node<T>::e_vococov : return true; 18045 | default : return false; 18046 | } 18047 | } 18048 | 18049 | template <typename T, typename T0, typename T1> 18050 | struct T0oT1_define 18051 | { 18052 | typedef details::T0oT1<T, T0, T1> type0; 18053 | }; 18054 | 18055 | template <typename T, typename T0, typename T1, typename T2> 18056 | struct T0oT1oT2_define 18057 | { 18058 | typedef details::T0oT1oT2<T, T0, T1, T2, typename T0oT1oT2process<T>::mode0> type0; 18059 | typedef details::T0oT1oT2<T, T0, T1, T2, typename T0oT1oT2process<T>::mode1> type1; 18060 | typedef details::T0oT1oT2_sf3<T, T0, T1, T2> sf3_type; 18061 | typedef details::sf3ext_type_node<T, T0, T1, T2> sf3_type_node; 18062 | }; 18063 | 18064 | template <typename T, typename T0, typename T1, typename T2, typename T3> 18065 | struct T0oT1oT2oT3_define 18066 | { 18067 | typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode0> type0; 18068 | typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode1> type1; 18069 | typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode2> type2; 18070 | typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode3> type3; 18071 | typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode4> type4; 18072 | typedef details::T0oT1oT2oT3_sf4<T, T0, T1, T2, T3> sf4_type; 18073 | }; 18074 | 18075 | template <typename T, typename Operation> 18076 | class vov_node exprtk_final : public vov_base_node<T> 18077 | { 18078 | public: 18079 | 18080 | typedef expression_node<T>* expression_ptr; 18081 | typedef Operation operation_t; 18082 | 18083 | // variable op variable node 18084 | explicit vov_node(const T& var0, const T& var1) 18085 | : v0_(var0) 18086 | , v1_(var1) 18087 | {} 18088 | 18089 | inline T value() const exprtk_override 18090 | { 18091 | return Operation::process(v0_,v1_); 18092 | } 18093 | 18094 | inline typename expression_node<T>::node_type type() const exprtk_override 18095 | { 18096 | return Operation::type(); 18097 | } 18098 | 18099 | inline operator_type operation() const exprtk_override 18100 | { 18101 | return Operation::operation(); 18102 | } 18103 | 18104 | inline const T& v0() const exprtk_override 18105 | { 18106 | return v0_; 18107 | } 18108 | 18109 | inline const T& v1() const exprtk_override 18110 | { 18111 | return v1_; 18112 | } 18113 | 18114 | protected: 18115 | 18116 | const T& v0_; 18117 | const T& v1_; 18118 | 18119 | private: 18120 | 18121 | vov_node(const vov_node<T,Operation>&) exprtk_delete; 18122 | vov_node<T,Operation>& operator=(const vov_node<T,Operation>&) exprtk_delete; 18123 | }; 18124 | 18125 | template <typename T, typename Operation> 18126 | class cov_node exprtk_final : public cov_base_node<T> 18127 | { 18128 | public: 18129 | 18130 | typedef expression_node<T>* expression_ptr; 18131 | typedef Operation operation_t; 18132 | 18133 | // constant op variable node 18134 | explicit cov_node(const T& const_var, const T& var) 18135 | : c_(const_var) 18136 | , v_(var) 18137 | {} 18138 | 18139 | inline T value() const exprtk_override 18140 | { 18141 | return Operation::process(c_,v_); 18142 | } 18143 | 18144 | inline typename expression_node<T>::node_type type() const exprtk_override 18145 | { 18146 | return Operation::type(); 18147 | } 18148 | 18149 | inline operator_type operation() const exprtk_override 18150 | { 18151 | return Operation::operation(); 18152 | } 18153 | 18154 | inline const T c() const exprtk_override 18155 | { 18156 | return c_; 18157 | } 18158 | 18159 | inline const T& v() const exprtk_override 18160 | { 18161 | return v_; 18162 | } 18163 | 18164 | protected: 18165 | 18166 | const T c_; 18167 | const T& v_; 18168 | 18169 | private: 18170 | 18171 | cov_node(const cov_node<T,Operation>&) exprtk_delete; 18172 | cov_node<T,Operation>& operator=(const cov_node<T,Operation>&) exprtk_delete; 18173 | }; 18174 | 18175 | template <typename T, typename Operation> 18176 | class voc_node exprtk_final : public voc_base_node<T> 18177 | { 18178 | public: 18179 | 18180 | typedef expression_node<T>* expression_ptr; 18181 | typedef Operation operation_t; 18182 | 18183 | // variable op constant node 18184 | explicit voc_node(const T& var, const T& const_var) 18185 | : v_(var) 18186 | , c_(const_var) 18187 | {} 18188 | 18189 | inline T value() const exprtk_override 18190 | { 18191 | return Operation::process(v_,c_); 18192 | } 18193 | 18194 | inline operator_type operation() const exprtk_override 18195 | { 18196 | return Operation::operation(); 18197 | } 18198 | 18199 | inline const T c() const exprtk_override 18200 | { 18201 | return c_; 18202 | } 18203 | 18204 | inline const T& v() const exprtk_override 18205 | { 18206 | return v_; 18207 | } 18208 | 18209 | protected: 18210 | 18211 | const T& v_; 18212 | const T c_; 18213 | 18214 | private: 18215 | 18216 | voc_node(const voc_node<T,Operation>&) exprtk_delete; 18217 | voc_node<T,Operation>& operator=(const voc_node<T,Operation>&) exprtk_delete; 18218 | }; 18219 | 18220 | template <typename T, typename Operation> 18221 | class vob_node exprtk_final : public vob_base_node<T> 18222 | { 18223 | public: 18224 | 18225 | typedef expression_node<T>* expression_ptr; 18226 | typedef std::pair<expression_ptr,bool> branch_t; 18227 | typedef Operation operation_t; 18228 | 18229 | // variable op binary node 18230 | explicit vob_node(const T& var, const expression_ptr branch) 18231 | : v_(var) 18232 | { 18233 | construct_branch_pair(branch_, branch); 18234 | assert(valid()); 18235 | } 18236 | 18237 | inline T value() const exprtk_override 18238 | { 18239 | return Operation::process(v_,branch_.first->value()); 18240 | } 18241 | 18242 | inline const T& v() const exprtk_override 18243 | { 18244 | return v_; 18245 | } 18246 | 18247 | inline bool valid() const exprtk_override 18248 | { 18249 | return branch_.first && branch_.first->valid(); 18250 | } 18251 | 18252 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 18253 | { 18254 | return branch_.first; 18255 | } 18256 | 18257 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 18258 | { 18259 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 18260 | } 18261 | 18262 | std::size_t node_depth() const exprtk_override 18263 | { 18264 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 18265 | } 18266 | 18267 | private: 18268 | 18269 | vob_node(const vob_node<T,Operation>&) exprtk_delete; 18270 | vob_node<T,Operation>& operator=(const vob_node<T,Operation>&) exprtk_delete; 18271 | 18272 | const T& v_; 18273 | branch_t branch_; 18274 | }; 18275 | 18276 | template <typename T, typename Operation> 18277 | class bov_node exprtk_final : public bov_base_node<T> 18278 | { 18279 | public: 18280 | 18281 | typedef expression_node<T>* expression_ptr; 18282 | typedef std::pair<expression_ptr,bool> branch_t; 18283 | typedef Operation operation_t; 18284 | 18285 | // binary node op variable node 18286 | explicit bov_node(const expression_ptr branch, const T& var) 18287 | : v_(var) 18288 | { 18289 | construct_branch_pair(branch_, branch); 18290 | assert(valid()); 18291 | } 18292 | 18293 | inline T value() const exprtk_override 18294 | { 18295 | return Operation::process(branch_.first->value(),v_); 18296 | } 18297 | 18298 | inline const T& v() const exprtk_override 18299 | { 18300 | return v_; 18301 | } 18302 | 18303 | inline bool valid() const exprtk_override 18304 | { 18305 | return branch_.first && branch_.first->valid(); 18306 | } 18307 | 18308 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 18309 | { 18310 | return branch_.first; 18311 | } 18312 | 18313 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 18314 | { 18315 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 18316 | } 18317 | 18318 | std::size_t node_depth() const exprtk_override 18319 | { 18320 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 18321 | } 18322 | 18323 | private: 18324 | 18325 | bov_node(const bov_node<T,Operation>&) exprtk_delete; 18326 | bov_node<T,Operation>& operator=(const bov_node<T,Operation>&) exprtk_delete; 18327 | 18328 | const T& v_; 18329 | branch_t branch_; 18330 | }; 18331 | 18332 | template <typename T, typename Operation> 18333 | class cob_node exprtk_final : public cob_base_node<T> 18334 | { 18335 | public: 18336 | 18337 | typedef expression_node<T>* expression_ptr; 18338 | typedef std::pair<expression_ptr,bool> branch_t; 18339 | typedef Operation operation_t; 18340 | 18341 | // constant op variable node 18342 | explicit cob_node(const T const_var, const expression_ptr branch) 18343 | : c_(const_var) 18344 | { 18345 | construct_branch_pair(branch_, branch); 18346 | assert(valid()); 18347 | } 18348 | 18349 | inline T value() const exprtk_override 18350 | { 18351 | return Operation::process(c_,branch_.first->value()); 18352 | } 18353 | 18354 | inline operator_type operation() const exprtk_override 18355 | { 18356 | return Operation::operation(); 18357 | } 18358 | 18359 | inline const T c() const exprtk_override 18360 | { 18361 | return c_; 18362 | } 18363 | 18364 | inline void set_c(const T new_c) exprtk_override 18365 | { 18366 | (*const_cast<T*>(&c_)) = new_c; 18367 | } 18368 | 18369 | inline bool valid() const exprtk_override 18370 | { 18371 | return branch_.first && branch_.first->valid(); 18372 | } 18373 | 18374 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 18375 | { 18376 | return branch_.first; 18377 | } 18378 | 18379 | inline expression_node<T>* move_branch(const std::size_t&) exprtk_override 18380 | { 18381 | branch_.second = false; 18382 | return branch_.first; 18383 | } 18384 | 18385 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 18386 | { 18387 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 18388 | } 18389 | 18390 | std::size_t node_depth() const exprtk_override 18391 | { 18392 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 18393 | } 18394 | 18395 | private: 18396 | 18397 | cob_node(const cob_node<T,Operation>&) exprtk_delete; 18398 | cob_node<T,Operation>& operator=(const cob_node<T,Operation>&) exprtk_delete; 18399 | 18400 | const T c_; 18401 | branch_t branch_; 18402 | }; 18403 | 18404 | template <typename T, typename Operation> 18405 | class boc_node exprtk_final : public boc_base_node<T> 18406 | { 18407 | public: 18408 | 18409 | typedef expression_node<T>* expression_ptr; 18410 | typedef std::pair<expression_ptr,bool> branch_t; 18411 | typedef Operation operation_t; 18412 | 18413 | // binary node op constant node 18414 | explicit boc_node(const expression_ptr branch, const T const_var) 18415 | : c_(const_var) 18416 | { 18417 | construct_branch_pair(branch_, branch); 18418 | assert(valid()); 18419 | } 18420 | 18421 | inline T value() const exprtk_override 18422 | { 18423 | return Operation::process(branch_.first->value(),c_); 18424 | } 18425 | 18426 | inline operator_type operation() const exprtk_override 18427 | { 18428 | return Operation::operation(); 18429 | } 18430 | 18431 | inline const T c() const exprtk_override 18432 | { 18433 | return c_; 18434 | } 18435 | 18436 | inline void set_c(const T new_c) exprtk_override 18437 | { 18438 | (*const_cast<T*>(&c_)) = new_c; 18439 | } 18440 | 18441 | inline bool valid() const exprtk_override 18442 | { 18443 | return branch_.first && branch_.first->valid(); 18444 | } 18445 | 18446 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 18447 | { 18448 | return branch_.first; 18449 | } 18450 | 18451 | inline expression_node<T>* move_branch(const std::size_t&) exprtk_override 18452 | { 18453 | branch_.second = false; 18454 | return branch_.first; 18455 | } 18456 | 18457 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 18458 | { 18459 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 18460 | } 18461 | 18462 | std::size_t node_depth() const exprtk_override 18463 | { 18464 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 18465 | } 18466 | 18467 | private: 18468 | 18469 | boc_node(const boc_node<T,Operation>&) exprtk_delete; 18470 | boc_node<T,Operation>& operator=(const boc_node<T,Operation>&) exprtk_delete; 18471 | 18472 | const T c_; 18473 | branch_t branch_; 18474 | }; 18475 | 18476 | #ifndef exprtk_disable_string_capabilities 18477 | template <typename T, typename SType0, typename SType1, typename Operation> 18478 | class sos_node exprtk_final : public sos_base_node<T> 18479 | { 18480 | public: 18481 | 18482 | typedef expression_node<T>* expression_ptr; 18483 | typedef Operation operation_t; 18484 | 18485 | // string op string node 18486 | explicit sos_node(SType0 p0, SType1 p1) 18487 | : s0_(p0) 18488 | , s1_(p1) 18489 | {} 18490 | 18491 | inline T value() const exprtk_override 18492 | { 18493 | return Operation::process(s0_,s1_); 18494 | } 18495 | 18496 | inline typename expression_node<T>::node_type type() const exprtk_override 18497 | { 18498 | return Operation::type(); 18499 | } 18500 | 18501 | inline operator_type operation() const exprtk_override 18502 | { 18503 | return Operation::operation(); 18504 | } 18505 | 18506 | inline std::string& s0() 18507 | { 18508 | return s0_; 18509 | } 18510 | 18511 | inline std::string& s1() 18512 | { 18513 | return s1_; 18514 | } 18515 | 18516 | protected: 18517 | 18518 | SType0 s0_; 18519 | SType1 s1_; 18520 | 18521 | private: 18522 | 18523 | sos_node(const sos_node<T,SType0,SType1,Operation>&) exprtk_delete; 18524 | sos_node<T,SType0,SType1,Operation>& operator=(const sos_node<T,SType0,SType1,Operation>&) exprtk_delete; 18525 | }; 18526 | 18527 | template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation> 18528 | class str_xrox_node exprtk_final : public sos_base_node<T> 18529 | { 18530 | public: 18531 | 18532 | typedef expression_node<T>* expression_ptr; 18533 | typedef Operation operation_t; 18534 | typedef str_xrox_node<T,SType0,SType1,RangePack,Operation> node_type; 18535 | 18536 | // string-range op string node 18537 | explicit str_xrox_node(SType0 p0, SType1 p1, RangePack rp0) 18538 | : s0_ (p0 ) 18539 | , s1_ (p1 ) 18540 | , rp0_(rp0) 18541 | {} 18542 | 18543 | ~str_xrox_node() exprtk_override 18544 | { 18545 | rp0_.free(); 18546 | } 18547 | 18548 | inline T value() const exprtk_override 18549 | { 18550 | std::size_t r0 = 0; 18551 | std::size_t r1 = 0; 18552 | 18553 | if (rp0_(r0, r1, s0_.size())) 18554 | return Operation::process(s0_.substr(r0, (r1 - r0) + 1), s1_); 18555 | else 18556 | return T(0); 18557 | } 18558 | 18559 | inline typename expression_node<T>::node_type type() const exprtk_override 18560 | { 18561 | return Operation::type(); 18562 | } 18563 | 18564 | inline operator_type operation() const exprtk_override 18565 | { 18566 | return Operation::operation(); 18567 | } 18568 | 18569 | inline std::string& s0() 18570 | { 18571 | return s0_; 18572 | } 18573 | 18574 | inline std::string& s1() 18575 | { 18576 | return s1_; 18577 | } 18578 | 18579 | protected: 18580 | 18581 | SType0 s0_; 18582 | SType1 s1_; 18583 | RangePack rp0_; 18584 | 18585 | private: 18586 | 18587 | str_xrox_node(const node_type&) exprtk_delete; 18588 | node_type& operator=(const node_type&) exprtk_delete; 18589 | }; 18590 | 18591 | template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation> 18592 | class str_xoxr_node exprtk_final : public sos_base_node<T> 18593 | { 18594 | public: 18595 | 18596 | typedef expression_node<T>* expression_ptr; 18597 | typedef Operation operation_t; 18598 | typedef str_xoxr_node<T,SType0,SType1,RangePack,Operation> node_type; 18599 | 18600 | // string op string range node 18601 | explicit str_xoxr_node(SType0 p0, SType1 p1, RangePack rp1) 18602 | : s0_ (p0 ) 18603 | , s1_ (p1 ) 18604 | , rp1_(rp1) 18605 | {} 18606 | 18607 | ~str_xoxr_node() 18608 | { 18609 | rp1_.free(); 18610 | } 18611 | 18612 | inline T value() const exprtk_override 18613 | { 18614 | std::size_t r0 = 0; 18615 | std::size_t r1 = 0; 18616 | 18617 | if (rp1_(r0, r1, s1_.size())) 18618 | { 18619 | return Operation::process 18620 | ( 18621 | s0_, 18622 | s1_.substr(r0, (r1 - r0) + 1) 18623 | ); 18624 | } 18625 | else 18626 | return T(0); 18627 | } 18628 | 18629 | inline typename expression_node<T>::node_type type() const exprtk_override 18630 | { 18631 | return Operation::type(); 18632 | } 18633 | 18634 | inline operator_type operation() const exprtk_override 18635 | { 18636 | return Operation::operation(); 18637 | } 18638 | 18639 | inline std::string& s0() 18640 | { 18641 | return s0_; 18642 | } 18643 | 18644 | inline std::string& s1() 18645 | { 18646 | return s1_; 18647 | } 18648 | 18649 | protected: 18650 | 18651 | SType0 s0_; 18652 | SType1 s1_; 18653 | RangePack rp1_; 18654 | 18655 | private: 18656 | 18657 | str_xoxr_node(const node_type&) exprtk_delete; 18658 | node_type& operator=(const node_type&) exprtk_delete; 18659 | }; 18660 | 18661 | template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation> 18662 | class str_xroxr_node exprtk_final : public sos_base_node<T> 18663 | { 18664 | public: 18665 | 18666 | typedef expression_node<T>* expression_ptr; 18667 | typedef Operation operation_t; 18668 | typedef str_xroxr_node<T,SType0,SType1,RangePack,Operation> node_type; 18669 | 18670 | // string-range op string-range node 18671 | explicit str_xroxr_node(SType0 p0, SType1 p1, RangePack rp0, RangePack rp1) 18672 | : s0_ (p0 ) 18673 | , s1_ (p1 ) 18674 | , rp0_(rp0) 18675 | , rp1_(rp1) 18676 | {} 18677 | 18678 | ~str_xroxr_node() exprtk_override 18679 | { 18680 | rp0_.free(); 18681 | rp1_.free(); 18682 | } 18683 | 18684 | inline T value() const exprtk_override 18685 | { 18686 | std::size_t r0_0 = 0; 18687 | std::size_t r0_1 = 0; 18688 | std::size_t r1_0 = 0; 18689 | std::size_t r1_1 = 0; 18690 | 18691 | if ( 18692 | rp0_(r0_0, r1_0, s0_.size()) && 18693 | rp1_(r0_1, r1_1, s1_.size()) 18694 | ) 18695 | { 18696 | return Operation::process 18697 | ( 18698 | s0_.substr(r0_0, (r1_0 - r0_0) + 1), 18699 | s1_.substr(r0_1, (r1_1 - r0_1) + 1) 18700 | ); 18701 | } 18702 | else 18703 | return T(0); 18704 | } 18705 | 18706 | inline typename expression_node<T>::node_type type() const exprtk_override 18707 | { 18708 | return Operation::type(); 18709 | } 18710 | 18711 | inline operator_type operation() const exprtk_override 18712 | { 18713 | return Operation::operation(); 18714 | } 18715 | 18716 | inline std::string& s0() 18717 | { 18718 | return s0_; 18719 | } 18720 | 18721 | inline std::string& s1() 18722 | { 18723 | return s1_; 18724 | } 18725 | 18726 | protected: 18727 | 18728 | SType0 s0_; 18729 | SType1 s1_; 18730 | RangePack rp0_; 18731 | RangePack rp1_; 18732 | 18733 | private: 18734 | 18735 | str_xroxr_node(const node_type&) exprtk_delete; 18736 | node_type& operator=(const node_type&) exprtk_delete; 18737 | }; 18738 | 18739 | template <typename T, typename Operation> 18740 | class str_sogens_node exprtk_final : public binary_node<T> 18741 | { 18742 | public: 18743 | 18744 | typedef expression_node <T>* expression_ptr; 18745 | typedef string_base_node<T>* str_base_ptr; 18746 | typedef range_pack <T> range_t; 18747 | typedef range_t* range_ptr; 18748 | typedef range_interface <T> irange_t; 18749 | typedef irange_t* irange_ptr; 18750 | 18751 | using binary_node<T>::branch; 18752 | 18753 | str_sogens_node(const operator_type& opr, 18754 | expression_ptr branch0, 18755 | expression_ptr branch1) 18756 | : binary_node<T>(opr, branch0, branch1) 18757 | , str0_base_ptr_ (0) 18758 | , str1_base_ptr_ (0) 18759 | , str0_range_ptr_(0) 18760 | , str1_range_ptr_(0) 18761 | , initialised_ (false) 18762 | { 18763 | if (is_generally_string_node(branch(0))) 18764 | { 18765 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0)); 18766 | 18767 | if (0 == str0_base_ptr_) 18768 | return; 18769 | 18770 | irange_ptr range = dynamic_cast<irange_ptr>(branch(0)); 18771 | 18772 | if (0 == range) 18773 | return; 18774 | 18775 | str0_range_ptr_ = &(range->range_ref()); 18776 | } 18777 | 18778 | if (is_generally_string_node(branch(1))) 18779 | { 18780 | str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1)); 18781 | 18782 | if (0 == str1_base_ptr_) 18783 | return; 18784 | 18785 | irange_ptr range = dynamic_cast<irange_ptr>(branch(1)); 18786 | 18787 | if (0 == range) 18788 | return; 18789 | 18790 | str1_range_ptr_ = &(range->range_ref()); 18791 | } 18792 | 18793 | initialised_ = 18794 | str0_base_ptr_ && 18795 | str1_base_ptr_ && 18796 | str0_range_ptr_ && 18797 | str1_range_ptr_; 18798 | 18799 | assert(valid()); 18800 | } 18801 | 18802 | inline T value() const exprtk_override 18803 | { 18804 | branch(0)->value(); 18805 | branch(1)->value(); 18806 | 18807 | std::size_t str0_r0 = 0; 18808 | std::size_t str0_r1 = 0; 18809 | 18810 | std::size_t str1_r0 = 0; 18811 | std::size_t str1_r1 = 0; 18812 | 18813 | const range_t& range0 = (*str0_range_ptr_); 18814 | const range_t& range1 = (*str1_range_ptr_); 18815 | 18816 | if ( 18817 | range0(str0_r0, str0_r1, str0_base_ptr_->size()) && 18818 | range1(str1_r0, str1_r1, str1_base_ptr_->size()) 18819 | ) 18820 | { 18821 | return Operation::process 18822 | ( 18823 | str0_base_ptr_->str().substr(str0_r0,(str0_r1 - str0_r0)), 18824 | str1_base_ptr_->str().substr(str1_r0,(str1_r1 - str1_r0)) 18825 | ); 18826 | } 18827 | 18828 | return std::numeric_limits<T>::quiet_NaN(); 18829 | } 18830 | 18831 | inline typename expression_node<T>::node_type type() const exprtk_override 18832 | { 18833 | return Operation::type(); 18834 | } 18835 | 18836 | inline bool valid() const exprtk_override 18837 | { 18838 | return initialised_; 18839 | } 18840 | 18841 | private: 18842 | 18843 | str_sogens_node(const str_sogens_node<T,Operation>&) exprtk_delete; 18844 | str_sogens_node<T,Operation>& operator=(const str_sogens_node<T,Operation>&) exprtk_delete; 18845 | 18846 | str_base_ptr str0_base_ptr_; 18847 | str_base_ptr str1_base_ptr_; 18848 | range_ptr str0_range_ptr_; 18849 | range_ptr str1_range_ptr_; 18850 | bool initialised_; 18851 | }; 18852 | 18853 | template <typename T, typename SType0, typename SType1, typename SType2, typename Operation> 18854 | class sosos_node exprtk_final : public sosos_base_node<T> 18855 | { 18856 | public: 18857 | 18858 | typedef expression_node<T>* expression_ptr; 18859 | typedef Operation operation_t; 18860 | typedef sosos_node<T, SType0, SType1, SType2, Operation> node_type; 18861 | 18862 | // string op string op string node 18863 | explicit sosos_node(SType0 p0, SType1 p1, SType2 p2) 18864 | : s0_(p0) 18865 | , s1_(p1) 18866 | , s2_(p2) 18867 | {} 18868 | 18869 | inline T value() const exprtk_override 18870 | { 18871 | return Operation::process(s0_, s1_, s2_); 18872 | } 18873 | 18874 | inline typename expression_node<T>::node_type type() const exprtk_override 18875 | { 18876 | return Operation::type(); 18877 | } 18878 | 18879 | inline operator_type operation() const exprtk_override 18880 | { 18881 | return Operation::operation(); 18882 | } 18883 | 18884 | inline std::string& s0() 18885 | { 18886 | return s0_; 18887 | } 18888 | 18889 | inline std::string& s1() 18890 | { 18891 | return s1_; 18892 | } 18893 | 18894 | inline std::string& s2() 18895 | { 18896 | return s2_; 18897 | } 18898 | 18899 | protected: 18900 | 18901 | SType0 s0_; 18902 | SType1 s1_; 18903 | SType2 s2_; 18904 | 18905 | private: 18906 | 18907 | sosos_node(const node_type&) exprtk_delete; 18908 | node_type& operator=(const node_type&) exprtk_delete; 18909 | }; 18910 | #endif 18911 | 18912 | template <typename T, typename PowOp> 18913 | class ipow_node exprtk_final: public expression_node<T> 18914 | { 18915 | public: 18916 | 18917 | typedef expression_node<T>* expression_ptr; 18918 | typedef PowOp operation_t; 18919 | 18920 | explicit ipow_node(const T& v) 18921 | : v_(v) 18922 | {} 18923 | 18924 | inline T value() const exprtk_override 18925 | { 18926 | return PowOp::result(v_); 18927 | } 18928 | 18929 | inline typename expression_node<T>::node_type type() const exprtk_override 18930 | { 18931 | return expression_node<T>::e_ipow; 18932 | } 18933 | 18934 | private: 18935 | 18936 | ipow_node(const ipow_node<T,PowOp>&) exprtk_delete; 18937 | ipow_node<T,PowOp>& operator=(const ipow_node<T,PowOp>&) exprtk_delete; 18938 | 18939 | const T& v_; 18940 | }; 18941 | 18942 | template <typename T, typename PowOp> 18943 | class bipow_node exprtk_final : public expression_node<T> 18944 | { 18945 | public: 18946 | 18947 | typedef expression_node<T>* expression_ptr; 18948 | typedef std::pair<expression_ptr, bool> branch_t; 18949 | typedef PowOp operation_t; 18950 | 18951 | explicit bipow_node(expression_ptr branch) 18952 | { 18953 | construct_branch_pair(branch_, branch); 18954 | assert(valid()); 18955 | } 18956 | 18957 | inline T value() const exprtk_override 18958 | { 18959 | return PowOp::result(branch_.first->value()); 18960 | } 18961 | 18962 | inline typename expression_node<T>::node_type type() const exprtk_override 18963 | { 18964 | return expression_node<T>::e_ipow; 18965 | } 18966 | 18967 | inline bool valid() const exprtk_override 18968 | { 18969 | return branch_.first && branch_.first->valid(); 18970 | } 18971 | 18972 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 18973 | { 18974 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 18975 | } 18976 | 18977 | std::size_t node_depth() const exprtk_override 18978 | { 18979 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 18980 | } 18981 | 18982 | private: 18983 | 18984 | bipow_node(const bipow_node<T,PowOp>&) exprtk_delete; 18985 | bipow_node<T,PowOp>& operator=(const bipow_node<T,PowOp>&) exprtk_delete; 18986 | 18987 | branch_t branch_; 18988 | }; 18989 | 18990 | template <typename T, typename PowOp> 18991 | class ipowinv_node exprtk_final : public expression_node<T> 18992 | { 18993 | public: 18994 | 18995 | typedef expression_node<T>* expression_ptr; 18996 | typedef PowOp operation_t; 18997 | 18998 | explicit ipowinv_node(const T& v) 18999 | : v_(v) 19000 | {} 19001 | 19002 | inline T value() const exprtk_override 19003 | { 19004 | return (T(1) / PowOp::result(v_)); 19005 | } 19006 | 19007 | inline typename expression_node<T>::node_type type() const exprtk_override 19008 | { 19009 | return expression_node<T>::e_ipowinv; 19010 | } 19011 | 19012 | private: 19013 | 19014 | ipowinv_node(const ipowinv_node<T,PowOp>&) exprtk_delete; 19015 | ipowinv_node<T,PowOp>& operator=(const ipowinv_node<T,PowOp>&) exprtk_delete; 19016 | 19017 | const T& v_; 19018 | }; 19019 | 19020 | template <typename T, typename PowOp> 19021 | class bipowinv_node exprtk_final : public expression_node<T> 19022 | { 19023 | public: 19024 | 19025 | typedef expression_node<T>* expression_ptr; 19026 | typedef std::pair<expression_ptr, bool> branch_t; 19027 | typedef PowOp operation_t; 19028 | 19029 | explicit bipowinv_node(expression_ptr branch) 19030 | { 19031 | construct_branch_pair(branch_, branch); 19032 | assert(valid()); 19033 | } 19034 | 19035 | inline T value() const exprtk_override 19036 | { 19037 | return (T(1) / PowOp::result(branch_.first->value())); 19038 | } 19039 | 19040 | inline typename expression_node<T>::node_type type() const exprtk_override 19041 | { 19042 | return expression_node<T>::e_ipowinv; 19043 | } 19044 | 19045 | inline bool valid() const exprtk_override 19046 | { 19047 | return branch_.first && branch_.first->valid(); 19048 | } 19049 | 19050 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 19051 | { 19052 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 19053 | } 19054 | 19055 | std::size_t node_depth() const exprtk_override 19056 | { 19057 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 19058 | } 19059 | 19060 | private: 19061 | 19062 | bipowinv_node(const bipowinv_node<T,PowOp>&) exprtk_delete; 19063 | bipowinv_node<T,PowOp>& operator=(const bipowinv_node<T,PowOp>&) exprtk_delete; 19064 | 19065 | branch_t branch_; 19066 | }; 19067 | 19068 | template <typename T> 19069 | inline bool is_vov_node(const expression_node<T>* node) 19070 | { 19071 | return (0 != dynamic_cast<const vov_base_node<T>*>(node)); 19072 | } 19073 | 19074 | template <typename T> 19075 | inline bool is_cov_node(const expression_node<T>* node) 19076 | { 19077 | return (0 != dynamic_cast<const cov_base_node<T>*>(node)); 19078 | } 19079 | 19080 | template <typename T> 19081 | inline bool is_voc_node(const expression_node<T>* node) 19082 | { 19083 | return (0 != dynamic_cast<const voc_base_node<T>*>(node)); 19084 | } 19085 | 19086 | template <typename T> 19087 | inline bool is_cob_node(const expression_node<T>* node) 19088 | { 19089 | return (0 != dynamic_cast<const cob_base_node<T>*>(node)); 19090 | } 19091 | 19092 | template <typename T> 19093 | inline bool is_boc_node(const expression_node<T>* node) 19094 | { 19095 | return (0 != dynamic_cast<const boc_base_node<T>*>(node)); 19096 | } 19097 | 19098 | template <typename T> 19099 | inline bool is_t0ot1ot2_node(const expression_node<T>* node) 19100 | { 19101 | return (0 != dynamic_cast<const T0oT1oT2_base_node<T>*>(node)); 19102 | } 19103 | 19104 | template <typename T> 19105 | inline bool is_t0ot1ot2ot3_node(const expression_node<T>* node) 19106 | { 19107 | return (0 != dynamic_cast<const T0oT1oT2oT3_base_node<T>*>(node)); 19108 | } 19109 | 19110 | template <typename T> 19111 | inline bool is_uv_node(const expression_node<T>* node) 19112 | { 19113 | return (0 != dynamic_cast<const uv_base_node<T>*>(node)); 19114 | } 19115 | 19116 | template <typename T> 19117 | inline bool is_string_node(const expression_node<T>* node) 19118 | { 19119 | return node && (expression_node<T>::e_stringvar == node->type()); 19120 | } 19121 | 19122 | template <typename T> 19123 | inline bool is_string_range_node(const expression_node<T>* node) 19124 | { 19125 | return node && (expression_node<T>::e_stringvarrng == node->type()); 19126 | } 19127 | 19128 | template <typename T> 19129 | inline bool is_const_string_node(const expression_node<T>* node) 19130 | { 19131 | return node && (expression_node<T>::e_stringconst == node->type()); 19132 | } 19133 | 19134 | template <typename T> 19135 | inline bool is_const_string_range_node(const expression_node<T>* node) 19136 | { 19137 | return node && (expression_node<T>::e_cstringvarrng == node->type()); 19138 | } 19139 | 19140 | template <typename T> 19141 | inline bool is_string_assignment_node(const expression_node<T>* node) 19142 | { 19143 | return node && (expression_node<T>::e_strass == node->type()); 19144 | } 19145 | 19146 | template <typename T> 19147 | inline bool is_string_concat_node(const expression_node<T>* node) 19148 | { 19149 | return node && (expression_node<T>::e_strconcat == node->type()); 19150 | } 19151 | 19152 | template <typename T> 19153 | inline bool is_string_function_node(const expression_node<T>* node) 19154 | { 19155 | return node && (expression_node<T>::e_strfunction == node->type()); 19156 | } 19157 | 19158 | template <typename T> 19159 | inline bool is_string_condition_node(const expression_node<T>* node) 19160 | { 19161 | return node && (expression_node<T>::e_strcondition == node->type()); 19162 | } 19163 | 19164 | template <typename T> 19165 | inline bool is_string_ccondition_node(const expression_node<T>* node) 19166 | { 19167 | return node && (expression_node<T>::e_strccondition == node->type()); 19168 | } 19169 | 19170 | template <typename T> 19171 | inline bool is_string_vararg_node(const expression_node<T>* node) 19172 | { 19173 | return node && (expression_node<T>::e_stringvararg == node->type()); 19174 | } 19175 | 19176 | template <typename T> 19177 | inline bool is_genricstring_range_node(const expression_node<T>* node) 19178 | { 19179 | return node && (expression_node<T>::e_strgenrange == node->type()); 19180 | } 19181 | 19182 | template <typename T> 19183 | inline bool is_generally_string_node(const expression_node<T>* node) 19184 | { 19185 | if (node) 19186 | { 19187 | switch (node->type()) 19188 | { 19189 | case expression_node<T>::e_stringvar : 19190 | case expression_node<T>::e_stringconst : 19191 | case expression_node<T>::e_stringvarrng : 19192 | case expression_node<T>::e_cstringvarrng : 19193 | case expression_node<T>::e_strgenrange : 19194 | case expression_node<T>::e_strass : 19195 | case expression_node<T>::e_strconcat : 19196 | case expression_node<T>::e_strfunction : 19197 | case expression_node<T>::e_strcondition : 19198 | case expression_node<T>::e_strccondition : 19199 | case expression_node<T>::e_stringvararg : return true; 19200 | default : return false; 19201 | } 19202 | } 19203 | 19204 | return false; 19205 | } 19206 | 19207 | template <typename T> 19208 | inline bool is_loop_node(const expression_node<T>* node) 19209 | { 19210 | if (node) 19211 | { 19212 | switch (node->type()) 19213 | { 19214 | case expression_node<T>::e_for : 19215 | case expression_node<T>::e_repeat : 19216 | case expression_node<T>::e_while : return true; 19217 | default : return false; 19218 | } 19219 | } 19220 | 19221 | return false; 19222 | } 19223 | 19224 | template <typename T> 19225 | inline bool is_block_node(const expression_node<T>* node) 19226 | { 19227 | if (node) 19228 | { 19229 | if (is_loop_node(node)) 19230 | { 19231 | return true; 19232 | } 19233 | 19234 | switch (node->type()) 19235 | { 19236 | case expression_node<T>::e_conditional : 19237 | case expression_node<T>::e_mswitch : 19238 | case expression_node<T>::e_switch : 19239 | case expression_node<T>::e_vararg : return true; 19240 | default : return false; 19241 | } 19242 | } 19243 | 19244 | return false; 19245 | } 19246 | 19247 | class node_allocator 19248 | { 19249 | public: 19250 | 19251 | template <typename ResultNode, typename OpType, typename ExprNode> 19252 | inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[1]) 19253 | { 19254 | expression_node<typename ResultNode::value_type>* result = 19255 | allocate<ResultNode>(operation, branch[0]); 19256 | result->node_depth(); 19257 | return result; 19258 | } 19259 | 19260 | template <typename ResultNode, typename OpType, typename ExprNode> 19261 | inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[2]) 19262 | { 19263 | expression_node<typename ResultNode::value_type>* result = 19264 | allocate<ResultNode>(operation, branch[0], branch[1]); 19265 | result->node_depth(); 19266 | return result; 19267 | } 19268 | 19269 | template <typename ResultNode, typename OpType, typename ExprNode> 19270 | inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[3]) 19271 | { 19272 | expression_node<typename ResultNode::value_type>* result = 19273 | allocate<ResultNode>(operation, branch[0], branch[1], branch[2]); 19274 | result->node_depth(); 19275 | return result; 19276 | } 19277 | 19278 | template <typename ResultNode, typename OpType, typename ExprNode> 19279 | inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[4]) 19280 | { 19281 | expression_node<typename ResultNode::value_type>* result = 19282 | allocate<ResultNode>(operation, branch[0], branch[1], branch[2], branch[3]); 19283 | result->node_depth(); 19284 | return result; 19285 | } 19286 | 19287 | template <typename ResultNode, typename OpType, typename ExprNode> 19288 | inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[5]) 19289 | { 19290 | expression_node<typename ResultNode::value_type>* result = 19291 | allocate<ResultNode>(operation, branch[0],branch[1], branch[2], branch[3], branch[4]); 19292 | result->node_depth(); 19293 | return result; 19294 | } 19295 | 19296 | template <typename ResultNode, typename OpType, typename ExprNode> 19297 | inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[6]) 19298 | { 19299 | expression_node<typename ResultNode::value_type>* result = 19300 | allocate<ResultNode>(operation, branch[0], branch[1], branch[2], branch[3], branch[4], branch[5]); 19301 | result->node_depth(); 19302 | return result; 19303 | } 19304 | 19305 | template <typename node_type> 19306 | inline expression_node<typename node_type::value_type>* allocate() const 19307 | { 19308 | return (new node_type()); 19309 | } 19310 | 19311 | template <typename node_type, 19312 | typename Type, 19313 | typename Allocator, 19314 | template <typename, typename> class Sequence> 19315 | inline expression_node<typename node_type::value_type>* allocate(const Sequence<Type,Allocator>& seq) const 19316 | { 19317 | expression_node<typename node_type::value_type>* 19318 | result = (new node_type(seq)); 19319 | result->node_depth(); 19320 | return result; 19321 | } 19322 | 19323 | template <typename node_type, typename T1> 19324 | inline expression_node<typename node_type::value_type>* allocate(T1& t1) const 19325 | { 19326 | expression_node<typename node_type::value_type>* 19327 | result = (new node_type(t1)); 19328 | result->node_depth(); 19329 | return result; 19330 | } 19331 | 19332 | template <typename node_type, typename T1> 19333 | inline expression_node<typename node_type::value_type>* allocate_c(const T1& t1) const 19334 | { 19335 | expression_node<typename node_type::value_type>* 19336 | result = (new node_type(t1)); 19337 | result->node_depth(); 19338 | return result; 19339 | } 19340 | 19341 | template <typename node_type, 19342 | typename T1, typename T2> 19343 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2) const 19344 | { 19345 | expression_node<typename node_type::value_type>* 19346 | result = (new node_type(t1, t2)); 19347 | result->node_depth(); 19348 | return result; 19349 | } 19350 | 19351 | template <typename node_type, 19352 | typename T1, typename T2> 19353 | inline expression_node<typename node_type::value_type>* allocate_cr(const T1& t1, T2& t2) const 19354 | { 19355 | expression_node<typename node_type::value_type>* 19356 | result = (new node_type(t1, t2)); 19357 | result->node_depth(); 19358 | return result; 19359 | } 19360 | 19361 | template <typename node_type, 19362 | typename T1, typename T2> 19363 | inline expression_node<typename node_type::value_type>* allocate_rc(T1& t1, const T2& t2) const 19364 | { 19365 | expression_node<typename node_type::value_type>* 19366 | result = (new node_type(t1, t2)); 19367 | result->node_depth(); 19368 | return result; 19369 | } 19370 | 19371 | template <typename node_type, 19372 | typename T1, typename T2> 19373 | inline expression_node<typename node_type::value_type>* allocate_rr(T1& t1, T2& t2) const 19374 | { 19375 | expression_node<typename node_type::value_type>* 19376 | result = (new node_type(t1, t2)); 19377 | result->node_depth(); 19378 | return result; 19379 | } 19380 | 19381 | template <typename node_type, 19382 | typename T1, typename T2> 19383 | inline expression_node<typename node_type::value_type>* allocate_tt(T1 t1, T2 t2) const 19384 | { 19385 | expression_node<typename node_type::value_type>* 19386 | result = (new node_type(t1, t2)); 19387 | result->node_depth(); 19388 | return result; 19389 | } 19390 | 19391 | template <typename node_type, 19392 | typename T1, typename T2, typename T3> 19393 | inline expression_node<typename node_type::value_type>* allocate_ttt(T1 t1, T2 t2, T3 t3) const 19394 | { 19395 | expression_node<typename node_type::value_type>* 19396 | result = (new node_type(t1, t2, t3)); 19397 | result->node_depth(); 19398 | return result; 19399 | } 19400 | 19401 | template <typename node_type, 19402 | typename T1, typename T2, typename T3, typename T4> 19403 | inline expression_node<typename node_type::value_type>* allocate_tttt(T1 t1, T2 t2, T3 t3, T4 t4) const 19404 | { 19405 | expression_node<typename node_type::value_type>* 19406 | result = (new node_type(t1, t2, t3, t4)); 19407 | result->node_depth(); 19408 | return result; 19409 | } 19410 | 19411 | template <typename node_type, 19412 | typename T1, typename T2, typename T3> 19413 | inline expression_node<typename node_type::value_type>* allocate_rrr(T1& t1, T2& t2, T3& t3) const 19414 | { 19415 | expression_node<typename node_type::value_type>* 19416 | result = (new node_type(t1, t2, t3)); 19417 | result->node_depth(); 19418 | return result; 19419 | } 19420 | 19421 | template <typename node_type, 19422 | typename T1, typename T2, typename T3, typename T4> 19423 | inline expression_node<typename node_type::value_type>* allocate_rrrr(T1& t1, T2& t2, T3& t3, T4& t4) const 19424 | { 19425 | expression_node<typename node_type::value_type>* 19426 | result = (new node_type(t1, t2, t3, t4)); 19427 | result->node_depth(); 19428 | return result; 19429 | } 19430 | 19431 | template <typename node_type, 19432 | typename T1, typename T2, typename T3, typename T4, typename T5> 19433 | inline expression_node<typename node_type::value_type>* allocate_rrrrr(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5) const 19434 | { 19435 | expression_node<typename node_type::value_type>* 19436 | result = (new node_type(t1, t2, t3, t4, t5)); 19437 | result->node_depth(); 19438 | return result; 19439 | } 19440 | 19441 | template <typename node_type, 19442 | typename T1, typename T2, typename T3> 19443 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19444 | const T3& t3) const 19445 | { 19446 | expression_node<typename node_type::value_type>* 19447 | result = (new node_type(t1, t2, t3)); 19448 | result->node_depth(); 19449 | return result; 19450 | } 19451 | 19452 | template <typename node_type, 19453 | typename T1, typename T2, 19454 | typename T3, typename T4> 19455 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19456 | const T3& t3, const T4& t4) const 19457 | { 19458 | expression_node<typename node_type::value_type>* 19459 | result = (new node_type(t1, t2, t3, t4)); 19460 | result->node_depth(); 19461 | return result; 19462 | } 19463 | 19464 | template <typename node_type, 19465 | typename T1, typename T2, 19466 | typename T3, typename T4, typename T5> 19467 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19468 | const T3& t3, const T4& t4, 19469 | const T5& t5) const 19470 | { 19471 | expression_node<typename node_type::value_type>* 19472 | result = (new node_type(t1, t2, t3, t4, t5)); 19473 | result->node_depth(); 19474 | return result; 19475 | } 19476 | 19477 | template <typename node_type, 19478 | typename T1, typename T2, 19479 | typename T3, typename T4, typename T5, typename T6> 19480 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19481 | const T3& t3, const T4& t4, 19482 | const T5& t5, const T6& t6) const 19483 | { 19484 | expression_node<typename node_type::value_type>* 19485 | result = (new node_type(t1, t2, t3, t4, t5, t6)); 19486 | result->node_depth(); 19487 | return result; 19488 | } 19489 | 19490 | template <typename node_type, 19491 | typename T1, typename T2, 19492 | typename T3, typename T4, 19493 | typename T5, typename T6, typename T7> 19494 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19495 | const T3& t3, const T4& t4, 19496 | const T5& t5, const T6& t6, 19497 | const T7& t7) const 19498 | { 19499 | expression_node<typename node_type::value_type>* 19500 | result = (new node_type(t1, t2, t3, t4, t5, t6, t7)); 19501 | result->node_depth(); 19502 | return result; 19503 | } 19504 | 19505 | template <typename node_type, 19506 | typename T1, typename T2, 19507 | typename T3, typename T4, 19508 | typename T5, typename T6, 19509 | typename T7, typename T8> 19510 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19511 | const T3& t3, const T4& t4, 19512 | const T5& t5, const T6& t6, 19513 | const T7& t7, const T8& t8) const 19514 | { 19515 | expression_node<typename node_type::value_type>* 19516 | result = (new node_type(t1, t2, t3, t4, t5, t6, t7, t8)); 19517 | result->node_depth(); 19518 | return result; 19519 | } 19520 | 19521 | template <typename node_type, 19522 | typename T1, typename T2, 19523 | typename T3, typename T4, 19524 | typename T5, typename T6, 19525 | typename T7, typename T8, typename T9> 19526 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19527 | const T3& t3, const T4& t4, 19528 | const T5& t5, const T6& t6, 19529 | const T7& t7, const T8& t8, 19530 | const T9& t9) const 19531 | { 19532 | expression_node<typename node_type::value_type>* 19533 | result = (new node_type(t1, t2, t3, t4, t5, t6, t7, t8, t9)); 19534 | result->node_depth(); 19535 | return result; 19536 | } 19537 | 19538 | template <typename node_type, 19539 | typename T1, typename T2, 19540 | typename T3, typename T4, 19541 | typename T5, typename T6, 19542 | typename T7, typename T8, 19543 | typename T9, typename T10> 19544 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19545 | const T3& t3, const T4& t4, 19546 | const T5& t5, const T6& t6, 19547 | const T7& t7, const T8& t8, 19548 | const T9& t9, const T10& t10) const 19549 | { 19550 | expression_node<typename node_type::value_type>* 19551 | result = (new node_type(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10)); 19552 | result->node_depth(); 19553 | return result; 19554 | } 19555 | 19556 | template <typename node_type, 19557 | typename T1, typename T2, typename T3> 19558 | inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, T3 t3) const 19559 | { 19560 | expression_node<typename node_type::value_type>* 19561 | result = (new node_type(t1, t2, t3)); 19562 | result->node_depth(); 19563 | return result; 19564 | } 19565 | 19566 | template <typename node_type, 19567 | typename T1, typename T2, 19568 | typename T3, typename T4> 19569 | inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, 19570 | T3 t3, T4 t4) const 19571 | { 19572 | expression_node<typename node_type::value_type>* 19573 | result = (new node_type(t1, t2, t3, t4)); 19574 | result->node_depth(); 19575 | return result; 19576 | } 19577 | 19578 | template <typename node_type, 19579 | typename T1, typename T2, 19580 | typename T3, typename T4, 19581 | typename T5> 19582 | inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, 19583 | T3 t3, T4 t4, 19584 | T5 t5) const 19585 | { 19586 | expression_node<typename node_type::value_type>* 19587 | result = (new node_type(t1, t2, t3, t4, t5)); 19588 | result->node_depth(); 19589 | return result; 19590 | } 19591 | 19592 | template <typename node_type, 19593 | typename T1, typename T2, 19594 | typename T3, typename T4, 19595 | typename T5, typename T6> 19596 | inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, 19597 | T3 t3, T4 t4, 19598 | T5 t5, T6 t6) const 19599 | { 19600 | expression_node<typename node_type::value_type>* 19601 | result = (new node_type(t1, t2, t3, t4, t5, t6)); 19602 | result->node_depth(); 19603 | return result; 19604 | } 19605 | 19606 | template <typename node_type, 19607 | typename T1, typename T2, 19608 | typename T3, typename T4, 19609 | typename T5, typename T6, typename T7> 19610 | inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, 19611 | T3 t3, T4 t4, 19612 | T5 t5, T6 t6, 19613 | T7 t7) const 19614 | { 19615 | expression_node<typename node_type::value_type>* 19616 | result = (new node_type(t1, t2, t3, t4, t5, t6, t7)); 19617 | result->node_depth(); 19618 | return result; 19619 | } 19620 | 19621 | template <typename T> 19622 | void inline free(expression_node<T>*& e) const 19623 | { 19624 | exprtk_debug(("node_allocator::free() - deleting expression_node " 19625 | "type: %03d addr: %p\n", 19626 | static_cast<int>(e->type()), 19627 | reinterpret_cast<void*>(e))); 19628 | delete e; 19629 | e = 0; 19630 | } 19631 | }; 19632 | 19633 | inline void load_operations_map(std::multimap<std::string,details::base_operation_t,details::ilesscompare>& m) 19634 | { 19635 | #define register_op(Symbol, Type, Args) \ 19636 | m.insert(std::make_pair(std::string(Symbol),details::base_operation_t(Type,Args))); \ 19637 | 19638 | register_op("abs" , e_abs , 1) 19639 | register_op("acos" , e_acos , 1) 19640 | register_op("acosh" , e_acosh , 1) 19641 | register_op("asin" , e_asin , 1) 19642 | register_op("asinh" , e_asinh , 1) 19643 | register_op("atan" , e_atan , 1) 19644 | register_op("atanh" , e_atanh , 1) 19645 | register_op("ceil" , e_ceil , 1) 19646 | register_op("cos" , e_cos , 1) 19647 | register_op("cosh" , e_cosh , 1) 19648 | register_op("exp" , e_exp , 1) 19649 | register_op("expm1" , e_expm1 , 1) 19650 | register_op("floor" , e_floor , 1) 19651 | register_op("log" , e_log , 1) 19652 | register_op("log10" , e_log10 , 1) 19653 | register_op("log2" , e_log2 , 1) 19654 | register_op("log1p" , e_log1p , 1) 19655 | register_op("round" , e_round , 1) 19656 | register_op("sin" , e_sin , 1) 19657 | register_op("sinc" , e_sinc , 1) 19658 | register_op("sinh" , e_sinh , 1) 19659 | register_op("sec" , e_sec , 1) 19660 | register_op("csc" , e_csc , 1) 19661 | register_op("sqrt" , e_sqrt , 1) 19662 | register_op("tan" , e_tan , 1) 19663 | register_op("tanh" , e_tanh , 1) 19664 | register_op("cot" , e_cot , 1) 19665 | register_op("rad2deg" , e_r2d , 1) 19666 | register_op("deg2rad" , e_d2r , 1) 19667 | register_op("deg2grad" , e_d2g , 1) 19668 | register_op("grad2deg" , e_g2d , 1) 19669 | register_op("sgn" , e_sgn , 1) 19670 | register_op("not" , e_notl , 1) 19671 | register_op("erf" , e_erf , 1) 19672 | register_op("erfc" , e_erfc , 1) 19673 | register_op("ncdf" , e_ncdf , 1) 19674 | register_op("frac" , e_frac , 1) 19675 | register_op("trunc" , e_trunc , 1) 19676 | register_op("atan2" , e_atan2 , 2) 19677 | register_op("mod" , e_mod , 2) 19678 | register_op("logn" , e_logn , 2) 19679 | register_op("pow" , e_pow , 2) 19680 | register_op("root" , e_root , 2) 19681 | register_op("roundn" , e_roundn , 2) 19682 | register_op("equal" , e_equal , 2) 19683 | register_op("not_equal" , e_nequal , 2) 19684 | register_op("hypot" , e_hypot , 2) 19685 | register_op("shr" , e_shr , 2) 19686 | register_op("shl" , e_shl , 2) 19687 | register_op("clamp" , e_clamp , 3) 19688 | register_op("iclamp" , e_iclamp , 3) 19689 | register_op("inrange" , e_inrange , 3) 19690 | #undef register_op 19691 | } 19692 | 19693 | } // namespace details 19694 | 19695 | class function_traits 19696 | { 19697 | public: 19698 | 19699 | function_traits() 19700 | : allow_zero_parameters_(false) 19701 | , has_side_effects_(true) 19702 | , min_num_args_(0) 19703 | , max_num_args_(std::numeric_limits<std::size_t>::max()) 19704 | {} 19705 | 19706 | inline bool& allow_zero_parameters() 19707 | { 19708 | return allow_zero_parameters_; 19709 | } 19710 | 19711 | inline bool& has_side_effects() 19712 | { 19713 | return has_side_effects_; 19714 | } 19715 | 19716 | std::size_t& min_num_args() 19717 | { 19718 | return min_num_args_; 19719 | } 19720 | 19721 | std::size_t& max_num_args() 19722 | { 19723 | return max_num_args_; 19724 | } 19725 | 19726 | private: 19727 | 19728 | bool allow_zero_parameters_; 19729 | bool has_side_effects_; 19730 | std::size_t min_num_args_; 19731 | std::size_t max_num_args_; 19732 | }; 19733 | 19734 | template <typename FunctionType> 19735 | void enable_zero_parameters(FunctionType& func) 19736 | { 19737 | func.allow_zero_parameters() = true; 19738 | 19739 | if (0 != func.min_num_args()) 19740 | { 19741 | func.min_num_args() = 0; 19742 | } 19743 | } 19744 | 19745 | template <typename FunctionType> 19746 | void disable_zero_parameters(FunctionType& func) 19747 | { 19748 | func.allow_zero_parameters() = false; 19749 | } 19750 | 19751 | template <typename FunctionType> 19752 | void enable_has_side_effects(FunctionType& func) 19753 | { 19754 | func.has_side_effects() = true; 19755 | } 19756 | 19757 | template <typename FunctionType> 19758 | void disable_has_side_effects(FunctionType& func) 19759 | { 19760 | func.has_side_effects() = false; 19761 | } 19762 | 19763 | template <typename FunctionType> 19764 | void set_min_num_args(FunctionType& func, const std::size_t& num_args) 19765 | { 19766 | func.min_num_args() = num_args; 19767 | 19768 | if ((0 != func.min_num_args()) && func.allow_zero_parameters()) 19769 | func.allow_zero_parameters() = false; 19770 | } 19771 | 19772 | template <typename FunctionType> 19773 | void set_max_num_args(FunctionType& func, const std::size_t& num_args) 19774 | { 19775 | func.max_num_args() = num_args; 19776 | } 19777 | 19778 | template <typename T> 19779 | class ifunction : public function_traits 19780 | { 19781 | public: 19782 | 19783 | explicit ifunction(const std::size_t& pc) 19784 | : param_count(pc) 19785 | {} 19786 | 19787 | virtual ~ifunction() 19788 | {} 19789 | 19790 | #define empty_method_body(N) \ 19791 | { \ 19792 | exprtk_debug(("ifunction::operator() - Operator(" #N ") has not been overridden\n")); \ 19793 | return std::numeric_limits<T>::quiet_NaN(); \ 19794 | } \ 19795 | 19796 | inline virtual T operator() () 19797 | empty_method_body(0) 19798 | 19799 | inline virtual T operator() (const T&) 19800 | empty_method_body(1) 19801 | 19802 | inline virtual T operator() (const T&,const T&) 19803 | empty_method_body(2) 19804 | 19805 | inline virtual T operator() (const T&, const T&, const T&) 19806 | empty_method_body(3) 19807 | 19808 | inline virtual T operator() (const T&, const T&, const T&, const T&) 19809 | empty_method_body(4) 19810 | 19811 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&) 19812 | empty_method_body(5) 19813 | 19814 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&) 19815 | empty_method_body(6) 19816 | 19817 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19818 | empty_method_body(7) 19819 | 19820 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19821 | empty_method_body(8) 19822 | 19823 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19824 | empty_method_body(9) 19825 | 19826 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19827 | empty_method_body(10) 19828 | 19829 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19830 | const T&) 19831 | empty_method_body(11) 19832 | 19833 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19834 | const T&, const T&) 19835 | empty_method_body(12) 19836 | 19837 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19838 | const T&, const T&, const T&) 19839 | empty_method_body(13) 19840 | 19841 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19842 | const T&, const T&, const T&, const T&) 19843 | empty_method_body(14) 19844 | 19845 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19846 | const T&, const T&, const T&, const T&, const T&) 19847 | empty_method_body(15) 19848 | 19849 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19850 | const T&, const T&, const T&, const T&, const T&, const T&) 19851 | empty_method_body(16) 19852 | 19853 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19854 | const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19855 | empty_method_body(17) 19856 | 19857 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19858 | const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19859 | empty_method_body(18) 19860 | 19861 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19862 | const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19863 | empty_method_body(19) 19864 | 19865 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19866 | const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19867 | empty_method_body(20) 19868 | 19869 | #undef empty_method_body 19870 | 19871 | std::size_t param_count; 19872 | }; 19873 | 19874 | template <typename T> 19875 | class ivararg_function : public function_traits 19876 | { 19877 | public: 19878 | 19879 | virtual ~ivararg_function() 19880 | {} 19881 | 19882 | inline virtual T operator() (const std::vector<T>&) 19883 | { 19884 | exprtk_debug(("ivararg_function::operator() - Operator has not been overridden\n")); 19885 | return std::numeric_limits<T>::quiet_NaN(); 19886 | } 19887 | }; 19888 | 19889 | template <typename T> 19890 | class igeneric_function : public function_traits 19891 | { 19892 | public: 19893 | 19894 | enum return_type 19895 | { 19896 | e_rtrn_scalar = 0, 19897 | e_rtrn_string = 1, 19898 | e_rtrn_overload = 2 19899 | }; 19900 | 19901 | typedef T type; 19902 | typedef type_store<T> generic_type; 19903 | typedef typename generic_type::parameter_list parameter_list_t; 19904 | 19905 | explicit igeneric_function(const std::string& param_seq = "", const return_type rtr_type = e_rtrn_scalar) 19906 | : parameter_sequence(param_seq) 19907 | , rtrn_type(rtr_type) 19908 | {} 19909 | 19910 | virtual ~igeneric_function() 19911 | {} 19912 | 19913 | #define igeneric_function_empty_body(N) \ 19914 | { \ 19915 | exprtk_debug(("igeneric_function::operator() - Operator(" #N ") has not been overridden\n")); \ 19916 | return std::numeric_limits<T>::quiet_NaN(); \ 19917 | } \ 19918 | 19919 | // f(i_0,i_1,....,i_N) --> Scalar 19920 | inline virtual T operator() (parameter_list_t) 19921 | igeneric_function_empty_body(1) 19922 | 19923 | // f(i_0,i_1,....,i_N) --> String 19924 | inline virtual T operator() (std::string&, parameter_list_t) 19925 | igeneric_function_empty_body(2) 19926 | 19927 | // f(psi,i_0,i_1,....,i_N) --> Scalar 19928 | inline virtual T operator() (const std::size_t&, parameter_list_t) 19929 | igeneric_function_empty_body(3) 19930 | 19931 | // f(psi,i_0,i_1,....,i_N) --> String 19932 | inline virtual T operator() (const std::size_t&, std::string&, parameter_list_t) 19933 | igeneric_function_empty_body(4) 19934 | 19935 | #undef igeneric_function_empty_body 19936 | 19937 | std::string parameter_sequence; 19938 | return_type rtrn_type; 19939 | 19940 | static inline std::string generate_prefix_args(const std::string& prefix_args, std::size_t start = 0, std::size_t end = 10) 19941 | { 19942 | std::string result; 19943 | 19944 | for (std::size_t i = start; i <= end; ++i) 19945 | { 19946 | result += prefix_args + std::string(i,'?'); 19947 | result += (i != end) ? "|" : "" 19948 | } 19949 | 19950 | return result; 19951 | } 19952 | 19953 | static inline std::string generate_suffix_args(const std::string& suffix_args, std::size_t start = 0, std::size_t end = 10) 19954 | { 19955 | std::string result; 19956 | 19957 | for (std::size_t i = start; i <= end; ++i) 19958 | { 19959 | result += std::string(i,'?') + suffix_args; 19960 | result += (i != end) ? "|" : "" 19961 | } 19962 | 19963 | return result; 19964 | } 19965 | }; 19966 | 19967 | #ifndef exprtk_disable_string_capabilities 19968 | template <typename T> 19969 | class stringvar_base 19970 | { 19971 | public: 19972 | 19973 | typedef typename details::stringvar_node<T> stringvar_node_t; 19974 | 19975 | stringvar_base(const std::string& name, stringvar_node_t* svn) 19976 | : name_(name) 19977 | , string_varnode_(svn) 19978 | {} 19979 | 19980 | bool valid() const 19981 | { 19982 | return !name_.empty() && (0 != string_varnode_); 19983 | } 19984 | 19985 | std::string name() const 19986 | { 19987 | assert(string_varnode_); 19988 | return name_; 19989 | } 19990 | 19991 | void rebase(std::string& s) 19992 | { 19993 | assert(string_varnode_); 19994 | string_varnode_->rebase(s); 19995 | } 19996 | 19997 | private: 19998 | 19999 | std::string name_; 20000 | stringvar_node_t* string_varnode_; 20001 | }; 20002 | #endif 20003 | 20004 | template <typename T> class parser; 20005 | template <typename T> class expression_helper; 20006 | 20007 | template <typename T> 20008 | class symbol_table 20009 | { 20010 | public: 20011 | 20012 | enum symtab_mutability_type 20013 | { 20014 | e_unknown = 0, 20015 | e_mutable = 1, 20016 | e_immutable = 2 20017 | }; 20018 | 20019 | typedef T (*ff00_functor)(); 20020 | typedef T (*ff01_functor)(T); 20021 | typedef T (*ff02_functor)(T, T); 20022 | typedef T (*ff03_functor)(T, T, T); 20023 | typedef T (*ff04_functor)(T, T, T, T); 20024 | typedef T (*ff05_functor)(T, T, T, T, T); 20025 | typedef T (*ff06_functor)(T, T, T, T, T, T); 20026 | typedef T (*ff07_functor)(T, T, T, T, T, T, T); 20027 | typedef T (*ff08_functor)(T, T, T, T, T, T, T, T); 20028 | typedef T (*ff09_functor)(T, T, T, T, T, T, T, T, T); 20029 | typedef T (*ff10_functor)(T, T, T, T, T, T, T, T, T, T); 20030 | typedef T (*ff11_functor)(T, T, T, T, T, T, T, T, T, T, T); 20031 | typedef T (*ff12_functor)(T, T, T, T, T, T, T, T, T, T, T, T); 20032 | typedef T (*ff13_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T); 20033 | typedef T (*ff14_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T); 20034 | typedef T (*ff15_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T, T); 20035 | 20036 | protected: 20037 | 20038 | struct freefunc00 exprtk_final : public exprtk::ifunction<T> 20039 | { 20040 | using exprtk::ifunction<T>::operator(); 20041 | 20042 | explicit freefunc00(ff00_functor ff) : exprtk::ifunction<T>(0), f(ff) {} 20043 | inline T operator() () exprtk_override 20044 | { return f(); } 20045 | ff00_functor f; 20046 | }; 20047 | 20048 | struct freefunc01 exprtk_final : public exprtk::ifunction<T> 20049 | { 20050 | using exprtk::ifunction<T>::operator(); 20051 | 20052 | explicit freefunc01(ff01_functor ff) : exprtk::ifunction<T>(1), f(ff) {} 20053 | inline T operator() (const T& v0) exprtk_override 20054 | { return f(v0); } 20055 | ff01_functor f; 20056 | }; 20057 | 20058 | struct freefunc02 exprtk_final : public exprtk::ifunction<T> 20059 | { 20060 | using exprtk::ifunction<T>::operator(); 20061 | 20062 | explicit freefunc02(ff02_functor ff) : exprtk::ifunction<T>(2), f(ff) {} 20063 | inline T operator() (const T& v0, const T& v1) exprtk_override 20064 | { return f(v0, v1); } 20065 | ff02_functor f; 20066 | }; 20067 | 20068 | struct freefunc03 exprtk_final : public exprtk::ifunction<T> 20069 | { 20070 | using exprtk::ifunction<T>::operator(); 20071 | 20072 | explicit freefunc03(ff03_functor ff) : exprtk::ifunction<T>(3), f(ff) {} 20073 | inline T operator() (const T& v0, const T& v1, const T& v2) exprtk_override 20074 | { return f(v0, v1, v2); } 20075 | ff03_functor f; 20076 | }; 20077 | 20078 | struct freefunc04 exprtk_final : public exprtk::ifunction<T> 20079 | { 20080 | using exprtk::ifunction<T>::operator(); 20081 | 20082 | explicit freefunc04(ff04_functor ff) : exprtk::ifunction<T>(4), f(ff) {} 20083 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3) exprtk_override 20084 | { return f(v0, v1, v2, v3); } 20085 | ff04_functor f; 20086 | }; 20087 | 20088 | struct freefunc05 : public exprtk::ifunction<T> 20089 | { 20090 | using exprtk::ifunction<T>::operator(); 20091 | 20092 | explicit freefunc05(ff05_functor ff) : exprtk::ifunction<T>(5), f(ff) {} 20093 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4) exprtk_override 20094 | { return f(v0, v1, v2, v3, v4); } 20095 | ff05_functor f; 20096 | }; 20097 | 20098 | struct freefunc06 exprtk_final : public exprtk::ifunction<T> 20099 | { 20100 | using exprtk::ifunction<T>::operator(); 20101 | 20102 | explicit freefunc06(ff06_functor ff) : exprtk::ifunction<T>(6), f(ff) {} 20103 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5) exprtk_override 20104 | { return f(v0, v1, v2, v3, v4, v5); } 20105 | ff06_functor f; 20106 | }; 20107 | 20108 | struct freefunc07 exprtk_final : public exprtk::ifunction<T> 20109 | { 20110 | using exprtk::ifunction<T>::operator(); 20111 | 20112 | explicit freefunc07(ff07_functor ff) : exprtk::ifunction<T>(7), f(ff) {} 20113 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, 20114 | const T& v5, const T& v6) exprtk_override 20115 | { return f(v0, v1, v2, v3, v4, v5, v6); } 20116 | ff07_functor f; 20117 | }; 20118 | 20119 | struct freefunc08 exprtk_final : public exprtk::ifunction<T> 20120 | { 20121 | using exprtk::ifunction<T>::operator(); 20122 | 20123 | explicit freefunc08(ff08_functor ff) : exprtk::ifunction<T>(8), f(ff) {} 20124 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, 20125 | const T& v5, const T& v6, const T& v7) exprtk_override 20126 | { return f(v0, v1, v2, v3, v4, v5, v6, v7); } 20127 | ff08_functor f; 20128 | }; 20129 | 20130 | struct freefunc09 exprtk_final : public exprtk::ifunction<T> 20131 | { 20132 | using exprtk::ifunction<T>::operator(); 20133 | 20134 | explicit freefunc09(ff09_functor ff) : exprtk::ifunction<T>(9), f(ff) {} 20135 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, 20136 | const T& v5, const T& v6, const T& v7, const T& v8) exprtk_override 20137 | { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8); } 20138 | ff09_functor f; 20139 | }; 20140 | 20141 | struct freefunc10 exprtk_final : public exprtk::ifunction<T> 20142 | { 20143 | using exprtk::ifunction<T>::operator(); 20144 | 20145 | explicit freefunc10(ff10_functor ff) : exprtk::ifunction<T>(10), f(ff) {} 20146 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, 20147 | const T& v5, const T& v6, const T& v7, const T& v8, const T& v9) exprtk_override 20148 | { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9); } 20149 | ff10_functor f; 20150 | }; 20151 | 20152 | struct freefunc11 exprtk_final : public exprtk::ifunction<T> 20153 | { 20154 | using exprtk::ifunction<T>::operator(); 20155 | 20156 | explicit freefunc11(ff11_functor ff) : exprtk::ifunction<T>(11), f(ff) {} 20157 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, 20158 | const T& v5, const T& v6, const T& v7, const T& v8, const T& v9, const T& v10) exprtk_override 20159 | { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10); } 20160 | ff11_functor f; 20161 | }; 20162 | 20163 | struct freefunc12 exprtk_final : public exprtk::ifunction<T> 20164 | { 20165 | using exprtk::ifunction<T>::operator(); 20166 | 20167 | explicit freefunc12(ff12_functor ff) : exprtk::ifunction<T>(12), f(ff) {} 20168 | inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04, 20169 | const T& v05, const T& v06, const T& v07, const T& v08, const T& v09, 20170 | const T& v10, const T& v11) exprtk_override 20171 | { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11); } 20172 | ff12_functor f; 20173 | }; 20174 | 20175 | struct freefunc13 exprtk_final : public exprtk::ifunction<T> 20176 | { 20177 | using exprtk::ifunction<T>::operator(); 20178 | 20179 | explicit freefunc13(ff13_functor ff) : exprtk::ifunction<T>(13), f(ff) {} 20180 | inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04, 20181 | const T& v05, const T& v06, const T& v07, const T& v08, const T& v09, 20182 | const T& v10, const T& v11, const T& v12) exprtk_override 20183 | { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12); } 20184 | ff13_functor f; 20185 | }; 20186 | 20187 | struct freefunc14 exprtk_final : public exprtk::ifunction<T> 20188 | { 20189 | using exprtk::ifunction<T>::operator(); 20190 | 20191 | explicit freefunc14(ff14_functor ff) : exprtk::ifunction<T>(14), f(ff) {} 20192 | inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04, 20193 | const T& v05, const T& v06, const T& v07, const T& v08, const T& v09, 20194 | const T& v10, const T& v11, const T& v12, const T& v13) exprtk_override 20195 | { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12, v13); } 20196 | ff14_functor f; 20197 | }; 20198 | 20199 | struct freefunc15 exprtk_final : public exprtk::ifunction<T> 20200 | { 20201 | using exprtk::ifunction<T>::operator(); 20202 | 20203 | explicit freefunc15(ff15_functor ff) : exprtk::ifunction<T>(15), f(ff) {} 20204 | inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04, 20205 | const T& v05, const T& v06, const T& v07, const T& v08, const T& v09, 20206 | const T& v10, const T& v11, const T& v12, const T& v13, const T& v14) exprtk_override 20207 | { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12, v13, v14); } 20208 | ff15_functor f; 20209 | }; 20210 | 20211 | template <typename Type, typename RawType> 20212 | struct type_store 20213 | { 20214 | typedef details::expression_node<T>* expression_ptr; 20215 | typedef typename details::variable_node<T> variable_node_t; 20216 | typedef ifunction<T> ifunction_t; 20217 | typedef ivararg_function<T> ivararg_function_t; 20218 | typedef igeneric_function<T> igeneric_function_t; 20219 | typedef details::vector_holder<T> vector_t; 20220 | #ifndef exprtk_disable_string_capabilities 20221 | typedef typename details::stringvar_node<T> stringvar_node_t; 20222 | #endif 20223 | 20224 | typedef Type type_t; 20225 | typedef type_t* type_ptr; 20226 | typedef std::pair<bool,type_ptr> type_pair_t; 20227 | typedef std::map<std::string,type_pair_t,details::ilesscompare> type_map_t; 20228 | typedef typename type_map_t::iterator tm_itr_t; 20229 | typedef typename type_map_t::const_iterator tm_const_itr_t; 20230 | 20231 | enum { lut_size = 256 }; 20232 | 20233 | type_map_t map; 20234 | std::size_t size; 20235 | 20236 | type_store() 20237 | : size(0) 20238 | {} 20239 | 20240 | struct deleter 20241 | { 20242 | #define exprtk_define_process(Type) \ 20243 | static inline void process(std::pair<bool,Type*>& n) \ 20244 | { \ 20245 | delete n.second; \ 20246 | } \ 20247 | 20248 | exprtk_define_process(variable_node_t ) 20249 | exprtk_define_process(vector_t ) 20250 | #ifndef exprtk_disable_string_capabilities 20251 | exprtk_define_process(stringvar_node_t) 20252 | #endif 20253 | 20254 | #undef exprtk_define_process 20255 | 20256 | template <typename DeleteType> 20257 | static inline void process(std::pair<bool,DeleteType*>&) 20258 | {} 20259 | }; 20260 | 20261 | inline bool symbol_exists(const std::string& symbol_name) const 20262 | { 20263 | if (symbol_name.empty()) 20264 | return false; 20265 | else if (map.end() != map.find(symbol_name)) 20266 | return true; 20267 | else 20268 | return false; 20269 | } 20270 | 20271 | template <typename PtrType> 20272 | inline std::string entity_name(const PtrType& ptr) const 20273 | { 20274 | if (map.empty()) 20275 | return std::string(); 20276 | 20277 | tm_const_itr_t itr = map.begin(); 20278 | 20279 | while (map.end() != itr) 20280 | { 20281 | if (itr->second.second == ptr) 20282 | { 20283 | return itr->first; 20284 | } 20285 | else 20286 | ++itr; 20287 | } 20288 | 20289 | return std::string(); 20290 | } 20291 | 20292 | inline bool is_constant(const std::string& symbol_name) const 20293 | { 20294 | if (symbol_name.empty()) 20295 | return false; 20296 | else 20297 | { 20298 | const tm_const_itr_t itr = map.find(symbol_name); 20299 | 20300 | if (map.end() == itr) 20301 | return false; 20302 | else 20303 | return (*itr).second.first; 20304 | } 20305 | } 20306 | 20307 | template <typename Tie, typename RType> 20308 | inline bool add_impl(const std::string& symbol_name, RType t, const bool is_const) 20309 | { 20310 | if (symbol_name.size() > 1) 20311 | { 20312 | for (std::size_t i = 0; i < details::reserved_symbols_size; ++i) 20313 | { 20314 | if (details::imatch(symbol_name, details::reserved_symbols[i])) 20315 | { 20316 | return false; 20317 | } 20318 | } 20319 | } 20320 | 20321 | const tm_itr_t itr = map.find(symbol_name); 20322 | 20323 | if (map.end() == itr) 20324 | { 20325 | map[symbol_name] = Tie::make(t,is_const); 20326 | ++size; 20327 | } 20328 | 20329 | return true; 20330 | } 20331 | 20332 | struct tie_array 20333 | { 20334 | static inline std::pair<bool,vector_t*> make(std::pair<T*,std::size_t> v, const bool is_const = false) 20335 | { 20336 | return std::make_pair(is_const, new vector_t(v.first, v.second)); 20337 | } 20338 | }; 20339 | 20340 | struct tie_stdvec 20341 | { 20342 | template <typename Allocator> 20343 | static inline std::pair<bool,vector_t*> make(std::vector<T,Allocator>& v, const bool is_const = false) 20344 | { 20345 | return std::make_pair(is_const, new vector_t(v)); 20346 | } 20347 | }; 20348 | 20349 | struct tie_vecview 20350 | { 20351 | static inline std::pair<bool,vector_t*> make(exprtk::vector_view<T>& v, const bool is_const = false) 20352 | { 20353 | return std::make_pair(is_const, new vector_t(v)); 20354 | } 20355 | }; 20356 | 20357 | struct tie_stddeq 20358 | { 20359 | template <typename Allocator> 20360 | static inline std::pair<bool,vector_t*> make(std::deque<T,Allocator>& v, const bool is_const = false) 20361 | { 20362 | return std::make_pair(is_const, new vector_t(v)); 20363 | } 20364 | }; 20365 | 20366 | template <std::size_t v_size> 20367 | inline bool add(const std::string& symbol_name, T (&v)[v_size], const bool is_const = false) 20368 | { 20369 | return add_impl<tie_array,std::pair<T*,std::size_t> > 20370 | (symbol_name, std::make_pair(v,v_size), is_const); 20371 | } 20372 | 20373 | inline bool add(const std::string& symbol_name, T* v, const std::size_t v_size, const bool is_const = false) 20374 | { 20375 | return add_impl<tie_array,std::pair<T*,std::size_t> > 20376 | (symbol_name, std::make_pair(v,v_size), is_const); 20377 | } 20378 | 20379 | template <typename Allocator> 20380 | inline bool add(const std::string& symbol_name, std::vector<T,Allocator>& v, const bool is_const = false) 20381 | { 20382 | return add_impl<tie_stdvec,std::vector<T,Allocator>&> 20383 | (symbol_name, v, is_const); 20384 | } 20385 | 20386 | inline bool add(const std::string& symbol_name, exprtk::vector_view<T>& v, const bool is_const = false) 20387 | { 20388 | return add_impl<tie_vecview,exprtk::vector_view<T>&> 20389 | (symbol_name, v, is_const); 20390 | } 20391 | 20392 | template <typename Allocator> 20393 | inline bool add(const std::string& symbol_name, std::deque<T,Allocator>& v, const bool is_const = false) 20394 | { 20395 | return add_impl<tie_stddeq,std::deque<T,Allocator>&> 20396 | (symbol_name, v, is_const); 20397 | } 20398 | 20399 | inline bool add(const std::string& symbol_name, RawType& t_, const bool is_const = false) 20400 | { 20401 | struct tie 20402 | { 20403 | static inline std::pair<bool,variable_node_t*> make(T& t, const bool is_constant = false) 20404 | { 20405 | return std::make_pair(is_constant, new variable_node_t(t)); 20406 | } 20407 | 20408 | #ifndef exprtk_disable_string_capabilities 20409 | static inline std::pair<bool,stringvar_node_t*> make(std::string& t, const bool is_constant = false) 20410 | { 20411 | return std::make_pair(is_constant, new stringvar_node_t(t)); 20412 | } 20413 | #endif 20414 | 20415 | static inline std::pair<bool,function_t*> make(function_t& t, const bool is_constant = false) 20416 | { 20417 | return std::make_pair(is_constant,&t); 20418 | } 20419 | 20420 | static inline std::pair<bool,vararg_function_t*> make(vararg_function_t& t, const bool is_constant = false) 20421 | { 20422 | return std::make_pair(is_constant,&t); 20423 | } 20424 | 20425 | static inline std::pair<bool,generic_function_t*> make(generic_function_t& t, const bool is_constant = false) 20426 | { 20427 | return std::make_pair(is_constant,&t); 20428 | } 20429 | }; 20430 | 20431 | const tm_itr_t itr = map.find(symbol_name); 20432 | 20433 | if (map.end() == itr) 20434 | { 20435 | map[symbol_name] = tie::make(t_,is_const); 20436 | ++size; 20437 | } 20438 | 20439 | return true; 20440 | } 20441 | 20442 | inline type_ptr get(const std::string& symbol_name) const 20443 | { 20444 | const tm_const_itr_t itr = map.find(symbol_name); 20445 | 20446 | if (map.end() == itr) 20447 | return reinterpret_cast<type_ptr>(0); 20448 | else 20449 | return itr->second.second; 20450 | } 20451 | 20452 | template <typename TType, typename TRawType, typename PtrType> 20453 | struct ptr_match 20454 | { 20455 | static inline bool test(const PtrType, const void*) 20456 | { 20457 | return false; 20458 | } 20459 | }; 20460 | 20461 | template <typename TType, typename TRawType> 20462 | struct ptr_match<TType,TRawType,variable_node_t*> 20463 | { 20464 | static inline bool test(const variable_node_t* p, const void* ptr) 20465 | { 20466 | exprtk_debug(("ptr_match::test() - %p <--> %p\n", reinterpret_cast<const void*>(&(p->ref())), ptr)); 20467 | return (&(p->ref()) == ptr); 20468 | } 20469 | }; 20470 | 20471 | inline type_ptr get_from_varptr(const void* ptr) const 20472 | { 20473 | tm_const_itr_t itr = map.begin(); 20474 | 20475 | while (map.end() != itr) 20476 | { 20477 | type_ptr ret_ptr = itr->second.second; 20478 | 20479 | if (ptr_match<Type,RawType,type_ptr>::test(ret_ptr,ptr)) 20480 | { 20481 | return ret_ptr; 20482 | } 20483 | 20484 | ++itr; 20485 | } 20486 | 20487 | return type_ptr(0); 20488 | } 20489 | 20490 | inline bool remove(const std::string& symbol_name, const bool delete_node = true) 20491 | { 20492 | const tm_itr_t itr = map.find(symbol_name); 20493 | 20494 | if (map.end() != itr) 20495 | { 20496 | if (delete_node) 20497 | { 20498 | deleter::process((*itr).second); 20499 | } 20500 | 20501 | map.erase(itr); 20502 | --size; 20503 | 20504 | return true; 20505 | } 20506 | else 20507 | return false; 20508 | } 20509 | 20510 | inline RawType& type_ref(const std::string& symbol_name) 20511 | { 20512 | struct init_type 20513 | { 20514 | static inline double set(double) { return (0.0); } 20515 | static inline double set(long double) { return (0.0); } 20516 | static inline float set(float) { return (0.0f); } 20517 | static inline std::string set(std::string&) { return std::string(""); } 20518 | }; 20519 | 20520 | static RawType null_type = init_type::set(RawType()); 20521 | 20522 | const tm_const_itr_t itr = map.find(symbol_name); 20523 | 20524 | if (map.end() == itr) 20525 | return null_type; 20526 | else 20527 | return itr->second.second->ref(); 20528 | } 20529 | 20530 | inline void clear(const bool delete_node = true) 20531 | { 20532 | if (!map.empty()) 20533 | { 20534 | if (delete_node) 20535 | { 20536 | tm_itr_t itr = map.begin(); 20537 | tm_itr_t end = map.end (); 20538 | 20539 | while (end != itr) 20540 | { 20541 | deleter::process((*itr).second); 20542 | ++itr; 20543 | } 20544 | } 20545 | 20546 | map.clear(); 20547 | } 20548 | 20549 | size = 0; 20550 | } 20551 | 20552 | template <typename Allocator, 20553 | template <typename, typename> class Sequence> 20554 | inline std::size_t get_list(Sequence<std::pair<std::string,RawType>,Allocator>& list) const 20555 | { 20556 | std::size_t count = 0; 20557 | 20558 | if (!map.empty()) 20559 | { 20560 | tm_const_itr_t itr = map.begin(); 20561 | tm_const_itr_t end = map.end (); 20562 | 20563 | while (end != itr) 20564 | { 20565 | list.push_back(std::make_pair((*itr).first,itr->second.second->ref())); 20566 | ++itr; 20567 | ++count; 20568 | } 20569 | } 20570 | 20571 | return count; 20572 | } 20573 | 20574 | template <typename Allocator, 20575 | template <typename, typename> class Sequence> 20576 | inline std::size_t get_list(Sequence<std::string,Allocator>& vlist) const 20577 | { 20578 | std::size_t count = 0; 20579 | 20580 | if (!map.empty()) 20581 | { 20582 | tm_const_itr_t itr = map.begin(); 20583 | tm_const_itr_t end = map.end (); 20584 | 20585 | while (end != itr) 20586 | { 20587 | vlist.push_back((*itr).first); 20588 | ++itr; 20589 | ++count; 20590 | } 20591 | } 20592 | 20593 | return count; 20594 | } 20595 | }; 20596 | 20597 | typedef details::expression_node<T>* expression_ptr; 20598 | typedef typename details::variable_node<T> variable_t; 20599 | typedef typename details::vector_holder<T> vector_holder_t; 20600 | typedef variable_t* variable_ptr; 20601 | #ifndef exprtk_disable_string_capabilities 20602 | typedef typename details::stringvar_node<T> stringvar_t; 20603 | typedef stringvar_t* stringvar_ptr; 20604 | #endif 20605 | typedef ifunction <T> function_t; 20606 | typedef ivararg_function <T> vararg_function_t; 20607 | typedef igeneric_function<T> generic_function_t; 20608 | typedef function_t* function_ptr; 20609 | typedef vararg_function_t* vararg_function_ptr; 20610 | typedef generic_function_t* generic_function_ptr; 20611 | 20612 | static const std::size_t lut_size = 256; 20613 | 20614 | // Symbol Table Holder 20615 | struct control_block 20616 | { 20617 | struct st_data 20618 | { 20619 | type_store<variable_t , T > variable_store; 20620 | type_store<function_t , function_t > function_store; 20621 | type_store<vararg_function_t , vararg_function_t > vararg_function_store; 20622 | type_store<generic_function_t, generic_function_t> generic_function_store; 20623 | type_store<generic_function_t, generic_function_t> string_function_store; 20624 | type_store<generic_function_t, generic_function_t> overload_function_store; 20625 | type_store<vector_holder_t , vector_holder_t > vector_store; 20626 | #ifndef exprtk_disable_string_capabilities 20627 | type_store<stringvar_t , std::string > stringvar_store; 20628 | #endif 20629 | 20630 | st_data() 20631 | { 20632 | for (std::size_t i = 0; i < details::reserved_words_size; ++i) 20633 | { 20634 | reserved_symbol_table_.insert(details::reserved_words[i]); 20635 | } 20636 | 20637 | for (std::size_t i = 0; i < details::reserved_symbols_size; ++i) 20638 | { 20639 | reserved_symbol_table_.insert(details::reserved_symbols[i]); 20640 | } 20641 | } 20642 | 20643 | ~st_data() 20644 | { 20645 | for (std::size_t i = 0; i < free_function_list_.size(); ++i) 20646 | { 20647 | delete free_function_list_[i]; 20648 | } 20649 | } 20650 | 20651 | inline bool is_reserved_symbol(const std::string& symbol) const 20652 | { 20653 | return (reserved_symbol_table_.end() != reserved_symbol_table_.find(symbol)); 20654 | } 20655 | 20656 | static inline st_data* create() 20657 | { 20658 | return (new st_data); 20659 | } 20660 | 20661 | static inline void destroy(st_data*& sd) 20662 | { 20663 | delete sd; 20664 | sd = reinterpret_cast<st_data*>(0); 20665 | } 20666 | 20667 | std::list<T> local_symbol_list_; 20668 | std::list<std::string> local_stringvar_list_; 20669 | std::set<std::string> reserved_symbol_table_; 20670 | std::vector<ifunction<T>*> free_function_list_; 20671 | }; 20672 | 20673 | control_block() 20674 | : ref_count(1) 20675 | , data_(st_data::create()) 20676 | , mutability_(e_mutable) 20677 | {} 20678 | 20679 | explicit control_block(st_data* data) 20680 | : ref_count(1) 20681 | , data_(data) 20682 | , mutability_(e_mutable) 20683 | {} 20684 | 20685 | ~control_block() 20686 | { 20687 | if (data_ && (0 == ref_count)) 20688 | { 20689 | st_data::destroy(data_); 20690 | } 20691 | } 20692 | 20693 | static inline control_block* create() 20694 | { 20695 | return (new control_block); 20696 | } 20697 | 20698 | template <typename SymTab> 20699 | static inline void destroy(control_block*& cntrl_blck, SymTab* sym_tab) 20700 | { 20701 | if (cntrl_blck) 20702 | { 20703 | if ( 20704 | (0 != cntrl_blck->ref_count) && 20705 | (0 == --cntrl_blck->ref_count) 20706 | ) 20707 | { 20708 | if (sym_tab) 20709 | sym_tab->clear(); 20710 | 20711 | delete cntrl_blck; 20712 | } 20713 | 20714 | cntrl_blck = 0; 20715 | } 20716 | } 20717 | 20718 | void set_mutability(const symtab_mutability_type mutability) 20719 | { 20720 | mutability_ = mutability; 20721 | } 20722 | 20723 | std::size_t ref_count; 20724 | st_data* data_; 20725 | symtab_mutability_type mutability_; 20726 | }; 20727 | 20728 | public: 20729 | 20730 | explicit symbol_table(const symtab_mutability_type mutability = e_mutable) 20731 | : control_block_(control_block::create()) 20732 | { 20733 | control_block_->set_mutability(mutability); 20734 | clear(); 20735 | } 20736 | 20737 | ~symbol_table() 20738 | { 20739 | exprtk::details::dump_ptr("~symbol_table", this); 20740 | control_block::destroy(control_block_, this); 20741 | } 20742 | 20743 | symbol_table(const symbol_table<T>& st) 20744 | { 20745 | control_block_ = st.control_block_; 20746 | control_block_->ref_count++; 20747 | } 20748 | 20749 | inline symbol_table<T>& operator=(const symbol_table<T>& st) 20750 | { 20751 | if (this != &st) 20752 | { 20753 | control_block::destroy(control_block_,reinterpret_cast<symbol_table<T>*>(0)); 20754 | 20755 | control_block_ = st.control_block_; 20756 | control_block_->ref_count++; 20757 | } 20758 | 20759 | return (*this); 20760 | } 20761 | 20762 | inline bool operator==(const symbol_table<T>& st) const 20763 | { 20764 | return (this == &st) || (control_block_ == st.control_block_); 20765 | } 20766 | 20767 | inline symtab_mutability_type mutability() const 20768 | { 20769 | return valid() ? control_block_->mutability_ : e_unknown; 20770 | } 20771 | 20772 | inline void clear_variables(const bool delete_node = true) 20773 | { 20774 | local_data().variable_store.clear(delete_node); 20775 | } 20776 | 20777 | inline void clear_functions() 20778 | { 20779 | local_data().function_store.clear(); 20780 | } 20781 | 20782 | inline void clear_strings() 20783 | { 20784 | #ifndef exprtk_disable_string_capabilities 20785 | local_data().stringvar_store.clear(); 20786 | #endif 20787 | } 20788 | 20789 | inline void clear_vectors() 20790 | { 20791 | local_data().vector_store.clear(); 20792 | } 20793 | 20794 | inline void clear_local_constants() 20795 | { 20796 | local_data().local_symbol_list_.clear(); 20797 | } 20798 | 20799 | inline void clear() 20800 | { 20801 | if (!valid()) return; 20802 | clear_variables (); 20803 | clear_functions (); 20804 | clear_strings (); 20805 | clear_vectors (); 20806 | clear_local_constants(); 20807 | } 20808 | 20809 | inline std::size_t variable_count() const 20810 | { 20811 | if (valid()) 20812 | return local_data().variable_store.size; 20813 | else 20814 | return 0; 20815 | } 20816 | 20817 | #ifndef exprtk_disable_string_capabilities 20818 | inline std::size_t stringvar_count() const 20819 | { 20820 | if (valid()) 20821 | return local_data().stringvar_store.size; 20822 | else 20823 | return 0; 20824 | } 20825 | #endif 20826 | 20827 | inline std::size_t function_count() const 20828 | { 20829 | if (valid()) 20830 | return local_data().function_store.size; 20831 | else 20832 | return 0; 20833 | } 20834 | 20835 | inline std::size_t vector_count() const 20836 | { 20837 | if (valid()) 20838 | return local_data().vector_store.size; 20839 | else 20840 | return 0; 20841 | } 20842 | 20843 | inline variable_ptr get_variable(const std::string& variable_name) const 20844 | { 20845 | if (!valid()) 20846 | return reinterpret_cast<variable_ptr>(0); 20847 | else if (!valid_symbol(variable_name)) 20848 | return reinterpret_cast<variable_ptr>(0); 20849 | else 20850 | return local_data().variable_store.get(variable_name); 20851 | } 20852 | 20853 | inline variable_ptr get_variable(const T& var_ref) const 20854 | { 20855 | if (!valid()) 20856 | return reinterpret_cast<variable_ptr>(0); 20857 | else 20858 | return local_data().variable_store.get_from_varptr( 20859 | reinterpret_cast<const void*>(&var_ref)); 20860 | } 20861 | 20862 | #ifndef exprtk_disable_string_capabilities 20863 | inline stringvar_ptr get_stringvar(const std::string& string_name) const 20864 | { 20865 | if (!valid()) 20866 | return reinterpret_cast<stringvar_ptr>(0); 20867 | else if (!valid_symbol(string_name)) 20868 | return reinterpret_cast<stringvar_ptr>(0); 20869 | else 20870 | return local_data().stringvar_store.get(string_name); 20871 | } 20872 | 20873 | inline stringvar_base<T> get_stringvar_base(const std::string& string_name) const 20874 | { 20875 | static stringvar_base<T> null_stringvar_base("",reinterpret_cast<stringvar_ptr>(0)); 20876 | if (!valid()) 20877 | return null_stringvar_base; 20878 | else if (!valid_symbol(string_name)) 20879 | return null_stringvar_base; 20880 | 20881 | stringvar_ptr stringvar = local_data().stringvar_store.get(string_name); 20882 | 20883 | if (0 == stringvar) 20884 | { 20885 | return null_stringvar_base; 20886 | } 20887 | 20888 | return stringvar_base<T>(string_name,stringvar); 20889 | } 20890 | #endif 20891 | 20892 | inline function_ptr get_function(const std::string& function_name) const 20893 | { 20894 | if (!valid()) 20895 | return reinterpret_cast<function_ptr>(0); 20896 | else if (!valid_symbol(function_name)) 20897 | return reinterpret_cast<function_ptr>(0); 20898 | else 20899 | return local_data().function_store.get(function_name); 20900 | } 20901 | 20902 | inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name) const 20903 | { 20904 | if (!valid()) 20905 | return reinterpret_cast<vararg_function_ptr>(0); 20906 | else if (!valid_symbol(vararg_function_name)) 20907 | return reinterpret_cast<vararg_function_ptr>(0); 20908 | else 20909 | return local_data().vararg_function_store.get(vararg_function_name); 20910 | } 20911 | 20912 | inline generic_function_ptr get_generic_function(const std::string& function_name) const 20913 | { 20914 | if (!valid()) 20915 | return reinterpret_cast<generic_function_ptr>(0); 20916 | else if (!valid_symbol(function_name)) 20917 | return reinterpret_cast<generic_function_ptr>(0); 20918 | else 20919 | return local_data().generic_function_store.get(function_name); 20920 | } 20921 | 20922 | inline generic_function_ptr get_string_function(const std::string& function_name) const 20923 | { 20924 | if (!valid()) 20925 | return reinterpret_cast<generic_function_ptr>(0); 20926 | else if (!valid_symbol(function_name)) 20927 | return reinterpret_cast<generic_function_ptr>(0); 20928 | else 20929 | return local_data().string_function_store.get(function_name); 20930 | } 20931 | 20932 | inline generic_function_ptr get_overload_function(const std::string& function_name) const 20933 | { 20934 | if (!valid()) 20935 | return reinterpret_cast<generic_function_ptr>(0); 20936 | else if (!valid_symbol(function_name)) 20937 | return reinterpret_cast<generic_function_ptr>(0); 20938 | else 20939 | return local_data().overload_function_store.get(function_name); 20940 | } 20941 | 20942 | typedef vector_holder_t* vector_holder_ptr; 20943 | 20944 | inline vector_holder_ptr get_vector(const std::string& vector_name) const 20945 | { 20946 | if (!valid()) 20947 | return reinterpret_cast<vector_holder_ptr>(0); 20948 | else if (!valid_symbol(vector_name)) 20949 | return reinterpret_cast<vector_holder_ptr>(0); 20950 | else 20951 | return local_data().vector_store.get(vector_name); 20952 | } 20953 | 20954 | inline T& variable_ref(const std::string& symbol_name) 20955 | { 20956 | static T null_var = T(0); 20957 | if (!valid()) 20958 | return null_var; 20959 | else if (!valid_symbol(symbol_name)) 20960 | return null_var; 20961 | else 20962 | return local_data().variable_store.type_ref(symbol_name); 20963 | } 20964 | 20965 | #ifndef exprtk_disable_string_capabilities 20966 | inline std::string& stringvar_ref(const std::string& symbol_name) 20967 | { 20968 | static std::string null_stringvar; 20969 | if (!valid()) 20970 | return null_stringvar; 20971 | else if (!valid_symbol(symbol_name)) 20972 | return null_stringvar; 20973 | else 20974 | return local_data().stringvar_store.type_ref(symbol_name); 20975 | } 20976 | #endif 20977 | 20978 | inline bool is_constant_node(const std::string& symbol_name) const 20979 | { 20980 | if (!valid()) 20981 | return false; 20982 | else if (!valid_symbol(symbol_name)) 20983 | return false; 20984 | else 20985 | return local_data().variable_store.is_constant(symbol_name); 20986 | } 20987 | 20988 | #ifndef exprtk_disable_string_capabilities 20989 | inline bool is_constant_string(const std::string& symbol_name) const 20990 | { 20991 | if (!valid()) 20992 | return false; 20993 | else if (!valid_symbol(symbol_name)) 20994 | return false; 20995 | else if (!local_data().stringvar_store.symbol_exists(symbol_name)) 20996 | return false; 20997 | else 20998 | return local_data().stringvar_store.is_constant(symbol_name); 20999 | } 21000 | #endif 21001 | 21002 | inline bool create_variable(const std::string& variable_name, const T& value = T(0)) 21003 | { 21004 | if (!valid()) 21005 | return false; 21006 | else if (!valid_symbol(variable_name)) 21007 | return false; 21008 | else if (symbol_exists(variable_name)) 21009 | return false; 21010 | 21011 | local_data().local_symbol_list_.push_back(value); 21012 | T& t = local_data().local_symbol_list_.back(); 21013 | 21014 | return add_variable(variable_name,t); 21015 | } 21016 | 21017 | #ifndef exprtk_disable_string_capabilities 21018 | inline bool create_stringvar(const std::string& stringvar_name, const std::string& value = std::string("")) 21019 | { 21020 | if (!valid()) 21021 | return false; 21022 | else if (!valid_symbol(stringvar_name)) 21023 | return false; 21024 | else if (symbol_exists(stringvar_name)) 21025 | return false; 21026 | 21027 | local_data().local_stringvar_list_.push_back(value); 21028 | std::string& s = local_data().local_stringvar_list_.back(); 21029 | 21030 | return add_stringvar(stringvar_name,s); 21031 | } 21032 | #endif 21033 | 21034 | inline bool add_variable(const std::string& variable_name, T& t, const bool is_constant = false) 21035 | { 21036 | if (!valid()) 21037 | return false; 21038 | else if (!valid_symbol(variable_name)) 21039 | return false; 21040 | else if (symbol_exists(variable_name)) 21041 | return false; 21042 | else 21043 | return local_data().variable_store.add(variable_name, t, is_constant); 21044 | } 21045 | 21046 | inline bool add_constant(const std::string& constant_name, const T& value) 21047 | { 21048 | if (!valid()) 21049 | return false; 21050 | else if (!valid_symbol(constant_name)) 21051 | return false; 21052 | else if (symbol_exists(constant_name)) 21053 | return false; 21054 | 21055 | local_data().local_symbol_list_.push_back(value); 21056 | T& t = local_data().local_symbol_list_.back(); 21057 | 21058 | return add_variable(constant_name, t, true); 21059 | } 21060 | 21061 | #ifndef exprtk_disable_string_capabilities 21062 | inline bool add_stringvar(const std::string& stringvar_name, std::string& s, const bool is_constant = false) 21063 | { 21064 | if (!valid()) 21065 | return false; 21066 | else if (!valid_symbol(stringvar_name)) 21067 | return false; 21068 | else if (symbol_exists(stringvar_name)) 21069 | return false; 21070 | else 21071 | return local_data().stringvar_store.add(stringvar_name, s, is_constant); 21072 | } 21073 | #endif 21074 | 21075 | inline bool add_function(const std::string& function_name, function_t& function) 21076 | { 21077 | if (!valid()) 21078 | return false; 21079 | else if (!valid_symbol(function_name)) 21080 | return false; 21081 | else if (symbol_exists(function_name)) 21082 | return false; 21083 | else 21084 | return local_data().function_store.add(function_name,function); 21085 | } 21086 | 21087 | inline bool add_function(const std::string& vararg_function_name, vararg_function_t& vararg_function) 21088 | { 21089 | if (!valid()) 21090 | return false; 21091 | else if (!valid_symbol(vararg_function_name)) 21092 | return false; 21093 | else if (symbol_exists(vararg_function_name)) 21094 | return false; 21095 | else 21096 | return local_data().vararg_function_store.add(vararg_function_name,vararg_function); 21097 | } 21098 | 21099 | inline bool add_function(const std::string& function_name, generic_function_t& function) 21100 | { 21101 | if (!valid()) 21102 | return false; 21103 | else if (!valid_symbol(function_name)) 21104 | return false; 21105 | else if (symbol_exists(function_name)) 21106 | return false; 21107 | else 21108 | { 21109 | switch (function.rtrn_type) 21110 | { 21111 | case generic_function_t::e_rtrn_scalar : 21112 | return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ? 21113 | local_data().generic_function_store.add(function_name,function) : false; 21114 | 21115 | case generic_function_t::e_rtrn_string : 21116 | return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ? 21117 | local_data().string_function_store.add(function_name,function) : false; 21118 | 21119 | case generic_function_t::e_rtrn_overload : 21120 | return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|:")) ? 21121 | local_data().overload_function_store.add(function_name,function) : false; 21122 | } 21123 | } 21124 | 21125 | return false; 21126 | } 21127 | 21128 | #define exprtk_define_freefunction(NN) \ 21129 | inline bool add_function(const std::string& function_name, ff##NN##_functor function) \ 21130 | { \ 21131 | if (!valid()) \ 21132 | { return false; } \ 21133 | if (!valid_symbol(function_name)) \ 21134 | { return false; } \ 21135 | if (symbol_exists(function_name)) \ 21136 | { return false; } \ 21137 | \ 21138 | exprtk::ifunction<T>* ifunc = new freefunc##NN(function); \ 21139 | \ 21140 | local_data().free_function_list_.push_back(ifunc); \ 21141 | \ 21142 | return add_function(function_name,(*local_data().free_function_list_.back())); \ 21143 | } \ 21144 | 21145 | exprtk_define_freefunction(00) exprtk_define_freefunction(01) 21146 | exprtk_define_freefunction(02) exprtk_define_freefunction(03) 21147 | exprtk_define_freefunction(04) exprtk_define_freefunction(05) 21148 | exprtk_define_freefunction(06) exprtk_define_freefunction(07) 21149 | exprtk_define_freefunction(08) exprtk_define_freefunction(09) 21150 | exprtk_define_freefunction(10) exprtk_define_freefunction(11) 21151 | exprtk_define_freefunction(12) exprtk_define_freefunction(13) 21152 | exprtk_define_freefunction(14) exprtk_define_freefunction(15) 21153 | 21154 | #undef exprtk_define_freefunction 21155 | 21156 | inline bool add_reserved_function(const std::string& function_name, function_t& function) 21157 | { 21158 | if (!valid()) 21159 | return false; 21160 | else if (!valid_symbol(function_name,false)) 21161 | return false; 21162 | else if (symbol_exists(function_name,false)) 21163 | return false; 21164 | else 21165 | return local_data().function_store.add(function_name,function); 21166 | } 21167 | 21168 | inline bool add_reserved_function(const std::string& vararg_function_name, vararg_function_t& vararg_function) 21169 | { 21170 | if (!valid()) 21171 | return false; 21172 | else if (!valid_symbol(vararg_function_name,false)) 21173 | return false; 21174 | else if (symbol_exists(vararg_function_name,false)) 21175 | return false; 21176 | else 21177 | return local_data().vararg_function_store.add(vararg_function_name,vararg_function); 21178 | } 21179 | 21180 | inline bool add_reserved_function(const std::string& function_name, generic_function_t& function) 21181 | { 21182 | if (!valid()) 21183 | return false; 21184 | else if (!valid_symbol(function_name,false)) 21185 | return false; 21186 | else if (symbol_exists(function_name,false)) 21187 | return false; 21188 | else 21189 | { 21190 | switch (function.rtrn_type) 21191 | { 21192 | case generic_function_t::e_rtrn_scalar : 21193 | return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ? 21194 | local_data().generic_function_store.add(function_name,function) : false; 21195 | 21196 | case generic_function_t::e_rtrn_string : 21197 | return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ? 21198 | local_data().string_function_store.add(function_name,function) : false; 21199 | 21200 | case generic_function_t::e_rtrn_overload : 21201 | return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|:")) ? 21202 | local_data().overload_function_store.add(function_name,function) : false; 21203 | } 21204 | } 21205 | 21206 | return false; 21207 | } 21208 | 21209 | #define exprtk_define_reserved_function(NN) \ 21210 | inline bool add_reserved_function(const std::string& function_name, ff##NN##_functor function) \ 21211 | { \ 21212 | if (!valid()) \ 21213 | { return false; } \ 21214 | if (!valid_symbol(function_name,false)) \ 21215 | { return false; } \ 21216 | if (symbol_exists(function_name,false)) \ 21217 | { return false; } \ 21218 | \ 21219 | exprtk::ifunction<T>* ifunc = new freefunc##NN(function); \ 21220 | \ 21221 | local_data().free_function_list_.push_back(ifunc); \ 21222 | \ 21223 | return add_reserved_function(function_name,(*local_data().free_function_list_.back())); \ 21224 | } \ 21225 | 21226 | exprtk_define_reserved_function(00) exprtk_define_reserved_function(01) 21227 | exprtk_define_reserved_function(02) exprtk_define_reserved_function(03) 21228 | exprtk_define_reserved_function(04) exprtk_define_reserved_function(05) 21229 | exprtk_define_reserved_function(06) exprtk_define_reserved_function(07) 21230 | exprtk_define_reserved_function(08) exprtk_define_reserved_function(09) 21231 | exprtk_define_reserved_function(10) exprtk_define_reserved_function(11) 21232 | exprtk_define_reserved_function(12) exprtk_define_reserved_function(13) 21233 | exprtk_define_reserved_function(14) exprtk_define_reserved_function(15) 21234 | 21235 | #undef exprtk_define_reserved_function 21236 | 21237 | template <std::size_t N> 21238 | inline bool add_vector(const std::string& vector_name, T (&v)[N]) 21239 | { 21240 | if (!valid()) 21241 | return false; 21242 | else if (!valid_symbol(vector_name)) 21243 | return false; 21244 | else if (symbol_exists(vector_name)) 21245 | return false; 21246 | else 21247 | return local_data().vector_store.add(vector_name,v); 21248 | } 21249 | 21250 | inline bool add_vector(const std::string& vector_name, T* v, const std::size_t& v_size) 21251 | { 21252 | if (!valid()) 21253 | return false; 21254 | else if (!valid_symbol(vector_name)) 21255 | return false; 21256 | else if (symbol_exists(vector_name)) 21257 | return false; 21258 | else if (0 == v_size) 21259 | return false; 21260 | else 21261 | return local_data().vector_store.add(vector_name, v, v_size); 21262 | } 21263 | 21264 | template <typename Allocator> 21265 | inline bool add_vector(const std::string& vector_name, std::vector<T,Allocator>& v) 21266 | { 21267 | if (!valid()) 21268 | return false; 21269 | else if (!valid_symbol(vector_name)) 21270 | return false; 21271 | else if (symbol_exists(vector_name)) 21272 | return false; 21273 | else if (0 == v.size()) 21274 | return false; 21275 | else 21276 | return local_data().vector_store.add(vector_name,v); 21277 | } 21278 | 21279 | inline bool add_vector(const std::string& vector_name, exprtk::vector_view<T>& v) 21280 | { 21281 | if (!valid()) 21282 | return false; 21283 | else if (!valid_symbol(vector_name)) 21284 | return false; 21285 | else if (symbol_exists(vector_name)) 21286 | return false; 21287 | else if (0 == v.size()) 21288 | return false; 21289 | else 21290 | return local_data().vector_store.add(vector_name,v); 21291 | } 21292 | 21293 | inline bool remove_variable(const std::string& variable_name, const bool delete_node = true) 21294 | { 21295 | if (!valid()) 21296 | return false; 21297 | else 21298 | return local_data().variable_store.remove(variable_name, delete_node); 21299 | } 21300 | 21301 | #ifndef exprtk_disable_string_capabilities 21302 | inline bool remove_stringvar(const std::string& string_name) 21303 | { 21304 | if (!valid()) 21305 | return false; 21306 | else 21307 | return local_data().stringvar_store.remove(string_name); 21308 | } 21309 | #endif 21310 | 21311 | inline bool remove_function(const std::string& function_name) 21312 | { 21313 | if (!valid()) 21314 | return false; 21315 | else 21316 | return local_data().function_store.remove(function_name); 21317 | } 21318 | 21319 | inline bool remove_vararg_function(const std::string& vararg_function_name) 21320 | { 21321 | if (!valid()) 21322 | return false; 21323 | else 21324 | return local_data().vararg_function_store.remove(vararg_function_name); 21325 | } 21326 | 21327 | inline bool remove_vector(const std::string& vector_name) 21328 | { 21329 | if (!valid()) 21330 | return false; 21331 | else 21332 | return local_data().vector_store.remove(vector_name); 21333 | } 21334 | 21335 | inline bool add_constants() 21336 | { 21337 | return add_pi () && 21338 | add_epsilon () && 21339 | add_infinity() ; 21340 | } 21341 | 21342 | inline bool add_pi() 21343 | { 21344 | const typename details::numeric::details::number_type<T>::type num_type; 21345 | static const T local_pi = details::numeric::details::const_pi_impl<T>(num_type); 21346 | return add_constant("pi",local_pi); 21347 | } 21348 | 21349 | inline bool add_epsilon() 21350 | { 21351 | static const T local_epsilon = details::numeric::details::epsilon_type<T>::value(); 21352 | return add_constant("epsilon",local_epsilon); 21353 | } 21354 | 21355 | inline bool add_infinity() 21356 | { 21357 | static const T local_infinity = std::numeric_limits<T>::infinity(); 21358 | return add_constant("inf",local_infinity); 21359 | } 21360 | 21361 | template <typename Package> 21362 | inline bool add_package(Package& package) 21363 | { 21364 | return package.register_package(*this); 21365 | } 21366 | 21367 | template <typename Allocator, 21368 | template <typename, typename> class Sequence> 21369 | inline std::size_t get_variable_list(Sequence<std::pair<std::string,T>,Allocator>& vlist) const 21370 | { 21371 | if (!valid()) 21372 | return 0; 21373 | else 21374 | return local_data().variable_store.get_list(vlist); 21375 | } 21376 | 21377 | template <typename Allocator, 21378 | template <typename, typename> class Sequence> 21379 | inline std::size_t get_variable_list(Sequence<std::string,Allocator>& vlist) const 21380 | { 21381 | if (!valid()) 21382 | return 0; 21383 | else 21384 | return local_data().variable_store.get_list(vlist); 21385 | } 21386 | 21387 | #ifndef exprtk_disable_string_capabilities 21388 | template <typename Allocator, 21389 | template <typename, typename> class Sequence> 21390 | inline std::size_t get_stringvar_list(Sequence<std::pair<std::string,std::string>,Allocator>& svlist) const 21391 | { 21392 | if (!valid()) 21393 | return 0; 21394 | else 21395 | return local_data().stringvar_store.get_list(svlist); 21396 | } 21397 | 21398 | template <typename Allocator, 21399 | template <typename, typename> class Sequence> 21400 | inline std::size_t get_stringvar_list(Sequence<std::string,Allocator>& svlist) const 21401 | { 21402 | if (!valid()) 21403 | return 0; 21404 | else 21405 | return local_data().stringvar_store.get_list(svlist); 21406 | } 21407 | #endif 21408 | 21409 | template <typename Allocator, 21410 | template <typename, typename> class Sequence> 21411 | inline std::size_t get_vector_list(Sequence<std::string,Allocator>& vec_list) const 21412 | { 21413 | if (!valid()) 21414 | return 0; 21415 | else 21416 | return local_data().vector_store.get_list(vec_list); 21417 | } 21418 | 21419 | template <typename Allocator, 21420 | template <typename, typename> class Sequence> 21421 | inline std::size_t get_function_list(Sequence<std::string,Allocator>& function_list) const 21422 | { 21423 | if (!valid()) 21424 | return 0; 21425 | 21426 | std::vector<std::string> function_names; 21427 | std::size_t count = 0; 21428 | 21429 | count += local_data().function_store .get_list(function_names); 21430 | count += local_data().vararg_function_store .get_list(function_names); 21431 | count += local_data().generic_function_store .get_list(function_names); 21432 | count += local_data().string_function_store .get_list(function_names); 21433 | count += local_data().overload_function_store.get_list(function_names); 21434 | 21435 | std::set<std::string> function_set; 21436 | 21437 | for (std::size_t i = 0; i < function_names.size(); ++i) 21438 | { 21439 | function_set.insert(function_names[i]); 21440 | } 21441 | 21442 | std::copy(function_set.begin(), function_set.end(), 21443 | std::back_inserter(function_list)); 21444 | 21445 | return count; 21446 | } 21447 | 21448 | inline std::vector<std::string> get_function_list() const 21449 | { 21450 | std::vector<std::string> result; 21451 | get_function_list(result); 21452 | return result; 21453 | } 21454 | 21455 | inline bool symbol_exists(const std::string& symbol_name, const bool check_reserved_symb = true) const 21456 | { 21457 | /* 21458 | Function will return true if symbol_name exists as either a 21459 | reserved symbol, variable, stringvar, vector or function name 21460 | in any of the type stores. 21461 | */ 21462 | if (!valid()) 21463 | return false; 21464 | else if (local_data().variable_store.symbol_exists(symbol_name)) 21465 | return true; 21466 | #ifndef exprtk_disable_string_capabilities 21467 | else if (local_data().stringvar_store.symbol_exists(symbol_name)) 21468 | return true; 21469 | #endif 21470 | else if (local_data().vector_store.symbol_exists(symbol_name)) 21471 | return true; 21472 | else if (local_data().function_store.symbol_exists(symbol_name)) 21473 | return true; 21474 | else if (check_reserved_symb && local_data().is_reserved_symbol(symbol_name)) 21475 | return true; 21476 | else 21477 | return false; 21478 | } 21479 | 21480 | inline bool is_variable(const std::string& variable_name) const 21481 | { 21482 | if (!valid()) 21483 | return false; 21484 | else 21485 | return local_data().variable_store.symbol_exists(variable_name); 21486 | } 21487 | 21488 | #ifndef exprtk_disable_string_capabilities 21489 | inline bool is_stringvar(const std::string& stringvar_name) const 21490 | { 21491 | if (!valid()) 21492 | return false; 21493 | else 21494 | return local_data().stringvar_store.symbol_exists(stringvar_name); 21495 | } 21496 | 21497 | inline bool is_conststr_stringvar(const std::string& symbol_name) const 21498 | { 21499 | if (!valid()) 21500 | return false; 21501 | else if (!valid_symbol(symbol_name)) 21502 | return false; 21503 | else if (!local_data().stringvar_store.symbol_exists(symbol_name)) 21504 | return false; 21505 | 21506 | return ( 21507 | local_data().stringvar_store.symbol_exists(symbol_name) || 21508 | local_data().stringvar_store.is_constant (symbol_name) 21509 | ); 21510 | } 21511 | #endif 21512 | 21513 | inline bool is_function(const std::string& function_name) const 21514 | { 21515 | if (!valid()) 21516 | return false; 21517 | else 21518 | return local_data().function_store.symbol_exists(function_name); 21519 | } 21520 | 21521 | inline bool is_vararg_function(const std::string& vararg_function_name) const 21522 | { 21523 | if (!valid()) 21524 | return false; 21525 | else 21526 | return local_data().vararg_function_store.symbol_exists(vararg_function_name); 21527 | } 21528 | 21529 | inline bool is_vector(const std::string& vector_name) const 21530 | { 21531 | if (!valid()) 21532 | return false; 21533 | else 21534 | return local_data().vector_store.symbol_exists(vector_name); 21535 | } 21536 | 21537 | inline std::string get_variable_name(const expression_ptr& ptr) const 21538 | { 21539 | return local_data().variable_store.entity_name(ptr); 21540 | } 21541 | 21542 | inline std::string get_vector_name(const vector_holder_ptr& ptr) const 21543 | { 21544 | return local_data().vector_store.entity_name(ptr); 21545 | } 21546 | 21547 | #ifndef exprtk_disable_string_capabilities 21548 | inline std::string get_stringvar_name(const expression_ptr& ptr) const 21549 | { 21550 | return local_data().stringvar_store.entity_name(ptr); 21551 | } 21552 | 21553 | inline std::string get_conststr_stringvar_name(const expression_ptr& ptr) const 21554 | { 21555 | return local_data().stringvar_store.entity_name(ptr); 21556 | } 21557 | #endif 21558 | 21559 | inline bool valid() const 21560 | { 21561 | // Symbol table sanity check. 21562 | return control_block_ && control_block_->data_; 21563 | } 21564 | 21565 | inline void load_from(const symbol_table<T>& st) 21566 | { 21567 | { 21568 | std::vector<std::string> name_list; 21569 | 21570 | st.local_data().function_store.get_list(name_list); 21571 | 21572 | if (!name_list.empty()) 21573 | { 21574 | for (std::size_t i = 0; i < name_list.size(); ++i) 21575 | { 21576 | exprtk::ifunction<T>& ifunc = *st.get_function(name_list[i]); 21577 | add_function(name_list[i],ifunc); 21578 | } 21579 | } 21580 | } 21581 | 21582 | { 21583 | std::vector<std::string> name_list; 21584 | 21585 | st.local_data().vararg_function_store.get_list(name_list); 21586 | 21587 | if (!name_list.empty()) 21588 | { 21589 | for (std::size_t i = 0; i < name_list.size(); ++i) 21590 | { 21591 | exprtk::ivararg_function<T>& ivafunc = *st.get_vararg_function(name_list[i]); 21592 | add_function(name_list[i],ivafunc); 21593 | } 21594 | } 21595 | } 21596 | 21597 | { 21598 | std::vector<std::string> name_list; 21599 | 21600 | st.local_data().generic_function_store.get_list(name_list); 21601 | 21602 | if (!name_list.empty()) 21603 | { 21604 | for (std::size_t i = 0; i < name_list.size(); ++i) 21605 | { 21606 | exprtk::igeneric_function<T>& ifunc = *st.get_generic_function(name_list[i]); 21607 | add_function(name_list[i],ifunc); 21608 | } 21609 | } 21610 | } 21611 | 21612 | { 21613 | std::vector<std::string> name_list; 21614 | 21615 | st.local_data().string_function_store.get_list(name_list); 21616 | 21617 | if (!name_list.empty()) 21618 | { 21619 | for (std::size_t i = 0; i < name_list.size(); ++i) 21620 | { 21621 | exprtk::igeneric_function<T>& ifunc = *st.get_string_function(name_list[i]); 21622 | add_function(name_list[i],ifunc); 21623 | } 21624 | } 21625 | } 21626 | 21627 | { 21628 | std::vector<std::string> name_list; 21629 | 21630 | st.local_data().overload_function_store.get_list(name_list); 21631 | 21632 | if (!name_list.empty()) 21633 | { 21634 | for (std::size_t i = 0; i < name_list.size(); ++i) 21635 | { 21636 | exprtk::igeneric_function<T>& ifunc = *st.get_overload_function(name_list[i]); 21637 | add_function(name_list[i],ifunc); 21638 | } 21639 | } 21640 | } 21641 | } 21642 | 21643 | inline void load_variables_from(const symbol_table<T>& st) 21644 | { 21645 | std::vector<std::string> name_list; 21646 | 21647 | st.local_data().variable_store.get_list(name_list); 21648 | 21649 | if (!name_list.empty()) 21650 | { 21651 | for (std::size_t i = 0; i < name_list.size(); ++i) 21652 | { 21653 | T& variable = st.get_variable(name_list[i])->ref(); 21654 | add_variable(name_list[i], variable); 21655 | } 21656 | } 21657 | } 21658 | 21659 | inline void load_vectors_from(const symbol_table<T>& st) 21660 | { 21661 | std::vector<std::string> name_list; 21662 | 21663 | st.local_data().vector_store.get_list(name_list); 21664 | 21665 | if (!name_list.empty()) 21666 | { 21667 | for (std::size_t i = 0; i < name_list.size(); ++i) 21668 | { 21669 | vector_holder_t& vecholder = *st.get_vector(name_list[i]); 21670 | add_vector(name_list[i], vecholder.data(), vecholder.size()); 21671 | } 21672 | } 21673 | } 21674 | 21675 | private: 21676 | 21677 | inline bool valid_symbol(const std::string& symbol, const bool check_reserved_symb = true) const 21678 | { 21679 | if (symbol.empty()) 21680 | return false; 21681 | else if (!details::is_letter(symbol[0])) 21682 | return false; 21683 | else if (symbol.size() > 1) 21684 | { 21685 | for (std::size_t i = 1; i < symbol.size(); ++i) 21686 | { 21687 | if ( 21688 | !details::is_letter_or_digit(symbol[i]) && 21689 | ('_' != symbol[i]) 21690 | ) 21691 | { 21692 | if ((i < (symbol.size() - 1)) && ('.' == symbol[i])) 21693 | continue; 21694 | else 21695 | return false; 21696 | } 21697 | } 21698 | } 21699 | 21700 | return (check_reserved_symb) ? (!local_data().is_reserved_symbol(symbol)) : true; 21701 | } 21702 | 21703 | inline bool valid_function(const std::string& symbol) const 21704 | { 21705 | if (symbol.empty()) 21706 | return false; 21707 | else if (!details::is_letter(symbol[0])) 21708 | return false; 21709 | else if (symbol.size() > 1) 21710 | { 21711 | for (std::size_t i = 1; i < symbol.size(); ++i) 21712 | { 21713 | if ( 21714 | !details::is_letter_or_digit(symbol[i]) && 21715 | ('_' != symbol[i]) 21716 | ) 21717 | { 21718 | if ((i < (symbol.size() - 1)) && ('.' == symbol[i])) 21719 | continue; 21720 | else 21721 | return false; 21722 | } 21723 | } 21724 | } 21725 | 21726 | return true; 21727 | } 21728 | 21729 | typedef typename control_block::st_data local_data_t; 21730 | 21731 | inline local_data_t& local_data() 21732 | { 21733 | return *(control_block_->data_); 21734 | } 21735 | 21736 | inline const local_data_t& local_data() const 21737 | { 21738 | return *(control_block_->data_); 21739 | } 21740 | 21741 | control_block* control_block_; 21742 | 21743 | friend class parser<T>; 21744 | }; // class symbol_table 21745 | 21746 | template <typename T> 21747 | class function_compositor; 21748 | 21749 | template <typename T> 21750 | class expression 21751 | { 21752 | private: 21753 | 21754 | typedef details::expression_node<T>* expression_ptr; 21755 | typedef details::vector_holder<T>* vector_holder_ptr; 21756 | typedef std::vector<symbol_table<T> > symtab_list_t; 21757 | 21758 | struct control_block 21759 | { 21760 | enum data_type 21761 | { 21762 | e_unknown , 21763 | e_expr , 21764 | e_vecholder, 21765 | e_data , 21766 | e_vecdata , 21767 | e_string 21768 | }; 21769 | 21770 | static std::string to_str(data_type dt) 21771 | { 21772 | switch (dt) 21773 | { 21774 | case e_unknown : return "e_unknown " 21775 | case e_expr : return "e_expr" ; 21776 | case e_vecholder : return "e_vecholder" 21777 | case e_data : return "e_data" ; 21778 | case e_vecdata : return "e_vecdata" ; 21779 | case e_string : return "e_string" ; 21780 | } 21781 | 21782 | return "" 21783 | } 21784 | 21785 | struct data_pack 21786 | { 21787 | data_pack() 21788 | : pointer(0) 21789 | , type(e_unknown) 21790 | , size(0) 21791 | {} 21792 | 21793 | data_pack(void* ptr, const data_type dt, const std::size_t sz = 0) 21794 | : pointer(ptr) 21795 | , type(dt) 21796 | , size(sz) 21797 | {} 21798 | 21799 | void* pointer; 21800 | data_type type; 21801 | std::size_t size; 21802 | }; 21803 | 21804 | typedef std::vector<data_pack> local_data_list_t; 21805 | typedef results_context<T> results_context_t; 21806 | typedef control_block* cntrl_blck_ptr_t; 21807 | 21808 | control_block() 21809 | : ref_count(0) 21810 | , expr (0) 21811 | , results (0) 21812 | , retinv_null(false) 21813 | , return_invoked(&retinv_null) 21814 | {} 21815 | 21816 | explicit control_block(expression_ptr e) 21817 | : ref_count(1) 21818 | , expr (e) 21819 | , results (0) 21820 | , retinv_null(false) 21821 | , return_invoked(&retinv_null) 21822 | {} 21823 | 21824 | ~control_block() 21825 | { 21826 | if (expr && details::branch_deletable(expr)) 21827 | { 21828 | destroy_node(expr); 21829 | } 21830 | 21831 | if (!local_data_list.empty()) 21832 | { 21833 | for (std::size_t i = 0; i < local_data_list.size(); ++i) 21834 | { 21835 | switch (local_data_list[i].type) 21836 | { 21837 | case e_expr : delete reinterpret_cast<expression_ptr>(local_data_list[i].pointer); 21838 | break; 21839 | 21840 | case e_vecholder : delete reinterpret_cast<vector_holder_ptr>(local_data_list[i].pointer); 21841 | break; 21842 | 21843 | case e_data : delete reinterpret_cast<T*>(local_data_list[i].pointer); 21844 | break; 21845 | 21846 | case e_vecdata : delete [] reinterpret_cast<T*>(local_data_list[i].pointer); 21847 | break; 21848 | 21849 | case e_string : delete reinterpret_cast<std::string*>(local_data_list[i].pointer); 21850 | break; 21851 | 21852 | default : break; 21853 | } 21854 | } 21855 | } 21856 | 21857 | if (results) 21858 | { 21859 | delete results; 21860 | } 21861 | } 21862 | 21863 | static inline cntrl_blck_ptr_t create(expression_ptr e) 21864 | { 21865 | return new control_block(e); 21866 | } 21867 | 21868 | static inline void destroy(cntrl_blck_ptr_t& cntrl_blck) 21869 | { 21870 | if (cntrl_blck) 21871 | { 21872 | if ( 21873 | (0 != cntrl_blck->ref_count) && 21874 | (0 == --cntrl_blck->ref_count) 21875 | ) 21876 | { 21877 | delete cntrl_blck; 21878 | } 21879 | 21880 | cntrl_blck = 0; 21881 | } 21882 | } 21883 | 21884 | std::size_t ref_count; 21885 | expression_ptr expr; 21886 | local_data_list_t local_data_list; 21887 | results_context_t* results; 21888 | bool retinv_null; 21889 | bool* return_invoked; 21890 | 21891 | friend class function_compositor<T>; 21892 | }; 21893 | 21894 | public: 21895 | 21896 | expression() 21897 | : control_block_(0) 21898 | { 21899 | set_expression(new details::null_node<T>()); 21900 | } 21901 | 21902 | expression(const expression<T>& e) 21903 | : control_block_ (e.control_block_ ) 21904 | , symbol_table_list_(e.symbol_table_list_) 21905 | { 21906 | control_block_->ref_count++; 21907 | } 21908 | 21909 | explicit expression(const symbol_table<T>& symbol_table) 21910 | : control_block_(0) 21911 | { 21912 | set_expression(new details::null_node<T>()); 21913 | symbol_table_list_.push_back(symbol_table); 21914 | } 21915 | 21916 | inline expression<T>& operator=(const expression<T>& e) 21917 | { 21918 | if (this != &e) 21919 | { 21920 | if (control_block_) 21921 | { 21922 | if ( 21923 | (0 != control_block_->ref_count) && 21924 | (0 == --control_block_->ref_count) 21925 | ) 21926 | { 21927 | delete control_block_; 21928 | } 21929 | 21930 | control_block_ = 0; 21931 | } 21932 | 21933 | control_block_ = e.control_block_; 21934 | control_block_->ref_count++; 21935 | symbol_table_list_ = e.symbol_table_list_; 21936 | } 21937 | 21938 | return *this; 21939 | } 21940 | 21941 | inline bool operator==(const expression<T>& e) const 21942 | { 21943 | return (this == &e); 21944 | } 21945 | 21946 | inline bool operator!() const 21947 | { 21948 | return ( 21949 | (0 == control_block_ ) || 21950 | (0 == control_block_->expr) 21951 | ); 21952 | } 21953 | 21954 | inline expression<T>& release() 21955 | { 21956 | exprtk::details::dump_ptr("expression::release", this); 21957 | control_block::destroy(control_block_); 21958 | 21959 | return (*this); 21960 | } 21961 | 21962 | ~expression() 21963 | { 21964 | control_block::destroy(control_block_); 21965 | } 21966 | 21967 | inline T value() const 21968 | { 21969 | assert(control_block_ ); 21970 | assert(control_block_->expr); 21971 | 21972 | return control_block_->expr->value(); 21973 | } 21974 | 21975 | inline T operator() () const 21976 | { 21977 | return value(); 21978 | } 21979 | 21980 | inline operator T() const 21981 | { 21982 | return value(); 21983 | } 21984 | 21985 | inline operator bool() const 21986 | { 21987 | return details::is_true(value()); 21988 | } 21989 | 21990 | inline bool register_symbol_table(symbol_table<T>& st) 21991 | { 21992 | for (std::size_t i = 0; i < symbol_table_list_.size(); ++i) 21993 | { 21994 | if (st == symbol_table_list_[i]) 21995 | { 21996 | return false; 21997 | } 21998 | } 21999 | 22000 | symbol_table_list_.push_back(st); 22001 | return true; 22002 | } 22003 | 22004 | inline const symbol_table<T>& get_symbol_table(const std::size_t& index = 0) const 22005 | { 22006 | return symbol_table_list_[index]; 22007 | } 22008 | 22009 | inline symbol_table<T>& get_symbol_table(const std::size_t& index = 0) 22010 | { 22011 | return symbol_table_list_[index]; 22012 | } 22013 | 22014 | std::size_t num_symbol_tables() const 22015 | { 22016 | return symbol_table_list_.size(); 22017 | } 22018 | 22019 | typedef results_context<T> results_context_t; 22020 | 22021 | inline const results_context_t& results() const 22022 | { 22023 | if (control_block_->results) 22024 | return (*control_block_->results); 22025 | else 22026 | { 22027 | static const results_context_t null_results; 22028 | return null_results; 22029 | } 22030 | } 22031 | 22032 | inline bool return_invoked() const 22033 | { 22034 | return (*control_block_->return_invoked); 22035 | } 22036 | 22037 | private: 22038 | 22039 | inline symtab_list_t get_symbol_table_list() const 22040 | { 22041 | return symbol_table_list_; 22042 | } 22043 | 22044 | inline void set_expression(const expression_ptr expr) 22045 | { 22046 | if (expr) 22047 | { 22048 | if (control_block_) 22049 | { 22050 | if (0 == --control_block_->ref_count) 22051 | { 22052 | delete control_block_; 22053 | } 22054 | } 22055 | 22056 | control_block_ = control_block::create(expr); 22057 | } 22058 | } 22059 | 22060 | inline void register_local_var(expression_ptr expr) 22061 | { 22062 | if (expr) 22063 | { 22064 | if (control_block_) 22065 | { 22066 | control_block_-> 22067 | local_data_list.push_back( 22068 | typename expression<T>::control_block:: 22069 | data_pack(reinterpret_cast<void*>(expr), 22070 | control_block::e_expr)); 22071 | } 22072 | } 22073 | } 22074 | 22075 | inline void register_local_var(vector_holder_ptr vec_holder) 22076 | { 22077 | if (vec_holder) 22078 | { 22079 | if (control_block_) 22080 | { 22081 | control_block_-> 22082 | local_data_list.push_back( 22083 | typename expression<T>::control_block:: 22084 | data_pack(reinterpret_cast<void*>(vec_holder), 22085 | control_block::e_vecholder)); 22086 | } 22087 | } 22088 | } 22089 | 22090 | inline void register_local_data(void* data, const std::size_t& size = 0, const std::size_t data_mode = 0) 22091 | { 22092 | if (data) 22093 | { 22094 | if (control_block_) 22095 | { 22096 | typename control_block::data_type dt = control_block::e_data; 22097 | 22098 | switch (data_mode) 22099 | { 22100 | case 0 : dt = control_block::e_data; break; 22101 | case 1 : dt = control_block::e_vecdata; break; 22102 | case 2 : dt = control_block::e_string; break; 22103 | } 22104 | 22105 | control_block_-> 22106 | local_data_list.push_back( 22107 | typename expression<T>::control_block:: 22108 | data_pack(reinterpret_cast<void*>(data), dt, size)); 22109 | } 22110 | } 22111 | } 22112 | 22113 | inline const typename control_block::local_data_list_t& local_data_list() 22114 | { 22115 | if (control_block_) 22116 | { 22117 | return control_block_->local_data_list; 22118 | } 22119 | else 22120 | { 22121 | static typename control_block::local_data_list_t null_local_data_list; 22122 | return null_local_data_list; 22123 | } 22124 | } 22125 | 22126 | inline void register_return_results(results_context_t* rc) 22127 | { 22128 | if (control_block_ && rc) 22129 | { 22130 | control_block_->results = rc; 22131 | } 22132 | } 22133 | 22134 | inline void set_retinvk(bool* retinvk_ptr) 22135 | { 22136 | if (control_block_) 22137 | { 22138 | control_block_->return_invoked = retinvk_ptr; 22139 | } 22140 | } 22141 | 22142 | control_block* control_block_; 22143 | symtab_list_t symbol_table_list_; 22144 | 22145 | friend class parser<T>; 22146 | friend class expression_helper<T>; 22147 | friend class function_compositor<T>; 22148 | template <typename TT> 22149 | friend bool is_valid(const expression<TT>& expr); 22150 | }; // class expression 22151 | 22152 | template <typename T> 22153 | class expression_helper 22154 | { 22155 | public: 22156 | 22157 | enum node_types 22158 | { 22159 | e_literal, 22160 | e_variable, 22161 | e_string, 22162 | e_unary, 22163 | e_binary, 22164 | e_function, 22165 | e_vararg, 22166 | e_null, 22167 | e_assert, 22168 | e_sf3ext, 22169 | e_sf4ext 22170 | }; 22171 | 22172 | static inline bool is_literal(const expression<T>& expr) 22173 | { 22174 | return expr.control_block_ && details::is_literal_node(expr.control_block_->expr); 22175 | } 22176 | 22177 | static inline bool is_variable(const expression<T>& expr) 22178 | { 22179 | return expr.control_block_ && details::is_variable_node(expr.control_block_->expr); 22180 | } 22181 | 22182 | static inline bool is_string(const expression<T>& expr) 22183 | { 22184 | return expr.control_block_ && details::is_generally_string_node(expr.control_block_->expr); 22185 | } 22186 | 22187 | static inline bool is_unary(const expression<T>& expr) 22188 | { 22189 | return expr.control_block_ && details::is_unary_node(expr.control_block_->expr); 22190 | } 22191 | 22192 | static inline bool is_binary(const expression<T>& expr) 22193 | { 22194 | return expr.control_block_ && details::is_binary_node(expr.control_block_->expr); 22195 | } 22196 | 22197 | static inline bool is_function(const expression<T>& expr) 22198 | { 22199 | return expr.control_block_ && details::is_function(expr.control_block_->expr); 22200 | } 22201 | 22202 | static inline bool is_vararg(const expression<T>& expr) 22203 | { 22204 | return expr.control_block_ && details::is_vararg_node(expr.control_block_->expr); 22205 | } 22206 | 22207 | static inline bool is_null(const expression<T>& expr) 22208 | { 22209 | return expr.control_block_ && details::is_null_node(expr.control_block_->expr); 22210 | } 22211 | 22212 | static inline bool is_assert(const expression<T>& expr) 22213 | { 22214 | return expr.control_block_ && details::is_assert_node(expr.control_block_->expr); 22215 | } 22216 | 22217 | static inline bool is_sf3ext(const expression<T>& expr) 22218 | { 22219 | return expr.control_block_ && details::is_sf3ext_node(expr.control_block_->expr); 22220 | } 22221 | 22222 | static inline bool is_sf4ext(const expression<T>& expr) 22223 | { 22224 | return expr.control_block_ && details::is_sf4ext_node(expr.control_block_->expr); 22225 | } 22226 | 22227 | static inline bool is_type(const expression<T>& expr, const node_types node_type) 22228 | { 22229 | if (0 == expr.control_block_) 22230 | { 22231 | return false; 22232 | } 22233 | 22234 | switch (node_type) 22235 | { 22236 | case e_literal : return is_literal_node(expr); 22237 | case e_variable : return is_variable (expr); 22238 | case e_string : return is_string (expr); 22239 | case e_unary : return is_unary (expr); 22240 | case e_binary : return is_binary (expr); 22241 | case e_function : return is_function (expr); 22242 | case e_null : return is_null (expr); 22243 | case e_assert : return is_assert (expr); 22244 | case e_sf3ext : return is_sf3ext (expr); 22245 | case e_sf4ext : return is_sf4ext (expr); 22246 | }; 22247 | 22248 | return false; 22249 | } 22250 | 22251 | static inline bool match_type_sequence(const expression<T>& expr, const std::vector<node_types>& type_seq) 22252 | { 22253 | if ((0 == expr.control_block_) || !is_vararg(expr)) 22254 | { 22255 | return false; 22256 | } 22257 | 22258 | typedef details::vararg_node<T, exprtk::details::vararg_multi_op<T> > mo_vararg_t; 22259 | 22260 | mo_vararg_t* vnode = dynamic_cast<mo_vararg_t*>(expr.control_block_->expr); 22261 | 22262 | if ( 22263 | (0 == vnode) || 22264 | type_seq.empty() || 22265 | (vnode->size() < type_seq.size()) 22266 | ) 22267 | { 22268 | return false; 22269 | } 22270 | 22271 | for (std::size_t i = 0; i < type_seq.size(); ++i) 22272 | { 22273 | assert((*vnode)[i]); 22274 | 22275 | switch (type_seq[i]) 22276 | { 22277 | case e_literal : { if (details::is_literal_node ((*vnode)[i])) continue; } break; 22278 | case e_variable : { if (details::is_variable_node ((*vnode)[i])) continue; } break; 22279 | case e_string : { if (details::is_generally_string_node((*vnode)[i])) continue; } break; 22280 | case e_unary : { if (details::is_unary_node ((*vnode)[i])) continue; } break; 22281 | case e_binary : { if (details::is_binary_node ((*vnode)[i])) continue; } break; 22282 | case e_function : { if (details::is_function ((*vnode)[i])) continue; } break; 22283 | case e_null : { if (details::is_null_node ((*vnode)[i])) continue; } break; 22284 | case e_assert : { if (details::is_assert_node ((*vnode)[i])) continue; } break; 22285 | case e_sf3ext : { if (details::is_sf3ext_node ((*vnode)[i])) continue; } break; 22286 | case e_sf4ext : { if (details::is_sf4ext_node ((*vnode)[i])) continue; } break; 22287 | case e_vararg : break; 22288 | } 22289 | 22290 | return false; 22291 | } 22292 | 22293 | return true; 22294 | } 22295 | }; 22296 | 22297 | template <typename T> 22298 | inline bool is_valid(const expression<T>& expr) 22299 | { 22300 | return expr.control_block_ && !expression_helper<T>::is_null(expr); 22301 | } 22302 | 22303 | namespace parser_error 22304 | { 22305 | enum error_mode 22306 | { 22307 | e_unknown = 0, 22308 | e_syntax = 1, 22309 | e_token = 2, 22310 | e_numeric = 4, 22311 | e_symtab = 5, 22312 | e_lexer = 6, 22313 | e_synthesis = 7, 22314 | e_helper = 8, 22315 | e_parser = 9 22316 | }; 22317 | 22318 | struct type 22319 | { 22320 | type() 22321 | : mode(parser_error::e_unknown) 22322 | , line_no (0) 22323 | , column_no(0) 22324 | {} 22325 | 22326 | lexer::token token; 22327 | error_mode mode; 22328 | std::string diagnostic; 22329 | std::string src_location; 22330 | std::string error_line; 22331 | std::size_t line_no; 22332 | std::size_t column_no; 22333 | }; 22334 | 22335 | inline type make_error(const error_mode mode, 22336 | const std::string& diagnostic = "", 22337 | const std::string& src_location = "") 22338 | { 22339 | type t; 22340 | t.mode = mode; 22341 | t.token.type = lexer::token::e_error; 22342 | t.diagnostic = diagnostic; 22343 | t.src_location = src_location; 22344 | exprtk_debug(("%s\n", diagnostic .c_str())); 22345 | return t; 22346 | } 22347 | 22348 | inline type make_error(const error_mode mode, 22349 | const lexer::token& tk, 22350 | const std::string& diagnostic = "", 22351 | const std::string& src_location = "") 22352 | { 22353 | type t; 22354 | t.mode = mode; 22355 | t.token = tk; 22356 | t.diagnostic = diagnostic; 22357 | t.src_location = src_location; 22358 | exprtk_debug(("%s\n", diagnostic .c_str())); 22359 | return t; 22360 | } 22361 | 22362 | inline std::string to_str(error_mode mode) 22363 | { 22364 | switch (mode) 22365 | { 22366 | case e_unknown : return std::string("Unknown Error"); 22367 | case e_syntax : return std::string("Syntax Error" ); 22368 | case e_token : return std::string("Token Error" ); 22369 | case e_numeric : return std::string("Numeric Error"); 22370 | case e_symtab : return std::string("Symbol Error" ); 22371 | case e_lexer : return std::string("Lexer Error" ); 22372 | case e_helper : return std::string("Helper Error" ); 22373 | case e_parser : return std::string("Parser Error" ); 22374 | default : return std::string("Unknown Error"); 22375 | } 22376 | } 22377 | 22378 | inline bool update_error(type& error, const std::string& expression) 22379 | { 22380 | if ( 22381 | expression.empty() || 22382 | (error.token.position > expression.size()) || 22383 | (std::numeric_limits<std::size_t>::max() == error.token.position) 22384 | ) 22385 | { 22386 | return false; 22387 | } 22388 | 22389 | std::size_t error_line_start = 0; 22390 | 22391 | for (std::size_t i = error.token.position; i > 0; --i) 22392 | { 22393 | const details::char_t c = expression[i]; 22394 | 22395 | if (('\n' == c) || ('\r' == c)) 22396 | { 22397 | error_line_start = i + 1; 22398 | break; 22399 | } 22400 | } 22401 | 22402 | std::size_t next_nl_position = std::min(expression.size(), 22403 | expression.find_first_of('\n',error.token.position + 1)); 22404 | 22405 | error.column_no = error.token.position - error_line_start; 22406 | error.error_line = expression.substr(error_line_start, 22407 | next_nl_position - error_line_start); 22408 | 22409 | error.line_no = 0; 22410 | 22411 | for (std::size_t i = 0; i < next_nl_position; ++i) 22412 | { 22413 | if ('\n' == expression[i]) 22414 | ++error.line_no; 22415 | } 22416 | 22417 | return true; 22418 | } 22419 | 22420 | inline void dump_error(const type& error) 22421 | { 22422 | printf("Position: %02d Type: [%s] Msg: %s\n", 22423 | static_cast<int>(error.token.position), 22424 | exprtk::parser_error::to_str(error.mode).c_str(), 22425 | error.diagnostic.c_str()); 22426 | } 22427 | } 22428 | 22429 | namespace details 22430 | { 22431 | template <typename Parser> 22432 | inline void disable_type_checking(Parser& p) 22433 | { 22434 | p.state_.type_check_enabled = false; 22435 | } 22436 | } 22437 | 22438 | template <typename T> 22439 | class parser : public lexer::parser_helper 22440 | { 22441 | private: 22442 | 22443 | enum precedence_level 22444 | { 22445 | e_level00, e_level01, e_level02, e_level03, e_level04, 22446 | e_level05, e_level06, e_level07, e_level08, e_level09, 22447 | e_level10, e_level11, e_level12, e_level13, e_level14 22448 | }; 22449 | 22450 | typedef const T& cref_t; 22451 | typedef const T const_t; 22452 | typedef ifunction<T> F; 22453 | typedef ivararg_function<T> VAF; 22454 | typedef igeneric_function<T> GF; 22455 | typedef ifunction<T> ifunction_t; 22456 | typedef ivararg_function<T> ivararg_function_t; 22457 | typedef igeneric_function<T> igeneric_function_t; 22458 | typedef details::expression_node<T> expression_node_t; 22459 | typedef details::literal_node<T> literal_node_t; 22460 | typedef details::unary_node<T> unary_node_t; 22461 | typedef details::binary_node<T> binary_node_t; 22462 | typedef details::trinary_node<T> trinary_node_t; 22463 | typedef details::quaternary_node<T> quaternary_node_t; 22464 | typedef details::conditional_node<T> conditional_node_t; 22465 | typedef details::cons_conditional_node<T> cons_conditional_node_t; 22466 | typedef details::while_loop_node<T> while_loop_node_t; 22467 | typedef details::repeat_until_loop_node<T> repeat_until_loop_node_t; 22468 | typedef details::for_loop_node<T> for_loop_node_t; 22469 | typedef details::while_loop_rtc_node<T> while_loop_rtc_node_t; 22470 | typedef details::repeat_until_loop_rtc_node<T> repeat_until_loop_rtc_node_t; 22471 | typedef details::for_loop_rtc_node<T> for_loop_rtc_node_t; 22472 | #ifndef exprtk_disable_break_continue 22473 | typedef details::while_loop_bc_node<T> while_loop_bc_node_t; 22474 | typedef details::repeat_until_loop_bc_node<T> repeat_until_loop_bc_node_t; 22475 | typedef details::for_loop_bc_node<T> for_loop_bc_node_t; 22476 | typedef details::while_loop_bc_rtc_node<T> while_loop_bc_rtc_node_t; 22477 | typedef details::repeat_until_loop_bc_rtc_node<T> repeat_until_loop_bc_rtc_node_t; 22478 | typedef details::for_loop_bc_rtc_node<T> for_loop_bc_rtc_node_t; 22479 | #endif 22480 | typedef details::switch_node<T> switch_node_t; 22481 | typedef details::variable_node<T> variable_node_t; 22482 | typedef details::vector_elem_node<T> vector_elem_node_t; 22483 | typedef details::vector_celem_node<T> vector_celem_node_t; 22484 | typedef details::vector_elem_rtc_node<T> vector_elem_rtc_node_t; 22485 | typedef details::vector_celem_rtc_node<T> vector_celem_rtc_node_t; 22486 | typedef details::rebasevector_elem_node<T> rebasevector_elem_node_t; 22487 | typedef details::rebasevector_celem_node<T> rebasevector_celem_node_t; 22488 | typedef details::rebasevector_elem_rtc_node<T> rebasevector_elem_rtc_node_t; 22489 | typedef details::rebasevector_celem_rtc_node<T> rebasevector_celem_rtc_node_t; 22490 | typedef details::vector_node<T> vector_node_t; 22491 | typedef details::vector_size_node<T> vector_size_node_t; 22492 | typedef details::range_pack<T> range_t; 22493 | #ifndef exprtk_disable_string_capabilities 22494 | typedef details::stringvar_node<T> stringvar_node_t; 22495 | typedef details::string_literal_node<T> string_literal_node_t; 22496 | typedef details::string_range_node<T> string_range_node_t; 22497 | typedef details::const_string_range_node<T> const_string_range_node_t; 22498 | typedef details::generic_string_range_node<T> generic_string_range_node_t; 22499 | typedef details::string_concat_node<T> string_concat_node_t; 22500 | typedef details::assignment_string_node<T> assignment_string_node_t; 22501 | typedef details::assignment_string_range_node<T> assignment_string_range_node_t; 22502 | typedef details::conditional_string_node<T> conditional_string_node_t; 22503 | typedef details::cons_conditional_str_node<T> cons_conditional_str_node_t; 22504 | #endif 22505 | typedef details::assignment_node<T> assignment_node_t; 22506 | typedef details::assignment_vec_elem_node<T> assignment_vec_elem_node_t; 22507 | typedef details::assignment_vec_elem_rtc_node<T> assignment_vec_elem_rtc_node_t; 22508 | typedef details::assignment_rebasevec_elem_node<T> assignment_rebasevec_elem_node_t; 22509 | typedef details::assignment_rebasevec_elem_rtc_node<T> assignment_rebasevec_elem_rtc_node_t; 22510 | typedef details::assignment_rebasevec_celem_node<T> assignment_rebasevec_celem_node_t; 22511 | typedef details::assignment_vec_node<T> assignment_vec_node_t; 22512 | typedef details::assignment_vecvec_node<T> assignment_vecvec_node_t; 22513 | typedef details::conditional_vector_node<T> conditional_vector_node_t; 22514 | typedef details::scand_node<T> scand_node_t; 22515 | typedef details::scor_node<T> scor_node_t; 22516 | typedef lexer::token token_t; 22517 | typedef expression_node_t* expression_node_ptr; 22518 | typedef expression<T> expression_t; 22519 | typedef symbol_table<T> symbol_table_t; 22520 | typedef typename expression<T>::symtab_list_t symbol_table_list_t; 22521 | typedef details::vector_holder<T> vector_holder_t; 22522 | typedef vector_holder_t* vector_holder_ptr; 22523 | 22524 | typedef typename details::functor_t<T> functor_t; 22525 | typedef typename functor_t::qfunc_t quaternary_functor_t; 22526 | typedef typename functor_t::tfunc_t trinary_functor_t; 22527 | typedef typename functor_t::bfunc_t binary_functor_t; 22528 | typedef typename functor_t::ufunc_t unary_functor_t; 22529 | 22530 | typedef details::operator_type operator_t; 22531 | 22532 | typedef std::map<operator_t, unary_functor_t > unary_op_map_t; 22533 | typedef std::map<operator_t, binary_functor_t > binary_op_map_t; 22534 | typedef std::map<operator_t, trinary_functor_t> trinary_op_map_t; 22535 | 22536 | typedef std::map<std::string,std::pair<trinary_functor_t ,operator_t> > sf3_map_t; 22537 | typedef std::map<std::string,std::pair<quaternary_functor_t,operator_t> > sf4_map_t; 22538 | 22539 | typedef std::map<binary_functor_t,operator_t> inv_binary_op_map_t; 22540 | typedef std::multimap<std::string,details::base_operation_t,details::ilesscompare> base_ops_map_t; 22541 | typedef std::set<std::string,details::ilesscompare> disabled_func_set_t; 22542 | 22543 | typedef details::T0oT1_define<T, cref_t , cref_t > vov_t; 22544 | typedef details::T0oT1_define<T, const_t, cref_t > cov_t; 22545 | typedef details::T0oT1_define<T, cref_t , const_t> voc_t; 22546 | 22547 | typedef details::T0oT1oT2_define<T, cref_t , cref_t , cref_t > vovov_t; 22548 | typedef details::T0oT1oT2_define<T, cref_t , cref_t , const_t> vovoc_t; 22549 | typedef details::T0oT1oT2_define<T, cref_t , const_t, cref_t > vocov_t; 22550 | typedef details::T0oT1oT2_define<T, const_t, cref_t , cref_t > covov_t; 22551 | typedef details::T0oT1oT2_define<T, const_t, cref_t , const_t> covoc_t; 22552 | typedef details::T0oT1oT2_define<T, const_t, const_t, cref_t > cocov_t; 22553 | typedef details::T0oT1oT2_define<T, cref_t , const_t, const_t> vococ_t; 22554 | 22555 | typedef details::T0oT1oT2oT3_define<T, cref_t , cref_t , cref_t , cref_t > vovovov_t; 22556 | typedef details::T0oT1oT2oT3_define<T, cref_t , cref_t , cref_t , const_t> vovovoc_t; 22557 | typedef details::T0oT1oT2oT3_define<T, cref_t , cref_t , const_t, cref_t > vovocov_t; 22558 | typedef details::T0oT1oT2oT3_define<T, cref_t , const_t, cref_t , cref_t > vocovov_t; 22559 | typedef details::T0oT1oT2oT3_define<T, const_t, cref_t , cref_t , cref_t > covovov_t; 22560 | 22561 | typedef details::T0oT1oT2oT3_define<T, const_t, cref_t , const_t, cref_t > covocov_t; 22562 | typedef details::T0oT1oT2oT3_define<T, cref_t , const_t, cref_t , const_t> vocovoc_t; 22563 | typedef details::T0oT1oT2oT3_define<T, const_t, cref_t , cref_t , const_t> covovoc_t; 22564 | typedef details::T0oT1oT2oT3_define<T, cref_t , const_t, const_t, cref_t > vococov_t; 22565 | 22566 | typedef results_context<T> results_context_t; 22567 | 22568 | typedef parser_helper prsrhlpr_t; 22569 | 22570 | struct scope_element 22571 | { 22572 | enum element_type 22573 | { 22574 | e_none , 22575 | e_literal , 22576 | e_variable, 22577 | e_vector , 22578 | e_vecelem , 22579 | e_string 22580 | }; 22581 | 22582 | typedef details::vector_holder<T> vector_holder_t; 22583 | typedef literal_node_t* literal_node_ptr; 22584 | typedef variable_node_t* variable_node_ptr; 22585 | typedef vector_holder_t* vector_holder_ptr; 22586 | typedef expression_node_t* expression_node_ptr; 22587 | #ifndef exprtk_disable_string_capabilities 22588 | typedef stringvar_node_t* stringvar_node_ptr; 22589 | #endif 22590 | 22591 | scope_element() 22592 | : name("???") 22593 | , size (std::numeric_limits<std::size_t>::max()) 22594 | , index(std::numeric_limits<std::size_t>::max()) 22595 | , depth(std::numeric_limits<std::size_t>::max()) 22596 | , ref_count(0) 22597 | , ip_index (0) 22598 | , type (e_none) 22599 | , active (false) 22600 | , data (0) 22601 | , var_node (0) 22602 | , vec_node (0) 22603 | #ifndef exprtk_disable_string_capabilities 22604 | , str_node(0) 22605 | #endif 22606 | {} 22607 | 22608 | bool operator < (const scope_element& se) const 22609 | { 22610 | if (ip_index < se.ip_index) 22611 | return true; 22612 | else if (ip_index > se.ip_index) 22613 | return false; 22614 | else if (depth < se.depth) 22615 | return true; 22616 | else if (depth > se.depth) 22617 | return false; 22618 | else if (index < se.index) 22619 | return true; 22620 | else if (index > se.index) 22621 | return false; 22622 | else 22623 | return (name < se.name); 22624 | } 22625 | 22626 | void clear() 22627 | { 22628 | name = "???" 22629 | size = std::numeric_limits<std::size_t>::max(); 22630 | index = std::numeric_limits<std::size_t>::max(); 22631 | depth = std::numeric_limits<std::size_t>::max(); 22632 | type = e_none; 22633 | active = false; 22634 | ref_count = 0; 22635 | ip_index = 0; 22636 | data = 0; 22637 | var_node = 0; 22638 | vec_node = 0; 22639 | #ifndef exprtk_disable_string_capabilities 22640 | str_node = 0; 22641 | #endif 22642 | } 22643 | 22644 | std::string name; 22645 | std::size_t size; 22646 | std::size_t index; 22647 | std::size_t depth; 22648 | std::size_t ref_count; 22649 | std::size_t ip_index; 22650 | element_type type; 22651 | bool active; 22652 | void* data; 22653 | expression_node_ptr var_node; 22654 | vector_holder_ptr vec_node; 22655 | #ifndef exprtk_disable_string_capabilities 22656 | stringvar_node_ptr str_node; 22657 | #endif 22658 | }; 22659 | 22660 | class scope_element_manager 22661 | { 22662 | public: 22663 | 22664 | typedef expression_node_t* expression_node_ptr; 22665 | typedef variable_node_t* variable_node_ptr; 22666 | typedef parser<T> parser_t; 22667 | 22668 | explicit scope_element_manager(parser<T>& p) 22669 | : parser_(p) 22670 | , input_param_cnt_(0) 22671 | , total_local_symb_size_bytes_(0) 22672 | {} 22673 | 22674 | inline std::size_t size() const 22675 | { 22676 | return element_.size(); 22677 | } 22678 | 22679 | inline bool empty() const 22680 | { 22681 | return element_.empty(); 22682 | } 22683 | 22684 | inline scope_element& get_element(const std::size_t& index) 22685 | { 22686 | if (index < element_.size()) 22687 | return element_[index]; 22688 | else 22689 | return null_element_; 22690 | } 22691 | 22692 | inline scope_element& get_element(const std::string& var_name, 22693 | const std::size_t index = std::numeric_limits<std::size_t>::max()) 22694 | { 22695 | const std::size_t current_depth = parser_.state_.scope_depth; 22696 | 22697 | for (std::size_t i = 0; i < element_.size(); ++i) 22698 | { 22699 | scope_element& se = element_[i]; 22700 | 22701 | if (se.depth > current_depth) 22702 | continue; 22703 | else if ( 22704 | details::imatch(se.name, var_name) && 22705 | (se.index == index) 22706 | ) 22707 | return se; 22708 | } 22709 | 22710 | return null_element_; 22711 | } 22712 | 22713 | inline scope_element& get_active_element(const std::string& var_name, 22714 | const std::size_t index = std::numeric_limits<std::size_t>::max()) 22715 | { 22716 | const std::size_t current_depth = parser_.state_.scope_depth; 22717 | 22718 | for (std::size_t i = 0; i < element_.size(); ++i) 22719 | { 22720 | scope_element& se = element_[i]; 22721 | 22722 | if (se.depth > current_depth) 22723 | continue; 22724 | else if ( 22725 | details::imatch(se.name, var_name) && 22726 | (se.index == index) && 22727 | (se.active) 22728 | ) 22729 | return se; 22730 | } 22731 | 22732 | return null_element_; 22733 | } 22734 | 22735 | inline bool add_element(const scope_element& se) 22736 | { 22737 | for (std::size_t i = 0; i < element_.size(); ++i) 22738 | { 22739 | scope_element& cse = element_[i]; 22740 | 22741 | if ( 22742 | details::imatch(cse.name, se.name) && 22743 | (cse.depth <= se.depth) && 22744 | (cse.index == se.index) && 22745 | (cse.size == se.size ) && 22746 | (cse.type == se.type ) && 22747 | (cse.active) 22748 | ) 22749 | return false; 22750 | } 22751 | 22752 | switch (se.type) 22753 | { 22754 | case scope_element::e_variable : total_local_symb_size_bytes_ += sizeof(T); 22755 | break; 22756 | 22757 | case scope_element::e_literal : total_local_symb_size_bytes_ += sizeof(T); 22758 | break; 22759 | 22760 | case scope_element::e_vector : total_local_symb_size_bytes_ += sizeof(T) * se.size; 22761 | break; 22762 | 22763 | default : break; 22764 | } 22765 | 22766 | element_.push_back(se); 22767 | std::sort(element_.begin(),element_.end()); 22768 | 22769 | return true; 22770 | } 22771 | 22772 | inline void deactivate(const std::size_t& scope_depth) 22773 | { 22774 | exprtk_debug(("deactivate() - Scope depth: %d\n", 22775 | static_cast<int>(parser_.state_.scope_depth))); 22776 | 22777 | for (std::size_t i = 0; i < element_.size(); ++i) 22778 | { 22779 | scope_element& se = element_[i]; 22780 | 22781 | if (se.active && (se.depth >= scope_depth)) 22782 | { 22783 | exprtk_debug(("deactivate() - element[%02d] '%s'\n", 22784 | static_cast<int>(i), 22785 | se.name.c_str())); 22786 | 22787 | se.active = false; 22788 | } 22789 | } 22790 | } 22791 | 22792 | inline void free_element(scope_element& se) 22793 | { 22794 | exprtk_debug(("free_element() - se[%s]\n", se.name.c_str())); 22795 | 22796 | switch (se.type) 22797 | { 22798 | case scope_element::e_literal : delete reinterpret_cast<T*>(se.data); 22799 | delete se.var_node; 22800 | break; 22801 | 22802 | case scope_element::e_variable : delete reinterpret_cast<T*>(se.data); 22803 | delete se.var_node; 22804 | break; 22805 | 22806 | case scope_element::e_vector : delete[] reinterpret_cast<T*>(se.data); 22807 | delete se.vec_node; 22808 | break; 22809 | 22810 | case scope_element::e_vecelem : delete se.var_node; 22811 | break; 22812 | 22813 | #ifndef exprtk_disable_string_capabilities 22814 | case scope_element::e_string : delete reinterpret_cast<std::string*>(se.data); 22815 | delete se.str_node; 22816 | break; 22817 | #endif 22818 | 22819 | default : return; 22820 | } 22821 | 22822 | se.clear(); 22823 | } 22824 | 22825 | inline void cleanup() 22826 | { 22827 | for (std::size_t i = 0; i < element_.size(); ++i) 22828 | { 22829 | free_element(element_[i]); 22830 | } 22831 | 22832 | element_.clear(); 22833 | 22834 | input_param_cnt_ = 0; 22835 | total_local_symb_size_bytes_ = 0; 22836 | } 22837 | 22838 | inline std::size_t total_local_symb_size_bytes() const 22839 | { 22840 | return total_local_symb_size_bytes_; 22841 | } 22842 | 22843 | inline std::size_t next_ip_index() 22844 | { 22845 | return ++input_param_cnt_; 22846 | } 22847 | 22848 | inline expression_node_ptr get_variable(const T& v) 22849 | { 22850 | for (std::size_t i = 0; i < element_.size(); ++i) 22851 | { 22852 | scope_element& se = element_[i]; 22853 | 22854 | if ( 22855 | se.active && 22856 | se.var_node && 22857 | details::is_variable_node(se.var_node) 22858 | ) 22859 | { 22860 | variable_node_ptr vn = reinterpret_cast<variable_node_ptr>(se.var_node); 22861 | 22862 | if (&(vn->ref()) == (&v)) 22863 | { 22864 | return se.var_node; 22865 | } 22866 | } 22867 | } 22868 | 22869 | return expression_node_ptr(0); 22870 | } 22871 | 22872 | inline std::string get_vector_name(const T* data) 22873 | { 22874 | for (std::size_t i = 0; i < element_.size(); ++i) 22875 | { 22876 | scope_element& se = element_[i]; 22877 | 22878 | if ( 22879 | se.active && 22880 | se.vec_node && 22881 | (se.vec_node->data() == data) 22882 | ) 22883 | { 22884 | return se.name; 22885 | } 22886 | } 22887 | 22888 | return "neo-vector" 22889 | } 22890 | 22891 | private: 22892 | 22893 | scope_element_manager(const scope_element_manager&) exprtk_delete; 22894 | scope_element_manager& operator=(const scope_element_manager&) exprtk_delete; 22895 | 22896 | parser_t& parser_; 22897 | std::vector<scope_element> element_; 22898 | scope_element null_element_; 22899 | std::size_t input_param_cnt_; 22900 | std::size_t total_local_symb_size_bytes_; 22901 | }; 22902 | 22903 | class scope_handler 22904 | { 22905 | public: 22906 | 22907 | typedef parser<T> parser_t; 22908 | 22909 | explicit scope_handler(parser<T>& p) 22910 | : parser_(p) 22911 | { 22912 | parser_.state_.scope_depth++; 22913 | #ifdef exprtk_enable_debugging 22914 | const std::string depth(2 * parser_.state_.scope_depth,'-'); 22915 | exprtk_debug(("%s> Scope Depth: %02d\n", 22916 | depth.c_str(), 22917 | static_cast<int>(parser_.state_.scope_depth))); 22918 | #endif 22919 | } 22920 | 22921 | ~scope_handler() 22922 | { 22923 | parser_.sem_.deactivate(parser_.state_.scope_depth); 22924 | parser_.state_.scope_depth--; 22925 | #ifdef exprtk_enable_debugging 22926 | const std::string depth(2 * parser_.state_.scope_depth,'-'); 22927 | exprtk_debug(("<%s Scope Depth: %02d\n", 22928 | depth.c_str(), 22929 | static_cast<int>(parser_.state_.scope_depth))); 22930 | #endif 22931 | } 22932 | 22933 | private: 22934 | 22935 | scope_handler(const scope_handler&) exprtk_delete; 22936 | scope_handler& operator=(const scope_handler&) exprtk_delete; 22937 | 22938 | parser_t& parser_; 22939 | }; 22940 | 22941 | template <typename T_> 22942 | struct halfopen_range_policy 22943 | { 22944 | static inline bool is_within(const T_& v, const T_& begin, const T_& end) 22945 | { 22946 | assert(begin <= end); 22947 | return (begin <= v) && (v < end); 22948 | } 22949 | 22950 | static inline bool is_less(const T_& v, const T_& begin) 22951 | { 22952 | return (v < begin); 22953 | } 22954 | 22955 | static inline bool is_greater(const T_& v, const T_& end) 22956 | { 22957 | return (end <= v); 22958 | } 22959 | 22960 | static inline bool end_inclusive() 22961 | { 22962 | return false; 22963 | } 22964 | }; 22965 | 22966 | template <typename T_> 22967 | struct closed_range_policy 22968 | { 22969 | static inline bool is_within(const T_& v, const T_& begin, const T_& end) 22970 | { 22971 | assert(begin <= end); 22972 | return (begin <= v) && (v <= end); 22973 | } 22974 | 22975 | static inline bool is_less(const T_& v, const T_& begin) 22976 | { 22977 | return (v < begin); 22978 | } 22979 | 22980 | static inline bool is_greater(const T_& v, const T_& end) 22981 | { 22982 | return (end < v); 22983 | } 22984 | 22985 | static inline bool end_inclusive() 22986 | { 22987 | return true; 22988 | } 22989 | }; 22990 | 22991 | template <typename IntervalPointType, 22992 | typename RangePolicy = halfopen_range_policy<IntervalPointType> > 22993 | class interval_container_t 22994 | { 22995 | public: 22996 | 22997 | typedef IntervalPointType interval_point_t; 22998 | typedef std::pair<interval_point_t, interval_point_t> interval_t; 22999 | typedef std::map<interval_point_t, interval_t> interval_map_t; 23000 | typedef typename interval_map_t::const_iterator interval_map_citr_t; 23001 | 23002 | std::size_t size() const 23003 | { 23004 | return interval_map_.size(); 23005 | } 23006 | 23007 | void reset() 23008 | { 23009 | interval_map_.clear(); 23010 | } 23011 | 23012 | bool in_interval(const interval_point_t point, interval_t& interval) const 23013 | { 23014 | interval_map_citr_t itr = RangePolicy::end_inclusive() ? 23015 | interval_map_.lower_bound(point): 23016 | interval_map_.upper_bound(point); 23017 | 23018 | for (; itr != interval_map_.end(); ++itr) 23019 | { 23020 | const interval_point_t& begin = itr->second.first; 23021 | const interval_point_t& end = itr->second.second; 23022 | 23023 | if (RangePolicy::is_within(point, begin, end)) 23024 | { 23025 | interval = interval_t(begin,end); 23026 | return true; 23027 | } 23028 | else if (RangePolicy::is_greater(point, end)) 23029 | { 23030 | break; 23031 | } 23032 | } 23033 | 23034 | return false; 23035 | } 23036 | 23037 | bool in_interval(const interval_point_t point) const 23038 | { 23039 | interval_t interval; 23040 | return in_interval(point,interval); 23041 | } 23042 | 23043 | bool add_interval(const interval_point_t begin, const interval_point_t end) 23044 | { 23045 | if ((end <= begin) || in_interval(begin) || in_interval(end)) 23046 | { 23047 | return false; 23048 | } 23049 | 23050 | interval_map_[end] = std::make_pair(begin, end); 23051 | 23052 | return true; 23053 | } 23054 | 23055 | bool add_interval(const interval_t interval) 23056 | { 23057 | return add_interval(interval.first, interval.second); 23058 | } 23059 | 23060 | private: 23061 | 23062 | interval_map_t interval_map_; 23063 | }; 23064 | 23065 | class stack_limit_handler 23066 | { 23067 | public: 23068 | 23069 | typedef parser<T> parser_t; 23070 | 23071 | explicit stack_limit_handler(parser<T>& p) 23072 | : parser_(p) 23073 | , limit_exceeded_(false) 23074 | { 23075 | if (++parser_.state_.stack_depth > parser_.settings_.max_stack_depth_) 23076 | { 23077 | limit_exceeded_ = true; 23078 | parser_.set_error(make_error( 23079 | parser_error::e_parser, 23080 | "ERR000 - Current stack depth " + details::to_str(parser_.state_.stack_depth) + 23081 | " exceeds maximum allowed stack depth of " + details::to_str(parser_.settings_.max_stack_depth_), 23082 | exprtk_error_location)); 23083 | } 23084 | } 23085 | 23086 | ~stack_limit_handler() 23087 | { 23088 | assert(parser_.state_.stack_depth > 0); 23089 | parser_.state_.stack_depth--; 23090 | } 23091 | 23092 | bool operator!() 23093 | { 23094 | return limit_exceeded_; 23095 | } 23096 | 23097 | private: 23098 | 23099 | stack_limit_handler(const stack_limit_handler&) exprtk_delete; 23100 | stack_limit_handler& operator=(const stack_limit_handler&) exprtk_delete; 23101 | 23102 | parser_t& parser_; 23103 | bool limit_exceeded_; 23104 | }; 23105 | 23106 | struct symtab_store 23107 | { 23108 | symbol_table_list_t symtab_list_; 23109 | 23110 | typedef typename symbol_table_t::local_data_t local_data_t; 23111 | typedef typename symbol_table_t::variable_ptr variable_ptr; 23112 | typedef typename symbol_table_t::function_ptr function_ptr; 23113 | #ifndef exprtk_disable_string_capabilities 23114 | typedef typename symbol_table_t::stringvar_ptr stringvar_ptr; 23115 | #endif 23116 | typedef typename symbol_table_t::vector_holder_ptr vector_holder_ptr; 23117 | typedef typename symbol_table_t::vararg_function_ptr vararg_function_ptr; 23118 | typedef typename symbol_table_t::generic_function_ptr generic_function_ptr; 23119 | 23120 | struct variable_context 23121 | { 23122 | variable_context() 23123 | : symbol_table(0) 23124 | , variable(0) 23125 | {} 23126 | 23127 | const symbol_table_t* symbol_table; 23128 | variable_ptr variable; 23129 | }; 23130 | 23131 | struct vector_context 23132 | { 23133 | vector_context() 23134 | : symbol_table(0) 23135 | , vector_holder(0) 23136 | {} 23137 | 23138 | const symbol_table_t* symbol_table; 23139 | vector_holder_ptr vector_holder; 23140 | }; 23141 | 23142 | #ifndef exprtk_disable_string_capabilities 23143 | struct string_context 23144 | { 23145 | string_context() 23146 | : symbol_table(0) 23147 | , str_var(0) 23148 | {} 23149 | 23150 | const symbol_table_t* symbol_table; 23151 | stringvar_ptr str_var; 23152 | }; 23153 | #endif 23154 | 23155 | inline bool empty() const 23156 | { 23157 | return symtab_list_.empty(); 23158 | } 23159 | 23160 | inline void clear() 23161 | { 23162 | symtab_list_.clear(); 23163 | } 23164 | 23165 | inline bool valid() const 23166 | { 23167 | if (!empty()) 23168 | { 23169 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23170 | { 23171 | if (symtab_list_[i].valid()) 23172 | return true; 23173 | } 23174 | } 23175 | 23176 | return false; 23177 | } 23178 | 23179 | inline bool valid_symbol(const std::string& symbol) const 23180 | { 23181 | if (!symtab_list_.empty()) 23182 | return symtab_list_[0].valid_symbol(symbol); 23183 | else 23184 | return false; 23185 | } 23186 | 23187 | inline bool valid_function_name(const std::string& symbol) const 23188 | { 23189 | if (!symtab_list_.empty()) 23190 | return symtab_list_[0].valid_function(symbol); 23191 | else 23192 | return false; 23193 | } 23194 | 23195 | inline variable_context get_variable_context(const std::string& variable_name) const 23196 | { 23197 | variable_context result; 23198 | 23199 | if (valid_symbol(variable_name)) 23200 | { 23201 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23202 | { 23203 | if (!symtab_list_[i].valid()) 23204 | { 23205 | continue; 23206 | } 23207 | 23208 | result.variable = local_data(i) 23209 | .variable_store.get(variable_name); 23210 | if (result.variable) 23211 | { 23212 | result.symbol_table = &symtab_list_[i]; 23213 | break; 23214 | } 23215 | } 23216 | } 23217 | 23218 | return result; 23219 | } 23220 | 23221 | inline variable_ptr get_variable(const std::string& variable_name) const 23222 | { 23223 | if (!valid_symbol(variable_name)) 23224 | return reinterpret_cast<variable_ptr>(0); 23225 | 23226 | variable_ptr result = reinterpret_cast<variable_ptr>(0); 23227 | 23228 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23229 | { 23230 | if (!symtab_list_[i].valid()) 23231 | continue; 23232 | else 23233 | result = local_data(i) 23234 | .variable_store.get(variable_name); 23235 | 23236 | if (result) break; 23237 | } 23238 | 23239 | return result; 23240 | } 23241 | 23242 | inline variable_ptr get_variable(const T& var_ref) const 23243 | { 23244 | variable_ptr result = reinterpret_cast<variable_ptr>(0); 23245 | 23246 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23247 | { 23248 | if (!symtab_list_[i].valid()) 23249 | continue; 23250 | else 23251 | result = local_data(i).variable_store 23252 | .get_from_varptr(reinterpret_cast<const void*>(&var_ref)); 23253 | 23254 | if (result) break; 23255 | } 23256 | 23257 | return result; 23258 | } 23259 | 23260 | #ifndef exprtk_disable_string_capabilities 23261 | inline string_context get_string_context(const std::string& string_name) const 23262 | { 23263 | string_context result; 23264 | 23265 | if (!valid_symbol(string_name)) 23266 | return result; 23267 | 23268 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23269 | { 23270 | if (!symtab_list_[i].valid()) 23271 | { 23272 | continue; 23273 | } 23274 | 23275 | result.str_var = local_data(i).stringvar_store.get(string_name); 23276 | 23277 | if (result.str_var) 23278 | { 23279 | result.symbol_table = &symtab_list_[i]; 23280 | break; 23281 | } 23282 | } 23283 | 23284 | return result; 23285 | } 23286 | 23287 | inline stringvar_ptr get_stringvar(const std::string& string_name) const 23288 | { 23289 | if (!valid_symbol(string_name)) 23290 | return reinterpret_cast<stringvar_ptr>(0); 23291 | 23292 | stringvar_ptr result = reinterpret_cast<stringvar_ptr>(0); 23293 | 23294 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23295 | { 23296 | if (!symtab_list_[i].valid()) 23297 | continue; 23298 | else 23299 | result = local_data(i) 23300 | .stringvar_store.get(string_name); 23301 | 23302 | if (result) break; 23303 | } 23304 | 23305 | return result; 23306 | } 23307 | #endif 23308 | 23309 | inline function_ptr get_function(const std::string& function_name) const 23310 | { 23311 | if (!valid_function_name(function_name)) 23312 | return reinterpret_cast<function_ptr>(0); 23313 | 23314 | function_ptr result = reinterpret_cast<function_ptr>(0); 23315 | 23316 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23317 | { 23318 | if (!symtab_list_[i].valid()) 23319 | continue; 23320 | else 23321 | result = local_data(i) 23322 | .function_store.get(function_name); 23323 | 23324 | if (result) break; 23325 | } 23326 | 23327 | return result; 23328 | } 23329 | 23330 | inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name) const 23331 | { 23332 | if (!valid_function_name(vararg_function_name)) 23333 | return reinterpret_cast<vararg_function_ptr>(0); 23334 | 23335 | vararg_function_ptr result = reinterpret_cast<vararg_function_ptr>(0); 23336 | 23337 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23338 | { 23339 | if (!symtab_list_[i].valid()) 23340 | continue; 23341 | else 23342 | result = local_data(i) 23343 | .vararg_function_store.get(vararg_function_name); 23344 | 23345 | if (result) break; 23346 | } 23347 | 23348 | return result; 23349 | } 23350 | 23351 | inline generic_function_ptr get_generic_function(const std::string& function_name) const 23352 | { 23353 | if (!valid_function_name(function_name)) 23354 | return reinterpret_cast<generic_function_ptr>(0); 23355 | 23356 | generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0); 23357 | 23358 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23359 | { 23360 | if (!symtab_list_[i].valid()) 23361 | continue; 23362 | else 23363 | result = local_data(i) 23364 | .generic_function_store.get(function_name); 23365 | 23366 | if (result) break; 23367 | } 23368 | 23369 | return result; 23370 | } 23371 | 23372 | inline generic_function_ptr get_string_function(const std::string& function_name) const 23373 | { 23374 | if (!valid_function_name(function_name)) 23375 | return reinterpret_cast<generic_function_ptr>(0); 23376 | 23377 | generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0); 23378 | 23379 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23380 | { 23381 | if (!symtab_list_[i].valid()) 23382 | continue; 23383 | else 23384 | result = 23385 | local_data(i).string_function_store.get(function_name); 23386 | 23387 | if (result) break; 23388 | } 23389 | 23390 | return result; 23391 | } 23392 | 23393 | inline generic_function_ptr get_overload_function(const std::string& function_name) const 23394 | { 23395 | if (!valid_function_name(function_name)) 23396 | return reinterpret_cast<generic_function_ptr>(0); 23397 | 23398 | generic_function_ptr result = reinterpret_cast<generic_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 = 23406 | local_data(i).overload_function_store.get(function_name); 23407 | 23408 | if (result) break; 23409 | } 23410 | 23411 | return result; 23412 | } 23413 | 23414 | inline vector_context get_vector_context(const std::string& vector_name) const 23415 | { 23416 | vector_context result; 23417 | if (!valid_symbol(vector_name)) 23418 | return result; 23419 | 23420 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23421 | { 23422 | if (!symtab_list_[i].valid()) 23423 | { 23424 | continue; 23425 | } 23426 | 23427 | result.vector_holder = local_data(i).vector_store.get(vector_name); 23428 | 23429 | if (result.vector_holder) 23430 | { 23431 | result.symbol_table = &symtab_list_[i]; 23432 | break; 23433 | } 23434 | } 23435 | 23436 | return result; 23437 | } 23438 | 23439 | inline vector_holder_ptr get_vector(const std::string& vector_name) const 23440 | { 23441 | if (!valid_symbol(vector_name)) 23442 | return reinterpret_cast<vector_holder_ptr>(0); 23443 | 23444 | vector_holder_ptr result = reinterpret_cast<vector_holder_ptr>(0); 23445 | 23446 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23447 | { 23448 | if (!symtab_list_[i].valid()) 23449 | { 23450 | continue; 23451 | } 23452 | 23453 | result = local_data(i).vector_store.get(vector_name); 23454 | 23455 | if (result) 23456 | { 23457 | break; 23458 | } 23459 | } 23460 | 23461 | return result; 23462 | } 23463 | 23464 | inline bool is_constant_node(const std::string& symbol_name) const 23465 | { 23466 | if (!valid_symbol(symbol_name)) 23467 | return false; 23468 | 23469 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23470 | { 23471 | if (!symtab_list_[i].valid()) 23472 | { 23473 | continue; 23474 | } 23475 | 23476 | if (local_data(i).variable_store.is_constant(symbol_name)) 23477 | { 23478 | return true; 23479 | } 23480 | } 23481 | 23482 | return false; 23483 | } 23484 | 23485 | #ifndef exprtk_disable_string_capabilities 23486 | inline bool is_constant_string(const std::string& symbol_name) const 23487 | { 23488 | if (!valid_symbol(symbol_name)) 23489 | return false; 23490 | 23491 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23492 | { 23493 | if (!symtab_list_[i].valid()) 23494 | continue; 23495 | else if (!local_data(i).stringvar_store.symbol_exists(symbol_name)) 23496 | continue; 23497 | else if (local_data(i).stringvar_store.is_constant(symbol_name)) 23498 | return true; 23499 | } 23500 | 23501 | return false; 23502 | } 23503 | #endif 23504 | 23505 | inline bool symbol_exists(const std::string& symbol) const 23506 | { 23507 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23508 | { 23509 | if (!symtab_list_[i].valid()) 23510 | { 23511 | continue; 23512 | } 23513 | 23514 | if (symtab_list_[i].symbol_exists(symbol)) 23515 | { 23516 | return true; 23517 | } 23518 | } 23519 | 23520 | return false; 23521 | } 23522 | 23523 | inline bool is_variable(const std::string& variable_name) const 23524 | { 23525 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23526 | { 23527 | if (!symtab_list_[i].valid()) 23528 | continue; 23529 | else if ( 23530 | symtab_list_[i].local_data().variable_store 23531 | .symbol_exists(variable_name) 23532 | ) 23533 | return true; 23534 | } 23535 | 23536 | return false; 23537 | } 23538 | 23539 | #ifndef exprtk_disable_string_capabilities 23540 | inline bool is_stringvar(const std::string& stringvar_name) const 23541 | { 23542 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23543 | { 23544 | if (!symtab_list_[i].valid()) 23545 | continue; 23546 | else if ( 23547 | symtab_list_[i].local_data().stringvar_store 23548 | .symbol_exists(stringvar_name) 23549 | ) 23550 | return true; 23551 | } 23552 | 23553 | return false; 23554 | } 23555 | 23556 | inline bool is_conststr_stringvar(const std::string& symbol_name) const 23557 | { 23558 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23559 | { 23560 | if (!symtab_list_[i].valid()) 23561 | continue; 23562 | else if ( 23563 | symtab_list_[i].local_data().stringvar_store 23564 | .symbol_exists(symbol_name) 23565 | ) 23566 | { 23567 | return ( 23568 | local_data(i).stringvar_store.symbol_exists(symbol_name) || 23569 | local_data(i).stringvar_store.is_constant (symbol_name) 23570 | ); 23571 | 23572 | } 23573 | } 23574 | 23575 | return false; 23576 | } 23577 | #endif 23578 | 23579 | inline bool is_function(const std::string& function_name) const 23580 | { 23581 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23582 | { 23583 | if (!symtab_list_[i].valid()) 23584 | continue; 23585 | else if ( 23586 | local_data(i).vararg_function_store 23587 | .symbol_exists(function_name) 23588 | ) 23589 | return true; 23590 | } 23591 | 23592 | return false; 23593 | } 23594 | 23595 | inline bool is_vararg_function(const std::string& vararg_function_name) const 23596 | { 23597 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23598 | { 23599 | if (!symtab_list_[i].valid()) 23600 | continue; 23601 | else if ( 23602 | local_data(i).vararg_function_store 23603 | .symbol_exists(vararg_function_name) 23604 | ) 23605 | return true; 23606 | } 23607 | 23608 | return false; 23609 | } 23610 | 23611 | inline bool is_vector(const std::string& vector_name) const 23612 | { 23613 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23614 | { 23615 | if (!symtab_list_[i].valid()) 23616 | continue; 23617 | else if ( 23618 | local_data(i).vector_store 23619 | .symbol_exists(vector_name) 23620 | ) 23621 | return true; 23622 | } 23623 | 23624 | return false; 23625 | } 23626 | 23627 | inline std::string get_variable_name(const expression_node_ptr& ptr) const 23628 | { 23629 | return local_data().variable_store.entity_name(ptr); 23630 | } 23631 | 23632 | inline std::string get_vector_name(const vector_holder_ptr& ptr) const 23633 | { 23634 | return local_data().vector_store.entity_name(ptr); 23635 | } 23636 | 23637 | #ifndef exprtk_disable_string_capabilities 23638 | inline std::string get_stringvar_name(const expression_node_ptr& ptr) const 23639 | { 23640 | return local_data().stringvar_store.entity_name(ptr); 23641 | } 23642 | 23643 | inline std::string get_conststr_stringvar_name(const expression_node_ptr& ptr) const 23644 | { 23645 | return local_data().stringvar_store.entity_name(ptr); 23646 | } 23647 | #endif 23648 | 23649 | inline local_data_t& local_data(const std::size_t& index = 0) 23650 | { 23651 | return symtab_list_[index].local_data(); 23652 | } 23653 | 23654 | inline const local_data_t& local_data(const std::size_t& index = 0) const 23655 | { 23656 | return symtab_list_[index].local_data(); 23657 | } 23658 | 23659 | inline symbol_table_t& get_symbol_table(const std::size_t& index = 0) 23660 | { 23661 | return symtab_list_[index]; 23662 | } 23663 | }; 23664 | 23665 | struct parser_state 23666 | { 23667 | parser_state() 23668 | : type_check_enabled(true) 23669 | { 23670 | reset(); 23671 | } 23672 | 23673 | void reset() 23674 | { 23675 | parsing_return_stmt = false; 23676 | parsing_break_stmt = false; 23677 | parsing_assert_stmt = false; 23678 | return_stmt_present = false; 23679 | side_effect_present = false; 23680 | scope_depth = 0; 23681 | stack_depth = 0; 23682 | parsing_loop_stmt_count = 0; 23683 | } 23684 | 23685 | #ifndef exprtk_enable_debugging 23686 | void activate_side_effect(const std::string&) 23687 | #else 23688 | void activate_side_effect(const std::string& source) 23689 | #endif 23690 | { 23691 | if (!side_effect_present) 23692 | { 23693 | side_effect_present = true; 23694 | 23695 | exprtk_debug(("activate_side_effect() - caller: %s\n", source.c_str())); 23696 | } 23697 | } 23698 | 23699 | bool parsing_return_stmt; 23700 | bool parsing_break_stmt; 23701 | bool parsing_assert_stmt; 23702 | bool return_stmt_present; 23703 | bool side_effect_present; 23704 | bool type_check_enabled; 23705 | std::size_t scope_depth; 23706 | std::size_t stack_depth; 23707 | std::size_t parsing_loop_stmt_count; 23708 | }; 23709 | 23710 | public: 23711 | 23712 | struct unknown_symbol_resolver 23713 | { 23714 | 23715 | enum usr_symbol_type 23716 | { 23717 | e_usr_unknown_type = 0, 23718 | e_usr_variable_type = 1, 23719 | e_usr_constant_type = 2 23720 | }; 23721 | 23722 | enum usr_mode 23723 | { 23724 | e_usrmode_default = 0, 23725 | e_usrmode_extended = 1 23726 | }; 23727 | 23728 | usr_mode mode; 23729 | 23730 | explicit unknown_symbol_resolver(const usr_mode m = e_usrmode_default) 23731 | : mode(m) 23732 | {} 23733 | 23734 | virtual ~unknown_symbol_resolver() 23735 | {} 23736 | 23737 | virtual bool process(const std::string& /*unknown_symbol*/, 23738 | usr_symbol_type& st, 23739 | T& default_value, 23740 | std::string& error_message) 23741 | { 23742 | if (e_usrmode_default != mode) 23743 | return false; 23744 | 23745 | st = e_usr_variable_type; 23746 | default_value = T(0); 23747 | error_message.clear(); 23748 | 23749 | return true; 23750 | } 23751 | 23752 | virtual bool process(const std::string& /* unknown_symbol */, 23753 | symbol_table_t& /* symbol_table */, 23754 | std::string& /* error_message */) 23755 | { 23756 | return false; 23757 | } 23758 | }; 23759 | 23760 | enum collect_type 23761 | { 23762 | e_ct_none = 0, 23763 | e_ct_variables = 1, 23764 | e_ct_functions = 2, 23765 | e_ct_assignments = 4 23766 | }; 23767 | 23768 | enum symbol_type 23769 | { 23770 | e_st_unknown = 0, 23771 | e_st_variable = 1, 23772 | e_st_vector = 2, 23773 | e_st_vecelem = 3, 23774 | e_st_string = 4, 23775 | e_st_function = 5, 23776 | e_st_local_variable = 6, 23777 | e_st_local_vector = 7, 23778 | e_st_local_string = 8 23779 | }; 23780 | 23781 | class dependent_entity_collector 23782 | { 23783 | public: 23784 | 23785 | typedef std::pair<std::string,symbol_type> symbol_t; 23786 | typedef std::vector<symbol_t> symbol_list_t; 23787 | 23788 | explicit dependent_entity_collector(const std::size_t options = e_ct_none) 23789 | : options_(options) 23790 | , collect_variables_ ((options_ & e_ct_variables ) == e_ct_variables ) 23791 | , collect_functions_ ((options_ & e_ct_functions ) == e_ct_functions ) 23792 | , collect_assignments_((options_ & e_ct_assignments) == e_ct_assignments) 23793 | , return_present_ (false) 23794 | , final_stmt_return_(false) 23795 | {} 23796 | 23797 | template <typename Allocator, 23798 | template <typename, typename> class Sequence> 23799 | inline std::size_t symbols(Sequence<symbol_t,Allocator>& symbols_list) 23800 | { 23801 | if (!collect_variables_ && !collect_functions_) 23802 | return 0; 23803 | else if (symbol_name_list_.empty()) 23804 | return 0; 23805 | 23806 | for (std::size_t i = 0; i < symbol_name_list_.size(); ++i) 23807 | { 23808 | details::case_normalise(symbol_name_list_[i].first); 23809 | } 23810 | 23811 | std::sort(symbol_name_list_.begin(), symbol_name_list_.end()); 23812 | 23813 | std::unique_copy 23814 | ( 23815 | symbol_name_list_.begin(), 23816 | symbol_name_list_.end (), 23817 | std::back_inserter(symbols_list) 23818 | ); 23819 | 23820 | return symbols_list.size(); 23821 | } 23822 | 23823 | template <typename Allocator, 23824 | template <typename, typename> class Sequence> 23825 | inline std::size_t assignment_symbols(Sequence<symbol_t,Allocator>& assignment_list) 23826 | { 23827 | if (!collect_assignments_) 23828 | return 0; 23829 | else if (assignment_name_list_.empty()) 23830 | return 0; 23831 | 23832 | for (std::size_t i = 0; i < assignment_name_list_.size(); ++i) 23833 | { 23834 | details::case_normalise(assignment_name_list_[i].first); 23835 | } 23836 | 23837 | std::sort(assignment_name_list_.begin(),assignment_name_list_.end()); 23838 | 23839 | std::unique_copy 23840 | ( 23841 | assignment_name_list_.begin(), 23842 | assignment_name_list_.end (), 23843 | std::back_inserter(assignment_list) 23844 | ); 23845 | 23846 | return assignment_list.size(); 23847 | } 23848 | 23849 | void clear() 23850 | { 23851 | symbol_name_list_ .clear(); 23852 | assignment_name_list_.clear(); 23853 | retparam_list_ .clear(); 23854 | return_present_ = false; 23855 | final_stmt_return_ = false; 23856 | } 23857 | 23858 | bool& collect_variables() 23859 | { 23860 | return collect_variables_; 23861 | } 23862 | 23863 | bool& collect_functions() 23864 | { 23865 | return collect_functions_; 23866 | } 23867 | 23868 | bool& collect_assignments() 23869 | { 23870 | return collect_assignments_; 23871 | } 23872 | 23873 | bool return_present() const 23874 | { 23875 | return return_present_; 23876 | } 23877 | 23878 | bool final_stmt_return() const 23879 | { 23880 | return final_stmt_return_; 23881 | } 23882 | 23883 | typedef std::vector<std::string> retparam_list_t; 23884 | 23885 | retparam_list_t return_param_type_list() const 23886 | { 23887 | return retparam_list_; 23888 | } 23889 | 23890 | private: 23891 | 23892 | inline void add_symbol(const std::string& symbol, const symbol_type st) 23893 | { 23894 | switch (st) 23895 | { 23896 | case e_st_variable : 23897 | case e_st_vector : 23898 | case e_st_string : 23899 | case e_st_local_variable : 23900 | case e_st_local_vector : 23901 | case e_st_local_string : if (collect_variables_) 23902 | symbol_name_list_ 23903 | .push_back(std::make_pair(symbol, st)); 23904 | break; 23905 | 23906 | case e_st_function : if (collect_functions_) 23907 | symbol_name_list_ 23908 | .push_back(std::make_pair(symbol, st)); 23909 | break; 23910 | 23911 | default : return; 23912 | } 23913 | } 23914 | 23915 | inline void add_assignment(const std::string& symbol, const symbol_type st) 23916 | { 23917 | switch (st) 23918 | { 23919 | case e_st_variable : 23920 | case e_st_vector : 23921 | case e_st_string : if (collect_assignments_) 23922 | assignment_name_list_ 23923 | .push_back(std::make_pair(symbol, st)); 23924 | break; 23925 | 23926 | default : return; 23927 | } 23928 | } 23929 | 23930 | std::size_t options_; 23931 | bool collect_variables_; 23932 | bool collect_functions_; 23933 | bool collect_assignments_; 23934 | bool return_present_; 23935 | bool final_stmt_return_; 23936 | symbol_list_t symbol_name_list_; 23937 | symbol_list_t assignment_name_list_; 23938 | retparam_list_t retparam_list_; 23939 | 23940 | friend class parser<T>; 23941 | }; 23942 | 23943 | class settings_store 23944 | { 23945 | private: 23946 | 23947 | typedef std::set<std::string,details::ilesscompare> disabled_entity_set_t; 23948 | typedef disabled_entity_set_t::iterator des_itr_t; 23949 | 23950 | public: 23951 | 23952 | enum settings_compilation_options 23953 | { 23954 | e_unknown = 0, 23955 | e_replacer = 1, 23956 | e_joiner = 2, 23957 | e_numeric_check = 4, 23958 | e_bracket_check = 8, 23959 | e_sequence_check = 16, 23960 | e_commutative_check = 32, 23961 | e_strength_reduction = 64, 23962 | e_disable_vardef = 128, 23963 | e_collect_vars = 256, 23964 | e_collect_funcs = 512, 23965 | e_collect_assings = 1024, 23966 | e_disable_usr_on_rsrvd = 2048, 23967 | e_disable_zero_return = 4096 23968 | }; 23969 | 23970 | enum settings_base_funcs 23971 | { 23972 | e_bf_unknown = 0, 23973 | e_bf_abs , e_bf_acos , e_bf_acosh , e_bf_asin , 23974 | e_bf_asinh , e_bf_atan , e_bf_atan2 , e_bf_atanh , 23975 | e_bf_avg , e_bf_ceil , e_bf_clamp , e_bf_cos , 23976 | e_bf_cosh , e_bf_cot , e_bf_csc , e_bf_equal , 23977 | e_bf_erf , e_bf_erfc , e_bf_exp , e_bf_expm1 , 23978 | e_bf_floor , e_bf_frac , e_bf_hypot , e_bf_iclamp , 23979 | e_bf_like , e_bf_log , e_bf_log10 , e_bf_log1p , 23980 | e_bf_log2 , e_bf_logn , e_bf_mand , e_bf_max , 23981 | e_bf_min , e_bf_mod , e_bf_mor , e_bf_mul , 23982 | e_bf_ncdf , e_bf_pow , e_bf_root , e_bf_round , 23983 | e_bf_roundn , e_bf_sec , e_bf_sgn , e_bf_sin , 23984 | e_bf_sinc , e_bf_sinh , e_bf_sqrt , e_bf_sum , 23985 | e_bf_swap , e_bf_tan , e_bf_tanh , e_bf_trunc , 23986 | e_bf_not_equal , e_bf_inrange , e_bf_deg2grad , e_bf_deg2rad , 23987 | e_bf_rad2deg , e_bf_grad2deg 23988 | }; 23989 | 23990 | enum settings_control_structs 23991 | { 23992 | e_ctrl_unknown = 0, 23993 | e_ctrl_ifelse, 23994 | e_ctrl_switch, 23995 | e_ctrl_for_loop, 23996 | e_ctrl_while_loop, 23997 | e_ctrl_repeat_loop, 23998 | e_ctrl_return 23999 | }; 24000 | 24001 | enum settings_logic_opr 24002 | { 24003 | e_logic_unknown = 0, 24004 | e_logic_and, e_logic_nand , e_logic_nor , 24005 | e_logic_not, e_logic_or , e_logic_xnor, 24006 | e_logic_xor, e_logic_scand, e_logic_scor 24007 | }; 24008 | 24009 | enum settings_arithmetic_opr 24010 | { 24011 | e_arith_unknown = 0, 24012 | e_arith_add, e_arith_sub, e_arith_mul, 24013 | e_arith_div, e_arith_mod, e_arith_pow 24014 | }; 24015 | 24016 | enum settings_assignment_opr 24017 | { 24018 | e_assign_unknown = 0, 24019 | e_assign_assign, e_assign_addass, e_assign_subass, 24020 | e_assign_mulass, e_assign_divass, e_assign_modass 24021 | }; 24022 | 24023 | enum settings_inequality_opr 24024 | { 24025 | e_ineq_unknown = 0, 24026 | e_ineq_lt , e_ineq_lte, e_ineq_eq , 24027 | e_ineq_equal, e_ineq_ne , e_ineq_nequal, 24028 | e_ineq_gte , e_ineq_gt 24029 | }; 24030 | 24031 | static const std::size_t default_compile_all_opts = 24032 | e_replacer + 24033 | e_joiner + 24034 | e_numeric_check + 24035 | e_bracket_check + 24036 | e_sequence_check + 24037 | e_commutative_check + 24038 | e_strength_reduction; 24039 | 24040 | settings_store(const std::size_t compile_options = default_compile_all_opts) 24041 | : max_stack_depth_(400) 24042 | , max_node_depth_(10000) 24043 | , max_total_local_symbol_size_bytes_(2000000000) 24044 | , max_local_vector_size_(max_total_local_symbol_size_bytes_ / sizeof(T)) 24045 | { 24046 | load_compile_options(compile_options); 24047 | } 24048 | 24049 | settings_store& enable_all_base_functions() 24050 | { 24051 | disabled_func_set_.clear(); 24052 | return (*this); 24053 | } 24054 | 24055 | settings_store& enable_all_control_structures() 24056 | { 24057 | disabled_ctrl_set_.clear(); 24058 | return (*this); 24059 | } 24060 | 24061 | settings_store& enable_all_logic_ops() 24062 | { 24063 | disabled_logic_set_.clear(); 24064 | return (*this); 24065 | } 24066 | 24067 | settings_store& enable_all_arithmetic_ops() 24068 | { 24069 | disabled_arithmetic_set_.clear(); 24070 | return (*this); 24071 | } 24072 | 24073 | settings_store& enable_all_assignment_ops() 24074 | { 24075 | disabled_assignment_set_.clear(); 24076 | return (*this); 24077 | } 24078 | 24079 | settings_store& enable_all_inequality_ops() 24080 | { 24081 | disabled_inequality_set_.clear(); 24082 | return (*this); 24083 | } 24084 | 24085 | settings_store& enable_local_vardef() 24086 | { 24087 | disable_vardef_ = false; 24088 | return (*this); 24089 | } 24090 | 24091 | settings_store& enable_commutative_check() 24092 | { 24093 | enable_commutative_check_ = true; 24094 | return (*this); 24095 | } 24096 | 24097 | settings_store& enable_strength_reduction() 24098 | { 24099 | enable_strength_reduction_ = true; 24100 | return (*this); 24101 | } 24102 | 24103 | settings_store& disable_all_base_functions() 24104 | { 24105 | std::copy(details::base_function_list, 24106 | details::base_function_list + details::base_function_list_size, 24107 | std::insert_iterator<disabled_entity_set_t> 24108 | (disabled_func_set_, disabled_func_set_.begin())); 24109 | return (*this); 24110 | } 24111 | 24112 | settings_store& disable_all_control_structures() 24113 | { 24114 | std::copy(details::cntrl_struct_list, 24115 | details::cntrl_struct_list + details::cntrl_struct_list_size, 24116 | std::insert_iterator<disabled_entity_set_t> 24117 | (disabled_ctrl_set_, disabled_ctrl_set_.begin())); 24118 | return (*this); 24119 | } 24120 | 24121 | settings_store& disable_all_logic_ops() 24122 | { 24123 | std::copy(details::logic_ops_list, 24124 | details::logic_ops_list + details::logic_ops_list_size, 24125 | std::insert_iterator<disabled_entity_set_t> 24126 | (disabled_logic_set_, disabled_logic_set_.begin())); 24127 | return (*this); 24128 | } 24129 | 24130 | settings_store& disable_all_arithmetic_ops() 24131 | { 24132 | std::copy(details::arithmetic_ops_list, 24133 | details::arithmetic_ops_list + details::arithmetic_ops_list_size, 24134 | std::insert_iterator<disabled_entity_set_t> 24135 | (disabled_arithmetic_set_, disabled_arithmetic_set_.begin())); 24136 | return (*this); 24137 | } 24138 | 24139 | settings_store& disable_all_assignment_ops() 24140 | { 24141 | std::copy(details::assignment_ops_list, 24142 | details::assignment_ops_list + details::assignment_ops_list_size, 24143 | std::insert_iterator<disabled_entity_set_t> 24144 | (disabled_assignment_set_, disabled_assignment_set_.begin())); 24145 | return (*this); 24146 | } 24147 | 24148 | settings_store& disable_all_inequality_ops() 24149 | { 24150 | std::copy(details::inequality_ops_list, 24151 | details::inequality_ops_list + details::inequality_ops_list_size, 24152 | std::insert_iterator<disabled_entity_set_t> 24153 | (disabled_inequality_set_, disabled_inequality_set_.begin())); 24154 | return (*this); 24155 | } 24156 | 24157 | settings_store& disable_local_vardef() 24158 | { 24159 | disable_vardef_ = true; 24160 | return (*this); 24161 | } 24162 | 24163 | settings_store& disable_commutative_check() 24164 | { 24165 | enable_commutative_check_ = false; 24166 | return (*this); 24167 | } 24168 | 24169 | settings_store& disable_strength_reduction() 24170 | { 24171 | enable_strength_reduction_ = false; 24172 | return (*this); 24173 | } 24174 | 24175 | bool replacer_enabled () const { return enable_replacer_; } 24176 | bool commutative_check_enabled () const { return enable_commutative_check_; } 24177 | bool joiner_enabled () const { return enable_joiner_; } 24178 | bool numeric_check_enabled () const { return enable_numeric_check_; } 24179 | bool bracket_check_enabled () const { return enable_bracket_check_; } 24180 | bool sequence_check_enabled () const { return enable_sequence_check_; } 24181 | bool strength_reduction_enabled () const { return enable_strength_reduction_; } 24182 | bool collect_variables_enabled () const { return enable_collect_vars_; } 24183 | bool collect_functions_enabled () const { return enable_collect_funcs_; } 24184 | bool collect_assignments_enabled() const { return enable_collect_assings_; } 24185 | bool vardef_disabled () const { return disable_vardef_; } 24186 | bool rsrvd_sym_usr_disabled () const { return disable_rsrvd_sym_usr_; } 24187 | bool zero_return_disabled () const { return disable_zero_return_; } 24188 | 24189 | bool function_enabled(const std::string& function_name) const 24190 | { 24191 | if (disabled_func_set_.empty()) 24192 | return true; 24193 | else 24194 | return (disabled_func_set_.end() == disabled_func_set_.find(function_name)); 24195 | } 24196 | 24197 | bool control_struct_enabled(const std::string& control_struct) const 24198 | { 24199 | if (disabled_ctrl_set_.empty()) 24200 | return true; 24201 | else 24202 | return (disabled_ctrl_set_.end() == disabled_ctrl_set_.find(control_struct)); 24203 | } 24204 | 24205 | bool logic_enabled(const std::string& logic_operation) const 24206 | { 24207 | if (disabled_logic_set_.empty()) 24208 | return true; 24209 | else 24210 | return (disabled_logic_set_.end() == disabled_logic_set_.find(logic_operation)); 24211 | } 24212 | 24213 | bool arithmetic_enabled(const details::operator_type& arithmetic_operation) const 24214 | { 24215 | if (disabled_logic_set_.empty()) 24216 | return true; 24217 | else 24218 | return disabled_arithmetic_set_.end() == disabled_arithmetic_set_ 24219 | .find(arith_opr_to_string(arithmetic_operation)); 24220 | } 24221 | 24222 | bool assignment_enabled(const details::operator_type& assignment) const 24223 | { 24224 | if (disabled_assignment_set_.empty()) 24225 | return true; 24226 | else 24227 | return disabled_assignment_set_.end() == disabled_assignment_set_ 24228 | .find(assign_opr_to_string(assignment)); 24229 | } 24230 | 24231 | bool inequality_enabled(const details::operator_type& inequality) const 24232 | { 24233 | if (disabled_inequality_set_.empty()) 24234 | return true; 24235 | else 24236 | return disabled_inequality_set_.end() == disabled_inequality_set_ 24237 | .find(inequality_opr_to_string(inequality)); 24238 | } 24239 | 24240 | bool function_disabled(const std::string& function_name) const 24241 | { 24242 | if (disabled_func_set_.empty()) 24243 | return false; 24244 | else 24245 | return (disabled_func_set_.end() != disabled_func_set_.find(function_name)); 24246 | } 24247 | 24248 | bool control_struct_disabled(const std::string& control_struct) const 24249 | { 24250 | if (disabled_ctrl_set_.empty()) 24251 | return false; 24252 | else 24253 | return (disabled_ctrl_set_.end() != disabled_ctrl_set_.find(control_struct)); 24254 | } 24255 | 24256 | bool logic_disabled(const std::string& logic_operation) const 24257 | { 24258 | if (disabled_logic_set_.empty()) 24259 | return false; 24260 | else 24261 | return (disabled_logic_set_.end() != disabled_logic_set_.find(logic_operation)); 24262 | } 24263 | 24264 | bool assignment_disabled(const details::operator_type assignment_operation) const 24265 | { 24266 | if (disabled_assignment_set_.empty()) 24267 | return false; 24268 | else 24269 | return disabled_assignment_set_.end() != disabled_assignment_set_ 24270 | .find(assign_opr_to_string(assignment_operation)); 24271 | } 24272 | 24273 | bool logic_disabled(const details::operator_type logic_operation) const 24274 | { 24275 | if (disabled_logic_set_.empty()) 24276 | return false; 24277 | else 24278 | return disabled_logic_set_.end() != disabled_logic_set_ 24279 | .find(logic_opr_to_string(logic_operation)); 24280 | } 24281 | 24282 | bool arithmetic_disabled(const details::operator_type arithmetic_operation) const 24283 | { 24284 | if (disabled_arithmetic_set_.empty()) 24285 | return false; 24286 | else 24287 | return disabled_arithmetic_set_.end() != disabled_arithmetic_set_ 24288 | .find(arith_opr_to_string(arithmetic_operation)); 24289 | } 24290 | 24291 | bool inequality_disabled(const details::operator_type& inequality) const 24292 | { 24293 | if (disabled_inequality_set_.empty()) 24294 | return false; 24295 | else 24296 | return disabled_inequality_set_.end() != disabled_inequality_set_ 24297 | .find(inequality_opr_to_string(inequality)); 24298 | } 24299 | 24300 | settings_store& disable_base_function(const settings_base_funcs bf) 24301 | { 24302 | if ( 24303 | (e_bf_unknown != bf) && 24304 | (static_cast<std::size_t>(bf) < (details::base_function_list_size + 1)) 24305 | ) 24306 | { 24307 | disabled_func_set_.insert(details::base_function_list[bf - 1]); 24308 | } 24309 | 24310 | return (*this); 24311 | } 24312 | 24313 | settings_store& disable_control_structure(const settings_control_structs ctrl_struct) 24314 | { 24315 | if ( 24316 | (e_ctrl_unknown != ctrl_struct) && 24317 | (static_cast<std::size_t>(ctrl_struct) < (details::cntrl_struct_list_size + 1)) 24318 | ) 24319 | { 24320 | disabled_ctrl_set_.insert(details::cntrl_struct_list[ctrl_struct - 1]); 24321 | } 24322 | 24323 | return (*this); 24324 | } 24325 | 24326 | settings_store& disable_logic_operation(const settings_logic_opr logic) 24327 | { 24328 | if ( 24329 | (e_logic_unknown != logic) && 24330 | (static_cast<std::size_t>(logic) < (details::logic_ops_list_size + 1)) 24331 | ) 24332 | { 24333 | disabled_logic_set_.insert(details::logic_ops_list[logic - 1]); 24334 | } 24335 | 24336 | return (*this); 24337 | } 24338 | 24339 | settings_store& disable_arithmetic_operation(const settings_arithmetic_opr arithmetic) 24340 | { 24341 | if ( 24342 | (e_arith_unknown != arithmetic) && 24343 | (static_cast<std::size_t>(arithmetic) < (details::arithmetic_ops_list_size + 1)) 24344 | ) 24345 | { 24346 | disabled_arithmetic_set_.insert(details::arithmetic_ops_list[arithmetic - 1]); 24347 | } 24348 | 24349 | return (*this); 24350 | } 24351 | 24352 | settings_store& disable_assignment_operation(const settings_assignment_opr assignment) 24353 | { 24354 | if ( 24355 | (e_assign_unknown != assignment) && 24356 | (static_cast<std::size_t>(assignment) < (details::assignment_ops_list_size + 1)) 24357 | ) 24358 | { 24359 | disabled_assignment_set_.insert(details::assignment_ops_list[assignment - 1]); 24360 | } 24361 | 24362 | return (*this); 24363 | } 24364 | 24365 | settings_store& disable_inequality_operation(const settings_inequality_opr inequality) 24366 | { 24367 | if ( 24368 | (e_ineq_unknown != inequality) && 24369 | (static_cast<std::size_t>(inequality) < (details::inequality_ops_list_size + 1)) 24370 | ) 24371 | { 24372 | disabled_inequality_set_.insert(details::inequality_ops_list[inequality - 1]); 24373 | } 24374 | 24375 | return (*this); 24376 | } 24377 | 24378 | settings_store& enable_base_function(const settings_base_funcs bf) 24379 | { 24380 | if ( 24381 | (e_bf_unknown != bf) && 24382 | (static_cast<std::size_t>(bf) < (details::base_function_list_size + 1)) 24383 | ) 24384 | { 24385 | const des_itr_t itr = disabled_func_set_.find(details::base_function_list[bf - 1]); 24386 | 24387 | if (disabled_func_set_.end() != itr) 24388 | { 24389 | disabled_func_set_.erase(itr); 24390 | } 24391 | } 24392 | 24393 | return (*this); 24394 | } 24395 | 24396 | settings_store& enable_control_structure(const settings_control_structs ctrl_struct) 24397 | { 24398 | if ( 24399 | (e_ctrl_unknown != ctrl_struct) && 24400 | (static_cast<std::size_t>(ctrl_struct) < (details::cntrl_struct_list_size + 1)) 24401 | ) 24402 | { 24403 | const des_itr_t itr = disabled_ctrl_set_.find(details::cntrl_struct_list[ctrl_struct - 1]); 24404 | 24405 | if (disabled_ctrl_set_.end() != itr) 24406 | { 24407 | disabled_ctrl_set_.erase(itr); 24408 | } 24409 | } 24410 | 24411 | return (*this); 24412 | } 24413 | 24414 | settings_store& enable_logic_operation(const settings_logic_opr logic) 24415 | { 24416 | if ( 24417 | (e_logic_unknown != logic) && 24418 | (static_cast<std::size_t>(logic) < (details::logic_ops_list_size + 1)) 24419 | ) 24420 | { 24421 | const des_itr_t itr = disabled_logic_set_.find(details::logic_ops_list[logic - 1]); 24422 | 24423 | if (disabled_logic_set_.end() != itr) 24424 | { 24425 | disabled_logic_set_.erase(itr); 24426 | } 24427 | } 24428 | 24429 | return (*this); 24430 | } 24431 | 24432 | settings_store& enable_arithmetic_operation(const settings_arithmetic_opr arithmetic) 24433 | { 24434 | if ( 24435 | (e_arith_unknown != arithmetic) && 24436 | (static_cast<std::size_t>(arithmetic) < (details::arithmetic_ops_list_size + 1)) 24437 | ) 24438 | { 24439 | const des_itr_t itr = disabled_arithmetic_set_.find(details::arithmetic_ops_list[arithmetic - 1]); 24440 | 24441 | if (disabled_arithmetic_set_.end() != itr) 24442 | { 24443 | disabled_arithmetic_set_.erase(itr); 24444 | } 24445 | } 24446 | 24447 | return (*this); 24448 | } 24449 | 24450 | settings_store& enable_assignment_operation(const settings_assignment_opr assignment) 24451 | { 24452 | if ( 24453 | (e_assign_unknown != assignment) && 24454 | (static_cast<std::size_t>(assignment) < (details::assignment_ops_list_size + 1)) 24455 | ) 24456 | { 24457 | const des_itr_t itr = disabled_assignment_set_.find(details::assignment_ops_list[assignment - 1]); 24458 | 24459 | if (disabled_assignment_set_.end() != itr) 24460 | { 24461 | disabled_assignment_set_.erase(itr); 24462 | } 24463 | } 24464 | 24465 | return (*this); 24466 | } 24467 | 24468 | settings_store& enable_inequality_operation(const settings_inequality_opr inequality) 24469 | { 24470 | if ( 24471 | (e_ineq_unknown != inequality) && 24472 | (static_cast<std::size_t>(inequality) < (details::inequality_ops_list_size + 1)) 24473 | ) 24474 | { 24475 | const des_itr_t itr = disabled_inequality_set_.find(details::inequality_ops_list[inequality - 1]); 24476 | 24477 | if (disabled_inequality_set_.end() != itr) 24478 | { 24479 | disabled_inequality_set_.erase(itr); 24480 | } 24481 | } 24482 | 24483 | return (*this); 24484 | } 24485 | 24486 | void set_max_stack_depth(const std::size_t max_stack_depth) 24487 | { 24488 | max_stack_depth_ = max_stack_depth; 24489 | } 24490 | 24491 | void set_max_node_depth(const std::size_t max_node_depth) 24492 | { 24493 | max_node_depth_ = max_node_depth; 24494 | } 24495 | 24496 | void set_max_local_vector_size(const std::size_t max_local_vector_size) 24497 | { 24498 | max_local_vector_size_ = max_local_vector_size; 24499 | } 24500 | 24501 | void set_max_total_local_symbol_size_bytes(const std::size_t max_total_lcl_symb_size) 24502 | { 24503 | max_total_local_symbol_size_bytes_ = max_total_lcl_symb_size; 24504 | } 24505 | 24506 | std::size_t max_stack_depth() const 24507 | { 24508 | return max_stack_depth_; 24509 | } 24510 | 24511 | std::size_t max_node_depth() const 24512 | { 24513 | return max_node_depth_; 24514 | } 24515 | 24516 | std::size_t max_local_vector_size() const 24517 | { 24518 | return max_local_vector_size_; 24519 | } 24520 | 24521 | std::size_t max_total_local_symbol_size_bytes() const 24522 | { 24523 | return max_total_local_symbol_size_bytes_; 24524 | } 24525 | 24526 | private: 24527 | 24528 | void load_compile_options(const std::size_t compile_options) 24529 | { 24530 | enable_replacer_ = (compile_options & e_replacer ) == e_replacer; 24531 | enable_joiner_ = (compile_options & e_joiner ) == e_joiner; 24532 | enable_numeric_check_ = (compile_options & e_numeric_check ) == e_numeric_check; 24533 | enable_bracket_check_ = (compile_options & e_bracket_check ) == e_bracket_check; 24534 | enable_sequence_check_ = (compile_options & e_sequence_check ) == e_sequence_check; 24535 | enable_commutative_check_ = (compile_options & e_commutative_check ) == e_commutative_check; 24536 | enable_strength_reduction_ = (compile_options & e_strength_reduction ) == e_strength_reduction; 24537 | enable_collect_vars_ = (compile_options & e_collect_vars ) == e_collect_vars; 24538 | enable_collect_funcs_ = (compile_options & e_collect_funcs ) == e_collect_funcs; 24539 | enable_collect_assings_ = (compile_options & e_collect_assings ) == e_collect_assings; 24540 | disable_vardef_ = (compile_options & e_disable_vardef ) == e_disable_vardef; 24541 | disable_rsrvd_sym_usr_ = (compile_options & e_disable_usr_on_rsrvd) == e_disable_usr_on_rsrvd; 24542 | disable_zero_return_ = (compile_options & e_disable_zero_return ) == e_disable_zero_return; 24543 | } 24544 | 24545 | std::string assign_opr_to_string(details::operator_type opr) const 24546 | { 24547 | switch (opr) 24548 | { 24549 | case details::e_assign : return ":=" 24550 | case details::e_addass : return "+=" 24551 | case details::e_subass : return "-=" 24552 | case details::e_mulass : return "*=" 24553 | case details::e_divass : return "/=" 24554 | case details::e_modass : return "%=" 24555 | default : return "" ; 24556 | } 24557 | } 24558 | 24559 | std::string arith_opr_to_string(details::operator_type opr) const 24560 | { 24561 | switch (opr) 24562 | { 24563 | case details::e_add : return "+" 24564 | case details::e_sub : return "-" 24565 | case details::e_mul : return "*" 24566 | case details::e_div : return "/" 24567 | case details::e_mod : return "%" 24568 | case details::e_pow : return "^" 24569 | default : return "" ; 24570 | } 24571 | } 24572 | 24573 | std::string inequality_opr_to_string(details::operator_type opr) const 24574 | { 24575 | switch (opr) 24576 | { 24577 | case details::e_lt : return "<" ; 24578 | case details::e_lte : return "<=" 24579 | case details::e_eq : return "==" 24580 | case details::e_equal : return "=" ; 24581 | case details::e_ne : return "!=" 24582 | case details::e_nequal: return "<>" 24583 | case details::e_gte : return ">=" 24584 | case details::e_gt : return ">" ; 24585 | default : return "" ; 24586 | } 24587 | } 24588 | 24589 | std::string logic_opr_to_string(details::operator_type opr) const 24590 | { 24591 | switch (opr) 24592 | { 24593 | case details::e_and : return "and" ; 24594 | case details::e_or : return "or" ; 24595 | case details::e_xor : return "xor" ; 24596 | case details::e_nand : return "nand" 24597 | case details::e_nor : return "nor" ; 24598 | case details::e_xnor : return "xnor" 24599 | case details::e_notl : return "not" ; 24600 | default : return "" ; 24601 | } 24602 | } 24603 | 24604 | bool enable_replacer_; 24605 | bool enable_joiner_; 24606 | bool enable_numeric_check_; 24607 | bool enable_bracket_check_; 24608 | bool enable_sequence_check_; 24609 | bool enable_commutative_check_; 24610 | bool enable_strength_reduction_; 24611 | bool enable_collect_vars_; 24612 | bool enable_collect_funcs_; 24613 | bool enable_collect_assings_; 24614 | bool disable_vardef_; 24615 | bool disable_rsrvd_sym_usr_; 24616 | bool disable_zero_return_; 24617 | 24618 | disabled_entity_set_t disabled_func_set_ ; 24619 | disabled_entity_set_t disabled_ctrl_set_ ; 24620 | disabled_entity_set_t disabled_logic_set_; 24621 | disabled_entity_set_t disabled_arithmetic_set_; 24622 | disabled_entity_set_t disabled_assignment_set_; 24623 | disabled_entity_set_t disabled_inequality_set_; 24624 | 24625 | std::size_t max_stack_depth_; 24626 | std::size_t max_node_depth_; 24627 | std::size_t max_total_local_symbol_size_bytes_; 24628 | std::size_t max_local_vector_size_; 24629 | 24630 | friend class parser<T>; 24631 | }; 24632 | 24633 | typedef settings_store settings_t; 24634 | 24635 | explicit parser(const settings_t& settings = settings_t()) 24636 | : settings_(settings) 24637 | , resolve_unknown_symbol_(false) 24638 | , results_context_(0) 24639 | , unknown_symbol_resolver_(reinterpret_cast<unknown_symbol_resolver*>(0)) 24640 | #ifdef _MSC_VER 24641 | #pragma warning(push) 24642 | #pragma warning (disable:4355) 24643 | #endif 24644 | , sem_(*this) 24645 | #ifdef _MSC_VER 24646 | #pragma warning(pop) 24647 | #endif 24648 | , operator_joiner_2_(2) 24649 | , operator_joiner_3_(3) 24650 | , loop_runtime_check_(0) 24651 | , vector_access_runtime_check_(0) 24652 | , compilation_check_ptr_(0) 24653 | , assert_check_(0) 24654 | { 24655 | init_precompilation(); 24656 | 24657 | load_operations_map (base_ops_map_ ); 24658 | load_unary_operations_map (unary_op_map_ ); 24659 | load_binary_operations_map (binary_op_map_ ); 24660 | load_inv_binary_operations_map(inv_binary_op_map_); 24661 | load_sf3_map (sf3_map_ ); 24662 | load_sf4_map (sf4_map_ ); 24663 | 24664 | expression_generator_.init_synthesize_map(); 24665 | expression_generator_.set_parser(*this); 24666 | expression_generator_.set_uom (unary_op_map_ ); 24667 | expression_generator_.set_bom (binary_op_map_ ); 24668 | expression_generator_.set_ibom(inv_binary_op_map_); 24669 | expression_generator_.set_sf3m(sf3_map_ ); 24670 | expression_generator_.set_sf4m(sf4_map_ ); 24671 | expression_generator_.set_strength_reduction_state(settings_.strength_reduction_enabled()); 24672 | } 24673 | 24674 | ~parser() 24675 | {} 24676 | 24677 | inline void init_precompilation() 24678 | { 24679 | dec_.collect_variables() = 24680 | settings_.collect_variables_enabled(); 24681 | 24682 | dec_.collect_functions() = 24683 | settings_.collect_functions_enabled(); 24684 | 24685 | dec_.collect_assignments() = 24686 | settings_.collect_assignments_enabled(); 24687 | 24688 | if (settings_.replacer_enabled()) 24689 | { 24690 | symbol_replacer_.clear(); 24691 | symbol_replacer_.add_replace("true" , "1", lexer::token::e_number); 24692 | symbol_replacer_.add_replace("false", "0", lexer::token::e_number); 24693 | helper_assembly_.token_modifier_list.clear(); 24694 | helper_assembly_.register_modifier(&symbol_replacer_); 24695 | } 24696 | 24697 | if (settings_.commutative_check_enabled()) 24698 | { 24699 | for (std::size_t i = 0; i < details::reserved_words_size; ++i) 24700 | { 24701 | commutative_inserter_.ignore_symbol(details::reserved_words[i]); 24702 | } 24703 | 24704 | helper_assembly_.token_inserter_list.clear(); 24705 | helper_assembly_.register_inserter(&commutative_inserter_); 24706 | } 24707 | 24708 | if (settings_.joiner_enabled()) 24709 | { 24710 | helper_assembly_.token_joiner_list.clear(); 24711 | helper_assembly_.register_joiner(&operator_joiner_2_); 24712 | helper_assembly_.register_joiner(&operator_joiner_3_); 24713 | } 24714 | 24715 | if ( 24716 | settings_.numeric_check_enabled () || 24717 | settings_.bracket_check_enabled () || 24718 | settings_.sequence_check_enabled() 24719 | ) 24720 | { 24721 | helper_assembly_.token_scanner_list.clear(); 24722 | 24723 | if (settings_.numeric_check_enabled()) 24724 | { 24725 | helper_assembly_.register_scanner(&numeric_checker_); 24726 | } 24727 | 24728 | if (settings_.bracket_check_enabled()) 24729 | { 24730 | helper_assembly_.register_scanner(&bracket_checker_); 24731 | } 24732 | 24733 | if (settings_.sequence_check_enabled()) 24734 | { 24735 | helper_assembly_.register_scanner(&sequence_validator_ ); 24736 | helper_assembly_.register_scanner(&sequence_validator_3tkns_); 24737 | } 24738 | } 24739 | } 24740 | 24741 | inline bool compile(const std::string& expression_string, expression<T>& expr) 24742 | { 24743 | state_ .reset(); 24744 | error_list_ .clear(); 24745 | brkcnt_list_ .clear(); 24746 | synthesis_error_ .clear(); 24747 | immutable_memory_map_.reset(); 24748 | immutable_symtok_map_.clear(); 24749 | current_state_stack_ .clear(); 24750 | assert_ids_ .clear(); 24751 | sem_ .cleanup(); 24752 | 24753 | return_cleanup(); 24754 | 24755 | if (!valid_settings()) 24756 | { 24757 | return false; 24758 | } 24759 | 24760 | expression_generator_.set_allocator(node_allocator_); 24761 | 24762 | if (expression_string.empty()) 24763 | { 24764 | set_error(make_error( 24765 | parser_error::e_syntax, 24766 | "ERR001 - Empty expression!", 24767 | exprtk_error_location)); 24768 | 24769 | return false; 24770 | } 24771 | 24772 | if (!init(expression_string)) 24773 | { 24774 | process_lexer_errors(); 24775 | return false; 24776 | } 24777 | 24778 | if (lexer().empty()) 24779 | { 24780 | set_error(make_error( 24781 | parser_error::e_syntax, 24782 | "ERR002 - Empty expression!", 24783 | exprtk_error_location)); 24784 | 24785 | return false; 24786 | } 24787 | 24788 | if (halt_compilation_check()) 24789 | { 24790 | exprtk_debug(("halt_compilation_check() - compile checkpoint 0\n")); 24791 | sem_.cleanup(); 24792 | return false; 24793 | } 24794 | 24795 | if (!run_assemblies()) 24796 | { 24797 | sem_.cleanup(); 24798 | return false; 24799 | } 24800 | 24801 | if (halt_compilation_check()) 24802 | { 24803 | exprtk_debug(("halt_compilation_check() - compile checkpoint 1\n")); 24804 | sem_.cleanup(); 24805 | return false; 24806 | } 24807 | 24808 | symtab_store_.symtab_list_ = expr.get_symbol_table_list(); 24809 | dec_.clear(); 24810 | 24811 | lexer().begin(); 24812 | 24813 | next_token(); 24814 | 24815 | expression_node_ptr e = parse_corpus(); 24816 | 24817 | if ((0 != e) && (token_t::e_eof == current_token().type)) 24818 | { 24819 | bool* retinvk_ptr = 0; 24820 | 24821 | if (state_.return_stmt_present) 24822 | { 24823 | dec_.return_present_ = true; 24824 | 24825 | e = expression_generator_ 24826 | .return_envelope(e, results_context_, retinvk_ptr); 24827 | } 24828 | 24829 | expr.set_expression(e); 24830 | expr.set_retinvk(retinvk_ptr); 24831 | 24832 | register_local_vars(expr); 24833 | register_return_results(expr); 24834 | 24835 | return !(!expr); 24836 | } 24837 | else 24838 | { 24839 | if (error_list_.empty()) 24840 | { 24841 | set_error(make_error( 24842 | parser_error::e_syntax, 24843 | current_token(), 24844 | "ERR003 - Invalid expression encountered", 24845 | exprtk_error_location)); 24846 | } 24847 | 24848 | if ((0 != e) && branch_deletable(e)) 24849 | { 24850 | destroy_node(e); 24851 | } 24852 | 24853 | dec_.clear (); 24854 | sem_.cleanup (); 24855 | return_cleanup(); 24856 | 24857 | return false; 24858 | } 24859 | } 24860 | 24861 | inline expression_t compile(const std::string& expression_string, symbol_table_t& symtab) 24862 | { 24863 | expression_t expression; 24864 | expression.register_symbol_table(symtab); 24865 | compile(expression_string,expression); 24866 | return expression; 24867 | } 24868 | 24869 | void process_lexer_errors() 24870 | { 24871 | for (std::size_t i = 0; i < lexer().size(); ++i) 24872 | { 24873 | if (lexer()[i].is_error()) 24874 | { 24875 | std::string diagnostic = "ERR004 - " 24876 | 24877 | switch (lexer()[i].type) 24878 | { 24879 | case lexer::token::e_error : diagnostic += "General token error" 24880 | break; 24881 | 24882 | case lexer::token::e_err_symbol : diagnostic += "Symbol error" 24883 | break; 24884 | 24885 | case lexer::token::e_err_number : diagnostic += "Invalid numeric token" 24886 | break; 24887 | 24888 | case lexer::token::e_err_string : diagnostic += "Invalid string token" 24889 | break; 24890 | 24891 | case lexer::token::e_err_sfunc : diagnostic += "Invalid special function token" 24892 | break; 24893 | 24894 | default : diagnostic += "Unknown compiler error" 24895 | } 24896 | 24897 | set_error(make_error( 24898 | parser_error::e_lexer, 24899 | lexer()[i], 24900 | diagnostic + ": " + lexer()[i].value, 24901 | exprtk_error_location)); 24902 | } 24903 | } 24904 | } 24905 | 24906 | inline bool run_assemblies() 24907 | { 24908 | if (settings_.commutative_check_enabled()) 24909 | { 24910 | helper_assembly_.run_inserters(lexer()); 24911 | } 24912 | 24913 | if (settings_.joiner_enabled()) 24914 | { 24915 | helper_assembly_.run_joiners(lexer()); 24916 | } 24917 | 24918 | if (settings_.replacer_enabled()) 24919 | { 24920 | helper_assembly_.run_modifiers(lexer()); 24921 | } 24922 | 24923 | if ( 24924 | settings_.numeric_check_enabled () || 24925 | settings_.bracket_check_enabled () || 24926 | settings_.sequence_check_enabled() 24927 | ) 24928 | { 24929 | if (!helper_assembly_.run_scanners(lexer())) 24930 | { 24931 | if (helper_assembly_.error_token_scanner) 24932 | { 24933 | lexer::helper::bracket_checker* bracket_checker_ptr = 0; 24934 | lexer::helper::numeric_checker<T>* numeric_checker_ptr = 0; 24935 | lexer::helper::sequence_validator* sequence_validator_ptr = 0; 24936 | lexer::helper::sequence_validator_3tokens* sequence_validator3_ptr = 0; 24937 | 24938 | if (0 != (bracket_checker_ptr = dynamic_cast<lexer::helper::bracket_checker*>(helper_assembly_.error_token_scanner))) 24939 | { 24940 | set_error(make_error( 24941 | parser_error::e_token, 24942 | bracket_checker_ptr->error_token(), 24943 | "ERR005 - Mismatched brackets: '" + bracket_checker_ptr->error_token().value + "'", 24944 | exprtk_error_location)); 24945 | } 24946 | else if (0 != (numeric_checker_ptr = dynamic_cast<lexer::helper::numeric_checker<T>*>(helper_assembly_.error_token_scanner))) 24947 | { 24948 | for (std::size_t i = 0; i < numeric_checker_ptr->error_count(); ++i) 24949 | { 24950 | lexer::token error_token = lexer()[numeric_checker_ptr->error_index(i)]; 24951 | 24952 | set_error(make_error( 24953 | parser_error::e_token, 24954 | error_token, 24955 | "ERR006 - Invalid numeric token: '" + error_token.value + "'", 24956 | exprtk_error_location)); 24957 | } 24958 | 24959 | if (numeric_checker_ptr->error_count()) 24960 | { 24961 | numeric_checker_ptr->clear_errors(); 24962 | } 24963 | } 24964 | else if (0 != (sequence_validator_ptr = dynamic_cast<lexer::helper::sequence_validator*>(helper_assembly_.error_token_scanner))) 24965 | { 24966 | for (std::size_t i = 0; i < sequence_validator_ptr->error_count(); ++i) 24967 | { 24968 | std::pair<lexer::token,lexer::token> error_token = sequence_validator_ptr->error(i); 24969 | 24970 | set_error(make_error( 24971 | parser_error::e_token, 24972 | error_token.first, 24973 | "ERR007 - Invalid token sequence: '" + 24974 | error_token.first.value + "' and '" + 24975 | error_token.second.value + "'", 24976 | exprtk_error_location)); 24977 | } 24978 | 24979 | if (sequence_validator_ptr->error_count()) 24980 | { 24981 | sequence_validator_ptr->clear_errors(); 24982 | } 24983 | } 24984 | else if (0 != (sequence_validator3_ptr = dynamic_cast<lexer::helper::sequence_validator_3tokens*>(helper_assembly_.error_token_scanner))) 24985 | { 24986 | for (std::size_t i = 0; i < sequence_validator3_ptr->error_count(); ++i) 24987 | { 24988 | std::pair<lexer::token,lexer::token> error_token = sequence_validator3_ptr->error(i); 24989 | 24990 | set_error(make_error( 24991 | parser_error::e_token, 24992 | error_token.first, 24993 | "ERR008 - Invalid token sequence: '" + 24994 | error_token.first.value + "' and '" + 24995 | error_token.second.value + "'", 24996 | exprtk_error_location)); 24997 | } 24998 | 24999 | if (sequence_validator3_ptr->error_count()) 25000 | { 25001 | sequence_validator3_ptr->clear_errors(); 25002 | } 25003 | } 25004 | } 25005 | 25006 | return false; 25007 | } 25008 | } 25009 | 25010 | return true; 25011 | } 25012 | 25013 | inline settings_store& settings() 25014 | { 25015 | return settings_; 25016 | } 25017 | 25018 | inline parser_error::type get_error(const std::size_t& index) const 25019 | { 25020 | if (index < error_list_.size()) 25021 | { 25022 | return error_list_[index]; 25023 | } 25024 | 25025 | throw std::invalid_argument("parser::get_error() - Invalid error index specified"); 25026 | } 25027 | 25028 | inline std::string error() const 25029 | { 25030 | if (!error_list_.empty()) 25031 | { 25032 | return error_list_[0].diagnostic; 25033 | } 25034 | else 25035 | return std::string("No Error"); 25036 | } 25037 | 25038 | inline std::size_t error_count() const 25039 | { 25040 | return error_list_.size(); 25041 | } 25042 | 25043 | inline dependent_entity_collector& dec() 25044 | { 25045 | return dec_; 25046 | } 25047 | 25048 | inline std::size_t total_local_symbol_size_bytes() const 25049 | { 25050 | return sem_.total_local_symb_size_bytes(); 25051 | } 25052 | 25053 | inline bool replace_symbol(const std::string& old_symbol, const std::string& new_symbol) 25054 | { 25055 | if (!settings_.replacer_enabled()) 25056 | return false; 25057 | else if (details::is_reserved_word(old_symbol)) 25058 | return false; 25059 | else 25060 | return symbol_replacer_.add_replace(old_symbol,new_symbol,lexer::token::e_symbol); 25061 | } 25062 | 25063 | inline bool remove_replace_symbol(const std::string& symbol) 25064 | { 25065 | if (!settings_.replacer_enabled()) 25066 | return false; 25067 | else if (details::is_reserved_word(symbol)) 25068 | return false; 25069 | else 25070 | return symbol_replacer_.remove(symbol); 25071 | } 25072 | 25073 | inline void enable_unknown_symbol_resolver(unknown_symbol_resolver* usr = reinterpret_cast<unknown_symbol_resolver*>(0)) 25074 | { 25075 | resolve_unknown_symbol_ = true; 25076 | 25077 | if (usr) 25078 | unknown_symbol_resolver_ = usr; 25079 | else 25080 | unknown_symbol_resolver_ = &default_usr_; 25081 | } 25082 | 25083 | inline void enable_unknown_symbol_resolver(unknown_symbol_resolver& usr) 25084 | { 25085 | enable_unknown_symbol_resolver(&usr); 25086 | } 25087 | 25088 | inline void disable_unknown_symbol_resolver() 25089 | { 25090 | resolve_unknown_symbol_ = false; 25091 | unknown_symbol_resolver_ = &default_usr_; 25092 | } 25093 | 25094 | inline void register_loop_runtime_check(loop_runtime_check& lrtchk) 25095 | { 25096 | loop_runtime_check_ = &lrtchk; 25097 | } 25098 | 25099 | inline void register_vector_access_runtime_check(vector_access_runtime_check& vartchk) 25100 | { 25101 | vector_access_runtime_check_ = &vartchk; 25102 | } 25103 | 25104 | inline void register_compilation_timeout_check(compilation_check& compchk) 25105 | { 25106 | compilation_check_ptr_ = &compchk; 25107 | } 25108 | 25109 | inline void register_assert_check(assert_check& assrt_chck) 25110 | { 25111 | assert_check_ = &assrt_chck; 25112 | } 25113 | 25114 | inline void clear_loop_runtime_check() 25115 | { 25116 | loop_runtime_check_ = loop_runtime_check_ptr(0); 25117 | } 25118 | 25119 | inline void clear_vector_access_runtime_check() 25120 | { 25121 | vector_access_runtime_check_ = vector_access_runtime_check_ptr(0); 25122 | } 25123 | 25124 | inline void clear_compilation_timeout_check() 25125 | { 25126 | compilation_check_ptr_ = compilation_check_ptr(0); 25127 | } 25128 | 25129 | inline void clear_assert_check() 25130 | { 25131 | assert_check_ = assert_check_ptr(0); 25132 | } 25133 | 25134 | private: 25135 | 25136 | inline bool valid_base_operation(const std::string& symbol) const 25137 | { 25138 | const std::size_t length = symbol.size(); 25139 | 25140 | if ( 25141 | (length < 3) || // Shortest base op symbol length 25142 | (length > 9) // Longest base op symbol length 25143 | ) 25144 | return false; 25145 | else 25146 | return settings_.function_enabled(symbol) && 25147 | (base_ops_map_.end() != base_ops_map_.find(symbol)); 25148 | } 25149 | 25150 | inline bool valid_vararg_operation(const std::string& symbol) const 25151 | { 25152 | static const std::string s_sum = "sum" ; 25153 | static const std::string s_mul = "mul" ; 25154 | static const std::string s_avg = "avg" ; 25155 | static const std::string s_min = "min" ; 25156 | static const std::string s_max = "max" ; 25157 | static const std::string s_mand = "mand" 25158 | static const std::string s_mor = "mor" ; 25159 | static const std::string s_multi = "~" ; 25160 | static const std::string s_mswitch = "[*]" ; 25161 | 25162 | return 25163 | ( 25164 | details::imatch(symbol,s_sum ) || 25165 | details::imatch(symbol,s_mul ) || 25166 | details::imatch(symbol,s_avg ) || 25167 | details::imatch(symbol,s_min ) || 25168 | details::imatch(symbol,s_max ) || 25169 | details::imatch(symbol,s_mand ) || 25170 | details::imatch(symbol,s_mor ) || 25171 | details::imatch(symbol,s_multi ) || 25172 | details::imatch(symbol,s_mswitch) 25173 | ) && 25174 | settings_.function_enabled(symbol); 25175 | } 25176 | 25177 | bool is_invalid_logic_operation(const details::operator_type operation) const 25178 | { 25179 | return settings_.logic_disabled(operation); 25180 | } 25181 | 25182 | bool is_invalid_arithmetic_operation(const details::operator_type operation) const 25183 | { 25184 | return settings_.arithmetic_disabled(operation); 25185 | } 25186 | 25187 | bool is_invalid_assignment_operation(const details::operator_type operation) const 25188 | { 25189 | return settings_.assignment_disabled(operation); 25190 | } 25191 | 25192 | bool is_invalid_inequality_operation(const details::operator_type operation) const 25193 | { 25194 | return settings_.inequality_disabled(operation); 25195 | } 25196 | 25197 | #ifdef exprtk_enable_debugging 25198 | inline void next_token() 25199 | { 25200 | const std::string ct_str = current_token().value; 25201 | const std::size_t ct_pos = current_token().position; 25202 | parser_helper::next_token(); 25203 | const std::string depth(2 * state_.scope_depth,' '); 25204 | exprtk_debug(("%s" 25205 | "prev[%s | %04d] --> curr[%s | %04d] stack_level: %3d\n", 25206 | depth.c_str(), 25207 | ct_str.c_str(), 25208 | static_cast<unsigned int>(ct_pos), 25209 | current_token().value.c_str(), 25210 | static_cast<unsigned int>(current_token().position), 25211 | static_cast<unsigned int>(state_.stack_depth))); 25212 | } 25213 | #endif 25214 | 25215 | inline expression_node_ptr parse_corpus() 25216 | { 25217 | std::vector<expression_node_ptr> arg_list; 25218 | std::vector<bool> side_effect_list; 25219 | 25220 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 25221 | 25222 | lexer::token begin_token; 25223 | lexer::token end_token; 25224 | 25225 | for ( ; ; ) 25226 | { 25227 | state_.side_effect_present = false; 25228 | 25229 | begin_token = current_token(); 25230 | 25231 | expression_node_ptr arg = parse_expression(); 25232 | 25233 | if (0 == arg) 25234 | { 25235 | if (error_list_.empty()) 25236 | { 25237 | set_error(make_error( 25238 | parser_error::e_syntax, 25239 | current_token(), 25240 | "ERR009 - Invalid expression encountered", 25241 | exprtk_error_location)); 25242 | } 25243 | 25244 | return error_node(); 25245 | } 25246 | else 25247 | { 25248 | arg_list.push_back(arg); 25249 | 25250 | side_effect_list.push_back(state_.side_effect_present); 25251 | 25252 | end_token = current_token(); 25253 | 25254 | const std::string sub_expr = construct_subexpr(begin_token, end_token); 25255 | 25256 | exprtk_debug(("parse_corpus(%02d) Subexpr: %s\n", 25257 | static_cast<int>(arg_list.size() - 1), 25258 | sub_expr.c_str())); 25259 | 25260 | exprtk_debug(("parse_corpus(%02d) - Side effect present: %s\n", 25261 | static_cast<int>(arg_list.size() - 1), 25262 | state_.side_effect_present ? "true" : "false")); 25263 | 25264 | exprtk_debug(("-------------------------------------------------\n")); 25265 | } 25266 | 25267 | if (token_is(token_t::e_eof,prsrhlpr_t::e_hold)) 25268 | { 25269 | if (lexer().finished()) 25270 | break; 25271 | else 25272 | next_token(); 25273 | } 25274 | else if ( 25275 | !settings_.commutative_check_enabled() && 25276 | ( 25277 | current_token().type == token_t::e_symbol || 25278 | current_token().type == token_t::e_number || 25279 | current_token().type == token_t::e_string || 25280 | token_is_bracket(prsrhlpr_t::e_hold) 25281 | ) 25282 | ) 25283 | { 25284 | set_error(make_error( 25285 | parser_error::e_syntax, 25286 | current_token(), 25287 | "ERR010 - Invalid syntax '" + current_token().value + "' possible missing operator or context", 25288 | exprtk_error_location)); 25289 | 25290 | return error_node(); 25291 | } 25292 | } 25293 | 25294 | if ( 25295 | !arg_list.empty() && 25296 | is_return_node(arg_list.back()) 25297 | ) 25298 | { 25299 | dec_.final_stmt_return_ = true; 25300 | } 25301 | 25302 | const expression_node_ptr result = simplify(arg_list,side_effect_list); 25303 | 25304 | svd.delete_ptr = (0 == result); 25305 | 25306 | return result; 25307 | } 25308 | 25309 | std::string construct_subexpr(lexer::token& begin_token, 25310 | lexer::token& end_token, 25311 | const bool cleanup_whitespace = true) 25312 | { 25313 | std::string result = lexer().substr(begin_token.position,end_token.position); 25314 | if (cleanup_whitespace) 25315 | { 25316 | for (std::size_t i = 0; i < result.size(); ++i) 25317 | { 25318 | if (details::is_whitespace(result[i])) result[i] = ' '; 25319 | } 25320 | } 25321 | 25322 | return result; 25323 | } 25324 | 25325 | static const precedence_level default_precedence = e_level00; 25326 | 25327 | struct state_t 25328 | { 25329 | inline void set(const precedence_level& l, 25330 | const precedence_level& r, 25331 | const details::operator_type& o, 25332 | const token_t& tkn = token_t()) 25333 | { 25334 | left = l; 25335 | right = r; 25336 | operation = o; 25337 | token = tkn; 25338 | } 25339 | 25340 | inline void reset() 25341 | { 25342 | left = e_level00; 25343 | right = e_level00; 25344 | operation = details::e_default; 25345 | } 25346 | 25347 | precedence_level left; 25348 | precedence_level right; 25349 | details::operator_type operation; 25350 | token_t token; 25351 | }; 25352 | 25353 | inline void push_current_state(const state_t current_state) 25354 | { 25355 | current_state_stack_.push_back(current_state); 25356 | } 25357 | 25358 | inline void pop_current_state() 25359 | { 25360 | if (!current_state_stack_.empty()) 25361 | { 25362 | current_state_stack_.pop_back(); 25363 | } 25364 | } 25365 | 25366 | inline state_t current_state() const 25367 | { 25368 | return (!current_state_stack_.empty()) ? 25369 | current_state_stack_.back() : 25370 | state_t(); 25371 | } 25372 | 25373 | inline bool halt_compilation_check() 25374 | { 25375 | compilation_check::compilation_context context; 25376 | 25377 | if (compilation_check_ptr_ && !compilation_check_ptr_->continue_compilation(context)) 25378 | { 25379 | const std::string error_message = 25380 | !context.error_message.empty() ? " Details: " + context.error_message : "" 25381 | 25382 | set_error(make_error( 25383 | parser_error::e_parser, 25384 | token_t(), 25385 | "ERR011 - Internal compilation check failed." + error_message, 25386 | exprtk_error_location)); 25387 | 25388 | return true; 25389 | } 25390 | 25391 | return false; 25392 | } 25393 | 25394 | inline expression_node_ptr parse_expression(precedence_level precedence = e_level00) 25395 | { 25396 | if (halt_compilation_check()) 25397 | { 25398 | exprtk_debug(("halt_compilation_check() - parse_expression checkpoint 2\n")); 25399 | return error_node(); 25400 | } 25401 | 25402 | stack_limit_handler slh(*this); 25403 | 25404 | if (!slh) 25405 | { 25406 | return error_node(); 25407 | } 25408 | 25409 | expression_node_ptr expression = parse_branch(precedence); 25410 | 25411 | if (0 == expression) 25412 | { 25413 | return error_node(); 25414 | } 25415 | 25416 | if (token_is(token_t::e_eof,prsrhlpr_t::e_hold)) 25417 | { 25418 | return expression; 25419 | } 25420 | 25421 | bool break_loop = false; 25422 | 25423 | state_t current_state; 25424 | 25425 | for ( ; ; ) 25426 | { 25427 | current_state.reset(); 25428 | 25429 | switch (current_token().type) 25430 | { 25431 | case token_t::e_assign : current_state.set(e_level00, e_level00, details::e_assign, current_token()); break; 25432 | case token_t::e_addass : current_state.set(e_level00, e_level00, details::e_addass, current_token()); break; 25433 | case token_t::e_subass : current_state.set(e_level00, e_level00, details::e_subass, current_token()); break; 25434 | case token_t::e_mulass : current_state.set(e_level00, e_level00, details::e_mulass, current_token()); break; 25435 | case token_t::e_divass : current_state.set(e_level00, e_level00, details::e_divass, current_token()); break; 25436 | case token_t::e_modass : current_state.set(e_level00, e_level00, details::e_modass, current_token()); break; 25437 | case token_t::e_swap : current_state.set(e_level00, e_level00, details::e_swap , current_token()); break; 25438 | case token_t::e_lt : current_state.set(e_level05, e_level06, details::e_lt , current_token()); break; 25439 | case token_t::e_lte : current_state.set(e_level05, e_level06, details::e_lte , current_token()); break; 25440 | case token_t::e_eq : current_state.set(e_level05, e_level06, details::e_eq , current_token()); break; 25441 | case token_t::e_ne : current_state.set(e_level05, e_level06, details::e_ne , current_token()); break; 25442 | case token_t::e_gte : current_state.set(e_level05, e_level06, details::e_gte , current_token()); break; 25443 | case token_t::e_gt : current_state.set(e_level05, e_level06, details::e_gt , current_token()); break; 25444 | case token_t::e_add : current_state.set(e_level07, e_level08, details::e_add , current_token()); break; 25445 | case token_t::e_sub : current_state.set(e_level07, e_level08, details::e_sub , current_token()); break; 25446 | case token_t::e_div : current_state.set(e_level10, e_level11, details::e_div , current_token()); break; 25447 | case token_t::e_mul : current_state.set(e_level10, e_level11, details::e_mul , current_token()); break; 25448 | case token_t::e_mod : current_state.set(e_level10, e_level11, details::e_mod , current_token()); break; 25449 | case token_t::e_pow : current_state.set(e_level12, e_level12, details::e_pow , current_token()); break; 25450 | default : 25451 | if (token_t::e_symbol == current_token().type) 25452 | { 25453 | static const std::string s_and = "and" ; 25454 | static const std::string s_nand = "nand" ; 25455 | static const std::string s_or = "or" ; 25456 | static const std::string s_nor = "nor" ; 25457 | static const std::string s_xor = "xor" ; 25458 | static const std::string s_xnor = "xnor" ; 25459 | static const std::string s_in = "in" ; 25460 | static const std::string s_like = "like" ; 25461 | static const std::string s_ilike = "ilike" 25462 | static const std::string s_and1 = "&" ; 25463 | static const std::string s_or1 = "|" ; 25464 | static const std::string s_not = "not" ; 25465 | 25466 | if (details::imatch(current_token().value,s_and)) 25467 | { 25468 | current_state.set(e_level03, e_level04, details::e_and, current_token()); 25469 | break; 25470 | } 25471 | else if (details::imatch(current_token().value,s_and1)) 25472 | { 25473 | #ifndef exprtk_disable_sc_andor 25474 | current_state.set(e_level03, e_level04, details::e_scand, current_token()); 25475 | #else 25476 | current_state.set(e_level03, e_level04, details::e_and, current_token()); 25477 | #endif 25478 | break; 25479 | } 25480 | else if (details::imatch(current_token().value,s_nand)) 25481 | { 25482 | current_state.set(e_level03, e_level04, details::e_nand, current_token()); 25483 | break; 25484 | } 25485 | else if (details::imatch(current_token().value,s_or)) 25486 | { 25487 | current_state.set(e_level01, e_level02, details::e_or, current_token()); 25488 | break; 25489 | } 25490 | else if (details::imatch(current_token().value,s_or1)) 25491 | { 25492 | #ifndef exprtk_disable_sc_andor 25493 | current_state.set(e_level01, e_level02, details::e_scor, current_token()); 25494 | #else 25495 | current_state.set(e_level01, e_level02, details::e_or, current_token()); 25496 | #endif 25497 | break; 25498 | } 25499 | else if (details::imatch(current_token().value,s_nor)) 25500 | { 25501 | current_state.set(e_level01, e_level02, details::e_nor, current_token()); 25502 | break; 25503 | } 25504 | else if (details::imatch(current_token().value,s_xor)) 25505 | { 25506 | current_state.set(e_level01, e_level02, details::e_xor, current_token()); 25507 | break; 25508 | } 25509 | else if (details::imatch(current_token().value,s_xnor)) 25510 | { 25511 | current_state.set(e_level01, e_level02, details::e_xnor, current_token()); 25512 | break; 25513 | } 25514 | else if (details::imatch(current_token().value,s_in)) 25515 | { 25516 | current_state.set(e_level04, e_level04, details::e_in, current_token()); 25517 | break; 25518 | } 25519 | else if (details::imatch(current_token().value,s_like)) 25520 | { 25521 | current_state.set(e_level04, e_level04, details::e_like, current_token()); 25522 | break; 25523 | } 25524 | else if (details::imatch(current_token().value,s_ilike)) 25525 | { 25526 | current_state.set(e_level04, e_level04, details::e_ilike, current_token()); 25527 | break; 25528 | } 25529 | else if (details::imatch(current_token().value,s_not)) 25530 | { 25531 | break; 25532 | } 25533 | } 25534 | 25535 | break_loop = true; 25536 | } 25537 | 25538 | if (break_loop) 25539 | { 25540 | parse_pending_string_rangesize(expression); 25541 | break; 25542 | } 25543 | else if (current_state.left < precedence) 25544 | break; 25545 | 25546 | const lexer::token prev_token = current_token(); 25547 | 25548 | next_token(); 25549 | 25550 | expression_node_ptr right_branch = error_node(); 25551 | expression_node_ptr new_expression = error_node(); 25552 | 25553 | if (is_invalid_logic_operation(current_state.operation)) 25554 | { 25555 | free_node(node_allocator_, expression); 25556 | 25557 | set_error(make_error( 25558 | parser_error::e_syntax, 25559 | prev_token, 25560 | "ERR012 - Invalid or disabled logic operation '" + details::to_str(current_state.operation) + "'", 25561 | exprtk_error_location)); 25562 | 25563 | return error_node(); 25564 | } 25565 | else if (is_invalid_arithmetic_operation(current_state.operation)) 25566 | { 25567 | free_node(node_allocator_, expression); 25568 | 25569 | set_error(make_error( 25570 | parser_error::e_syntax, 25571 | prev_token, 25572 | "ERR013 - Invalid or disabled arithmetic operation '" + details::to_str(current_state.operation) + "'", 25573 | exprtk_error_location)); 25574 | 25575 | return error_node(); 25576 | } 25577 | else if (is_invalid_inequality_operation(current_state.operation)) 25578 | { 25579 | free_node(node_allocator_, expression); 25580 | 25581 | set_error(make_error( 25582 | parser_error::e_syntax, 25583 | prev_token, 25584 | "ERR014 - Invalid inequality operation '" + details::to_str(current_state.operation) + "'", 25585 | exprtk_error_location)); 25586 | 25587 | return error_node(); 25588 | } 25589 | else if (is_invalid_assignment_operation(current_state.operation)) 25590 | { 25591 | free_node(node_allocator_, expression); 25592 | 25593 | set_error(make_error( 25594 | parser_error::e_syntax, 25595 | prev_token, 25596 | "ERR015 - Invalid or disabled assignment operation '" + details::to_str(current_state.operation) + "'", 25597 | exprtk_error_location)); 25598 | 25599 | return error_node(); 25600 | } 25601 | 25602 | if (0 != (right_branch = parse_expression(current_state.right))) 25603 | { 25604 | if ( 25605 | details::is_return_node(expression ) || 25606 | details::is_return_node(right_branch) 25607 | ) 25608 | { 25609 | free_node(node_allocator_, expression ); 25610 | free_node(node_allocator_, right_branch); 25611 | 25612 | set_error(make_error( 25613 | parser_error::e_syntax, 25614 | prev_token, 25615 | "ERR016 - Return statements cannot be part of sub-expressions", 25616 | exprtk_error_location)); 25617 | 25618 | return error_node(); 25619 | } 25620 | 25621 | push_current_state(current_state); 25622 | 25623 | new_expression = expression_generator_ 25624 | ( 25625 | current_state.operation, 25626 | expression, 25627 | right_branch 25628 | ); 25629 | 25630 | pop_current_state(); 25631 | } 25632 | 25633 | if (0 == new_expression) 25634 | { 25635 | if (error_list_.empty()) 25636 | { 25637 | set_error(make_error( 25638 | parser_error::e_syntax, 25639 | prev_token, 25640 | !synthesis_error_.empty() ? 25641 | synthesis_error_ : 25642 | "ERR017 - General parsing error at token: '" + prev_token.value + "'", 25643 | exprtk_error_location)); 25644 | } 25645 | 25646 | free_node(node_allocator_, expression ); 25647 | free_node(node_allocator_, right_branch); 25648 | 25649 | return error_node(); 25650 | } 25651 | else 25652 | { 25653 | if ( 25654 | token_is(token_t::e_ternary,prsrhlpr_t::e_hold) && 25655 | (e_level00 == precedence) 25656 | ) 25657 | { 25658 | expression = parse_ternary_conditional_statement(new_expression); 25659 | } 25660 | else 25661 | expression = new_expression; 25662 | 25663 | parse_pending_string_rangesize(expression); 25664 | } 25665 | } 25666 | 25667 | if ((0 != expression) && (expression->node_depth() > settings_.max_node_depth_)) 25668 | { 25669 | set_error(make_error( 25670 | parser_error::e_syntax, 25671 | current_token(), 25672 | "ERR018 - Expression depth of " + details::to_str(static_cast<int>(expression->node_depth())) + 25673 | " exceeds maximum allowed expression depth of " + details::to_str(static_cast<int>(settings_.max_node_depth_)), 25674 | exprtk_error_location)); 25675 | 25676 | free_node(node_allocator_, expression); 25677 | 25678 | return error_node(); 25679 | } 25680 | else if ( 25681 | !settings_.commutative_check_enabled() && 25682 | !details::is_logic_opr(current_token().value) && 25683 | (current_state.operation == details::e_default) && 25684 | ( 25685 | current_token().type == token_t::e_symbol || 25686 | current_token().type == token_t::e_number || 25687 | current_token().type == token_t::e_string 25688 | ) 25689 | ) 25690 | { 25691 | set_error(make_error( 25692 | parser_error::e_syntax, 25693 | current_token(), 25694 | "ERR019 - Invalid syntax '" + current_token().value + "' possible missing operator or context", 25695 | exprtk_error_location)); 25696 | 25697 | free_node(node_allocator_, expression); 25698 | 25699 | return error_node(); 25700 | } 25701 | 25702 | return expression; 25703 | } 25704 | 25705 | bool simplify_unary_negation_branch(expression_node_ptr& node) 25706 | { 25707 | { 25708 | typedef details::unary_branch_node<T,details::neg_op<T> > ubn_t; 25709 | ubn_t* n = dynamic_cast<ubn_t*>(node); 25710 | 25711 | if (n) 25712 | { 25713 | expression_node_ptr un_r = n->branch(0); 25714 | n->release(); 25715 | free_node(node_allocator_, node); 25716 | node = un_r; 25717 | 25718 | return true; 25719 | } 25720 | } 25721 | 25722 | { 25723 | typedef details::unary_variable_node<T,details::neg_op<T> > uvn_t; 25724 | 25725 | uvn_t* n = dynamic_cast<uvn_t*>(node); 25726 | 25727 | if (n) 25728 | { 25729 | const T& v = n->v(); 25730 | expression_node_ptr return_node = error_node(); 25731 | 25732 | if ( 25733 | (0 != (return_node = symtab_store_.get_variable(v))) || 25734 | (0 != (return_node = sem_ .get_variable(v))) 25735 | ) 25736 | { 25737 | free_node(node_allocator_, node); 25738 | node = return_node; 25739 | 25740 | return true; 25741 | } 25742 | else 25743 | { 25744 | set_error(make_error( 25745 | parser_error::e_syntax, 25746 | current_token(), 25747 | "ERR020 - Failed to find variable node in symbol table", 25748 | exprtk_error_location)); 25749 | 25750 | free_node(node_allocator_, node); 25751 | 25752 | return false; 25753 | } 25754 | } 25755 | } 25756 | 25757 | return false; 25758 | } 25759 | 25760 | static inline expression_node_ptr error_node() 25761 | { 25762 | return reinterpret_cast<expression_node_ptr>(0); 25763 | } 25764 | 25765 | struct scoped_expression_delete 25766 | { 25767 | scoped_expression_delete(parser<T>& pr, expression_node_ptr& expression) 25768 | : delete_ptr(true) 25769 | , parser_(pr) 25770 | , expression_(expression) 25771 | {} 25772 | 25773 | ~scoped_expression_delete() 25774 | { 25775 | if (delete_ptr) 25776 | { 25777 | free_node(parser_.node_allocator_, expression_); 25778 | } 25779 | } 25780 | 25781 | bool delete_ptr; 25782 | parser<T>& parser_; 25783 | expression_node_ptr& expression_; 25784 | 25785 | private: 25786 | 25787 | scoped_expression_delete(const scoped_expression_delete&) exprtk_delete; 25788 | scoped_expression_delete& operator=(const scoped_expression_delete&) exprtk_delete; 25789 | }; 25790 | 25791 | template <typename Type, std::size_t N> 25792 | struct scoped_delete 25793 | { 25794 | typedef Type* ptr_t; 25795 | 25796 | scoped_delete(parser<T>& pr, ptr_t& p) 25797 | : delete_ptr(true) 25798 | , parser_(pr) 25799 | , p_(&p) 25800 | {} 25801 | 25802 | scoped_delete(parser<T>& pr, ptr_t (&p)[N]) 25803 | : delete_ptr(true) 25804 | , parser_(pr) 25805 | , p_(&p[0]) 25806 | {} 25807 | 25808 | ~scoped_delete() 25809 | { 25810 | if (delete_ptr) 25811 | { 25812 | for (std::size_t i = 0; i < N; ++i) 25813 | { 25814 | free_node(parser_.node_allocator_, p_[i]); 25815 | } 25816 | } 25817 | } 25818 | 25819 | bool delete_ptr; 25820 | parser<T>& parser_; 25821 | ptr_t* p_; 25822 | 25823 | private: 25824 | 25825 | scoped_delete(const scoped_delete<Type,N>&) exprtk_delete; 25826 | scoped_delete<Type,N>& operator=(const scoped_delete<Type,N>&) exprtk_delete; 25827 | }; 25828 | 25829 | template <typename Type> 25830 | struct scoped_deq_delete 25831 | { 25832 | typedef Type* ptr_t; 25833 | 25834 | scoped_deq_delete(parser<T>& pr, std::deque<ptr_t>& deq) 25835 | : delete_ptr(true) 25836 | , parser_(pr) 25837 | , deq_(deq) 25838 | {} 25839 | 25840 | ~scoped_deq_delete() 25841 | { 25842 | if (delete_ptr && !deq_.empty()) 25843 | { 25844 | for (std::size_t i = 0; i < deq_.size(); ++i) 25845 | { 25846 | exprtk_debug(("~scoped_deq_delete() - deleting node: %p\n", reinterpret_cast<void*>(deq_[i]))); 25847 | free_node(parser_.node_allocator_,deq_[i]); 25848 | } 25849 | 25850 | deq_.clear(); 25851 | } 25852 | } 25853 | 25854 | bool delete_ptr; 25855 | parser<T>& parser_; 25856 | std::deque<ptr_t>& deq_; 25857 | 25858 | private: 25859 | 25860 | scoped_deq_delete(const scoped_deq_delete<Type>&) exprtk_delete; 25861 | scoped_deq_delete<Type>& operator=(const scoped_deq_delete<Type>&) exprtk_delete; 25862 | }; 25863 | 25864 | template <typename Type> 25865 | struct scoped_vec_delete 25866 | { 25867 | typedef Type* ptr_t; 25868 | 25869 | scoped_vec_delete(parser<T>& pr, std::vector<ptr_t>& vec) 25870 | : delete_ptr(true) 25871 | , parser_(pr) 25872 | , vec_(vec) 25873 | {} 25874 | 25875 | ~scoped_vec_delete() 25876 | { 25877 | if (delete_ptr && !vec_.empty()) 25878 | { 25879 | for (std::size_t i = 0; i < vec_.size(); ++i) 25880 | { 25881 | exprtk_debug(("~scoped_vec_delete() - deleting node: %p\n", reinterpret_cast<void*>(vec_[i]))); 25882 | free_node(parser_.node_allocator_,vec_[i]); 25883 | } 25884 | 25885 | vec_.clear(); 25886 | } 25887 | } 25888 | 25889 | ptr_t operator[](const std::size_t index) 25890 | { 25891 | return vec_[index]; 25892 | } 25893 | 25894 | bool delete_ptr; 25895 | parser<T>& parser_; 25896 | std::vector<ptr_t>& vec_; 25897 | 25898 | private: 25899 | 25900 | scoped_vec_delete(const scoped_vec_delete<Type>&) exprtk_delete; 25901 | scoped_vec_delete<Type>& operator=(const scoped_vec_delete<Type>&) exprtk_delete; 25902 | }; 25903 | 25904 | struct scoped_bool_negator 25905 | { 25906 | explicit scoped_bool_negator(bool& bb) 25907 | : b(bb) 25908 | { b = !b; } 25909 | 25910 | ~scoped_bool_negator() 25911 | { b = !b; } 25912 | 25913 | bool& b; 25914 | }; 25915 | 25916 | struct scoped_bool_or_restorer 25917 | { 25918 | explicit scoped_bool_or_restorer(bool& bb) 25919 | : b(bb) 25920 | , original_value_(bb) 25921 | {} 25922 | 25923 | ~scoped_bool_or_restorer() 25924 | { 25925 | b = b || original_value_; 25926 | } 25927 | 25928 | bool& b; 25929 | bool original_value_; 25930 | }; 25931 | 25932 | struct scoped_inc_dec 25933 | { 25934 | explicit scoped_inc_dec(std::size_t& v) 25935 | : v_(v) 25936 | { ++v_; } 25937 | 25938 | ~scoped_inc_dec() 25939 | { 25940 | assert(v_ > 0); 25941 | --v_; 25942 | } 25943 | 25944 | std::size_t& v_; 25945 | }; 25946 | 25947 | inline expression_node_ptr parse_function_invocation(ifunction<T>* function, const std::string& function_name) 25948 | { 25949 | expression_node_ptr func_node = reinterpret_cast<expression_node_ptr>(0); 25950 | 25951 | switch (function->param_count) 25952 | { 25953 | case 0 : func_node = parse_function_call_0 (function,function_name); break; 25954 | case 1 : func_node = parse_function_call< 1>(function,function_name); break; 25955 | case 2 : func_node = parse_function_call< 2>(function,function_name); break; 25956 | case 3 : func_node = parse_function_call< 3>(function,function_name); break; 25957 | case 4 : func_node = parse_function_call< 4>(function,function_name); break; 25958 | case 5 : func_node = parse_function_call< 5>(function,function_name); break; 25959 | case 6 : func_node = parse_function_call< 6>(function,function_name); break; 25960 | case 7 : func_node = parse_function_call< 7>(function,function_name); break; 25961 | case 8 : func_node = parse_function_call< 8>(function,function_name); break; 25962 | case 9 : func_node = parse_function_call< 9>(function,function_name); break; 25963 | case 10 : func_node = parse_function_call<10>(function,function_name); break; 25964 | case 11 : func_node = parse_function_call<11>(function,function_name); break; 25965 | case 12 : func_node = parse_function_call<12>(function,function_name); break; 25966 | case 13 : func_node = parse_function_call<13>(function,function_name); break; 25967 | case 14 : func_node = parse_function_call<14>(function,function_name); break; 25968 | case 15 : func_node = parse_function_call<15>(function,function_name); break; 25969 | case 16 : func_node = parse_function_call<16>(function,function_name); break; 25970 | case 17 : func_node = parse_function_call<17>(function,function_name); break; 25971 | case 18 : func_node = parse_function_call<18>(function,function_name); break; 25972 | case 19 : func_node = parse_function_call<19>(function,function_name); break; 25973 | case 20 : func_node = parse_function_call<20>(function,function_name); break; 25974 | default : { 25975 | set_error(make_error( 25976 | parser_error::e_syntax, 25977 | current_token(), 25978 | "ERR021 - Invalid number of parameters for function: '" + function_name + "'", 25979 | exprtk_error_location)); 25980 | 25981 | return error_node(); 25982 | } 25983 | } 25984 | 25985 | if (func_node) 25986 | return func_node; 25987 | else 25988 | { 25989 | set_error(make_error( 25990 | parser_error::e_syntax, 25991 | current_token(), 25992 | "ERR022 - Failed to generate call to function: '" + function_name + "'", 25993 | exprtk_error_location)); 25994 | 25995 | return error_node(); 25996 | } 25997 | } 25998 | 25999 | template <std::size_t NumberofParameters> 26000 | inline expression_node_ptr parse_function_call(ifunction<T>* function, const std::string& function_name) 26001 | { 26002 | #ifdef _MSC_VER 26003 | #pragma warning(push) 26004 | #pragma warning(disable: 4127) 26005 | #endif 26006 | if (0 == NumberofParameters) 26007 | { 26008 | set_error(make_error( 26009 | parser_error::e_syntax, 26010 | current_token(), 26011 | "ERR023 - Expecting ifunction '" + function_name + "' to have non-zero parameter count", 26012 | exprtk_error_location)); 26013 | 26014 | return error_node(); 26015 | } 26016 | #ifdef _MSC_VER 26017 | #pragma warning(pop) 26018 | #endif 26019 | 26020 | expression_node_ptr branch[NumberofParameters]; 26021 | expression_node_ptr result = error_node(); 26022 | 26023 | std::fill_n(branch, NumberofParameters, reinterpret_cast<expression_node_ptr>(0)); 26024 | 26025 | scoped_delete<expression_node_t,NumberofParameters> sd((*this),branch); 26026 | 26027 | next_token(); 26028 | 26029 | if (!token_is(token_t::e_lbracket)) 26030 | { 26031 | set_error(make_error( 26032 | parser_error::e_syntax, 26033 | current_token(), 26034 | "ERR024 - Expecting argument list for function: '" + function_name + "'", 26035 | exprtk_error_location)); 26036 | 26037 | return error_node(); 26038 | } 26039 | 26040 | for (int i = 0; i < static_cast<int>(NumberofParameters); ++i) 26041 | { 26042 | branch[i] = parse_expression(); 26043 | 26044 | if (0 == branch[i]) 26045 | { 26046 | set_error(make_error( 26047 | parser_error::e_syntax, 26048 | current_token(), 26049 | "ERR025 - Failed to parse argument " + details::to_str(i) + " for function: '" + function_name + "'", 26050 | exprtk_error_location)); 26051 | 26052 | return error_node(); 26053 | } 26054 | else if (i < static_cast<int>(NumberofParameters - 1)) 26055 | { 26056 | if (!token_is(token_t::e_comma)) 26057 | { 26058 | set_error(make_error( 26059 | parser_error::e_syntax, 26060 | current_token(), 26061 | "ERR026 - Invalid number of arguments for function: '" + function_name + "'", 26062 | exprtk_error_location)); 26063 | 26064 | return error_node(); 26065 | } 26066 | } 26067 | } 26068 | 26069 | if (!token_is(token_t::e_rbracket)) 26070 | { 26071 | set_error(make_error( 26072 | parser_error::e_syntax, 26073 | current_token(), 26074 | "ERR027 - Invalid number of arguments for function: '" + function_name + "'", 26075 | exprtk_error_location)); 26076 | 26077 | return error_node(); 26078 | } 26079 | else 26080 | result = expression_generator_.function(function,branch); 26081 | 26082 | sd.delete_ptr = (0 == result); 26083 | 26084 | return result; 26085 | } 26086 | 26087 | inline expression_node_ptr parse_function_call_0(ifunction<T>* function, const std::string& function_name) 26088 | { 26089 | expression_node_ptr result = expression_generator_.function(function); 26090 | 26091 | state_.side_effect_present = function->has_side_effects(); 26092 | 26093 | next_token(); 26094 | 26095 | if ( 26096 | token_is(token_t::e_lbracket) && 26097 | !token_is(token_t::e_rbracket) 26098 | ) 26099 | { 26100 | set_error(make_error( 26101 | parser_error::e_syntax, 26102 | current_token(), 26103 | "ERR028 - Expecting '()' to proceed call to function: '" + function_name + "'", 26104 | exprtk_error_location)); 26105 | 26106 | free_node(node_allocator_, result); 26107 | 26108 | return error_node(); 26109 | } 26110 | else 26111 | return result; 26112 | } 26113 | 26114 | template <std::size_t MaxNumberofParameters> 26115 | inline std::size_t parse_base_function_call(expression_node_ptr (¶m_list)[MaxNumberofParameters], const std::string& function_name = "") 26116 | { 26117 | std::fill_n(param_list, MaxNumberofParameters, reinterpret_cast<expression_node_ptr>(0)); 26118 | 26119 | scoped_delete<expression_node_t,MaxNumberofParameters> sd((*this),param_list); 26120 | 26121 | next_token(); 26122 | 26123 | if (!token_is(token_t::e_lbracket)) 26124 | { 26125 | set_error(make_error( 26126 | parser_error::e_syntax, 26127 | current_token(), 26128 | "ERR029 - Expected a '(' at start of function call to '" + function_name + 26129 | "', instead got: '" + current_token().value + "'", 26130 | exprtk_error_location)); 26131 | 26132 | return 0; 26133 | } 26134 | 26135 | if (token_is(token_t::e_rbracket, e_hold)) 26136 | { 26137 | set_error(make_error( 26138 | parser_error::e_syntax, 26139 | current_token(), 26140 | "ERR030 - Expected at least one input parameter for function call '" + function_name + "'", 26141 | exprtk_error_location)); 26142 | 26143 | return 0; 26144 | } 26145 | 26146 | std::size_t param_index = 0; 26147 | 26148 | for (; param_index < MaxNumberofParameters; ++param_index) 26149 | { 26150 | param_list[param_index] = parse_expression(); 26151 | 26152 | if (0 == param_list[param_index]) 26153 | return 0; 26154 | else if (token_is(token_t::e_rbracket)) 26155 | { 26156 | sd.delete_ptr = false; 26157 | break; 26158 | } 26159 | else if (token_is(token_t::e_comma)) 26160 | continue; 26161 | else 26162 | { 26163 | set_error(make_error( 26164 | parser_error::e_syntax, 26165 | current_token(), 26166 | "ERR031 - Expected a ',' between function input parameters, instead got: '" + current_token().value + "'", 26167 | exprtk_error_location)); 26168 | 26169 | return 0; 26170 | } 26171 | } 26172 | 26173 | if (sd.delete_ptr) 26174 | { 26175 | set_error(make_error( 26176 | parser_error::e_syntax, 26177 | current_token(), 26178 | "ERR032 - Invalid number of input parameters passed to function '" + function_name + "'", 26179 | exprtk_error_location)); 26180 | 26181 | return 0; 26182 | } 26183 | 26184 | return (param_index + 1); 26185 | } 26186 | 26187 | inline expression_node_ptr parse_base_operation() 26188 | { 26189 | typedef std::pair<base_ops_map_t::iterator,base_ops_map_t::iterator> map_range_t; 26190 | 26191 | const std::string operation_name = current_token().value; 26192 | const token_t diagnostic_token = current_token(); 26193 | 26194 | map_range_t itr_range = base_ops_map_.equal_range(operation_name); 26195 | 26196 | if (0 == std::distance(itr_range.first,itr_range.second)) 26197 | { 26198 | set_error(make_error( 26199 | parser_error::e_syntax, 26200 | diagnostic_token, 26201 | "ERR033 - No entry found for base operation: " + operation_name, 26202 | exprtk_error_location)); 26203 | 26204 | return error_node(); 26205 | } 26206 | 26207 | static const std::size_t MaxNumberofParameters = 4; 26208 | expression_node_ptr param_list[MaxNumberofParameters] = {0}; 26209 | 26210 | const std::size_t parameter_count = parse_base_function_call(param_list, operation_name); 26211 | 26212 | if ((parameter_count > 0) && (parameter_count <= MaxNumberofParameters)) 26213 | { 26214 | for (base_ops_map_t::iterator itr = itr_range.first; itr != itr_range.second; ++itr) 26215 | { 26216 | const details::base_operation_t& operation = itr->second; 26217 | 26218 | if (operation.num_params == parameter_count) 26219 | { 26220 | switch (parameter_count) 26221 | { 26222 | #define base_opr_case(N) \ 26223 | case N : { \ 26224 | expression_node_ptr pl##N[N] = {0}; \ 26225 | std::copy(param_list, param_list + N, pl##N); \ 26226 | lodge_symbol(operation_name, e_st_function); \ 26227 | return expression_generator_(operation.type, pl##N); \ 26228 | } \ 26229 | 26230 | base_opr_case(1) 26231 | base_opr_case(2) 26232 | base_opr_case(3) 26233 | base_opr_case(4) 26234 | #undef base_opr_case 26235 | } 26236 | } 26237 | } 26238 | } 26239 | 26240 | for (std::size_t i = 0; i < MaxNumberofParameters; ++i) 26241 | { 26242 | free_node(node_allocator_, param_list[i]); 26243 | } 26244 | 26245 | set_error(make_error( 26246 | parser_error::e_syntax, 26247 | diagnostic_token, 26248 | "ERR034 - Invalid number of input parameters for call to function: '" + operation_name + "'", 26249 | exprtk_error_location)); 26250 | 26251 | return error_node(); 26252 | } 26253 | 26254 | inline expression_node_ptr parse_conditional_statement_01(expression_node_ptr condition) 26255 | { 26256 | // Parse: [if][(][condition][,][consequent][,][alternative][)] 26257 | 26258 | expression_node_ptr consequent = error_node(); 26259 | expression_node_ptr alternative = error_node(); 26260 | 26261 | bool result = true; 26262 | 26263 | if (!token_is(token_t::e_comma)) 26264 | { 26265 | set_error(make_error( 26266 | parser_error::e_syntax, 26267 | current_token(), 26268 | "ERR035 - Expected ',' between if-statement condition and consequent", 26269 | exprtk_error_location)); 26270 | 26271 | result = false; 26272 | } 26273 | else if (0 == (consequent = parse_expression())) 26274 | { 26275 | set_error(make_error( 26276 | parser_error::e_syntax, 26277 | current_token(), 26278 | "ERR036 - Failed to parse consequent for if-statement", 26279 | exprtk_error_location)); 26280 | 26281 | result = false; 26282 | } 26283 | else if (!token_is(token_t::e_comma)) 26284 | { 26285 | set_error(make_error( 26286 | parser_error::e_syntax, 26287 | current_token(), 26288 | "ERR037 - Expected ',' between if-statement consequent and alternative", 26289 | exprtk_error_location)); 26290 | 26291 | result = false; 26292 | } 26293 | else if (0 == (alternative = parse_expression())) 26294 | { 26295 | set_error(make_error( 26296 | parser_error::e_syntax, 26297 | current_token(), 26298 | "ERR038 - Failed to parse alternative for if-statement", 26299 | exprtk_error_location)); 26300 | 26301 | result = false; 26302 | } 26303 | else if (!token_is(token_t::e_rbracket)) 26304 | { 26305 | set_error(make_error( 26306 | parser_error::e_syntax, 26307 | current_token(), 26308 | "ERR039 - Expected ')' at the end of if-statement", 26309 | exprtk_error_location)); 26310 | 26311 | result = false; 26312 | } 26313 | 26314 | #ifndef exprtk_disable_string_capabilities 26315 | if (result) 26316 | { 26317 | const bool consq_is_str = is_generally_string_node(consequent ); 26318 | const bool alter_is_str = is_generally_string_node(alternative); 26319 | 26320 | if (consq_is_str || alter_is_str) 26321 | { 26322 | if (consq_is_str && alter_is_str) 26323 | { 26324 | expression_node_ptr result_node = 26325 | expression_generator_ 26326 | .conditional_string(condition, consequent, alternative); 26327 | 26328 | if (result_node && result_node->valid()) 26329 | { 26330 | return result_node; 26331 | } 26332 | 26333 | set_error(make_error( 26334 | parser_error::e_synthesis, 26335 | current_token(), 26336 | "ERR040 - Failed to synthesize node: conditional_string", 26337 | exprtk_error_location)); 26338 | 26339 | free_node(node_allocator_, result_node); 26340 | return error_node(); 26341 | } 26342 | 26343 | set_error(make_error( 26344 | parser_error::e_syntax, 26345 | current_token(), 26346 | "ERR041 - Return types of if-statement differ: string/non-string", 26347 | exprtk_error_location)); 26348 | 26349 | result = false; 26350 | } 26351 | } 26352 | #endif 26353 | 26354 | if (result) 26355 | { 26356 | const bool consq_is_vec = is_ivector_node(consequent ); 26357 | const bool alter_is_vec = is_ivector_node(alternative); 26358 | 26359 | if (consq_is_vec || alter_is_vec) 26360 | { 26361 | if (consq_is_vec && alter_is_vec) 26362 | { 26363 | return expression_generator_ 26364 | .conditional_vector(condition, consequent, alternative); 26365 | } 26366 | 26367 | set_error(make_error( 26368 | parser_error::e_syntax, 26369 | current_token(), 26370 | "ERR042 - Return types of if-statement differ: vector/non-vector", 26371 | exprtk_error_location)); 26372 | 26373 | result = false; 26374 | } 26375 | } 26376 | 26377 | if (!result) 26378 | { 26379 | free_node(node_allocator_, condition ); 26380 | free_node(node_allocator_, consequent ); 26381 | free_node(node_allocator_, alternative); 26382 | 26383 | return error_node(); 26384 | } 26385 | else 26386 | return expression_generator_ 26387 | .conditional(condition, consequent, alternative); 26388 | } 26389 | 26390 | inline expression_node_ptr parse_conditional_statement_02(expression_node_ptr condition) 26391 | { 26392 | expression_node_ptr consequent = error_node(); 26393 | expression_node_ptr alternative = error_node(); 26394 | 26395 | bool result = true; 26396 | 26397 | if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) 26398 | { 26399 | if (0 == (consequent = parse_multi_sequence("if-statement-01"))) 26400 | { 26401 | set_error(make_error( 26402 | parser_error::e_syntax, 26403 | current_token(), 26404 | "ERR043 - Failed to parse body of consequent for if-statement", 26405 | exprtk_error_location)); 26406 | 26407 | result = false; 26408 | } 26409 | else if 26410 | ( 26411 | !settings_.commutative_check_enabled() && 26412 | !token_is("else",prsrhlpr_t::e_hold) && 26413 | !token_is_loop(prsrhlpr_t::e_hold) && 26414 | !token_is_arithmetic_opr(prsrhlpr_t::e_hold) && 26415 | !token_is_right_bracket (prsrhlpr_t::e_hold) && 26416 | !token_is_ineq_opr (prsrhlpr_t::e_hold) && 26417 | !token_is(token_t::e_ternary,prsrhlpr_t::e_hold) && 26418 | !token_is(token_t::e_eof ,prsrhlpr_t::e_hold) 26419 | ) 26420 | { 26421 | set_error(make_error( 26422 | parser_error::e_syntax, 26423 | current_token(), 26424 | "ERR044 - Expected ';' at the end of the consequent for if-statement (1)", 26425 | exprtk_error_location)); 26426 | 26427 | result = false; 26428 | } 26429 | } 26430 | else 26431 | { 26432 | if ( 26433 | settings_.commutative_check_enabled() && 26434 | token_is(token_t::e_mul,prsrhlpr_t::e_hold) 26435 | ) 26436 | { 26437 | next_token(); 26438 | } 26439 | 26440 | if (0 != (consequent = parse_expression())) 26441 | { 26442 | if (!token_is(token_t::e_eof, prsrhlpr_t::e_hold)) 26443 | { 26444 | set_error(make_error( 26445 | parser_error::e_syntax, 26446 | current_token(), 26447 | "ERR045 - Expected ';' at the end of the consequent for if-statement (2)", 26448 | exprtk_error_location)); 26449 | 26450 | result = false; 26451 | } 26452 | } 26453 | else 26454 | { 26455 | set_error(make_error( 26456 | parser_error::e_syntax, 26457 | current_token(), 26458 | "ERR046 - Failed to parse body of consequent for if-statement", 26459 | exprtk_error_location)); 26460 | 26461 | result = false; 26462 | } 26463 | } 26464 | 26465 | if (result) 26466 | { 26467 | if ( 26468 | details::imatch(current_token().value,"else") || 26469 | (token_is(token_t::e_eof, prsrhlpr_t::e_hold) && peek_token_is("else")) 26470 | ) 26471 | { 26472 | next_token(); 26473 | 26474 | if (details::imatch(current_token().value,"else")) 26475 | { 26476 | next_token(); 26477 | } 26478 | 26479 | if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) 26480 | { 26481 | if (0 == (alternative = parse_multi_sequence("else-statement-01"))) 26482 | { 26483 | set_error(make_error( 26484 | parser_error::e_syntax, 26485 | current_token(), 26486 | "ERR047 - Failed to parse body of the 'else' for if-statement", 26487 | exprtk_error_location)); 26488 | 26489 | result = false; 26490 | } 26491 | } 26492 | else if (details::imatch(current_token().value,"if")) 26493 | { 26494 | if (0 == (alternative = parse_conditional_statement())) 26495 | { 26496 | set_error(make_error( 26497 | parser_error::e_syntax, 26498 | current_token(), 26499 | "ERR048 - Failed to parse body of if-else statement", 26500 | exprtk_error_location)); 26501 | 26502 | result = false; 26503 | } 26504 | } 26505 | else if (0 != (alternative = parse_expression())) 26506 | { 26507 | if ( 26508 | !token_is(token_t::e_ternary , prsrhlpr_t::e_hold) && 26509 | !token_is(token_t::e_rcrlbracket, prsrhlpr_t::e_hold) && 26510 | !token_is(token_t::e_eof) 26511 | ) 26512 | { 26513 | set_error(make_error( 26514 | parser_error::e_syntax, 26515 | current_token(), 26516 | "ERR049 - Expected ';' at the end of the 'else-if' for the if-statement", 26517 | exprtk_error_location)); 26518 | 26519 | result = false; 26520 | } 26521 | } 26522 | else 26523 | { 26524 | set_error(make_error( 26525 | parser_error::e_syntax, 26526 | current_token(), 26527 | "ERR050 - Failed to parse body of the 'else' for if-statement", 26528 | exprtk_error_location)); 26529 | 26530 | result = false; 26531 | } 26532 | } 26533 | } 26534 | 26535 | #ifndef exprtk_disable_string_capabilities 26536 | if (result) 26537 | { 26538 | const bool consq_is_str = is_generally_string_node(consequent ); 26539 | const bool alter_is_str = is_generally_string_node(alternative); 26540 | 26541 | if (consq_is_str || alter_is_str) 26542 | { 26543 | if (consq_is_str && alter_is_str) 26544 | { 26545 | return expression_generator_ 26546 | .conditional_string(condition, consequent, alternative); 26547 | } 26548 | 26549 | set_error(make_error( 26550 | parser_error::e_syntax, 26551 | current_token(), 26552 | "ERR051 - Return types of if-statement differ: string/non-string", 26553 | exprtk_error_location)); 26554 | 26555 | result = false; 26556 | } 26557 | } 26558 | #endif 26559 | 26560 | if (result) 26561 | { 26562 | const bool consq_is_vec = is_ivector_node(consequent ); 26563 | const bool alter_is_vec = is_ivector_node(alternative); 26564 | 26565 | if (consq_is_vec || alter_is_vec) 26566 | { 26567 | if (consq_is_vec && alter_is_vec) 26568 | { 26569 | return expression_generator_ 26570 | .conditional_vector(condition, consequent, alternative); 26571 | } 26572 | 26573 | set_error(make_error( 26574 | parser_error::e_syntax, 26575 | current_token(), 26576 | "ERR052 - Return types of if-statement differ: vector/non-vector", 26577 | exprtk_error_location)); 26578 | 26579 | result = false; 26580 | } 26581 | } 26582 | 26583 | if (!result) 26584 | { 26585 | free_node(node_allocator_, condition ); 26586 | free_node(node_allocator_, consequent ); 26587 | free_node(node_allocator_, alternative); 26588 | 26589 | return error_node(); 26590 | } 26591 | else 26592 | return expression_generator_ 26593 | .conditional(condition, consequent, alternative); 26594 | } 26595 | 26596 | inline expression_node_ptr parse_conditional_statement() 26597 | { 26598 | expression_node_ptr condition = error_node(); 26599 | 26600 | next_token(); 26601 | 26602 | if (!token_is(token_t::e_lbracket)) 26603 | { 26604 | set_error(make_error( 26605 | parser_error::e_syntax, 26606 | current_token(), 26607 | "ERR053 - Expected '(' at start of if-statement, instead got: '" + current_token().value + "'", 26608 | exprtk_error_location)); 26609 | 26610 | return error_node(); 26611 | } 26612 | else if (0 == (condition = parse_expression())) 26613 | { 26614 | set_error(make_error( 26615 | parser_error::e_syntax, 26616 | current_token(), 26617 | "ERR054 - Failed to parse condition for if-statement", 26618 | exprtk_error_location)); 26619 | 26620 | return error_node(); 26621 | } 26622 | else if (token_is(token_t::e_comma,prsrhlpr_t::e_hold)) 26623 | { 26624 | // if (x,y,z) 26625 | return parse_conditional_statement_01(condition); 26626 | } 26627 | else if (token_is(token_t::e_rbracket)) 26628 | { 26629 | /* 26630 | 00. if (x) y; 26631 | 01. if (x) y; else z; 26632 | 02. if (x) y; else {z0; ... zn;} 26633 | 03. if (x) y; else if (z) w; 26634 | 04. if (x) y; else if (z) w; else u; 26635 | 05. if (x) y; else if (z) w; else {u0; ... un;} 26636 | 06. if (x) y; else if (z) {w0; ... wn;} 26637 | 07. if (x) {y0; ... yn;} 26638 | 08. if (x) {y0; ... yn;} else z; 26639 | 09. if (x) {y0; ... yn;} else {z0; ... zn;}; 26640 | 10. if (x) {y0; ... yn;} else if (z) w; 26641 | 11. if (x) {y0; ... yn;} else if (z) w; else u; 26642 | 12. if (x) {y0; ... nex;} else if (z) w; else {u0 ... un;} 26643 | 13. if (x) {y0; ... yn;} else if (z) {w0; ... wn;} 26644 | */ 26645 | return parse_conditional_statement_02(condition); 26646 | } 26647 | 26648 | set_error(make_error( 26649 | parser_error::e_syntax, 26650 | current_token(), 26651 | "ERR055 - Invalid if-statement", 26652 | exprtk_error_location)); 26653 | 26654 | free_node(node_allocator_, condition); 26655 | 26656 | return error_node(); 26657 | } 26658 | 26659 | inline expression_node_ptr parse_ternary_conditional_statement(expression_node_ptr condition) 26660 | { 26661 | // Parse: [condition][?][consequent][:][alternative] 26662 | expression_node_ptr consequent = error_node(); 26663 | expression_node_ptr alternative = error_node(); 26664 | 26665 | bool result = true; 26666 | 26667 | if (0 == condition) 26668 | { 26669 | set_error(make_error( 26670 | parser_error::e_syntax, 26671 | current_token(), 26672 | "ERR056 - Encountered invalid condition branch for ternary if-statement", 26673 | exprtk_error_location)); 26674 | 26675 | return error_node(); 26676 | } 26677 | else if (!token_is(token_t::e_ternary)) 26678 | { 26679 | set_error(make_error( 26680 | parser_error::e_syntax, 26681 | current_token(), 26682 | "ERR057 - Expected '?' after condition of ternary if-statement", 26683 | exprtk_error_location)); 26684 | 26685 | result = false; 26686 | } 26687 | else if (0 == (consequent = parse_expression())) 26688 | { 26689 | set_error(make_error( 26690 | parser_error::e_syntax, 26691 | current_token(), 26692 | "ERR058 - Failed to parse consequent for ternary if-statement", 26693 | exprtk_error_location)); 26694 | 26695 | result = false; 26696 | } 26697 | else if (!token_is(token_t::e_colon)) 26698 | { 26699 | set_error(make_error( 26700 | parser_error::e_syntax, 26701 | current_token(), 26702 | "ERR059 - Expected ':' between ternary if-statement consequent and alternative", 26703 | exprtk_error_location)); 26704 | 26705 | result = false; 26706 | } 26707 | else if (0 == (alternative = parse_expression())) 26708 | { 26709 | set_error(make_error( 26710 | parser_error::e_syntax, 26711 | current_token(), 26712 | "ERR060 - Failed to parse alternative for ternary if-statement", 26713 | exprtk_error_location)); 26714 | 26715 | result = false; 26716 | } 26717 | 26718 | #ifndef exprtk_disable_string_capabilities 26719 | if (result) 26720 | { 26721 | const bool consq_is_str = is_generally_string_node(consequent ); 26722 | const bool alter_is_str = is_generally_string_node(alternative); 26723 | 26724 | if (consq_is_str || alter_is_str) 26725 | { 26726 | if (consq_is_str && alter_is_str) 26727 | { 26728 | return expression_generator_ 26729 | .conditional_string(condition, consequent, alternative); 26730 | } 26731 | 26732 | set_error(make_error( 26733 | parser_error::e_syntax, 26734 | current_token(), 26735 | "ERR061 - Return types of ternary differ: string/non-string", 26736 | exprtk_error_location)); 26737 | 26738 | result = false; 26739 | } 26740 | } 26741 | #endif 26742 | 26743 | if (result) 26744 | { 26745 | const bool consq_is_vec = is_ivector_node(consequent ); 26746 | const bool alter_is_vec = is_ivector_node(alternative); 26747 | 26748 | if (consq_is_vec || alter_is_vec) 26749 | { 26750 | if (consq_is_vec && alter_is_vec) 26751 | { 26752 | return expression_generator_ 26753 | .conditional_vector(condition, consequent, alternative); 26754 | } 26755 | 26756 | set_error(make_error( 26757 | parser_error::e_syntax, 26758 | current_token(), 26759 | "ERR062 - Return types of ternary differ: vector/non-vector", 26760 | exprtk_error_location)); 26761 | 26762 | result = false; 26763 | } 26764 | } 26765 | 26766 | if (!result) 26767 | { 26768 | free_node(node_allocator_, condition ); 26769 | free_node(node_allocator_, consequent ); 26770 | free_node(node_allocator_, alternative); 26771 | 26772 | return error_node(); 26773 | } 26774 | else 26775 | return expression_generator_ 26776 | .conditional(condition, consequent, alternative); 26777 | } 26778 | 26779 | inline expression_node_ptr parse_not_statement() 26780 | { 26781 | if (settings_.logic_disabled("not")) 26782 | { 26783 | set_error(make_error( 26784 | parser_error::e_syntax, 26785 | current_token(), 26786 | "ERR063 - Invalid or disabled logic operation 'not'", 26787 | exprtk_error_location)); 26788 | 26789 | return error_node(); 26790 | } 26791 | 26792 | return parse_base_operation(); 26793 | } 26794 | 26795 | void handle_brkcnt_scope_exit() 26796 | { 26797 | assert(!brkcnt_list_.empty()); 26798 | brkcnt_list_.pop_front(); 26799 | } 26800 | 26801 | inline expression_node_ptr parse_while_loop() 26802 | { 26803 | // Parse: [while][(][test expr][)][{][expression][}] 26804 | expression_node_ptr condition = error_node(); 26805 | expression_node_ptr branch = error_node(); 26806 | expression_node_ptr result_node = error_node(); 26807 | 26808 | bool result = true; 26809 | 26810 | next_token(); 26811 | 26812 | if (!token_is(token_t::e_lbracket)) 26813 | { 26814 | set_error(make_error( 26815 | parser_error::e_syntax, 26816 | current_token(), 26817 | "ERR064 - Expected '(' at start of while-loop condition statement", 26818 | exprtk_error_location)); 26819 | 26820 | return error_node(); 26821 | } 26822 | else if (0 == (condition = parse_expression())) 26823 | { 26824 | set_error(make_error( 26825 | parser_error::e_syntax, 26826 | current_token(), 26827 | "ERR065 - Failed to parse condition for while-loop", 26828 | exprtk_error_location)); 26829 | 26830 | return error_node(); 26831 | } 26832 | else if (!token_is(token_t::e_rbracket)) 26833 | { 26834 | set_error(make_error( 26835 | parser_error::e_syntax, 26836 | current_token(), 26837 | "ERR066 - Expected ')' at end of while-loop condition statement", 26838 | exprtk_error_location)); 26839 | 26840 | result = false; 26841 | } 26842 | 26843 | brkcnt_list_.push_front(false); 26844 | 26845 | if (result) 26846 | { 26847 | scoped_inc_dec sid(state_.parsing_loop_stmt_count); 26848 | 26849 | if (0 == (branch = parse_multi_sequence("while-loop", true))) 26850 | { 26851 | set_error(make_error( 26852 | parser_error::e_syntax, 26853 | current_token(), 26854 | "ERR067 - Failed to parse body of while-loop")); 26855 | result = false; 26856 | } 26857 | else if (0 == (result_node = expression_generator_.while_loop(condition, 26858 | branch, 26859 | brkcnt_list_.front()))) 26860 | { 26861 | set_error(make_error( 26862 | parser_error::e_syntax, 26863 | current_token(), 26864 | "ERR068 - Failed to synthesize while-loop", 26865 | exprtk_error_location)); 26866 | 26867 | result = false; 26868 | } 26869 | } 26870 | 26871 | handle_brkcnt_scope_exit(); 26872 | 26873 | if (!result) 26874 | { 26875 | free_node(node_allocator_, branch ); 26876 | free_node(node_allocator_, condition ); 26877 | free_node(node_allocator_, result_node); 26878 | 26879 | return error_node(); 26880 | } 26881 | 26882 | if (result_node && result_node->valid()) 26883 | { 26884 | return result_node; 26885 | } 26886 | 26887 | set_error(make_error( 26888 | parser_error::e_synthesis, 26889 | current_token(), 26890 | "ERR069 - Failed to synthesize 'valid' while-loop", 26891 | exprtk_error_location)); 26892 | 26893 | free_node(node_allocator_, result_node); 26894 | 26895 | return error_node(); 26896 | } 26897 | 26898 | inline expression_node_ptr parse_repeat_until_loop() 26899 | { 26900 | // Parse: [repeat][{][expression][}][until][(][test expr][)] 26901 | expression_node_ptr condition = error_node(); 26902 | expression_node_ptr branch = error_node(); 26903 | next_token(); 26904 | 26905 | std::vector<expression_node_ptr> arg_list; 26906 | std::vector<bool> side_effect_list; 26907 | 26908 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 26909 | 26910 | brkcnt_list_.push_front(false); 26911 | 26912 | if (details::imatch(current_token().value,"until")) 26913 | { 26914 | next_token(); 26915 | branch = node_allocator_.allocate<details::null_node<T> >(); 26916 | } 26917 | else 26918 | { 26919 | const token_t::token_type separator = token_t::e_eof; 26920 | 26921 | scope_handler sh(*this); 26922 | 26923 | scoped_bool_or_restorer sbr(state_.side_effect_present); 26924 | 26925 | scoped_inc_dec sid(state_.parsing_loop_stmt_count); 26926 | 26927 | for ( ; ; ) 26928 | { 26929 | state_.side_effect_present = false; 26930 | 26931 | expression_node_ptr arg = parse_expression(); 26932 | 26933 | if (0 == arg) 26934 | return error_node(); 26935 | else 26936 | { 26937 | arg_list.push_back(arg); 26938 | side_effect_list.push_back(state_.side_effect_present); 26939 | } 26940 | 26941 | if (details::imatch(current_token().value,"until")) 26942 | { 26943 | next_token(); 26944 | break; 26945 | } 26946 | 26947 | const bool is_next_until = peek_token_is(token_t::e_symbol) && 26948 | peek_token_is("until"); 26949 | 26950 | if (!token_is(separator) && is_next_until) 26951 | { 26952 | set_error(make_error( 26953 | parser_error::e_syntax, 26954 | current_token(), 26955 | "ERR070 - Expected '" + token_t::to_str(separator) + "' in body of repeat until loop", 26956 | exprtk_error_location)); 26957 | 26958 | return error_node(); 26959 | } 26960 | 26961 | if (details::imatch(current_token().value,"until")) 26962 | { 26963 | next_token(); 26964 | break; 26965 | } 26966 | } 26967 | 26968 | branch = simplify(arg_list,side_effect_list); 26969 | 26970 | svd.delete_ptr = (0 == branch); 26971 | 26972 | if (svd.delete_ptr) 26973 | { 26974 | set_error(make_error( 26975 | parser_error::e_syntax, 26976 | current_token(), 26977 | "ERR071 - Failed to parse body of repeat until loop", 26978 | exprtk_error_location)); 26979 | 26980 | return error_node(); 26981 | } 26982 | } 26983 | 26984 | if (!token_is(token_t::e_lbracket)) 26985 | { 26986 | set_error(make_error( 26987 | parser_error::e_syntax, 26988 | current_token(), 26989 | "ERR072 - Expected '(' before condition statement of repeat until loop", 26990 | exprtk_error_location)); 26991 | 26992 | free_node(node_allocator_, branch); 26993 | return error_node(); 26994 | } 26995 | else if (0 == (condition = parse_expression())) 26996 | { 26997 | set_error(make_error( 26998 | parser_error::e_syntax, 26999 | current_token(), 27000 | "ERR073 - Failed to parse condition for repeat until loop", 27001 | exprtk_error_location)); 27002 | 27003 | free_node(node_allocator_, branch); 27004 | return error_node(); 27005 | } 27006 | else if (!token_is(token_t::e_rbracket)) 27007 | { 27008 | set_error(make_error( 27009 | parser_error::e_syntax, 27010 | current_token(), 27011 | "ERR074 - Expected ')' after condition of repeat until loop", 27012 | exprtk_error_location)); 27013 | 27014 | free_node(node_allocator_, branch ); 27015 | free_node(node_allocator_, condition); 27016 | 27017 | return error_node(); 27018 | } 27019 | 27020 | expression_node_ptr result_node = 27021 | expression_generator_ 27022 | .repeat_until_loop( 27023 | condition, 27024 | branch, 27025 | brkcnt_list_.front()); 27026 | 27027 | if (0 == result_node) 27028 | { 27029 | set_error(make_error( 27030 | parser_error::e_syntax, 27031 | current_token(), 27032 | "ERR075 - Failed to synthesize repeat until loop", 27033 | exprtk_error_location)); 27034 | 27035 | free_node(node_allocator_, condition); 27036 | 27037 | return error_node(); 27038 | } 27039 | 27040 | handle_brkcnt_scope_exit(); 27041 | 27042 | if (result_node && result_node->valid()) 27043 | { 27044 | return result_node; 27045 | } 27046 | 27047 | set_error(make_error( 27048 | parser_error::e_synthesis, 27049 | current_token(), 27050 | "ERR076 - Failed to synthesize 'valid' repeat until loop", 27051 | exprtk_error_location)); 27052 | 27053 | free_node(node_allocator_, result_node); 27054 | 27055 | return error_node(); 27056 | } 27057 | 27058 | inline expression_node_ptr parse_for_loop() 27059 | { 27060 | expression_node_ptr initialiser = error_node(); 27061 | expression_node_ptr condition = error_node(); 27062 | expression_node_ptr incrementor = error_node(); 27063 | expression_node_ptr loop_body = error_node(); 27064 | 27065 | scope_element* se = 0; 27066 | bool result = true; 27067 | 27068 | next_token(); 27069 | 27070 | scope_handler sh(*this); 27071 | 27072 | if (!token_is(token_t::e_lbracket)) 27073 | { 27074 | set_error(make_error( 27075 | parser_error::e_syntax, 27076 | current_token(), 27077 | "ERR077 - Expected '(' at start of for-loop", 27078 | exprtk_error_location)); 27079 | 27080 | return error_node(); 27081 | } 27082 | 27083 | if (!token_is(token_t::e_eof)) 27084 | { 27085 | if ( 27086 | !token_is(token_t::e_symbol,prsrhlpr_t::e_hold) && 27087 | details::imatch(current_token().value,"var") 27088 | ) 27089 | { 27090 | next_token(); 27091 | 27092 | if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold)) 27093 | { 27094 | set_error(make_error( 27095 | parser_error::e_syntax, 27096 | current_token(), 27097 | "ERR078 - Expected a variable at the start of initialiser section of for-loop", 27098 | exprtk_error_location)); 27099 | 27100 | return error_node(); 27101 | } 27102 | else if (!peek_token_is(token_t::e_assign)) 27103 | { 27104 | set_error(make_error( 27105 | parser_error::e_syntax, 27106 | current_token(), 27107 | "ERR079 - Expected variable assignment of initialiser section of for-loop", 27108 | exprtk_error_location)); 27109 | 27110 | return error_node(); 27111 | } 27112 | 27113 | const std::string loop_counter_symbol = current_token().value; 27114 | 27115 | se = &sem_.get_element(loop_counter_symbol); 27116 | 27117 | if ((se->name == loop_counter_symbol) && se->active) 27118 | { 27119 | set_error(make_error( 27120 | parser_error::e_syntax, 27121 | current_token(), 27122 | "ERR080 - For-loop variable '" + loop_counter_symbol+ "' is being shadowed by a previous declaration", 27123 | exprtk_error_location)); 27124 | 27125 | return error_node(); 27126 | } 27127 | else if (!symtab_store_.is_variable(loop_counter_symbol)) 27128 | { 27129 | if ( 27130 | !se->active && 27131 | (se->name == loop_counter_symbol) && 27132 | (se->type == scope_element::e_variable) 27133 | ) 27134 | { 27135 | se->active = true; 27136 | se->ref_count++; 27137 | } 27138 | else 27139 | { 27140 | scope_element nse; 27141 | nse.name = loop_counter_symbol; 27142 | nse.active = true; 27143 | nse.ref_count = 1; 27144 | nse.type = scope_element::e_variable; 27145 | nse.depth = state_.scope_depth; 27146 | nse.data = new T(T(0)); 27147 | nse.var_node = node_allocator_.allocate<variable_node_t>(*reinterpret_cast<T*>(nse.data)); 27148 | 27149 | if (!sem_.add_element(nse)) 27150 | { 27151 | set_error(make_error( 27152 | parser_error::e_syntax, 27153 | current_token(), 27154 | "ERR081 - Failed to add new local variable '" + loop_counter_symbol + "' to SEM", 27155 | exprtk_error_location)); 27156 | 27157 | sem_.free_element(nse); 27158 | 27159 | result = false; 27160 | } 27161 | else 27162 | { 27163 | exprtk_debug(("parse_for_loop() - INFO - Added new local variable: %s\n", nse.name.c_str())); 27164 | 27165 | state_.activate_side_effect("parse_for_loop()"); 27166 | } 27167 | } 27168 | } 27169 | } 27170 | 27171 | if (0 == (initialiser = parse_expression())) 27172 | { 27173 | set_error(make_error( 27174 | parser_error::e_syntax, 27175 | current_token(), 27176 | "ERR082 - Failed to parse initialiser of for-loop", 27177 | exprtk_error_location)); 27178 | 27179 | result = false; 27180 | } 27181 | else if (!token_is(token_t::e_eof)) 27182 | { 27183 | set_error(make_error( 27184 | parser_error::e_syntax, 27185 | current_token(), 27186 | "ERR083 - Expected ';' after initialiser of for-loop", 27187 | exprtk_error_location)); 27188 | 27189 | result = false; 27190 | } 27191 | } 27192 | 27193 | if (!token_is(token_t::e_eof)) 27194 | { 27195 | if (0 == (condition = parse_expression())) 27196 | { 27197 | set_error(make_error( 27198 | parser_error::e_syntax, 27199 | current_token(), 27200 | "ERR084 - Failed to parse condition of for-loop", 27201 | exprtk_error_location)); 27202 | 27203 | result = false; 27204 | } 27205 | else if (!token_is(token_t::e_eof)) 27206 | { 27207 | set_error(make_error( 27208 | parser_error::e_syntax, 27209 | current_token(), 27210 | "ERR085 - Expected ';' after condition section of for-loop", 27211 | exprtk_error_location)); 27212 | 27213 | result = false; 27214 | } 27215 | } 27216 | 27217 | if (!token_is(token_t::e_rbracket)) 27218 | { 27219 | if (0 == (incrementor = parse_expression())) 27220 | { 27221 | set_error(make_error( 27222 | parser_error::e_syntax, 27223 | current_token(), 27224 | "ERR086 - Failed to parse incrementor of for-loop", 27225 | exprtk_error_location)); 27226 | 27227 | result = false; 27228 | } 27229 | else if (!token_is(token_t::e_rbracket)) 27230 | { 27231 | set_error(make_error( 27232 | parser_error::e_syntax, 27233 | current_token(), 27234 | "ERR087 - Expected ')' after incrementor section of for-loop", 27235 | exprtk_error_location)); 27236 | 27237 | result = false; 27238 | } 27239 | } 27240 | 27241 | if (result) 27242 | { 27243 | brkcnt_list_.push_front(false); 27244 | 27245 | scoped_inc_dec sid(state_.parsing_loop_stmt_count); 27246 | 27247 | if (0 == (loop_body = parse_multi_sequence("for-loop", true))) 27248 | { 27249 | set_error(make_error( 27250 | parser_error::e_syntax, 27251 | current_token(), 27252 | "ERR088 - Failed to parse body of for-loop", 27253 | exprtk_error_location)); 27254 | 27255 | result = false; 27256 | } 27257 | } 27258 | 27259 | if (!result) 27260 | { 27261 | if (se) 27262 | { 27263 | se->ref_count--; 27264 | } 27265 | 27266 | free_node(node_allocator_, initialiser); 27267 | free_node(node_allocator_, condition ); 27268 | free_node(node_allocator_, incrementor); 27269 | free_node(node_allocator_, loop_body ); 27270 | return error_node(); 27271 | } 27272 | 27273 | expression_node_ptr result_node = 27274 | expression_generator_.for_loop(initialiser, 27275 | condition, 27276 | incrementor, 27277 | loop_body, 27278 | brkcnt_list_.front()); 27279 | handle_brkcnt_scope_exit(); 27280 | 27281 | if (result_node && result_node->valid()) 27282 | { 27283 | return result_node; 27284 | } 27285 | 27286 | set_error(make_error( 27287 | parser_error::e_synthesis, 27288 | current_token(), 27289 | "ERR089 - Failed to synthesize 'valid' for-loop", 27290 | exprtk_error_location)); 27291 | 27292 | free_node(node_allocator_, result_node); 27293 | 27294 | return error_node(); 27295 | } 27296 | 27297 | inline expression_node_ptr parse_switch_statement() 27298 | { 27299 | std::vector<expression_node_ptr> arg_list; 27300 | 27301 | if (!details::imatch(current_token().value,"switch")) 27302 | { 27303 | set_error(make_error( 27304 | parser_error::e_syntax, 27305 | current_token(), 27306 | "ERR090 - Expected keyword 'switch'", 27307 | exprtk_error_location)); 27308 | 27309 | return error_node(); 27310 | } 27311 | 27312 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 27313 | 27314 | next_token(); 27315 | 27316 | if (!token_is(token_t::e_lcrlbracket)) 27317 | { 27318 | set_error(make_error( 27319 | parser_error::e_syntax, 27320 | current_token(), 27321 | "ERR091 - Expected '{' for call to switch statement", 27322 | exprtk_error_location)); 27323 | 27324 | return error_node(); 27325 | } 27326 | 27327 | expression_node_ptr default_statement = error_node(); 27328 | 27329 | scoped_expression_delete defstmt_delete((*this), default_statement); 27330 | 27331 | for ( ; ; ) 27332 | { 27333 | if (details::imatch("case",current_token().value)) 27334 | { 27335 | next_token(); 27336 | 27337 | expression_node_ptr condition = parse_expression(); 27338 | 27339 | if (0 == condition) 27340 | return error_node(); 27341 | else if (!token_is(token_t::e_colon)) 27342 | { 27343 | set_error(make_error( 27344 | parser_error::e_syntax, 27345 | current_token(), 27346 | "ERR092 - Expected ':' for case of switch statement", 27347 | exprtk_error_location)); 27348 | 27349 | free_node(node_allocator_, condition); 27350 | 27351 | return error_node(); 27352 | } 27353 | 27354 | expression_node_ptr consequent = 27355 | (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) ? 27356 | parse_multi_sequence("switch-consequent") : 27357 | parse_expression(); 27358 | 27359 | if (0 == consequent) 27360 | { 27361 | free_node(node_allocator_, condition); 27362 | 27363 | return error_node(); 27364 | } 27365 | else if (!token_is(token_t::e_eof)) 27366 | { 27367 | set_error(make_error( 27368 | parser_error::e_syntax, 27369 | current_token(), 27370 | "ERR093 - Expected ';' at end of case for switch statement", 27371 | exprtk_error_location)); 27372 | 27373 | free_node(node_allocator_, condition ); 27374 | free_node(node_allocator_, consequent); 27375 | 27376 | return error_node(); 27377 | } 27378 | 27379 | // Can we optimise away the case statement? 27380 | if (is_constant_node(condition) && is_false(condition)) 27381 | { 27382 | free_node(node_allocator_, condition ); 27383 | free_node(node_allocator_, consequent); 27384 | } 27385 | else 27386 | { 27387 | arg_list.push_back(condition ); 27388 | arg_list.push_back(consequent); 27389 | } 27390 | 27391 | } 27392 | else if (details::imatch("default",current_token().value)) 27393 | { 27394 | if (0 != default_statement) 27395 | { 27396 | set_error(make_error( 27397 | parser_error::e_syntax, 27398 | current_token(), 27399 | "ERR094 - Multiple default cases for switch statement", 27400 | exprtk_error_location)); 27401 | 27402 | return error_node(); 27403 | } 27404 | 27405 | next_token(); 27406 | 27407 | if (!token_is(token_t::e_colon)) 27408 | { 27409 | set_error(make_error( 27410 | parser_error::e_syntax, 27411 | current_token(), 27412 | "ERR095 - Expected ':' for default of switch statement", 27413 | exprtk_error_location)); 27414 | 27415 | return error_node(); 27416 | } 27417 | 27418 | default_statement = 27419 | (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) ? 27420 | parse_multi_sequence("switch-default"): 27421 | parse_expression(); 27422 | 27423 | if (0 == default_statement) 27424 | return error_node(); 27425 | else if (!token_is(token_t::e_eof)) 27426 | { 27427 | set_error(make_error( 27428 | parser_error::e_syntax, 27429 | current_token(), 27430 | "ERR096 - Expected ';' at end of default for switch statement", 27431 | exprtk_error_location)); 27432 | 27433 | return error_node(); 27434 | } 27435 | } 27436 | else if (token_is(token_t::e_rcrlbracket)) 27437 | break; 27438 | else 27439 | { 27440 | set_error(make_error( 27441 | parser_error::e_syntax, 27442 | current_token(), 27443 | "ERR097 - Expected '}' at end of switch statement", 27444 | exprtk_error_location)); 27445 | 27446 | return error_node(); 27447 | } 27448 | } 27449 | 27450 | const bool default_statement_present = (0 != default_statement); 27451 | 27452 | if (default_statement_present) 27453 | { 27454 | arg_list.push_back(default_statement); 27455 | } 27456 | else 27457 | { 27458 | arg_list.push_back(node_allocator_.allocate_c<literal_node_t>(std::numeric_limits<T>::quiet_NaN())); 27459 | } 27460 | 27461 | expression_node_ptr result = expression_generator_.switch_statement(arg_list, (0 != default_statement)); 27462 | 27463 | svd.delete_ptr = (0 == result); 27464 | defstmt_delete.delete_ptr = (0 == result); 27465 | 27466 | return result; 27467 | } 27468 | 27469 | inline expression_node_ptr parse_multi_switch_statement() 27470 | { 27471 | std::vector<expression_node_ptr> arg_list; 27472 | 27473 | if (!details::imatch(current_token().value,"[*]")) 27474 | { 27475 | set_error(make_error( 27476 | parser_error::e_syntax, 27477 | current_token(), 27478 | "ERR098 - Expected token '[*]'", 27479 | exprtk_error_location)); 27480 | 27481 | return error_node(); 27482 | } 27483 | 27484 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 27485 | 27486 | next_token(); 27487 | 27488 | if (!token_is(token_t::e_lcrlbracket)) 27489 | { 27490 | set_error(make_error( 27491 | parser_error::e_syntax, 27492 | current_token(), 27493 | "ERR099 - Expected '{' for call to [*] statement", 27494 | exprtk_error_location)); 27495 | 27496 | return error_node(); 27497 | } 27498 | 27499 | for ( ; ; ) 27500 | { 27501 | if (!details::imatch("case",current_token().value)) 27502 | { 27503 | set_error(make_error( 27504 | parser_error::e_syntax, 27505 | current_token(), 27506 | "ERR100 - Expected a 'case' statement for multi-switch", 27507 | exprtk_error_location)); 27508 | 27509 | return error_node(); 27510 | } 27511 | 27512 | next_token(); 27513 | 27514 | expression_node_ptr condition = parse_expression(); 27515 | 27516 | if (0 == condition) 27517 | return error_node(); 27518 | 27519 | if (!token_is(token_t::e_colon)) 27520 | { 27521 | set_error(make_error( 27522 | parser_error::e_syntax, 27523 | current_token(), 27524 | "ERR101 - Expected ':' for case of [*] statement", 27525 | exprtk_error_location)); 27526 | 27527 | return error_node(); 27528 | } 27529 | 27530 | expression_node_ptr consequent = 27531 | (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) ? 27532 | parse_multi_sequence("multi-switch-consequent") : 27533 | parse_expression(); 27534 | 27535 | if (0 == consequent) 27536 | return error_node(); 27537 | 27538 | if (!token_is(token_t::e_eof)) 27539 | { 27540 | set_error(make_error( 27541 | parser_error::e_syntax, 27542 | current_token(), 27543 | "ERR102 - Expected ';' at end of case for [*] statement", 27544 | exprtk_error_location)); 27545 | 27546 | return error_node(); 27547 | } 27548 | 27549 | // Can we optimise away the case statement? 27550 | if (is_constant_node(condition) && is_false(condition)) 27551 | { 27552 | free_node(node_allocator_, condition ); 27553 | free_node(node_allocator_, consequent); 27554 | } 27555 | else 27556 | { 27557 | arg_list.push_back(condition ); 27558 | arg_list.push_back(consequent); 27559 | } 27560 | 27561 | if (token_is(token_t::e_rcrlbracket,prsrhlpr_t::e_hold)) 27562 | { 27563 | break; 27564 | } 27565 | } 27566 | 27567 | if (!token_is(token_t::e_rcrlbracket)) 27568 | { 27569 | set_error(make_error( 27570 | parser_error::e_syntax, 27571 | current_token(), 27572 | "ERR103 - Expected '}' at end of [*] statement", 27573 | exprtk_error_location)); 27574 | 27575 | return error_node(); 27576 | } 27577 | 27578 | const expression_node_ptr result = expression_generator_.multi_switch_statement(arg_list); 27579 | 27580 | svd.delete_ptr = (0 == result); 27581 | 27582 | return result; 27583 | } 27584 | 27585 | inline expression_node_ptr parse_vararg_function() 27586 | { 27587 | std::vector<expression_node_ptr> arg_list; 27588 | 27589 | details::operator_type opt_type = details::e_default; 27590 | const std::string symbol = current_token().value; 27591 | 27592 | if (details::imatch(symbol,"~")) 27593 | { 27594 | next_token(); 27595 | return check_block_statement_closure(parse_multi_sequence()); 27596 | } 27597 | else if (details::imatch(symbol,"[*]")) 27598 | { 27599 | return check_block_statement_closure(parse_multi_switch_statement()); 27600 | } 27601 | else if (details::imatch(symbol, "avg" )) opt_type = details::e_avg ; 27602 | else if (details::imatch(symbol, "mand")) opt_type = details::e_mand; 27603 | else if (details::imatch(symbol, "max" )) opt_type = details::e_max ; 27604 | else if (details::imatch(symbol, "min" )) opt_type = details::e_min ; 27605 | else if (details::imatch(symbol, "mor" )) opt_type = details::e_mor ; 27606 | else if (details::imatch(symbol, "mul" )) opt_type = details::e_prod; 27607 | else if (details::imatch(symbol, "sum" )) opt_type = details::e_sum ; 27608 | else 27609 | { 27610 | set_error(make_error( 27611 | parser_error::e_syntax, 27612 | current_token(), 27613 | "ERR104 - Unsupported built-in vararg function: " + symbol, 27614 | exprtk_error_location)); 27615 | 27616 | return error_node(); 27617 | } 27618 | 27619 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 27620 | 27621 | lodge_symbol(symbol, e_st_function); 27622 | 27623 | next_token(); 27624 | 27625 | if (!token_is(token_t::e_lbracket)) 27626 | { 27627 | set_error(make_error( 27628 | parser_error::e_syntax, 27629 | current_token(), 27630 | "ERR105 - Expected '(' for call to vararg function: " + symbol, 27631 | exprtk_error_location)); 27632 | 27633 | return error_node(); 27634 | } 27635 | 27636 | if (token_is(token_t::e_rbracket)) 27637 | { 27638 | set_error(make_error( 27639 | parser_error::e_syntax, 27640 | current_token(), 27641 | "ERR106 - vararg function: " + symbol + 27642 | " requires at least one input parameter", 27643 | exprtk_error_location)); 27644 | 27645 | return error_node(); 27646 | } 27647 | 27648 | for ( ; ; ) 27649 | { 27650 | expression_node_ptr arg = parse_expression(); 27651 | 27652 | if (0 == arg) 27653 | return error_node(); 27654 | else 27655 | arg_list.push_back(arg); 27656 | 27657 | if (token_is(token_t::e_rbracket)) 27658 | break; 27659 | else if (!token_is(token_t::e_comma)) 27660 | { 27661 | set_error(make_error( 27662 | parser_error::e_syntax, 27663 | current_token(), 27664 | "ERR107 - Expected ',' for call to vararg function: " + symbol, 27665 | exprtk_error_location)); 27666 | 27667 | return error_node(); 27668 | } 27669 | } 27670 | 27671 | const expression_node_ptr result = expression_generator_.vararg_function(opt_type,arg_list); 27672 | 27673 | svd.delete_ptr = (0 == result); 27674 | return result; 27675 | } 27676 | 27677 | #ifndef exprtk_disable_string_capabilities 27678 | inline expression_node_ptr parse_string_range_statement(expression_node_ptr& expression) 27679 | { 27680 | if (!token_is(token_t::e_lsqrbracket)) 27681 | { 27682 | set_error(make_error( 27683 | parser_error::e_syntax, 27684 | current_token(), 27685 | "ERR108 - Expected '[' as start of string range definition", 27686 | exprtk_error_location)); 27687 | 27688 | free_node(node_allocator_, expression); 27689 | 27690 | return error_node(); 27691 | } 27692 | else if (token_is(token_t::e_rsqrbracket)) 27693 | { 27694 | return node_allocator_.allocate<details::string_size_node<T> >(expression); 27695 | } 27696 | 27697 | range_t rp; 27698 | 27699 | if (!parse_range(rp,true)) 27700 | { 27701 | free_node(node_allocator_, expression); 27702 | 27703 | return error_node(); 27704 | } 27705 | 27706 | expression_node_ptr result = expression_generator_(expression,rp); 27707 | 27708 | if (0 == result) 27709 | { 27710 | set_error(make_error( 27711 | parser_error::e_syntax, 27712 | current_token(), 27713 | "ERR109 - Failed to generate string range node", 27714 | exprtk_error_location)); 27715 | 27716 | free_node(node_allocator_, expression); 27717 | rp.free(); 27718 | } 27719 | 27720 | rp.clear(); 27721 | 27722 | if (result && result->valid()) 27723 | { 27724 | return result; 27725 | } 27726 | 27727 | set_error(make_error( 27728 | parser_error::e_synthesis, 27729 | current_token(), 27730 | "ERR110 - Failed to synthesize node: string_range_node", 27731 | exprtk_error_location)); 27732 | 27733 | free_node(node_allocator_, result); 27734 | rp.free(); 27735 | return error_node(); 27736 | } 27737 | #else 27738 | inline expression_node_ptr parse_string_range_statement(expression_node_ptr&) 27739 | { 27740 | return error_node(); 27741 | } 27742 | #endif 27743 | 27744 | inline bool parse_pending_string_rangesize(expression_node_ptr& expression) 27745 | { 27746 | // Allow no more than 100 range calls, eg: s[][][]...[][] 27747 | const std::size_t max_rangesize_parses = 100; 27748 | 27749 | std::size_t i = 0; 27750 | 27751 | while 27752 | ( 27753 | (0 != expression) && 27754 | (i++ < max_rangesize_parses) && 27755 | error_list_.empty() && 27756 | is_generally_string_node(expression) && 27757 | token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold) 27758 | ) 27759 | { 27760 | expression = parse_string_range_statement(expression); 27761 | } 27762 | 27763 | return (i > 1); 27764 | } 27765 | 27766 | inline void parse_pending_vector_index_operator(expression_node_ptr& expression) 27767 | { 27768 | if 27769 | ( 27770 | (0 != expression) && 27771 | error_list_.empty() && 27772 | is_ivector_node(expression) 27773 | ) 27774 | { 27775 | if ( 27776 | settings_.commutative_check_enabled() && 27777 | token_is(token_t::e_mul,prsrhlpr_t::e_hold) && 27778 | peek_token_is(token_t::e_lsqrbracket) 27779 | ) 27780 | { 27781 | token_is(token_t::e_mul); 27782 | token_is(token_t::e_lsqrbracket); 27783 | } 27784 | else if (token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold)) 27785 | { 27786 | token_is(token_t::e_lsqrbracket); 27787 | } 27788 | else if ( 27789 | token_is(token_t::e_rbracket,prsrhlpr_t::e_hold) && 27790 | peek_token_is(token_t::e_lsqrbracket) 27791 | ) 27792 | { 27793 | token_is(token_t::e_rbracket ); 27794 | token_is(token_t::e_lsqrbracket); 27795 | } 27796 | else 27797 | return; 27798 | 27799 | details::vector_interface<T>* vi = dynamic_cast<details::vector_interface<T>*>(expression); 27800 | 27801 | if (vi) 27802 | { 27803 | details::vector_holder<T>& vec = vi->vec()->vec_holder(); 27804 | const std::string vector_name = sem_.get_vector_name(vec.data()); 27805 | expression_node_ptr index = parse_vector_index(vector_name); 27806 | 27807 | if (index) 27808 | { 27809 | expression = synthesize_vector_element(vector_name, &vec, expression, index); 27810 | return; 27811 | } 27812 | } 27813 | 27814 | free_node(node_allocator_, expression); 27815 | expression = error_node(); 27816 | } 27817 | } 27818 | 27819 | template <typename Allocator1, 27820 | typename Allocator2, 27821 | template <typename, typename> class Sequence> 27822 | inline expression_node_ptr simplify(Sequence<expression_node_ptr,Allocator1>& expression_list, 27823 | Sequence<bool,Allocator2>& side_effect_list, 27824 | const bool specialise_on_final_type = false) 27825 | { 27826 | if (expression_list.empty()) 27827 | return error_node(); 27828 | else if (1 == expression_list.size()) 27829 | return expression_list[0]; 27830 | 27831 | Sequence<expression_node_ptr,Allocator1> tmp_expression_list; 27832 | 27833 | exprtk_debug(("simplify() - expression_list.size: %d side_effect_list.size(): %d\n", 27834 | static_cast<int>(expression_list .size()), 27835 | static_cast<int>(side_effect_list.size()))); 27836 | 27837 | bool return_node_present = false; 27838 | 27839 | for (std::size_t i = 0; i < (expression_list.size() - 1); ++i) 27840 | { 27841 | if (is_variable_node(expression_list[i])) 27842 | continue; 27843 | else if ( 27844 | is_return_node (expression_list[i]) || 27845 | is_break_node (expression_list[i]) || 27846 | is_continue_node(expression_list[i]) 27847 | ) 27848 | { 27849 | tmp_expression_list.push_back(expression_list[i]); 27850 | 27851 | // Remove all subexpressions after first short-circuit 27852 | // node has been encountered. 27853 | 27854 | for (std::size_t j = i + 1; j < expression_list.size(); ++j) 27855 | { 27856 | free_node(node_allocator_, expression_list[j]); 27857 | } 27858 | 27859 | return_node_present = true; 27860 | 27861 | break; 27862 | } 27863 | else if ( 27864 | is_constant_node(expression_list[i]) || 27865 | is_null_node (expression_list[i]) || 27866 | !side_effect_list[i] 27867 | ) 27868 | { 27869 | free_node(node_allocator_, expression_list[i]); 27870 | continue; 27871 | } 27872 | else 27873 | tmp_expression_list.push_back(expression_list[i]); 27874 | } 27875 | 27876 | if (!return_node_present) 27877 | { 27878 | tmp_expression_list.push_back(expression_list.back()); 27879 | } 27880 | 27881 | expression_list.swap(tmp_expression_list); 27882 | 27883 | if (tmp_expression_list.size() > expression_list.size()) 27884 | { 27885 | exprtk_debug(("simplify() - Reduced subexpressions from %d to %d\n", 27886 | static_cast<int>(tmp_expression_list.size()), 27887 | static_cast<int>(expression_list .size()))); 27888 | } 27889 | 27890 | if ( 27891 | return_node_present || 27892 | side_effect_list.back() || 27893 | (expression_list.size() > 1) 27894 | ) 27895 | state_.activate_side_effect("simplify()"); 27896 | 27897 | if (1 == expression_list.size()) 27898 | return expression_list[0]; 27899 | else if (specialise_on_final_type && is_generally_string_node(expression_list.back())) 27900 | return expression_generator_.vararg_function(details::e_smulti,expression_list); 27901 | else 27902 | return expression_generator_.vararg_function(details::e_multi,expression_list); 27903 | } 27904 | 27905 | inline expression_node_ptr parse_multi_sequence(const std::string& source = "", 27906 | const bool enforce_crlbrackets = false) 27907 | { 27908 | token_t::token_type open_bracket = token_t::e_lcrlbracket; 27909 | token_t::token_type close_bracket = token_t::e_rcrlbracket; 27910 | token_t::token_type separator = token_t::e_eof; 27911 | 27912 | if (!token_is(open_bracket)) 27913 | { 27914 | if (!enforce_crlbrackets && token_is(token_t::e_lbracket)) 27915 | { 27916 | open_bracket = token_t::e_lbracket; 27917 | close_bracket = token_t::e_rbracket; 27918 | separator = token_t::e_comma; 27919 | } 27920 | else 27921 | { 27922 | set_error(make_error( 27923 | parser_error::e_syntax, 27924 | current_token(), 27925 | "ERR111 - Expected '" + token_t::to_str(open_bracket) + "' for call to multi-sequence" + 27926 | ((!source.empty()) ? std::string(" section of " + source): ""), 27927 | exprtk_error_location)); 27928 | 27929 | return error_node(); 27930 | } 27931 | } 27932 | else if (token_is(close_bracket)) 27933 | { 27934 | return node_allocator_.allocate<details::null_node<T> >(); 27935 | } 27936 | 27937 | std::vector<expression_node_ptr> arg_list; 27938 | std::vector<bool> side_effect_list; 27939 | 27940 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 27941 | 27942 | scope_handler sh(*this); 27943 | 27944 | scoped_bool_or_restorer sbr(state_.side_effect_present); 27945 | 27946 | for ( ; ; ) 27947 | { 27948 | state_.side_effect_present = false; 27949 | 27950 | expression_node_ptr arg = parse_expression(); 27951 | 27952 | if (0 == arg) 27953 | return error_node(); 27954 | else 27955 | { 27956 | arg_list.push_back(arg); 27957 | side_effect_list.push_back(state_.side_effect_present); 27958 | } 27959 | 27960 | if (token_is(close_bracket)) 27961 | break; 27962 | 27963 | const bool is_next_close = peek_token_is(close_bracket); 27964 | 27965 | if (!token_is(separator) && is_next_close) 27966 | { 27967 | set_error(make_error( 27968 | parser_error::e_syntax, 27969 | current_token(), 27970 | "ERR112 - Expected '" + lexer::token::seperator_to_str(separator) + "' for call to multi-sequence section of " + source, 27971 | exprtk_error_location)); 27972 | 27973 | return error_node(); 27974 | } 27975 | 27976 | if (token_is(close_bracket)) 27977 | break; 27978 | } 27979 | 27980 | expression_node_ptr result = simplify(arg_list, side_effect_list, source.empty()); 27981 | 27982 | svd.delete_ptr = (0 == result); 27983 | return result; 27984 | } 27985 | 27986 | inline bool parse_range(range_t& rp, const bool skip_lsqr = false) 27987 | { 27988 | // Examples of valid ranges: 27989 | // 1. [1:5] -> [1,5) 27990 | // 2. [ :5] -> [0,5) 27991 | // 3. [1: ] -> [1,end) 27992 | // 4. [x:y] -> [x,y) where x <= y 27993 | // 5. [x+1:y/2] -> [x+1,y/2) where x+1 <= y/2 27994 | // 6. [ :y] -> [0,y) where 0 <= y 27995 | // 7. [x: ] -> [x,end) where x <= end 27996 | 27997 | rp.clear(); 27998 | 27999 | if (!skip_lsqr && !token_is(token_t::e_lsqrbracket)) 28000 | { 28001 | set_error(make_error( 28002 | parser_error::e_syntax, 28003 | current_token(), 28004 | "ERR113 - Expected '[' for start of range", 28005 | exprtk_error_location)); 28006 | 28007 | return false; 28008 | } 28009 | 28010 | if (token_is(token_t::e_colon)) 28011 | { 28012 | rp.n0_c.first = true; 28013 | rp.n0_c.second = 0; 28014 | rp.cache.first = 0; 28015 | } 28016 | else 28017 | { 28018 | expression_node_ptr r0 = parse_expression(); 28019 | 28020 | if (0 == r0) 28021 | { 28022 | set_error(make_error( 28023 | parser_error::e_syntax, 28024 | current_token(), 28025 | "ERR114 - Failed parse begin section of range", 28026 | exprtk_error_location)); 28027 | 28028 | return false; 28029 | } 28030 | else if (is_constant_node(r0)) 28031 | { 28032 | const T r0_value = r0->value(); 28033 | 28034 | if (r0_value >= T(0)) 28035 | { 28036 | rp.n0_c.first = true; 28037 | rp.n0_c.second = static_cast<std::size_t>(details::numeric::to_int64(r0_value)); 28038 | rp.cache.first = rp.n0_c.second; 28039 | } 28040 | 28041 | free_node(node_allocator_, r0); 28042 | 28043 | if (r0_value < T(0)) 28044 | { 28045 | set_error(make_error( 28046 | parser_error::e_syntax, 28047 | current_token(), 28048 | "ERR115 - Range lower bound less than zero! Constraint: r0 >= 0", 28049 | exprtk_error_location)); 28050 | 28051 | return false; 28052 | } 28053 | } 28054 | else 28055 | { 28056 | rp.n0_e.first = true; 28057 | rp.n0_e.second = r0; 28058 | } 28059 | 28060 | if (!token_is(token_t::e_colon)) 28061 | { 28062 | set_error(make_error( 28063 | parser_error::e_syntax, 28064 | current_token(), 28065 | "ERR116 - Expected ':' for break in range", 28066 | exprtk_error_location)); 28067 | 28068 | rp.free(); 28069 | 28070 | return false; 28071 | } 28072 | } 28073 | 28074 | if (token_is(token_t::e_rsqrbracket)) 28075 | { 28076 | rp.n1_c.first = true; 28077 | rp.n1_c.second = std::numeric_limits<std::size_t>::max(); 28078 | } 28079 | else 28080 | { 28081 | expression_node_ptr r1 = parse_expression(); 28082 | 28083 | if (0 == r1) 28084 | { 28085 | set_error(make_error( 28086 | parser_error::e_syntax, 28087 | current_token(), 28088 | "ERR117 - Failed parse end section of range", 28089 | exprtk_error_location)); 28090 | 28091 | rp.free(); 28092 | 28093 | return false; 28094 | } 28095 | else if (is_constant_node(r1)) 28096 | { 28097 | const T r1_value = r1->value(); 28098 | 28099 | if (r1_value >= T(0)) 28100 | { 28101 | rp.n1_c.first = true; 28102 | rp.n1_c.second = static_cast<std::size_t>(details::numeric::to_int64(r1_value)); 28103 | rp.cache.second = rp.n1_c.second; 28104 | } 28105 | 28106 | free_node(node_allocator_, r1); 28107 | 28108 | if (r1_value < T(0)) 28109 | { 28110 | set_error(make_error( 28111 | parser_error::e_syntax, 28112 | current_token(), 28113 | "ERR118 - Range upper bound less than zero! Constraint: r1 >= 0", 28114 | exprtk_error_location)); 28115 | 28116 | rp.free(); 28117 | 28118 | return false; 28119 | } 28120 | } 28121 | else 28122 | { 28123 | rp.n1_e.first = true; 28124 | rp.n1_e.second = r1; 28125 | } 28126 | 28127 | if (!token_is(token_t::e_rsqrbracket)) 28128 | { 28129 | set_error(make_error( 28130 | parser_error::e_syntax, 28131 | current_token(), 28132 | "ERR119 - Expected ']' for start of range", 28133 | exprtk_error_location)); 28134 | 28135 | rp.free(); 28136 | 28137 | return false; 28138 | } 28139 | } 28140 | 28141 | if (rp.const_range()) 28142 | { 28143 | std::size_t r0 = 0; 28144 | std::size_t r1 = 0; 28145 | 28146 | bool rp_result = false; 28147 | 28148 | try 28149 | { 28150 | rp_result = rp(r0, r1); 28151 | } 28152 | catch (std::runtime_error&) 28153 | {} 28154 | 28155 | if (!rp_result || (r0 > r1)) 28156 | { 28157 | set_error(make_error( 28158 | parser_error::e_syntax, 28159 | current_token(), 28160 | "ERR120 - Invalid range, Constraint: r0 <= r1", 28161 | exprtk_error_location)); 28162 | 28163 | return false; 28164 | } 28165 | } 28166 | 28167 | return true; 28168 | } 28169 | 28170 | inline void lodge_symbol(const std::string& symbol, 28171 | const symbol_type st) 28172 | { 28173 | dec_.add_symbol(symbol,st); 28174 | } 28175 | 28176 | #ifndef exprtk_disable_string_capabilities 28177 | inline expression_node_ptr parse_string() 28178 | { 28179 | const std::string symbol = current_token().value; 28180 | 28181 | typedef details::stringvar_node<T>* strvar_node_t; 28182 | 28183 | expression_node_ptr result = error_node(); 28184 | strvar_node_t const_str_node = static_cast<strvar_node_t>(0); 28185 | 28186 | scope_element& se = sem_.get_active_element(symbol); 28187 | 28188 | if (scope_element::e_string == se.type) 28189 | { 28190 | se.active = true; 28191 | result = se.str_node; 28192 | lodge_symbol(symbol, e_st_local_string); 28193 | } 28194 | else 28195 | { 28196 | typedef typename symtab_store::string_context str_ctxt_t; 28197 | str_ctxt_t str_ctx = symtab_store_.get_string_context(symbol); 28198 | 28199 | if ((0 == str_ctx.str_var) || !symtab_store_.is_conststr_stringvar(symbol)) 28200 | { 28201 | set_error(make_error( 28202 | parser_error::e_syntax, 28203 | current_token(), 28204 | "ERR121 - Unknown string symbol", 28205 | exprtk_error_location)); 28206 | 28207 | return error_node(); 28208 | } 28209 | 28210 | assert(str_ctx.str_var != 0); 28211 | assert(str_ctx.symbol_table != 0); 28212 | 28213 | result = str_ctx.str_var; 28214 | 28215 | if (symtab_store_.is_constant_string(symbol)) 28216 | { 28217 | const_str_node = static_cast<strvar_node_t>(result); 28218 | result = expression_generator_(const_str_node->str()); 28219 | } 28220 | else if (symbol_table_t::e_immutable == str_ctx.symbol_table->mutability()) 28221 | { 28222 | lodge_immutable_symbol( 28223 | current_token(), 28224 | make_memory_range(str_ctx.str_var->base(), str_ctx.str_var->size())); 28225 | } 28226 | 28227 | lodge_symbol(symbol, e_st_string); 28228 | } 28229 | 28230 | if (peek_token_is(token_t::e_lsqrbracket)) 28231 | { 28232 | next_token(); 28233 | 28234 | if (peek_token_is(token_t::e_rsqrbracket)) 28235 | { 28236 | next_token(); 28237 | next_token(); 28238 | 28239 | if (const_str_node) 28240 | { 28241 | free_node(node_allocator_, result); 28242 | 28243 | return expression_generator_(T(const_str_node->size())); 28244 | } 28245 | else 28246 | return node_allocator_.allocate<details::stringvar_size_node<T> > 28247 | (static_cast<details::stringvar_node<T>*>(result)->ref()); 28248 | } 28249 | 28250 | range_t rp; 28251 | 28252 | if (!parse_range(rp)) 28253 | { 28254 | free_node(node_allocator_, result); 28255 | 28256 | return error_node(); 28257 | } 28258 | else if (const_str_node) 28259 | { 28260 | free_node(node_allocator_, result); 28261 | result = expression_generator_(const_str_node->ref(),rp); 28262 | } 28263 | else 28264 | result = expression_generator_(static_cast<details::stringvar_node<T>*> 28265 | (result)->ref(), rp); 28266 | 28267 | if (result) 28268 | rp.clear(); 28269 | } 28270 | else 28271 | next_token(); 28272 | 28273 | return result; 28274 | } 28275 | #else 28276 | inline expression_node_ptr parse_string() 28277 | { 28278 | return error_node(); 28279 | } 28280 | #endif 28281 | 28282 | #ifndef exprtk_disable_string_capabilities 28283 | inline expression_node_ptr parse_const_string() 28284 | { 28285 | const std::string const_str = current_token().value; 28286 | expression_node_ptr result = expression_generator_(const_str); 28287 | 28288 | if (peek_token_is(token_t::e_lsqrbracket)) 28289 | { 28290 | next_token(); 28291 | 28292 | if (peek_token_is(token_t::e_rsqrbracket)) 28293 | { 28294 | next_token(); 28295 | next_token(); 28296 | 28297 | free_node(node_allocator_, result); 28298 | 28299 | return expression_generator_(T(const_str.size())); 28300 | } 28301 | 28302 | range_t rp; 28303 | 28304 | if (!parse_range(rp)) 28305 | { 28306 | free_node(node_allocator_, result); 28307 | rp.free(); 28308 | 28309 | return error_node(); 28310 | } 28311 | 28312 | free_node(node_allocator_, result); 28313 | 28314 | if (rp.n1_c.first && (rp.n1_c.second == std::numeric_limits<std::size_t>::max())) 28315 | { 28316 | rp.n1_c.second = const_str.size() - 1; 28317 | rp.cache.second = rp.n1_c.second; 28318 | } 28319 | 28320 | if ( 28321 | (rp.n0_c.first && (rp.n0_c.second >= const_str.size())) || 28322 | (rp.n1_c.first && (rp.n1_c.second >= const_str.size())) 28323 | ) 28324 | { 28325 | set_error(make_error( 28326 | parser_error::e_syntax, 28327 | current_token(), 28328 | "ERR122 - Overflow in range for string: '" + const_str + "'[" + 28329 | (rp.n0_c.first ? details::to_str(static_cast<int>(rp.n0_c.second)) : "?") + ":" + 28330 | (rp.n1_c.first ? details::to_str(static_cast<int>(rp.n1_c.second)) : "?") + "]", 28331 | exprtk_error_location)); 28332 | 28333 | rp.free(); 28334 | 28335 | return error_node(); 28336 | } 28337 | 28338 | result = expression_generator_(const_str,rp); 28339 | 28340 | if (result) 28341 | rp.clear(); 28342 | } 28343 | else 28344 | next_token(); 28345 | 28346 | return result; 28347 | } 28348 | #else 28349 | inline expression_node_ptr parse_const_string() 28350 | { 28351 | return error_node(); 28352 | } 28353 | #endif 28354 | 28355 | inline expression_node_ptr parse_vector_index(const std::string& vector_name = "") 28356 | { 28357 | expression_node_ptr index_expr = error_node(); 28358 | 28359 | if (0 == (index_expr = parse_expression())) 28360 | { 28361 | set_error(make_error( 28362 | parser_error::e_syntax, 28363 | current_token(), 28364 | "ERR123 - Failed to parse index for vector: '" + vector_name + "'", 28365 | exprtk_error_location)); 28366 | 28367 | return error_node(); 28368 | } 28369 | else if (!token_is(token_t::e_rsqrbracket)) 28370 | { 28371 | set_error(make_error( 28372 | parser_error::e_syntax, 28373 | current_token(), 28374 | "ERR124 - Expected ']' for index of vector: '" + vector_name + "'", 28375 | exprtk_error_location)); 28376 | 28377 | free_node(node_allocator_, index_expr); 28378 | 28379 | return error_node(); 28380 | } 28381 | 28382 | return index_expr; 28383 | } 28384 | 28385 | inline expression_node_ptr parse_vector() 28386 | { 28387 | const std::string vector_name = current_token().value; 28388 | 28389 | vector_holder_ptr vec = vector_holder_ptr(0); 28390 | 28391 | const scope_element& se = sem_.get_active_element(vector_name); 28392 | 28393 | if ( 28394 | !details::imatch(se.name, vector_name) || 28395 | (se.depth > state_.scope_depth) || 28396 | (scope_element::e_vector != se.type) 28397 | ) 28398 | { 28399 | typedef typename symtab_store::vector_context vec_ctxt_t; 28400 | vec_ctxt_t vec_ctx = symtab_store_.get_vector_context(vector_name); 28401 | 28402 | if (0 == vec_ctx.vector_holder) 28403 | { 28404 | set_error(make_error( 28405 | parser_error::e_syntax, 28406 | current_token(), 28407 | "ERR125 - Symbol '" + vector_name + " not a vector", 28408 | exprtk_error_location)); 28409 | 28410 | return error_node(); 28411 | } 28412 | 28413 | assert(0 != vec_ctx.vector_holder); 28414 | assert(0 != vec_ctx.symbol_table ); 28415 | 28416 | vec = vec_ctx.vector_holder; 28417 | 28418 | if (symbol_table_t::e_immutable == vec_ctx.symbol_table->mutability()) 28419 | { 28420 | lodge_immutable_symbol( 28421 | current_token(), 28422 | make_memory_range(vec->data(), vec->size())); 28423 | } 28424 | } 28425 | else 28426 | { 28427 | vec = se.vec_node; 28428 | } 28429 | 28430 | assert(0 != vec); 28431 | 28432 | next_token(); 28433 | 28434 | if (!token_is(token_t::e_lsqrbracket)) 28435 | { 28436 | return node_allocator_.allocate<vector_node_t>(vec); 28437 | } 28438 | else if (token_is(token_t::e_rsqrbracket)) 28439 | { 28440 | return (vec->rebaseable()) ? 28441 | node_allocator_.allocate<vector_size_node_t>(vec) : 28442 | expression_generator_(T(vec->size())); 28443 | } 28444 | 28445 | expression_node_ptr index_expr = parse_vector_index(vector_name); 28446 | 28447 | if (index_expr) 28448 | { 28449 | expression_node_ptr vec_node = node_allocator_.allocate<vector_node_t>(vec); 28450 | 28451 | return synthesize_vector_element(vector_name, vec, vec_node, index_expr); 28452 | } 28453 | 28454 | return error_node(); 28455 | } 28456 | 28457 | inline expression_node_ptr synthesize_vector_element(const std::string& vector_name, 28458 | vector_holder_ptr vec, 28459 | expression_node_ptr vec_node, 28460 | expression_node_ptr index_expr) 28461 | { 28462 | // Perform compile-time range check 28463 | if (details::is_constant_node(index_expr)) 28464 | { 28465 | const std::size_t index = static_cast<std::size_t>(details::numeric::to_int32(index_expr->value())); 28466 | const std::size_t vec_size = vec->size(); 28467 | 28468 | if (index >= vec_size) 28469 | { 28470 | set_error(make_error( 28471 | parser_error::e_syntax, 28472 | current_token(), 28473 | "ERR126 - Index of " + details::to_str(index) + " out of range for " 28474 | "vector '" + vector_name + "' of size " + details::to_str(vec_size), 28475 | exprtk_error_location)); 28476 | 28477 | free_node(node_allocator_, vec_node ); 28478 | free_node(node_allocator_, index_expr); 28479 | 28480 | return error_node(); 28481 | } 28482 | } 28483 | 28484 | return expression_generator_.vector_element(vector_name, vec, vec_node, index_expr); 28485 | } 28486 | 28487 | inline expression_node_ptr parse_vararg_function_call(ivararg_function<T>* vararg_function, const std::string& vararg_function_name) 28488 | { 28489 | std::vector<expression_node_ptr> arg_list; 28490 | 28491 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 28492 | 28493 | next_token(); 28494 | 28495 | if (token_is(token_t::e_lbracket)) 28496 | { 28497 | if (token_is(token_t::e_rbracket)) 28498 | { 28499 | if (!vararg_function->allow_zero_parameters()) 28500 | { 28501 | set_error(make_error( 28502 | parser_error::e_syntax, 28503 | current_token(), 28504 | "ERR127 - Zero parameter call to vararg function: " 28505 | + vararg_function_name + " not allowed", 28506 | exprtk_error_location)); 28507 | 28508 | return error_node(); 28509 | } 28510 | } 28511 | else 28512 | { 28513 | for ( ; ; ) 28514 | { 28515 | expression_node_ptr arg = parse_expression(); 28516 | 28517 | if (0 == arg) 28518 | return error_node(); 28519 | else 28520 | arg_list.push_back(arg); 28521 | 28522 | if (token_is(token_t::e_rbracket)) 28523 | break; 28524 | else if (!token_is(token_t::e_comma)) 28525 | { 28526 | set_error(make_error( 28527 | parser_error::e_syntax, 28528 | current_token(), 28529 | "ERR128 - Expected ',' for call to vararg function: " 28530 | + vararg_function_name, 28531 | exprtk_error_location)); 28532 | 28533 | return error_node(); 28534 | } 28535 | } 28536 | } 28537 | } 28538 | else if (!vararg_function->allow_zero_parameters()) 28539 | { 28540 | set_error(make_error( 28541 | parser_error::e_syntax, 28542 | current_token(), 28543 | "ERR129 - Zero parameter call to vararg function: " 28544 | + vararg_function_name + " not allowed", 28545 | exprtk_error_location)); 28546 | 28547 | return error_node(); 28548 | } 28549 | 28550 | if (arg_list.size() < vararg_function->min_num_args()) 28551 | { 28552 | set_error(make_error( 28553 | parser_error::e_syntax, 28554 | current_token(), 28555 | "ERR130 - Invalid number of parameters to call to vararg function: " 28556 | + vararg_function_name + ", require at least " 28557 | + details::to_str(static_cast<int>(vararg_function->min_num_args())) + " parameters", 28558 | exprtk_error_location)); 28559 | 28560 | return error_node(); 28561 | } 28562 | else if (arg_list.size() > vararg_function->max_num_args()) 28563 | { 28564 | set_error(make_error( 28565 | parser_error::e_syntax, 28566 | current_token(), 28567 | "ERR131 - Invalid number of parameters to call to vararg function: " 28568 | + vararg_function_name + ", require no more than " 28569 | + details::to_str(static_cast<int>(vararg_function->max_num_args())) + " parameters", 28570 | exprtk_error_location)); 28571 | 28572 | return error_node(); 28573 | } 28574 | 28575 | expression_node_ptr result = expression_generator_.vararg_function_call(vararg_function,arg_list); 28576 | 28577 | svd.delete_ptr = (0 == result); 28578 | 28579 | return result; 28580 | } 28581 | 28582 | class type_checker 28583 | { 28584 | public: 28585 | 28586 | enum return_type_t 28587 | { 28588 | e_overload = ' ', 28589 | e_numeric = 'T', 28590 | e_string = 'S' 28591 | }; 28592 | 28593 | struct function_prototype_t 28594 | { 28595 | return_type_t return_type; 28596 | std::string param_seq; 28597 | }; 28598 | 28599 | typedef parser<T> parser_t; 28600 | typedef std::vector<function_prototype_t> function_definition_list_t; 28601 | 28602 | type_checker(parser_t& p, 28603 | const std::string& func_name, 28604 | const std::string& func_prototypes, 28605 | const return_type_t default_return_type) 28606 | : invalid_state_(true) 28607 | , parser_(p) 28608 | , function_name_(func_name) 28609 | , default_return_type_(default_return_type) 28610 | { 28611 | parse_function_prototypes(func_prototypes); 28612 | } 28613 | 28614 | bool verify(const std::string& param_seq, std::size_t& pseq_index) 28615 | { 28616 | if (function_definition_list_.empty()) 28617 | return true; 28618 | 28619 | std::vector<std::pair<std::size_t,char> > error_list; 28620 | 28621 | for (std::size_t i = 0; i < function_definition_list_.size(); ++i) 28622 | { 28623 | details::char_t diff_value = 0; 28624 | std::size_t diff_index = 0; 28625 | 28626 | const bool result = details::sequence_match(function_definition_list_[i].param_seq, 28627 | param_seq, 28628 | diff_index, diff_value); 28629 | 28630 | if (result) 28631 | { 28632 | pseq_index = i; 28633 | return true; 28634 | } 28635 | else 28636 | error_list.push_back(std::make_pair(diff_index, diff_value)); 28637 | } 28638 | 28639 | if (1 == error_list.size()) 28640 | { 28641 | parser_.set_error(make_error( 28642 | parser_error::e_syntax, 28643 | parser_.current_token(), 28644 | "ERR132 - Failed parameter type check for function '" + function_name_ + "', " 28645 | "Expected '" + function_definition_list_[0].param_seq + 28646 | "' call set: '" + param_seq + "'", 28647 | exprtk_error_location)); 28648 | } 28649 | else 28650 | { 28651 | // find first with largest diff_index; 28652 | std::size_t max_diff_index = 0; 28653 | 28654 | for (std::size_t i = 1; i < error_list.size(); ++i) 28655 | { 28656 | if (error_list[i].first > error_list[max_diff_index].first) 28657 | { 28658 | max_diff_index = i; 28659 | } 28660 | } 28661 | 28662 | parser_.set_error(make_error( 28663 | parser_error::e_syntax, 28664 | parser_.current_token(), 28665 | "ERR133 - Failed parameter type check for function '" + function_name_ + "', " 28666 | "Best match: '" + function_definition_list_[max_diff_index].param_seq + 28667 | "' call set: '" + param_seq + "'", 28668 | exprtk_error_location)); 28669 | } 28670 | 28671 | return false; 28672 | } 28673 | 28674 | std::size_t paramseq_count() const 28675 | { 28676 | return function_definition_list_.size(); 28677 | } 28678 | 28679 | std::string paramseq(const std::size_t& index) const 28680 | { 28681 | return function_definition_list_[index].param_seq; 28682 | } 28683 | 28684 | return_type_t return_type(const std::size_t& index) const 28685 | { 28686 | return function_definition_list_[index].return_type; 28687 | } 28688 | 28689 | bool invalid() const 28690 | { 28691 | return !invalid_state_; 28692 | } 28693 | 28694 | bool allow_zero_parameters() const 28695 | { 28696 | 28697 | for (std::size_t i = 0; i < function_definition_list_.size(); ++i) 28698 | { 28699 | if (std::string::npos != function_definition_list_[i].param_seq.find("Z")) 28700 | { 28701 | return true; 28702 | } 28703 | } 28704 | 28705 | return false; 28706 | } 28707 | 28708 | private: 28709 | 28710 | std::vector<std::string> split_param_seq(const std::string& param_seq, const details::char_t delimiter = '|') const 28711 | { 28712 | std::string::const_iterator current_begin = param_seq.begin(); 28713 | std::string::const_iterator iter = param_seq.begin(); 28714 | 28715 | std::vector<std::string> result; 28716 | 28717 | while (iter != param_seq.end()) 28718 | { 28719 | if (*iter == delimiter) 28720 | { 28721 | result.push_back(std::string(current_begin, iter)); 28722 | current_begin = ++iter; 28723 | } 28724 | else 28725 | ++iter; 28726 | } 28727 | 28728 | if (current_begin != iter) 28729 | { 28730 | result.push_back(std::string(current_begin, iter)); 28731 | } 28732 | 28733 | return result; 28734 | } 28735 | 28736 | inline bool is_valid_token(std::string param_seq, 28737 | function_prototype_t& funcproto) const 28738 | { 28739 | // Determine return type 28740 | funcproto.return_type = default_return_type_; 28741 | 28742 | if (param_seq.size() > 2) 28743 | { 28744 | if (':' == param_seq[1]) 28745 | { 28746 | // Note: Only overloaded igeneric functions can have return 28747 | // type definitions. 28748 | if (type_checker::e_overload != default_return_type_) 28749 | return false; 28750 | 28751 | switch (param_seq[0]) 28752 | { 28753 | case 'T' : funcproto.return_type = type_checker::e_numeric; 28754 | break; 28755 | 28756 | case 'S' : funcproto.return_type = type_checker::e_string; 28757 | break; 28758 | 28759 | default : return false; 28760 | } 28761 | 28762 | param_seq.erase(0,2); 28763 | } 28764 | } 28765 | 28766 | if ( 28767 | (std::string::npos != param_seq.find("?*")) || 28768 | (std::string::npos != param_seq.find("**")) 28769 | ) 28770 | { 28771 | return false; 28772 | } 28773 | else if ( 28774 | (std::string::npos == param_seq.find_first_not_of("STV*?|")) || 28775 | ("Z" == param_seq) 28776 | ) 28777 | { 28778 | funcproto.param_seq = param_seq; 28779 | return true; 28780 | } 28781 | 28782 | return false; 28783 | } 28784 | 28785 | void parse_function_prototypes(const std::string& func_prototypes) 28786 | { 28787 | if (func_prototypes.empty()) 28788 | return; 28789 | 28790 | std::vector<std::string> param_seq_list = split_param_seq(func_prototypes); 28791 | 28792 | typedef std::map<std::string,std::size_t> param_seq_map_t; 28793 | param_seq_map_t param_seq_map; 28794 | 28795 | for (std::size_t i = 0; i < param_seq_list.size(); ++i) 28796 | { 28797 | function_prototype_t func_proto; 28798 | 28799 | if (!is_valid_token(param_seq_list[i], func_proto)) 28800 | { 28801 | invalid_state_ = false; 28802 | 28803 | parser_.set_error(make_error( 28804 | parser_error::e_syntax, 28805 | parser_.current_token(), 28806 | "ERR134 - Invalid parameter sequence of '" + param_seq_list[i] + 28807 | "' for function: " + function_name_, 28808 | exprtk_error_location)); 28809 | return; 28810 | } 28811 | 28812 | param_seq_map_t::const_iterator seq_itr = param_seq_map.find(param_seq_list[i]); 28813 | 28814 | if (param_seq_map.end() != seq_itr) 28815 | { 28816 | invalid_state_ = false; 28817 | 28818 | parser_.set_error(make_error( 28819 | parser_error::e_syntax, 28820 | parser_.current_token(), 28821 | "ERR135 - Function '" + function_name_ + "' has a parameter sequence conflict between " + 28822 | "pseq_idx[" + details::to_str(seq_itr->second) + "] and" + 28823 | "pseq_idx[" + details::to_str(i) + "] " + 28824 | "param seq: " + param_seq_list[i], 28825 | exprtk_error_location)); 28826 | return; 28827 | } 28828 | 28829 | function_definition_list_.push_back(func_proto); 28830 | } 28831 | } 28832 | 28833 | type_checker(const type_checker&) exprtk_delete; 28834 | type_checker& operator=(const type_checker&) exprtk_delete; 28835 | 28836 | bool invalid_state_; 28837 | parser_t& parser_; 28838 | std::string function_name_; 28839 | const return_type_t default_return_type_; 28840 | function_definition_list_t function_definition_list_; 28841 | }; 28842 | 28843 | inline expression_node_ptr parse_generic_function_call(igeneric_function<T>* function, const std::string& function_name) 28844 | { 28845 | std::vector<expression_node_ptr> arg_list; 28846 | 28847 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 28848 | 28849 | next_token(); 28850 | 28851 | std::string param_type_list; 28852 | 28853 | type_checker tc( 28854 | (*this), 28855 | function_name, 28856 | function->parameter_sequence, 28857 | type_checker::e_string); 28858 | 28859 | if (tc.invalid()) 28860 | { 28861 | set_error(make_error( 28862 | parser_error::e_syntax, 28863 | current_token(), 28864 | "ERR136 - Type checker instantiation failure for generic function: " + function_name, 28865 | exprtk_error_location)); 28866 | 28867 | return error_node(); 28868 | } 28869 | 28870 | if (token_is(token_t::e_lbracket)) 28871 | { 28872 | if (token_is(token_t::e_rbracket)) 28873 | { 28874 | if ( 28875 | !function->allow_zero_parameters() && 28876 | !tc .allow_zero_parameters() 28877 | ) 28878 | { 28879 | set_error(make_error( 28880 | parser_error::e_syntax, 28881 | current_token(), 28882 | "ERR137 - Zero parameter call to generic function: " 28883 | + function_name + " not allowed", 28884 | exprtk_error_location)); 28885 | 28886 | return error_node(); 28887 | } 28888 | } 28889 | else 28890 | { 28891 | for ( ; ; ) 28892 | { 28893 | expression_node_ptr arg = parse_expression(); 28894 | 28895 | if (0 == arg) 28896 | return error_node(); 28897 | 28898 | if (is_ivector_node(arg)) 28899 | param_type_list += 'V'; 28900 | else if (is_generally_string_node(arg)) 28901 | param_type_list += 'S'; 28902 | else // Everything else is assumed to be a scalar returning expression 28903 | param_type_list += 'T'; 28904 | 28905 | arg_list.push_back(arg); 28906 | 28907 | if (token_is(token_t::e_rbracket)) 28908 | break; 28909 | else if (!token_is(token_t::e_comma)) 28910 | { 28911 | set_error(make_error( 28912 | parser_error::e_syntax, 28913 | current_token(), 28914 | "ERR138 - Expected ',' for call to generic function: " + function_name, 28915 | exprtk_error_location)); 28916 | 28917 | return error_node(); 28918 | } 28919 | } 28920 | } 28921 | } 28922 | else if ( 28923 | !function->parameter_sequence.empty() && 28924 | function->allow_zero_parameters () && 28925 | !tc .allow_zero_parameters () 28926 | ) 28927 | { 28928 | set_error(make_error( 28929 | parser_error::e_syntax, 28930 | current_token(), 28931 | "ERR139 - Zero parameter call to generic function: " 28932 | + function_name + " not allowed", 28933 | exprtk_error_location)); 28934 | 28935 | return error_node(); 28936 | } 28937 | 28938 | std::size_t param_seq_index = 0; 28939 | 28940 | if ( 28941 | state_.type_check_enabled && 28942 | !tc.verify(param_type_list, param_seq_index) 28943 | ) 28944 | { 28945 | set_error(make_error( 28946 | parser_error::e_syntax, 28947 | current_token(), 28948 | "ERR140 - Invalid input parameter sequence for call to generic function: " + function_name, 28949 | exprtk_error_location)); 28950 | 28951 | return error_node(); 28952 | } 28953 | 28954 | expression_node_ptr result = 28955 | (tc.paramseq_count() <= 1) ? 28956 | expression_generator_ 28957 | .generic_function_call(function, arg_list) : 28958 | expression_generator_ 28959 | .generic_function_call(function, arg_list, param_seq_index); 28960 | 28961 | svd.delete_ptr = (0 == result); 28962 | 28963 | return result; 28964 | } 28965 | 28966 | inline bool parse_igeneric_function_params(std::string& param_type_list, 28967 | std::vector<expression_node_ptr>& arg_list, 28968 | const std::string& function_name, 28969 | igeneric_function<T>* function, 28970 | const type_checker& tc) 28971 | { 28972 | if (token_is(token_t::e_lbracket)) 28973 | { 28974 | if (token_is(token_t::e_rbracket)) 28975 | { 28976 | if ( 28977 | !function->allow_zero_parameters() && 28978 | !tc .allow_zero_parameters() 28979 | ) 28980 | { 28981 | set_error(make_error( 28982 | parser_error::e_syntax, 28983 | current_token(), 28984 | "ERR141 - Zero parameter call to generic function: " 28985 | + function_name + " not allowed", 28986 | exprtk_error_location)); 28987 | 28988 | return false; 28989 | } 28990 | } 28991 | else 28992 | { 28993 | for ( ; ; ) 28994 | { 28995 | expression_node_ptr arg = parse_expression(); 28996 | 28997 | if (0 == arg) 28998 | return false; 28999 | 29000 | if (is_ivector_node(arg)) 29001 | param_type_list += 'V'; 29002 | else if (is_generally_string_node(arg)) 29003 | param_type_list += 'S'; 29004 | else // Everything else is a scalar returning expression 29005 | param_type_list += 'T'; 29006 | 29007 | arg_list.push_back(arg); 29008 | 29009 | if (token_is(token_t::e_rbracket)) 29010 | break; 29011 | else if (!token_is(token_t::e_comma)) 29012 | { 29013 | set_error(make_error( 29014 | parser_error::e_syntax, 29015 | current_token(), 29016 | "ERR142 - Expected ',' for call to string function: " + function_name, 29017 | exprtk_error_location)); 29018 | 29019 | return false; 29020 | } 29021 | } 29022 | } 29023 | 29024 | return true; 29025 | } 29026 | else 29027 | return false; 29028 | } 29029 | 29030 | #ifndef exprtk_disable_string_capabilities 29031 | inline expression_node_ptr parse_string_function_call(igeneric_function<T>* function, const std::string& function_name) 29032 | { 29033 | // Move pass the function name 29034 | next_token(); 29035 | 29036 | std::string param_type_list; 29037 | 29038 | type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_string); 29039 | 29040 | if ( 29041 | (!function->parameter_sequence.empty()) && 29042 | (0 == tc.paramseq_count()) 29043 | ) 29044 | { 29045 | return error_node(); 29046 | } 29047 | 29048 | std::vector<expression_node_ptr> arg_list; 29049 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 29050 | 29051 | if (!parse_igeneric_function_params(param_type_list, arg_list, function_name, function, tc)) 29052 | { 29053 | return error_node(); 29054 | } 29055 | 29056 | std::size_t param_seq_index = 0; 29057 | 29058 | if (!tc.verify(param_type_list, param_seq_index)) 29059 | { 29060 | set_error(make_error( 29061 | parser_error::e_syntax, 29062 | current_token(), 29063 | "ERR143 - Invalid input parameter sequence for call to string function: " + function_name, 29064 | exprtk_error_location)); 29065 | 29066 | return error_node(); 29067 | } 29068 | 29069 | expression_node_ptr result = 29070 | (tc.paramseq_count() <= 1) ? 29071 | expression_generator_ 29072 | .string_function_call(function, arg_list) : 29073 | expression_generator_ 29074 | .string_function_call(function, arg_list, param_seq_index); 29075 | 29076 | svd.delete_ptr = (0 == result); 29077 | 29078 | return result; 29079 | } 29080 | 29081 | inline expression_node_ptr parse_overload_function_call(igeneric_function<T>* function, const std::string& function_name) 29082 | { 29083 | // Move pass the function name 29084 | next_token(); 29085 | 29086 | std::string param_type_list; 29087 | 29088 | type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_overload); 29089 | 29090 | if ( 29091 | (!function->parameter_sequence.empty()) && 29092 | (0 == tc.paramseq_count()) 29093 | ) 29094 | { 29095 | return error_node(); 29096 | } 29097 | 29098 | std::vector<expression_node_ptr> arg_list; 29099 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 29100 | 29101 | if (!parse_igeneric_function_params(param_type_list, arg_list, function_name, function, tc)) 29102 | { 29103 | return error_node(); 29104 | } 29105 | 29106 | std::size_t param_seq_index = 0; 29107 | 29108 | if (!tc.verify(param_type_list, param_seq_index)) 29109 | { 29110 | set_error(make_error( 29111 | parser_error::e_syntax, 29112 | current_token(), 29113 | "ERR144 - Invalid input parameter sequence for call to overloaded function: " + function_name, 29114 | exprtk_error_location)); 29115 | 29116 | return error_node(); 29117 | } 29118 | 29119 | expression_node_ptr result = error_node(); 29120 | 29121 | if (type_checker::e_numeric == tc.return_type(param_seq_index)) 29122 | { 29123 | if (tc.paramseq_count() <= 1) 29124 | result = expression_generator_ 29125 | .generic_function_call(function, arg_list); 29126 | else 29127 | result = expression_generator_ 29128 | .generic_function_call(function, arg_list, param_seq_index); 29129 | } 29130 | else if (type_checker::e_string == tc.return_type(param_seq_index)) 29131 | { 29132 | if (tc.paramseq_count() <= 1) 29133 | result = expression_generator_ 29134 | .string_function_call(function, arg_list); 29135 | else 29136 | result = expression_generator_ 29137 | .string_function_call(function, arg_list, param_seq_index); 29138 | } 29139 | else 29140 | { 29141 | set_error(make_error( 29142 | parser_error::e_syntax, 29143 | current_token(), 29144 | "ERR145 - Invalid return type for call to overloaded function: " + function_name, 29145 | exprtk_error_location)); 29146 | } 29147 | 29148 | svd.delete_ptr = (0 == result); 29149 | return result; 29150 | } 29151 | #endif 29152 | 29153 | template <typename Type, std::size_t NumberOfParameters> 29154 | struct parse_special_function_impl 29155 | { 29156 | static inline expression_node_ptr process(parser<Type>& p, const details::operator_type opt_type, const std::string& sf_name) 29157 | { 29158 | expression_node_ptr branch[NumberOfParameters]; 29159 | expression_node_ptr result = error_node(); 29160 | 29161 | std::fill_n(branch, NumberOfParameters, reinterpret_cast<expression_node_ptr>(0)); 29162 | 29163 | scoped_delete<expression_node_t,NumberOfParameters> sd(p,branch); 29164 | 29165 | p.next_token(); 29166 | 29167 | if (!p.token_is(token_t::e_lbracket)) 29168 | { 29169 | p.set_error(make_error( 29170 | parser_error::e_syntax, 29171 | p.current_token(), 29172 | "ERR146 - Expected '(' for special function '" + sf_name + "'", 29173 | exprtk_error_location)); 29174 | 29175 | return error_node(); 29176 | } 29177 | 29178 | for (std::size_t i = 0; i < NumberOfParameters; ++i) 29179 | { 29180 | branch[i] = p.parse_expression(); 29181 | 29182 | if (0 == branch[i]) 29183 | { 29184 | return p.error_node(); 29185 | } 29186 | else if (i < (NumberOfParameters - 1)) 29187 | { 29188 | if (!p.token_is(token_t::e_comma)) 29189 | { 29190 | p.set_error(make_error( 29191 | parser_error::e_syntax, 29192 | p.current_token(), 29193 | "ERR147 - Expected ',' before next parameter of special function '" + sf_name + "'", 29194 | exprtk_error_location)); 29195 | 29196 | return p.error_node(); 29197 | } 29198 | } 29199 | } 29200 | 29201 | if (!p.token_is(token_t::e_rbracket)) 29202 | { 29203 | p.set_error(make_error( 29204 | parser_error::e_syntax, 29205 | p.current_token(), 29206 | "ERR148 - Invalid number of parameters for special function '" + sf_name + "'", 29207 | exprtk_error_location)); 29208 | 29209 | return p.error_node(); 29210 | } 29211 | else 29212 | result = p.expression_generator_.special_function(opt_type,branch); 29213 | 29214 | sd.delete_ptr = (0 == result); 29215 | 29216 | return result; 29217 | } 29218 | }; 29219 | 29220 | inline expression_node_ptr parse_special_function() 29221 | { 29222 | const std::string sf_name = current_token().value; 29223 | 29224 | // Expect: $fDD(expr0,expr1,expr2) or $fDD(expr0,expr1,expr2,expr3) 29225 | if ( 29226 | !details::is_digit(sf_name[2]) || 29227 | !details::is_digit(sf_name[3]) 29228 | ) 29229 | { 29230 | set_error(make_error( 29231 | parser_error::e_token, 29232 | current_token(), 29233 | "ERR149 - Invalid special function[1]: " + sf_name, 29234 | exprtk_error_location)); 29235 | 29236 | return error_node(); 29237 | } 29238 | 29239 | const int id = (sf_name[2] - '0') * 10 + 29240 | (sf_name[3] - '0'); 29241 | 29242 | if (id >= details::e_sffinal) 29243 | { 29244 | set_error(make_error( 29245 | parser_error::e_token, 29246 | current_token(), 29247 | "ERR150 - Invalid special function[2]: " + sf_name, 29248 | exprtk_error_location)); 29249 | 29250 | return error_node(); 29251 | } 29252 | 29253 | const int sf_3_to_4 = details::e_sf48; 29254 | const details::operator_type opt_type = details::operator_type(id + 1000); 29255 | const std::size_t NumberOfParameters = (id < (sf_3_to_4 - 1000)) ? 3U : 4U; 29256 | 29257 | switch (NumberOfParameters) 29258 | { 29259 | case 3 : return parse_special_function_impl<T,3>::process((*this), opt_type, sf_name); 29260 | case 4 : return parse_special_function_impl<T,4>::process((*this), opt_type, sf_name); 29261 | default : return error_node(); 29262 | } 29263 | } 29264 | 29265 | inline expression_node_ptr parse_null_statement() 29266 | { 29267 | next_token(); 29268 | return node_allocator_.allocate<details::null_node<T> >(); 29269 | } 29270 | 29271 | #ifndef exprtk_disable_break_continue 29272 | inline expression_node_ptr parse_break_statement() 29273 | { 29274 | if (state_.parsing_break_stmt) 29275 | { 29276 | set_error(make_error( 29277 | parser_error::e_syntax, 29278 | current_token(), 29279 | "ERR151 - Invoking 'break' within a break call is not allowed", 29280 | exprtk_error_location)); 29281 | 29282 | return error_node(); 29283 | } 29284 | else if (0 == state_.parsing_loop_stmt_count) 29285 | { 29286 | set_error(make_error( 29287 | parser_error::e_syntax, 29288 | current_token(), 29289 | "ERR152 - Invalid use of 'break', allowed only in the scope of a loop", 29290 | exprtk_error_location)); 29291 | 29292 | return error_node(); 29293 | } 29294 | 29295 | scoped_bool_negator sbn(state_.parsing_break_stmt); 29296 | 29297 | if (!brkcnt_list_.empty()) 29298 | { 29299 | next_token(); 29300 | 29301 | brkcnt_list_.front() = true; 29302 | 29303 | expression_node_ptr return_expr = error_node(); 29304 | 29305 | if (token_is(token_t::e_lsqrbracket)) 29306 | { 29307 | if (0 == (return_expr = parse_expression())) 29308 | { 29309 | set_error(make_error( 29310 | parser_error::e_syntax, 29311 | current_token(), 29312 | "ERR153 - Failed to parse return expression for 'break' statement", 29313 | exprtk_error_location)); 29314 | 29315 | return error_node(); 29316 | } 29317 | else if (!token_is(token_t::e_rsqrbracket)) 29318 | { 29319 | set_error(make_error( 29320 | parser_error::e_syntax, 29321 | current_token(), 29322 | "ERR154 - Expected ']' at the completion of break's return expression", 29323 | exprtk_error_location)); 29324 | 29325 | free_node(node_allocator_, return_expr); 29326 | 29327 | return error_node(); 29328 | } 29329 | } 29330 | 29331 | state_.activate_side_effect("parse_break_statement()"); 29332 | 29333 | return node_allocator_.allocate<details::break_node<T> >(return_expr); 29334 | } 29335 | else 29336 | { 29337 | set_error(make_error( 29338 | parser_error::e_syntax, 29339 | current_token(), 29340 | "ERR155 - Invalid use of 'break', allowed only in the scope of a loop", 29341 | exprtk_error_location)); 29342 | } 29343 | 29344 | return error_node(); 29345 | } 29346 | 29347 | inline expression_node_ptr parse_continue_statement() 29348 | { 29349 | if (0 == state_.parsing_loop_stmt_count) 29350 | { 29351 | set_error(make_error( 29352 | parser_error::e_syntax, 29353 | current_token(), 29354 | "ERR156 - Invalid use of 'continue', allowed only in the scope of a loop", 29355 | exprtk_error_location)); 29356 | 29357 | return error_node(); 29358 | } 29359 | else 29360 | { 29361 | next_token(); 29362 | 29363 | brkcnt_list_.front() = true; 29364 | state_.activate_side_effect("parse_continue_statement()"); 29365 | 29366 | return node_allocator_.allocate<details::continue_node<T> >(); 29367 | } 29368 | } 29369 | #endif 29370 | 29371 | inline expression_node_ptr parse_define_vector_statement(const std::string& vec_name) 29372 | { 29373 | expression_node_ptr size_expression_node = error_node(); 29374 | 29375 | if (!token_is(token_t::e_lsqrbracket)) 29376 | { 29377 | set_error(make_error( 29378 | parser_error::e_syntax, 29379 | current_token(), 29380 | "ERR157 - Expected '[' as part of vector size definition", 29381 | exprtk_error_location)); 29382 | 29383 | return error_node(); 29384 | } 29385 | else if (0 == (size_expression_node = parse_expression())) 29386 | { 29387 | set_error(make_error( 29388 | parser_error::e_syntax, 29389 | current_token(), 29390 | "ERR158 - Failed to determine size of vector '" + vec_name + "'", 29391 | exprtk_error_location)); 29392 | 29393 | return error_node(); 29394 | } 29395 | else if (!is_constant_node(size_expression_node)) 29396 | { 29397 | const bool is_rebaseble_vector = 29398 | (size_expression_node->type() == details::expression_node<T>::e_vecsize) && 29399 | static_cast<details::vector_size_node<T>*>(size_expression_node)->vec_holder()->rebaseable(); 29400 | 29401 | free_node(node_allocator_, size_expression_node); 29402 | 29403 | const std::string error_msg = (is_rebaseble_vector) ? 29404 | std::string("Rebasable/Resizable vector cannot be used to define the size of vector") : 29405 | std::string("Expected a constant literal number as size of vector"); 29406 | set_error(make_error( 29407 | parser_error::e_syntax, 29408 | current_token(), 29409 | "ERR159 - " + error_msg + " '" + vec_name + "'", 29410 | exprtk_error_location)); 29411 | 29412 | return error_node(); 29413 | } 29414 | 29415 | const T vector_size = size_expression_node->value(); 29416 | 29417 | free_node(node_allocator_, size_expression_node); 29418 | 29419 | const std::size_t max_vector_size = settings_.max_local_vector_size(); 29420 | 29421 | if ( 29422 | (vector_size <= T(0)) || 29423 | std::not_equal_to<T>() 29424 | (T(0),vector_size - details::numeric::trunc(vector_size)) || 29425 | (static_cast<std::size_t>(vector_size) > max_vector_size) 29426 | ) 29427 | { 29428 | set_error(make_error( 29429 | parser_error::e_syntax, 29430 | current_token(), 29431 | "ERR160 - Invalid vector size. Must be an integer in the " 29432 | "range [0," + details::to_str(static_cast<std::size_t>(max_vector_size)) + "], size: " + 29433 | details::to_str(details::numeric::to_int32(vector_size)), 29434 | exprtk_error_location)); 29435 | 29436 | return error_node(); 29437 | } 29438 | 29439 | typename symbol_table_t::vector_holder_ptr vec_holder = typename symbol_table_t::vector_holder_ptr(0); 29440 | 29441 | const std::size_t vec_size = static_cast<std::size_t>(details::numeric::to_int32(vector_size)); 29442 | const std::size_t predicted_total_lclsymb_size = sizeof(T) * vec_size + sem_.total_local_symb_size_bytes(); 29443 | 29444 | if (predicted_total_lclsymb_size > settings().max_total_local_symbol_size_bytes()) 29445 | { 29446 | set_error(make_error( 29447 | parser_error::e_syntax, 29448 | current_token(), 29449 | "ERR161 - Adding vector '" + vec_name + "' of size " + details::to_str(vec_size) + " bytes " 29450 | "will exceed max total local symbol size of: " + details::to_str(settings().max_total_local_symbol_size_bytes()) + " bytes, " 29451 | "current total size: " + details::to_str(sem_.total_local_symb_size_bytes()) + " bytes", 29452 | exprtk_error_location)); 29453 | 29454 | return error_node(); 29455 | } 29456 | 29457 | scope_element& se = sem_.get_element(vec_name); 29458 | 29459 | if (se.name == vec_name) 29460 | { 29461 | if (se.active) 29462 | { 29463 | set_error(make_error( 29464 | parser_error::e_syntax, 29465 | current_token(), 29466 | "ERR162 - Illegal redefinition of local vector: '" + vec_name + "'", 29467 | exprtk_error_location)); 29468 | 29469 | return error_node(); 29470 | } 29471 | else if ( 29472 | (se.size == vec_size) && 29473 | (scope_element::e_vector == se.type) 29474 | ) 29475 | { 29476 | vec_holder = se.vec_node; 29477 | se.active = true; 29478 | se.depth = state_.scope_depth; 29479 | se.ref_count++; 29480 | } 29481 | } 29482 | 29483 | if (0 == vec_holder) 29484 | { 29485 | scope_element nse; 29486 | nse.name = vec_name; 29487 | nse.active = true; 29488 | nse.ref_count = 1; 29489 | nse.type = scope_element::e_vector; 29490 | nse.depth = state_.scope_depth; 29491 | nse.size = vec_size; 29492 | nse.data = new T[vec_size]; 29493 | nse.vec_node = new typename scope_element::vector_holder_t(reinterpret_cast<T*>(nse.data),nse.size); 29494 | 29495 | details::set_zero_value(reinterpret_cast<T*>(nse.data),vec_size); 29496 | 29497 | if (!sem_.add_element(nse)) 29498 | { 29499 | set_error(make_error( 29500 | parser_error::e_syntax, 29501 | current_token(), 29502 | "ERR163 - Failed to add new local vector '" + vec_name + "' to SEM", 29503 | exprtk_error_location)); 29504 | 29505 | sem_.free_element(nse); 29506 | 29507 | return error_node(); 29508 | } 29509 | 29510 | assert(sem_.total_local_symb_size_bytes() <= settings().max_total_local_symbol_size_bytes()); 29511 | 29512 | vec_holder = nse.vec_node; 29513 | 29514 | exprtk_debug(("parse_define_vector_statement() - INFO - Added new local vector: %s[%d]\n", 29515 | nse.name.c_str(), 29516 | static_cast<int>(nse.size))); 29517 | } 29518 | 29519 | state_.activate_side_effect("parse_define_vector_statement()"); 29520 | 29521 | lodge_symbol(vec_name, e_st_local_vector); 29522 | 29523 | std::vector<expression_node_ptr> vec_initilizer_list; 29524 | 29525 | scoped_vec_delete<expression_node_t> svd((*this), vec_initilizer_list); 29526 | 29527 | bool single_value_initialiser = false; 29528 | bool range_value_initialiser = false; 29529 | bool vec_to_vec_initialiser = false; 29530 | bool null_initialisation = false; 29531 | 29532 | if (!token_is(token_t::e_rsqrbracket)) 29533 | { 29534 | set_error(make_error( 29535 | parser_error::e_syntax, 29536 | current_token(), 29537 | "ERR164 - Expected ']' as part of vector size definition", 29538 | exprtk_error_location)); 29539 | 29540 | return error_node(); 29541 | } 29542 | else if (!token_is(token_t::e_eof, prsrhlpr_t::e_hold)) 29543 | { 29544 | if (!token_is(token_t::e_assign)) 29545 | { 29546 | set_error(make_error( 29547 | parser_error::e_syntax, 29548 | current_token(), 29549 | "ERR165 - Expected ':=' as part of vector definition", 29550 | exprtk_error_location)); 29551 | 29552 | return error_node(); 29553 | } 29554 | else if (token_is(token_t::e_lsqrbracket)) 29555 | { 29556 | expression_node_ptr initialiser_component = parse_expression(); 29557 | 29558 | if (0 == initialiser_component) 29559 | { 29560 | set_error(make_error( 29561 | parser_error::e_syntax, 29562 | current_token(), 29563 | "ERR166 - Failed to parse first component of vector initialiser for vector: " + vec_name, 29564 | exprtk_error_location)); 29565 | 29566 | return error_node(); 29567 | } 29568 | 29569 | vec_initilizer_list.push_back(initialiser_component); 29570 | 29571 | if (token_is(token_t::e_colon)) 29572 | { 29573 | initialiser_component = parse_expression(); 29574 | 29575 | if (0 == initialiser_component) 29576 | { 29577 | set_error(make_error( 29578 | parser_error::e_syntax, 29579 | current_token(), 29580 | "ERR167 - Failed to parse second component of vector initialiser for vector: " + vec_name, 29581 | exprtk_error_location)); 29582 | 29583 | return error_node(); 29584 | } 29585 | 29586 | vec_initilizer_list.push_back(initialiser_component); 29587 | } 29588 | 29589 | if (!token_is(token_t::e_rsqrbracket)) 29590 | { 29591 | set_error(make_error( 29592 | parser_error::e_syntax, 29593 | current_token(), 29594 | "ERR168 - Expected ']' to close single value vector initialiser", 29595 | exprtk_error_location)); 29596 | 29597 | return error_node(); 29598 | } 29599 | 29600 | switch (vec_initilizer_list.size()) 29601 | { 29602 | case 1 : single_value_initialiser = true; break; 29603 | case 2 : range_value_initialiser = true; break; 29604 | } 29605 | } 29606 | else if (!token_is(token_t::e_lcrlbracket)) 29607 | { 29608 | expression_node_ptr initialiser = error_node(); 29609 | 29610 | // Is this a vector to vector assignment and initialisation? 29611 | if (token_t::e_symbol == current_token().type) 29612 | { 29613 | // Is it a locally defined vector? 29614 | const scope_element& lcl_se = sem_.get_active_element(current_token().value); 29615 | 29616 | if (scope_element::e_vector == lcl_se.type) 29617 | { 29618 | if (0 != (initialiser = parse_expression())) 29619 | vec_initilizer_list.push_back(initialiser); 29620 | else 29621 | return error_node(); 29622 | } 29623 | // Are we dealing with a user defined vector? 29624 | else if (symtab_store_.is_vector(current_token().value)) 29625 | { 29626 | lodge_symbol(current_token().value, e_st_vector); 29627 | 29628 | if (0 != (initialiser = parse_expression())) 29629 | vec_initilizer_list.push_back(initialiser); 29630 | else 29631 | return error_node(); 29632 | } 29633 | // Are we dealing with a null initialisation vector definition? 29634 | else if (token_is(token_t::e_symbol,"null")) 29635 | null_initialisation = true; 29636 | } 29637 | 29638 | if (!null_initialisation) 29639 | { 29640 | if (0 == initialiser) 29641 | { 29642 | set_error(make_error( 29643 | parser_error::e_syntax, 29644 | current_token(), 29645 | "ERR169 - Expected '{' as part of vector initialiser list", 29646 | exprtk_error_location)); 29647 | 29648 | return error_node(); 29649 | } 29650 | else 29651 | vec_to_vec_initialiser = true; 29652 | } 29653 | } 29654 | else if (!token_is(token_t::e_rcrlbracket)) 29655 | { 29656 | for ( ; ; ) 29657 | { 29658 | expression_node_ptr initialiser = parse_expression(); 29659 | 29660 | if (0 == initialiser) 29661 | { 29662 | set_error(make_error( 29663 | parser_error::e_syntax, 29664 | current_token(), 29665 | "ERR170 - Expected '{' as part of vector initialiser list", 29666 | exprtk_error_location)); 29667 | 29668 | return error_node(); 29669 | } 29670 | else 29671 | vec_initilizer_list.push_back(initialiser); 29672 | 29673 | if (token_is(token_t::e_rcrlbracket)) 29674 | break; 29675 | 29676 | const bool is_next_close = peek_token_is(token_t::e_rcrlbracket); 29677 | 29678 | if (!token_is(token_t::e_comma) && is_next_close) 29679 | { 29680 | set_error(make_error( 29681 | parser_error::e_syntax, 29682 | current_token(), 29683 | "ERR171 - Expected ',' between vector initialisers", 29684 | exprtk_error_location)); 29685 | 29686 | return error_node(); 29687 | } 29688 | 29689 | if (token_is(token_t::e_rcrlbracket)) 29690 | break; 29691 | } 29692 | } 29693 | 29694 | if ( 29695 | !token_is(token_t::e_rbracket , prsrhlpr_t::e_hold) && 29696 | !token_is(token_t::e_rcrlbracket, prsrhlpr_t::e_hold) && 29697 | !token_is(token_t::e_rsqrbracket, prsrhlpr_t::e_hold) 29698 | ) 29699 | { 29700 | if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold)) 29701 | { 29702 | set_error(make_error( 29703 | parser_error::e_syntax, 29704 | current_token(), 29705 | "ERR172 - Expected ';' at end of vector definition", 29706 | exprtk_error_location)); 29707 | 29708 | return error_node(); 29709 | } 29710 | } 29711 | 29712 | if ( 29713 | !single_value_initialiser && 29714 | !range_value_initialiser && 29715 | (T(vec_initilizer_list.size()) > vector_size) 29716 | ) 29717 | { 29718 | set_error(make_error( 29719 | parser_error::e_syntax, 29720 | current_token(), 29721 | "ERR173 - Initialiser list larger than the number of elements in the vector: '" + vec_name + "'", 29722 | exprtk_error_location)); 29723 | 29724 | return error_node(); 29725 | } 29726 | } 29727 | 29728 | expression_node_ptr result = error_node(); 29729 | 29730 | if ( 29731 | (vec_initilizer_list.size() == 1) && 29732 | single_value_initialiser 29733 | ) 29734 | { 29735 | if (details::is_constant_node(vec_initilizer_list[0])) 29736 | { 29737 | // vector_init_zero_value_node var v[10] := [0] 29738 | if (T(0) == vec_initilizer_list[0]->value()) 29739 | { 29740 | result = node_allocator_ 29741 | .allocate<details::vector_init_zero_value_node<T> >( 29742 | (*vec_holder)[0], 29743 | vec_size, 29744 | vec_initilizer_list); 29745 | } 29746 | else 29747 | { 29748 | // vector_init_single_constvalue_node var v[10] := [123] 29749 | result = node_allocator_ 29750 | .allocate<details::vector_init_single_constvalue_node<T> >( 29751 | (*vec_holder)[0], 29752 | vec_size, 29753 | vec_initilizer_list); 29754 | } 29755 | } 29756 | else 29757 | { 29758 | // vector_init_single_value_node var v[10] := [123 + (x / y)] 29759 | result = node_allocator_ 29760 | .allocate<details::vector_init_single_value_node<T> >( 29761 | (*vec_holder)[0], 29762 | vec_size, 29763 | vec_initilizer_list); 29764 | } 29765 | } 29766 | else if ( 29767 | (vec_initilizer_list.size() == 2) && 29768 | range_value_initialiser 29769 | ) 29770 | { 29771 | bool base_const = details::is_constant_node(vec_initilizer_list[0]); 29772 | bool inc_const = details::is_constant_node(vec_initilizer_list[1]); 29773 | 29774 | if (base_const && inc_const) 29775 | { 29776 | // vector_init_single_value_node var v[10] := [1 : 3.5] 29777 | result = node_allocator_ 29778 | .allocate<details::vector_init_iota_constconst_node<T> >( 29779 | (*vec_holder)[0], 29780 | vec_size, 29781 | vec_initilizer_list); 29782 | } 29783 | else if (base_const && !inc_const) 29784 | { 29785 | // vector_init_single_value_node var v[10] := [1 : x + y] 29786 | result = node_allocator_ 29787 | .allocate<details::vector_init_iota_constnconst_node<T> >( 29788 | (*vec_holder)[0], 29789 | vec_size, 29790 | vec_initilizer_list); 29791 | } 29792 | else if (!base_const && inc_const) 29793 | { 29794 | // vector_init_single_value_node var v[10] := [x + y : 3] 29795 | result = node_allocator_ 29796 | .allocate<details::vector_init_iota_nconstconst_node<T> >( 29797 | (*vec_holder)[0], 29798 | vec_size, 29799 | vec_initilizer_list); 29800 | } 29801 | else if (!base_const && !inc_const) 29802 | { 29803 | // vector_init_single_value_node var v[10] := [x + y : z / w] 29804 | result = node_allocator_ 29805 | .allocate<details::vector_init_iota_nconstnconst_node<T> >( 29806 | (*vec_holder)[0], 29807 | vec_size, 29808 | vec_initilizer_list); 29809 | } 29810 | } 29811 | else if (null_initialisation) 29812 | result = expression_generator_(T(0.0)); 29813 | else if (vec_to_vec_initialiser) 29814 | { 29815 | expression_node_ptr vec_node = node_allocator_.allocate<vector_node_t>(vec_holder); 29816 | 29817 | result = expression_generator_( 29818 | details::e_assign, 29819 | vec_node, 29820 | vec_initilizer_list[0]); 29821 | } 29822 | else 29823 | { 29824 | result = node_allocator_ 29825 | .allocate<details::vector_initialisation_node<T> >( 29826 | (*vec_holder)[0], 29827 | vec_size, 29828 | vec_initilizer_list, 29829 | single_value_initialiser); 29830 | } 29831 | 29832 | svd.delete_ptr = false; 29833 | 29834 | if (result && result->valid()) 29835 | { 29836 | return result; 29837 | } 29838 | 29839 | details::free_node(node_allocator_, result); 29840 | 29841 | set_error(make_error( 29842 | parser_error::e_synthesis, 29843 | current_token(), 29844 | "ERR174 - Failed to generate initialisation node for vector: " + vec_name, 29845 | exprtk_error_location)); 29846 | 29847 | return error_node(); 29848 | } 29849 | 29850 | #ifndef exprtk_disable_string_capabilities 29851 | inline expression_node_ptr parse_define_string_statement(const std::string& str_name, expression_node_ptr initialisation_expression) 29852 | { 29853 | stringvar_node_t* str_node = reinterpret_cast<stringvar_node_t*>(0); 29854 | 29855 | scope_element& se = sem_.get_element(str_name); 29856 | 29857 | if (se.name == str_name) 29858 | { 29859 | if (se.active) 29860 | { 29861 | set_error(make_error( 29862 | parser_error::e_syntax, 29863 | current_token(), 29864 | "ERR175 - Illegal redefinition of local variable: '" + str_name + "'", 29865 | exprtk_error_location)); 29866 | 29867 | free_node(node_allocator_, initialisation_expression); 29868 | 29869 | return error_node(); 29870 | } 29871 | else if (scope_element::e_string == se.type) 29872 | { 29873 | str_node = se.str_node; 29874 | se.active = true; 29875 | se.depth = state_.scope_depth; 29876 | se.ref_count++; 29877 | } 29878 | } 29879 | 29880 | if (0 == str_node) 29881 | { 29882 | scope_element nse; 29883 | nse.name = str_name; 29884 | nse.active = true; 29885 | nse.ref_count = 1; 29886 | nse.type = scope_element::e_string; 29887 | nse.depth = state_.scope_depth; 29888 | nse.data = new std::string; 29889 | nse.str_node = new stringvar_node_t(*reinterpret_cast<std::string*>(nse.data)); 29890 | 29891 | if (!sem_.add_element(nse)) 29892 | { 29893 | set_error(make_error( 29894 | parser_error::e_syntax, 29895 | current_token(), 29896 | "ERR176 - Failed to add new local string variable '" + str_name + "' to SEM", 29897 | exprtk_error_location)); 29898 | 29899 | free_node(node_allocator_, initialisation_expression); 29900 | 29901 | sem_.free_element(nse); 29902 | 29903 | return error_node(); 29904 | } 29905 | 29906 | assert(sem_.total_local_symb_size_bytes() <= settings().max_total_local_symbol_size_bytes()); 29907 | 29908 | str_node = nse.str_node; 29909 | 29910 | exprtk_debug(("parse_define_string_statement() - INFO - Added new local string variable: %s\n", nse.name.c_str())); 29911 | } 29912 | 29913 | lodge_symbol(str_name, e_st_local_string); 29914 | 29915 | state_.activate_side_effect("parse_define_string_statement()"); 29916 | 29917 | expression_node_ptr branch[2] = {0}; 29918 | 29919 | branch[0] = str_node; 29920 | branch[1] = initialisation_expression; 29921 | 29922 | return expression_generator_(details::e_assign,branch); 29923 | } 29924 | #else 29925 | inline expression_node_ptr parse_define_string_statement(const std::string&, expression_node_ptr) 29926 | { 29927 | return error_node(); 29928 | } 29929 | #endif 29930 | 29931 | inline bool local_variable_is_shadowed(const std::string& symbol) 29932 | { 29933 | const scope_element& se = sem_.get_element(symbol); 29934 | return (se.name == symbol) && se.active; 29935 | } 29936 | 29937 | inline expression_node_ptr parse_define_var_statement() 29938 | { 29939 | if (settings_.vardef_disabled()) 29940 | { 29941 | set_error(make_error( 29942 | parser_error::e_syntax, 29943 | current_token(), 29944 | "ERR177 - Illegal variable definition", 29945 | exprtk_error_location)); 29946 | 29947 | return error_node(); 29948 | } 29949 | else if (!details::imatch(current_token().value,"var")) 29950 | { 29951 | return error_node(); 29952 | } 29953 | else 29954 | next_token(); 29955 | 29956 | const std::string var_name = current_token().value; 29957 | 29958 | expression_node_ptr initialisation_expression = error_node(); 29959 | 29960 | if (!token_is(token_t::e_symbol)) 29961 | { 29962 | set_error(make_error( 29963 | parser_error::e_syntax, 29964 | current_token(), 29965 | "ERR178 - Expected a symbol for variable definition", 29966 | exprtk_error_location)); 29967 | 29968 | return error_node(); 29969 | } 29970 | else if (details::is_reserved_symbol(var_name)) 29971 | { 29972 | set_error(make_error( 29973 | parser_error::e_syntax, 29974 | current_token(), 29975 | "ERR179 - Illegal redefinition of reserved keyword: '" + var_name + "'", 29976 | exprtk_error_location)); 29977 | 29978 | return error_node(); 29979 | } 29980 | else if (symtab_store_.symbol_exists(var_name)) 29981 | { 29982 | set_error(make_error( 29983 | parser_error::e_syntax, 29984 | current_token(), 29985 | "ERR180 - Illegal redefinition of variable '" + var_name + "'", 29986 | exprtk_error_location)); 29987 | 29988 | return error_node(); 29989 | } 29990 | else if (local_variable_is_shadowed(var_name)) 29991 | { 29992 | set_error(make_error( 29993 | parser_error::e_syntax, 29994 | current_token(), 29995 | "ERR181 - Illegal redefinition of local variable: '" + var_name + "'", 29996 | exprtk_error_location)); 29997 | 29998 | return error_node(); 29999 | } 30000 | else if (token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold)) 30001 | { 30002 | return parse_define_vector_statement(var_name); 30003 | } 30004 | else if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) 30005 | { 30006 | return parse_uninitialised_var_statement(var_name); 30007 | } 30008 | else if (token_is(token_t::e_assign)) 30009 | { 30010 | if (0 == (initialisation_expression = parse_expression())) 30011 | { 30012 | set_error(make_error( 30013 | parser_error::e_syntax, 30014 | current_token(), 30015 | "ERR182 - Failed to parse initialisation expression for variable '" + var_name + "'", 30016 | exprtk_error_location)); 30017 | 30018 | return error_node(); 30019 | } 30020 | } 30021 | 30022 | if ( 30023 | !token_is(token_t::e_rbracket , prsrhlpr_t::e_hold) && 30024 | !token_is(token_t::e_rcrlbracket, prsrhlpr_t::e_hold) && 30025 | !token_is(token_t::e_rsqrbracket, prsrhlpr_t::e_hold) 30026 | ) 30027 | { 30028 | if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold)) 30029 | { 30030 | set_error(make_error( 30031 | parser_error::e_syntax, 30032 | current_token(), 30033 | "ERR183 - Expected ';' after variable '" + var_name + "' definition", 30034 | exprtk_error_location)); 30035 | 30036 | free_node(node_allocator_, initialisation_expression); 30037 | 30038 | return error_node(); 30039 | } 30040 | } 30041 | 30042 | if ( 30043 | (0 != initialisation_expression) && 30044 | details::is_generally_string_node(initialisation_expression) 30045 | ) 30046 | { 30047 | return parse_define_string_statement(var_name,initialisation_expression); 30048 | } 30049 | 30050 | expression_node_ptr var_node = reinterpret_cast<expression_node_ptr>(0); 30051 | 30052 | scope_element& se = sem_.get_element(var_name); 30053 | 30054 | if (se.name == var_name) 30055 | { 30056 | if (se.active) 30057 | { 30058 | set_error(make_error( 30059 | parser_error::e_syntax, 30060 | current_token(), 30061 | "ERR184 - Illegal redefinition of local variable: '" + var_name + "'", 30062 | exprtk_error_location)); 30063 | 30064 | free_node(node_allocator_, initialisation_expression); 30065 | 30066 | return error_node(); 30067 | } 30068 | else if (scope_element::e_variable == se.type) 30069 | { 30070 | var_node = se.var_node; 30071 | se.active = true; 30072 | se.depth = state_.scope_depth; 30073 | se.ref_count++; 30074 | } 30075 | } 30076 | 30077 | if (0 == var_node) 30078 | { 30079 | const std::size_t predicted_total_lclsymb_size = sizeof(T) + sem_.total_local_symb_size_bytes(); 30080 | 30081 | if (predicted_total_lclsymb_size > settings().max_total_local_symbol_size_bytes()) 30082 | { 30083 | set_error(make_error( 30084 | parser_error::e_syntax, 30085 | current_token(), 30086 | "ERR185 - Adding variable '" + var_name + "' " 30087 | "will exceed max total local symbol size of: " + details::to_str(settings().max_total_local_symbol_size_bytes()) + " bytes, " 30088 | "current total size: " + details::to_str(sem_.total_local_symb_size_bytes()) + " bytes", 30089 | exprtk_error_location)); 30090 | 30091 | free_node(node_allocator_, initialisation_expression); 30092 | 30093 | return error_node(); 30094 | } 30095 | 30096 | scope_element nse; 30097 | nse.name = var_name; 30098 | nse.active = true; 30099 | nse.ref_count = 1; 30100 | nse.type = scope_element::e_variable; 30101 | nse.depth = state_.scope_depth; 30102 | nse.data = new T(T(0)); 30103 | nse.var_node = node_allocator_.allocate<variable_node_t>(*reinterpret_cast<T*>(nse.data)); 30104 | 30105 | if (!sem_.add_element(nse)) 30106 | { 30107 | set_error(make_error( 30108 | parser_error::e_syntax, 30109 | current_token(), 30110 | "ERR186 - Failed to add new local variable '" + var_name + "' to SEM", 30111 | exprtk_error_location)); 30112 | 30113 | free_node(node_allocator_, initialisation_expression); 30114 | 30115 | sem_.free_element(nse); 30116 | 30117 | return error_node(); 30118 | } 30119 | 30120 | assert(sem_.total_local_symb_size_bytes() <= settings().max_total_local_symbol_size_bytes()); 30121 | 30122 | var_node = nse.var_node; 30123 | 30124 | exprtk_debug(("parse_define_var_statement() - INFO - Added new local variable: %s\n", nse.name.c_str())); 30125 | } 30126 | 30127 | state_.activate_side_effect("parse_define_var_statement()"); 30128 | 30129 | lodge_symbol(var_name, e_st_local_variable); 30130 | 30131 | expression_node_ptr branch[2] = {0}; 30132 | 30133 | branch[0] = var_node; 30134 | branch[1] = initialisation_expression ? initialisation_expression : expression_generator_(T(0)); 30135 | 30136 | return expression_generator_(details::e_assign,branch); 30137 | } 30138 | 30139 | inline expression_node_ptr parse_define_constvar_statement() 30140 | { 30141 | if (settings_.vardef_disabled()) 30142 | { 30143 | set_error(make_error( 30144 | parser_error::e_syntax, 30145 | current_token(), 30146 | "ERR187 - Illegal const variable definition", 30147 | exprtk_error_location)); 30148 | 30149 | return error_node(); 30150 | } 30151 | else if (!token_is("const")) 30152 | { 30153 | set_error(make_error( 30154 | parser_error::e_syntax, 30155 | current_token(), 30156 | "ERR188 - Expected 'const' keyword for const-variable definition", 30157 | exprtk_error_location)); 30158 | 30159 | return error_node(); 30160 | } 30161 | else if (!token_is("var")) 30162 | { 30163 | set_error(make_error( 30164 | parser_error::e_syntax, 30165 | current_token(), 30166 | "ERR189 - Expected 'var' keyword for const-variable definition", 30167 | exprtk_error_location)); 30168 | 30169 | return error_node(); 30170 | } 30171 | 30172 | const std::string var_name = current_token().value; 30173 | 30174 | expression_node_ptr initialisation_expression = error_node(); 30175 | 30176 | if (!token_is(token_t::e_symbol)) 30177 | { 30178 | set_error(make_error( 30179 | parser_error::e_syntax, 30180 | current_token(), 30181 | "ERR190 - Expected a symbol for const-variable definition", 30182 | exprtk_error_location)); 30183 | 30184 | return error_node(); 30185 | } 30186 | else if (details::is_reserved_symbol(var_name)) 30187 | { 30188 | set_error(make_error( 30189 | parser_error::e_syntax, 30190 | current_token(), 30191 | "ERR191 - Illegal redefinition of reserved keyword: '" + var_name + "'", 30192 | exprtk_error_location)); 30193 | 30194 | return error_node(); 30195 | } 30196 | else if (symtab_store_.symbol_exists(var_name)) 30197 | { 30198 | set_error(make_error( 30199 | parser_error::e_syntax, 30200 | current_token(), 30201 | "ERR192 - Illegal redefinition of variable '" + var_name + "'", 30202 | exprtk_error_location)); 30203 | 30204 | return error_node(); 30205 | } 30206 | else if (local_variable_is_shadowed(var_name)) 30207 | { 30208 | set_error(make_error( 30209 | parser_error::e_syntax, 30210 | current_token(), 30211 | "ERR193 - Illegal redefinition of local variable: '" + var_name + "'", 30212 | exprtk_error_location)); 30213 | 30214 | return error_node(); 30215 | } 30216 | else if (!token_is(token_t::e_assign)) 30217 | { 30218 | set_error(make_error( 30219 | parser_error::e_syntax, 30220 | current_token(), 30221 | "ERR194 - Expected assignment operator after const-variable: '" + var_name + "' definition", 30222 | exprtk_error_location)); 30223 | 30224 | return error_node(); 30225 | } 30226 | else if (0 == (initialisation_expression = parse_expression())) 30227 | { 30228 | set_error(make_error( 30229 | parser_error::e_syntax, 30230 | current_token(), 30231 | "ERR195 - Failed to parse initialisation expression for const-variable: '" + var_name + "'", 30232 | exprtk_error_location)); 30233 | 30234 | return error_node(); 30235 | } 30236 | 30237 | if (!details::is_literal_node(initialisation_expression)) 30238 | { 30239 | set_error(make_error( 30240 | parser_error::e_syntax, 30241 | current_token(), 30242 | "ERR196 - initialisation expression for const-variable: '" + var_name + "' must be a constant/literal", 30243 | exprtk_error_location)); 30244 | 30245 | free_node(node_allocator_, initialisation_expression); 30246 | 30247 | return error_node(); 30248 | } 30249 | 30250 | assert(initialisation_expression); 30251 | 30252 | const T init_value = initialisation_expression->value(); 30253 | 30254 | free_node(node_allocator_, initialisation_expression); 30255 | 30256 | expression_node_ptr var_node = reinterpret_cast<expression_node_ptr>(0); 30257 | 30258 | scope_element& se = sem_.get_element(var_name); 30259 | 30260 | if (se.name == var_name) 30261 | { 30262 | if (se.active) 30263 | { 30264 | set_error(make_error( 30265 | parser_error::e_syntax, 30266 | current_token(), 30267 | "ERR197 - Illegal redefinition of local variable: '" + var_name + "'", 30268 | exprtk_error_location)); 30269 | 30270 | return error_node(); 30271 | } 30272 | else if (scope_element::e_literal == se.type) 30273 | { 30274 | var_node = se.var_node; 30275 | se.active = true; 30276 | se.depth = state_.scope_depth; 30277 | se.ref_count++; 30278 | } 30279 | } 30280 | 30281 | if (0 == var_node) 30282 | { 30283 | const std::size_t predicted_total_lclsymb_size = sizeof(T) + sem_.total_local_symb_size_bytes(); 30284 | 30285 | if (predicted_total_lclsymb_size > settings().max_total_local_symbol_size_bytes()) 30286 | { 30287 | set_error(make_error( 30288 | parser_error::e_syntax, 30289 | current_token(), 30290 | "ERR198 - Adding variable '" + var_name + "' " 30291 | "will exceed max total local symbol size of: " + details::to_str(settings().max_total_local_symbol_size_bytes()) + " bytes, " 30292 | "current total size: " + details::to_str(sem_.total_local_symb_size_bytes()) + " bytes", 30293 | exprtk_error_location)); 30294 | 30295 | return error_node(); 30296 | } 30297 | 30298 | scope_element nse; 30299 | nse.name = var_name; 30300 | nse.active = true; 30301 | nse.ref_count = 1; 30302 | nse.type = scope_element::e_literal; 30303 | nse.depth = state_.scope_depth; 30304 | nse.data = 0; 30305 | nse.var_node = node_allocator_.allocate<literal_node_t>(init_value); 30306 | 30307 | if (!sem_.add_element(nse)) 30308 | { 30309 | set_error(make_error( 30310 | parser_error::e_syntax, 30311 | current_token(), 30312 | "ERR199 - Failed to add new local const-variable '" + var_name + "' to SEM", 30313 | exprtk_error_location)); 30314 | 30315 | sem_.free_element(nse); 30316 | 30317 | return error_node(); 30318 | } 30319 | 30320 | assert(sem_.total_local_symb_size_bytes() <= settings().max_total_local_symbol_size_bytes()); 30321 | 30322 | var_node = nse.var_node; 30323 | 30324 | exprtk_debug(("parse_define_constvar_statement() - INFO - Added new local const-variable: %s\n", nse.name.c_str())); 30325 | } 30326 | 30327 | state_.activate_side_effect("parse_define_constvar_statement()"); 30328 | 30329 | lodge_symbol(var_name, e_st_local_variable); 30330 | 30331 | return expression_generator_(var_node->value()); 30332 | } 30333 | 30334 | inline expression_node_ptr parse_uninitialised_var_statement(const std::string& var_name) 30335 | { 30336 | if ( 30337 | !token_is(token_t::e_lcrlbracket) || 30338 | !token_is(token_t::e_rcrlbracket) 30339 | ) 30340 | { 30341 | set_error(make_error( 30342 | parser_error::e_syntax, 30343 | current_token(), 30344 | "ERR200 - Expected a '{}' for uninitialised var definition", 30345 | exprtk_error_location)); 30346 | 30347 | return error_node(); 30348 | } 30349 | else if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold)) 30350 | { 30351 | set_error(make_error( 30352 | parser_error::e_syntax, 30353 | current_token(), 30354 | "ERR201 - Expected ';' after uninitialised variable definition", 30355 | exprtk_error_location)); 30356 | 30357 | return error_node(); 30358 | } 30359 | 30360 | expression_node_ptr var_node = reinterpret_cast<expression_node_ptr>(0); 30361 | 30362 | scope_element& se = sem_.get_element(var_name); 30363 | 30364 | if (se.name == var_name) 30365 | { 30366 | if (se.active) 30367 | { 30368 | set_error(make_error( 30369 | parser_error::e_syntax, 30370 | current_token(), 30371 | "ERR202 - Illegal redefinition of local variable: '" + var_name + "'", 30372 | exprtk_error_location)); 30373 | 30374 | return error_node(); 30375 | } 30376 | else if (scope_element::e_variable == se.type) 30377 | { 30378 | var_node = se.var_node; 30379 | se.active = true; 30380 | se.ref_count++; 30381 | } 30382 | } 30383 | 30384 | if (0 == var_node) 30385 | { 30386 | const std::size_t predicted_total_lclsymb_size = sizeof(T) + sem_.total_local_symb_size_bytes(); 30387 | 30388 | if (predicted_total_lclsymb_size > settings().max_total_local_symbol_size_bytes()) 30389 | { 30390 | set_error(make_error( 30391 | parser_error::e_syntax, 30392 | current_token(), 30393 | "ERR203 - Adding variable '" + var_name + "' " 30394 | "will exceed max total local symbol size of: " + details::to_str(settings().max_total_local_symbol_size_bytes()) + " bytes, " 30395 | "current total size: " + details::to_str(sem_.total_local_symb_size_bytes()) + " bytes", 30396 | exprtk_error_location)); 30397 | 30398 | return error_node(); 30399 | } 30400 | 30401 | scope_element nse; 30402 | nse.name = var_name; 30403 | nse.active = true; 30404 | nse.ref_count = 1; 30405 | nse.type = scope_element::e_variable; 30406 | nse.depth = state_.scope_depth; 30407 | nse.ip_index = sem_.next_ip_index(); 30408 | nse.data = new T(T(0)); 30409 | nse.var_node = node_allocator_.allocate<variable_node_t>(*reinterpret_cast<T*>(nse.data)); 30410 | 30411 | if (!sem_.add_element(nse)) 30412 | { 30413 | set_error(make_error( 30414 | parser_error::e_syntax, 30415 | current_token(), 30416 | "ERR204 - Failed to add new local variable '" + var_name + "' to SEM", 30417 | exprtk_error_location)); 30418 | 30419 | sem_.free_element(nse); 30420 | 30421 | return error_node(); 30422 | } 30423 | 30424 | assert(sem_.total_local_symb_size_bytes() <= settings().max_total_local_symbol_size_bytes()); 30425 | 30426 | exprtk_debug(("parse_uninitialised_var_statement() - INFO - Added new local variable: %s\n", 30427 | nse.name.c_str())); 30428 | } 30429 | 30430 | lodge_symbol(var_name, e_st_local_variable); 30431 | 30432 | state_.activate_side_effect("parse_uninitialised_var_statement()"); 30433 | 30434 | return expression_generator_(T(0)); 30435 | } 30436 | 30437 | inline expression_node_ptr parse_swap_statement() 30438 | { 30439 | if (!details::imatch(current_token().value,"swap")) 30440 | { 30441 | return error_node(); 30442 | } 30443 | else 30444 | next_token(); 30445 | 30446 | if (!token_is(token_t::e_lbracket)) 30447 | { 30448 | set_error(make_error( 30449 | parser_error::e_syntax, 30450 | current_token(), 30451 | "ERR205 - Expected '(' at start of swap statement", 30452 | exprtk_error_location)); 30453 | 30454 | return error_node(); 30455 | } 30456 | 30457 | expression_node_ptr variable0 = error_node(); 30458 | expression_node_ptr variable1 = error_node(); 30459 | 30460 | bool variable0_generated = false; 30461 | bool variable1_generated = false; 30462 | 30463 | const std::string var0_name = current_token().value; 30464 | 30465 | if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold)) 30466 | { 30467 | set_error(make_error( 30468 | parser_error::e_syntax, 30469 | current_token(), 30470 | "ERR206 - Expected a symbol for variable or vector element definition", 30471 | exprtk_error_location)); 30472 | 30473 | return error_node(); 30474 | } 30475 | else if (peek_token_is(token_t::e_lsqrbracket)) 30476 | { 30477 | if (0 == (variable0 = parse_vector())) 30478 | { 30479 | set_error(make_error( 30480 | parser_error::e_syntax, 30481 | current_token(), 30482 | "ERR207 - First parameter to swap is an invalid vector element: '" + var0_name + "'", 30483 | exprtk_error_location)); 30484 | 30485 | return error_node(); 30486 | } 30487 | 30488 | variable0_generated = true; 30489 | } 30490 | else 30491 | { 30492 | if (symtab_store_.is_variable(var0_name)) 30493 | { 30494 | variable0 = symtab_store_.get_variable(var0_name); 30495 | } 30496 | 30497 | const scope_element& se = sem_.get_element(var0_name); 30498 | 30499 | if ( 30500 | (se.active) && 30501 | (se.name == var0_name) && 30502 | (scope_element::e_variable == se.type) 30503 | ) 30504 | { 30505 | variable0 = se.var_node; 30506 | } 30507 | 30508 | lodge_symbol(var0_name, e_st_variable); 30509 | 30510 | if (0 == variable0) 30511 | { 30512 | set_error(make_error( 30513 | parser_error::e_syntax, 30514 | current_token(), 30515 | "ERR208 - First parameter to swap is an invalid variable: '" + var0_name + "'", 30516 | exprtk_error_location)); 30517 | 30518 | return error_node(); 30519 | } 30520 | else 30521 | next_token(); 30522 | } 30523 | 30524 | if (!token_is(token_t::e_comma)) 30525 | { 30526 | set_error(make_error( 30527 | parser_error::e_syntax, 30528 | current_token(), 30529 | "ERR209 - Expected ',' between parameters to swap", 30530 | exprtk_error_location)); 30531 | 30532 | if (variable0_generated) 30533 | { 30534 | free_node(node_allocator_, variable0); 30535 | } 30536 | 30537 | return error_node(); 30538 | } 30539 | 30540 | const std::string var1_name = current_token().value; 30541 | 30542 | if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold)) 30543 | { 30544 | set_error(make_error( 30545 | parser_error::e_syntax, 30546 | current_token(), 30547 | "ERR210 - Expected a symbol for variable or vector element definition", 30548 | exprtk_error_location)); 30549 | 30550 | if (variable0_generated) 30551 | { 30552 | free_node(node_allocator_, variable0); 30553 | } 30554 | 30555 | return error_node(); 30556 | } 30557 | else if (peek_token_is(token_t::e_lsqrbracket)) 30558 | { 30559 | if (0 == (variable1 = parse_vector())) 30560 | { 30561 | set_error(make_error( 30562 | parser_error::e_syntax, 30563 | current_token(), 30564 | "ERR211 - Second parameter to swap is an invalid vector element: '" + var1_name + "'", 30565 | exprtk_error_location)); 30566 | 30567 | if (variable0_generated) 30568 | { 30569 | free_node(node_allocator_, variable0); 30570 | } 30571 | 30572 | return error_node(); 30573 | } 30574 | 30575 | variable1_generated = true; 30576 | } 30577 | else 30578 | { 30579 | if (symtab_store_.is_variable(var1_name)) 30580 | { 30581 | variable1 = symtab_store_.get_variable(var1_name); 30582 | } 30583 | 30584 | const scope_element& se = sem_.get_element(var1_name); 30585 | 30586 | if ( 30587 | (se.active) && 30588 | (se.name == var1_name) && 30589 | (scope_element::e_variable == se.type) 30590 | ) 30591 | { 30592 | variable1 = se.var_node; 30593 | } 30594 | 30595 | lodge_symbol(var1_name, e_st_variable); 30596 | 30597 | if (0 == variable1) 30598 | { 30599 | set_error(make_error( 30600 | parser_error::e_syntax, 30601 | current_token(), 30602 | "ERR212 - Second parameter to swap is an invalid variable: '" + var1_name + "'", 30603 | exprtk_error_location)); 30604 | 30605 | if (variable0_generated) 30606 | { 30607 | free_node(node_allocator_, variable0); 30608 | } 30609 | 30610 | return error_node(); 30611 | } 30612 | else 30613 | next_token(); 30614 | } 30615 | 30616 | if (!token_is(token_t::e_rbracket)) 30617 | { 30618 | set_error(make_error( 30619 | parser_error::e_syntax, 30620 | current_token(), 30621 | "ERR213 - Expected ')' at end of swap statement", 30622 | exprtk_error_location)); 30623 | 30624 | if (variable0_generated) 30625 | { 30626 | free_node(node_allocator_, variable0); 30627 | } 30628 | 30629 | if (variable1_generated) 30630 | { 30631 | free_node(node_allocator_, variable1); 30632 | } 30633 | 30634 | return error_node(); 30635 | } 30636 | 30637 | typedef details::variable_node<T>* variable_node_ptr; 30638 | 30639 | variable_node_ptr v0 = variable_node_ptr(0); 30640 | variable_node_ptr v1 = variable_node_ptr(0); 30641 | 30642 | expression_node_ptr result = error_node(); 30643 | 30644 | if ( 30645 | (0 != (v0 = dynamic_cast<variable_node_ptr>(variable0))) && 30646 | (0 != (v1 = dynamic_cast<variable_node_ptr>(variable1))) 30647 | ) 30648 | { 30649 | result = node_allocator_.allocate<details::swap_node<T> >(v0, v1); 30650 | 30651 | if (variable0_generated) 30652 | { 30653 | free_node(node_allocator_, variable0); 30654 | } 30655 | 30656 | if (variable1_generated) 30657 | { 30658 | free_node(node_allocator_, variable1); 30659 | } 30660 | } 30661 | else 30662 | result = node_allocator_.allocate<details::swap_generic_node<T> > 30663 | (variable0, variable1); 30664 | 30665 | state_.activate_side_effect("parse_swap_statement()"); 30666 | 30667 | return result; 30668 | } 30669 | 30670 | #ifndef exprtk_disable_return_statement 30671 | inline expression_node_ptr parse_return_statement() 30672 | { 30673 | if (state_.parsing_return_stmt) 30674 | { 30675 | set_error(make_error( 30676 | parser_error::e_syntax, 30677 | current_token(), 30678 | "ERR214 - Return call within a return call is not allowed", 30679 | exprtk_error_location)); 30680 | 30681 | return error_node(); 30682 | } 30683 | 30684 | scoped_bool_negator sbn(state_.parsing_return_stmt); 30685 | 30686 | std::vector<expression_node_ptr> arg_list; 30687 | 30688 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 30689 | 30690 | if (!details::imatch(current_token().value,"return")) 30691 | { 30692 | return error_node(); 30693 | } 30694 | else 30695 | next_token(); 30696 | 30697 | if (!token_is(token_t::e_lsqrbracket)) 30698 | { 30699 | set_error(make_error( 30700 | parser_error::e_syntax, 30701 | current_token(), 30702 | "ERR215 - Expected '[' at start of return statement", 30703 | exprtk_error_location)); 30704 | 30705 | return error_node(); 30706 | } 30707 | else if (!token_is(token_t::e_rsqrbracket)) 30708 | { 30709 | for ( ; ; ) 30710 | { 30711 | expression_node_ptr arg = parse_expression(); 30712 | 30713 | if (0 == arg) 30714 | return error_node(); 30715 | 30716 | arg_list.push_back(arg); 30717 | 30718 | if (token_is(token_t::e_rsqrbracket)) 30719 | break; 30720 | else if (!token_is(token_t::e_comma)) 30721 | { 30722 | set_error(make_error( 30723 | parser_error::e_syntax, 30724 | current_token(), 30725 | "ERR216 - Expected ',' between values during call to return", 30726 | exprtk_error_location)); 30727 | 30728 | return error_node(); 30729 | } 30730 | } 30731 | } 30732 | else if (settings_.zero_return_disabled()) 30733 | { 30734 | set_error(make_error( 30735 | parser_error::e_syntax, 30736 | current_token(), 30737 | "ERR217 - Zero parameter return statement not allowed", 30738 | exprtk_error_location)); 30739 | 30740 | return error_node(); 30741 | } 30742 | 30743 | const lexer::token prev_token = current_token(); 30744 | 30745 | if (token_is(token_t::e_rsqrbracket)) 30746 | { 30747 | if (!arg_list.empty()) 30748 | { 30749 | set_error(make_error( 30750 | parser_error::e_syntax, 30751 | prev_token, 30752 | "ERR218 - Invalid ']' found during return call", 30753 | exprtk_error_location)); 30754 | 30755 | return error_node(); 30756 | } 30757 | } 30758 | 30759 | std::string ret_param_type_list; 30760 | 30761 | for (std::size_t i = 0; i < arg_list.size(); ++i) 30762 | { 30763 | if (0 == arg_list[i]) 30764 | return error_node(); 30765 | else if (is_ivector_node(arg_list[i])) 30766 | ret_param_type_list += 'V'; 30767 | else if (is_generally_string_node(arg_list[i])) 30768 | ret_param_type_list += 'S'; 30769 | else 30770 | ret_param_type_list += 'T'; 30771 | } 30772 | 30773 | dec_.retparam_list_.push_back(ret_param_type_list); 30774 | 30775 | expression_node_ptr result = expression_generator_.return_call(arg_list); 30776 | 30777 | svd.delete_ptr = (0 == result); 30778 | 30779 | state_.return_stmt_present = true; 30780 | 30781 | state_.activate_side_effect("parse_return_statement()"); 30782 | 30783 | return result; 30784 | } 30785 | #else 30786 | inline expression_node_ptr parse_return_statement() 30787 | { 30788 | return error_node(); 30789 | } 30790 | #endif 30791 | 30792 | inline expression_node_ptr parse_assert_statement() 30793 | { 30794 | assert(details::imatch(current_token().value, "assert")); 30795 | 30796 | if (state_.parsing_assert_stmt) 30797 | { 30798 | set_error(make_error( 30799 | parser_error::e_syntax, 30800 | current_token(), 30801 | "ERR219 - Assert statement within an assert statement is not allowed", 30802 | exprtk_error_location)); 30803 | 30804 | return error_node(); 30805 | } 30806 | 30807 | scoped_bool_negator sbn(state_.parsing_assert_stmt); 30808 | 30809 | next_token(); 30810 | 30811 | std::vector<expression_node_ptr> assert_arg_list(3, error_node()); 30812 | scoped_vec_delete<expression_node_t> svd((*this), assert_arg_list); 30813 | 30814 | expression_node_ptr& assert_condition = assert_arg_list[0]; 30815 | expression_node_ptr& assert_message = assert_arg_list[1]; 30816 | expression_node_ptr& assert_id = assert_arg_list[2]; 30817 | 30818 | if (!token_is(token_t::e_lbracket)) 30819 | { 30820 | set_error(make_error( 30821 | parser_error::e_syntax, 30822 | current_token(), 30823 | "ERR220 - Expected '(' at start of assert statement", 30824 | exprtk_error_location)); 30825 | 30826 | return error_node(); 30827 | } 30828 | 30829 | const token_t start_token = current_token(); 30830 | 30831 | // Parse the assert condition 30832 | if (0 == (assert_condition = parse_expression())) 30833 | { 30834 | set_error(make_error( 30835 | parser_error::e_syntax, 30836 | current_token(), 30837 | "ERR221 - Failed to parse condition for assert statement", 30838 | exprtk_error_location)); 30839 | 30840 | return error_node(); 30841 | } 30842 | 30843 | const token_t end_token = current_token(); 30844 | 30845 | if (!token_is(token_t::e_rbracket)) 30846 | { 30847 | if (!token_is(token_t::e_comma)) 30848 | { 30849 | set_error(make_error( 30850 | parser_error::e_syntax, 30851 | current_token(), 30852 | "ERR222 - Expected ',' between condition and message for assert statement", 30853 | exprtk_error_location)); 30854 | 30855 | return error_node(); 30856 | } 30857 | // Parse the assert message 30858 | else if ( 30859 | (0 == (assert_message = parse_expression())) || 30860 | !details::is_generally_string_node(assert_message) 30861 | ) 30862 | { 30863 | set_error(make_error( 30864 | parser_error::e_syntax, 30865 | current_token(), 30866 | "ERR223 - " + 30867 | (assert_message ? 30868 | std::string("Expected string for assert message") : 30869 | std::string("Failed to parse message for assert statement")), 30870 | exprtk_error_location)); 30871 | 30872 | return error_node(); 30873 | } 30874 | else if (!token_is(token_t::e_rbracket)) 30875 | { 30876 | if (!token_is(token_t::e_comma)) 30877 | { 30878 | set_error(make_error( 30879 | parser_error::e_syntax, 30880 | current_token(), 30881 | "ERR224 - Expected ',' between message and ID for assert statement", 30882 | exprtk_error_location)); 30883 | 30884 | return error_node(); 30885 | } 30886 | // Parse assert ID 30887 | else if ( 30888 | (0 == (assert_id = parse_expression())) || 30889 | !details::is_const_string_node(assert_id) 30890 | ) 30891 | { 30892 | set_error(make_error( 30893 | parser_error::e_syntax, 30894 | current_token(), 30895 | "ERR225 - " + 30896 | (assert_id ? 30897 | std::string("Expected literal string for assert ID") : 30898 | std::string("Failed to parse string for assert ID")), 30899 | exprtk_error_location)); 30900 | 30901 | return error_node(); 30902 | } 30903 | else if (!token_is(token_t::e_rbracket)) 30904 | { 30905 | set_error(make_error( 30906 | parser_error::e_syntax, 30907 | current_token(), 30908 | "ERR226 - Expected ')' at start of assert statement", 30909 | exprtk_error_location)); 30910 | 30911 | return error_node(); 30912 | } 30913 | } 30914 | } 30915 | 30916 | exprtk::assert_check::assert_context context; 30917 | context.condition = lexer().substr(start_token.position, end_token.position); 30918 | context.offet = start_token.position; 30919 | 30920 | if (0 == assert_check_) 30921 | { 30922 | exprtk_debug(("parse_assert_statement() - assert functionality is disabled. assert condition: %s\n", 30923 | context.condition.c_str())); 30924 | 30925 | return new details::null_node<T>(); 30926 | } 30927 | 30928 | #ifndef exprtk_disable_string_capabilities 30929 | if (assert_message && details::is_const_string_node(assert_message)) 30930 | { 30931 | context.message = dynamic_cast<details::string_base_node<T>*>(assert_message)->str(); 30932 | } 30933 | 30934 | if (assert_id && details::is_const_string_node(assert_id)) 30935 | { 30936 | context.id = dynamic_cast<details::string_base_node<T>*>(assert_id)->str(); 30937 | 30938 | if (assert_ids_.end() != assert_ids_.find(context.id)) 30939 | { 30940 | set_error(make_error( 30941 | parser_error::e_syntax, 30942 | current_token(), 30943 | "ERR227 - Duplicate assert ID: " + context.id, 30944 | exprtk_error_location)); 30945 | 30946 | return error_node(); 30947 | } 30948 | 30949 | assert_ids_.insert(context.id); 30950 | free_node(node_allocator_, assert_id); 30951 | } 30952 | #endif 30953 | 30954 | expression_node_ptr result_node = 30955 | expression_generator_.assert_call( 30956 | assert_condition, 30957 | assert_message, 30958 | context); 30959 | 30960 | exprtk_debug(("parse_assert_statement() - assert condition: [%s]\n", context.condition.c_str() )); 30961 | exprtk_debug(("parse_assert_statement() - assert message: [%s]\n", context.message .c_str() )); 30962 | exprtk_debug(("parse_assert_statement() - assert id: [%s]\n", context.id .c_str() )); 30963 | exprtk_debug(("parse_assert_statement() - assert offset: [%d]\n", static_cast<int>(context.offet))); 30964 | 30965 | if (0 == result_node) 30966 | { 30967 | set_error(make_error( 30968 | parser_error::e_syntax, 30969 | current_token(), 30970 | "ERR228 - Failed to synthesize assert", 30971 | exprtk_error_location)); 30972 | 30973 | return error_node(); 30974 | } 30975 | 30976 | svd.delete_ptr = false; 30977 | return result_node; 30978 | } 30979 | 30980 | inline bool post_variable_process(const std::string& symbol) 30981 | { 30982 | if ( 30983 | peek_token_is(token_t::e_lbracket ) || 30984 | peek_token_is(token_t::e_lcrlbracket) || 30985 | peek_token_is(token_t::e_lsqrbracket) 30986 | ) 30987 | { 30988 | if (!settings_.commutative_check_enabled()) 30989 | { 30990 | set_error(make_error( 30991 | parser_error::e_syntax, 30992 | current_token(), 30993 | "ERR229 - Invalid sequence of variable '" + symbol + "' and bracket", 30994 | exprtk_error_location)); 30995 | 30996 | return false; 30997 | } 30998 | 30999 | lexer().insert_front(token_t::e_mul); 31000 | } 31001 | 31002 | return true; 31003 | } 31004 | 31005 | inline bool post_bracket_process(const typename token_t::token_type& token, expression_node_ptr& branch) 31006 | { 31007 | bool implied_mul = false; 31008 | 31009 | if (details::is_generally_string_node(branch)) 31010 | return true; 31011 | 31012 | if (details::is_ivector_node(branch)) 31013 | return true; 31014 | 31015 | const lexer::parser_helper::token_advance_mode hold = prsrhlpr_t::e_hold; 31016 | 31017 | switch (token) 31018 | { 31019 | case token_t::e_lcrlbracket : implied_mul = token_is(token_t::e_lbracket , hold) || 31020 | token_is(token_t::e_lcrlbracket, hold) || 31021 | token_is(token_t::e_lsqrbracket, hold) ; 31022 | break; 31023 | 31024 | case token_t::e_lbracket : implied_mul = token_is(token_t::e_lbracket , hold) || 31025 | token_is(token_t::e_lcrlbracket, hold) || 31026 | token_is(token_t::e_lsqrbracket, hold) ; 31027 | break; 31028 | 31029 | case token_t::e_lsqrbracket : implied_mul = token_is(token_t::e_lbracket , hold) || 31030 | token_is(token_t::e_lcrlbracket, hold) || 31031 | token_is(token_t::e_lsqrbracket, hold) ; 31032 | break; 31033 | 31034 | default : return true; 31035 | } 31036 | 31037 | if (implied_mul) 31038 | { 31039 | if (!settings_.commutative_check_enabled()) 31040 | { 31041 | set_error(make_error( 31042 | parser_error::e_syntax, 31043 | current_token(), 31044 | "ERR230 - Invalid sequence of brackets", 31045 | exprtk_error_location)); 31046 | 31047 | return false; 31048 | } 31049 | else if (token_t::e_eof != current_token().type) 31050 | { 31051 | lexer().insert_front(current_token().type); 31052 | lexer().insert_front(token_t::e_mul); 31053 | next_token(); 31054 | } 31055 | } 31056 | 31057 | return true; 31058 | } 31059 | 31060 | typedef typename interval_container_t<const void*>::interval_t interval_t; 31061 | typedef interval_container_t<const void*> immutable_memory_map_t; 31062 | typedef std::map<interval_t,token_t> immutable_symtok_map_t; 31063 | 31064 | inline interval_t make_memory_range(const T& t) 31065 | { 31066 | const T* begin = reinterpret_cast<const T*>(&t); 31067 | const T* end = begin + 1; 31068 | return interval_t(begin, end); 31069 | } 31070 | 31071 | inline interval_t make_memory_range(const T* begin, const std::size_t size) 31072 | { 31073 | return interval_t(begin, begin + size); 31074 | } 31075 | 31076 | inline interval_t make_memory_range(details::char_cptr begin, const std::size_t size) 31077 | { 31078 | return interval_t(begin, begin + size); 31079 | } 31080 | 31081 | void lodge_immutable_symbol(const lexer::token& token, const interval_t interval) 31082 | { 31083 | immutable_memory_map_.add_interval(interval); 31084 | immutable_symtok_map_[interval] = token; 31085 | } 31086 | 31087 | inline expression_node_ptr parse_symtab_symbol() 31088 | { 31089 | const std::string symbol = current_token().value; 31090 | 31091 | // Are we dealing with a variable or a special constant? 31092 | typedef typename symtab_store::variable_context var_ctxt_t; 31093 | var_ctxt_t var_ctx = symtab_store_.get_variable_context(symbol); 31094 | 31095 | if (var_ctx.variable) 31096 | { 31097 | assert(var_ctx.symbol_table); 31098 | 31099 | expression_node_ptr result_variable = var_ctx.variable; 31100 | 31101 | if (symtab_store_.is_constant_node(symbol)) 31102 | { 31103 | result_variable = expression_generator_(var_ctx.variable->value()); 31104 | } 31105 | else if (symbol_table_t::e_immutable == var_ctx.symbol_table->mutability()) 31106 | { 31107 | lodge_immutable_symbol(current_token(), make_memory_range(var_ctx.variable->ref())); 31108 | result_variable = var_ctx.variable; 31109 | } 31110 | 31111 | if (!post_variable_process(symbol)) 31112 | return error_node(); 31113 | 31114 | lodge_symbol(symbol, e_st_variable); 31115 | 31116 | next_token(); 31117 | 31118 | return result_variable; 31119 | } 31120 | 31121 | // Are we dealing with a locally defined variable, vector or string? 31122 | if (!sem_.empty()) 31123 | { 31124 | scope_element& se = sem_.get_active_element(symbol); 31125 | 31126 | if (se.active && details::imatch(se.name, symbol)) 31127 | { 31128 | if ( 31129 | (scope_element::e_variable == se.type) || 31130 | (scope_element::e_literal == se.type) 31131 | ) 31132 | { 31133 | se.active = true; 31134 | lodge_symbol(symbol, e_st_local_variable); 31135 | 31136 | if (!post_variable_process(symbol)) 31137 | return error_node(); 31138 | 31139 | next_token(); 31140 | 31141 | return (scope_element::e_variable == se.type) ? 31142 | se.var_node : 31143 | expression_generator_(se.var_node->value()); 31144 | } 31145 | else if (scope_element::e_vector == se.type) 31146 | { 31147 | return parse_vector(); 31148 | } 31149 | #ifndef exprtk_disable_string_capabilities 31150 | else if (scope_element::e_string == se.type) 31151 | { 31152 | return parse_string(); 31153 | } 31154 | #endif 31155 | } 31156 | } 31157 | 31158 | #ifndef exprtk_disable_string_capabilities 31159 | // Are we dealing with a string variable? 31160 | if (symtab_store_.is_stringvar(symbol)) 31161 | { 31162 | return parse_string(); 31163 | } 31164 | #endif 31165 | 31166 | { 31167 | // Are we dealing with a function? 31168 | ifunction<T>* function = symtab_store_.get_function(symbol); 31169 | 31170 | if (function) 31171 | { 31172 | lodge_symbol(symbol, e_st_function); 31173 | 31174 | expression_node_ptr func_node = 31175 | parse_function_invocation(function,symbol); 31176 | 31177 | if (func_node) 31178 | return func_node; 31179 | else 31180 | { 31181 | set_error(make_error( 31182 | parser_error::e_syntax, 31183 | current_token(), 31184 | "ERR231 - Failed to generate node for function: '" + symbol + "'", 31185 | exprtk_error_location)); 31186 | 31187 | return error_node(); 31188 | } 31189 | } 31190 | } 31191 | 31192 | { 31193 | // Are we dealing with a vararg function? 31194 | ivararg_function<T>* vararg_function = symtab_store_.get_vararg_function(symbol); 31195 | 31196 | if (vararg_function) 31197 | { 31198 | lodge_symbol(symbol, e_st_function); 31199 | 31200 | expression_node_ptr vararg_func_node = 31201 | parse_vararg_function_call(vararg_function, symbol); 31202 | 31203 | if (vararg_func_node) 31204 | return vararg_func_node; 31205 | else 31206 | { 31207 | set_error(make_error( 31208 | parser_error::e_syntax, 31209 | current_token(), 31210 | "ERR232 - Failed to generate node for vararg function: '" + symbol + "'", 31211 | exprtk_error_location)); 31212 | 31213 | return error_node(); 31214 | } 31215 | } 31216 | } 31217 | 31218 | { 31219 | // Are we dealing with a vararg generic function? 31220 | igeneric_function<T>* generic_function = symtab_store_.get_generic_function(symbol); 31221 | 31222 | if (generic_function) 31223 | { 31224 | lodge_symbol(symbol, e_st_function); 31225 | 31226 | expression_node_ptr genericfunc_node = 31227 | parse_generic_function_call(generic_function, symbol); 31228 | 31229 | if (genericfunc_node) 31230 | return genericfunc_node; 31231 | else 31232 | { 31233 | set_error(make_error( 31234 | parser_error::e_syntax, 31235 | current_token(), 31236 | "ERR233 - Failed to generate node for generic function: '" + symbol + "'", 31237 | exprtk_error_location)); 31238 | 31239 | return error_node(); 31240 | } 31241 | } 31242 | } 31243 | 31244 | #ifndef exprtk_disable_string_capabilities 31245 | { 31246 | // Are we dealing with a vararg string returning function? 31247 | igeneric_function<T>* string_function = symtab_store_.get_string_function(symbol); 31248 | 31249 | if (string_function) 31250 | { 31251 | lodge_symbol(symbol, e_st_function); 31252 | 31253 | expression_node_ptr stringfunc_node = 31254 | parse_string_function_call(string_function, symbol); 31255 | 31256 | if (stringfunc_node) 31257 | return stringfunc_node; 31258 | else 31259 | { 31260 | set_error(make_error( 31261 | parser_error::e_syntax, 31262 | current_token(), 31263 | "ERR234 - Failed to generate node for string function: '" + symbol + "'", 31264 | exprtk_error_location)); 31265 | 31266 | return error_node(); 31267 | } 31268 | } 31269 | } 31270 | 31271 | { 31272 | // Are we dealing with a vararg overloaded scalar/string returning function? 31273 | igeneric_function<T>* overload_function = symtab_store_.get_overload_function(symbol); 31274 | 31275 | if (overload_function) 31276 | { 31277 | lodge_symbol(symbol, e_st_function); 31278 | 31279 | expression_node_ptr overloadfunc_node = 31280 | parse_overload_function_call(overload_function, symbol); 31281 | 31282 | if (overloadfunc_node) 31283 | return overloadfunc_node; 31284 | else 31285 | { 31286 | set_error(make_error( 31287 | parser_error::e_syntax, 31288 | current_token(), 31289 | "ERR235 - Failed to generate node for overload function: '" + symbol + "'", 31290 | exprtk_error_location)); 31291 | 31292 | return error_node(); 31293 | } 31294 | } 31295 | } 31296 | #endif 31297 | 31298 | // Are we dealing with a vector? 31299 | if (symtab_store_.is_vector(symbol)) 31300 | { 31301 | lodge_symbol(symbol, e_st_vector); 31302 | return parse_vector(); 31303 | } 31304 | 31305 | if (details::is_reserved_symbol(symbol)) 31306 | { 31307 | if ( 31308 | settings_.function_enabled(symbol) || 31309 | !details::is_base_function(symbol) 31310 | ) 31311 | { 31312 | set_error(make_error( 31313 | parser_error::e_syntax, 31314 | current_token(), 31315 | "ERR236 - Invalid use of reserved symbol '" + symbol + "'", 31316 | exprtk_error_location)); 31317 | 31318 | return error_node(); 31319 | } 31320 | } 31321 | 31322 | // Should we handle unknown symbols? 31323 | if (resolve_unknown_symbol_ && unknown_symbol_resolver_) 31324 | { 31325 | if (!(settings_.rsrvd_sym_usr_disabled() && details::is_reserved_symbol(symbol))) 31326 | { 31327 | symbol_table_t& symtab = symtab_store_.get_symbol_table(); 31328 | 31329 | std::string error_message; 31330 | 31331 | if (unknown_symbol_resolver::e_usrmode_default == unknown_symbol_resolver_->mode) 31332 | { 31333 | T default_value = T(0); 31334 | 31335 | typename unknown_symbol_resolver::usr_symbol_type usr_symbol_type = unknown_symbol_resolver::e_usr_unknown_type; 31336 | 31337 | if (unknown_symbol_resolver_->process(symbol, usr_symbol_type, default_value, error_message)) 31338 | { 31339 | bool create_result = false; 31340 | 31341 | switch (usr_symbol_type) 31342 | { 31343 | case unknown_symbol_resolver::e_usr_variable_type : 31344 | create_result = symtab.create_variable(symbol, default_value); 31345 | break; 31346 | 31347 | case unknown_symbol_resolver::e_usr_constant_type : 31348 | create_result = symtab.add_constant(symbol, default_value); 31349 | break; 31350 | 31351 | default : create_result = false; 31352 | } 31353 | 31354 | if (create_result) 31355 | { 31356 | expression_node_ptr var = symtab_store_.get_variable(symbol); 31357 | 31358 | if (var) 31359 | { 31360 | if (symtab_store_.is_constant_node(symbol)) 31361 | { 31362 | var = expression_generator_(var->value()); 31363 | } 31364 | 31365 | lodge_symbol(symbol, e_st_variable); 31366 | 31367 | if (!post_variable_process(symbol)) 31368 | return error_node(); 31369 | 31370 | next_token(); 31371 | 31372 | return var; 31373 | } 31374 | } 31375 | } 31376 | 31377 | set_error(make_error( 31378 | parser_error::e_symtab, 31379 | current_token(), 31380 | "ERR237 - Failed to create variable: '" + symbol + "'" + 31381 | (error_message.empty() ? "" : " - " + error_message), 31382 | exprtk_error_location)); 31383 | 31384 | } 31385 | else if (unknown_symbol_resolver::e_usrmode_extended == unknown_symbol_resolver_->mode) 31386 | { 31387 | if (unknown_symbol_resolver_->process(symbol, symtab, error_message)) 31388 | { 31389 | expression_node_ptr result = parse_symtab_symbol(); 31390 | 31391 | if (result) 31392 | { 31393 | return result; 31394 | } 31395 | } 31396 | 31397 | set_error(make_error( 31398 | parser_error::e_symtab, 31399 | current_token(), 31400 | "ERR238 - Failed to resolve symbol: '" + symbol + "'" + 31401 | (error_message.empty() ? "" : " - " + error_message), 31402 | exprtk_error_location)); 31403 | } 31404 | 31405 | return error_node(); 31406 | } 31407 | } 31408 | 31409 | set_error(make_error( 31410 | parser_error::e_syntax, 31411 | current_token(), 31412 | "ERR239 - Undefined symbol: '" + symbol + "'", 31413 | exprtk_error_location)); 31414 | 31415 | return error_node(); 31416 | } 31417 | 31418 | inline expression_node_ptr check_block_statement_closure(expression_node_ptr expression) 31419 | { 31420 | if ( 31421 | expression && 31422 | ( 31423 | (current_token().type == token_t::e_symbol) || 31424 | (current_token().type == token_t::e_number) 31425 | ) 31426 | ) 31427 | { 31428 | free_node(node_allocator_, expression); 31429 | 31430 | set_error(make_error( 31431 | parser_error::e_syntax, 31432 | current_token(), 31433 | "ERR240 - Invalid syntax '" + current_token().value + "' possible missing operator or context", 31434 | exprtk_error_location)); 31435 | 31436 | return error_node(); 31437 | } 31438 | 31439 | return expression; 31440 | } 31441 | 31442 | inline expression_node_ptr parse_symbol() 31443 | { 31444 | static const std::string symbol_if = "if" ; 31445 | static const std::string symbol_while = "while" ; 31446 | static const std::string symbol_repeat = "repeat" ; 31447 | static const std::string symbol_for = "for" ; 31448 | static const std::string symbol_switch = "switch" ; 31449 | static const std::string symbol_null = "null" ; 31450 | static const std::string symbol_break = "break" ; 31451 | static const std::string symbol_continue = "continue" 31452 | static const std::string symbol_var = "var" ; 31453 | static const std::string symbol_const = "const" ; 31454 | static const std::string symbol_swap = "swap" ; 31455 | static const std::string symbol_return = "return" ; 31456 | static const std::string symbol_not = "not" ; 31457 | static const std::string symbol_assert = "assert" ; 31458 | 31459 | const std::string symbol = current_token().value; 31460 | 31461 | if (valid_vararg_operation(symbol)) 31462 | { 31463 | return parse_vararg_function(); 31464 | } 31465 | else if (details::imatch(symbol, symbol_not)) 31466 | { 31467 | return parse_not_statement(); 31468 | } 31469 | else if (valid_base_operation(symbol)) 31470 | { 31471 | return parse_base_operation(); 31472 | } 31473 | else if ( 31474 | details::imatch(symbol, symbol_if) && 31475 | settings_.control_struct_enabled(symbol) 31476 | ) 31477 | { 31478 | return parse_conditional_statement(); 31479 | } 31480 | else if ( 31481 | details::imatch(symbol, symbol_while) && 31482 | settings_.control_struct_enabled(symbol) 31483 | ) 31484 | { 31485 | return check_block_statement_closure(parse_while_loop()); 31486 | } 31487 | else if ( 31488 | details::imatch(symbol, symbol_repeat) && 31489 | settings_.control_struct_enabled(symbol) 31490 | ) 31491 | { 31492 | return check_block_statement_closure(parse_repeat_until_loop()); 31493 | } 31494 | else if ( 31495 | details::imatch(symbol, symbol_for) && 31496 | settings_.control_struct_enabled(symbol) 31497 | ) 31498 | { 31499 | return check_block_statement_closure(parse_for_loop()); 31500 | } 31501 | else if ( 31502 | details::imatch(symbol, symbol_switch) && 31503 | settings_.control_struct_enabled(symbol) 31504 | ) 31505 | { 31506 | return check_block_statement_closure(parse_switch_statement()); 31507 | } 31508 | else if (details::is_valid_sf_symbol(symbol)) 31509 | { 31510 | return parse_special_function(); 31511 | } 31512 | else if (details::imatch(symbol, symbol_null)) 31513 | { 31514 | return parse_null_statement(); 31515 | } 31516 | #ifndef exprtk_disable_break_continue 31517 | else if (details::imatch(symbol, symbol_break)) 31518 | { 31519 | return parse_break_statement(); 31520 | } 31521 | else if (details::imatch(symbol, symbol_continue)) 31522 | { 31523 | return parse_continue_statement(); 31524 | } 31525 | #endif 31526 | else if (details::imatch(symbol, symbol_var)) 31527 | { 31528 | return parse_define_var_statement(); 31529 | } 31530 | else if (details::imatch(symbol, symbol_const)) 31531 | { 31532 | return parse_define_constvar_statement(); 31533 | } 31534 | else if (details::imatch(symbol, symbol_swap)) 31535 | { 31536 | return parse_swap_statement(); 31537 | } 31538 | #ifndef exprtk_disable_return_statement 31539 | else if ( 31540 | details::imatch(symbol, symbol_return) && 31541 | settings_.control_struct_enabled(symbol) 31542 | ) 31543 | { 31544 | return check_block_statement_closure(parse_return_statement()); 31545 | } 31546 | #endif 31547 | else if (details::imatch(symbol, symbol_assert)) 31548 | { 31549 | return parse_assert_statement(); 31550 | } 31551 | else if (symtab_store_.valid() || !sem_.empty()) 31552 | { 31553 | return parse_symtab_symbol(); 31554 | } 31555 | else 31556 | { 31557 | set_error(make_error( 31558 | parser_error::e_symtab, 31559 | current_token(), 31560 | "ERR241 - Unknown variable or function encountered. Symbol table(s) " 31561 | "is either invalid or does not contain symbol: '" + symbol + "'", 31562 | exprtk_error_location)); 31563 | 31564 | return error_node(); 31565 | } 31566 | } 31567 | 31568 | inline expression_node_ptr parse_branch(precedence_level precedence = e_level00) 31569 | { 31570 | stack_limit_handler slh(*this); 31571 | 31572 | if (!slh) 31573 | { 31574 | return error_node(); 31575 | } 31576 | 31577 | expression_node_ptr branch = error_node(); 31578 | 31579 | if (token_t::e_number == current_token().type) 31580 | { 31581 | T numeric_value = T(0); 31582 | 31583 | if (details::string_to_real(current_token().value, numeric_value)) 31584 | { 31585 | expression_node_ptr literal_exp = expression_generator_(numeric_value); 31586 | 31587 | if (0 == literal_exp) 31588 | { 31589 | set_error(make_error( 31590 | parser_error::e_numeric, 31591 | current_token(), 31592 | "ERR242 - Failed generate node for scalar: '" + current_token().value + "'", 31593 | exprtk_error_location)); 31594 | 31595 | return error_node(); 31596 | } 31597 | 31598 | next_token(); 31599 | branch = literal_exp; 31600 | } 31601 | else 31602 | { 31603 | set_error(make_error( 31604 | parser_error::e_numeric, 31605 | current_token(), 31606 | "ERR243 - Failed to convert '" + current_token().value + "' to a number", 31607 | exprtk_error_location)); 31608 | 31609 | return error_node(); 31610 | } 31611 | } 31612 | else if (token_t::e_symbol == current_token().type) 31613 | { 31614 | branch = parse_symbol(); 31615 | } 31616 | #ifndef exprtk_disable_string_capabilities 31617 | else if (token_t::e_string == current_token().type) 31618 | { 31619 | branch = parse_const_string(); 31620 | } 31621 | #endif 31622 | else if (token_t::e_lbracket == current_token().type) 31623 | { 31624 | next_token(); 31625 | 31626 | if (0 == (branch = parse_expression())) 31627 | { 31628 | return error_node(); 31629 | } 31630 | 31631 | token_is(token_t::e_eof); 31632 | 31633 | if (!token_is(token_t::e_rbracket)) 31634 | { 31635 | set_error(make_error( 31636 | parser_error::e_syntax, 31637 | current_token(), 31638 | "ERR244 - Expected ')' instead of: '" + current_token().value + "'", 31639 | exprtk_error_location)); 31640 | 31641 | details::free_node(node_allocator_, branch); 31642 | 31643 | return error_node(); 31644 | } 31645 | else if (!post_bracket_process(token_t::e_lbracket,branch)) 31646 | { 31647 | details::free_node(node_allocator_, branch); 31648 | 31649 | return error_node(); 31650 | } 31651 | 31652 | parse_pending_vector_index_operator(branch); 31653 | } 31654 | else if (token_t::e_lsqrbracket == current_token().type) 31655 | { 31656 | next_token(); 31657 | 31658 | if (0 == (branch = parse_expression())) 31659 | return error_node(); 31660 | else if (!token_is(token_t::e_rsqrbracket)) 31661 | { 31662 | set_error(make_error( 31663 | parser_error::e_syntax, 31664 | current_token(), 31665 | "ERR245 - Expected ']' instead of: '" + current_token().value + "'", 31666 | exprtk_error_location)); 31667 | 31668 | details::free_node(node_allocator_, branch); 31669 | 31670 | return error_node(); 31671 | } 31672 | else if (!post_bracket_process(token_t::e_lsqrbracket,branch)) 31673 | { 31674 | details::free_node(node_allocator_, branch); 31675 | 31676 | return error_node(); 31677 | } 31678 | } 31679 | else if (token_t::e_lcrlbracket == current_token().type) 31680 | { 31681 | next_token(); 31682 | 31683 | if (0 == (branch = parse_expression())) 31684 | return error_node(); 31685 | else if (!token_is(token_t::e_rcrlbracket)) 31686 | { 31687 | set_error(make_error( 31688 | parser_error::e_syntax, 31689 | current_token(), 31690 | "ERR246 - Expected '}' instead of: '" + current_token().value + "'", 31691 | exprtk_error_location)); 31692 | 31693 | details::free_node(node_allocator_, branch); 31694 | 31695 | return error_node(); 31696 | } 31697 | else if (!post_bracket_process(token_t::e_lcrlbracket,branch)) 31698 | { 31699 | details::free_node(node_allocator_, branch); 31700 | 31701 | return error_node(); 31702 | } 31703 | } 31704 | else if (token_t::e_sub == current_token().type) 31705 | { 31706 | next_token(); 31707 | branch = parse_expression(e_level11); 31708 | 31709 | if ( 31710 | branch && 31711 | !( 31712 | details::is_neg_unary_node (branch) && 31713 | simplify_unary_negation_branch(branch) 31714 | ) 31715 | ) 31716 | { 31717 | expression_node_ptr result = expression_generator_(details::e_neg,branch); 31718 | 31719 | if (0 == result) 31720 | { 31721 | details::free_node(node_allocator_, branch); 31722 | 31723 | return error_node(); 31724 | } 31725 | else 31726 | branch = result; 31727 | } 31728 | } 31729 | else if (token_t::e_add == current_token().type) 31730 | { 31731 | next_token(); 31732 | branch = parse_expression(e_level13); 31733 | } 31734 | else if (token_t::e_eof == current_token().type) 31735 | { 31736 | set_error(make_error( 31737 | parser_error::e_syntax, 31738 | current_token(), 31739 | "ERR247 - Premature end of expression[1]", 31740 | exprtk_error_location)); 31741 | 31742 | return error_node(); 31743 | } 31744 | else 31745 | { 31746 | set_error(make_error( 31747 | parser_error::e_syntax, 31748 | current_token(), 31749 | "ERR248 - Premature end of expression[2]", 31750 | exprtk_error_location)); 31751 | 31752 | return error_node(); 31753 | } 31754 | 31755 | if ( 31756 | branch && 31757 | (e_level00 == precedence) && 31758 | token_is(token_t::e_ternary,prsrhlpr_t::e_hold) 31759 | ) 31760 | { 31761 | branch = parse_ternary_conditional_statement(branch); 31762 | } 31763 | 31764 | parse_pending_string_rangesize(branch); 31765 | 31766 | return branch; 31767 | } 31768 | 31769 | template <typename Type> 31770 | class expression_generator 31771 | { 31772 | public: 31773 | 31774 | typedef details::expression_node<Type>* expression_node_ptr; 31775 | typedef expression_node_ptr (*synthesize_functor_t)(expression_generator<T>&, const details::operator_type& operation, expression_node_ptr (&branch)[2]); 31776 | typedef std::map<std::string,synthesize_functor_t> synthesize_map_t; 31777 | typedef typename exprtk::parser<Type> parser_t; 31778 | typedef const Type& vtype; 31779 | typedef const Type ctype; 31780 | 31781 | inline void init_synthesize_map() 31782 | { 31783 | #ifndef exprtk_disable_enhanced_features 31784 | synthesize_map_["(v)o(v)"] = synthesize_vov_expression::process; 31785 | synthesize_map_["(c)o(v)"] = synthesize_cov_expression::process; 31786 | synthesize_map_["(v)o(c)"] = synthesize_voc_expression::process; 31787 | 31788 | #define register_synthezier(S) \ 31789 | synthesize_map_[S ::node_type::id()] = S ::process; \ 31790 | 31791 | register_synthezier(synthesize_vovov_expression0) 31792 | register_synthezier(synthesize_vovov_expression1) 31793 | register_synthezier(synthesize_vovoc_expression0) 31794 | register_synthezier(synthesize_vovoc_expression1) 31795 | register_synthezier(synthesize_vocov_expression0) 31796 | register_synthezier(synthesize_vocov_expression1) 31797 | register_synthezier(synthesize_covov_expression0) 31798 | register_synthezier(synthesize_covov_expression1) 31799 | register_synthezier(synthesize_covoc_expression0) 31800 | register_synthezier(synthesize_covoc_expression1) 31801 | register_synthezier(synthesize_cocov_expression1) 31802 | register_synthezier(synthesize_vococ_expression0) 31803 | 31804 | register_synthezier(synthesize_vovovov_expression0) 31805 | register_synthezier(synthesize_vovovoc_expression0) 31806 | register_synthezier(synthesize_vovocov_expression0) 31807 | register_synthezier(synthesize_vocovov_expression0) 31808 | register_synthezier(synthesize_covovov_expression0) 31809 | register_synthezier(synthesize_covocov_expression0) 31810 | register_synthezier(synthesize_vocovoc_expression0) 31811 | register_synthezier(synthesize_covovoc_expression0) 31812 | register_synthezier(synthesize_vococov_expression0) 31813 | 31814 | register_synthezier(synthesize_vovovov_expression1) 31815 | register_synthezier(synthesize_vovovoc_expression1) 31816 | register_synthezier(synthesize_vovocov_expression1) 31817 | register_synthezier(synthesize_vocovov_expression1) 31818 | register_synthezier(synthesize_covovov_expression1) 31819 | register_synthezier(synthesize_covocov_expression1) 31820 | register_synthezier(synthesize_vocovoc_expression1) 31821 | register_synthezier(synthesize_covovoc_expression1) 31822 | register_synthezier(synthesize_vococov_expression1) 31823 | 31824 | register_synthezier(synthesize_vovovov_expression2) 31825 | register_synthezier(synthesize_vovovoc_expression2) 31826 | register_synthezier(synthesize_vovocov_expression2) 31827 | register_synthezier(synthesize_vocovov_expression2) 31828 | register_synthezier(synthesize_covovov_expression2) 31829 | register_synthezier(synthesize_covocov_expression2) 31830 | register_synthezier(synthesize_vocovoc_expression2) 31831 | register_synthezier(synthesize_covovoc_expression2) 31832 | 31833 | register_synthezier(synthesize_vovovov_expression3) 31834 | register_synthezier(synthesize_vovovoc_expression3) 31835 | register_synthezier(synthesize_vovocov_expression3) 31836 | register_synthezier(synthesize_vocovov_expression3) 31837 | register_synthezier(synthesize_covovov_expression3) 31838 | register_synthezier(synthesize_covocov_expression3) 31839 | register_synthezier(synthesize_vocovoc_expression3) 31840 | register_synthezier(synthesize_covovoc_expression3) 31841 | register_synthezier(synthesize_vococov_expression3) 31842 | 31843 | register_synthezier(synthesize_vovovov_expression4) 31844 | register_synthezier(synthesize_vovovoc_expression4) 31845 | register_synthezier(synthesize_vovocov_expression4) 31846 | register_synthezier(synthesize_vocovov_expression4) 31847 | register_synthezier(synthesize_covovov_expression4) 31848 | register_synthezier(synthesize_covocov_expression4) 31849 | register_synthezier(synthesize_vocovoc_expression4) 31850 | register_synthezier(synthesize_covovoc_expression4) 31851 | 31852 | #undef register_synthezier 31853 | #endif 31854 | } 31855 | 31856 | inline void set_parser(parser_t& p) 31857 | { 31858 | parser_ = &p; 31859 | } 31860 | 31861 | inline void set_uom(unary_op_map_t& unary_op_map) 31862 | { 31863 | unary_op_map_ = &unary_op_map; 31864 | } 31865 | 31866 | inline void set_bom(binary_op_map_t& binary_op_map) 31867 | { 31868 | binary_op_map_ = &binary_op_map; 31869 | } 31870 | 31871 | inline void set_ibom(inv_binary_op_map_t& inv_binary_op_map) 31872 | { 31873 | inv_binary_op_map_ = &inv_binary_op_map; 31874 | } 31875 | 31876 | inline void set_sf3m(sf3_map_t& sf3_map) 31877 | { 31878 | sf3_map_ = &sf3_map; 31879 | } 31880 | 31881 | inline void set_sf4m(sf4_map_t& sf4_map) 31882 | { 31883 | sf4_map_ = &sf4_map; 31884 | } 31885 | 31886 | inline void set_allocator(details::node_allocator& na) 31887 | { 31888 | node_allocator_ = &na; 31889 | } 31890 | 31891 | inline void set_strength_reduction_state(const bool enabled) 31892 | { 31893 | strength_reduction_enabled_ = enabled; 31894 | } 31895 | 31896 | inline bool strength_reduction_enabled() const 31897 | { 31898 | return strength_reduction_enabled_; 31899 | } 31900 | 31901 | inline bool valid_operator(const details::operator_type& operation, binary_functor_t& bop) 31902 | { 31903 | typename binary_op_map_t::iterator bop_itr = binary_op_map_->find(operation); 31904 | 31905 | if (binary_op_map_->end() == bop_itr) 31906 | return false; 31907 | 31908 | bop = bop_itr->second; 31909 | 31910 | return true; 31911 | } 31912 | 31913 | inline bool valid_operator(const details::operator_type& operation, unary_functor_t& uop) 31914 | { 31915 | typename unary_op_map_t::iterator uop_itr = unary_op_map_->find(operation); 31916 | 31917 | if ((*unary_op_map_).end() == uop_itr) 31918 | return false; 31919 | 31920 | uop = uop_itr->second; 31921 | 31922 | return true; 31923 | } 31924 | 31925 | inline details::operator_type get_operator(const binary_functor_t& bop) const 31926 | { 31927 | return (*inv_binary_op_map_).find(bop)->second; 31928 | } 31929 | 31930 | inline expression_node_ptr operator() (const Type& v) const 31931 | { 31932 | return node_allocator_->allocate<literal_node_t>(v); 31933 | } 31934 | 31935 | #ifndef exprtk_disable_string_capabilities 31936 | inline expression_node_ptr operator() (const std::string& s) const 31937 | { 31938 | return node_allocator_->allocate<string_literal_node_t>(s); 31939 | } 31940 | 31941 | inline expression_node_ptr operator() (std::string& s, range_t& rp) const 31942 | { 31943 | return node_allocator_->allocate_rr<string_range_node_t>(s,rp); 31944 | } 31945 | 31946 | inline expression_node_ptr operator() (const std::string& s, range_t& rp) const 31947 | { 31948 | return node_allocator_->allocate_tt<const_string_range_node_t>(s,rp); 31949 | } 31950 | 31951 | inline expression_node_ptr operator() (expression_node_ptr branch, range_t& rp) const 31952 | { 31953 | if (is_generally_string_node(branch)) 31954 | return node_allocator_->allocate_tt<generic_string_range_node_t>(branch,rp); 31955 | else 31956 | return error_node(); 31957 | } 31958 | #endif 31959 | 31960 | inline bool unary_optimisable(const details::operator_type& operation) const 31961 | { 31962 | return (details::e_abs == operation) || (details::e_acos == operation) || 31963 | (details::e_acosh == operation) || (details::e_asin == operation) || 31964 | (details::e_asinh == operation) || (details::e_atan == operation) || 31965 | (details::e_atanh == operation) || (details::e_ceil == operation) || 31966 | (details::e_cos == operation) || (details::e_cosh == operation) || 31967 | (details::e_exp == operation) || (details::e_expm1 == operation) || 31968 | (details::e_floor == operation) || (details::e_log == operation) || 31969 | (details::e_log10 == operation) || (details::e_log2 == operation) || 31970 | (details::e_log1p == operation) || (details::e_neg == operation) || 31971 | (details::e_pos == operation) || (details::e_round == operation) || 31972 | (details::e_sin == operation) || (details::e_sinc == operation) || 31973 | (details::e_sinh == operation) || (details::e_sqrt == operation) || 31974 | (details::e_tan == operation) || (details::e_tanh == operation) || 31975 | (details::e_cot == operation) || (details::e_sec == operation) || 31976 | (details::e_csc == operation) || (details::e_r2d == operation) || 31977 | (details::e_d2r == operation) || (details::e_d2g == operation) || 31978 | (details::e_g2d == operation) || (details::e_notl == operation) || 31979 | (details::e_sgn == operation) || (details::e_erf == operation) || 31980 | (details::e_erfc == operation) || (details::e_ncdf == operation) || 31981 | (details::e_frac == operation) || (details::e_trunc == operation) ; 31982 | } 31983 | 31984 | inline bool sf3_optimisable(const std::string& sf3id, trinary_functor_t& tfunc) const 31985 | { 31986 | typename sf3_map_t::const_iterator itr = sf3_map_->find(sf3id); 31987 | 31988 | if (sf3_map_->end() == itr) 31989 | return false; 31990 | else 31991 | tfunc = itr->second.first; 31992 | 31993 | return true; 31994 | } 31995 | 31996 | inline bool sf4_optimisable(const std::string& sf4id, quaternary_functor_t& qfunc) const 31997 | { 31998 | typename sf4_map_t::const_iterator itr = sf4_map_->find(sf4id); 31999 | 32000 | if (sf4_map_->end() == itr) 32001 | return false; 32002 | else 32003 | qfunc = itr->second.first; 32004 | 32005 | return true; 32006 | } 32007 | 32008 | inline bool sf3_optimisable(const std::string& sf3id, details::operator_type& operation) const 32009 | { 32010 | typename sf3_map_t::const_iterator itr = sf3_map_->find(sf3id); 32011 | 32012 | if (sf3_map_->end() == itr) 32013 | return false; 32014 | else 32015 | operation = itr->second.second; 32016 | 32017 | return true; 32018 | } 32019 | 32020 | inline bool sf4_optimisable(const std::string& sf4id, details::operator_type& operation) const 32021 | { 32022 | typename sf4_map_t::const_iterator itr = sf4_map_->find(sf4id); 32023 | 32024 | if (sf4_map_->end() == itr) 32025 | return false; 32026 | else 32027 | operation = itr->second.second; 32028 | 32029 | return true; 32030 | } 32031 | 32032 | inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[1]) 32033 | { 32034 | if (0 == branch[0]) 32035 | { 32036 | return error_node(); 32037 | } 32038 | else if (details::is_null_node(branch[0])) 32039 | { 32040 | return branch[0]; 32041 | } 32042 | else if (details::is_break_node(branch[0])) 32043 | { 32044 | return error_node(); 32045 | } 32046 | else if (details::is_continue_node(branch[0])) 32047 | { 32048 | return error_node(); 32049 | } 32050 | else if (details::is_constant_node(branch[0])) 32051 | { 32052 | return synthesize_expression<unary_node_t,1>(operation,branch); 32053 | } 32054 | else if (unary_optimisable(operation) && details::is_variable_node(branch[0])) 32055 | { 32056 | return synthesize_uv_expression(operation,branch); 32057 | } 32058 | else if (unary_optimisable(operation) && details::is_ivector_node(branch[0])) 32059 | { 32060 | return synthesize_uvec_expression(operation,branch); 32061 | } 32062 | else 32063 | return synthesize_unary_expression(operation,branch); 32064 | } 32065 | 32066 | inline bool is_assignment_operation(const details::operator_type& operation) const 32067 | { 32068 | return ( 32069 | (details::e_addass == operation) || 32070 | (details::e_subass == operation) || 32071 | (details::e_mulass == operation) || 32072 | (details::e_divass == operation) || 32073 | (details::e_modass == operation) 32074 | ) && 32075 | parser_->settings_.assignment_enabled(operation); 32076 | } 32077 | 32078 | #ifndef exprtk_disable_string_capabilities 32079 | inline bool valid_string_operation(const details::operator_type& operation) const 32080 | { 32081 | return (details::e_add == operation) || 32082 | (details::e_lt == operation) || 32083 | (details::e_lte == operation) || 32084 | (details::e_gt == operation) || 32085 | (details::e_gte == operation) || 32086 | (details::e_eq == operation) || 32087 | (details::e_ne == operation) || 32088 | (details::e_in == operation) || 32089 | (details::e_like == operation) || 32090 | (details::e_ilike == operation) || 32091 | (details::e_assign == operation) || 32092 | (details::e_addass == operation) || 32093 | (details::e_swap == operation) ; 32094 | } 32095 | #else 32096 | inline bool valid_string_operation(const details::operator_type&) const 32097 | { 32098 | return false; 32099 | } 32100 | #endif 32101 | 32102 | inline std::string to_str(const details::operator_type& operation) const 32103 | { 32104 | switch (operation) 32105 | { 32106 | case details::e_add : return "+" ; 32107 | case details::e_sub : return "-" ; 32108 | case details::e_mul : return "*" ; 32109 | case details::e_div : return "/" ; 32110 | case details::e_mod : return "%" ; 32111 | case details::e_pow : return "^" ; 32112 | case details::e_lt : return "<" ; 32113 | case details::e_lte : return "<=" ; 32114 | case details::e_gt : return ">" ; 32115 | case details::e_gte : return ">=" ; 32116 | case details::e_eq : return "==" ; 32117 | case details::e_ne : return "!=" ; 32118 | case details::e_and : return "and" ; 32119 | case details::e_nand : return "nand" ; 32120 | case details::e_or : return "or" ; 32121 | case details::e_nor : return "nor" ; 32122 | case details::e_xor : return "xor" ; 32123 | case details::e_xnor : return "xnor" ; 32124 | default : return "UNKNOWN" 32125 | } 32126 | } 32127 | 32128 | inline bool operation_optimisable(const details::operator_type& operation) const 32129 | { 32130 | return (details::e_add == operation) || 32131 | (details::e_sub == operation) || 32132 | (details::e_mul == operation) || 32133 | (details::e_div == operation) || 32134 | (details::e_mod == operation) || 32135 | (details::e_pow == operation) || 32136 | (details::e_lt == operation) || 32137 | (details::e_lte == operation) || 32138 | (details::e_gt == operation) || 32139 | (details::e_gte == operation) || 32140 | (details::e_eq == operation) || 32141 | (details::e_ne == operation) || 32142 | (details::e_and == operation) || 32143 | (details::e_nand == operation) || 32144 | (details::e_or == operation) || 32145 | (details::e_nor == operation) || 32146 | (details::e_xor == operation) || 32147 | (details::e_xnor == operation) ; 32148 | } 32149 | 32150 | inline std::string branch_to_id(expression_node_ptr branch) const 32151 | { 32152 | static const std::string null_str ("(null)" ); 32153 | static const std::string const_str ("(c)" ); 32154 | static const std::string var_str ("(v)" ); 32155 | static const std::string vov_str ("(vov)" ); 32156 | static const std::string cov_str ("(cov)" ); 32157 | static const std::string voc_str ("(voc)" ); 32158 | static const std::string str_str ("(s)" ); 32159 | static const std::string strrng_str ("(rngs)" ); 32160 | static const std::string cs_str ("(cs)" ); 32161 | static const std::string cstrrng_str("(crngs)"); 32162 | 32163 | if (details::is_null_node(branch)) 32164 | return null_str; 32165 | else if (details::is_constant_node(branch)) 32166 | return const_str; 32167 | else if (details::is_variable_node(branch)) 32168 | return var_str; 32169 | else if (details::is_vov_node(branch)) 32170 | return vov_str; 32171 | else if (details::is_cov_node(branch)) 32172 | return cov_str; 32173 | else if (details::is_voc_node(branch)) 32174 | return voc_str; 32175 | else if (details::is_string_node(branch)) 32176 | return str_str; 32177 | else if (details::is_const_string_node(branch)) 32178 | return cs_str; 32179 | else if (details::is_string_range_node(branch)) 32180 | return strrng_str; 32181 | else if (details::is_const_string_range_node(branch)) 32182 | return cstrrng_str; 32183 | else if (details::is_t0ot1ot2_node(branch)) 32184 | return "(" + dynamic_cast<details::T0oT1oT2_base_node<T>*>(branch)->type_id() + ")" 32185 | else if (details::is_t0ot1ot2ot3_node(branch)) 32186 | return "(" + dynamic_cast<details::T0oT1oT2oT3_base_node<T>*>(branch)->type_id() + ")" 32187 | else 32188 | return "ERROR" 32189 | } 32190 | 32191 | inline std::string branch_to_id(expression_node_ptr (&branch)[2]) const 32192 | { 32193 | return branch_to_id(branch[0]) + std::string("o") + branch_to_id(branch[1]); 32194 | } 32195 | 32196 | inline bool cov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32197 | { 32198 | if (!operation_optimisable(operation)) 32199 | return false; 32200 | else 32201 | return details::is_constant_node(branch[0]) && 32202 | details::is_variable_node(branch[1]) ; 32203 | } 32204 | 32205 | inline bool voc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32206 | { 32207 | if (!operation_optimisable(operation)) 32208 | return false; 32209 | else 32210 | return details::is_variable_node(branch[0]) && 32211 | details::is_constant_node(branch[1]) ; 32212 | } 32213 | 32214 | inline bool vov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32215 | { 32216 | if (!operation_optimisable(operation)) 32217 | return false; 32218 | else 32219 | return details::is_variable_node(branch[0]) && 32220 | details::is_variable_node(branch[1]) ; 32221 | } 32222 | 32223 | inline bool cob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32224 | { 32225 | if (!operation_optimisable(operation)) 32226 | return false; 32227 | else 32228 | return details::is_constant_node(branch[0]) && 32229 | !details::is_constant_node(branch[1]) ; 32230 | } 32231 | 32232 | inline bool boc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32233 | { 32234 | if (!operation_optimisable(operation)) 32235 | return false; 32236 | else 32237 | return !details::is_constant_node(branch[0]) && 32238 | details::is_constant_node(branch[1]) ; 32239 | } 32240 | 32241 | inline bool cocob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32242 | { 32243 | if ( 32244 | (details::e_add == operation) || 32245 | (details::e_sub == operation) || 32246 | (details::e_mul == operation) || 32247 | (details::e_div == operation) 32248 | ) 32249 | { 32250 | return (details::is_constant_node(branch[0]) && details::is_cob_node(branch[1])) || 32251 | (details::is_constant_node(branch[1]) && details::is_cob_node(branch[0])) ; 32252 | } 32253 | else 32254 | return false; 32255 | } 32256 | 32257 | inline bool coboc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32258 | { 32259 | if ( 32260 | (details::e_add == operation) || 32261 | (details::e_sub == operation) || 32262 | (details::e_mul == operation) || 32263 | (details::e_div == operation) 32264 | ) 32265 | { 32266 | return (details::is_constant_node(branch[0]) && details::is_boc_node(branch[1])) || 32267 | (details::is_constant_node(branch[1]) && details::is_boc_node(branch[0])) ; 32268 | } 32269 | else 32270 | return false; 32271 | } 32272 | 32273 | inline bool uvouv_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32274 | { 32275 | if (!operation_optimisable(operation)) 32276 | return false; 32277 | else 32278 | return details::is_uv_node(branch[0]) && 32279 | details::is_uv_node(branch[1]) ; 32280 | } 32281 | 32282 | inline bool vob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32283 | { 32284 | if (!operation_optimisable(operation)) 32285 | return false; 32286 | else 32287 | return details::is_variable_node(branch[0]) && 32288 | !details::is_variable_node(branch[1]) ; 32289 | } 32290 | 32291 | inline bool bov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32292 | { 32293 | if (!operation_optimisable(operation)) 32294 | return false; 32295 | else 32296 | return !details::is_variable_node(branch[0]) && 32297 | details::is_variable_node(branch[1]) ; 32298 | } 32299 | 32300 | inline bool binext_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32301 | { 32302 | if (!operation_optimisable(operation)) 32303 | return false; 32304 | else 32305 | return !details::is_constant_node(branch[0]) || 32306 | !details::is_constant_node(branch[1]) ; 32307 | } 32308 | 32309 | inline bool is_invalid_assignment_op(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32310 | { 32311 | if (is_assignment_operation(operation)) 32312 | { 32313 | const bool b1_is_genstring = details::is_generally_string_node(branch[1]); 32314 | 32315 | if (details::is_string_node(branch[0])) 32316 | return !b1_is_genstring; 32317 | else if (details::is_literal_node(branch[0])) 32318 | return true; 32319 | else 32320 | return ( 32321 | !details::is_variable_node (branch[0]) && 32322 | !details::is_vector_elem_node (branch[0]) && 32323 | !details::is_vector_celem_node (branch[0]) && 32324 | !details::is_vector_elem_rtc_node (branch[0]) && 32325 | !details::is_vector_celem_rtc_node (branch[0]) && 32326 | !details::is_rebasevector_elem_node (branch[0]) && 32327 | !details::is_rebasevector_celem_node (branch[0]) && 32328 | !details::is_rebasevector_elem_rtc_node (branch[0]) && 32329 | !details::is_rebasevector_celem_rtc_node(branch[0]) && 32330 | !details::is_vector_node (branch[0]) 32331 | ) 32332 | || b1_is_genstring; 32333 | } 32334 | else 32335 | return false; 32336 | } 32337 | 32338 | inline bool is_constpow_operation(const details::operator_type& operation, expression_node_ptr(&branch)[2]) const 32339 | { 32340 | if ( 32341 | !details::is_constant_node(branch[1]) || 32342 | details::is_constant_node(branch[0]) || 32343 | details::is_variable_node(branch[0]) || 32344 | details::is_vector_node (branch[0]) || 32345 | details::is_generally_string_node(branch[0]) 32346 | ) 32347 | return false; 32348 | 32349 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 32350 | 32351 | return cardinal_pow_optimisable(operation, c); 32352 | } 32353 | 32354 | inline bool is_invalid_break_continue_op(expression_node_ptr (&branch)[2]) const 32355 | { 32356 | return ( 32357 | details::is_break_node (branch[0]) || 32358 | details::is_break_node (branch[1]) || 32359 | details::is_continue_node(branch[0]) || 32360 | details::is_continue_node(branch[1]) 32361 | ); 32362 | } 32363 | 32364 | inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32365 | { 32366 | const bool b0_string = is_generally_string_node(branch[0]); 32367 | const bool b1_string = is_generally_string_node(branch[1]); 32368 | 32369 | bool result = false; 32370 | 32371 | if (b0_string != b1_string) 32372 | result = true; 32373 | else if (!valid_string_operation(operation) && b0_string && b1_string) 32374 | result = true; 32375 | 32376 | if (result) 32377 | { 32378 | parser_->set_synthesis_error("Invalid string operation"); 32379 | } 32380 | 32381 | return result; 32382 | } 32383 | 32384 | inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[3]) const 32385 | { 32386 | const bool b0_string = is_generally_string_node(branch[0]); 32387 | const bool b1_string = is_generally_string_node(branch[1]); 32388 | const bool b2_string = is_generally_string_node(branch[2]); 32389 | 32390 | bool result = false; 32391 | 32392 | if ((b0_string != b1_string) || (b1_string != b2_string)) 32393 | result = true; 32394 | else if ((details::e_inrange != operation) && b0_string && b1_string && b2_string) 32395 | result = true; 32396 | 32397 | if (result) 32398 | { 32399 | parser_->set_synthesis_error("Invalid string operation"); 32400 | } 32401 | 32402 | return result; 32403 | } 32404 | 32405 | inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32406 | { 32407 | const bool b0_string = is_generally_string_node(branch[0]); 32408 | const bool b1_string = is_generally_string_node(branch[1]); 32409 | 32410 | return (b0_string && b1_string && valid_string_operation(operation)); 32411 | } 32412 | 32413 | inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[3]) const 32414 | { 32415 | const bool b0_string = is_generally_string_node(branch[0]); 32416 | const bool b1_string = is_generally_string_node(branch[1]); 32417 | const bool b2_string = is_generally_string_node(branch[2]); 32418 | 32419 | return (b0_string && b1_string && b2_string && (details::e_inrange == operation)); 32420 | } 32421 | 32422 | #ifndef exprtk_disable_sc_andor 32423 | inline bool is_shortcircuit_expression(const details::operator_type& operation) const 32424 | { 32425 | return ( 32426 | (details::e_scand == operation) || 32427 | (details::e_scor == operation) 32428 | ); 32429 | } 32430 | #else 32431 | inline bool is_shortcircuit_expression(const details::operator_type&) const 32432 | { 32433 | return false; 32434 | } 32435 | #endif 32436 | 32437 | inline bool is_null_present(expression_node_ptr (&branch)[2]) const 32438 | { 32439 | return ( 32440 | details::is_null_node(branch[0]) || 32441 | details::is_null_node(branch[1]) 32442 | ); 32443 | } 32444 | 32445 | inline bool is_vector_eqineq_logic_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32446 | { 32447 | if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1])) 32448 | return false; 32449 | else 32450 | return ( 32451 | (details::e_lt == operation) || 32452 | (details::e_lte == operation) || 32453 | (details::e_gt == operation) || 32454 | (details::e_gte == operation) || 32455 | (details::e_eq == operation) || 32456 | (details::e_ne == operation) || 32457 | (details::e_equal == operation) || 32458 | (details::e_and == operation) || 32459 | (details::e_nand == operation) || 32460 | (details::e_or == operation) || 32461 | (details::e_nor == operation) || 32462 | (details::e_xor == operation) || 32463 | (details::e_xnor == operation) 32464 | ); 32465 | } 32466 | 32467 | inline bool is_vector_arithmetic_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32468 | { 32469 | if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1])) 32470 | return false; 32471 | else 32472 | return ( 32473 | (details::e_add == operation) || 32474 | (details::e_sub == operation) || 32475 | (details::e_mul == operation) || 32476 | (details::e_div == operation) || 32477 | (details::e_pow == operation) 32478 | ); 32479 | } 32480 | 32481 | inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[2]) 32482 | { 32483 | if ((0 == branch[0]) || (0 == branch[1])) 32484 | { 32485 | parser_->set_error(parser_error::make_error( 32486 | parser_error::e_syntax, 32487 | parser_->current_state().token, 32488 | "ERR249 - Invalid branches received for operator '" + details::to_str(operation) + "'", 32489 | exprtk_error_location)); 32490 | 32491 | return error_node(); 32492 | } 32493 | else if (is_invalid_string_op(operation,branch)) 32494 | { 32495 | parser_->set_error(parser_error::make_error( 32496 | parser_error::e_syntax, 32497 | parser_->current_state().token, 32498 | "ERR250 - Invalid branch pair for string operator '" + details::to_str(operation) + "'", 32499 | exprtk_error_location)); 32500 | 32501 | return error_node(); 32502 | } 32503 | else if (is_invalid_assignment_op(operation,branch)) 32504 | { 32505 | parser_->set_error(parser_error::make_error( 32506 | parser_error::e_syntax, 32507 | parser_->current_state().token, 32508 | "ERR251 - Invalid branch pair for assignment operator '" + details::to_str(operation) + "'", 32509 | exprtk_error_location)); 32510 | 32511 | return error_node(); 32512 | } 32513 | else if (is_invalid_break_continue_op(branch)) 32514 | { 32515 | parser_->set_error(parser_error::make_error( 32516 | parser_error::e_syntax, 32517 | parser_->current_state().token, 32518 | "ERR252 - Invalid branch pair for break/continue operator '" + details::to_str(operation) + "'", 32519 | exprtk_error_location)); 32520 | 32521 | return error_node(); 32522 | } 32523 | else if (details::e_assign == operation) 32524 | { 32525 | return synthesize_assignment_expression(operation, branch); 32526 | } 32527 | else if (details::e_swap == operation) 32528 | { 32529 | return synthesize_swap_expression(branch); 32530 | } 32531 | else if (is_assignment_operation(operation)) 32532 | { 32533 | return synthesize_assignment_operation_expression(operation, branch); 32534 | } 32535 | else if (is_vector_eqineq_logic_operation(operation, branch)) 32536 | { 32537 | return synthesize_veceqineqlogic_operation_expression(operation, branch); 32538 | } 32539 | else if (is_vector_arithmetic_operation(operation, branch)) 32540 | { 32541 | return synthesize_vecarithmetic_operation_expression(operation, branch); 32542 | } 32543 | else if (is_shortcircuit_expression(operation)) 32544 | { 32545 | return synthesize_shortcircuit_expression(operation, branch); 32546 | } 32547 | else if (is_string_operation(operation, branch)) 32548 | { 32549 | return synthesize_string_expression(operation, branch); 32550 | } 32551 | else if (is_null_present(branch)) 32552 | { 32553 | return synthesize_null_expression(operation, branch); 32554 | } 32555 | #ifndef exprtk_disable_cardinal_pow_optimisation 32556 | else if (is_constpow_operation(operation, branch)) 32557 | { 32558 | return cardinal_pow_optimisation(branch); 32559 | } 32560 | #endif 32561 | 32562 | expression_node_ptr result = error_node(); 32563 | 32564 | #ifndef exprtk_disable_enhanced_features 32565 | if (synthesize_expression(operation, branch, result)) 32566 | { 32567 | return result; 32568 | } 32569 | else 32570 | #endif 32571 | 32572 | { 32573 | /* 32574 | Possible reductions: 32575 | 1. c o cob -> cob 32576 | 2. cob o c -> cob 32577 | 3. c o boc -> boc 32578 | 4. boc o c -> boc 32579 | */ 32580 | result = error_node(); 32581 | 32582 | if (cocob_optimisable(operation, branch)) 32583 | { 32584 | result = synthesize_cocob_expression::process((*this), operation, branch); 32585 | } 32586 | else if (coboc_optimisable(operation, branch) && (0 == result)) 32587 | { 32588 | result = synthesize_coboc_expression::process((*this), operation, branch); 32589 | } 32590 | 32591 | if (result) 32592 | return result; 32593 | } 32594 | 32595 | if (uvouv_optimisable(operation, branch)) 32596 | { 32597 | return synthesize_uvouv_expression(operation, branch); 32598 | } 32599 | else if (vob_optimisable(operation, branch)) 32600 | { 32601 | return synthesize_vob_expression::process((*this), operation, branch); 32602 | } 32603 | else if (bov_optimisable(operation, branch)) 32604 | { 32605 | return synthesize_bov_expression::process((*this), operation, branch); 32606 | } 32607 | else if (cob_optimisable(operation, branch)) 32608 | { 32609 | return synthesize_cob_expression::process((*this), operation, branch); 32610 | } 32611 | else if (boc_optimisable(operation, branch)) 32612 | { 32613 | return synthesize_boc_expression::process((*this), operation, branch); 32614 | } 32615 | #ifndef exprtk_disable_enhanced_features 32616 | else if (cov_optimisable(operation, branch)) 32617 | { 32618 | return synthesize_cov_expression::process((*this), operation, branch); 32619 | } 32620 | #endif 32621 | else if (binext_optimisable(operation, branch)) 32622 | { 32623 | return synthesize_binary_ext_expression::process((*this), operation, branch); 32624 | } 32625 | else 32626 | return synthesize_expression<binary_node_t,2>(operation, branch); 32627 | } 32628 | 32629 | inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[3]) 32630 | { 32631 | if ( 32632 | (0 == branch[0]) || 32633 | (0 == branch[1]) || 32634 | (0 == branch[2]) 32635 | ) 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 | "ERR253 - Invalid branches operator '" + details::to_str(operation) + "'", 32643 | exprtk_error_location)); 32644 | 32645 | return error_node(); 32646 | } 32647 | else if (is_invalid_string_op(operation, branch)) 32648 | { 32649 | parser_->set_error(parser_error::make_error( 32650 | parser_error::e_syntax, 32651 | parser_->current_state().token, 32652 | "ERR254 - Invalid branches for string operator '" + details::to_str(operation) + "'", 32653 | exprtk_error_location)); 32654 | 32655 | return error_node(); 32656 | } 32657 | else if (is_string_operation(operation, branch)) 32658 | { 32659 | return synthesize_string_expression(operation, branch); 32660 | } 32661 | else 32662 | return synthesize_expression<trinary_node_t,3>(operation, branch); 32663 | } 32664 | 32665 | inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[4]) 32666 | { 32667 | return synthesize_expression<quaternary_node_t,4>(operation,branch); 32668 | } 32669 | 32670 | inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr b0) 32671 | { 32672 | expression_node_ptr branch[1] = { b0 }; 32673 | return (*this)(operation,branch); 32674 | } 32675 | 32676 | inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr& b0, expression_node_ptr& b1) 32677 | { 32678 | expression_node_ptr result = error_node(); 32679 | 32680 | if ((0 != b0) && (0 != b1)) 32681 | { 32682 | expression_node_ptr branch[2] = { b0, b1 }; 32683 | result = expression_generator<Type>::operator()(operation, branch); 32684 | b0 = branch[0]; 32685 | b1 = branch[1]; 32686 | } 32687 | 32688 | return result; 32689 | } 32690 | 32691 | inline expression_node_ptr conditional(expression_node_ptr condition, 32692 | expression_node_ptr consequent, 32693 | expression_node_ptr alternative) const 32694 | { 32695 | if ((0 == condition) || (0 == consequent)) 32696 | { 32697 | details::free_node(*node_allocator_, condition ); 32698 | details::free_node(*node_allocator_, consequent ); 32699 | details::free_node(*node_allocator_, alternative); 32700 | 32701 | const std::string invalid_branches = 32702 | ((0 == condition ) ? std::string("condition ") : "") + 32703 | ((0 == consequent) ? std::string("consequent") : "") ; 32704 | 32705 | parser_->set_error(parser_error::make_error( 32706 | parser_error::e_parser, 32707 | parser_->current_state().token, 32708 | "ERR255 - Invalid " + invalid_branches + " for conditional statement", 32709 | exprtk_error_location)); 32710 | 32711 | return error_node(); 32712 | } 32713 | // Can the condition be immediately evaluated? if so optimise. 32714 | else if (details::is_constant_node(condition)) 32715 | { 32716 | // True branch 32717 | if (details::is_true(condition)) 32718 | { 32719 | details::free_node(*node_allocator_, condition ); 32720 | details::free_node(*node_allocator_, alternative); 32721 | 32722 | return consequent; 32723 | } 32724 | // False branch 32725 | else 32726 | { 32727 | details::free_node(*node_allocator_, condition ); 32728 | details::free_node(*node_allocator_, consequent); 32729 | 32730 | if (alternative) 32731 | return alternative; 32732 | else 32733 | return node_allocator_->allocate<details::null_node<T> >(); 32734 | } 32735 | } 32736 | 32737 | expression_node_ptr result = error_node(); 32738 | std::string node_name = "Unknown!" 32739 | 32740 | if ((0 != consequent) && (0 != alternative)) 32741 | { 32742 | result = node_allocator_->allocate<conditional_node_t>(condition, consequent, alternative); 32743 | node_name = "conditional_node_t" 32744 | } 32745 | else 32746 | { 32747 | result = node_allocator_->allocate<cons_conditional_node_t>(condition, consequent); 32748 | node_name = "cons_conditional_node_t" 32749 | } 32750 | 32751 | if (result && result->valid()) 32752 | { 32753 | return result; 32754 | } 32755 | 32756 | parser_->set_error(parser_error::make_error( 32757 | parser_error::e_parser, 32758 | token_t(), 32759 | "ERR256 - Failed to synthesize node: " + node_name, 32760 | exprtk_error_location)); 32761 | 32762 | details::free_node(*node_allocator_, result); 32763 | return error_node(); 32764 | } 32765 | 32766 | #ifndef exprtk_disable_string_capabilities 32767 | inline expression_node_ptr conditional_string(expression_node_ptr condition, 32768 | expression_node_ptr consequent, 32769 | expression_node_ptr alternative) const 32770 | { 32771 | if ((0 == condition) || (0 == consequent)) 32772 | { 32773 | details::free_node(*node_allocator_, condition ); 32774 | details::free_node(*node_allocator_, consequent ); 32775 | details::free_node(*node_allocator_, alternative); 32776 | 32777 | const std::string invalid_branches = 32778 | ((0 == condition ) ? std::string("condition ") : "") + 32779 | ((0 == consequent) ? std::string("consequent") : "") ; 32780 | 32781 | parser_->set_error(parser_error::make_error( 32782 | parser_error::e_parser, 32783 | parser_->current_state().token, 32784 | "ERR257 - Invalid " + invalid_branches + " for string conditional statement", 32785 | exprtk_error_location)); 32786 | 32787 | return error_node(); 32788 | } 32789 | // Can the condition be immediately evaluated? if so optimise. 32790 | else if (details::is_constant_node(condition)) 32791 | { 32792 | // True branch 32793 | if (details::is_true(condition)) 32794 | { 32795 | details::free_node(*node_allocator_, condition ); 32796 | details::free_node(*node_allocator_, alternative); 32797 | 32798 | return consequent; 32799 | } 32800 | // False branch 32801 | else 32802 | { 32803 | details::free_node(*node_allocator_, condition ); 32804 | details::free_node(*node_allocator_, consequent); 32805 | 32806 | if (alternative) 32807 | return alternative; 32808 | else 32809 | return node_allocator_-> 32810 | allocate_c<details::string_literal_node<Type> >(""); 32811 | } 32812 | } 32813 | else if ((0 != consequent) && (0 != alternative)) 32814 | { 32815 | expression_node_ptr result = 32816 | node_allocator_->allocate<conditional_string_node_t>(condition, consequent, alternative); 32817 | 32818 | if (result && result->valid()) 32819 | { 32820 | return result; 32821 | } 32822 | 32823 | parser_->set_error(parser_error::make_error( 32824 | parser_error::e_parser, 32825 | token_t(), 32826 | "ERR258 - Failed to synthesize node: conditional_string_node_t", 32827 | exprtk_error_location)); 32828 | 32829 | details::free_node(*node_allocator_, result); 32830 | } 32831 | 32832 | return error_node(); 32833 | } 32834 | #else 32835 | inline expression_node_ptr conditional_string(expression_node_ptr, 32836 | expression_node_ptr, 32837 | expression_node_ptr) const 32838 | { 32839 | return error_node(); 32840 | } 32841 | #endif 32842 | 32843 | inline expression_node_ptr conditional_vector(expression_node_ptr condition, 32844 | expression_node_ptr consequent, 32845 | expression_node_ptr alternative) const 32846 | { 32847 | if ((0 == condition) || (0 == consequent)) 32848 | { 32849 | details::free_node(*node_allocator_, condition ); 32850 | details::free_node(*node_allocator_, consequent ); 32851 | details::free_node(*node_allocator_, alternative); 32852 | 32853 | const std::string invalid_branches = 32854 | ((0 == condition ) ? std::string("condition ") : "") + 32855 | ((0 == consequent) ? std::string("consequent") : "") ; 32856 | 32857 | parser_->set_error(parser_error::make_error( 32858 | parser_error::e_parser, 32859 | parser_->current_state().token, 32860 | "ERR259 - Invalid " + invalid_branches + " for vector conditional statement", 32861 | exprtk_error_location)); 32862 | 32863 | return error_node(); 32864 | } 32865 | // Can the condition be immediately evaluated? if so optimise. 32866 | else if (details::is_constant_node(condition)) 32867 | { 32868 | // True branch 32869 | if (details::is_true(condition)) 32870 | { 32871 | details::free_node(*node_allocator_, condition ); 32872 | details::free_node(*node_allocator_, alternative); 32873 | 32874 | return consequent; 32875 | } 32876 | // False branch 32877 | else 32878 | { 32879 | details::free_node(*node_allocator_, condition ); 32880 | details::free_node(*node_allocator_, consequent); 32881 | 32882 | if (alternative) 32883 | return alternative; 32884 | else 32885 | return node_allocator_->allocate<details::null_node<T> >(); 32886 | 32887 | } 32888 | } 32889 | else if ((0 != consequent) && (0 != alternative)) 32890 | { 32891 | return node_allocator_-> 32892 | allocate<conditional_vector_node_t>(condition, consequent, alternative); 32893 | } 32894 | else 32895 | return error_node(); 32896 | } 32897 | 32898 | inline loop_runtime_check_ptr get_loop_runtime_check(const loop_runtime_check::loop_types loop_type) const 32899 | { 32900 | if ( 32901 | parser_->loop_runtime_check_ && 32902 | (loop_type == (parser_->loop_runtime_check_->loop_set & loop_type)) 32903 | ) 32904 | { 32905 | return parser_->loop_runtime_check_; 32906 | } 32907 | 32908 | return loop_runtime_check_ptr(0); 32909 | } 32910 | 32911 | inline vector_access_runtime_check_ptr get_vector_access_runtime_check() const 32912 | { 32913 | return parser_->vector_access_runtime_check_; 32914 | } 32915 | 32916 | inline expression_node_ptr while_loop(expression_node_ptr& condition, 32917 | expression_node_ptr& branch, 32918 | const bool break_continue_present = false) const 32919 | { 32920 | if ( 32921 | !break_continue_present && 32922 | !parser_->state_.return_stmt_present && 32923 | details::is_constant_node(condition) 32924 | ) 32925 | { 32926 | expression_node_ptr result = error_node(); 32927 | if (details::is_true(condition)) 32928 | { 32929 | // Infinite loops are not allowed. 32930 | 32931 | parser_->set_error(parser_error::make_error( 32932 | parser_error::e_parser, 32933 | parser_->current_state().token, 32934 | "ERR260 - Infinite loop condition without 'break' or 'return' not allowed in while-loops", 32935 | exprtk_error_location)); 32936 | 32937 | result = error_node(); 32938 | } 32939 | else 32940 | result = node_allocator_->allocate<details::null_node<Type> >(); 32941 | 32942 | details::free_node(*node_allocator_, condition); 32943 | details::free_node(*node_allocator_, branch ); 32944 | 32945 | return result; 32946 | } 32947 | else if (details::is_null_node(condition)) 32948 | { 32949 | details::free_node(*node_allocator_,condition); 32950 | 32951 | return branch; 32952 | } 32953 | 32954 | loop_runtime_check_ptr rtc = get_loop_runtime_check(loop_runtime_check::e_while_loop); 32955 | 32956 | if (!break_continue_present) 32957 | { 32958 | if (rtc) 32959 | return node_allocator_->allocate<while_loop_rtc_node_t> 32960 | (condition, branch, rtc); 32961 | else 32962 | return node_allocator_->allocate<while_loop_node_t> 32963 | (condition, branch); 32964 | } 32965 | #ifndef exprtk_disable_break_continue 32966 | else 32967 | { 32968 | if (rtc) 32969 | return node_allocator_->allocate<while_loop_bc_rtc_node_t> 32970 | (condition, branch, rtc); 32971 | else 32972 | return node_allocator_->allocate<while_loop_bc_node_t> 32973 | (condition, branch); 32974 | } 32975 | #else 32976 | return error_node(); 32977 | #endif 32978 | } 32979 | 32980 | inline expression_node_ptr repeat_until_loop(expression_node_ptr& condition, 32981 | expression_node_ptr& branch, 32982 | const bool break_continue_present = false) const 32983 | { 32984 | if (!break_continue_present && details::is_constant_node(condition)) 32985 | { 32986 | if ( 32987 | details::is_true(condition) && 32988 | details::is_constant_node(branch) 32989 | ) 32990 | { 32991 | free_node(*node_allocator_,condition); 32992 | 32993 | return branch; 32994 | } 32995 | 32996 | details::free_node(*node_allocator_, condition); 32997 | details::free_node(*node_allocator_, branch ); 32998 | 32999 | return error_node(); 33000 | } 33001 | else if (details::is_null_node(condition)) 33002 | { 33003 | details::free_node(*node_allocator_,condition); 33004 | 33005 | return branch; 33006 | } 33007 | 33008 | loop_runtime_check_ptr rtc = get_loop_runtime_check(loop_runtime_check::e_repeat_until_loop); 33009 | 33010 | if (!break_continue_present) 33011 | { 33012 | if (rtc) 33013 | return node_allocator_->allocate<repeat_until_loop_rtc_node_t> 33014 | (condition, branch, rtc); 33015 | else 33016 | return node_allocator_->allocate<repeat_until_loop_node_t> 33017 | (condition, branch); 33018 | } 33019 | #ifndef exprtk_disable_break_continue 33020 | else 33021 | { 33022 | if (rtc) 33023 | return node_allocator_->allocate<repeat_until_loop_bc_rtc_node_t> 33024 | (condition, branch, rtc); 33025 | else 33026 | return node_allocator_->allocate<repeat_until_loop_bc_node_t> 33027 | (condition, branch); 33028 | } 33029 | #else 33030 | return error_node(); 33031 | #endif 33032 | } 33033 | 33034 | inline expression_node_ptr for_loop(expression_node_ptr& initialiser, 33035 | expression_node_ptr& condition, 33036 | expression_node_ptr& incrementor, 33037 | expression_node_ptr& loop_body, 33038 | bool break_continue_present = false) const 33039 | { 33040 | if ( 33041 | !break_continue_present && 33042 | !parser_->state_.return_stmt_present && 33043 | details::is_constant_node(condition) 33044 | ) 33045 | { 33046 | expression_node_ptr result = error_node(); 33047 | 33048 | if (details::is_true(condition)) 33049 | { 33050 | // Infinite loops are not allowed. 33051 | 33052 | parser_->set_error(parser_error::make_error( 33053 | parser_error::e_parser, 33054 | parser_->current_state().token, 33055 | "ERR261 - Infinite loop condition without 'break' or 'return' not allowed in for-loop", 33056 | exprtk_error_location)); 33057 | 33058 | result = error_node(); 33059 | } 33060 | else 33061 | result = node_allocator_->allocate<details::null_node<Type> >(); 33062 | 33063 | details::free_node(*node_allocator_, initialiser); 33064 | details::free_node(*node_allocator_, condition ); 33065 | details::free_node(*node_allocator_, incrementor); 33066 | details::free_node(*node_allocator_, loop_body ); 33067 | 33068 | return result; 33069 | } 33070 | else if (details::is_null_node(condition) || (0 == condition)) 33071 | { 33072 | details::free_node(*node_allocator_, initialiser); 33073 | details::free_node(*node_allocator_, condition ); 33074 | details::free_node(*node_allocator_, incrementor); 33075 | 33076 | return loop_body; 33077 | } 33078 | 33079 | loop_runtime_check_ptr rtc = get_loop_runtime_check(loop_runtime_check::e_for_loop); 33080 | 33081 | if (!break_continue_present) 33082 | { 33083 | if (rtc) 33084 | return node_allocator_->allocate<for_loop_rtc_node_t> 33085 | ( 33086 | initialiser, 33087 | condition, 33088 | incrementor, 33089 | loop_body, 33090 | rtc 33091 | ); 33092 | else 33093 | return node_allocator_->allocate<for_loop_node_t> 33094 | ( 33095 | initialiser, 33096 | condition, 33097 | incrementor, 33098 | loop_body 33099 | ); 33100 | } 33101 | #ifndef exprtk_disable_break_continue 33102 | else 33103 | { 33104 | if (rtc) 33105 | return node_allocator_->allocate<for_loop_bc_rtc_node_t> 33106 | ( 33107 | initialiser, 33108 | condition, 33109 | incrementor, 33110 | loop_body, 33111 | rtc 33112 | ); 33113 | else 33114 | return node_allocator_->allocate<for_loop_bc_node_t> 33115 | ( 33116 | initialiser, 33117 | condition, 33118 | incrementor, 33119 | loop_body 33120 | ); 33121 | } 33122 | #else 33123 | return error_node(); 33124 | #endif 33125 | } 33126 | 33127 | template <typename Allocator, 33128 | template <typename, typename> class Sequence> 33129 | inline expression_node_ptr const_optimise_switch(Sequence<expression_node_ptr,Allocator>& arg_list) 33130 | { 33131 | expression_node_ptr result = error_node(); 33132 | 33133 | for (std::size_t i = 0; i < (arg_list.size() / 2); ++i) 33134 | { 33135 | expression_node_ptr condition = arg_list[(2 * i) ]; 33136 | expression_node_ptr consequent = arg_list[(2 * i) + 1]; 33137 | 33138 | if ((0 == result) && details::is_true(condition)) 33139 | { 33140 | result = consequent; 33141 | break; 33142 | } 33143 | } 33144 | 33145 | if (0 == result) 33146 | { 33147 | result = arg_list.back(); 33148 | } 33149 | 33150 | for (std::size_t i = 0; i < arg_list.size(); ++i) 33151 | { 33152 | expression_node_ptr current_expr = arg_list[i]; 33153 | 33154 | if (current_expr && (current_expr != result)) 33155 | { 33156 | free_node(*node_allocator_,current_expr); 33157 | } 33158 | } 33159 | 33160 | return result; 33161 | } 33162 | 33163 | template <typename Allocator, 33164 | template <typename, typename> class Sequence> 33165 | inline expression_node_ptr const_optimise_mswitch(Sequence<expression_node_ptr,Allocator>& arg_list) 33166 | { 33167 | expression_node_ptr result = error_node(); 33168 | 33169 | for (std::size_t i = 0; i < (arg_list.size() / 2); ++i) 33170 | { 33171 | expression_node_ptr condition = arg_list[(2 * i) ]; 33172 | expression_node_ptr consequent = arg_list[(2 * i) + 1]; 33173 | 33174 | if (details::is_true(condition)) 33175 | { 33176 | result = consequent; 33177 | } 33178 | } 33179 | 33180 | if (0 == result) 33181 | { 33182 | const T zero = T(0); 33183 | result = node_allocator_->allocate<literal_node_t>(zero); 33184 | } 33185 | 33186 | for (std::size_t i = 0; i < arg_list.size(); ++i) 33187 | { 33188 | expression_node_ptr& current_expr = arg_list[i]; 33189 | 33190 | if (current_expr && (current_expr != result)) 33191 | { 33192 | details::free_node(*node_allocator_,current_expr); 33193 | } 33194 | } 33195 | 33196 | return result; 33197 | } 33198 | 33199 | struct switch_nodes 33200 | { 33201 | typedef std::vector<std::pair<expression_node_ptr,bool> > arg_list_t; 33202 | 33203 | #define case_stmt(N) \ 33204 | if (is_true(arg[(2 * N)].first)) { return arg[(2 * N) + 1].first->value(); } \ 33205 | 33206 | struct switch_impl_1 33207 | { 33208 | static inline T process(const arg_list_t& arg) 33209 | { 33210 | case_stmt(0) 33211 | 33212 | assert(arg.size() == ((2 * 1) + 1)); 33213 | 33214 | return arg.back().first->value(); 33215 | } 33216 | }; 33217 | 33218 | struct switch_impl_2 33219 | { 33220 | static inline T process(const arg_list_t& arg) 33221 | { 33222 | case_stmt(0) case_stmt(1) 33223 | 33224 | assert(arg.size() == ((2 * 2) + 1)); 33225 | 33226 | return arg.back().first->value(); 33227 | } 33228 | }; 33229 | 33230 | struct switch_impl_3 33231 | { 33232 | static inline T process(const arg_list_t& arg) 33233 | { 33234 | case_stmt(0) case_stmt(1) 33235 | case_stmt(2) 33236 | 33237 | assert(arg.size() == ((2 * 3) + 1)); 33238 | 33239 | return arg.back().first->value(); 33240 | } 33241 | }; 33242 | 33243 | struct switch_impl_4 33244 | { 33245 | static inline T process(const arg_list_t& arg) 33246 | { 33247 | case_stmt(0) case_stmt(1) 33248 | case_stmt(2) case_stmt(3) 33249 | 33250 | assert(arg.size() == ((2 * 4) + 1)); 33251 | 33252 | return arg.back().first->value(); 33253 | } 33254 | }; 33255 | 33256 | struct switch_impl_5 33257 | { 33258 | static inline T process(const arg_list_t& arg) 33259 | { 33260 | case_stmt(0) case_stmt(1) 33261 | case_stmt(2) case_stmt(3) 33262 | case_stmt(4) 33263 | 33264 | assert(arg.size() == ((2 * 5) + 1)); 33265 | 33266 | return arg.back().first->value(); 33267 | } 33268 | }; 33269 | 33270 | struct switch_impl_6 33271 | { 33272 | static inline T process(const arg_list_t& arg) 33273 | { 33274 | case_stmt(0) case_stmt(1) 33275 | case_stmt(2) case_stmt(3) 33276 | case_stmt(4) case_stmt(5) 33277 | 33278 | assert(arg.size() == ((2 * 6) + 1)); 33279 | 33280 | return arg.back().first->value(); 33281 | } 33282 | }; 33283 | 33284 | struct switch_impl_7 33285 | { 33286 | static inline T process(const arg_list_t& arg) 33287 | { 33288 | case_stmt(0) case_stmt(1) 33289 | case_stmt(2) case_stmt(3) 33290 | case_stmt(4) case_stmt(5) 33291 | case_stmt(6) 33292 | 33293 | assert(arg.size() == ((2 * 7) + 1)); 33294 | 33295 | return arg.back().first->value(); 33296 | } 33297 | }; 33298 | 33299 | #undef case_stmt 33300 | }; 33301 | 33302 | template <typename Allocator, 33303 | template <typename, typename> class Sequence> 33304 | inline expression_node_ptr switch_statement(Sequence<expression_node_ptr,Allocator>& arg_list, const bool default_statement_present) 33305 | { 33306 | if (arg_list.empty()) 33307 | return error_node(); 33308 | else if ( 33309 | !all_nodes_valid(arg_list) || 33310 | (!default_statement_present && (arg_list.size() < 2)) 33311 | ) 33312 | { 33313 | details::free_all_nodes(*node_allocator_,arg_list); 33314 | 33315 | return error_node(); 33316 | } 33317 | else if (is_constant_foldable(arg_list)) 33318 | return const_optimise_switch(arg_list); 33319 | 33320 | switch ((arg_list.size() - 1) / 2) 33321 | { 33322 | #define case_stmt(N) \ 33323 | case N : \ 33324 | return node_allocator_-> \ 33325 | allocate<details::switch_n_node \ 33326 | <Type,typename switch_nodes::switch_impl_##N > >(arg_list); \ 33327 | 33328 | case_stmt(1) 33329 | case_stmt(2) 33330 | case_stmt(3) 33331 | case_stmt(4) 33332 | case_stmt(5) 33333 | case_stmt(6) 33334 | case_stmt(7) 33335 | #undef case_stmt 33336 | 33337 | default : return node_allocator_->allocate<details::switch_node<Type> >(arg_list); 33338 | } 33339 | } 33340 | 33341 | template <typename Allocator, 33342 | template <typename, typename> class Sequence> 33343 | inline expression_node_ptr multi_switch_statement(Sequence<expression_node_ptr,Allocator>& arg_list) 33344 | { 33345 | if (!all_nodes_valid(arg_list)) 33346 | { 33347 | details::free_all_nodes(*node_allocator_,arg_list); 33348 | 33349 | return error_node(); 33350 | } 33351 | else if (is_constant_foldable(arg_list)) 33352 | return const_optimise_mswitch(arg_list); 33353 | else 33354 | return node_allocator_->allocate<details::multi_switch_node<Type> >(arg_list); 33355 | } 33356 | 33357 | inline expression_node_ptr assert_call(expression_node_ptr& assert_condition, 33358 | expression_node_ptr& assert_message, 33359 | const assert_check::assert_context& context) 33360 | { 33361 | typedef details::assert_node<Type> alloc_type; 33362 | 33363 | expression_node_ptr result = node_allocator_->allocate_rrrr<alloc_type> 33364 | (assert_condition, assert_message, parser_->assert_check_, context); 33365 | 33366 | if (result && result->valid()) 33367 | { 33368 | parser_->state_.activate_side_effect("assert_call()"); 33369 | return result; 33370 | } 33371 | 33372 | details::free_node(*node_allocator_, result ); 33373 | details::free_node(*node_allocator_, assert_condition); 33374 | details::free_node(*node_allocator_, assert_message ); 33375 | 33376 | return error_node(); 33377 | } 33378 | 33379 | #define unary_opr_switch_statements \ 33380 | case_stmt(details::e_abs , details::abs_op ) \ 33381 | case_stmt(details::e_acos , details::acos_op ) \ 33382 | case_stmt(details::e_acosh , details::acosh_op) \ 33383 | case_stmt(details::e_asin , details::asin_op ) \ 33384 | case_stmt(details::e_asinh , details::asinh_op) \ 33385 | case_stmt(details::e_atan , details::atan_op ) \ 33386 | case_stmt(details::e_atanh , details::atanh_op) \ 33387 | case_stmt(details::e_ceil , details::ceil_op ) \ 33388 | case_stmt(details::e_cos , details::cos_op ) \ 33389 | case_stmt(details::e_cosh , details::cosh_op ) \ 33390 | case_stmt(details::e_exp , details::exp_op ) \ 33391 | case_stmt(details::e_expm1 , details::expm1_op) \ 33392 | case_stmt(details::e_floor , details::floor_op) \ 33393 | case_stmt(details::e_log , details::log_op ) \ 33394 | case_stmt(details::e_log10 , details::log10_op) \ 33395 | case_stmt(details::e_log2 , details::log2_op ) \ 33396 | case_stmt(details::e_log1p , details::log1p_op) \ 33397 | case_stmt(details::e_neg , details::neg_op ) \ 33398 | case_stmt(details::e_pos , details::pos_op ) \ 33399 | case_stmt(details::e_round , details::round_op) \ 33400 | case_stmt(details::e_sin , details::sin_op ) \ 33401 | case_stmt(details::e_sinc , details::sinc_op ) \ 33402 | case_stmt(details::e_sinh , details::sinh_op ) \ 33403 | case_stmt(details::e_sqrt , details::sqrt_op ) \ 33404 | case_stmt(details::e_tan , details::tan_op ) \ 33405 | case_stmt(details::e_tanh , details::tanh_op ) \ 33406 | case_stmt(details::e_cot , details::cot_op ) \ 33407 | case_stmt(details::e_sec , details::sec_op ) \ 33408 | case_stmt(details::e_csc , details::csc_op ) \ 33409 | case_stmt(details::e_r2d , details::r2d_op ) \ 33410 | case_stmt(details::e_d2r , details::d2r_op ) \ 33411 | case_stmt(details::e_d2g , details::d2g_op ) \ 33412 | case_stmt(details::e_g2d , details::g2d_op ) \ 33413 | case_stmt(details::e_notl , details::notl_op ) \ 33414 | case_stmt(details::e_sgn , details::sgn_op ) \ 33415 | case_stmt(details::e_erf , details::erf_op ) \ 33416 | case_stmt(details::e_erfc , details::erfc_op ) \ 33417 | case_stmt(details::e_ncdf , details::ncdf_op ) \ 33418 | case_stmt(details::e_frac , details::frac_op ) \ 33419 | case_stmt(details::e_trunc , details::trunc_op) \ 33420 | 33421 | inline expression_node_ptr synthesize_uv_expression(const details::operator_type& operation, 33422 | expression_node_ptr (&branch)[1]) 33423 | { 33424 | T& v = static_cast<details::variable_node<T>*>(branch[0])->ref(); 33425 | 33426 | switch (operation) 33427 | { 33428 | #define case_stmt(op0, op1) \ 33429 | case op0 : return node_allocator_-> \ 33430 | allocate<typename details::unary_variable_node<Type,op1<Type> > >(v); \ 33431 | 33432 | unary_opr_switch_statements 33433 | #undef case_stmt 33434 | default : return error_node(); 33435 | } 33436 | } 33437 | 33438 | inline expression_node_ptr synthesize_uvec_expression(const details::operator_type& operation, 33439 | expression_node_ptr (&branch)[1]) 33440 | { 33441 | switch (operation) 33442 | { 33443 | #define case_stmt(op0, op1) \ 33444 | case op0 : return node_allocator_-> \ 33445 | allocate<typename details::unary_vector_node<Type,op1<Type> > > \ 33446 | (operation, branch[0]); \ 33447 | 33448 | unary_opr_switch_statements 33449 | #undef case_stmt 33450 | default : return error_node(); 33451 | } 33452 | } 33453 | 33454 | inline expression_node_ptr synthesize_unary_expression(const details::operator_type& operation, 33455 | expression_node_ptr (&branch)[1]) 33456 | { 33457 | switch (operation) 33458 | { 33459 | #define case_stmt(op0, op1) \ 33460 | case op0 : return node_allocator_-> \ 33461 | allocate<typename details::unary_branch_node<Type,op1<Type> > >(branch[0]); \ 33462 | 33463 | unary_opr_switch_statements 33464 | #undef case_stmt 33465 | default : return error_node(); 33466 | } 33467 | } 33468 | 33469 | inline expression_node_ptr const_optimise_sf3(const details::operator_type& operation, 33470 | expression_node_ptr (&branch)[3]) 33471 | { 33472 | expression_node_ptr temp_node = error_node(); 33473 | 33474 | switch (operation) 33475 | { 33476 | #define case_stmt(op) \ 33477 | case details::e_sf##op : temp_node = node_allocator_-> \ 33478 | allocate<details::sf3_node<Type,details::sf##op##_op<Type> > > \ 33479 | (operation, branch); \ 33480 | break; \ 33481 | 33482 | case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03) 33483 | case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07) 33484 | case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11) 33485 | case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15) 33486 | case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19) 33487 | case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23) 33488 | case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27) 33489 | case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31) 33490 | case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35) 33491 | case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39) 33492 | case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43) 33493 | case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47) 33494 | #undef case_stmt 33495 | default : return error_node(); 33496 | } 33497 | 33498 | assert(temp_node); 33499 | 33500 | const T v = temp_node->value(); 33501 | 33502 | details::free_node(*node_allocator_,temp_node); 33503 | 33504 | return node_allocator_->allocate<literal_node_t>(v); 33505 | } 33506 | 33507 | inline expression_node_ptr varnode_optimise_sf3(const details::operator_type& operation, expression_node_ptr (&branch)[3]) 33508 | { 33509 | typedef details::variable_node<Type>* variable_ptr; 33510 | 33511 | const Type& v0 = static_cast<variable_ptr>(branch[0])->ref(); 33512 | const Type& v1 = static_cast<variable_ptr>(branch[1])->ref(); 33513 | const Type& v2 = static_cast<variable_ptr>(branch[2])->ref(); 33514 | 33515 | switch (operation) 33516 | { 33517 | #define case_stmt(op) \ 33518 | case details::e_sf##op : return node_allocator_-> \ 33519 | allocate_rrr<details::sf3_var_node<Type,details::sf##op##_op<Type> > > \ 33520 | (v0, v1, v2); \ 33521 | 33522 | case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03) 33523 | case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07) 33524 | case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11) 33525 | case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15) 33526 | case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19) 33527 | case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23) 33528 | case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27) 33529 | case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31) 33530 | case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35) 33531 | case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39) 33532 | case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43) 33533 | case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47) 33534 | #undef case_stmt 33535 | default : return error_node(); 33536 | } 33537 | } 33538 | 33539 | inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[3]) 33540 | { 33541 | if (!all_nodes_valid(branch)) 33542 | return error_node(); 33543 | else if (is_constant_foldable(branch)) 33544 | return const_optimise_sf3(operation,branch); 33545 | else if (all_nodes_variables(branch)) 33546 | return varnode_optimise_sf3(operation,branch); 33547 | else 33548 | { 33549 | switch (operation) 33550 | { 33551 | #define case_stmt(op) \ 33552 | case details::e_sf##op : return node_allocator_-> \ 33553 | allocate<details::sf3_node<Type,details::sf##op##_op<Type> > > \ 33554 | (operation, branch); \ 33555 | 33556 | case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03) 33557 | case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07) 33558 | case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11) 33559 | case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15) 33560 | case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19) 33561 | case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23) 33562 | case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27) 33563 | case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31) 33564 | case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35) 33565 | case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39) 33566 | case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43) 33567 | case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47) 33568 | #undef case_stmt 33569 | default : return error_node(); 33570 | } 33571 | } 33572 | } 33573 | 33574 | inline expression_node_ptr const_optimise_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4]) 33575 | { 33576 | expression_node_ptr temp_node = error_node(); 33577 | 33578 | switch (operation) 33579 | { 33580 | #define case_stmt(op) \ 33581 | case details::e_sf##op : temp_node = node_allocator_-> \ 33582 | allocate<details::sf4_node<Type,details::sf##op##_op<Type> > > \ 33583 | (operation, branch); \ 33584 | break; \ 33585 | 33586 | case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51) 33587 | case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55) 33588 | case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59) 33589 | case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63) 33590 | case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67) 33591 | case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71) 33592 | case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75) 33593 | case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79) 33594 | case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83) 33595 | case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87) 33596 | case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91) 33597 | case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95) 33598 | case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99) 33599 | #undef case_stmt 33600 | default : return error_node(); 33601 | } 33602 | 33603 | assert(temp_node); 33604 | 33605 | const T v = temp_node->value(); 33606 | 33607 | details::free_node(*node_allocator_,temp_node); 33608 | 33609 | return node_allocator_->allocate<literal_node_t>(v); 33610 | } 33611 | 33612 | inline expression_node_ptr varnode_optimise_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4]) 33613 | { 33614 | typedef details::variable_node<Type>* variable_ptr; 33615 | 33616 | const Type& v0 = static_cast<variable_ptr>(branch[0])->ref(); 33617 | const Type& v1 = static_cast<variable_ptr>(branch[1])->ref(); 33618 | const Type& v2 = static_cast<variable_ptr>(branch[2])->ref(); 33619 | const Type& v3 = static_cast<variable_ptr>(branch[3])->ref(); 33620 | 33621 | switch (operation) 33622 | { 33623 | #define case_stmt(op) \ 33624 | case details::e_sf##op : return node_allocator_-> \ 33625 | allocate_rrrr<details::sf4_var_node<Type,details::sf##op##_op<Type> > > \ 33626 | (v0, v1, v2, v3); \ 33627 | 33628 | case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51) 33629 | case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55) 33630 | case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59) 33631 | case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63) 33632 | case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67) 33633 | case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71) 33634 | case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75) 33635 | case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79) 33636 | case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83) 33637 | case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87) 33638 | case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91) 33639 | case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95) 33640 | case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99) 33641 | #undef case_stmt 33642 | default : return error_node(); 33643 | } 33644 | } 33645 | 33646 | inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[4]) 33647 | { 33648 | if (!all_nodes_valid(branch)) 33649 | return error_node(); 33650 | else if (is_constant_foldable(branch)) 33651 | return const_optimise_sf4(operation,branch); 33652 | else if (all_nodes_variables(branch)) 33653 | return varnode_optimise_sf4(operation,branch); 33654 | switch (operation) 33655 | { 33656 | #define case_stmt(op) \ 33657 | case details::e_sf##op : return node_allocator_-> \ 33658 | allocate<details::sf4_node<Type,details::sf##op##_op<Type> > > \ 33659 | (operation, branch); \ 33660 | 33661 | case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51) 33662 | case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55) 33663 | case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59) 33664 | case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63) 33665 | case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67) 33666 | case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71) 33667 | case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75) 33668 | case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79) 33669 | case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83) 33670 | case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87) 33671 | case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91) 33672 | case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95) 33673 | case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99) 33674 | #undef case_stmt 33675 | default : return error_node(); 33676 | } 33677 | } 33678 | 33679 | template <typename Allocator, 33680 | template <typename, typename> class Sequence> 33681 | inline expression_node_ptr const_optimise_varargfunc(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list) 33682 | { 33683 | expression_node_ptr temp_node = error_node(); 33684 | 33685 | switch (operation) 33686 | { 33687 | #define case_stmt(op0, op1) \ 33688 | case op0 : temp_node = node_allocator_-> \ 33689 | allocate<details::vararg_node<Type,op1<Type> > > \ 33690 | (arg_list); \ 33691 | break; \ 33692 | 33693 | case_stmt(details::e_sum , details::vararg_add_op ) 33694 | case_stmt(details::e_prod , details::vararg_mul_op ) 33695 | case_stmt(details::e_avg , details::vararg_avg_op ) 33696 | case_stmt(details::e_min , details::vararg_min_op ) 33697 | case_stmt(details::e_max , details::vararg_max_op ) 33698 | case_stmt(details::e_mand , details::vararg_mand_op ) 33699 | case_stmt(details::e_mor , details::vararg_mor_op ) 33700 | case_stmt(details::e_multi , details::vararg_multi_op) 33701 | #undef case_stmt 33702 | default : return error_node(); 33703 | } 33704 | 33705 | const T v = temp_node->value(); 33706 | 33707 | details::free_node(*node_allocator_,temp_node); 33708 | 33709 | return node_allocator_->allocate<literal_node_t>(v); 33710 | } 33711 | 33712 | inline bool special_one_parameter_vararg(const details::operator_type& operation) const 33713 | { 33714 | return ( 33715 | (details::e_sum == operation) || 33716 | (details::e_prod == operation) || 33717 | (details::e_avg == operation) || 33718 | (details::e_min == operation) || 33719 | (details::e_max == operation) 33720 | ); 33721 | } 33722 | 33723 | template <typename Allocator, 33724 | template <typename, typename> class Sequence> 33725 | inline expression_node_ptr varnode_optimise_varargfunc(const details::operator_type& operation, 33726 | Sequence<expression_node_ptr,Allocator>& arg_list) 33727 | { 33728 | switch (operation) 33729 | { 33730 | #define case_stmt(op0, op1) \ 33731 | case op0 : return node_allocator_-> \ 33732 | allocate<details::vararg_varnode<Type,op1<Type> > >(arg_list); \ 33733 | 33734 | case_stmt(details::e_sum , details::vararg_add_op ) 33735 | case_stmt(details::e_prod , details::vararg_mul_op ) 33736 | case_stmt(details::e_avg , details::vararg_avg_op ) 33737 | case_stmt(details::e_min , details::vararg_min_op ) 33738 | case_stmt(details::e_max , details::vararg_max_op ) 33739 | case_stmt(details::e_mand , details::vararg_mand_op ) 33740 | case_stmt(details::e_mor , details::vararg_mor_op ) 33741 | case_stmt(details::e_multi , details::vararg_multi_op) 33742 | #undef case_stmt 33743 | default : return error_node(); 33744 | } 33745 | } 33746 | 33747 | template <typename Allocator, 33748 | template <typename, typename> class Sequence> 33749 | inline expression_node_ptr vectorize_func(const details::operator_type& operation, 33750 | Sequence<expression_node_ptr,Allocator>& arg_list) 33751 | { 33752 | if (1 == arg_list.size()) 33753 | { 33754 | switch (operation) 33755 | { 33756 | #define case_stmt(op0, op1) \ 33757 | case op0 : return node_allocator_-> \ 33758 | allocate<details::vectorize_node<Type,op1<Type> > >(arg_list[0]); \ 33759 | 33760 | case_stmt(details::e_sum , details::vec_add_op) 33761 | case_stmt(details::e_prod , details::vec_mul_op) 33762 | case_stmt(details::e_avg , details::vec_avg_op) 33763 | case_stmt(details::e_min , details::vec_min_op) 33764 | case_stmt(details::e_max , details::vec_max_op) 33765 | #undef case_stmt 33766 | default : return error_node(); 33767 | } 33768 | } 33769 | else 33770 | return error_node(); 33771 | } 33772 | 33773 | template <typename Allocator, 33774 | template <typename, typename> class Sequence> 33775 | inline expression_node_ptr vararg_function(const details::operator_type& operation, 33776 | Sequence<expression_node_ptr,Allocator>& arg_list) 33777 | { 33778 | if (!all_nodes_valid(arg_list)) 33779 | { 33780 | details::free_all_nodes(*node_allocator_,arg_list); 33781 | 33782 | return error_node(); 33783 | } 33784 | else if (is_constant_foldable(arg_list)) 33785 | return const_optimise_varargfunc(operation,arg_list); 33786 | else if ((1 == arg_list.size()) && details::is_ivector_node(arg_list[0])) 33787 | return vectorize_func(operation,arg_list); 33788 | else if ((1 == arg_list.size()) && special_one_parameter_vararg(operation)) 33789 | return arg_list[0]; 33790 | else if (all_nodes_variables(arg_list)) 33791 | return varnode_optimise_varargfunc(operation,arg_list); 33792 | 33793 | #ifndef exprtk_disable_string_capabilities 33794 | if (details::e_smulti == operation) 33795 | { 33796 | expression_node_ptr result = node_allocator_-> 33797 | allocate<details::str_vararg_node<Type,details::vararg_multi_op<Type> > >(arg_list); 33798 | if (result && result->valid()) 33799 | { 33800 | return result; 33801 | } 33802 | 33803 | parser_->set_error(parser_error::make_error( 33804 | parser_error::e_synthesis, 33805 | token_t(), 33806 | "ERR262 - Failed to synthesize node: str_vararg_node<vararg_multi_op>", 33807 | exprtk_error_location)); 33808 | 33809 | details::free_node(*node_allocator_, result); 33810 | } 33811 | else 33812 | #endif 33813 | { 33814 | expression_node_ptr result = error_node(); 33815 | 33816 | switch (operation) 33817 | { 33818 | #define case_stmt(op0, op1) \ 33819 | case op0 : result = node_allocator_-> \ 33820 | allocate<details::vararg_node<Type,op1<Type> > >(arg_list); \ 33821 | break; \ 33822 | 33823 | case_stmt(details::e_sum , details::vararg_add_op ) 33824 | case_stmt(details::e_prod , details::vararg_mul_op ) 33825 | case_stmt(details::e_avg , details::vararg_avg_op ) 33826 | case_stmt(details::e_min , details::vararg_min_op ) 33827 | case_stmt(details::e_max , details::vararg_max_op ) 33828 | case_stmt(details::e_mand , details::vararg_mand_op ) 33829 | case_stmt(details::e_mor , details::vararg_mor_op ) 33830 | case_stmt(details::e_multi , details::vararg_multi_op) 33831 | #undef case_stmt 33832 | default : return error_node(); 33833 | } 33834 | 33835 | if (result && result->valid()) 33836 | { 33837 | return result; 33838 | } 33839 | 33840 | parser_->set_error(parser_error::make_error( 33841 | parser_error::e_synthesis, 33842 | token_t(), 33843 | "ERR263 - Failed to synthesize node: vararg_node", 33844 | exprtk_error_location)); 33845 | 33846 | details::free_node(*node_allocator_, result); 33847 | } 33848 | 33849 | return error_node(); 33850 | } 33851 | 33852 | template <std::size_t N> 33853 | inline expression_node_ptr function(ifunction_t* f, expression_node_ptr (&b)[N]) 33854 | { 33855 | typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t; 33856 | expression_node_ptr result = synthesize_expression<function_N_node_t,N>(f,b); 33857 | 33858 | if (0 == result) 33859 | return error_node(); 33860 | else 33861 | { 33862 | // Can the function call be completely optimised? 33863 | if (details::is_constant_node(result)) 33864 | return result; 33865 | else if (!all_nodes_valid(b)) 33866 | { 33867 | details::free_node(*node_allocator_,result); 33868 | std::fill_n(b, N, reinterpret_cast<expression_node_ptr>(0)); 33869 | 33870 | return error_node(); 33871 | } 33872 | else if (N != f->param_count) 33873 | { 33874 | details::free_node(*node_allocator_,result); 33875 | std::fill_n(b, N, reinterpret_cast<expression_node_ptr>(0)); 33876 | 33877 | return error_node(); 33878 | } 33879 | 33880 | function_N_node_t* func_node_ptr = reinterpret_cast<function_N_node_t*>(result); 33881 | 33882 | if (!func_node_ptr->init_branches(b)) 33883 | { 33884 | details::free_node(*node_allocator_,result); 33885 | std::fill_n(b, N, reinterpret_cast<expression_node_ptr>(0)); 33886 | 33887 | return error_node(); 33888 | } 33889 | 33890 | if (result && result->valid()) 33891 | { 33892 | return result; 33893 | } 33894 | 33895 | parser_->set_error(parser_error::make_error( 33896 | parser_error::e_synthesis, 33897 | token_t(), 33898 | "ERR264 - Failed to synthesize node: function_N_node_t", 33899 | exprtk_error_location)); 33900 | 33901 | details::free_node(*node_allocator_, result); 33902 | return error_node(); 33903 | } 33904 | } 33905 | 33906 | inline expression_node_ptr function(ifunction_t* f) 33907 | { 33908 | typedef typename details::function_N_node<Type,ifunction_t,0> function_N_node_t; 33909 | return node_allocator_->allocate<function_N_node_t>(f); 33910 | } 33911 | 33912 | inline expression_node_ptr vararg_function_call(ivararg_function_t* vaf, 33913 | std::vector<expression_node_ptr>& arg_list) 33914 | { 33915 | if (!all_nodes_valid(arg_list)) 33916 | { 33917 | details::free_all_nodes(*node_allocator_,arg_list); 33918 | 33919 | return error_node(); 33920 | } 33921 | 33922 | typedef details::vararg_function_node<Type,ivararg_function_t> alloc_type; 33923 | 33924 | expression_node_ptr result = node_allocator_->allocate<alloc_type>(vaf,arg_list); 33925 | 33926 | if ( 33927 | !arg_list.empty() && 33928 | !vaf->has_side_effects() && 33929 | is_constant_foldable(arg_list) 33930 | ) 33931 | { 33932 | const Type v = result->value(); 33933 | details::free_node(*node_allocator_,result); 33934 | result = node_allocator_->allocate<literal_node_t>(v); 33935 | } 33936 | 33937 | parser_->state_.activate_side_effect("vararg_function_call()"); 33938 | 33939 | if (result && result->valid()) 33940 | { 33941 | return result; 33942 | } 33943 | 33944 | parser_->set_error(parser_error::make_error( 33945 | parser_error::e_synthesis, 33946 | token_t(), 33947 | "ERR265 - Failed to synthesize node: vararg_function_node<ivararg_function_t>", 33948 | exprtk_error_location)); 33949 | 33950 | details::free_node(*node_allocator_, result); 33951 | return error_node(); 33952 | } 33953 | 33954 | inline expression_node_ptr generic_function_call(igeneric_function_t* gf, 33955 | std::vector<expression_node_ptr>& arg_list, 33956 | const std::size_t& param_seq_index = std::numeric_limits<std::size_t>::max()) 33957 | { 33958 | if (!all_nodes_valid(arg_list)) 33959 | { 33960 | details::free_all_nodes(*node_allocator_,arg_list); 33961 | return error_node(); 33962 | } 33963 | 33964 | typedef details::generic_function_node <Type,igeneric_function_t> alloc_type1; 33965 | typedef details::multimode_genfunction_node<Type,igeneric_function_t> alloc_type2; 33966 | 33967 | const std::size_t no_psi = std::numeric_limits<std::size_t>::max(); 33968 | 33969 | expression_node_ptr result = error_node(); 33970 | std::string node_name = "Unknown" 33971 | 33972 | if (no_psi == param_seq_index) 33973 | { 33974 | result = node_allocator_->allocate<alloc_type1>(arg_list,gf); 33975 | node_name = "generic_function_node<igeneric_function_t>" 33976 | } 33977 | else 33978 | { 33979 | result = node_allocator_->allocate<alloc_type2>(gf, param_seq_index, arg_list); 33980 | node_name = "multimode_genfunction_node<igeneric_function_t>" 33981 | } 33982 | 33983 | alloc_type1* genfunc_node_ptr = static_cast<alloc_type1*>(result); 33984 | 33985 | assert(genfunc_node_ptr); 33986 | 33987 | if ( 33988 | !arg_list.empty() && 33989 | !gf->has_side_effects() && 33990 | parser_->state_.type_check_enabled && 33991 | is_constant_foldable(arg_list) 33992 | ) 33993 | { 33994 | genfunc_node_ptr->init_branches(); 33995 | 33996 | const Type v = result->value(); 33997 | 33998 | details::free_node(*node_allocator_,result); 33999 | 34000 | return node_allocator_->allocate<literal_node_t>(v); 34001 | } 34002 | else if (genfunc_node_ptr->init_branches()) 34003 | { 34004 | if (result && result->valid()) 34005 | { 34006 | parser_->state_.activate_side_effect("generic_function_call()"); 34007 | return result; 34008 | } 34009 | 34010 | parser_->set_error(parser_error::make_error( 34011 | parser_error::e_synthesis, 34012 | token_t(), 34013 | "ERR266 - Failed to synthesize node: " + node_name, 34014 | exprtk_error_location)); 34015 | 34016 | details::free_node(*node_allocator_, result); 34017 | return error_node(); 34018 | } 34019 | else 34020 | { 34021 | details::free_node(*node_allocator_, result); 34022 | details::free_all_nodes(*node_allocator_, arg_list); 34023 | 34024 | return error_node(); 34025 | } 34026 | } 34027 | 34028 | #ifndef exprtk_disable_string_capabilities 34029 | inline expression_node_ptr string_function_call(igeneric_function_t* gf, 34030 | std::vector<expression_node_ptr>& arg_list, 34031 | const std::size_t& param_seq_index = std::numeric_limits<std::size_t>::max()) 34032 | { 34033 | if (!all_nodes_valid(arg_list)) 34034 | { 34035 | details::free_all_nodes(*node_allocator_,arg_list); 34036 | return error_node(); 34037 | } 34038 | 34039 | typedef details::string_function_node <Type,igeneric_function_t> alloc_type1; 34040 | typedef details::multimode_strfunction_node<Type,igeneric_function_t> alloc_type2; 34041 | 34042 | const std::size_t no_psi = std::numeric_limits<std::size_t>::max(); 34043 | 34044 | expression_node_ptr result = error_node(); 34045 | std::string node_name = "Unknown" 34046 | 34047 | if (no_psi == param_seq_index) 34048 | { 34049 | result = node_allocator_->allocate<alloc_type1>(gf,arg_list); 34050 | node_name = "string_function_node<igeneric_function_t>" 34051 | } 34052 | else 34053 | { 34054 | result = node_allocator_->allocate<alloc_type2>(gf, param_seq_index, arg_list); 34055 | node_name = "multimode_strfunction_node<igeneric_function_t>" 34056 | } 34057 | 34058 | alloc_type1* strfunc_node_ptr = static_cast<alloc_type1*>(result); 34059 | 34060 | assert(strfunc_node_ptr); 34061 | 34062 | if ( 34063 | !arg_list.empty() && 34064 | !gf->has_side_effects() && 34065 | is_constant_foldable(arg_list) 34066 | ) 34067 | { 34068 | strfunc_node_ptr->init_branches(); 34069 | 34070 | const Type v = result->value(); 34071 | 34072 | details::free_node(*node_allocator_,result); 34073 | 34074 | return node_allocator_->allocate<literal_node_t>(v); 34075 | } 34076 | else if (strfunc_node_ptr->init_branches()) 34077 | { 34078 | if (result && result->valid()) 34079 | { 34080 | parser_->state_.activate_side_effect("string_function_call()"); 34081 | return result; 34082 | } 34083 | 34084 | parser_->set_error(parser_error::make_error( 34085 | parser_error::e_synthesis, 34086 | token_t(), 34087 | "ERR267 - Failed to synthesize node: " + node_name, 34088 | exprtk_error_location)); 34089 | 34090 | details::free_node(*node_allocator_, result); 34091 | return error_node(); 34092 | } 34093 | else 34094 | { 34095 | details::free_node (*node_allocator_,result ); 34096 | details::free_all_nodes(*node_allocator_,arg_list); 34097 | 34098 | return error_node(); 34099 | } 34100 | } 34101 | #endif 34102 | 34103 | #ifndef exprtk_disable_return_statement 34104 | inline expression_node_ptr return_call(std::vector<expression_node_ptr>& arg_list) 34105 | { 34106 | if (!all_nodes_valid(arg_list)) 34107 | { 34108 | details::free_all_nodes(*node_allocator_,arg_list); 34109 | return error_node(); 34110 | } 34111 | 34112 | typedef details::return_node<Type> alloc_type; 34113 | 34114 | expression_node_ptr result = node_allocator_-> 34115 | allocate_rr<alloc_type>(arg_list,parser_->results_ctx()); 34116 | 34117 | alloc_type* return_node_ptr = static_cast<alloc_type*>(result); 34118 | 34119 | assert(return_node_ptr); 34120 | 34121 | if (return_node_ptr->init_branches()) 34122 | { 34123 | if (result && result->valid()) 34124 | { 34125 | parser_->state_.activate_side_effect("return_call()"); 34126 | return result; 34127 | } 34128 | 34129 | parser_->set_error(parser_error::make_error( 34130 | parser_error::e_synthesis, 34131 | token_t(), 34132 | "ERR268 - Failed to synthesize node: return_node", 34133 | exprtk_error_location)); 34134 | 34135 | details::free_node(*node_allocator_, result); 34136 | return error_node(); 34137 | } 34138 | else 34139 | { 34140 | details::free_node (*node_allocator_, result ); 34141 | details::free_all_nodes(*node_allocator_, arg_list); 34142 | 34143 | return error_node(); 34144 | } 34145 | } 34146 | 34147 | inline expression_node_ptr return_envelope(expression_node_ptr body, 34148 | results_context_t* rc, 34149 | bool*& return_invoked) 34150 | { 34151 | typedef details::return_envelope_node<Type> alloc_type; 34152 | 34153 | expression_node_ptr result = node_allocator_-> 34154 | allocate_cr<alloc_type>(body,(*rc)); 34155 | 34156 | return_invoked = static_cast<alloc_type*>(result)->retinvk_ptr(); 34157 | 34158 | return result; 34159 | } 34160 | #else 34161 | inline expression_node_ptr return_call(std::vector<expression_node_ptr>&) 34162 | { 34163 | return error_node(); 34164 | } 34165 | 34166 | inline expression_node_ptr return_envelope(expression_node_ptr, 34167 | results_context_t*, 34168 | bool*&) 34169 | { 34170 | return error_node(); 34171 | } 34172 | #endif 34173 | 34174 | inline expression_node_ptr vector_element(const std::string& symbol, 34175 | vector_holder_ptr vector_base, 34176 | expression_node_ptr vec_node, 34177 | expression_node_ptr index) 34178 | { 34179 | expression_node_ptr result = error_node(); 34180 | std::string node_name = "Unknown" 34181 | 34182 | if (details::is_constant_node(index)) 34183 | { 34184 | const std::size_t vec_index = static_cast<std::size_t>(details::numeric::to_int64(index->value())); 34185 | 34186 | details::free_node(*node_allocator_,index); 34187 | 34188 | if (vec_index >= vector_base->size()) 34189 | { 34190 | parser_->set_error(parser_error::make_error( 34191 | parser_error::e_parser, 34192 | token_t(), 34193 | "ERR269 - Index of " + details::to_str(vec_index) + " out of range for " 34194 | "vector '" + symbol + "' of size " + details::to_str(vector_base->size()), 34195 | exprtk_error_location)); 34196 | 34197 | details::free_node(*node_allocator_,vec_node); 34198 | 34199 | return error_node(); 34200 | } 34201 | 34202 | if (vector_base->rebaseable()) 34203 | { 34204 | vector_access_runtime_check_ptr rtc = get_vector_access_runtime_check(); 34205 | 34206 | result = (rtc) ? 34207 | node_allocator_->allocate<rebasevector_celem_rtc_node_t>(vec_node, vec_index, vector_base, rtc) : 34208 | node_allocator_->allocate<rebasevector_celem_node_t >(vec_node, vec_index, vector_base ) ; 34209 | 34210 | node_name = (rtc) ? 34211 | "rebasevector_elem_rtc_node_t" : 34212 | "rebasevector_elem_node_t" ; 34213 | 34214 | if (result && result->valid()) 34215 | { 34216 | return result; 34217 | } 34218 | 34219 | parser_->set_error(parser_error::make_error( 34220 | parser_error::e_synthesis, 34221 | token_t(), 34222 | "ERR270 - Failed to synthesize node: " + node_name + " for vector: " + symbol, 34223 | exprtk_error_location)); 34224 | 34225 | details::free_node(*node_allocator_, result); 34226 | return error_node(); 34227 | } 34228 | else if (details::is_ivector_node(vec_node) && !details::is_vector_node(vec_node)) 34229 | { 34230 | vector_access_runtime_check_ptr rtc = get_vector_access_runtime_check(); 34231 | 34232 | result = (rtc) ? 34233 | node_allocator_->allocate<vector_celem_rtc_node_t>(vec_node, vec_index, vector_base, rtc) : 34234 | node_allocator_->allocate<vector_celem_node_t >(vec_node, vec_index, vector_base ) ; 34235 | 34236 | node_name = (rtc) ? 34237 | "vector_elem_rtc_node_t" : 34238 | "vector_elem_node_t" ; 34239 | 34240 | if (result && result->valid()) 34241 | { 34242 | return result; 34243 | } 34244 | 34245 | parser_->set_error(parser_error::make_error( 34246 | parser_error::e_synthesis, 34247 | token_t(), 34248 | "ERR271 - Failed to synthesize node: " + node_name + " for vector: " + symbol, 34249 | exprtk_error_location)); 34250 | 34251 | details::free_node(*node_allocator_, result); 34252 | return error_node(); 34253 | } 34254 | 34255 | const scope_element& se = parser_->sem_.get_element(symbol,vec_index); 34256 | 34257 | if (se.index == vec_index) 34258 | { 34259 | result = se.var_node; 34260 | details::free_node(*node_allocator_,vec_node); 34261 | } 34262 | else 34263 | { 34264 | scope_element nse; 34265 | nse.name = symbol; 34266 | nse.active = true; 34267 | nse.ref_count = 1; 34268 | nse.type = scope_element::e_vecelem; 34269 | nse.index = vec_index; 34270 | nse.depth = parser_->state_.scope_depth; 34271 | nse.data = 0; 34272 | nse.var_node = node_allocator_->allocate<variable_node_t>((*(*vector_base)[vec_index])); 34273 | 34274 | if (!parser_->sem_.add_element(nse)) 34275 | { 34276 | parser_->set_synthesis_error("Failed to add new local vector element to SEM [1]"); 34277 | 34278 | parser_->sem_.free_element(nse); 34279 | 34280 | result = error_node(); 34281 | } 34282 | 34283 | assert(parser_->sem_.total_local_symb_size_bytes() <= parser_->settings().max_total_local_symbol_size_bytes()); 34284 | 34285 | details::free_node(*node_allocator_,vec_node); 34286 | 34287 | exprtk_debug(("vector_element() - INFO - Added new local vector element: %s\n", nse.name.c_str())); 34288 | 34289 | parser_->state_.activate_side_effect("vector_element()"); 34290 | 34291 | result = nse.var_node; 34292 | node_name = "variable_node_t" 34293 | } 34294 | } 34295 | else 34296 | { 34297 | vector_access_runtime_check_ptr rtc = get_vector_access_runtime_check(); 34298 | 34299 | if (vector_base->rebaseable()) 34300 | { 34301 | result = (rtc) ? 34302 | node_allocator_->allocate<rebasevector_elem_rtc_node_t>(vec_node, index, vector_base, rtc) : 34303 | node_allocator_->allocate<rebasevector_elem_node_t >(vec_node, index, vector_base ) ; 34304 | 34305 | node_name = (rtc) ? 34306 | "rebasevector_elem_rtc_node_t" : 34307 | "rebasevector_elem_node_t" ; 34308 | } 34309 | else 34310 | { 34311 | result = rtc ? 34312 | node_allocator_->allocate<vector_elem_rtc_node_t>(vec_node, index, vector_base, rtc) : 34313 | node_allocator_->allocate<vector_elem_node_t >(vec_node, index, vector_base ) ; 34314 | 34315 | node_name = (rtc) ? 34316 | "vector_elem_rtc_node_t" : 34317 | "vector_elem_node_t" ; 34318 | } 34319 | } 34320 | 34321 | if (result && result->valid()) 34322 | { 34323 | return result; 34324 | } 34325 | 34326 | parser_->set_error(parser_error::make_error( 34327 | parser_error::e_synthesis, 34328 | token_t(), 34329 | "ERR272 - Failed to synthesize node: " + node_name, 34330 | exprtk_error_location)); 34331 | 34332 | details::free_node(*node_allocator_, result); 34333 | return error_node(); 34334 | } 34335 | 34336 | private: 34337 | 34338 | template <std::size_t N, typename NodePtr> 34339 | inline bool is_constant_foldable(NodePtr (&b)[N]) const 34340 | { 34341 | for (std::size_t i = 0; i < N; ++i) 34342 | { 34343 | if (0 == b[i]) 34344 | return false; 34345 | else if (!details::is_constant_node(b[i])) 34346 | return false; 34347 | } 34348 | 34349 | return true; 34350 | } 34351 | 34352 | template <typename NodePtr, 34353 | typename Allocator, 34354 | template <typename, typename> class Sequence> 34355 | inline bool is_constant_foldable(const Sequence<NodePtr,Allocator>& b) const 34356 | { 34357 | for (std::size_t i = 0; i < b.size(); ++i) 34358 | { 34359 | if (0 == b[i]) 34360 | return false; 34361 | else if (!details::is_constant_node(b[i])) 34362 | return false; 34363 | } 34364 | 34365 | return true; 34366 | } 34367 | 34368 | void lodge_assignment(symbol_type cst, expression_node_ptr node) 34369 | { 34370 | parser_->state_.activate_side_effect("lodge_assignment()"); 34371 | 34372 | if (!parser_->dec_.collect_assignments()) 34373 | return; 34374 | 34375 | std::string symbol_name; 34376 | 34377 | switch (cst) 34378 | { 34379 | case e_st_variable : symbol_name = parser_->symtab_store_ 34380 | .get_variable_name(node); 34381 | break; 34382 | 34383 | #ifndef exprtk_disable_string_capabilities 34384 | case e_st_string : symbol_name = parser_->symtab_store_ 34385 | .get_stringvar_name(node); 34386 | break; 34387 | #endif 34388 | 34389 | case e_st_vector : { 34390 | typedef details::vector_holder<T> vector_holder_t; 34391 | 34392 | vector_holder_t& vh = static_cast<vector_node_t*>(node)->vec_holder(); 34393 | 34394 | symbol_name = parser_->symtab_store_.get_vector_name(&vh); 34395 | } 34396 | break; 34397 | 34398 | case e_st_vecelem : { 34399 | typedef details::vector_holder<T> vector_holder_t; 34400 | 34401 | vector_holder_t& vh = static_cast<vector_elem_node_t*>(node)->vec_holder(); 34402 | 34403 | symbol_name = parser_->symtab_store_.get_vector_name(&vh); 34404 | 34405 | cst = e_st_vector; 34406 | } 34407 | break; 34408 | 34409 | default : return; 34410 | } 34411 | 34412 | if (!symbol_name.empty()) 34413 | { 34414 | parser_->dec_.add_assignment(symbol_name,cst); 34415 | } 34416 | } 34417 | 34418 | const void* base_ptr(expression_node_ptr node) 34419 | { 34420 | if (node) 34421 | { 34422 | switch (node->type()) 34423 | { 34424 | case details::expression_node<T>::e_variable: 34425 | return reinterpret_cast<const void*>(&static_cast<variable_node_t*>(node)->ref()); 34426 | 34427 | case details::expression_node<T>::e_vecelem: 34428 | return reinterpret_cast<const void*>(&static_cast<vector_elem_node_t*>(node)->ref()); 34429 | 34430 | case details::expression_node<T>::e_veccelem: 34431 | return reinterpret_cast<const void*>(&static_cast<vector_celem_node_t*>(node)->ref()); 34432 | 34433 | case details::expression_node<T>::e_vecelemrtc: 34434 | return reinterpret_cast<const void*>(&static_cast<vector_elem_rtc_node_t*>(node)->ref()); 34435 | 34436 | case details::expression_node<T>::e_veccelemrtc: 34437 | return reinterpret_cast<const void*>(&static_cast<vector_celem_rtc_node_t*>(node)->ref()); 34438 | 34439 | case details::expression_node<T>::e_rbvecelem: 34440 | return reinterpret_cast<const void*>(&static_cast<rebasevector_elem_node_t*>(node)->ref()); 34441 | 34442 | case details::expression_node<T>::e_rbvecelemrtc: 34443 | return reinterpret_cast<const void*>(&static_cast<rebasevector_elem_rtc_node_t*>(node)->ref()); 34444 | 34445 | case details::expression_node<T>::e_rbveccelem: 34446 | return reinterpret_cast<const void*>(&static_cast<rebasevector_celem_node_t*>(node)->ref()); 34447 | 34448 | case details::expression_node<T>::e_rbveccelemrtc: 34449 | return reinterpret_cast<const void*>(&static_cast<rebasevector_celem_rtc_node_t*>(node)->ref()); 34450 | 34451 | case details::expression_node<T>::e_vector: 34452 | return reinterpret_cast<const void*>(static_cast<vector_node_t*>(node)->vec_holder().data()); 34453 | 34454 | #ifndef exprtk_disable_string_capabilities 34455 | case details::expression_node<T>::e_stringvar: 34456 | return reinterpret_cast<const void*>((static_cast<stringvar_node_t*>(node)->base())); 34457 | 34458 | case details::expression_node<T>::e_stringvarrng: 34459 | return reinterpret_cast<const void*>((static_cast<string_range_node_t*>(node)->base())); 34460 | #endif 34461 | default : return reinterpret_cast<const void*>(0); 34462 | } 34463 | } 34464 | 34465 | return reinterpret_cast<const void*>(0); 34466 | } 34467 | 34468 | bool assign_immutable_symbol(expression_node_ptr node) 34469 | { 34470 | interval_t interval; 34471 | const void* baseptr_addr = base_ptr(node); 34472 | 34473 | exprtk_debug(("assign_immutable_symbol - base ptr addr: %p\n", baseptr_addr)); 34474 | 34475 | if (parser_->immutable_memory_map_.in_interval(baseptr_addr,interval)) 34476 | { 34477 | typename immutable_symtok_map_t::iterator itr = parser_->immutable_symtok_map_.find(interval); 34478 | 34479 | if (parser_->immutable_symtok_map_.end() != itr) 34480 | { 34481 | token_t& token = itr->second; 34482 | parser_->set_error(parser_error::make_error( 34483 | parser_error::e_parser, 34484 | token, 34485 | "ERR273 - Symbol '" + token.value + "' cannot be assigned-to as it is immutable.", 34486 | exprtk_error_location)); 34487 | } 34488 | else 34489 | parser_->set_synthesis_error("Unable to assign symbol is immutable."); 34490 | 34491 | return true; 34492 | } 34493 | 34494 | return false; 34495 | } 34496 | 34497 | inline expression_node_ptr synthesize_assignment_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2]) 34498 | { 34499 | if (assign_immutable_symbol(branch[0])) 34500 | { 34501 | return error_node(); 34502 | } 34503 | else if (details::is_variable_node(branch[0])) 34504 | { 34505 | lodge_assignment(e_st_variable,branch[0]); 34506 | return synthesize_expression<assignment_node_t,2>(operation,branch); 34507 | } 34508 | else if (details::is_vector_elem_node(branch[0]) || details::is_vector_celem_node(branch[0])) 34509 | { 34510 | lodge_assignment(e_st_vecelem,branch[0]); 34511 | return synthesize_expression<assignment_vec_elem_node_t, 2>(operation, branch); 34512 | } 34513 | else if (details::is_vector_elem_rtc_node(branch[0]) || details::is_vector_celem_rtc_node(branch[0])) 34514 | { 34515 | lodge_assignment(e_st_vecelem,branch[0]); 34516 | return synthesize_expression<assignment_vec_elem_rtc_node_t, 2>(operation, branch); 34517 | } 34518 | else if (details::is_rebasevector_elem_node(branch[0])) 34519 | { 34520 | lodge_assignment(e_st_vecelem,branch[0]); 34521 | return synthesize_expression<assignment_rebasevec_elem_node_t, 2>(operation, branch); 34522 | } 34523 | else if (details::is_rebasevector_elem_rtc_node(branch[0])) 34524 | { 34525 | lodge_assignment(e_st_vecelem,branch[0]); 34526 | return synthesize_expression<assignment_rebasevec_elem_rtc_node_t, 2>(operation, branch); 34527 | } 34528 | else if (details::is_rebasevector_celem_node(branch[0])) 34529 | { 34530 | lodge_assignment(e_st_vecelem,branch[0]); 34531 | return synthesize_expression<assignment_rebasevec_celem_node_t, 2>(operation, branch); 34532 | } 34533 | #ifndef exprtk_disable_string_capabilities 34534 | else if (details::is_string_node(branch[0])) 34535 | { 34536 | lodge_assignment(e_st_string,branch[0]); 34537 | return synthesize_expression<assignment_string_node_t,2>(operation, branch); 34538 | } 34539 | else if (details::is_string_range_node(branch[0])) 34540 | { 34541 | lodge_assignment(e_st_string,branch[0]); 34542 | return synthesize_expression<assignment_string_range_node_t,2>(operation, branch); 34543 | } 34544 | #endif 34545 | else if (details::is_vector_node(branch[0])) 34546 | { 34547 | lodge_assignment(e_st_vector,branch[0]); 34548 | 34549 | if (details::is_ivector_node(branch[1])) 34550 | return synthesize_expression<assignment_vecvec_node_t,2>(operation, branch); 34551 | else 34552 | return synthesize_expression<assignment_vec_node_t,2>(operation, branch); 34553 | } 34554 | else if (details::is_literal_node(branch[0])) 34555 | { 34556 | parser_->set_error(parser_error::make_error( 34557 | parser_error::e_syntax, 34558 | parser_->current_state().token, 34559 | "ERR274 - Cannot assign value to const variable", 34560 | exprtk_error_location)); 34561 | 34562 | return error_node(); 34563 | } 34564 | else 34565 | { 34566 | parser_->set_error(parser_error::make_error( 34567 | parser_error::e_syntax, 34568 | parser_->current_state().token, 34569 | "ERR275 - Invalid branches for assignment operator '" + details::to_str(operation) + "'", 34570 | exprtk_error_location)); 34571 | 34572 | return error_node(); 34573 | } 34574 | } 34575 | 34576 | inline expression_node_ptr synthesize_assignment_operation_expression(const details::operator_type& operation, 34577 | expression_node_ptr (&branch)[2]) 34578 | { 34579 | if (assign_immutable_symbol(branch[0])) 34580 | { 34581 | return error_node(); 34582 | } 34583 | 34584 | expression_node_ptr result = error_node(); 34585 | std::string node_name = "Unknown" 34586 | 34587 | if (details::is_variable_node(branch[0])) 34588 | { 34589 | lodge_assignment(e_st_variable,branch[0]); 34590 | 34591 | switch (operation) 34592 | { 34593 | #define case_stmt(op0, op1) \ 34594 | case op0 : result = node_allocator_-> \ 34595 | template allocate_rrr<typename details::assignment_op_node<Type,op1<Type> > > \ 34596 | (operation, branch[0], branch[1]); \ 34597 | node_name = "assignment_op_node" \ 34598 | break; \ 34599 | 34600 | case_stmt(details::e_addass , details::add_op) 34601 | case_stmt(details::e_subass , details::sub_op) 34602 | case_stmt(details::e_mulass , details::mul_op) 34603 | case_stmt(details::e_divass , details::div_op) 34604 | case_stmt(details::e_modass , details::mod_op) 34605 | #undef case_stmt 34606 | default : return error_node(); 34607 | } 34608 | } 34609 | else if (details::is_vector_elem_node(branch[0])) 34610 | { 34611 | lodge_assignment(e_st_vecelem,branch[0]); 34612 | 34613 | switch (operation) 34614 | { 34615 | #define case_stmt(op0, op1) \ 34616 | case op0 : result = node_allocator_-> \ 34617 | template allocate_rrr<typename details::assignment_vec_elem_op_node<Type,op1<Type> > > \ 34618 | (operation, branch[0], branch[1]); \ 34619 | node_name = "assignment_vec_elem_op_node" \ 34620 | break; \ 34621 | 34622 | case_stmt(details::e_addass , details::add_op) 34623 | case_stmt(details::e_subass , details::sub_op) 34624 | case_stmt(details::e_mulass , details::mul_op) 34625 | case_stmt(details::e_divass , details::div_op) 34626 | case_stmt(details::e_modass , details::mod_op) 34627 | #undef case_stmt 34628 | default : return error_node(); 34629 | } 34630 | } 34631 | else if (details::is_vector_elem_rtc_node(branch[0])) 34632 | { 34633 | lodge_assignment(e_st_vecelem,branch[0]); 34634 | 34635 | switch (operation) 34636 | { 34637 | #define case_stmt(op0, op1) \ 34638 | case op0 : result = node_allocator_-> \ 34639 | template allocate_rrr<typename details::assignment_vec_elem_op_rtc_node<Type,op1<Type> > > \ 34640 | (operation, branch[0], branch[1]); \ 34641 | node_name = "assignment_vec_elem_op_rtc_node" \ 34642 | break; \ 34643 | 34644 | case_stmt(details::e_addass , details::add_op) 34645 | case_stmt(details::e_subass , details::sub_op) 34646 | case_stmt(details::e_mulass , details::mul_op) 34647 | case_stmt(details::e_divass , details::div_op) 34648 | case_stmt(details::e_modass , details::mod_op) 34649 | #undef case_stmt 34650 | default : return error_node(); 34651 | } 34652 | } 34653 | else if (details::is_vector_celem_rtc_node(branch[0])) 34654 | { 34655 | lodge_assignment(e_st_vecelem,branch[0]); 34656 | 34657 | switch (operation) 34658 | { 34659 | #define case_stmt(op0, op1) \ 34660 | case op0 : result = node_allocator_-> \ 34661 | template allocate_rrr<typename details::assignment_vec_celem_op_rtc_node<Type,op1<Type> > > \ 34662 | (operation, branch[0], branch[1]); \ 34663 | node_name = "assignment_vec_celem_op_rtc_node" \ 34664 | break; \ 34665 | 34666 | case_stmt(details::e_addass , details::add_op) 34667 | case_stmt(details::e_subass , details::sub_op) 34668 | case_stmt(details::e_mulass , details::mul_op) 34669 | case_stmt(details::e_divass , details::div_op) 34670 | case_stmt(details::e_modass , details::mod_op) 34671 | #undef case_stmt 34672 | default : return error_node(); 34673 | } 34674 | } 34675 | else if (details::is_rebasevector_elem_node(branch[0])) 34676 | { 34677 | lodge_assignment(e_st_vecelem,branch[0]); 34678 | 34679 | switch (operation) 34680 | { 34681 | #define case_stmt(op0, op1) \ 34682 | case op0 : result = node_allocator_-> \ 34683 | template allocate_rrr<typename details::assignment_rebasevec_elem_op_node<Type,op1<Type> > > \ 34684 | (operation, branch[0], branch[1]); \ 34685 | node_name = "assignment_rebasevec_elem_op_node" \ 34686 | break; \ 34687 | 34688 | case_stmt(details::e_addass , details::add_op) 34689 | case_stmt(details::e_subass , details::sub_op) 34690 | case_stmt(details::e_mulass , details::mul_op) 34691 | case_stmt(details::e_divass , details::div_op) 34692 | case_stmt(details::e_modass , details::mod_op) 34693 | #undef case_stmt 34694 | default : return error_node(); 34695 | } 34696 | } 34697 | else if (details::is_rebasevector_celem_node(branch[0])) 34698 | { 34699 | lodge_assignment(e_st_vecelem,branch[0]); 34700 | 34701 | switch (operation) 34702 | { 34703 | #define case_stmt(op0, op1) \ 34704 | case op0 : result = node_allocator_-> \ 34705 | template allocate_rrr<typename details::assignment_rebasevec_celem_op_node<Type,op1<Type> > > \ 34706 | (operation, branch[0], branch[1]); \ 34707 | node_name = "assignment_rebasevec_celem_op_node" \ 34708 | break; \ 34709 | 34710 | case_stmt(details::e_addass , details::add_op) 34711 | case_stmt(details::e_subass , details::sub_op) 34712 | case_stmt(details::e_mulass , details::mul_op) 34713 | case_stmt(details::e_divass , details::div_op) 34714 | case_stmt(details::e_modass , details::mod_op) 34715 | #undef case_stmt 34716 | default : return error_node(); 34717 | } 34718 | } 34719 | else if (details::is_rebasevector_elem_rtc_node(branch[0])) 34720 | { 34721 | lodge_assignment(e_st_vecelem,branch[0]); 34722 | 34723 | switch (operation) 34724 | { 34725 | #define case_stmt(op0, op1) \ 34726 | case op0 : result = node_allocator_-> \ 34727 | template allocate_rrr<typename details::assignment_rebasevec_elem_op_rtc_node<Type,op1<Type> > > \ 34728 | (operation, branch[0], branch[1]); \ 34729 | node_name = "assignment_rebasevec_elem_op_rtc_node" \ 34730 | break; \ 34731 | 34732 | case_stmt(details::e_addass , details::add_op) 34733 | case_stmt(details::e_subass , details::sub_op) 34734 | case_stmt(details::e_mulass , details::mul_op) 34735 | case_stmt(details::e_divass , details::div_op) 34736 | case_stmt(details::e_modass , details::mod_op) 34737 | #undef case_stmt 34738 | default : return error_node(); 34739 | } 34740 | } 34741 | else if (details::is_rebasevector_celem_rtc_node(branch[0])) 34742 | { 34743 | lodge_assignment(e_st_vecelem,branch[0]); 34744 | 34745 | switch (operation) 34746 | { 34747 | #define case_stmt(op0, op1) \ 34748 | case op0 : result = node_allocator_-> \ 34749 | template allocate_rrr<typename details::assignment_rebasevec_celem_op_rtc_node<Type,op1<Type> > > \ 34750 | (operation, branch[0], branch[1]); \ 34751 | node_name = "assignment_rebasevec_celem_op_rtc_node" \ 34752 | break; \ 34753 | 34754 | case_stmt(details::e_addass , details::add_op) 34755 | case_stmt(details::e_subass , details::sub_op) 34756 | case_stmt(details::e_mulass , details::mul_op) 34757 | case_stmt(details::e_divass , details::div_op) 34758 | case_stmt(details::e_modass , details::mod_op) 34759 | #undef case_stmt 34760 | default : return error_node(); 34761 | } 34762 | } 34763 | else if (details::is_vector_node(branch[0])) 34764 | { 34765 | lodge_assignment(e_st_vector,branch[0]); 34766 | 34767 | if (details::is_ivector_node(branch[1])) 34768 | { 34769 | switch (operation) 34770 | { 34771 | #define case_stmt(op0, op1) \ 34772 | case op0 : result = node_allocator_-> \ 34773 | template allocate_rrr<typename details::assignment_vecvec_op_node<Type,op1<Type> > > \ 34774 | (operation, branch[0], branch[1]); \ 34775 | node_name = "assignment_rebasevec_celem_op_node" \ 34776 | break; \ 34777 | 34778 | case_stmt(details::e_addass , details::add_op) 34779 | case_stmt(details::e_subass , details::sub_op) 34780 | case_stmt(details::e_mulass , details::mul_op) 34781 | case_stmt(details::e_divass , details::div_op) 34782 | case_stmt(details::e_modass , details::mod_op) 34783 | #undef case_stmt 34784 | default : return error_node(); 34785 | } 34786 | } 34787 | else 34788 | { 34789 | switch (operation) 34790 | { 34791 | #define case_stmt(op0, op1) \ 34792 | case op0 : result = node_allocator_-> \ 34793 | template allocate_rrr<typename details::assignment_vec_op_node<Type,op1<Type> > > \ 34794 | (operation, branch[0], branch[1]); \ 34795 | node_name = "assignment_vec_op_node" \ 34796 | break; \ 34797 | 34798 | case_stmt(details::e_addass , details::add_op) 34799 | case_stmt(details::e_subass , details::sub_op) 34800 | case_stmt(details::e_mulass , details::mul_op) 34801 | case_stmt(details::e_divass , details::div_op) 34802 | case_stmt(details::e_modass , details::mod_op) 34803 | #undef case_stmt 34804 | default : return error_node(); 34805 | } 34806 | } 34807 | } 34808 | #ifndef exprtk_disable_string_capabilities 34809 | else if ( 34810 | (details::e_addass == operation) && 34811 | details::is_string_node(branch[0]) 34812 | ) 34813 | { 34814 | typedef details::assignment_string_node<T,details::asn_addassignment> addass_t; 34815 | 34816 | lodge_assignment(e_st_string,branch[0]); 34817 | 34818 | result = synthesize_expression<addass_t,2>(operation,branch); 34819 | node_name = "assignment_string_node<T,details::asn_addassignment>" 34820 | } 34821 | #endif 34822 | else 34823 | { 34824 | parser_->set_error(parser_error::make_error( 34825 | parser_error::e_syntax, 34826 | parser_->current_state().token, 34827 | "ERR276 - Invalid branches for assignment operator '" + details::to_str(operation) + "'", 34828 | exprtk_error_location)); 34829 | 34830 | return error_node(); 34831 | } 34832 | 34833 | if (result && result->valid()) 34834 | { 34835 | return result; 34836 | } 34837 | 34838 | parser_->set_error(parser_error::make_error( 34839 | parser_error::e_synthesis, 34840 | token_t(), 34841 | "ERR277 - Failed to synthesize node: " + node_name, 34842 | exprtk_error_location)); 34843 | 34844 | details::free_node(*node_allocator_, result); 34845 | return error_node(); 34846 | } 34847 | 34848 | inline expression_node_ptr synthesize_veceqineqlogic_operation_expression(const details::operator_type& operation, 34849 | expression_node_ptr (&branch)[2]) 34850 | { 34851 | const bool is_b0_ivec = details::is_ivector_node(branch[0]); 34852 | const bool is_b1_ivec = details::is_ivector_node(branch[1]); 34853 | 34854 | #define batch_eqineq_logic_case \ 34855 | case_stmt(details::e_lt , details::lt_op ) \ 34856 | case_stmt(details::e_lte , details::lte_op ) \ 34857 | case_stmt(details::e_gt , details::gt_op ) \ 34858 | case_stmt(details::e_gte , details::gte_op ) \ 34859 | case_stmt(details::e_eq , details::eq_op ) \ 34860 | case_stmt(details::e_ne , details::ne_op ) \ 34861 | case_stmt(details::e_equal , details::equal_op) \ 34862 | case_stmt(details::e_and , details::and_op ) \ 34863 | case_stmt(details::e_nand , details::nand_op ) \ 34864 | case_stmt(details::e_or , details::or_op ) \ 34865 | case_stmt(details::e_nor , details::nor_op ) \ 34866 | case_stmt(details::e_xor , details::xor_op ) \ 34867 | case_stmt(details::e_xnor , details::xnor_op ) \ 34868 | 34869 | expression_node_ptr result = error_node(); 34870 | std::string node_name = "Unknown" 34871 | 34872 | if (is_b0_ivec && is_b1_ivec) 34873 | { 34874 | switch (operation) 34875 | { 34876 | #define case_stmt(op0, op1) \ 34877 | case op0 : result = node_allocator_-> \ 34878 | template allocate_rrr<typename details::vec_binop_vecvec_node<Type,op1<Type> > > \ 34879 | (operation, branch[0], branch[1]); \ 34880 | node_name = "vec_binop_vecvec_node" \ 34881 | break; \ 34882 | 34883 | batch_eqineq_logic_case 34884 | #undef case_stmt 34885 | default : return error_node(); 34886 | } 34887 | } 34888 | else if (is_b0_ivec && !is_b1_ivec) 34889 | { 34890 | switch (operation) 34891 | { 34892 | #define case_stmt(op0, op1) \ 34893 | case op0 : result = node_allocator_-> \ 34894 | template allocate_rrr<typename details::vec_binop_vecval_node<Type,op1<Type> > > \ 34895 | (operation, branch[0], branch[1]); \ 34896 | node_name = "vec_binop_vecval_node" \ 34897 | break; \ 34898 | 34899 | batch_eqineq_logic_case 34900 | #undef case_stmt 34901 | default : return error_node(); 34902 | } 34903 | } 34904 | else if (!is_b0_ivec && is_b1_ivec) 34905 | { 34906 | switch (operation) 34907 | { 34908 | #define case_stmt(op0, op1) \ 34909 | case op0 : result = node_allocator_-> \ 34910 | template allocate_rrr<typename details::vec_binop_valvec_node<Type,op1<Type> > > \ 34911 | (operation, branch[0], branch[1]); \ 34912 | node_name = "vec_binop_valvec_node" \ 34913 | break; \ 34914 | 34915 | batch_eqineq_logic_case 34916 | #undef case_stmt 34917 | default : return error_node(); 34918 | } 34919 | } 34920 | else 34921 | return error_node(); 34922 | 34923 | if (result && result->valid()) 34924 | { 34925 | return result; 34926 | } 34927 | 34928 | parser_->set_error(parser_error::make_error( 34929 | parser_error::e_synthesis, 34930 | token_t(), 34931 | "ERR278 - Failed to synthesize node: " + node_name, 34932 | exprtk_error_location)); 34933 | 34934 | details::free_node(*node_allocator_, result); 34935 | return error_node(); 34936 | 34937 | #undef batch_eqineq_logic_case 34938 | } 34939 | 34940 | inline expression_node_ptr synthesize_vecarithmetic_operation_expression(const details::operator_type& operation, 34941 | expression_node_ptr (&branch)[2]) 34942 | { 34943 | const bool is_b0_ivec = details::is_ivector_node(branch[0]); 34944 | const bool is_b1_ivec = details::is_ivector_node(branch[1]); 34945 | 34946 | #define vector_ops \ 34947 | case_stmt(details::e_add , details::add_op) \ 34948 | case_stmt(details::e_sub , details::sub_op) \ 34949 | case_stmt(details::e_mul , details::mul_op) \ 34950 | case_stmt(details::e_div , details::div_op) \ 34951 | case_stmt(details::e_mod , details::mod_op) \ 34952 | 34953 | expression_node_ptr result = error_node(); 34954 | std::string node_name = "Unknown" 34955 | 34956 | if (is_b0_ivec && is_b1_ivec) 34957 | { 34958 | switch (operation) 34959 | { 34960 | #define case_stmt(op0, op1) \ 34961 | case op0 : result = node_allocator_-> \ 34962 | template allocate_rrr<typename details::vec_binop_vecvec_node<Type,op1<Type> > > \ 34963 | (operation, branch[0], branch[1]); \ 34964 | node_name = "vec_binop_vecvec_node" \ 34965 | break; \ 34966 | 34967 | vector_ops 34968 | case_stmt(details::e_pow,details:: pow_op) 34969 | #undef case_stmt 34970 | default : return error_node(); 34971 | } 34972 | } 34973 | else if (is_b0_ivec && !is_b1_ivec) 34974 | { 34975 | switch (operation) 34976 | { 34977 | #define case_stmt(op0, op1) \ 34978 | case op0 : result = node_allocator_-> \ 34979 | template allocate_rrr<typename details::vec_binop_vecval_node<Type,op1<Type> > > \ 34980 | (operation, branch[0], branch[1]); \ 34981 | node_name = "vec_binop_vecval_node(b0ivec,!b1ivec)" \ 34982 | break; \ 34983 | 34984 | vector_ops 34985 | case_stmt(details::e_pow,details:: pow_op) 34986 | #undef case_stmt 34987 | default : return error_node(); 34988 | } 34989 | } 34990 | else if (!is_b0_ivec && is_b1_ivec) 34991 | { 34992 | switch (operation) 34993 | { 34994 | #define case_stmt(op0, op1) \ 34995 | case op0 : result = node_allocator_-> \ 34996 | template allocate_rrr<typename details::vec_binop_valvec_node<Type,op1<Type> > > \ 34997 | (operation, branch[0], branch[1]); \ 34998 | node_name = "vec_binop_vecval_node(!b0ivec,b1ivec)" \ 34999 | break; \ 35000 | 35001 | vector_ops 35002 | #undef case_stmt 35003 | default : return error_node(); 35004 | } 35005 | } 35006 | else 35007 | return error_node(); 35008 | 35009 | if (result && result->valid()) 35010 | { 35011 | return result; 35012 | } 35013 | 35014 | parser_->set_error(parser_error::make_error( 35015 | parser_error::e_synthesis, 35016 | token_t(), 35017 | "ERR279 - Failed to synthesize node: " + node_name, 35018 | exprtk_error_location)); 35019 | 35020 | details::free_node(*node_allocator_, result); 35021 | return error_node(); 35022 | 35023 | #undef vector_ops 35024 | } 35025 | 35026 | inline expression_node_ptr synthesize_swap_expression(expression_node_ptr (&branch)[2]) 35027 | { 35028 | const bool v0_is_ivar = details::is_ivariable_node(branch[0]); 35029 | const bool v1_is_ivar = details::is_ivariable_node(branch[1]); 35030 | 35031 | const bool v0_is_ivec = details::is_ivector_node (branch[0]); 35032 | const bool v1_is_ivec = details::is_ivector_node (branch[1]); 35033 | 35034 | #ifndef exprtk_disable_string_capabilities 35035 | const bool v0_is_str = details::is_generally_string_node(branch[0]); 35036 | const bool v1_is_str = details::is_generally_string_node(branch[1]); 35037 | #endif 35038 | 35039 | expression_node_ptr result = error_node(); 35040 | std::string node_name = "Unknown" 35041 | 35042 | if (v0_is_ivar && v1_is_ivar) 35043 | { 35044 | typedef details::variable_node<T>* variable_node_ptr; 35045 | 35046 | variable_node_ptr v0 = variable_node_ptr(0); 35047 | variable_node_ptr v1 = variable_node_ptr(0); 35048 | 35049 | if ( 35050 | (0 != (v0 = dynamic_cast<variable_node_ptr>(branch[0]))) && 35051 | (0 != (v1 = dynamic_cast<variable_node_ptr>(branch[1]))) 35052 | ) 35053 | { 35054 | result = node_allocator_->allocate<details::swap_node<T> >(v0,v1); 35055 | node_name = "swap_node" 35056 | } 35057 | else 35058 | { 35059 | result = node_allocator_->allocate<details::swap_generic_node<T> >(branch[0],branch[1]); 35060 | node_name = "swap_generic_node" 35061 | } 35062 | } 35063 | else if (v0_is_ivec && v1_is_ivec) 35064 | { 35065 | result = node_allocator_->allocate<details::swap_vecvec_node<T> >(branch[0],branch[1]); 35066 | node_name = "swap_vecvec_node" 35067 | } 35068 | #ifndef exprtk_disable_string_capabilities 35069 | else if (v0_is_str && v1_is_str) 35070 | { 35071 | if (is_string_node(branch[0]) && is_string_node(branch[1])) 35072 | { 35073 | result = node_allocator_->allocate<details::swap_string_node<T> > 35074 | (branch[0], branch[1]); 35075 | node_name = "swap_string_node" 35076 | } 35077 | else 35078 | { 35079 | result = node_allocator_->allocate<details::swap_genstrings_node<T> > 35080 | (branch[0], branch[1]); 35081 | node_name = "swap_genstrings_node" 35082 | } 35083 | } 35084 | #endif 35085 | else 35086 | { 35087 | parser_->set_synthesis_error("Only variables, strings, vectors or vector elements can be swapped"); 35088 | return error_node(); 35089 | } 35090 | 35091 | if (result && result->valid()) 35092 | { 35093 | parser_->state_.activate_side_effect("synthesize_swap_expression()"); 35094 | return result; 35095 | } 35096 | 35097 | parser_->set_error(parser_error::make_error( 35098 | parser_error::e_synthesis, 35099 | token_t(), 35100 | "ERR280 - Failed to synthesize node: " + node_name, 35101 | exprtk_error_location)); 35102 | 35103 | details::free_node(*node_allocator_, result); 35104 | return error_node(); 35105 | } 35106 | 35107 | #ifndef exprtk_disable_sc_andor 35108 | inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2]) 35109 | { 35110 | expression_node_ptr result = error_node(); 35111 | 35112 | if (details::is_constant_node(branch[0])) 35113 | { 35114 | if ( 35115 | (details::e_scand == operation) && 35116 | std::equal_to<T>()(T(0),branch[0]->value()) 35117 | ) 35118 | result = node_allocator_->allocate_c<literal_node_t>(T(0)); 35119 | else if ( 35120 | (details::e_scor == operation) && 35121 | std::not_equal_to<T>()(T(0),branch[0]->value()) 35122 | ) 35123 | result = node_allocator_->allocate_c<literal_node_t>(T(1)); 35124 | } 35125 | 35126 | if (details::is_constant_node(branch[1]) && (0 == result)) 35127 | { 35128 | if ( 35129 | (details::e_scand == operation) && 35130 | std::equal_to<T>()(T(0),branch[1]->value()) 35131 | ) 35132 | result = node_allocator_->allocate_c<literal_node_t>(T(0)); 35133 | else if ( 35134 | (details::e_scor == operation) && 35135 | std::not_equal_to<T>()(T(0),branch[1]->value()) 35136 | ) 35137 | result = node_allocator_->allocate_c<literal_node_t>(T(1)); 35138 | } 35139 | 35140 | if (result) 35141 | { 35142 | details::free_node(*node_allocator_, branch[0]); 35143 | details::free_node(*node_allocator_, branch[1]); 35144 | 35145 | return result; 35146 | } 35147 | else if (details::e_scand == operation) 35148 | { 35149 | return synthesize_expression<scand_node_t,2>(operation, branch); 35150 | } 35151 | else if (details::e_scor == operation) 35152 | { 35153 | return synthesize_expression<scor_node_t,2>(operation, branch); 35154 | } 35155 | else 35156 | return error_node(); 35157 | } 35158 | #else 35159 | inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type&, expression_node_ptr (&)[2]) 35160 | { 35161 | return error_node(); 35162 | } 35163 | #endif 35164 | 35165 | #define basic_opr_switch_statements \ 35166 | case_stmt(details::e_add , details::add_op) \ 35167 | case_stmt(details::e_sub , details::sub_op) \ 35168 | case_stmt(details::e_mul , details::mul_op) \ 35169 | case_stmt(details::e_div , details::div_op) \ 35170 | case_stmt(details::e_mod , details::mod_op) \ 35171 | case_stmt(details::e_pow , details::pow_op) \ 35172 | 35173 | #define extended_opr_switch_statements \ 35174 | case_stmt(details::e_lt , details::lt_op ) \ 35175 | case_stmt(details::e_lte , details::lte_op ) \ 35176 | case_stmt(details::e_gt , details::gt_op ) \ 35177 | case_stmt(details::e_gte , details::gte_op ) \ 35178 | case_stmt(details::e_eq , details::eq_op ) \ 35179 | case_stmt(details::e_ne , details::ne_op ) \ 35180 | case_stmt(details::e_and , details::and_op ) \ 35181 | case_stmt(details::e_nand , details::nand_op) \ 35182 | case_stmt(details::e_or , details::or_op ) \ 35183 | case_stmt(details::e_nor , details::nor_op ) \ 35184 | case_stmt(details::e_xor , details::xor_op ) \ 35185 | case_stmt(details::e_xnor , details::xnor_op) \ 35186 | 35187 | #ifndef exprtk_disable_cardinal_pow_optimisation 35188 | template <typename TType, template <typename, typename> class IPowNode> 35189 | inline expression_node_ptr cardinal_pow_optimisation_impl(const TType& v, const unsigned int& p) 35190 | { 35191 | switch (p) 35192 | { 35193 | #define case_stmt(cp) \ 35194 | case cp : return node_allocator_-> \ 35195 | allocate<IPowNode<T,details::numeric::fast_exp<T,cp> > >(v); \ 35196 | 35197 | case_stmt( 1) case_stmt( 2) case_stmt( 3) case_stmt( 4) 35198 | case_stmt( 5) case_stmt( 6) case_stmt( 7) case_stmt( 8) 35199 | case_stmt( 9) case_stmt(10) case_stmt(11) case_stmt(12) 35200 | case_stmt(13) case_stmt(14) case_stmt(15) case_stmt(16) 35201 | case_stmt(17) case_stmt(18) case_stmt(19) case_stmt(20) 35202 | case_stmt(21) case_stmt(22) case_stmt(23) case_stmt(24) 35203 | case_stmt(25) case_stmt(26) case_stmt(27) case_stmt(28) 35204 | case_stmt(29) case_stmt(30) case_stmt(31) case_stmt(32) 35205 | case_stmt(33) case_stmt(34) case_stmt(35) case_stmt(36) 35206 | case_stmt(37) case_stmt(38) case_stmt(39) case_stmt(40) 35207 | case_stmt(41) case_stmt(42) case_stmt(43) case_stmt(44) 35208 | case_stmt(45) case_stmt(46) case_stmt(47) case_stmt(48) 35209 | case_stmt(49) case_stmt(50) case_stmt(51) case_stmt(52) 35210 | case_stmt(53) case_stmt(54) case_stmt(55) case_stmt(56) 35211 | case_stmt(57) case_stmt(58) case_stmt(59) case_stmt(60) 35212 | #undef case_stmt 35213 | default : return error_node(); 35214 | } 35215 | } 35216 | 35217 | inline expression_node_ptr cardinal_pow_optimisation(const T& v, const T& c) 35218 | { 35219 | const bool not_recipricol = (c >= T(0)); 35220 | const unsigned int p = static_cast<unsigned int>(details::numeric::to_int32(details::numeric::abs(c))); 35221 | 35222 | if (0 == p) 35223 | return node_allocator_->allocate_c<literal_node_t>(T(1)); 35224 | else if (std::equal_to<T>()(T(2),c)) 35225 | { 35226 | return node_allocator_-> 35227 | template allocate_rr<typename details::vov_node<Type,details::mul_op<Type> > >(v,v); 35228 | } 35229 | else 35230 | { 35231 | if (not_recipricol) 35232 | return cardinal_pow_optimisation_impl<T,details::ipow_node>(v,p); 35233 | else 35234 | return cardinal_pow_optimisation_impl<T,details::ipowinv_node>(v,p); 35235 | } 35236 | } 35237 | 35238 | inline bool cardinal_pow_optimisable(const details::operator_type& operation, const T& c) const 35239 | { 35240 | return (details::e_pow == operation) && (details::numeric::abs(c) <= T(60)) && details::numeric::is_integer(c); 35241 | } 35242 | 35243 | inline expression_node_ptr cardinal_pow_optimisation(expression_node_ptr (&branch)[2]) 35244 | { 35245 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 35246 | const bool not_recipricol = (c >= T(0)); 35247 | const unsigned int p = static_cast<unsigned int>(details::numeric::to_int32(details::numeric::abs(c))); 35248 | 35249 | node_allocator_->free(branch[1]); 35250 | 35251 | if (0 == p) 35252 | { 35253 | details::free_all_nodes(*node_allocator_, branch); 35254 | 35255 | return node_allocator_->allocate_c<literal_node_t>(T(1)); 35256 | } 35257 | else if (not_recipricol) 35258 | return cardinal_pow_optimisation_impl<expression_node_ptr,details::bipow_node>(branch[0],p); 35259 | else 35260 | return cardinal_pow_optimisation_impl<expression_node_ptr,details::bipowinv_node>(branch[0],p); 35261 | } 35262 | #else 35263 | inline expression_node_ptr cardinal_pow_optimisation(T&, const T&) 35264 | { 35265 | return error_node(); 35266 | } 35267 | 35268 | inline bool cardinal_pow_optimisable(const details::operator_type&, const T&) 35269 | { 35270 | return false; 35271 | } 35272 | 35273 | inline expression_node_ptr cardinal_pow_optimisation(expression_node_ptr(&)[2]) 35274 | { 35275 | return error_node(); 35276 | } 35277 | #endif 35278 | 35279 | struct synthesize_binary_ext_expression 35280 | { 35281 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 35282 | const details::operator_type& operation, 35283 | expression_node_ptr (&branch)[2]) 35284 | { 35285 | const bool left_neg = is_neg_unary_node(branch[0]); 35286 | const bool right_neg = is_neg_unary_node(branch[1]); 35287 | 35288 | if (left_neg && right_neg) 35289 | { 35290 | if ( 35291 | (details::e_add == operation) || 35292 | (details::e_sub == operation) || 35293 | (details::e_mul == operation) || 35294 | (details::e_div == operation) 35295 | ) 35296 | { 35297 | if ( 35298 | !expr_gen.parser_->simplify_unary_negation_branch(branch[0]) || 35299 | !expr_gen.parser_->simplify_unary_negation_branch(branch[1]) 35300 | ) 35301 | { 35302 | details::free_all_nodes(*expr_gen.node_allocator_,branch); 35303 | 35304 | return error_node(); 35305 | } 35306 | } 35307 | 35308 | switch (operation) 35309 | { 35310 | // -f(x + 1) + -g(y + 1) --> -(f(x + 1) + g(y + 1)) 35311 | case details::e_add : return expr_gen(details::e_neg, 35312 | expr_gen.node_allocator_-> 35313 | template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > > 35314 | (branch[0],branch[1])); 35315 | 35316 | // -f(x + 1) - -g(y + 1) --> g(y + 1) - f(x + 1) 35317 | case details::e_sub : return expr_gen.node_allocator_-> 35318 | template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > > 35319 | (branch[1],branch[0]); 35320 | 35321 | default : break; 35322 | } 35323 | } 35324 | else if (left_neg && !right_neg) 35325 | { 35326 | if ( 35327 | (details::e_add == operation) || 35328 | (details::e_sub == operation) || 35329 | (details::e_mul == operation) || 35330 | (details::e_div == operation) 35331 | ) 35332 | { 35333 | if (!expr_gen.parser_->simplify_unary_negation_branch(branch[0])) 35334 | { 35335 | details::free_all_nodes(*expr_gen.node_allocator_,branch); 35336 | 35337 | return error_node(); 35338 | } 35339 | 35340 | switch (operation) 35341 | { 35342 | // -f(x + 1) + g(y + 1) --> g(y + 1) - f(x + 1) 35343 | case details::e_add : return expr_gen.node_allocator_-> 35344 | template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > > 35345 | (branch[1], branch[0]); 35346 | 35347 | // -f(x + 1) - g(y + 1) --> -(f(x + 1) + g(y + 1)) 35348 | case details::e_sub : return expr_gen(details::e_neg, 35349 | expr_gen.node_allocator_-> 35350 | template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > > 35351 | (branch[0], branch[1])); 35352 | 35353 | // -f(x + 1) * g(y + 1) --> -(f(x + 1) * g(y + 1)) 35354 | case details::e_mul : return expr_gen(details::e_neg, 35355 | expr_gen.node_allocator_-> 35356 | template allocate<typename details::binary_ext_node<Type,details::mul_op<Type> > > 35357 | (branch[0], branch[1])); 35358 | 35359 | // -f(x + 1) / g(y + 1) --> -(f(x + 1) / g(y + 1)) 35360 | case details::e_div : return expr_gen(details::e_neg, 35361 | expr_gen.node_allocator_-> 35362 | template allocate<typename details::binary_ext_node<Type,details::div_op<Type> > > 35363 | (branch[0], branch[1])); 35364 | 35365 | default : return error_node(); 35366 | } 35367 | } 35368 | } 35369 | else if (!left_neg && right_neg) 35370 | { 35371 | if ( 35372 | (details::e_add == operation) || 35373 | (details::e_sub == operation) || 35374 | (details::e_mul == operation) || 35375 | (details::e_div == operation) 35376 | ) 35377 | { 35378 | if (!expr_gen.parser_->simplify_unary_negation_branch(branch[1])) 35379 | { 35380 | details::free_all_nodes(*expr_gen.node_allocator_,branch); 35381 | 35382 | return error_node(); 35383 | } 35384 | 35385 | switch (operation) 35386 | { 35387 | // f(x + 1) + -g(y + 1) --> f(x + 1) - g(y + 1) 35388 | case details::e_add : return expr_gen.node_allocator_-> 35389 | template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > > 35390 | (branch[0], branch[1]); 35391 | 35392 | // f(x + 1) - - g(y + 1) --> f(x + 1) + g(y + 1) 35393 | case details::e_sub : return expr_gen.node_allocator_-> 35394 | template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > > 35395 | (branch[0], branch[1]); 35396 | 35397 | // f(x + 1) * -g(y + 1) --> -(f(x + 1) * g(y + 1)) 35398 | case details::e_mul : return expr_gen(details::e_neg, 35399 | expr_gen.node_allocator_-> 35400 | template allocate<typename details::binary_ext_node<Type,details::mul_op<Type> > > 35401 | (branch[0], branch[1])); 35402 | 35403 | // f(x + 1) / -g(y + 1) --> -(f(x + 1) / g(y + 1)) 35404 | case details::e_div : return expr_gen(details::e_neg, 35405 | expr_gen.node_allocator_-> 35406 | template allocate<typename details::binary_ext_node<Type,details::div_op<Type> > > 35407 | (branch[0], branch[1])); 35408 | 35409 | default : return error_node(); 35410 | } 35411 | } 35412 | } 35413 | 35414 | switch (operation) 35415 | { 35416 | #define case_stmt(op0, op1) \ 35417 | case op0 : return expr_gen.node_allocator_-> \ 35418 | template allocate<typename details::binary_ext_node<Type,op1<Type> > > \ 35419 | (branch[0], branch[1]); \ 35420 | 35421 | basic_opr_switch_statements 35422 | extended_opr_switch_statements 35423 | #undef case_stmt 35424 | default : return error_node(); 35425 | } 35426 | } 35427 | }; 35428 | 35429 | struct synthesize_vob_expression 35430 | { 35431 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 35432 | const details::operator_type& operation, 35433 | expression_node_ptr (&branch)[2]) 35434 | { 35435 | const Type& v = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 35436 | 35437 | #ifndef exprtk_disable_enhanced_features 35438 | if (details::is_sf3ext_node(branch[1])) 35439 | { 35440 | expression_node_ptr result = error_node(); 35441 | 35442 | const bool synthesis_result = 35443 | synthesize_sf4ext_expression::template compile_right<vtype> 35444 | (expr_gen, v, operation, branch[1], result); 35445 | 35446 | if (synthesis_result) 35447 | { 35448 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35449 | return result; 35450 | } 35451 | } 35452 | #endif 35453 | 35454 | if ( 35455 | (details::e_mul == operation) || 35456 | (details::e_div == operation) 35457 | ) 35458 | { 35459 | if (details::is_uv_node(branch[1])) 35460 | { 35461 | typedef details::uv_base_node<Type>* uvbn_ptr_t; 35462 | 35463 | details::operator_type o = static_cast<uvbn_ptr_t>(branch[1])->operation(); 35464 | 35465 | if (details::e_neg == o) 35466 | { 35467 | const Type& v1 = static_cast<uvbn_ptr_t>(branch[1])->v(); 35468 | 35469 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35470 | 35471 | switch (operation) 35472 | { 35473 | case details::e_mul : return expr_gen(details::e_neg, 35474 | expr_gen.node_allocator_-> 35475 | template allocate_rr<typename details:: 35476 | vov_node<Type,details::mul_op<Type> > >(v,v1)); 35477 | 35478 | case details::e_div : return expr_gen(details::e_neg, 35479 | expr_gen.node_allocator_-> 35480 | template allocate_rr<typename details:: 35481 | vov_node<Type,details::div_op<Type> > >(v,v1)); 35482 | 35483 | default : break; 35484 | } 35485 | } 35486 | } 35487 | } 35488 | 35489 | switch (operation) 35490 | { 35491 | #define case_stmt(op0, op1) \ 35492 | case op0 : return expr_gen.node_allocator_-> \ 35493 | template allocate_rc<typename details::vob_node<Type,op1<Type> > > \ 35494 | (v, branch[1]); \ 35495 | 35496 | basic_opr_switch_statements 35497 | extended_opr_switch_statements 35498 | #undef case_stmt 35499 | default : return error_node(); 35500 | } 35501 | } 35502 | }; 35503 | 35504 | struct synthesize_bov_expression 35505 | { 35506 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 35507 | const details::operator_type& operation, 35508 | expression_node_ptr (&branch)[2]) 35509 | { 35510 | const Type& v = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 35511 | 35512 | #ifndef exprtk_disable_enhanced_features 35513 | if (details::is_sf3ext_node(branch[0])) 35514 | { 35515 | expression_node_ptr result = error_node(); 35516 | 35517 | const bool synthesis_result = 35518 | synthesize_sf4ext_expression::template compile_left<vtype> 35519 | (expr_gen, v, operation, branch[0], result); 35520 | 35521 | if (synthesis_result) 35522 | { 35523 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35524 | 35525 | return result; 35526 | } 35527 | } 35528 | #endif 35529 | 35530 | if ( 35531 | (details::e_add == operation) || 35532 | (details::e_sub == operation) || 35533 | (details::e_mul == operation) || 35534 | (details::e_div == operation) 35535 | ) 35536 | { 35537 | if (details::is_uv_node(branch[0])) 35538 | { 35539 | typedef details::uv_base_node<Type>* uvbn_ptr_t; 35540 | 35541 | details::operator_type o = static_cast<uvbn_ptr_t>(branch[0])->operation(); 35542 | 35543 | if (details::e_neg == o) 35544 | { 35545 | const Type& v0 = static_cast<uvbn_ptr_t>(branch[0])->v(); 35546 | 35547 | details::free_node(*expr_gen.node_allocator_,branch[0]); 35548 | 35549 | switch (operation) 35550 | { 35551 | case details::e_add : return expr_gen.node_allocator_-> 35552 | template allocate_rr<typename details:: 35553 | vov_node<Type,details::sub_op<Type> > >(v,v0); 35554 | 35555 | case details::e_sub : return expr_gen(details::e_neg, 35556 | expr_gen.node_allocator_-> 35557 | template allocate_rr<typename details:: 35558 | vov_node<Type,details::add_op<Type> > >(v0,v)); 35559 | 35560 | case details::e_mul : return expr_gen(details::e_neg, 35561 | expr_gen.node_allocator_-> 35562 | template allocate_rr<typename details:: 35563 | vov_node<Type,details::mul_op<Type> > >(v0,v)); 35564 | 35565 | case details::e_div : return expr_gen(details::e_neg, 35566 | expr_gen.node_allocator_-> 35567 | template allocate_rr<typename details:: 35568 | vov_node<Type,details::div_op<Type> > >(v0,v)); 35569 | default : break; 35570 | } 35571 | } 35572 | } 35573 | } 35574 | 35575 | switch (operation) 35576 | { 35577 | #define case_stmt(op0, op1) \ 35578 | case op0 : return expr_gen.node_allocator_-> \ 35579 | template allocate_cr<typename details::bov_node<Type,op1<Type> > > \ 35580 | (branch[0], v); \ 35581 | 35582 | basic_opr_switch_statements 35583 | extended_opr_switch_statements 35584 | #undef case_stmt 35585 | default : return error_node(); 35586 | } 35587 | } 35588 | }; 35589 | 35590 | struct synthesize_cob_expression 35591 | { 35592 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 35593 | const details::operator_type& operation, 35594 | expression_node_ptr (&branch)[2]) 35595 | { 35596 | const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); 35597 | 35598 | details::free_node(*expr_gen.node_allocator_,branch[0]); 35599 | 35600 | if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation)) 35601 | { 35602 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35603 | 35604 | return expr_gen(T(0)); 35605 | } 35606 | else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation)) 35607 | { 35608 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35609 | 35610 | return expr_gen(T(0)); 35611 | } 35612 | else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation)) 35613 | return branch[1]; 35614 | else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation)) 35615 | return branch[1]; 35616 | 35617 | if (details::is_cob_node(branch[1])) 35618 | { 35619 | // Simplify expressions of the form: 35620 | // 1. (1 * (2 * (3 * (4 * (5 * (6 * (7 * (8 * (9 + x))))))))) --> 40320 * (9 + x) 35621 | // 2. (1 + (2 + (3 + (4 + (5 + (6 + (7 + (8 + (9 + x))))))))) --> 45 + x 35622 | if ( 35623 | (details::e_mul == operation) || 35624 | (details::e_add == operation) 35625 | ) 35626 | { 35627 | details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]); 35628 | 35629 | if (operation == cobnode->operation()) 35630 | { 35631 | switch (operation) 35632 | { 35633 | case details::e_add : cobnode->set_c(c + cobnode->c()); break; 35634 | case details::e_mul : cobnode->set_c(c * cobnode->c()); break; 35635 | default : return error_node(); 35636 | } 35637 | 35638 | return cobnode; 35639 | } 35640 | } 35641 | 35642 | if (operation == details::e_mul) 35643 | { 35644 | details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]); 35645 | details::operator_type cob_opr = cobnode->operation(); 35646 | 35647 | if ( 35648 | (details::e_div == cob_opr) || 35649 | (details::e_mul == cob_opr) 35650 | ) 35651 | { 35652 | switch (cob_opr) 35653 | { 35654 | case details::e_div : cobnode->set_c(c * cobnode->c()); break; 35655 | case details::e_mul : cobnode->set_c(cobnode->c() / c); break; 35656 | default : return error_node(); 35657 | } 35658 | 35659 | return cobnode; 35660 | } 35661 | } 35662 | else if (operation == details::e_div) 35663 | { 35664 | details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]); 35665 | details::operator_type cob_opr = cobnode->operation(); 35666 | 35667 | if ( 35668 | (details::e_div == cob_opr) || 35669 | (details::e_mul == cob_opr) 35670 | ) 35671 | { 35672 | details::expression_node<Type>* new_cobnode = error_node(); 35673 | 35674 | switch (cob_opr) 35675 | { 35676 | case details::e_div : new_cobnode = expr_gen.node_allocator_-> 35677 | template allocate_tt<typename details::cob_node<Type,details::mul_op<Type> > > 35678 | (c / cobnode->c(), cobnode->move_branch(0)); 35679 | break; 35680 | 35681 | case details::e_mul : new_cobnode = expr_gen.node_allocator_-> 35682 | template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > > 35683 | (c / cobnode->c(), cobnode->move_branch(0)); 35684 | break; 35685 | 35686 | default : return error_node(); 35687 | } 35688 | 35689 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35690 | 35691 | return new_cobnode; 35692 | } 35693 | } 35694 | } 35695 | #ifndef exprtk_disable_enhanced_features 35696 | else if (details::is_sf3ext_node(branch[1])) 35697 | { 35698 | expression_node_ptr result = error_node(); 35699 | 35700 | const bool synthesis_result = 35701 | synthesize_sf4ext_expression::template compile_right<ctype> 35702 | (expr_gen, c, operation, branch[1], result); 35703 | 35704 | if (synthesis_result) 35705 | { 35706 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35707 | 35708 | return result; 35709 | } 35710 | } 35711 | #endif 35712 | 35713 | switch (operation) 35714 | { 35715 | #define case_stmt(op0, op1) \ 35716 | case op0 : return expr_gen.node_allocator_-> \ 35717 | template allocate_tt<typename details::cob_node<Type,op1<Type> > > \ 35718 | (c, branch[1]); \ 35719 | 35720 | basic_opr_switch_statements 35721 | extended_opr_switch_statements 35722 | #undef case_stmt 35723 | default : return error_node(); 35724 | } 35725 | } 35726 | }; 35727 | 35728 | struct synthesize_boc_expression 35729 | { 35730 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 35731 | const details::operator_type& operation, 35732 | expression_node_ptr (&branch)[2]) 35733 | { 35734 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 35735 | 35736 | details::free_node(*(expr_gen.node_allocator_), branch[1]); 35737 | 35738 | if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation)) 35739 | { 35740 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35741 | 35742 | return expr_gen(T(0)); 35743 | } 35744 | else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation)) 35745 | { 35746 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35747 | 35748 | return expr_gen(std::numeric_limits<T>::quiet_NaN()); 35749 | } 35750 | else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation)) 35751 | return branch[0]; 35752 | else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation)) 35753 | return branch[0]; 35754 | 35755 | if (details::is_boc_node(branch[0])) 35756 | { 35757 | // Simplify expressions of the form: 35758 | // 1. (((((((((x + 9) * 8) * 7) * 6) * 5) * 4) * 3) * 2) * 1) --> (x + 9) * 40320 35759 | // 2. (((((((((x + 9) + 8) + 7) + 6) + 5) + 4) + 3) + 2) + 1) --> x + 45 35760 | if ( 35761 | (details::e_mul == operation) || 35762 | (details::e_add == operation) 35763 | ) 35764 | { 35765 | details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]); 35766 | 35767 | if (operation == bocnode->operation()) 35768 | { 35769 | switch (operation) 35770 | { 35771 | case details::e_add : bocnode->set_c(c + bocnode->c()); break; 35772 | case details::e_mul : bocnode->set_c(c * bocnode->c()); break; 35773 | default : return error_node(); 35774 | } 35775 | 35776 | return bocnode; 35777 | } 35778 | } 35779 | else if (operation == details::e_div) 35780 | { 35781 | details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]); 35782 | details::operator_type boc_opr = bocnode->operation(); 35783 | 35784 | if ( 35785 | (details::e_div == boc_opr) || 35786 | (details::e_mul == boc_opr) 35787 | ) 35788 | { 35789 | switch (boc_opr) 35790 | { 35791 | case details::e_div : bocnode->set_c(c * bocnode->c()); break; 35792 | case details::e_mul : bocnode->set_c(bocnode->c() / c); break; 35793 | default : return error_node(); 35794 | } 35795 | 35796 | return bocnode; 35797 | } 35798 | } 35799 | else if (operation == details::e_pow) 35800 | { 35801 | // (v ^ c0) ^ c1 --> v ^(c0 * c1) 35802 | details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]); 35803 | details::operator_type boc_opr = bocnode->operation(); 35804 | 35805 | if (details::e_pow == boc_opr) 35806 | { 35807 | bocnode->set_c(bocnode->c() * c); 35808 | 35809 | return bocnode; 35810 | } 35811 | } 35812 | } 35813 | 35814 | #ifndef exprtk_disable_enhanced_features 35815 | if (details::is_sf3ext_node(branch[0])) 35816 | { 35817 | expression_node_ptr result = error_node(); 35818 | 35819 | const bool synthesis_result = 35820 | synthesize_sf4ext_expression::template compile_left<ctype> 35821 | (expr_gen, c, operation, branch[0], result); 35822 | 35823 | if (synthesis_result) 35824 | { 35825 | free_node(*expr_gen.node_allocator_, branch[0]); 35826 | 35827 | return result; 35828 | } 35829 | } 35830 | #endif 35831 | 35832 | switch (operation) 35833 | { 35834 | #define case_stmt(op0, op1) \ 35835 | case op0 : return expr_gen.node_allocator_-> \ 35836 | template allocate_cr<typename details::boc_node<Type,op1<Type> > > \ 35837 | (branch[0], c); \ 35838 | 35839 | basic_opr_switch_statements 35840 | extended_opr_switch_statements 35841 | #undef case_stmt 35842 | default : return error_node(); 35843 | } 35844 | } 35845 | }; 35846 | 35847 | struct synthesize_cocob_expression 35848 | { 35849 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 35850 | const details::operator_type& operation, 35851 | expression_node_ptr (&branch)[2]) 35852 | { 35853 | expression_node_ptr result = error_node(); 35854 | 35855 | // (cob) o c --> cob 35856 | if (details::is_cob_node(branch[0])) 35857 | { 35858 | details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[0]); 35859 | 35860 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 35861 | 35862 | if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation)) 35863 | { 35864 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35865 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35866 | 35867 | return expr_gen(T(0)); 35868 | } 35869 | else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation)) 35870 | { 35871 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35872 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35873 | 35874 | return expr_gen(T(std::numeric_limits<T>::quiet_NaN())); 35875 | } 35876 | else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation)) 35877 | { 35878 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35879 | 35880 | return branch[0]; 35881 | } 35882 | else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation)) 35883 | { 35884 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35885 | 35886 | return branch[0]; 35887 | } 35888 | else if (std::equal_to<T>()(T(1),c) && (details::e_div == operation)) 35889 | { 35890 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35891 | 35892 | return branch[0]; 35893 | } 35894 | 35895 | const bool op_addsub = (details::e_add == cobnode->operation()) || 35896 | (details::e_sub == cobnode->operation()) ; 35897 | 35898 | if (op_addsub) 35899 | { 35900 | switch (operation) 35901 | { 35902 | case details::e_add : cobnode->set_c(cobnode->c() + c); break; 35903 | case details::e_sub : cobnode->set_c(cobnode->c() - c); break; 35904 | default : return error_node(); 35905 | } 35906 | 35907 | result = cobnode; 35908 | } 35909 | else if (details::e_mul == cobnode->operation()) 35910 | { 35911 | switch (operation) 35912 | { 35913 | case details::e_mul : cobnode->set_c(cobnode->c() * c); break; 35914 | case details::e_div : cobnode->set_c(cobnode->c() / c); break; 35915 | default : return error_node(); 35916 | } 35917 | 35918 | result = cobnode; 35919 | } 35920 | else if (details::e_div == cobnode->operation()) 35921 | { 35922 | if (details::e_mul == operation) 35923 | { 35924 | cobnode->set_c(cobnode->c() * c); 35925 | result = cobnode; 35926 | } 35927 | else if (details::e_div == operation) 35928 | { 35929 | result = expr_gen.node_allocator_-> 35930 | template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > > 35931 | (cobnode->c() / c, cobnode->move_branch(0)); 35932 | 35933 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35934 | } 35935 | } 35936 | 35937 | if (result) 35938 | { 35939 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35940 | } 35941 | } 35942 | 35943 | // c o (cob) --> cob 35944 | else if (details::is_cob_node(branch[1])) 35945 | { 35946 | details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]); 35947 | 35948 | const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); 35949 | 35950 | if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation)) 35951 | { 35952 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35953 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35954 | 35955 | return expr_gen(T(0)); 35956 | } 35957 | else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation)) 35958 | { 35959 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35960 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35961 | 35962 | return expr_gen(T(0)); 35963 | } 35964 | else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation)) 35965 | { 35966 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35967 | 35968 | return branch[1]; 35969 | } 35970 | else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation)) 35971 | { 35972 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35973 | 35974 | return branch[1]; 35975 | } 35976 | 35977 | if (details::e_add == cobnode->operation()) 35978 | { 35979 | if (details::e_add == operation) 35980 | { 35981 | cobnode->set_c(c + cobnode->c()); 35982 | result = cobnode; 35983 | } 35984 | else if (details::e_sub == operation) 35985 | { 35986 | result = expr_gen.node_allocator_-> 35987 | template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > > 35988 | (c - cobnode->c(), cobnode->move_branch(0)); 35989 | 35990 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35991 | } 35992 | } 35993 | else if (details::e_sub == cobnode->operation()) 35994 | { 35995 | if (details::e_add == operation) 35996 | { 35997 | cobnode->set_c(c + cobnode->c()); 35998 | result = cobnode; 35999 | } 36000 | else if (details::e_sub == operation) 36001 | { 36002 | result = expr_gen.node_allocator_-> 36003 | template allocate_tt<typename details::cob_node<Type,details::add_op<Type> > > 36004 | (c - cobnode->c(), cobnode->move_branch(0)); 36005 | 36006 | details::free_node(*expr_gen.node_allocator_,branch[1]); 36007 | } 36008 | } 36009 | else if (details::e_mul == cobnode->operation()) 36010 | { 36011 | if (details::e_mul == operation) 36012 | { 36013 | cobnode->set_c(c * cobnode->c()); 36014 | result = cobnode; 36015 | } 36016 | else if (details::e_div == operation) 36017 | { 36018 | result = expr_gen.node_allocator_-> 36019 | template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > > 36020 | (c / cobnode->c(), cobnode->move_branch(0)); 36021 | 36022 | details::free_node(*expr_gen.node_allocator_,branch[1]); 36023 | } 36024 | } 36025 | else if (details::e_div == cobnode->operation()) 36026 | { 36027 | if (details::e_mul == operation) 36028 | { 36029 | cobnode->set_c(c * cobnode->c()); 36030 | result = cobnode; 36031 | } 36032 | else if (details::e_div == operation) 36033 | { 36034 | result = expr_gen.node_allocator_-> 36035 | template allocate_tt<typename details::cob_node<Type,details::mul_op<Type> > > 36036 | (c / cobnode->c(), cobnode->move_branch(0)); 36037 | 36038 | details::free_node(*expr_gen.node_allocator_,branch[1]); 36039 | } 36040 | } 36041 | 36042 | if (result) 36043 | { 36044 | details::free_node(*expr_gen.node_allocator_,branch[0]); 36045 | } 36046 | } 36047 | 36048 | return result; 36049 | } 36050 | }; 36051 | 36052 | struct synthesize_coboc_expression 36053 | { 36054 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36055 | const details::operator_type& operation, 36056 | expression_node_ptr (&branch)[2]) 36057 | { 36058 | expression_node_ptr result = error_node(); 36059 | 36060 | // (boc) o c --> boc 36061 | if (details::is_boc_node(branch[0])) 36062 | { 36063 | details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]); 36064 | 36065 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 36066 | 36067 | if (details::e_add == bocnode->operation()) 36068 | { 36069 | switch (operation) 36070 | { 36071 | case details::e_add : bocnode->set_c(bocnode->c() + c); break; 36072 | case details::e_sub : bocnode->set_c(bocnode->c() - c); break; 36073 | default : return error_node(); 36074 | } 36075 | 36076 | result = bocnode; 36077 | } 36078 | else if (details::e_mul == bocnode->operation()) 36079 | { 36080 | switch (operation) 36081 | { 36082 | case details::e_mul : bocnode->set_c(bocnode->c() * c); break; 36083 | case details::e_div : bocnode->set_c(bocnode->c() / c); break; 36084 | default : return error_node(); 36085 | } 36086 | 36087 | result = bocnode; 36088 | } 36089 | else if (details::e_sub == bocnode->operation()) 36090 | { 36091 | if (details::e_add == operation) 36092 | { 36093 | result = expr_gen.node_allocator_-> 36094 | template allocate_tt<typename details::boc_node<Type,details::add_op<Type> > > 36095 | (bocnode->move_branch(0), c - bocnode->c()); 36096 | 36097 | details::free_node(*expr_gen.node_allocator_,branch[0]); 36098 | } 36099 | else if (details::e_sub == operation) 36100 | { 36101 | bocnode->set_c(bocnode->c() + c); 36102 | result = bocnode; 36103 | } 36104 | } 36105 | else if (details::e_div == bocnode->operation()) 36106 | { 36107 | switch (operation) 36108 | { 36109 | case details::e_div : bocnode->set_c(bocnode->c() * c); break; 36110 | case details::e_mul : bocnode->set_c(bocnode->c() / c); break; 36111 | default : return error_node(); 36112 | } 36113 | 36114 | result = bocnode; 36115 | } 36116 | 36117 | if (result) 36118 | { 36119 | details::free_node(*expr_gen.node_allocator_, branch[1]); 36120 | } 36121 | } 36122 | 36123 | // c o (boc) --> boc 36124 | else if (details::is_boc_node(branch[1])) 36125 | { 36126 | details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[1]); 36127 | 36128 | const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); 36129 | 36130 | if (details::e_add == bocnode->operation()) 36131 | { 36132 | if (details::e_add == operation) 36133 | { 36134 | bocnode->set_c(c + bocnode->c()); 36135 | result = bocnode; 36136 | } 36137 | else if (details::e_sub == operation) 36138 | { 36139 | result = expr_gen.node_allocator_-> 36140 | template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > > 36141 | (c - bocnode->c(), bocnode->move_branch(0)); 36142 | 36143 | details::free_node(*expr_gen.node_allocator_,branch[1]); 36144 | } 36145 | } 36146 | else if (details::e_sub == bocnode->operation()) 36147 | { 36148 | if (details::e_add == operation) 36149 | { 36150 | result = expr_gen.node_allocator_-> 36151 | template allocate_tt<typename details::boc_node<Type,details::add_op<Type> > > 36152 | (bocnode->move_branch(0), c - bocnode->c()); 36153 | 36154 | details::free_node(*expr_gen.node_allocator_,branch[1]); 36155 | } 36156 | else if (details::e_sub == operation) 36157 | { 36158 | result = expr_gen.node_allocator_-> 36159 | template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > > 36160 | (c + bocnode->c(), bocnode->move_branch(0)); 36161 | 36162 | details::free_node(*expr_gen.node_allocator_,branch[1]); 36163 | } 36164 | } 36165 | else if (details::e_mul == bocnode->operation()) 36166 | { 36167 | if (details::e_mul == operation) 36168 | { 36169 | bocnode->set_c(c * bocnode->c()); 36170 | result = bocnode; 36171 | } 36172 | else if (details::e_div == operation) 36173 | { 36174 | result = expr_gen.node_allocator_-> 36175 | template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > > 36176 | (c / bocnode->c(), bocnode->move_branch(0)); 36177 | 36178 | details::free_node(*expr_gen.node_allocator_,branch[1]); 36179 | } 36180 | } 36181 | else if (details::e_div == bocnode->operation()) 36182 | { 36183 | if (details::e_mul == operation) 36184 | { 36185 | bocnode->set_c(bocnode->c() / c); 36186 | result = bocnode; 36187 | } 36188 | else if (details::e_div == operation) 36189 | { 36190 | result = expr_gen.node_allocator_-> 36191 | template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > > 36192 | (c * bocnode->c(), bocnode->move_branch(0)); 36193 | 36194 | details::free_node(*expr_gen.node_allocator_,branch[1]); 36195 | } 36196 | } 36197 | 36198 | if (result) 36199 | { 36200 | details::free_node(*expr_gen.node_allocator_,branch[0]); 36201 | } 36202 | } 36203 | 36204 | return result; 36205 | } 36206 | }; 36207 | 36208 | #ifndef exprtk_disable_enhanced_features 36209 | inline bool synthesize_expression(const details::operator_type& operation, 36210 | expression_node_ptr (&branch)[2], 36211 | expression_node_ptr& result) 36212 | { 36213 | result = error_node(); 36214 | 36215 | if (!operation_optimisable(operation)) 36216 | return false; 36217 | 36218 | const std::string node_id = branch_to_id(branch); 36219 | 36220 | const typename synthesize_map_t::iterator itr = synthesize_map_.find(node_id); 36221 | 36222 | if (synthesize_map_.end() != itr) 36223 | { 36224 | result = itr->second((*this), operation, branch); 36225 | 36226 | return true; 36227 | } 36228 | else 36229 | return false; 36230 | } 36231 | 36232 | struct synthesize_vov_expression 36233 | { 36234 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36235 | const details::operator_type& operation, 36236 | expression_node_ptr (&branch)[2]) 36237 | { 36238 | const Type& v1 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 36239 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 36240 | 36241 | switch (operation) 36242 | { 36243 | #define case_stmt(op0, op1) \ 36244 | case op0 : return expr_gen.node_allocator_-> \ 36245 | template allocate_rr<typename details::vov_node<Type,op1<Type> > > \ 36246 | (v1, v2); \ 36247 | 36248 | basic_opr_switch_statements 36249 | extended_opr_switch_statements 36250 | #undef case_stmt 36251 | default : return error_node(); 36252 | } 36253 | } 36254 | }; 36255 | 36256 | struct synthesize_cov_expression 36257 | { 36258 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36259 | const details::operator_type& operation, 36260 | expression_node_ptr (&branch)[2]) 36261 | { 36262 | const Type c = static_cast<details::literal_node<Type>*> (branch[0])->value(); 36263 | const Type& v = static_cast<details::variable_node<Type>*>(branch[1])->ref (); 36264 | 36265 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 36266 | 36267 | if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation)) 36268 | return expr_gen(T(0)); 36269 | else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation)) 36270 | return expr_gen(T(0)); 36271 | else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation)) 36272 | return static_cast<details::variable_node<Type>*>(branch[1]); 36273 | else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation)) 36274 | return static_cast<details::variable_node<Type>*>(branch[1]); 36275 | 36276 | switch (operation) 36277 | { 36278 | #define case_stmt(op0, op1) \ 36279 | case op0 : return expr_gen.node_allocator_-> \ 36280 | template allocate_cr<typename details::cov_node<Type,op1<Type> > > \ 36281 | (c, v); \ 36282 | 36283 | basic_opr_switch_statements 36284 | extended_opr_switch_statements 36285 | #undef case_stmt 36286 | default : return error_node(); 36287 | } 36288 | } 36289 | }; 36290 | 36291 | struct synthesize_voc_expression 36292 | { 36293 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36294 | const details::operator_type& operation, 36295 | expression_node_ptr (&branch)[2]) 36296 | { 36297 | const Type& v = static_cast<details::variable_node<Type>*>(branch[0])->ref (); 36298 | const Type c = static_cast<details::literal_node<Type>*> (branch[1])->value(); 36299 | 36300 | details::free_node(*(expr_gen.node_allocator_), branch[1]); 36301 | 36302 | if (expr_gen.cardinal_pow_optimisable(operation,c)) 36303 | { 36304 | if (std::equal_to<T>()(T(1),c)) 36305 | return branch[0]; 36306 | else 36307 | return expr_gen.cardinal_pow_optimisation(v,c); 36308 | } 36309 | else if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation)) 36310 | return expr_gen(T(0)); 36311 | else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation)) 36312 | return expr_gen(std::numeric_limits<T>::quiet_NaN()); 36313 | else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation)) 36314 | return static_cast<details::variable_node<Type>*>(branch[0]); 36315 | else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation)) 36316 | return static_cast<details::variable_node<Type>*>(branch[0]); 36317 | else if (std::equal_to<T>()(T(1),c) && (details::e_div == operation)) 36318 | return static_cast<details::variable_node<Type>*>(branch[0]); 36319 | 36320 | switch (operation) 36321 | { 36322 | #define case_stmt(op0, op1) \ 36323 | case op0 : return expr_gen.node_allocator_-> \ 36324 | template allocate_rc<typename details::voc_node<Type,op1<Type> > > \ 36325 | (v, c); \ 36326 | 36327 | basic_opr_switch_statements 36328 | extended_opr_switch_statements 36329 | #undef case_stmt 36330 | default : return error_node(); 36331 | } 36332 | } 36333 | }; 36334 | 36335 | struct synthesize_sf3ext_expression 36336 | { 36337 | template <typename T0, typename T1, typename T2> 36338 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36339 | const details::operator_type& sf3opr, 36340 | T0 t0, T1 t1, T2 t2) 36341 | { 36342 | switch (sf3opr) 36343 | { 36344 | #define case_stmt(op) \ 36345 | case details::e_sf##op : return details::T0oT1oT2_sf3ext<T,T0,T1,T2,details::sf##op##_op<Type> >:: \ 36346 | allocate(*(expr_gen.node_allocator_), t0, t1, t2); \ 36347 | 36348 | case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03) 36349 | case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07) 36350 | case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11) 36351 | case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15) 36352 | case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19) 36353 | case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23) 36354 | case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27) 36355 | case_stmt(28) case_stmt(29) case_stmt(30) 36356 | #undef case_stmt 36357 | default : return error_node(); 36358 | } 36359 | } 36360 | 36361 | template <typename T0, typename T1, typename T2> 36362 | static inline bool compile(expression_generator<Type>& expr_gen, const std::string& id, 36363 | T0 t0, T1 t1, T2 t2, 36364 | expression_node_ptr& result) 36365 | { 36366 | details::operator_type sf3opr; 36367 | 36368 | if (!expr_gen.sf3_optimisable(id,sf3opr)) 36369 | return false; 36370 | else 36371 | result = synthesize_sf3ext_expression::template process<T0, T1, T2> 36372 | (expr_gen, sf3opr, t0, t1, t2); 36373 | 36374 | return true; 36375 | } 36376 | }; 36377 | 36378 | struct synthesize_sf4ext_expression 36379 | { 36380 | template <typename T0, typename T1, typename T2, typename T3> 36381 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36382 | const details::operator_type& sf4opr, 36383 | T0 t0, T1 t1, T2 t2, T3 t3) 36384 | { 36385 | switch (sf4opr) 36386 | { 36387 | #define case_stmt0(op) \ 36388 | case details::e_sf##op : return details::T0oT1oT2oT3_sf4ext<Type,T0,T1,T2,T3,details::sf##op##_op<Type> >:: \ 36389 | allocate(*(expr_gen.node_allocator_), t0, t1, t2, t3); \ 36390 | 36391 | #define case_stmt1(op) \ 36392 | case details::e_sf4ext##op : return details::T0oT1oT2oT3_sf4ext<Type,T0,T1,T2,T3,details::sfext##op##_op<Type> >:: \ 36393 | allocate(*(expr_gen.node_allocator_), t0, t1, t2, t3); \ 36394 | 36395 | case_stmt0(48) case_stmt0(49) case_stmt0(50) case_stmt0(51) 36396 | case_stmt0(52) case_stmt0(53) case_stmt0(54) case_stmt0(55) 36397 | case_stmt0(56) case_stmt0(57) case_stmt0(58) case_stmt0(59) 36398 | case_stmt0(60) case_stmt0(61) case_stmt0(62) case_stmt0(63) 36399 | case_stmt0(64) case_stmt0(65) case_stmt0(66) case_stmt0(67) 36400 | case_stmt0(68) case_stmt0(69) case_stmt0(70) case_stmt0(71) 36401 | case_stmt0(72) case_stmt0(73) case_stmt0(74) case_stmt0(75) 36402 | case_stmt0(76) case_stmt0(77) case_stmt0(78) case_stmt0(79) 36403 | case_stmt0(80) case_stmt0(81) case_stmt0(82) case_stmt0(83) 36404 | 36405 | case_stmt1(00) case_stmt1(01) case_stmt1(02) case_stmt1(03) 36406 | case_stmt1(04) case_stmt1(05) case_stmt1(06) case_stmt1(07) 36407 | case_stmt1(08) case_stmt1(09) case_stmt1(10) case_stmt1(11) 36408 | case_stmt1(12) case_stmt1(13) case_stmt1(14) case_stmt1(15) 36409 | case_stmt1(16) case_stmt1(17) case_stmt1(18) case_stmt1(19) 36410 | case_stmt1(20) case_stmt1(21) case_stmt1(22) case_stmt1(23) 36411 | case_stmt1(24) case_stmt1(25) case_stmt1(26) case_stmt1(27) 36412 | case_stmt1(28) case_stmt1(29) case_stmt1(30) case_stmt1(31) 36413 | case_stmt1(32) case_stmt1(33) case_stmt1(34) case_stmt1(35) 36414 | case_stmt1(36) case_stmt1(37) case_stmt1(38) case_stmt1(39) 36415 | case_stmt1(40) case_stmt1(41) case_stmt1(42) case_stmt1(43) 36416 | case_stmt1(44) case_stmt1(45) case_stmt1(46) case_stmt1(47) 36417 | case_stmt1(48) case_stmt1(49) case_stmt1(50) case_stmt1(51) 36418 | case_stmt1(52) case_stmt1(53) case_stmt1(54) case_stmt1(55) 36419 | case_stmt1(56) case_stmt1(57) case_stmt1(58) case_stmt1(59) 36420 | case_stmt1(60) case_stmt1(61) 36421 | 36422 | #undef case_stmt0 36423 | #undef case_stmt1 36424 | default : return error_node(); 36425 | } 36426 | } 36427 | 36428 | template <typename T0, typename T1, typename T2, typename T3> 36429 | static inline bool compile(expression_generator<Type>& expr_gen, const std::string& id, 36430 | T0 t0, T1 t1, T2 t2, T3 t3, 36431 | expression_node_ptr& result) 36432 | { 36433 | details::operator_type sf4opr; 36434 | 36435 | if (!expr_gen.sf4_optimisable(id,sf4opr)) 36436 | return false; 36437 | else 36438 | result = synthesize_sf4ext_expression::template process<T0, T1, T2, T3> 36439 | (expr_gen, sf4opr, t0, t1, t2, t3); 36440 | 36441 | return true; 36442 | } 36443 | 36444 | // T o (sf3ext) 36445 | template <typename ExternalType> 36446 | static inline bool compile_right(expression_generator<Type>& expr_gen, 36447 | ExternalType t, 36448 | const details::operator_type& operation, 36449 | expression_node_ptr& sf3node, 36450 | expression_node_ptr& result) 36451 | { 36452 | if (!details::is_sf3ext_node(sf3node)) 36453 | return false; 36454 | 36455 | typedef details::T0oT1oT2_base_node<Type>* sf3ext_base_ptr; 36456 | 36457 | sf3ext_base_ptr n = static_cast<sf3ext_base_ptr>(sf3node); 36458 | const std::string id = "t" + expr_gen.to_str(operation) + "(" + n->type_id() + ")" 36459 | 36460 | switch (n->type()) 36461 | { 36462 | case details::expression_node<Type>::e_covoc : return compile_right_impl 36463 | <typename covoc_t::sf3_type_node,ExternalType, ctype, vtype, ctype> 36464 | (expr_gen, id, t, sf3node, result); 36465 | 36466 | case details::expression_node<Type>::e_covov : return compile_right_impl 36467 | <typename covov_t::sf3_type_node,ExternalType, ctype, vtype, vtype> 36468 | (expr_gen, id, t, sf3node, result); 36469 | 36470 | case details::expression_node<Type>::e_vocov : return compile_right_impl 36471 | <typename vocov_t::sf3_type_node,ExternalType, vtype, ctype, vtype> 36472 | (expr_gen, id, t, sf3node, result); 36473 | 36474 | case details::expression_node<Type>::e_vovoc : return compile_right_impl 36475 | <typename vovoc_t::sf3_type_node,ExternalType, vtype, vtype, ctype> 36476 | (expr_gen, id, t, sf3node, result); 36477 | 36478 | case details::expression_node<Type>::e_vovov : return compile_right_impl 36479 | <typename vovov_t::sf3_type_node,ExternalType, vtype, vtype, vtype> 36480 | (expr_gen, id, t, sf3node, result); 36481 | 36482 | default : return false; 36483 | } 36484 | } 36485 | 36486 | // (sf3ext) o T 36487 | template <typename ExternalType> 36488 | static inline bool compile_left(expression_generator<Type>& expr_gen, 36489 | ExternalType t, 36490 | const details::operator_type& operation, 36491 | expression_node_ptr& sf3node, 36492 | expression_node_ptr& result) 36493 | { 36494 | if (!details::is_sf3ext_node(sf3node)) 36495 | return false; 36496 | 36497 | typedef details::T0oT1oT2_base_node<Type>* sf3ext_base_ptr; 36498 | 36499 | sf3ext_base_ptr n = static_cast<sf3ext_base_ptr>(sf3node); 36500 | 36501 | const std::string id = "(" + n->type_id() + ")" + expr_gen.to_str(operation) + "t" 36502 | 36503 | switch (n->type()) 36504 | { 36505 | case details::expression_node<Type>::e_covoc : return compile_left_impl 36506 | <typename covoc_t::sf3_type_node,ExternalType, ctype, vtype, ctype> 36507 | (expr_gen, id, t, sf3node, result); 36508 | 36509 | case details::expression_node<Type>::e_covov : return compile_left_impl 36510 | <typename covov_t::sf3_type_node,ExternalType, ctype, vtype, vtype> 36511 | (expr_gen, id, t, sf3node, result); 36512 | 36513 | case details::expression_node<Type>::e_vocov : return compile_left_impl 36514 | <typename vocov_t::sf3_type_node,ExternalType, vtype, ctype, vtype> 36515 | (expr_gen, id, t, sf3node, result); 36516 | 36517 | case details::expression_node<Type>::e_vovoc : return compile_left_impl 36518 | <typename vovoc_t::sf3_type_node,ExternalType, vtype, vtype, ctype> 36519 | (expr_gen, id, t, sf3node, result); 36520 | 36521 | case details::expression_node<Type>::e_vovov : return compile_left_impl 36522 | <typename vovov_t::sf3_type_node,ExternalType, vtype, vtype, vtype> 36523 | (expr_gen, id, t, sf3node, result); 36524 | 36525 | default : return false; 36526 | } 36527 | } 36528 | 36529 | template <typename SF3TypeNode, typename ExternalType, typename T0, typename T1, typename T2> 36530 | static inline bool compile_right_impl(expression_generator<Type>& expr_gen, 36531 | const std::string& id, 36532 | ExternalType t, 36533 | expression_node_ptr& node, 36534 | expression_node_ptr& result) 36535 | { 36536 | SF3TypeNode* n = dynamic_cast<SF3TypeNode*>(node); 36537 | 36538 | if (n) 36539 | { 36540 | T0 t0 = n->t0(); 36541 | T1 t1 = n->t1(); 36542 | T2 t2 = n->t2(); 36543 | 36544 | return synthesize_sf4ext_expression::template compile<ExternalType, T0, T1, T2> 36545 | (expr_gen, id, t, t0, t1, t2, result); 36546 | } 36547 | else 36548 | return false; 36549 | } 36550 | 36551 | template <typename SF3TypeNode, typename ExternalType, typename T0, typename T1, typename T2> 36552 | static inline bool compile_left_impl(expression_generator<Type>& expr_gen, 36553 | const std::string& id, 36554 | ExternalType t, 36555 | expression_node_ptr& node, 36556 | expression_node_ptr& result) 36557 | { 36558 | SF3TypeNode* n = dynamic_cast<SF3TypeNode*>(node); 36559 | 36560 | if (n) 36561 | { 36562 | T0 t0 = n->t0(); 36563 | T1 t1 = n->t1(); 36564 | T2 t2 = n->t2(); 36565 | 36566 | return synthesize_sf4ext_expression::template compile<T0, T1, T2, ExternalType> 36567 | (expr_gen, id, t0, t1, t2, t, result); 36568 | } 36569 | else 36570 | return false; 36571 | } 36572 | }; 36573 | 36574 | struct synthesize_vovov_expression0 36575 | { 36576 | typedef typename vovov_t::type0 node_type; 36577 | typedef typename vovov_t::sf3_type sf3_type; 36578 | 36579 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36580 | const details::operator_type& operation, 36581 | expression_node_ptr (&branch)[2]) 36582 | { 36583 | // (v0 o0 v1) o1 (v2) 36584 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]); 36585 | const Type& v0 = vov->v0(); 36586 | const Type& v1 = vov->v1(); 36587 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 36588 | const details::operator_type o0 = vov->operation(); 36589 | const details::operator_type o1 = operation; 36590 | 36591 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 36592 | 36593 | expression_node_ptr result = error_node(); 36594 | 36595 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36596 | { 36597 | // (v0 / v1) / v2 --> (vovov) v0 / (v1 * v2) 36598 | if ((details::e_div == o0) && (details::e_div == o1)) 36599 | { 36600 | const bool synthesis_result = 36601 | synthesize_sf3ext_expression:: 36602 | template compile<vtype, vtype, vtype>(expr_gen, "t/(t*t)", v0, v1, v2, result); 36603 | 36604 | exprtk_debug(("(v0 / v1) / v2 --> (vovov) v0 / (v1 * v2)\n")); 36605 | 36606 | return (synthesis_result) ? result : error_node(); 36607 | } 36608 | } 36609 | 36610 | const bool synthesis_result = 36611 | synthesize_sf3ext_expression::template compile<vtype, vtype, vtype> 36612 | (expr_gen, id(expr_gen, o0, o1), v0, v1, v2, result); 36613 | 36614 | if (synthesis_result) 36615 | return result; 36616 | 36617 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36618 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36619 | 36620 | if (!expr_gen.valid_operator(o0,f0)) 36621 | return error_node(); 36622 | else if (!expr_gen.valid_operator(o1,f1)) 36623 | return error_node(); 36624 | else 36625 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, f0, f1); 36626 | } 36627 | 36628 | static inline std::string id(expression_generator<Type>& expr_gen, 36629 | const details::operator_type o0, 36630 | const details::operator_type o1) 36631 | { 36632 | return details::build_string() 36633 | << "(t" << expr_gen.to_str(o0) 36634 | << "t)" << expr_gen.to_str(o1) 36635 | << "t" 36636 | } 36637 | }; 36638 | 36639 | struct synthesize_vovov_expression1 36640 | { 36641 | typedef typename vovov_t::type1 node_type; 36642 | typedef typename vovov_t::sf3_type sf3_type; 36643 | 36644 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36645 | const details::operator_type& operation, 36646 | expression_node_ptr (&branch)[2]) 36647 | { 36648 | // (v0) o0 (v1 o1 v2) 36649 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]); 36650 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 36651 | const Type& v1 = vov->v0(); 36652 | const Type& v2 = vov->v1(); 36653 | const details::operator_type o0 = operation; 36654 | const details::operator_type o1 = vov->operation(); 36655 | 36656 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 36657 | 36658 | expression_node_ptr result = error_node(); 36659 | 36660 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36661 | { 36662 | // v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1 36663 | if ((details::e_div == o0) && (details::e_div == o1)) 36664 | { 36665 | const bool synthesis_result = 36666 | synthesize_sf3ext_expression:: 36667 | template compile<vtype, vtype, vtype>(expr_gen, "(t*t)/t", v0, v2, v1, result); 36668 | 36669 | exprtk_debug(("v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1\n")); 36670 | 36671 | return (synthesis_result) ? result : error_node(); 36672 | } 36673 | } 36674 | 36675 | const bool synthesis_result = 36676 | synthesize_sf3ext_expression::template compile<vtype, vtype, vtype> 36677 | (expr_gen, id(expr_gen, o0, o1), v0, v1, v2, result); 36678 | 36679 | if (synthesis_result) 36680 | return result; 36681 | 36682 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36683 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36684 | 36685 | if (!expr_gen.valid_operator(o0,f0)) 36686 | return error_node(); 36687 | else if (!expr_gen.valid_operator(o1,f1)) 36688 | return error_node(); 36689 | else 36690 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, f0, f1); 36691 | } 36692 | 36693 | static inline std::string id(expression_generator<Type>& expr_gen, 36694 | const details::operator_type o0, 36695 | const details::operator_type o1) 36696 | { 36697 | return details::build_string() 36698 | << "t" << expr_gen.to_str(o0) 36699 | << "(t" << expr_gen.to_str(o1) 36700 | << "t)" 36701 | } 36702 | }; 36703 | 36704 | struct synthesize_vovoc_expression0 36705 | { 36706 | typedef typename vovoc_t::type0 node_type; 36707 | typedef typename vovoc_t::sf3_type sf3_type; 36708 | 36709 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36710 | const details::operator_type& operation, 36711 | expression_node_ptr (&branch)[2]) 36712 | { 36713 | // (v0 o0 v1) o1 (c) 36714 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]); 36715 | const Type& v0 = vov->v0(); 36716 | const Type& v1 = vov->v1(); 36717 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 36718 | const details::operator_type o0 = vov->operation(); 36719 | const details::operator_type o1 = operation; 36720 | 36721 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 36722 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 36723 | 36724 | expression_node_ptr result = error_node(); 36725 | 36726 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36727 | { 36728 | // (v0 / v1) / c --> (vovoc) v0 / (v1 * c) 36729 | if ((details::e_div == o0) && (details::e_div == o1)) 36730 | { 36731 | const bool synthesis_result = 36732 | synthesize_sf3ext_expression:: 36733 | template compile<vtype, vtype, ctype>(expr_gen, "t/(t*t)", v0, v1, c, result); 36734 | 36735 | exprtk_debug(("(v0 / v1) / c --> (vovoc) v0 / (v1 * c)\n")); 36736 | 36737 | return (synthesis_result) ? result : error_node(); 36738 | } 36739 | } 36740 | 36741 | const bool synthesis_result = 36742 | synthesize_sf3ext_expression::template compile<vtype, vtype, ctype> 36743 | (expr_gen, id(expr_gen, o0, o1), v0, v1, c, result); 36744 | 36745 | if (synthesis_result) 36746 | return result; 36747 | 36748 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36749 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36750 | 36751 | if (!expr_gen.valid_operator(o0,f0)) 36752 | return error_node(); 36753 | else if (!expr_gen.valid_operator(o1,f1)) 36754 | return error_node(); 36755 | else 36756 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, f0, f1); 36757 | } 36758 | 36759 | static inline std::string id(expression_generator<Type>& expr_gen, 36760 | const details::operator_type o0, 36761 | const details::operator_type o1) 36762 | { 36763 | return details::build_string() 36764 | << "(t" << expr_gen.to_str(o0) 36765 | << "t)" << expr_gen.to_str(o1) 36766 | << "t" 36767 | } 36768 | }; 36769 | 36770 | struct synthesize_vovoc_expression1 36771 | { 36772 | typedef typename vovoc_t::type1 node_type; 36773 | typedef typename vovoc_t::sf3_type sf3_type; 36774 | 36775 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36776 | const details::operator_type& operation, 36777 | expression_node_ptr (&branch)[2]) 36778 | { 36779 | // (v0) o0 (v1 o1 c) 36780 | const details::voc_base_node<Type>* voc = static_cast<const details::voc_base_node<Type>*>(branch[1]); 36781 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 36782 | const Type& v1 = voc->v(); 36783 | const Type c = voc->c(); 36784 | const details::operator_type o0 = operation; 36785 | const details::operator_type o1 = voc->operation(); 36786 | 36787 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 36788 | 36789 | expression_node_ptr result = error_node(); 36790 | 36791 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36792 | { 36793 | // v0 / (v1 / c) --> (vocov) (v0 * c) / v1 36794 | if ((details::e_div == o0) && (details::e_div == o1)) 36795 | { 36796 | const bool synthesis_result = 36797 | synthesize_sf3ext_expression:: 36798 | template compile<vtype, ctype, vtype>(expr_gen, "(t*t)/t", v0, c, v1, result); 36799 | 36800 | exprtk_debug(("v0 / (v1 / c) --> (vocov) (v0 * c) / v1\n")); 36801 | 36802 | return (synthesis_result) ? result : error_node(); 36803 | } 36804 | } 36805 | 36806 | const bool synthesis_result = 36807 | synthesize_sf3ext_expression::template compile<vtype, vtype, ctype> 36808 | (expr_gen, id(expr_gen, o0, o1), v0, v1, c, result); 36809 | 36810 | if (synthesis_result) 36811 | return result; 36812 | 36813 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36814 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36815 | 36816 | if (!expr_gen.valid_operator(o0,f0)) 36817 | return error_node(); 36818 | else if (!expr_gen.valid_operator(o1,f1)) 36819 | return error_node(); 36820 | else 36821 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, f0, f1); 36822 | } 36823 | 36824 | static inline std::string id(expression_generator<Type>& expr_gen, 36825 | const details::operator_type o0, 36826 | const details::operator_type o1) 36827 | { 36828 | return details::build_string() 36829 | << "t" << expr_gen.to_str(o0) 36830 | << "(t" << expr_gen.to_str(o1) 36831 | << "t)" 36832 | } 36833 | }; 36834 | 36835 | struct synthesize_vocov_expression0 36836 | { 36837 | typedef typename vocov_t::type0 node_type; 36838 | typedef typename vocov_t::sf3_type sf3_type; 36839 | 36840 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36841 | const details::operator_type& operation, 36842 | expression_node_ptr (&branch)[2]) 36843 | { 36844 | // (v0 o0 c) o1 (v1) 36845 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]); 36846 | const Type& v0 = voc->v(); 36847 | const Type c = voc->c(); 36848 | const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 36849 | const details::operator_type o0 = voc->operation(); 36850 | const details::operator_type o1 = operation; 36851 | 36852 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 36853 | 36854 | expression_node_ptr result = error_node(); 36855 | 36856 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36857 | { 36858 | // (v0 / c) / v1 --> (vovoc) v0 / (v1 * c) 36859 | if ((details::e_div == o0) && (details::e_div == o1)) 36860 | { 36861 | const bool synthesis_result = 36862 | synthesize_sf3ext_expression:: 36863 | template compile<vtype, vtype, ctype>(expr_gen, "t/(t*t)", v0, v1, c, result); 36864 | 36865 | exprtk_debug(("(v0 / c) / v1 --> (vovoc) v0 / (v1 * c)\n")); 36866 | 36867 | return (synthesis_result) ? result : error_node(); 36868 | } 36869 | } 36870 | 36871 | const bool synthesis_result = 36872 | synthesize_sf3ext_expression::template compile<vtype, ctype, vtype> 36873 | (expr_gen, id(expr_gen, o0, o1), v0, c, v1, result); 36874 | 36875 | if (synthesis_result) 36876 | return result; 36877 | 36878 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36879 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36880 | 36881 | if (!expr_gen.valid_operator(o0,f0)) 36882 | return error_node(); 36883 | else if (!expr_gen.valid_operator(o1,f1)) 36884 | return error_node(); 36885 | else 36886 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, f0, f1); 36887 | } 36888 | 36889 | static inline std::string id(expression_generator<Type>& expr_gen, 36890 | const details::operator_type o0, 36891 | const details::operator_type o1) 36892 | { 36893 | return details::build_string() 36894 | << "(t" << expr_gen.to_str(o0) 36895 | << "t)" << expr_gen.to_str(o1) 36896 | << "t" 36897 | } 36898 | }; 36899 | 36900 | struct synthesize_vocov_expression1 36901 | { 36902 | typedef typename vocov_t::type1 node_type; 36903 | typedef typename vocov_t::sf3_type sf3_type; 36904 | 36905 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36906 | const details::operator_type& operation, 36907 | expression_node_ptr (&branch)[2]) 36908 | { 36909 | // (v0) o0 (c o1 v1) 36910 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]); 36911 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 36912 | const Type c = cov->c(); 36913 | const Type& v1 = cov->v(); 36914 | const details::operator_type o0 = operation; 36915 | const details::operator_type o1 = cov->operation(); 36916 | 36917 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 36918 | 36919 | expression_node_ptr result = error_node(); 36920 | 36921 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36922 | { 36923 | // v0 / (c / v1) --> (vovoc) (v0 * v1) / c 36924 | if ((details::e_div == o0) && (details::e_div == o1)) 36925 | { 36926 | const bool synthesis_result = 36927 | synthesize_sf3ext_expression:: 36928 | template compile<vtype, vtype, ctype>(expr_gen, "(t*t)/t", v0, v1, c, result); 36929 | 36930 | exprtk_debug(("v0 / (c / v1) --> (vovoc) (v0 * v1) / c\n")); 36931 | 36932 | return (synthesis_result) ? result : error_node(); 36933 | } 36934 | } 36935 | 36936 | const bool synthesis_result = 36937 | synthesize_sf3ext_expression::template compile<vtype, ctype, vtype> 36938 | (expr_gen, id(expr_gen, o0, o1), v0, c, v1, result); 36939 | 36940 | if (synthesis_result) 36941 | return result; 36942 | 36943 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36944 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36945 | 36946 | if (!expr_gen.valid_operator(o0,f0)) 36947 | return error_node(); 36948 | else if (!expr_gen.valid_operator(o1,f1)) 36949 | return error_node(); 36950 | else 36951 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, f0, f1); 36952 | } 36953 | 36954 | static inline std::string id(expression_generator<Type>& expr_gen, 36955 | const details::operator_type o0, 36956 | const details::operator_type o1) 36957 | { 36958 | return details::build_string() 36959 | << "t" << expr_gen.to_str(o0) 36960 | << "(t" << expr_gen.to_str(o1) 36961 | << "t)" 36962 | } 36963 | }; 36964 | 36965 | struct synthesize_covov_expression0 36966 | { 36967 | typedef typename covov_t::type0 node_type; 36968 | typedef typename covov_t::sf3_type sf3_type; 36969 | 36970 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36971 | const details::operator_type& operation, 36972 | expression_node_ptr (&branch)[2]) 36973 | { 36974 | // (c o0 v0) o1 (v1) 36975 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]); 36976 | const Type c = cov->c(); 36977 | const Type& v0 = cov->v(); 36978 | const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 36979 | const details::operator_type o0 = cov->operation(); 36980 | const details::operator_type o1 = operation; 36981 | 36982 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 36983 | 36984 | expression_node_ptr result = error_node(); 36985 | 36986 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36987 | { 36988 | // (c / v0) / v1 --> (covov) c / (v0 * v1) 36989 | if ((details::e_div == o0) && (details::e_div == o1)) 36990 | { 36991 | const bool synthesis_result = 36992 | synthesize_sf3ext_expression:: 36993 | template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", c, v0, v1, result); 36994 | 36995 | exprtk_debug(("(c / v0) / v1 --> (covov) c / (v0 * v1)\n")); 36996 | 36997 | return (synthesis_result) ? result : error_node(); 36998 | } 36999 | } 37000 | 37001 | const bool synthesis_result = 37002 | synthesize_sf3ext_expression::template compile<ctype, vtype, vtype> 37003 | (expr_gen, id(expr_gen, o0, o1), c, v0, v1, result); 37004 | 37005 | if (synthesis_result) 37006 | return result; 37007 | 37008 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37009 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37010 | 37011 | if (!expr_gen.valid_operator(o0,f0)) 37012 | return error_node(); 37013 | else if (!expr_gen.valid_operator(o1,f1)) 37014 | return error_node(); 37015 | else 37016 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, f0, f1); 37017 | } 37018 | 37019 | static inline std::string id(expression_generator<Type>& expr_gen, 37020 | const details::operator_type o0, 37021 | const details::operator_type o1) 37022 | { 37023 | return details::build_string() 37024 | << "(t" << expr_gen.to_str(o0) 37025 | << "t)" << expr_gen.to_str(o1) 37026 | << "t" 37027 | } 37028 | }; 37029 | 37030 | struct synthesize_covov_expression1 37031 | { 37032 | typedef typename covov_t::type1 node_type; 37033 | typedef typename covov_t::sf3_type sf3_type; 37034 | 37035 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37036 | const details::operator_type& operation, 37037 | expression_node_ptr (&branch)[2]) 37038 | { 37039 | // (c) o0 (v0 o1 v1) 37040 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]); 37041 | const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); 37042 | const Type& v0 = vov->v0(); 37043 | const Type& v1 = vov->v1(); 37044 | const details::operator_type o0 = operation; 37045 | const details::operator_type o1 = vov->operation(); 37046 | 37047 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37048 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37049 | 37050 | expression_node_ptr result = error_node(); 37051 | 37052 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37053 | { 37054 | // c / (v0 / v1) --> (covov) (c * v1) / v0 37055 | if ((details::e_div == o0) && (details::e_div == o1)) 37056 | { 37057 | const bool synthesis_result = 37058 | synthesize_sf3ext_expression:: 37059 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", c, v1, v0, result); 37060 | 37061 | exprtk_debug(("c / (v0 / v1) --> (covov) (c * v1) / v0\n")); 37062 | 37063 | return (synthesis_result) ? result : error_node(); 37064 | } 37065 | } 37066 | 37067 | const bool synthesis_result = 37068 | synthesize_sf3ext_expression::template compile<ctype, vtype, vtype> 37069 | (expr_gen, id(expr_gen, o0, o1), c, v0, v1, result); 37070 | 37071 | if (synthesis_result) 37072 | return result; 37073 | 37074 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37075 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37076 | 37077 | if (!expr_gen.valid_operator(o0,f0)) 37078 | return error_node(); 37079 | else if (!expr_gen.valid_operator(o1,f1)) 37080 | return error_node(); 37081 | else 37082 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, f0, f1); 37083 | } 37084 | 37085 | static inline std::string id(expression_generator<Type>& expr_gen, 37086 | const details::operator_type o0, 37087 | const details::operator_type o1) 37088 | { 37089 | return details::build_string() 37090 | << "t" << expr_gen.to_str(o0) 37091 | << "(t" << expr_gen.to_str(o1) 37092 | << "t)" 37093 | } 37094 | }; 37095 | 37096 | struct synthesize_covoc_expression0 37097 | { 37098 | typedef typename covoc_t::type0 node_type; 37099 | typedef typename covoc_t::sf3_type sf3_type; 37100 | 37101 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37102 | const details::operator_type& operation, 37103 | expression_node_ptr (&branch)[2]) 37104 | { 37105 | // (c0 o0 v) o1 (c1) 37106 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]); 37107 | const Type c0 = cov->c(); 37108 | const Type& v = cov->v(); 37109 | const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); 37110 | const details::operator_type o0 = cov->operation(); 37111 | const details::operator_type o1 = operation; 37112 | 37113 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37114 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37115 | 37116 | expression_node_ptr result = error_node(); 37117 | 37118 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37119 | { 37120 | // (c0 + v) + c1 --> (cov) (c0 + c1) + v 37121 | if ((details::e_add == o0) && (details::e_add == o1)) 37122 | { 37123 | exprtk_debug(("(c0 + v) + c1 --> (cov) (c0 + c1) + v\n")); 37124 | 37125 | return expr_gen.node_allocator_-> 37126 | template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v); 37127 | } 37128 | // (c0 + v) - c1 --> (cov) (c0 - c1) + v 37129 | else if ((details::e_add == o0) && (details::e_sub == o1)) 37130 | { 37131 | exprtk_debug(("(c0 + v) - c1 --> (cov) (c0 - c1) + v\n")); 37132 | 37133 | return expr_gen.node_allocator_-> 37134 | template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v); 37135 | } 37136 | // (c0 - v) + c1 --> (cov) (c0 + c1) - v 37137 | else if ((details::e_sub == o0) && (details::e_add == o1)) 37138 | { 37139 | exprtk_debug(("(c0 - v) + c1 --> (cov) (c0 + c1) - v\n")); 37140 | 37141 | return expr_gen.node_allocator_-> 37142 | template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v); 37143 | } 37144 | // (c0 - v) - c1 --> (cov) (c0 - c1) - v 37145 | else if ((details::e_sub == o0) && (details::e_sub == o1)) 37146 | { 37147 | exprtk_debug(("(c0 - v) - c1 --> (cov) (c0 - c1) - v\n")); 37148 | 37149 | return expr_gen.node_allocator_-> 37150 | template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v); 37151 | } 37152 | // (c0 * v) * c1 --> (cov) (c0 * c1) * v 37153 | else if ((details::e_mul == o0) && (details::e_mul == o1)) 37154 | { 37155 | exprtk_debug(("(c0 * v) * c1 --> (cov) (c0 * c1) * v\n")); 37156 | 37157 | return expr_gen.node_allocator_-> 37158 | template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v); 37159 | } 37160 | // (c0 * v) / c1 --> (cov) (c0 / c1) * v 37161 | else if ((details::e_mul == o0) && (details::e_div == o1)) 37162 | { 37163 | exprtk_debug(("(c0 * v) / c1 --> (cov) (c0 / c1) * v\n")); 37164 | 37165 | return expr_gen.node_allocator_-> 37166 | template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v); 37167 | } 37168 | // (c0 / v) * c1 --> (cov) (c0 * c1) / v 37169 | else if ((details::e_div == o0) && (details::e_mul == o1)) 37170 | { 37171 | exprtk_debug(("(c0 / v) * c1 --> (cov) (c0 * c1) / v\n")); 37172 | 37173 | return expr_gen.node_allocator_-> 37174 | template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v); 37175 | } 37176 | // (c0 / v) / c1 --> (cov) (c0 / c1) / v 37177 | else if ((details::e_div == o0) && (details::e_div == o1)) 37178 | { 37179 | exprtk_debug(("(c0 / v) / c1 --> (cov) (c0 / c1) / v\n")); 37180 | 37181 | return expr_gen.node_allocator_-> 37182 | template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v); 37183 | } 37184 | } 37185 | 37186 | const bool synthesis_result = 37187 | synthesize_sf3ext_expression::template compile<ctype, vtype, ctype> 37188 | (expr_gen, id(expr_gen, o0, o1), c0, v, c1, result); 37189 | 37190 | if (synthesis_result) 37191 | return result; 37192 | 37193 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37194 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37195 | 37196 | if (!expr_gen.valid_operator(o0,f0)) 37197 | return error_node(); 37198 | else if (!expr_gen.valid_operator(o1,f1)) 37199 | return error_node(); 37200 | else 37201 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v, c1, f0, f1); 37202 | } 37203 | 37204 | static inline std::string id(expression_generator<Type>& expr_gen, 37205 | const details::operator_type o0, 37206 | const details::operator_type o1) 37207 | { 37208 | return details::build_string() 37209 | << "(t" << expr_gen.to_str(o0) 37210 | << "t)" << expr_gen.to_str(o1) 37211 | << "t" 37212 | } 37213 | }; 37214 | 37215 | struct synthesize_covoc_expression1 37216 | { 37217 | typedef typename covoc_t::type1 node_type; 37218 | typedef typename covoc_t::sf3_type sf3_type; 37219 | 37220 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37221 | const details::operator_type& operation, 37222 | expression_node_ptr (&branch)[2]) 37223 | { 37224 | // (c0) o0 (v o1 c1) 37225 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]); 37226 | const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); 37227 | const Type& v = voc->v(); 37228 | const Type c1 = voc->c(); 37229 | const details::operator_type o0 = operation; 37230 | const details::operator_type o1 = voc->operation(); 37231 | 37232 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37233 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37234 | 37235 | expression_node_ptr result = error_node(); 37236 | 37237 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37238 | { 37239 | // (c0) + (v + c1) --> (cov) (c0 + c1) + v 37240 | if ((details::e_add == o0) && (details::e_add == o1)) 37241 | { 37242 | exprtk_debug(("(c0) + (v + c1) --> (cov) (c0 + c1) + v\n")); 37243 | 37244 | return expr_gen.node_allocator_-> 37245 | template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v); 37246 | } 37247 | // (c0) + (v - c1) --> (cov) (c0 - c1) + v 37248 | else if ((details::e_add == o0) && (details::e_sub == o1)) 37249 | { 37250 | exprtk_debug(("(c0) + (v - c1) --> (cov) (c0 - c1) + v\n")); 37251 | 37252 | return expr_gen.node_allocator_-> 37253 | template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v); 37254 | } 37255 | // (c0) - (v + c1) --> (cov) (c0 - c1) - v 37256 | else if ((details::e_sub == o0) && (details::e_add == o1)) 37257 | { 37258 | exprtk_debug(("(c0) - (v + c1) --> (cov) (c0 - c1) - v\n")); 37259 | 37260 | return expr_gen.node_allocator_-> 37261 | template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v); 37262 | } 37263 | // (c0) - (v - c1) --> (cov) (c0 + c1) - v 37264 | else if ((details::e_sub == o0) && (details::e_sub == o1)) 37265 | { 37266 | exprtk_debug(("(c0) - (v - c1) --> (cov) (c0 + c1) - v\n")); 37267 | 37268 | return expr_gen.node_allocator_-> 37269 | template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v); 37270 | } 37271 | // (c0) * (v * c1) --> (voc) v * (c0 * c1) 37272 | else if ((details::e_mul == o0) && (details::e_mul == o1)) 37273 | { 37274 | exprtk_debug(("(c0) * (v * c1) --> (voc) v * (c0 * c1)\n")); 37275 | 37276 | return expr_gen.node_allocator_-> 37277 | template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v); 37278 | } 37279 | // (c0) * (v / c1) --> (cov) (c0 / c1) * v 37280 | else if ((details::e_mul == o0) && (details::e_div == o1)) 37281 | { 37282 | exprtk_debug(("(c0) * (v / c1) --> (cov) (c0 / c1) * v\n")); 37283 | 37284 | return expr_gen.node_allocator_-> 37285 | template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v); 37286 | } 37287 | // (c0) / (v * c1) --> (cov) (c0 / c1) / v 37288 | else if ((details::e_div == o0) && (details::e_mul == o1)) 37289 | { 37290 | exprtk_debug(("(c0) / (v * c1) --> (cov) (c0 / c1) / v\n")); 37291 | 37292 | return expr_gen.node_allocator_-> 37293 | template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v); 37294 | } 37295 | // (c0) / (v / c1) --> (cov) (c0 * c1) / v 37296 | else if ((details::e_div == o0) && (details::e_div == o1)) 37297 | { 37298 | exprtk_debug(("(c0) / (v / c1) --> (cov) (c0 * c1) / v\n")); 37299 | 37300 | return expr_gen.node_allocator_-> 37301 | template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v); 37302 | } 37303 | } 37304 | 37305 | const bool synthesis_result = 37306 | synthesize_sf3ext_expression::template compile<ctype, vtype, ctype> 37307 | (expr_gen, id(expr_gen, o0, o1), c0, v, c1, result); 37308 | 37309 | if (synthesis_result) 37310 | return result; 37311 | 37312 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37313 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37314 | 37315 | if (!expr_gen.valid_operator(o0,f0)) 37316 | return error_node(); 37317 | else if (!expr_gen.valid_operator(o1,f1)) 37318 | return error_node(); 37319 | else 37320 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v, c1, f0, f1); 37321 | } 37322 | 37323 | static inline std::string id(expression_generator<Type>& expr_gen, 37324 | const details::operator_type o0, 37325 | const details::operator_type o1) 37326 | { 37327 | return details::build_string() 37328 | << "t" << expr_gen.to_str(o0) 37329 | << "(t" << expr_gen.to_str(o1) 37330 | << "t)" 37331 | } 37332 | }; 37333 | 37334 | struct synthesize_cocov_expression0 37335 | { 37336 | typedef typename cocov_t::type0 node_type; 37337 | static inline expression_node_ptr process(expression_generator<Type>&, 37338 | const details::operator_type&, 37339 | expression_node_ptr (&)[2]) 37340 | { 37341 | // (c0 o0 c1) o1 (v) - Not possible. 37342 | return error_node(); 37343 | } 37344 | }; 37345 | 37346 | struct synthesize_cocov_expression1 37347 | { 37348 | typedef typename cocov_t::type1 node_type; 37349 | typedef typename cocov_t::sf3_type sf3_type; 37350 | 37351 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37352 | const details::operator_type& operation, 37353 | expression_node_ptr (&branch)[2]) 37354 | { 37355 | // (c0) o0 (c1 o1 v) 37356 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]); 37357 | const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); 37358 | const Type c1 = cov->c(); 37359 | const Type& v = cov->v(); 37360 | const details::operator_type o0 = operation; 37361 | const details::operator_type o1 = cov->operation(); 37362 | 37363 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37364 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37365 | 37366 | expression_node_ptr result = error_node(); 37367 | 37368 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37369 | { 37370 | // (c0) + (c1 + v) --> (cov) (c0 + c1) + v 37371 | if ((details::e_add == o0) && (details::e_add == o1)) 37372 | { 37373 | exprtk_debug(("(c0) + (c1 + v) --> (cov) (c0 + c1) + v\n")); 37374 | 37375 | return expr_gen.node_allocator_-> 37376 | template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v); 37377 | } 37378 | // (c0) + (c1 - v) --> (cov) (c0 + c1) - v 37379 | else if ((details::e_add == o0) && (details::e_sub == o1)) 37380 | { 37381 | exprtk_debug(("(c0) + (c1 - v) --> (cov) (c0 + c1) - v\n")); 37382 | 37383 | return expr_gen.node_allocator_-> 37384 | template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v); 37385 | } 37386 | // (c0) - (c1 + v) --> (cov) (c0 - c1) - v 37387 | else if ((details::e_sub == o0) && (details::e_add == o1)) 37388 | { 37389 | exprtk_debug(("(c0) - (c1 + v) --> (cov) (c0 - c1) - v\n")); 37390 | 37391 | return expr_gen.node_allocator_-> 37392 | template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v); 37393 | } 37394 | // (c0) - (c1 - v) --> (cov) (c0 - c1) + v 37395 | else if ((details::e_sub == o0) && (details::e_sub == o1)) 37396 | { 37397 | exprtk_debug(("(c0) - (c1 - v) --> (cov) (c0 - c1) + v\n")); 37398 | 37399 | return expr_gen.node_allocator_-> 37400 | template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v); 37401 | } 37402 | // (c0) * (c1 * v) --> (cov) (c0 * c1) * v 37403 | else if ((details::e_mul == o0) && (details::e_mul == o1)) 37404 | { 37405 | exprtk_debug(("(c0) * (c1 * v) --> (cov) (c0 * c1) * v\n")); 37406 | 37407 | return expr_gen.node_allocator_-> 37408 | template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v); 37409 | } 37410 | // (c0) * (c1 / v) --> (cov) (c0 * c1) / v 37411 | else if ((details::e_mul == o0) && (details::e_div == o1)) 37412 | { 37413 | exprtk_debug(("(c0) * (c1 / v) --> (cov) (c0 * c1) / v\n")); 37414 | 37415 | return expr_gen.node_allocator_-> 37416 | template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v); 37417 | } 37418 | // (c0) / (c1 * v) --> (cov) (c0 / c1) / v 37419 | else if ((details::e_div == o0) && (details::e_mul == o1)) 37420 | { 37421 | exprtk_debug(("(c0) / (c1 * v) --> (cov) (c0 / c1) / v\n")); 37422 | 37423 | return expr_gen.node_allocator_-> 37424 | template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v); 37425 | } 37426 | // (c0) / (c1 / v) --> (cov) (c0 / c1) * v 37427 | else if ((details::e_div == o0) && (details::e_div == o1)) 37428 | { 37429 | exprtk_debug(("(c0) / (c1 / v) --> (cov) (c0 / c1) * v\n")); 37430 | 37431 | return expr_gen.node_allocator_-> 37432 | template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v); 37433 | } 37434 | } 37435 | 37436 | const bool synthesis_result = 37437 | synthesize_sf3ext_expression::template compile<ctype, ctype, vtype> 37438 | (expr_gen, id(expr_gen, o0, o1), c0, c1, v, result); 37439 | 37440 | if (synthesis_result) 37441 | return result; 37442 | 37443 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37444 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37445 | 37446 | if (!expr_gen.valid_operator(o0,f0)) 37447 | return error_node(); 37448 | else if (!expr_gen.valid_operator(o1,f1)) 37449 | return error_node(); 37450 | else 37451 | return node_type::allocate(*(expr_gen.node_allocator_), c0, c1, v, f0, f1); 37452 | } 37453 | 37454 | static inline std::string id(expression_generator<Type>& expr_gen, 37455 | const details::operator_type o0, 37456 | const details::operator_type o1) 37457 | { 37458 | return details::build_string() 37459 | << "t" << expr_gen.to_str(o0) 37460 | << "(t" << expr_gen.to_str(o1) 37461 | << "t)" 37462 | } 37463 | }; 37464 | 37465 | struct synthesize_vococ_expression0 37466 | { 37467 | typedef typename vococ_t::type0 node_type; 37468 | typedef typename vococ_t::sf3_type sf3_type; 37469 | 37470 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37471 | const details::operator_type& operation, 37472 | expression_node_ptr (&branch)[2]) 37473 | { 37474 | // (v o0 c0) o1 (c1) 37475 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]); 37476 | const Type& v = voc->v(); 37477 | const Type& c0 = voc->c(); 37478 | const Type& c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); 37479 | const details::operator_type o0 = voc->operation(); 37480 | const details::operator_type o1 = operation; 37481 | 37482 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37483 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37484 | 37485 | expression_node_ptr result = error_node(); 37486 | 37487 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37488 | { 37489 | // (v + c0) + c1 --> (voc) v + (c0 + c1) 37490 | if ((details::e_add == o0) && (details::e_add == o1)) 37491 | { 37492 | exprtk_debug(("(v + c0) + c1 --> (voc) v + (c0 + c1)\n")); 37493 | 37494 | return expr_gen.node_allocator_-> 37495 | template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c0 + c1); 37496 | } 37497 | // (v + c0) - c1 --> (voc) v + (c0 - c1) 37498 | else if ((details::e_add == o0) && (details::e_sub == o1)) 37499 | { 37500 | exprtk_debug(("(v + c0) - c1 --> (voc) v + (c0 - c1)\n")); 37501 | 37502 | return expr_gen.node_allocator_-> 37503 | template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c0 - c1); 37504 | } 37505 | // (v - c0) + c1 --> (voc) v - (c0 + c1) 37506 | else if ((details::e_sub == o0) && (details::e_add == o1)) 37507 | { 37508 | exprtk_debug(("(v - c0) + c1 --> (voc) v - (c0 + c1)\n")); 37509 | 37510 | return expr_gen.node_allocator_-> 37511 | template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c1 - c0); 37512 | } 37513 | // (v - c0) - c1 --> (voc) v - (c0 + c1) 37514 | else if ((details::e_sub == o0) && (details::e_sub == o1)) 37515 | { 37516 | exprtk_debug(("(v - c0) - c1 --> (voc) v - (c0 + c1)\n")); 37517 | 37518 | return expr_gen.node_allocator_-> 37519 | template allocate_rc<typename details::voc_node<Type,details::sub_op<Type> > >(v, c0 + c1); 37520 | } 37521 | // (v * c0) * c1 --> (voc) v * (c0 * c1) 37522 | else if ((details::e_mul == o0) && (details::e_mul == o1)) 37523 | { 37524 | exprtk_debug(("(v * c0) * c1 --> (voc) v * (c0 * c1)\n")); 37525 | 37526 | return expr_gen.node_allocator_-> 37527 | template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c0 * c1); 37528 | } 37529 | // (v * c0) / c1 --> (voc) v * (c0 / c1) 37530 | else if ((details::e_mul == o0) && (details::e_div == o1)) 37531 | { 37532 | exprtk_debug(("(v * c0) / c1 --> (voc) v * (c0 / c1)\n")); 37533 | 37534 | return expr_gen.node_allocator_-> 37535 | template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c0 / c1); 37536 | } 37537 | // (v / c0) * c1 --> (voc) v * (c1 / c0) 37538 | else if ((details::e_div == o0) && (details::e_mul == o1)) 37539 | { 37540 | exprtk_debug(("(v / c0) * c1 --> (voc) v * (c1 / c0)\n")); 37541 | 37542 | return expr_gen.node_allocator_-> 37543 | template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c1 / c0); 37544 | } 37545 | // (v / c0) / c1 --> (voc) v / (c0 * c1) 37546 | else if ((details::e_div == o0) && (details::e_div == o1)) 37547 | { 37548 | exprtk_debug(("(v / c0) / c1 --> (voc) v / (c0 * c1)\n")); 37549 | 37550 | return expr_gen.node_allocator_-> 37551 | template allocate_rc<typename details::voc_node<Type,details::div_op<Type> > >(v, c0 * c1); 37552 | } 37553 | // (v ^ c0) ^ c1 --> (voc) v ^ (c0 * c1) 37554 | else if ((details::e_pow == o0) && (details::e_pow == o1)) 37555 | { 37556 | exprtk_debug(("(v ^ c0) ^ c1 --> (voc) v ^ (c0 * c1)\n")); 37557 | 37558 | return expr_gen.node_allocator_-> 37559 | template allocate_rc<typename details::voc_node<Type,details::pow_op<Type> > >(v, c0 * c1); 37560 | } 37561 | } 37562 | 37563 | const bool synthesis_result = 37564 | synthesize_sf3ext_expression::template compile<vtype, ctype, ctype> 37565 | (expr_gen, id(expr_gen, o0, o1), v, c0, c1, result); 37566 | 37567 | if (synthesis_result) 37568 | return result; 37569 | 37570 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37571 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37572 | 37573 | if (!expr_gen.valid_operator(o0,f0)) 37574 | return error_node(); 37575 | else if (!expr_gen.valid_operator(o1,f1)) 37576 | return error_node(); 37577 | else 37578 | return node_type::allocate(*(expr_gen.node_allocator_), v, c0, c1, f0, f1); 37579 | } 37580 | 37581 | static inline std::string id(expression_generator<Type>& expr_gen, 37582 | const details::operator_type o0, 37583 | const details::operator_type o1) 37584 | { 37585 | return details::build_string() 37586 | << "(t" << expr_gen.to_str(o0) 37587 | << "t)" << expr_gen.to_str(o1) 37588 | << "t" 37589 | } 37590 | }; 37591 | 37592 | struct synthesize_vococ_expression1 37593 | { 37594 | typedef typename vococ_t::type0 node_type; 37595 | 37596 | static inline expression_node_ptr process(expression_generator<Type>&, 37597 | const details::operator_type&, 37598 | expression_node_ptr (&)[2]) 37599 | { 37600 | // (v) o0 (c0 o1 c1) - Not possible. 37601 | exprtk_debug(("(v) o0 (c0 o1 c1) - Not possible.\n")); 37602 | return error_node(); 37603 | } 37604 | }; 37605 | 37606 | struct synthesize_vovovov_expression0 37607 | { 37608 | typedef typename vovovov_t::type0 node_type; 37609 | typedef typename vovovov_t::sf4_type sf4_type; 37610 | typedef typename node_type::T0 T0; 37611 | typedef typename node_type::T1 T1; 37612 | typedef typename node_type::T2 T2; 37613 | typedef typename node_type::T3 T3; 37614 | 37615 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37616 | const details::operator_type& operation, 37617 | expression_node_ptr (&branch)[2]) 37618 | { 37619 | // (v0 o0 v1) o1 (v2 o2 v3) 37620 | const details::vov_base_node<Type>* vov0 = static_cast<details::vov_base_node<Type>*>(branch[0]); 37621 | const details::vov_base_node<Type>* vov1 = static_cast<details::vov_base_node<Type>*>(branch[1]); 37622 | const Type& v0 = vov0->v0(); 37623 | const Type& v1 = vov0->v1(); 37624 | const Type& v2 = vov1->v0(); 37625 | const Type& v3 = vov1->v1(); 37626 | const details::operator_type o0 = vov0->operation(); 37627 | const details::operator_type o1 = operation; 37628 | const details::operator_type o2 = vov1->operation(); 37629 | 37630 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37631 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37632 | 37633 | expression_node_ptr result = error_node(); 37634 | 37635 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37636 | { 37637 | // (v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3) 37638 | if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 37639 | { 37640 | const bool synthesis_result = 37641 | synthesize_sf4ext_expression:: 37642 | template compile<vtype, vtype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, v3, result); 37643 | 37644 | exprtk_debug(("(v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3)\n")); 37645 | 37646 | return (synthesis_result) ? result : error_node(); 37647 | } 37648 | // (v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2) 37649 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 37650 | { 37651 | const bool synthesis_result = 37652 | synthesize_sf4ext_expression:: 37653 | template compile<vtype, vtype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", v0, v3, v1, v2, result); 37654 | 37655 | exprtk_debug(("(v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2)\n")); 37656 | 37657 | return (synthesis_result) ? result : error_node(); 37658 | } 37659 | // (v0 + v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2) 37660 | else if ((details::e_add == o0) && (details::e_div == o1) && (details::e_div == o2)) 37661 | { 37662 | const bool synthesis_result = 37663 | synthesize_sf4ext_expression:: 37664 | template compile<vtype, vtype, vtype, vtype>(expr_gen, "(t+t)*(t/t)", v0, v1, v3, v2, result); 37665 | 37666 | exprtk_debug(("(v0 + v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2)\n")); 37667 | 37668 | return (synthesis_result) ? result : error_node(); 37669 | } 37670 | // (v0 - v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2) 37671 | else if ((details::e_sub == o0) && (details::e_div == o1) && (details::e_div == o2)) 37672 | { 37673 | const bool synthesis_result = 37674 | synthesize_sf4ext_expression:: 37675 | template compile<vtype, vtype, vtype, vtype>(expr_gen, "(t-t)*(t/t)", v0, v1, v3, v2, result); 37676 | 37677 | exprtk_debug(("(v0 - v1) / (v2 / v3) --> (vovovov) (v0 - v1) * (v3 / v2)\n")); 37678 | 37679 | return (synthesis_result) ? result : error_node(); 37680 | } 37681 | // (v0 * v1) / (v2 / v3) --> (vovovov) ((v0 * v1) * v3) / v2 37682 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) 37683 | { 37684 | const bool synthesis_result = 37685 | synthesize_sf4ext_expression:: 37686 | template compile<vtype, vtype, vtype, vtype>(expr_gen, "((t*t)*t)/t", v0, v1, v3, v2, result); 37687 | 37688 | exprtk_debug(("(v0 * v1) / (v2 / v3) --> (vovovov) ((v0 * v1) * v3) / v2\n")); 37689 | 37690 | return (synthesis_result) ? result : error_node(); 37691 | } 37692 | } 37693 | 37694 | const bool synthesis_result = 37695 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 37696 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result); 37697 | 37698 | if (synthesis_result) 37699 | return result; 37700 | 37701 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37702 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37703 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 37704 | 37705 | if (!expr_gen.valid_operator(o0,f0)) 37706 | return error_node(); 37707 | else if (!expr_gen.valid_operator(o1,f1)) 37708 | return error_node(); 37709 | else if (!expr_gen.valid_operator(o2,f2)) 37710 | return error_node(); 37711 | else 37712 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2); 37713 | } 37714 | 37715 | static inline std::string id(expression_generator<Type>& expr_gen, 37716 | const details::operator_type o0, 37717 | const details::operator_type o1, 37718 | const details::operator_type o2) 37719 | { 37720 | return details::build_string() 37721 | << "(t" << expr_gen.to_str(o0) 37722 | << "t)" << expr_gen.to_str(o1) 37723 | << "(t" << expr_gen.to_str(o2) 37724 | << "t)" 37725 | } 37726 | }; 37727 | 37728 | struct synthesize_vovovoc_expression0 37729 | { 37730 | typedef typename vovovoc_t::type0 node_type; 37731 | typedef typename vovovoc_t::sf4_type sf4_type; 37732 | typedef typename node_type::T0 T0; 37733 | typedef typename node_type::T1 T1; 37734 | typedef typename node_type::T2 T2; 37735 | typedef typename node_type::T3 T3; 37736 | 37737 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37738 | const details::operator_type& operation, 37739 | expression_node_ptr (&branch)[2]) 37740 | { 37741 | // (v0 o0 v1) o1 (v2 o2 c) 37742 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]); 37743 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]); 37744 | const Type& v0 = vov->v0(); 37745 | const Type& v1 = vov->v1(); 37746 | const Type& v2 = voc->v (); 37747 | const Type c = voc->c (); 37748 | const details::operator_type o0 = vov->operation(); 37749 | const details::operator_type o1 = operation; 37750 | const details::operator_type o2 = voc->operation(); 37751 | 37752 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37753 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37754 | 37755 | expression_node_ptr result = error_node(); 37756 | 37757 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37758 | { 37759 | // (v0 / v1) * (v2 / c) --> (vovovoc) (v0 * v2) / (v1 * c) 37760 | if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 37761 | { 37762 | const bool synthesis_result = 37763 | synthesize_sf4ext_expression:: 37764 | template compile<vtype, vtype, vtype, ctype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, c, result); 37765 | 37766 | exprtk_debug(("(v0 / v1) * (v2 / c) --> (vovovoc) (v0 * v2) / (v1 * c)\n")); 37767 | 37768 | return (synthesis_result) ? result : error_node(); 37769 | } 37770 | // (v0 / v1) / (v2 / c) --> (vocovov) (v0 * c) / (v1 * v2) 37771 | if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 37772 | { 37773 | const bool synthesis_result = 37774 | synthesize_sf4ext_expression:: 37775 | template compile<vtype, ctype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", v0, c, v1, v2, result); 37776 | 37777 | exprtk_debug(("(v0 / v1) / (v2 / c) --> (vocovov) (v0 * c) / (v1 * v2)\n")); 37778 | 37779 | return (synthesis_result) ? result : error_node(); 37780 | } 37781 | } 37782 | 37783 | const bool synthesis_result = 37784 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 37785 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result); 37786 | 37787 | if (synthesis_result) 37788 | return result; 37789 | 37790 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37791 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37792 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 37793 | 37794 | if (!expr_gen.valid_operator(o0,f0)) 37795 | return error_node(); 37796 | else if (!expr_gen.valid_operator(o1,f1)) 37797 | return error_node(); 37798 | else if (!expr_gen.valid_operator(o2,f2)) 37799 | return error_node(); 37800 | else 37801 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2); 37802 | } 37803 | 37804 | static inline std::string id(expression_generator<Type>& expr_gen, 37805 | const details::operator_type o0, 37806 | const details::operator_type o1, 37807 | const details::operator_type o2) 37808 | { 37809 | return details::build_string() 37810 | << "(t" << expr_gen.to_str(o0) 37811 | << "t)" << expr_gen.to_str(o1) 37812 | << "(t" << expr_gen.to_str(o2) 37813 | << "t)" 37814 | } 37815 | }; 37816 | 37817 | struct synthesize_vovocov_expression0 37818 | { 37819 | typedef typename vovocov_t::type0 node_type; 37820 | typedef typename vovocov_t::sf4_type sf4_type; 37821 | typedef typename node_type::T0 T0; 37822 | typedef typename node_type::T1 T1; 37823 | typedef typename node_type::T2 T2; 37824 | typedef typename node_type::T3 T3; 37825 | 37826 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37827 | const details::operator_type& operation, 37828 | expression_node_ptr (&branch)[2]) 37829 | { 37830 | // (v0 o0 v1) o1 (c o2 v2) 37831 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]); 37832 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]); 37833 | const Type& v0 = vov->v0(); 37834 | const Type& v1 = vov->v1(); 37835 | const Type& v2 = cov->v (); 37836 | const Type c = cov->c (); 37837 | const details::operator_type o0 = vov->operation(); 37838 | const details::operator_type o1 = operation; 37839 | const details::operator_type o2 = cov->operation(); 37840 | 37841 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37842 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37843 | 37844 | expression_node_ptr result = error_node(); 37845 | 37846 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37847 | { 37848 | // (v0 / v1) * (c / v2) --> (vocovov) (v0 * c) / (v1 * v2) 37849 | if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 37850 | { 37851 | const bool synthesis_result = 37852 | synthesize_sf4ext_expression:: 37853 | template compile<vtype, ctype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", v0, c, v1, v2, result); 37854 | 37855 | exprtk_debug(("(v0 / v1) * (c / v2) --> (vocovov) (v0 * c) / (v1 * v2)\n")); 37856 | 37857 | return (synthesis_result) ? result : error_node(); 37858 | } 37859 | // (v0 / v1) / (c / v2) --> (vovovoc) (v0 * v2) / (v1 * c) 37860 | if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 37861 | { 37862 | const bool synthesis_result = 37863 | synthesize_sf4ext_expression:: 37864 | template compile<vtype, vtype, vtype, ctype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, c, result); 37865 | 37866 | exprtk_debug(("(v0 / v1) / (c / v2) --> (vovovoc) (v0 * v2) / (v1 * c)\n")); 37867 | 37868 | return (synthesis_result) ? result : error_node(); 37869 | } 37870 | } 37871 | 37872 | const bool synthesis_result = 37873 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 37874 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result); 37875 | 37876 | if (synthesis_result) 37877 | return result; 37878 | 37879 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37880 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37881 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 37882 | 37883 | if (!expr_gen.valid_operator(o0,f0)) 37884 | return error_node(); 37885 | else if (!expr_gen.valid_operator(o1,f1)) 37886 | return error_node(); 37887 | else if (!expr_gen.valid_operator(o2,f2)) 37888 | return error_node(); 37889 | else 37890 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2); 37891 | } 37892 | 37893 | static inline std::string id(expression_generator<Type>& expr_gen, 37894 | const details::operator_type o0, 37895 | const details::operator_type o1, 37896 | const details::operator_type o2) 37897 | { 37898 | return details::build_string() 37899 | << "(t" << expr_gen.to_str(o0) 37900 | << "t)" << expr_gen.to_str(o1) 37901 | << "(t" << expr_gen.to_str(o2) 37902 | << "t)" 37903 | } 37904 | }; 37905 | 37906 | struct synthesize_vocovov_expression0 37907 | { 37908 | typedef typename vocovov_t::type0 node_type; 37909 | typedef typename vocovov_t::sf4_type sf4_type; 37910 | typedef typename node_type::T0 T0; 37911 | typedef typename node_type::T1 T1; 37912 | typedef typename node_type::T2 T2; 37913 | typedef typename node_type::T3 T3; 37914 | 37915 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37916 | const details::operator_type& operation, 37917 | expression_node_ptr (&branch)[2]) 37918 | { 37919 | // (v0 o0 c) o1 (v1 o2 v2) 37920 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]); 37921 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]); 37922 | const Type c = voc->c (); 37923 | const Type& v0 = voc->v (); 37924 | const Type& v1 = vov->v0(); 37925 | const Type& v2 = vov->v1(); 37926 | const details::operator_type o0 = voc->operation(); 37927 | const details::operator_type o1 = operation; 37928 | const details::operator_type o2 = vov->operation(); 37929 | 37930 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37931 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37932 | 37933 | expression_node_ptr result = error_node(); 37934 | 37935 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37936 | { 37937 | // (v0 / c) * (v1 / v2) --> (vovocov) (v0 * v1) / (c * v2) 37938 | if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 37939 | { 37940 | const bool synthesis_result = 37941 | synthesize_sf4ext_expression:: 37942 | template compile<vtype, vtype, ctype, vtype>(expr_gen, "(t*t)/(t*t)", v0, v1, c, v2, result); 37943 | 37944 | exprtk_debug(("(v0 / c) * (v1 / v2) --> (vovocov) (v0 * v1) / (c * v2)\n")); 37945 | 37946 | return (synthesis_result) ? result : error_node(); 37947 | } 37948 | // (v0 / c) / (v1 / v2) --> (vovocov) (v0 * v2) / (c * v1) 37949 | if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 37950 | { 37951 | const bool synthesis_result = 37952 | synthesize_sf4ext_expression:: 37953 | template compile<vtype, vtype, ctype, vtype>(expr_gen, "(t*t)/(t*t)", v0, v2, c, v1, result); 37954 | 37955 | exprtk_debug(("(v0 / c) / (v1 / v2) --> (vovocov) (v0 * v2) / (c * v1)\n")); 37956 | 37957 | return (synthesis_result) ? result : error_node(); 37958 | } 37959 | } 37960 | 37961 | const bool synthesis_result = 37962 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 37963 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result); 37964 | 37965 | if (synthesis_result) 37966 | return result; 37967 | 37968 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37969 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37970 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 37971 | 37972 | if (!expr_gen.valid_operator(o0,f0)) 37973 | return error_node(); 37974 | else if (!expr_gen.valid_operator(o1,f1)) 37975 | return error_node(); 37976 | else if (!expr_gen.valid_operator(o2,f2)) 37977 | return error_node(); 37978 | else 37979 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2); 37980 | } 37981 | 37982 | static inline std::string id(expression_generator<Type>& expr_gen, 37983 | const details::operator_type o0, 37984 | const details::operator_type o1, 37985 | const details::operator_type o2) 37986 | { 37987 | return details::build_string() 37988 | << "(t" << expr_gen.to_str(o0) 37989 | << "t)" << expr_gen.to_str(o1) 37990 | << "(t" << expr_gen.to_str(o2) 37991 | << "t)" 37992 | } 37993 | }; 37994 | 37995 | struct synthesize_covovov_expression0 37996 | { 37997 | typedef typename covovov_t::type0 node_type; 37998 | typedef typename covovov_t::sf4_type sf4_type; 37999 | typedef typename node_type::T0 T0; 38000 | typedef typename node_type::T1 T1; 38001 | typedef typename node_type::T2 T2; 38002 | typedef typename node_type::T3 T3; 38003 | 38004 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38005 | const details::operator_type& operation, 38006 | expression_node_ptr (&branch)[2]) 38007 | { 38008 | // (c o0 v0) o1 (v1 o2 v2) 38009 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]); 38010 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]); 38011 | const Type c = cov->c (); 38012 | const Type& v0 = cov->v (); 38013 | const Type& v1 = vov->v0(); 38014 | const Type& v2 = vov->v1(); 38015 | const details::operator_type o0 = cov->operation(); 38016 | const details::operator_type o1 = operation; 38017 | const details::operator_type o2 = vov->operation(); 38018 | 38019 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 38020 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38021 | 38022 | expression_node_ptr result = error_node(); 38023 | 38024 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 38025 | { 38026 | // (c / v0) * (v1 / v2) --> (covovov) (c * v1) / (v0 * v2) 38027 | if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 38028 | { 38029 | const bool synthesis_result = 38030 | synthesize_sf4ext_expression:: 38031 | template compile<ctype, vtype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", c, v1, v0, v2, result); 38032 | 38033 | exprtk_debug(("(c / v0) * (v1 / v2) --> (covovov) (c * v1) / (v0 * v2)\n")); 38034 | 38035 | return (synthesis_result) ? result : error_node(); 38036 | } 38037 | // (c / v0) / (v1 / v2) --> (covovov) (c * v2) / (v0 * v1) 38038 | if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 38039 | { 38040 | const bool synthesis_result = 38041 | synthesize_sf4ext_expression:: 38042 | template compile<ctype, vtype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", c, v2, v0, v1, result); 38043 | 38044 | exprtk_debug(("(c / v0) / (v1 / v2) --> (covovov) (c * v2) / (v0 * v1)\n")); 38045 | 38046 | return (synthesis_result) ? result : error_node(); 38047 | } 38048 | } 38049 | 38050 | const bool synthesis_result = 38051 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38052 | (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result); 38053 | 38054 | if (synthesis_result) 38055 | return result; 38056 | 38057 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38058 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 38059 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 38060 | 38061 | if (!expr_gen.valid_operator(o0,f0)) 38062 | return error_node(); 38063 | else if (!expr_gen.valid_operator(o1,f1)) 38064 | return error_node(); 38065 | else if (!expr_gen.valid_operator(o2,f2)) 38066 | return error_node(); 38067 | else 38068 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2); 38069 | } 38070 | 38071 | static inline std::string id(expression_generator<Type>& expr_gen, 38072 | const details::operator_type o0, 38073 | const details::operator_type o1, 38074 | const details::operator_type o2) 38075 | { 38076 | return details::build_string() 38077 | << "(t" << expr_gen.to_str(o0) 38078 | << "t)" << expr_gen.to_str(o1) 38079 | << "(t" << expr_gen.to_str(o2) 38080 | << "t)" 38081 | } 38082 | }; 38083 | 38084 | struct synthesize_covocov_expression0 38085 | { 38086 | typedef typename covocov_t::type0 node_type; 38087 | typedef typename covocov_t::sf4_type sf4_type; 38088 | typedef typename node_type::T0 T0; 38089 | typedef typename node_type::T1 T1; 38090 | typedef typename node_type::T2 T2; 38091 | typedef typename node_type::T3 T3; 38092 | 38093 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38094 | const details::operator_type& operation, 38095 | expression_node_ptr (&branch)[2]) 38096 | { 38097 | // (c0 o0 v0) o1 (c1 o2 v1) 38098 | const details::cov_base_node<Type>* cov0 = static_cast<details::cov_base_node<Type>*>(branch[0]); 38099 | const details::cov_base_node<Type>* cov1 = static_cast<details::cov_base_node<Type>*>(branch[1]); 38100 | const Type c0 = cov0->c(); 38101 | const Type& v0 = cov0->v(); 38102 | const Type c1 = cov1->c(); 38103 | const Type& v1 = cov1->v(); 38104 | const details::operator_type o0 = cov0->operation(); 38105 | const details::operator_type o1 = operation; 38106 | const details::operator_type o2 = cov1->operation(); 38107 | 38108 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 38109 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38110 | 38111 | expression_node_ptr result = error_node(); 38112 | 38113 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 38114 | { 38115 | // (c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1 38116 | if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2)) 38117 | { 38118 | const bool synthesis_result = 38119 | synthesize_sf3ext_expression:: 38120 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result); 38121 | 38122 | exprtk_debug(("(c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n")); 38123 | 38124 | return (synthesis_result) ? result : error_node(); 38125 | } 38126 | // (c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1 38127 | else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2)) 38128 | { 38129 | const bool synthesis_result = 38130 | synthesize_sf3ext_expression:: 38131 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result); 38132 | 38133 | exprtk_debug(("(c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n")); 38134 | 38135 | return (synthesis_result) ? result : error_node(); 38136 | } 38137 | // (c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1 38138 | else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2)) 38139 | { 38140 | const bool synthesis_result = 38141 | synthesize_sf3ext_expression:: 38142 | template compile<ctype, vtype, vtype>(expr_gen, "(t-t)+t", (c0 - c1), v0, v1, result); 38143 | 38144 | exprtk_debug(("(c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1\n")); 38145 | 38146 | return (synthesis_result) ? result : error_node(); 38147 | } 38148 | // (c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1 38149 | else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2)) 38150 | { 38151 | const bool synthesis_result = 38152 | synthesize_sf3ext_expression:: 38153 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result); 38154 | 38155 | exprtk_debug(("(c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n")); 38156 | 38157 | return (synthesis_result) ? result : error_node(); 38158 | } 38159 | // (c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1) 38160 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38161 | { 38162 | const bool synthesis_result = 38163 | synthesize_sf3ext_expression:: 38164 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result); 38165 | 38166 | exprtk_debug(("(c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1)\n")); 38167 | 38168 | return (synthesis_result) ? result : error_node(); 38169 | } 38170 | // (c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1) 38171 | else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 38172 | { 38173 | const bool synthesis_result = 38174 | synthesize_sf3ext_expression:: 38175 | template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", (c0 * c1), v0, v1, result); 38176 | 38177 | exprtk_debug(("(c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1)\n")); 38178 | 38179 | return (synthesis_result) ? result : error_node(); 38180 | } 38181 | // (c0 / v0) / (c1 / v1) --> (covov) ((c0 / c1) * v1) / v0 38182 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 38183 | { 38184 | const bool synthesis_result = 38185 | synthesize_sf3ext_expression:: 38186 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v1, v0, result); 38187 | 38188 | exprtk_debug(("(c0 / v0) / (c1 / v1) --> (covov) ((c0 / c1) * v1) / v0\n")); 38189 | 38190 | return (synthesis_result) ? result : error_node(); 38191 | } 38192 | // (c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1) 38193 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) 38194 | { 38195 | const bool synthesis_result = 38196 | synthesize_sf3ext_expression:: 38197 | template compile<ctype, vtype, vtype>(expr_gen, "t*(t*t)", (c0 / c1), v0, v1, result); 38198 | 38199 | exprtk_debug(("(c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n")); 38200 | 38201 | return (synthesis_result) ? result : error_node(); 38202 | } 38203 | // (c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1) 38204 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38205 | { 38206 | const bool synthesis_result = 38207 | synthesize_sf3ext_expression:: 38208 | template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", (c0 / c1), v0, v1, result); 38209 | 38210 | exprtk_debug(("(c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1)\n")); 38211 | 38212 | return (synthesis_result) ? result : error_node(); 38213 | } 38214 | // (c * v0) +/- (c * v1) --> (covov) c * (v0 +/- v1) 38215 | else if ( 38216 | (std::equal_to<T>()(c0,c1)) && 38217 | (details::e_mul == o0) && 38218 | (details::e_mul == o2) && 38219 | ( 38220 | (details::e_add == o1) || 38221 | (details::e_sub == o1) 38222 | ) 38223 | ) 38224 | { 38225 | std::string specfunc; 38226 | 38227 | switch (o1) 38228 | { 38229 | case details::e_add : specfunc = "t*(t+t)" break; 38230 | case details::e_sub : specfunc = "t*(t-t)" break; 38231 | default : return error_node(); 38232 | } 38233 | 38234 | const bool synthesis_result = 38235 | synthesize_sf3ext_expression:: 38236 | template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result); 38237 | 38238 | exprtk_debug(("(c * v0) +/- (c * v1) --> (covov) c * (v0 +/- v1)\n")); 38239 | 38240 | return (synthesis_result) ? result : error_node(); 38241 | } 38242 | } 38243 | 38244 | const bool synthesis_result = 38245 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38246 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result); 38247 | 38248 | if (synthesis_result) 38249 | return result; 38250 | 38251 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38252 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 38253 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 38254 | 38255 | if (!expr_gen.valid_operator(o0,f0)) 38256 | return error_node(); 38257 | else if (!expr_gen.valid_operator(o1,f1)) 38258 | return error_node(); 38259 | else if (!expr_gen.valid_operator(o2,f2)) 38260 | return error_node(); 38261 | else 38262 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2); 38263 | } 38264 | 38265 | static inline std::string id(expression_generator<Type>& expr_gen, 38266 | const details::operator_type o0, 38267 | const details::operator_type o1, 38268 | const details::operator_type o2) 38269 | { 38270 | return details::build_string() 38271 | << "(t" << expr_gen.to_str(o0) 38272 | << "t)" << expr_gen.to_str(o1) 38273 | << "(t" << expr_gen.to_str(o2) 38274 | << "t)" 38275 | } 38276 | }; 38277 | 38278 | struct synthesize_vocovoc_expression0 38279 | { 38280 | typedef typename vocovoc_t::type0 node_type; 38281 | typedef typename vocovoc_t::sf4_type sf4_type; 38282 | typedef typename node_type::T0 T0; 38283 | typedef typename node_type::T1 T1; 38284 | typedef typename node_type::T2 T2; 38285 | typedef typename node_type::T3 T3; 38286 | 38287 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38288 | const details::operator_type& operation, 38289 | expression_node_ptr (&branch)[2]) 38290 | { 38291 | // (v0 o0 c0) o1 (v1 o2 c1) 38292 | const details::voc_base_node<Type>* voc0 = static_cast<details::voc_base_node<Type>*>(branch[0]); 38293 | const details::voc_base_node<Type>* voc1 = static_cast<details::voc_base_node<Type>*>(branch[1]); 38294 | const Type c0 = voc0->c(); 38295 | const Type& v0 = voc0->v(); 38296 | const Type c1 = voc1->c(); 38297 | const Type& v1 = voc1->v(); 38298 | const details::operator_type o0 = voc0->operation(); 38299 | const details::operator_type o1 = operation; 38300 | const details::operator_type o2 = voc1->operation(); 38301 | 38302 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 38303 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38304 | 38305 | expression_node_ptr result = error_node(); 38306 | 38307 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 38308 | { 38309 | // (v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1 38310 | if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2)) 38311 | { 38312 | const bool synthesis_result = 38313 | synthesize_sf3ext_expression:: 38314 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result); 38315 | 38316 | exprtk_debug(("(v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n")); 38317 | 38318 | return (synthesis_result) ? result : error_node(); 38319 | } 38320 | // (v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1 38321 | else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2)) 38322 | { 38323 | const bool synthesis_result = 38324 | synthesize_sf3ext_expression:: 38325 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result); 38326 | 38327 | exprtk_debug(("(v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n")); 38328 | 38329 | return (synthesis_result) ? result : error_node(); 38330 | } 38331 | // (v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1 38332 | else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2)) 38333 | { 38334 | const bool synthesis_result = 38335 | synthesize_sf3ext_expression:: 38336 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c1 - c0), v0, v1, result); 38337 | 38338 | exprtk_debug(("(v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1\n")); 38339 | 38340 | return (synthesis_result) ? result : error_node(); 38341 | } 38342 | // (v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1 38343 | else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2)) 38344 | { 38345 | const bool synthesis_result = 38346 | synthesize_sf3ext_expression:: 38347 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result); 38348 | 38349 | exprtk_debug(("(v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n")); 38350 | 38351 | return (synthesis_result) ? result : error_node(); 38352 | } 38353 | // (v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1) 38354 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38355 | { 38356 | const bool synthesis_result = 38357 | synthesize_sf3ext_expression:: 38358 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result); 38359 | 38360 | exprtk_debug(("(v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n")); 38361 | 38362 | return (synthesis_result) ? result : error_node(); 38363 | } 38364 | // (v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1 38365 | else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 38366 | { 38367 | const bool synthesis_result = 38368 | synthesize_sf3ext_expression:: 38369 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", Type(1) / (c0 * c1), v0, v1, result); 38370 | 38371 | exprtk_debug(("(v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1\n")); 38372 | 38373 | return (synthesis_result) ? result : error_node(); 38374 | } 38375 | // (v0 / c0) / (v1 / c1) --> (covov) ((c1 / c0) * v0) / v1 38376 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 38377 | { 38378 | const bool synthesis_result = 38379 | synthesize_sf3ext_expression:: 38380 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c1 / c0), v0, v1, result); 38381 | 38382 | exprtk_debug(("(v0 / c0) / (v1 / c1) --> (covov) ((c1 / c0) * v0) / v1\n")); 38383 | 38384 | return (synthesis_result) ? result : error_node(); 38385 | } 38386 | // (v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1) 38387 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) 38388 | { 38389 | const bool synthesis_result = 38390 | synthesize_sf3ext_expression:: 38391 | template compile<ctype, vtype, vtype>(expr_gen, "t*(t/t)", (c0 * c1), v0, v1, result); 38392 | 38393 | exprtk_debug(("(v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n")); 38394 | 38395 | return (synthesis_result) ? result : error_node(); 38396 | } 38397 | // (v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1 38398 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38399 | { 38400 | const bool synthesis_result = 38401 | synthesize_sf3ext_expression:: 38402 | template compile<ctype, vtype, vtype>(expr_gen, "t*(t/t)", Type(1) / (c0 * c1), v0, v1, result); 38403 | 38404 | exprtk_debug(("(v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1\n")); 38405 | 38406 | return (synthesis_result) ? result : error_node(); 38407 | } 38408 | // (v0 / c0) * (v1 + c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 + c1) 38409 | else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_add == o2)) 38410 | { 38411 | const bool synthesis_result = 38412 | synthesize_sf4ext_expression:: 38413 | template compile<vtype, ctype, vtype, ctype>(expr_gen, "(t*t)*(t+t)", v0, T(1) / c0, v1, c1, result); 38414 | 38415 | exprtk_debug(("(v0 / c0) * (v1 + c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 + c1)\n")); 38416 | 38417 | return (synthesis_result) ? result : error_node(); 38418 | } 38419 | // (v0 / c0) * (v1 - c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 - c1) 38420 | else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_sub == o2)) 38421 | { 38422 | const bool synthesis_result = 38423 | synthesize_sf4ext_expression:: 38424 | template compile<vtype, ctype, vtype, ctype>(expr_gen, "(t*t)*(t-t)", v0, T(1) / c0, v1, c1, result); 38425 | 38426 | exprtk_debug(("(v0 / c0) * (v1 - c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 - c1)\n")); 38427 | 38428 | return (synthesis_result) ? result : error_node(); 38429 | } 38430 | // (v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1) 38431 | else if ( 38432 | (std::equal_to<T>()(c0,c1)) && 38433 | (details::e_mul == o0) && 38434 | (details::e_mul == o2) && 38435 | ( 38436 | (details::e_add == o1) || 38437 | (details::e_sub == o1) 38438 | ) 38439 | ) 38440 | { 38441 | std::string specfunc; 38442 | 38443 | switch (o1) 38444 | { 38445 | case details::e_add : specfunc = "t*(t+t)" break; 38446 | case details::e_sub : specfunc = "t*(t-t)" break; 38447 | default : return error_node(); 38448 | } 38449 | 38450 | const bool synthesis_result = 38451 | synthesize_sf3ext_expression:: 38452 | template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result); 38453 | 38454 | exprtk_debug(("(v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n")); 38455 | 38456 | return (synthesis_result) ? result : error_node(); 38457 | } 38458 | // (v0 / c) +/- (v1 / c) --> (vovoc) (v0 +/- v1) / c 38459 | else if ( 38460 | (std::equal_to<T>()(c0,c1)) && 38461 | (details::e_div == o0) && 38462 | (details::e_div == o2) && 38463 | ( 38464 | (details::e_add == o1) || 38465 | (details::e_sub == o1) 38466 | ) 38467 | ) 38468 | { 38469 | std::string specfunc; 38470 | 38471 | switch (o1) 38472 | { 38473 | case details::e_add : specfunc = "(t+t)/t" break; 38474 | case details::e_sub : specfunc = "(t-t)/t" break; 38475 | default : return error_node(); 38476 | } 38477 | 38478 | const bool synthesis_result = 38479 | synthesize_sf3ext_expression:: 38480 | template compile<vtype, vtype, ctype>(expr_gen, specfunc, v0, v1, c0, result); 38481 | 38482 | exprtk_debug(("(v0 / c) +/- (v1 / c) --> (vovoc) (v0 +/- v1) / c\n")); 38483 | 38484 | return (synthesis_result) ? result : error_node(); 38485 | } 38486 | } 38487 | 38488 | const bool synthesis_result = 38489 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38490 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result); 38491 | 38492 | if (synthesis_result) 38493 | return result; 38494 | 38495 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38496 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 38497 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 38498 | 38499 | if (!expr_gen.valid_operator(o0,f0)) 38500 | return error_node(); 38501 | else if (!expr_gen.valid_operator(o1,f1)) 38502 | return error_node(); 38503 | else if (!expr_gen.valid_operator(o2,f2)) 38504 | return error_node(); 38505 | else 38506 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2); 38507 | } 38508 | 38509 | static inline std::string id(expression_generator<Type>& expr_gen, 38510 | const details::operator_type o0, 38511 | const details::operator_type o1, 38512 | const details::operator_type o2) 38513 | { 38514 | return details::build_string() 38515 | << "(t" << expr_gen.to_str(o0) 38516 | << "t)" << expr_gen.to_str(o1) 38517 | << "(t" << expr_gen.to_str(o2) 38518 | << "t)" 38519 | } 38520 | }; 38521 | 38522 | struct synthesize_covovoc_expression0 38523 | { 38524 | typedef typename covovoc_t::type0 node_type; 38525 | typedef typename covovoc_t::sf4_type sf4_type; 38526 | typedef typename node_type::T0 T0; 38527 | typedef typename node_type::T1 T1; 38528 | typedef typename node_type::T2 T2; 38529 | typedef typename node_type::T3 T3; 38530 | 38531 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38532 | const details::operator_type& operation, 38533 | expression_node_ptr (&branch)[2]) 38534 | { 38535 | // (c0 o0 v0) o1 (v1 o2 c1) 38536 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]); 38537 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]); 38538 | const Type c0 = cov->c(); 38539 | const Type& v0 = cov->v(); 38540 | const Type c1 = voc->c(); 38541 | const Type& v1 = voc->v(); 38542 | const details::operator_type o0 = cov->operation(); 38543 | const details::operator_type o1 = operation; 38544 | const details::operator_type o2 = voc->operation(); 38545 | 38546 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 38547 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38548 | 38549 | expression_node_ptr result = error_node(); 38550 | 38551 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 38552 | { 38553 | // (c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1 38554 | if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2)) 38555 | { 38556 | const bool synthesis_result = 38557 | synthesize_sf3ext_expression:: 38558 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result); 38559 | 38560 | exprtk_debug(("(c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n")); 38561 | 38562 | return (synthesis_result) ? result : error_node(); 38563 | } 38564 | // (c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1 38565 | else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2)) 38566 | { 38567 | const bool synthesis_result = 38568 | synthesize_sf3ext_expression:: 38569 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result); 38570 | 38571 | exprtk_debug(("(c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n")); 38572 | 38573 | return (synthesis_result) ? result : error_node(); 38574 | } 38575 | // (c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1 38576 | else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2)) 38577 | { 38578 | const bool synthesis_result = 38579 | synthesize_sf3ext_expression:: 38580 | template compile<ctype, vtype, vtype>(expr_gen, "t-(t+t)", (c0 + c1), v0, v1, result); 38581 | 38582 | exprtk_debug(("(c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1\n")); 38583 | 38584 | return (synthesis_result) ? result : error_node(); 38585 | } 38586 | // (c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1 38587 | else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2)) 38588 | { 38589 | const bool synthesis_result = 38590 | synthesize_sf3ext_expression:: 38591 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result); 38592 | 38593 | exprtk_debug(("(c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n")); 38594 | 38595 | return (synthesis_result) ? result : error_node(); 38596 | } 38597 | // (c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1) 38598 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38599 | { 38600 | const bool synthesis_result = 38601 | synthesize_sf3ext_expression:: 38602 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result); 38603 | 38604 | exprtk_debug(("(c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n")); 38605 | 38606 | return (synthesis_result) ? result : error_node(); 38607 | } 38608 | // (c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0) 38609 | else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 38610 | { 38611 | const bool synthesis_result = 38612 | synthesize_sf3ext_expression:: 38613 | template compile<ctype, vtype, vtype>(expr_gen, "t*(t/t)", (c0 / c1), v1, v0, result); 38614 | 38615 | exprtk_debug(("(c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0)\n")); 38616 | 38617 | return (synthesis_result) ? result : error_node(); 38618 | } 38619 | // (c0 / v0) / (v1 / c1) --> (covov) (c0 * c1) / (v0 * v1) 38620 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 38621 | { 38622 | const bool synthesis_result = 38623 | synthesize_sf3ext_expression:: 38624 | template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", (c0 * c1), v0, v1, result); 38625 | 38626 | exprtk_debug(("(c0 / v0) / (v1 / c1) --> (covov) (c0 * c1) / (v0 * v1)\n")); 38627 | 38628 | return (synthesis_result) ? result : error_node(); 38629 | } 38630 | // (c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1) 38631 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) 38632 | { 38633 | const bool synthesis_result = 38634 | synthesize_sf3ext_expression:: 38635 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 * c1), v0, v1, result); 38636 | 38637 | exprtk_debug(("(c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n")); 38638 | 38639 | return (synthesis_result) ? result : error_node(); 38640 | } 38641 | // (c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1) 38642 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38643 | { 38644 | const bool synthesis_result = 38645 | synthesize_sf3ext_expression:: 38646 | template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", (c0 / c1), v0, v1, result); 38647 | 38648 | exprtk_debug(("(c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1)\n")); 38649 | 38650 | return (synthesis_result) ? result : error_node(); 38651 | } 38652 | // (c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1) 38653 | else if ( 38654 | (std::equal_to<T>()(c0,c1)) && 38655 | (details::e_mul == o0) && 38656 | (details::e_mul == o2) && 38657 | ( 38658 | (details::e_add == o1) || 38659 | (details::e_sub == o1) 38660 | ) 38661 | ) 38662 | { 38663 | std::string specfunc; 38664 | 38665 | switch (o1) 38666 | { 38667 | case details::e_add : specfunc = "t*(t+t)" break; 38668 | case details::e_sub : specfunc = "t*(t-t)" break; 38669 | default : return error_node(); 38670 | } 38671 | 38672 | const bool synthesis_result = 38673 | synthesize_sf3ext_expression:: 38674 | template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result); 38675 | 38676 | exprtk_debug(("(c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n")); 38677 | 38678 | return (synthesis_result) ? result : error_node(); 38679 | } 38680 | } 38681 | 38682 | const bool synthesis_result = 38683 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38684 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result); 38685 | 38686 | if (synthesis_result) 38687 | return result; 38688 | 38689 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38690 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 38691 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 38692 | 38693 | if (!expr_gen.valid_operator(o0,f0)) 38694 | return error_node(); 38695 | else if (!expr_gen.valid_operator(o1,f1)) 38696 | return error_node(); 38697 | else if (!expr_gen.valid_operator(o2,f2)) 38698 | return error_node(); 38699 | else 38700 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2); 38701 | } 38702 | 38703 | static inline std::string id(expression_generator<Type>& expr_gen, 38704 | const details::operator_type o0, 38705 | const details::operator_type o1, 38706 | const details::operator_type o2) 38707 | { 38708 | return details::build_string() 38709 | << "(t" << expr_gen.to_str(o0) 38710 | << "t)" << expr_gen.to_str(o1) 38711 | << "(t" << expr_gen.to_str(o2) 38712 | << "t)" 38713 | } 38714 | }; 38715 | 38716 | struct synthesize_vococov_expression0 38717 | { 38718 | typedef typename vococov_t::type0 node_type; 38719 | typedef typename vococov_t::sf4_type sf4_type; 38720 | typedef typename node_type::T0 T0; 38721 | typedef typename node_type::T1 T1; 38722 | typedef typename node_type::T2 T2; 38723 | typedef typename node_type::T3 T3; 38724 | 38725 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38726 | const details::operator_type& operation, 38727 | expression_node_ptr (&branch)[2]) 38728 | { 38729 | // (v0 o0 c0) o1 (c1 o2 v1) 38730 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]); 38731 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]); 38732 | const Type c0 = voc->c(); 38733 | const Type& v0 = voc->v(); 38734 | const Type c1 = cov->c(); 38735 | const Type& v1 = cov->v(); 38736 | const details::operator_type o0 = voc->operation(); 38737 | const details::operator_type o1 = operation; 38738 | const details::operator_type o2 = cov->operation(); 38739 | 38740 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 38741 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38742 | 38743 | expression_node_ptr result = error_node(); 38744 | 38745 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 38746 | { 38747 | // (v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1 38748 | if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2)) 38749 | { 38750 | const bool synthesis_result = 38751 | synthesize_sf3ext_expression:: 38752 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result); 38753 | 38754 | exprtk_debug(("(v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n")); 38755 | 38756 | return (synthesis_result) ? result : error_node(); 38757 | } 38758 | // (v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1 38759 | else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2)) 38760 | { 38761 | const bool synthesis_result = 38762 | synthesize_sf3ext_expression:: 38763 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result); 38764 | 38765 | exprtk_debug(("(v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n")); 38766 | 38767 | return (synthesis_result) ? result : error_node(); 38768 | } 38769 | // (v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0) 38770 | else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2)) 38771 | { 38772 | const bool synthesis_result = 38773 | synthesize_sf3ext_expression:: 38774 | template compile<vtype, vtype, ctype>(expr_gen, "(t+t)-t", v0, v1, (c1 + c0), result); 38775 | 38776 | exprtk_debug(("(v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0)\n")); 38777 | 38778 | return (synthesis_result) ? result : error_node(); 38779 | } 38780 | // (v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1 38781 | else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2)) 38782 | { 38783 | const bool synthesis_result = 38784 | synthesize_sf3ext_expression:: 38785 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result); 38786 | 38787 | exprtk_debug(("(v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n")); 38788 | 38789 | return (synthesis_result) ? result : error_node(); 38790 | } 38791 | // (v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1) 38792 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38793 | { 38794 | const bool synthesis_result = 38795 | synthesize_sf3ext_expression:: 38796 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result); 38797 | 38798 | exprtk_debug(("(v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1)\n")); 38799 | 38800 | return (synthesis_result) ? result : error_node(); 38801 | } 38802 | // (v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1) 38803 | else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 38804 | { 38805 | const bool synthesis_result = 38806 | synthesize_sf3ext_expression:: 38807 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c1 / c0), v0, v1, result); 38808 | 38809 | exprtk_debug(("(v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1)\n")); 38810 | 38811 | return (synthesis_result) ? result : error_node(); 38812 | } 38813 | // (v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1) 38814 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) 38815 | { 38816 | const bool synthesis_result = 38817 | synthesize_sf3ext_expression:: 38818 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 / c1), v0, v1, result); 38819 | 38820 | exprtk_debug(("(v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n")); 38821 | 38822 | return (synthesis_result) ? result : error_node(); 38823 | } 38824 | // (v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1) 38825 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38826 | { 38827 | const bool synthesis_result = 38828 | synthesize_sf3ext_expression:: 38829 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", Type(1) / (c0 * c1), v0, v1, result); 38830 | 38831 | exprtk_debug(("(v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1)\n")); 38832 | 38833 | return (synthesis_result) ? result : error_node(); 38834 | } 38835 | // (v0 / c0) / (c1 / v1) --> (vovoc) (v0 * v1) * (1 / (c0 * c1)) 38836 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 38837 | { 38838 | const bool synthesis_result = 38839 | synthesize_sf3ext_expression:: 38840 | template compile<vtype, vtype, ctype>(expr_gen, "(t*t)*t", v0, v1, Type(1) / (c0 * c1), result); 38841 | 38842 | exprtk_debug(("(v0 / c0) / (c1 / v1) --> (vovoc) (v0 * v1) * (1 / (c0 * c1))\n")); 38843 | 38844 | return (synthesis_result) ? result : error_node(); 38845 | } 38846 | // (v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1) 38847 | else if ( 38848 | (std::equal_to<T>()(c0,c1)) && 38849 | (details::e_mul == o0) && 38850 | (details::e_mul == o2) && 38851 | ( 38852 | (details::e_add == o1) || (details::e_sub == o1) 38853 | ) 38854 | ) 38855 | { 38856 | std::string specfunc; 38857 | 38858 | switch (o1) 38859 | { 38860 | case details::e_add : specfunc = "t*(t+t)" break; 38861 | case details::e_sub : specfunc = "t*(t-t)" break; 38862 | default : return error_node(); 38863 | } 38864 | 38865 | const bool synthesis_result = 38866 | synthesize_sf3ext_expression:: 38867 | template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result); 38868 | 38869 | exprtk_debug(("(v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1)\n")); 38870 | 38871 | return (synthesis_result) ? result : error_node(); 38872 | } 38873 | } 38874 | 38875 | const bool synthesis_result = 38876 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38877 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result); 38878 | 38879 | if (synthesis_result) 38880 | return result; 38881 | 38882 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38883 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 38884 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 38885 | 38886 | if (!expr_gen.valid_operator(o0,f0)) 38887 | return error_node(); 38888 | else if (!expr_gen.valid_operator(o1,f1)) 38889 | return error_node(); 38890 | else if (!expr_gen.valid_operator(o2,f2)) 38891 | return error_node(); 38892 | else 38893 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2); 38894 | } 38895 | 38896 | static inline std::string id(expression_generator<Type>& expr_gen, 38897 | const details::operator_type o0, 38898 | const details::operator_type o1, 38899 | const details::operator_type o2) 38900 | { 38901 | return details::build_string() 38902 | << "(t" << expr_gen.to_str(o0) 38903 | << "t)" << expr_gen.to_str(o1) 38904 | << "(t" << expr_gen.to_str(o2) 38905 | << "t)" 38906 | } 38907 | }; 38908 | 38909 | struct synthesize_vovovov_expression1 38910 | { 38911 | typedef typename vovovov_t::type1 node_type; 38912 | typedef typename vovovov_t::sf4_type sf4_type; 38913 | typedef typename node_type::T0 T0; 38914 | typedef typename node_type::T1 T1; 38915 | typedef typename node_type::T2 T2; 38916 | typedef typename node_type::T3 T3; 38917 | 38918 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38919 | const details::operator_type& operation, 38920 | expression_node_ptr (&branch)[2]) 38921 | { 38922 | // v0 o0 (v1 o1 (v2 o2 v3)) 38923 | typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t; 38924 | 38925 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]); 38926 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 38927 | const Type& v1 = vovov->t0(); 38928 | const Type& v2 = vovov->t1(); 38929 | const Type& v3 = vovov->t2(); 38930 | const details::operator_type o0 = operation; 38931 | const details::operator_type o1 = expr_gen.get_operator(vovov->f0()); 38932 | const details::operator_type o2 = expr_gen.get_operator(vovov->f1()); 38933 | 38934 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38935 | binary_functor_t f1 = vovov->f0(); 38936 | binary_functor_t f2 = vovov->f1(); 38937 | 38938 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38939 | 38940 | expression_node_ptr result = error_node(); 38941 | 38942 | const bool synthesis_result = 38943 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38944 | (expr_gen,id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result); 38945 | 38946 | if (synthesis_result) 38947 | return result; 38948 | else if (!expr_gen.valid_operator(o0,f0)) 38949 | return error_node(); 38950 | 38951 | exprtk_debug(("v0 o0 (v1 o1 (v2 o2 v3))\n")); 38952 | 38953 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2); 38954 | } 38955 | 38956 | static inline std::string id(expression_generator<Type>& expr_gen, 38957 | const details::operator_type o0, 38958 | const details::operator_type o1, 38959 | const details::operator_type o2) 38960 | { 38961 | return details::build_string() 38962 | << "t" << expr_gen.to_str(o0) 38963 | << "(t" << expr_gen.to_str(o1) 38964 | << "(t" << expr_gen.to_str(o2) 38965 | << "t))" 38966 | } 38967 | }; 38968 | 38969 | struct synthesize_vovovoc_expression1 38970 | { 38971 | typedef typename vovovoc_t::type1 node_type; 38972 | typedef typename vovovoc_t::sf4_type sf4_type; 38973 | typedef typename node_type::T0 T0; 38974 | typedef typename node_type::T1 T1; 38975 | typedef typename node_type::T2 T2; 38976 | typedef typename node_type::T3 T3; 38977 | 38978 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38979 | const details::operator_type& operation, 38980 | expression_node_ptr (&branch)[2]) 38981 | { 38982 | // v0 o0 (v1 o1 (v2 o2 c)) 38983 | typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t; 38984 | 38985 | const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]); 38986 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 38987 | const Type& v1 = vovoc->t0(); 38988 | const Type& v2 = vovoc->t1(); 38989 | const Type c = vovoc->t2(); 38990 | const details::operator_type o0 = operation; 38991 | const details::operator_type o1 = expr_gen.get_operator(vovoc->f0()); 38992 | const details::operator_type o2 = expr_gen.get_operator(vovoc->f1()); 38993 | 38994 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38995 | binary_functor_t f1 = vovoc->f0(); 38996 | binary_functor_t f2 = vovoc->f1(); 38997 | 38998 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38999 | 39000 | expression_node_ptr result = error_node(); 39001 | 39002 | const bool synthesis_result = 39003 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39004 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result); 39005 | 39006 | if (synthesis_result) 39007 | return result; 39008 | else if (!expr_gen.valid_operator(o0,f0)) 39009 | return error_node(); 39010 | 39011 | exprtk_debug(("v0 o0 (v1 o1 (v2 o2 c))\n")); 39012 | 39013 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2); 39014 | } 39015 | 39016 | static inline std::string id(expression_generator<Type>& expr_gen, 39017 | const details::operator_type o0, 39018 | const details::operator_type o1, 39019 | const details::operator_type o2) 39020 | { 39021 | return details::build_string() 39022 | << "t" << expr_gen.to_str(o0) 39023 | << "(t" << expr_gen.to_str(o1) 39024 | << "(t" << expr_gen.to_str(o2) 39025 | << "t))" 39026 | } 39027 | }; 39028 | 39029 | struct synthesize_vovocov_expression1 39030 | { 39031 | typedef typename vovocov_t::type1 node_type; 39032 | typedef typename vovocov_t::sf4_type sf4_type; 39033 | typedef typename node_type::T0 T0; 39034 | typedef typename node_type::T1 T1; 39035 | typedef typename node_type::T2 T2; 39036 | typedef typename node_type::T3 T3; 39037 | 39038 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39039 | const details::operator_type& operation, 39040 | expression_node_ptr (&branch)[2]) 39041 | { 39042 | // v0 o0 (v1 o1 (c o2 v2)) 39043 | typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t; 39044 | 39045 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]); 39046 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39047 | const Type& v1 = vocov->t0(); 39048 | const Type c = vocov->t1(); 39049 | const Type& v2 = vocov->t2(); 39050 | const details::operator_type o0 = operation; 39051 | const details::operator_type o1 = expr_gen.get_operator(vocov->f0()); 39052 | const details::operator_type o2 = expr_gen.get_operator(vocov->f1()); 39053 | 39054 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39055 | binary_functor_t f1 = vocov->f0(); 39056 | binary_functor_t f2 = vocov->f1(); 39057 | 39058 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39059 | 39060 | expression_node_ptr result = error_node(); 39061 | 39062 | const bool synthesis_result = 39063 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39064 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result); 39065 | 39066 | if (synthesis_result) 39067 | return result; 39068 | if (!expr_gen.valid_operator(o0,f0)) 39069 | return error_node(); 39070 | 39071 | exprtk_debug(("v0 o0 (v1 o1 (c o2 v2))\n")); 39072 | 39073 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2); 39074 | } 39075 | 39076 | static inline std::string id(expression_generator<Type>& expr_gen, 39077 | const details::operator_type o0, 39078 | const details::operator_type o1, 39079 | const details::operator_type o2) 39080 | { 39081 | return details::build_string() 39082 | << "t" << expr_gen.to_str(o0) 39083 | << "(t" << expr_gen.to_str(o1) 39084 | << "(t" << expr_gen.to_str(o2) 39085 | << "t))" 39086 | } 39087 | }; 39088 | 39089 | struct synthesize_vocovov_expression1 39090 | { 39091 | typedef typename vocovov_t::type1 node_type; 39092 | typedef typename vocovov_t::sf4_type sf4_type; 39093 | typedef typename node_type::T0 T0; 39094 | typedef typename node_type::T1 T1; 39095 | typedef typename node_type::T2 T2; 39096 | typedef typename node_type::T3 T3; 39097 | 39098 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39099 | const details::operator_type& operation, 39100 | expression_node_ptr (&branch)[2]) 39101 | { 39102 | // v0 o0 (c o1 (v1 o2 v2)) 39103 | typedef typename synthesize_covov_expression1::node_type lcl_covov_t; 39104 | 39105 | const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[1]); 39106 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39107 | const Type c = covov->t0(); 39108 | const Type& v1 = covov->t1(); 39109 | const Type& v2 = covov->t2(); 39110 | const details::operator_type o0 = operation; 39111 | const details::operator_type o1 = expr_gen.get_operator(covov->f0()); 39112 | const details::operator_type o2 = expr_gen.get_operator(covov->f1()); 39113 | 39114 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39115 | binary_functor_t f1 = covov->f0(); 39116 | binary_functor_t f2 = covov->f1(); 39117 | 39118 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39119 | 39120 | expression_node_ptr result = error_node(); 39121 | 39122 | const bool synthesis_result = 39123 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39124 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result); 39125 | 39126 | if (synthesis_result) 39127 | return result; 39128 | else if (!expr_gen.valid_operator(o0,f0)) 39129 | return error_node(); 39130 | 39131 | exprtk_debug(("v0 o0 (c o1 (v1 o2 v2))\n")); 39132 | 39133 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2); 39134 | } 39135 | 39136 | static inline std::string id(expression_generator<Type>& expr_gen, 39137 | const details::operator_type o0, 39138 | const details::operator_type o1, 39139 | const details::operator_type o2) 39140 | { 39141 | return details::build_string() 39142 | << "t" << expr_gen.to_str(o0) 39143 | << "(t" << expr_gen.to_str(o1) 39144 | << "(t" << expr_gen.to_str(o2) 39145 | << "t))" 39146 | } 39147 | }; 39148 | 39149 | struct synthesize_covovov_expression1 39150 | { 39151 | typedef typename covovov_t::type1 node_type; 39152 | typedef typename covovov_t::sf4_type sf4_type; 39153 | typedef typename node_type::T0 T0; 39154 | typedef typename node_type::T1 T1; 39155 | typedef typename node_type::T2 T2; 39156 | typedef typename node_type::T3 T3; 39157 | 39158 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39159 | const details::operator_type& operation, 39160 | expression_node_ptr (&branch)[2]) 39161 | { 39162 | // c o0 (v0 o1 (v1 o2 v2)) 39163 | typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t; 39164 | 39165 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]); 39166 | const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); 39167 | const Type& v0 = vovov->t0(); 39168 | const Type& v1 = vovov->t1(); 39169 | const Type& v2 = vovov->t2(); 39170 | const details::operator_type o0 = operation; 39171 | const details::operator_type o1 = expr_gen.get_operator(vovov->f0()); 39172 | const details::operator_type o2 = expr_gen.get_operator(vovov->f1()); 39173 | 39174 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39175 | binary_functor_t f1 = vovov->f0(); 39176 | binary_functor_t f2 = vovov->f1(); 39177 | 39178 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39179 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39180 | 39181 | expression_node_ptr result = error_node(); 39182 | 39183 | const bool synthesis_result = 39184 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39185 | (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result); 39186 | 39187 | if (synthesis_result) 39188 | return result; 39189 | if (!expr_gen.valid_operator(o0,f0)) 39190 | return error_node(); 39191 | 39192 | exprtk_debug(("c o0 (v0 o1 (v1 o2 v2))\n")); 39193 | 39194 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2); 39195 | } 39196 | 39197 | static inline std::string id(expression_generator<Type>& expr_gen, 39198 | const details::operator_type o0, 39199 | const details::operator_type o1, 39200 | const details::operator_type o2) 39201 | { 39202 | return details::build_string() 39203 | << "t" << expr_gen.to_str(o0) 39204 | << "(t" << expr_gen.to_str(o1) 39205 | << "(t" << expr_gen.to_str(o2) 39206 | << "t))" 39207 | } 39208 | }; 39209 | 39210 | struct synthesize_covocov_expression1 39211 | { 39212 | typedef typename covocov_t::type1 node_type; 39213 | typedef typename covocov_t::sf4_type sf4_type; 39214 | typedef typename node_type::T0 T0; 39215 | typedef typename node_type::T1 T1; 39216 | typedef typename node_type::T2 T2; 39217 | typedef typename node_type::T3 T3; 39218 | 39219 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39220 | const details::operator_type& operation, 39221 | expression_node_ptr (&branch)[2]) 39222 | { 39223 | // c0 o0 (v0 o1 (c1 o2 v1)) 39224 | typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t; 39225 | 39226 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]); 39227 | const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); 39228 | const Type& v0 = vocov->t0(); 39229 | const Type c1 = vocov->t1(); 39230 | const Type& v1 = vocov->t2(); 39231 | const details::operator_type o0 = operation; 39232 | const details::operator_type o1 = expr_gen.get_operator(vocov->f0()); 39233 | const details::operator_type o2 = expr_gen.get_operator(vocov->f1()); 39234 | 39235 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39236 | binary_functor_t f1 = vocov->f0(); 39237 | binary_functor_t f2 = vocov->f1(); 39238 | 39239 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39240 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39241 | 39242 | expression_node_ptr result = error_node(); 39243 | 39244 | const bool synthesis_result = 39245 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39246 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result); 39247 | 39248 | if (synthesis_result) 39249 | return result; 39250 | else if (!expr_gen.valid_operator(o0,f0)) 39251 | return error_node(); 39252 | 39253 | exprtk_debug(("c0 o0 (v0 o1 (c1 o2 v1))\n")); 39254 | 39255 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2); 39256 | } 39257 | 39258 | static inline std::string id(expression_generator<Type>& expr_gen, 39259 | const details::operator_type o0, 39260 | const details::operator_type o1, 39261 | const details::operator_type o2) 39262 | { 39263 | return details::build_string() 39264 | << "t" << expr_gen.to_str(o0) 39265 | << "(t" << expr_gen.to_str(o1) 39266 | << "(t" << expr_gen.to_str(o2) 39267 | << "t))" 39268 | } 39269 | }; 39270 | 39271 | struct synthesize_vocovoc_expression1 39272 | { 39273 | typedef typename vocovoc_t::type1 node_type; 39274 | typedef typename vocovoc_t::sf4_type sf4_type; 39275 | typedef typename node_type::T0 T0; 39276 | typedef typename node_type::T1 T1; 39277 | typedef typename node_type::T2 T2; 39278 | typedef typename node_type::T3 T3; 39279 | 39280 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39281 | const details::operator_type& operation, 39282 | expression_node_ptr (&branch)[2]) 39283 | { 39284 | // v0 o0 (c0 o1 (v1 o2 c2)) 39285 | typedef typename synthesize_covoc_expression1::node_type lcl_covoc_t; 39286 | 39287 | const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[1]); 39288 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39289 | const Type c0 = covoc->t0(); 39290 | const Type& v1 = covoc->t1(); 39291 | const Type c1 = covoc->t2(); 39292 | const details::operator_type o0 = operation; 39293 | const details::operator_type o1 = expr_gen.get_operator(covoc->f0()); 39294 | const details::operator_type o2 = expr_gen.get_operator(covoc->f1()); 39295 | 39296 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39297 | binary_functor_t f1 = covoc->f0(); 39298 | binary_functor_t f2 = covoc->f1(); 39299 | 39300 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39301 | 39302 | expression_node_ptr result = error_node(); 39303 | 39304 | const bool synthesis_result = 39305 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39306 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result); 39307 | 39308 | if (synthesis_result) 39309 | return result; 39310 | else if (!expr_gen.valid_operator(o0,f0)) 39311 | return error_node(); 39312 | 39313 | exprtk_debug(("v0 o0 (c0 o1 (v1 o2 c2))\n")); 39314 | 39315 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2); 39316 | } 39317 | 39318 | static inline std::string id(expression_generator<Type>& expr_gen, 39319 | const details::operator_type o0, 39320 | const details::operator_type o1, 39321 | const details::operator_type o2) 39322 | { 39323 | return details::build_string() 39324 | << "t" << expr_gen.to_str(o0) 39325 | << "(t" << expr_gen.to_str(o1) 39326 | << "(t" << expr_gen.to_str(o2) 39327 | << "t))" 39328 | } 39329 | }; 39330 | 39331 | struct synthesize_covovoc_expression1 39332 | { 39333 | typedef typename covovoc_t::type1 node_type; 39334 | typedef typename covovoc_t::sf4_type sf4_type; 39335 | typedef typename node_type::T0 T0; 39336 | typedef typename node_type::T1 T1; 39337 | typedef typename node_type::T2 T2; 39338 | typedef typename node_type::T3 T3; 39339 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39340 | const details::operator_type& operation, 39341 | expression_node_ptr (&branch)[2]) 39342 | { 39343 | // c0 o0 (v0 o1 (v1 o2 c1)) 39344 | typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t; 39345 | 39346 | const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]); 39347 | const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); 39348 | const Type& v0 = vovoc->t0(); 39349 | const Type& v1 = vovoc->t1(); 39350 | const Type c1 = vovoc->t2(); 39351 | const details::operator_type o0 = operation; 39352 | const details::operator_type o1 = expr_gen.get_operator(vovoc->f0()); 39353 | const details::operator_type o2 = expr_gen.get_operator(vovoc->f1()); 39354 | 39355 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39356 | binary_functor_t f1 = vovoc->f0(); 39357 | binary_functor_t f2 = vovoc->f1(); 39358 | 39359 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39360 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39361 | 39362 | expression_node_ptr result = error_node(); 39363 | 39364 | const bool synthesis_result = 39365 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39366 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result); 39367 | 39368 | if (synthesis_result) 39369 | return result; 39370 | else if (!expr_gen.valid_operator(o0,f0)) 39371 | return error_node(); 39372 | 39373 | exprtk_debug(("c0 o0 (v0 o1 (v1 o2 c1))\n")); 39374 | 39375 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2); 39376 | } 39377 | 39378 | static inline std::string id(expression_generator<Type>& expr_gen, 39379 | const details::operator_type o0, 39380 | const details::operator_type o1, 39381 | const details::operator_type o2) 39382 | { 39383 | return details::build_string() 39384 | << "t" << expr_gen.to_str(o0) 39385 | << "(t" << expr_gen.to_str(o1) 39386 | << "(t" << expr_gen.to_str(o2) 39387 | << "t))" 39388 | } 39389 | }; 39390 | 39391 | struct synthesize_vococov_expression1 39392 | { 39393 | typedef typename vococov_t::type1 node_type; 39394 | typedef typename vococov_t::sf4_type sf4_type; 39395 | typedef typename node_type::T0 T0; 39396 | typedef typename node_type::T1 T1; 39397 | typedef typename node_type::T2 T2; 39398 | typedef typename node_type::T3 T3; 39399 | 39400 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39401 | const details::operator_type& operation, 39402 | expression_node_ptr (&branch)[2]) 39403 | { 39404 | // v0 o0 (c0 o1 (c1 o2 v1)) 39405 | typedef typename synthesize_cocov_expression1::node_type lcl_cocov_t; 39406 | 39407 | const lcl_cocov_t* cocov = static_cast<const lcl_cocov_t*>(branch[1]); 39408 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39409 | const Type c0 = cocov->t0(); 39410 | const Type c1 = cocov->t1(); 39411 | const Type& v1 = cocov->t2(); 39412 | const details::operator_type o0 = operation; 39413 | const details::operator_type o1 = expr_gen.get_operator(cocov->f0()); 39414 | const details::operator_type o2 = expr_gen.get_operator(cocov->f1()); 39415 | 39416 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39417 | binary_functor_t f1 = cocov->f0(); 39418 | binary_functor_t f2 = cocov->f1(); 39419 | 39420 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39421 | 39422 | expression_node_ptr result = error_node(); 39423 | 39424 | const bool synthesis_result = 39425 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39426 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result); 39427 | 39428 | if (synthesis_result) 39429 | return result; 39430 | else if (!expr_gen.valid_operator(o0,f0)) 39431 | return error_node(); 39432 | 39433 | exprtk_debug(("v0 o0 (c0 o1 (c1 o2 v1))\n")); 39434 | 39435 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2); 39436 | } 39437 | 39438 | static inline std::string id(expression_generator<Type>& expr_gen, 39439 | const details::operator_type o0, 39440 | const details::operator_type o1, 39441 | const details::operator_type o2) 39442 | { 39443 | return details::build_string() 39444 | << "t" << expr_gen.to_str(o0) 39445 | << "(t" << expr_gen.to_str(o1) 39446 | << "(t" << expr_gen.to_str(o2) 39447 | << "t))" 39448 | } 39449 | }; 39450 | 39451 | struct synthesize_vovovov_expression2 39452 | { 39453 | typedef typename vovovov_t::type2 node_type; 39454 | typedef typename vovovov_t::sf4_type sf4_type; 39455 | typedef typename node_type::T0 T0; 39456 | typedef typename node_type::T1 T1; 39457 | typedef typename node_type::T2 T2; 39458 | typedef typename node_type::T3 T3; 39459 | 39460 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39461 | const details::operator_type& operation, 39462 | expression_node_ptr (&branch)[2]) 39463 | { 39464 | // v0 o0 ((v1 o1 v2) o2 v3) 39465 | typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t; 39466 | 39467 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]); 39468 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39469 | const Type& v1 = vovov->t0(); 39470 | const Type& v2 = vovov->t1(); 39471 | const Type& v3 = vovov->t2(); 39472 | const details::operator_type o0 = operation; 39473 | const details::operator_type o1 = expr_gen.get_operator(vovov->f0()); 39474 | const details::operator_type o2 = expr_gen.get_operator(vovov->f1()); 39475 | 39476 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39477 | binary_functor_t f1 = vovov->f0(); 39478 | binary_functor_t f2 = vovov->f1(); 39479 | 39480 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39481 | 39482 | expression_node_ptr result = error_node(); 39483 | 39484 | const bool synthesis_result = 39485 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39486 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result); 39487 | 39488 | if (synthesis_result) 39489 | return result; 39490 | else if (!expr_gen.valid_operator(o0,f0)) 39491 | return error_node(); 39492 | 39493 | exprtk_debug(("v0 o0 ((v1 o1 v2) o2 v3)\n")); 39494 | 39495 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2); 39496 | } 39497 | 39498 | static inline std::string id(expression_generator<Type>& expr_gen, 39499 | const details::operator_type o0, 39500 | const details::operator_type o1, 39501 | const details::operator_type o2) 39502 | { 39503 | return details::build_string() 39504 | << "t" << expr_gen.to_str(o0) 39505 | << "((t" << expr_gen.to_str(o1) 39506 | << "t)" << expr_gen.to_str(o2) 39507 | << "t)" 39508 | } 39509 | }; 39510 | 39511 | struct synthesize_vovovoc_expression2 39512 | { 39513 | typedef typename vovovoc_t::type2 node_type; 39514 | typedef typename vovovoc_t::sf4_type sf4_type; 39515 | typedef typename node_type::T0 T0; 39516 | typedef typename node_type::T1 T1; 39517 | typedef typename node_type::T2 T2; 39518 | typedef typename node_type::T3 T3; 39519 | 39520 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39521 | const details::operator_type& operation, 39522 | expression_node_ptr (&branch)[2]) 39523 | { 39524 | // v0 o0 ((v1 o1 v2) o2 c) 39525 | typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t; 39526 | 39527 | const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]); 39528 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39529 | const Type& v1 = vovoc->t0(); 39530 | const Type& v2 = vovoc->t1(); 39531 | const Type c = vovoc->t2(); 39532 | const details::operator_type o0 = operation; 39533 | const details::operator_type o1 = expr_gen.get_operator(vovoc->f0()); 39534 | const details::operator_type o2 = expr_gen.get_operator(vovoc->f1()); 39535 | 39536 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39537 | binary_functor_t f1 = vovoc->f0(); 39538 | binary_functor_t f2 = vovoc->f1(); 39539 | 39540 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39541 | 39542 | expression_node_ptr result = error_node(); 39543 | 39544 | const bool synthesis_result = 39545 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39546 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result); 39547 | 39548 | if (synthesis_result) 39549 | return result; 39550 | else if (!expr_gen.valid_operator(o0,f0)) 39551 | return error_node(); 39552 | 39553 | exprtk_debug(("v0 o0 ((v1 o1 v2) o2 c)\n")); 39554 | 39555 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2); 39556 | } 39557 | 39558 | static inline std::string id(expression_generator<Type>& expr_gen, 39559 | const details::operator_type o0, 39560 | const details::operator_type o1, 39561 | const details::operator_type o2) 39562 | { 39563 | return details::build_string() 39564 | << "t" << expr_gen.to_str(o0) 39565 | << "((t" << expr_gen.to_str(o1) 39566 | << "t)" << expr_gen.to_str(o2) 39567 | << "t)" 39568 | } 39569 | }; 39570 | 39571 | struct synthesize_vovocov_expression2 39572 | { 39573 | typedef typename vovocov_t::type2 node_type; 39574 | typedef typename vovocov_t::sf4_type sf4_type; 39575 | typedef typename node_type::T0 T0; 39576 | typedef typename node_type::T1 T1; 39577 | typedef typename node_type::T2 T2; 39578 | typedef typename node_type::T3 T3; 39579 | 39580 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39581 | const details::operator_type& operation, 39582 | expression_node_ptr (&branch)[2]) 39583 | { 39584 | // v0 o0 ((v1 o1 c) o2 v2) 39585 | typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t; 39586 | 39587 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]); 39588 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39589 | const Type& v1 = vocov->t0(); 39590 | const Type c = vocov->t1(); 39591 | const Type& v2 = vocov->t2(); 39592 | const details::operator_type o0 = operation; 39593 | const details::operator_type o1 = expr_gen.get_operator(vocov->f0()); 39594 | const details::operator_type o2 = expr_gen.get_operator(vocov->f1()); 39595 | 39596 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39597 | binary_functor_t f1 = vocov->f0(); 39598 | binary_functor_t f2 = vocov->f1(); 39599 | 39600 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39601 | 39602 | expression_node_ptr result = error_node(); 39603 | 39604 | const bool synthesis_result = 39605 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39606 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result); 39607 | 39608 | if (synthesis_result) 39609 | return result; 39610 | else if (!expr_gen.valid_operator(o0,f0)) 39611 | return error_node(); 39612 | 39613 | exprtk_debug(("v0 o0 ((v1 o1 c) o2 v2)\n")); 39614 | 39615 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2); 39616 | } 39617 | 39618 | static inline std::string id(expression_generator<Type>& expr_gen, 39619 | const details::operator_type o0, 39620 | const details::operator_type o1, 39621 | const details::operator_type o2) 39622 | { 39623 | return details::build_string() 39624 | << "t" << expr_gen.to_str(o0) 39625 | << "((t" << expr_gen.to_str(o1) 39626 | << "t)" << expr_gen.to_str(o2) 39627 | << "t)" 39628 | } 39629 | }; 39630 | 39631 | struct synthesize_vocovov_expression2 39632 | { 39633 | typedef typename vocovov_t::type2 node_type; 39634 | typedef typename vocovov_t::sf4_type sf4_type; 39635 | typedef typename node_type::T0 T0; 39636 | typedef typename node_type::T1 T1; 39637 | typedef typename node_type::T2 T2; 39638 | typedef typename node_type::T3 T3; 39639 | 39640 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39641 | const details::operator_type& operation, 39642 | expression_node_ptr (&branch)[2]) 39643 | { 39644 | // v0 o0 ((c o1 v1) o2 v2) 39645 | typedef typename synthesize_covov_expression0::node_type lcl_covov_t; 39646 | 39647 | const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[1]); 39648 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39649 | const Type c = covov->t0(); 39650 | const Type& v1 = covov->t1(); 39651 | const Type& v2 = covov->t2(); 39652 | const details::operator_type o0 = operation; 39653 | const details::operator_type o1 = expr_gen.get_operator(covov->f0()); 39654 | const details::operator_type o2 = expr_gen.get_operator(covov->f1()); 39655 | 39656 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39657 | binary_functor_t f1 = covov->f0(); 39658 | binary_functor_t f2 = covov->f1(); 39659 | 39660 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39661 | 39662 | expression_node_ptr result = error_node(); 39663 | 39664 | const bool synthesis_result = 39665 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39666 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result); 39667 | 39668 | if (synthesis_result) 39669 | return result; 39670 | else if (!expr_gen.valid_operator(o0,f0)) 39671 | return error_node(); 39672 | 39673 | exprtk_debug(("v0 o0 ((c o1 v1) o2 v2)\n")); 39674 | 39675 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2); 39676 | } 39677 | 39678 | static inline std::string id(expression_generator<Type>& expr_gen, 39679 | const details::operator_type o0, 39680 | const details::operator_type o1, 39681 | const details::operator_type o2) 39682 | { 39683 | return details::build_string() 39684 | << "t" << expr_gen.to_str(o0) 39685 | << "((t" << expr_gen.to_str(o1) 39686 | << "t)" << expr_gen.to_str(o2) 39687 | << "t)" 39688 | } 39689 | }; 39690 | 39691 | struct synthesize_covovov_expression2 39692 | { 39693 | typedef typename covovov_t::type2 node_type; 39694 | typedef typename covovov_t::sf4_type sf4_type; 39695 | typedef typename node_type::T0 T0; 39696 | typedef typename node_type::T1 T1; 39697 | typedef typename node_type::T2 T2; 39698 | typedef typename node_type::T3 T3; 39699 | 39700 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39701 | const details::operator_type& operation, 39702 | expression_node_ptr (&branch)[2]) 39703 | { 39704 | // c o0 ((v1 o1 v2) o2 v3) 39705 | typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t; 39706 | 39707 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]); 39708 | const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); 39709 | const Type& v0 = vovov->t0(); 39710 | const Type& v1 = vovov->t1(); 39711 | const Type& v2 = vovov->t2(); 39712 | const details::operator_type o0 = operation; 39713 | const details::operator_type o1 = expr_gen.get_operator(vovov->f0()); 39714 | const details::operator_type o2 = expr_gen.get_operator(vovov->f1()); 39715 | 39716 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39717 | binary_functor_t f1 = vovov->f0(); 39718 | binary_functor_t f2 = vovov->f1(); 39719 | 39720 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39721 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39722 | 39723 | expression_node_ptr result = error_node(); 39724 | 39725 | const bool synthesis_result = 39726 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39727 | (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result); 39728 | 39729 | if (synthesis_result) 39730 | return result; 39731 | else if (!expr_gen.valid_operator(o0,f0)) 39732 | return error_node(); 39733 | 39734 | exprtk_debug(("c o0 ((v1 o1 v2) o2 v3)\n")); 39735 | 39736 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2); 39737 | } 39738 | 39739 | static inline std::string id(expression_generator<Type>& expr_gen, 39740 | const details::operator_type o0, 39741 | const details::operator_type o1, 39742 | const details::operator_type o2) 39743 | { 39744 | return details::build_string() 39745 | << "t" << expr_gen.to_str(o0) 39746 | << "((t" << expr_gen.to_str(o1) 39747 | << "t)" << expr_gen.to_str(o2) 39748 | << "t)" 39749 | } 39750 | }; 39751 | 39752 | struct synthesize_covocov_expression2 39753 | { 39754 | typedef typename covocov_t::type2 node_type; 39755 | typedef typename covocov_t::sf4_type sf4_type; 39756 | typedef typename node_type::T0 T0; 39757 | typedef typename node_type::T1 T1; 39758 | typedef typename node_type::T2 T2; 39759 | typedef typename node_type::T3 T3; 39760 | 39761 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39762 | const details::operator_type& operation, 39763 | expression_node_ptr (&branch)[2]) 39764 | { 39765 | // c0 o0 ((v0 o1 c1) o2 v1) 39766 | typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t; 39767 | 39768 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]); 39769 | const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); 39770 | const Type& v0 = vocov->t0(); 39771 | const Type c1 = vocov->t1(); 39772 | const Type& v1 = vocov->t2(); 39773 | const details::operator_type o0 = operation; 39774 | const details::operator_type o1 = expr_gen.get_operator(vocov->f0()); 39775 | const details::operator_type o2 = expr_gen.get_operator(vocov->f1()); 39776 | 39777 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39778 | binary_functor_t f1 = vocov->f0(); 39779 | binary_functor_t f2 = vocov->f1(); 39780 | 39781 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39782 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39783 | 39784 | expression_node_ptr result = error_node(); 39785 | 39786 | const bool synthesis_result = 39787 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39788 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result); 39789 | 39790 | if (synthesis_result) 39791 | return result; 39792 | else if (!expr_gen.valid_operator(o0,f0)) 39793 | return error_node(); 39794 | 39795 | exprtk_debug(("c0 o0 ((v0 o1 c1) o2 v1)\n")); 39796 | 39797 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2); 39798 | } 39799 | 39800 | static inline std::string id(expression_generator<Type>& expr_gen, 39801 | const details::operator_type o0, 39802 | const details::operator_type o1, 39803 | const details::operator_type o2) 39804 | { 39805 | return details::build_string() 39806 | << "t" << expr_gen.to_str(o0) 39807 | << "((t" << expr_gen.to_str(o1) 39808 | << "t)" << expr_gen.to_str(o2) 39809 | << "t)" 39810 | } 39811 | }; 39812 | 39813 | struct synthesize_vocovoc_expression2 39814 | { 39815 | typedef typename vocovoc_t::type2 node_type; 39816 | typedef typename vocovoc_t::sf4_type sf4_type; 39817 | typedef typename node_type::T0 T0; 39818 | typedef typename node_type::T1 T1; 39819 | typedef typename node_type::T2 T2; 39820 | typedef typename node_type::T3 T3; 39821 | 39822 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39823 | const details::operator_type& operation, 39824 | expression_node_ptr (&branch)[2]) 39825 | { 39826 | // v0 o0 ((c0 o1 v1) o2 c1) 39827 | typedef typename synthesize_covoc_expression0::node_type lcl_covoc_t; 39828 | 39829 | const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[1]); 39830 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39831 | const Type c0 = covoc->t0(); 39832 | const Type& v1 = covoc->t1(); 39833 | const Type c1 = covoc->t2(); 39834 | const details::operator_type o0 = operation; 39835 | const details::operator_type o1 = expr_gen.get_operator(covoc->f0()); 39836 | const details::operator_type o2 = expr_gen.get_operator(covoc->f1()); 39837 | 39838 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39839 | binary_functor_t f1 = covoc->f0(); 39840 | binary_functor_t f2 = covoc->f1(); 39841 | 39842 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39843 | 39844 | expression_node_ptr result = error_node(); 39845 | 39846 | const bool synthesis_result = 39847 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39848 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result); 39849 | 39850 | if (synthesis_result) 39851 | return result; 39852 | else if (!expr_gen.valid_operator(o0,f0)) 39853 | return error_node(); 39854 | 39855 | exprtk_debug(("v0 o0 ((c0 o1 v1) o2 c1)\n")); 39856 | 39857 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2); 39858 | } 39859 | 39860 | static inline std::string id(expression_generator<Type>& expr_gen, 39861 | const details::operator_type o0, 39862 | const details::operator_type o1, 39863 | const details::operator_type o2) 39864 | { 39865 | return details::build_string() 39866 | << "t" << expr_gen.to_str(o0) 39867 | << "((t" << expr_gen.to_str(o1) 39868 | << "t)" << expr_gen.to_str(o2) 39869 | << "t)" 39870 | } 39871 | }; 39872 | 39873 | struct synthesize_covovoc_expression2 39874 | { 39875 | typedef typename covovoc_t::type2 node_type; 39876 | typedef typename covovoc_t::sf4_type sf4_type; 39877 | typedef typename node_type::T0 T0; 39878 | typedef typename node_type::T1 T1; 39879 | typedef typename node_type::T2 T2; 39880 | typedef typename node_type::T3 T3; 39881 | 39882 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39883 | const details::operator_type& operation, 39884 | expression_node_ptr (&branch)[2]) 39885 | { 39886 | // c0 o0 ((v0 o1 v1) o2 c1) 39887 | typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t; 39888 | 39889 | const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]); 39890 | const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); 39891 | const Type& v0 = vovoc->t0(); 39892 | const Type& v1 = vovoc->t1(); 39893 | const Type c1 = vovoc->t2(); 39894 | const details::operator_type o0 = operation; 39895 | const details::operator_type o1 = expr_gen.get_operator(vovoc->f0()); 39896 | const details::operator_type o2 = expr_gen.get_operator(vovoc->f1()); 39897 | 39898 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39899 | binary_functor_t f1 = vovoc->f0(); 39900 | binary_functor_t f2 = vovoc->f1(); 39901 | 39902 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39903 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39904 | 39905 | expression_node_ptr result = error_node(); 39906 | 39907 | const bool synthesis_result = 39908 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39909 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result); 39910 | 39911 | if (synthesis_result) 39912 | return result; 39913 | else if (!expr_gen.valid_operator(o0,f0)) 39914 | return error_node(); 39915 | 39916 | exprtk_debug(("c0 o0 ((v0 o1 v1) o2 c1)\n")); 39917 | 39918 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2); 39919 | } 39920 | 39921 | static inline std::string id(expression_generator<Type>& expr_gen, 39922 | const details::operator_type o0, 39923 | const details::operator_type o1, 39924 | const details::operator_type o2) 39925 | { 39926 | return details::build_string() 39927 | << "t" << expr_gen.to_str(o0) 39928 | << "((t" << expr_gen.to_str(o1) 39929 | << "t)" << expr_gen.to_str(o2) 39930 | << "t)" 39931 | } 39932 | }; 39933 | 39934 | struct synthesize_vococov_expression2 39935 | { 39936 | typedef typename vococov_t::type2 node_type; 39937 | static inline expression_node_ptr process(expression_generator<Type>&, 39938 | const details::operator_type&, 39939 | expression_node_ptr (&)[2]) 39940 | { 39941 | // v0 o0 ((c0 o1 c1) o2 v1) - Not possible 39942 | exprtk_debug(("v0 o0 ((c0 o1 c1) o2 v1) - Not possible\n")); 39943 | return error_node(); 39944 | } 39945 | 39946 | static inline std::string id(expression_generator<Type>&, 39947 | const details::operator_type, 39948 | const details::operator_type, 39949 | const details::operator_type) 39950 | { 39951 | return "INVALID" 39952 | } 39953 | }; 39954 | 39955 | struct synthesize_vovovov_expression3 39956 | { 39957 | typedef typename vovovov_t::type3 node_type; 39958 | typedef typename vovovov_t::sf4_type sf4_type; 39959 | typedef typename node_type::T0 T0; 39960 | typedef typename node_type::T1 T1; 39961 | typedef typename node_type::T2 T2; 39962 | typedef typename node_type::T3 T3; 39963 | 39964 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39965 | const details::operator_type& operation, 39966 | expression_node_ptr (&branch)[2]) 39967 | { 39968 | // ((v0 o0 v1) o1 v2) o2 v3 39969 | typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t; 39970 | 39971 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]); 39972 | const Type& v0 = vovov->t0(); 39973 | const Type& v1 = vovov->t1(); 39974 | const Type& v2 = vovov->t2(); 39975 | const Type& v3 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 39976 | const details::operator_type o0 = expr_gen.get_operator(vovov->f0()); 39977 | const details::operator_type o1 = expr_gen.get_operator(vovov->f1()); 39978 | const details::operator_type o2 = operation; 39979 | 39980 | binary_functor_t f0 = vovov->f0(); 39981 | binary_functor_t f1 = vovov->f1(); 39982 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 39983 | 39984 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39985 | 39986 | expression_node_ptr result = error_node(); 39987 | 39988 | const bool synthesis_result = 39989 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39990 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result); 39991 | 39992 | if (synthesis_result) 39993 | return result; 39994 | else if (!expr_gen.valid_operator(o2,f2)) 39995 | return error_node(); 39996 | 39997 | exprtk_debug(("((v0 o0 v1) o1 v2) o2 v3\n")); 39998 | 39999 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2); 40000 | } 40001 | 40002 | static inline std::string id(expression_generator<Type>& expr_gen, 40003 | const details::operator_type o0, 40004 | const details::operator_type o1, 40005 | const details::operator_type o2) 40006 | { 40007 | return details::build_string() 40008 | << "((t" << expr_gen.to_str(o0) 40009 | << "t)" << expr_gen.to_str(o1) 40010 | << "t)" << expr_gen.to_str(o2) 40011 | << "t" 40012 | } 40013 | }; 40014 | 40015 | struct synthesize_vovovoc_expression3 40016 | { 40017 | typedef typename vovovoc_t::type3 node_type; 40018 | typedef typename vovovoc_t::sf4_type sf4_type; 40019 | typedef typename node_type::T0 T0; 40020 | typedef typename node_type::T1 T1; 40021 | typedef typename node_type::T2 T2; 40022 | typedef typename node_type::T3 T3; 40023 | 40024 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40025 | const details::operator_type& operation, 40026 | expression_node_ptr (&branch)[2]) 40027 | { 40028 | // ((v0 o0 v1) o1 v2) o2 c 40029 | typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t; 40030 | 40031 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]); 40032 | const Type& v0 = vovov->t0(); 40033 | const Type& v1 = vovov->t1(); 40034 | const Type& v2 = vovov->t2(); 40035 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 40036 | const details::operator_type o0 = expr_gen.get_operator(vovov->f0()); 40037 | const details::operator_type o1 = expr_gen.get_operator(vovov->f1()); 40038 | const details::operator_type o2 = operation; 40039 | 40040 | binary_functor_t f0 = vovov->f0(); 40041 | binary_functor_t f1 = vovov->f1(); 40042 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40043 | 40044 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40045 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 40046 | 40047 | expression_node_ptr result = error_node(); 40048 | 40049 | const bool synthesis_result = 40050 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40051 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result); 40052 | 40053 | if (synthesis_result) 40054 | return result; 40055 | else if (!expr_gen.valid_operator(o2,f2)) 40056 | return error_node(); 40057 | 40058 | exprtk_debug(("((v0 o0 v1) o1 v2) o2 c\n")); 40059 | 40060 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2); 40061 | } 40062 | 40063 | static inline std::string id(expression_generator<Type>& expr_gen, 40064 | const details::operator_type o0, 40065 | const details::operator_type o1, 40066 | const details::operator_type o2) 40067 | { 40068 | return details::build_string() 40069 | << "((t" << expr_gen.to_str(o0) 40070 | << "t)" << expr_gen.to_str(o1) 40071 | << "t)" << expr_gen.to_str(o2) 40072 | << "t" 40073 | } 40074 | }; 40075 | 40076 | struct synthesize_vovocov_expression3 40077 | { 40078 | typedef typename vovocov_t::type3 node_type; 40079 | typedef typename vovocov_t::sf4_type sf4_type; 40080 | typedef typename node_type::T0 T0; 40081 | typedef typename node_type::T1 T1; 40082 | typedef typename node_type::T2 T2; 40083 | typedef typename node_type::T3 T3; 40084 | 40085 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40086 | const details::operator_type& operation, 40087 | expression_node_ptr (&branch)[2]) 40088 | { 40089 | // ((v0 o0 v1) o1 c) o2 v2 40090 | typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t; 40091 | 40092 | const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[0]); 40093 | const Type& v0 = vovoc->t0(); 40094 | const Type& v1 = vovoc->t1(); 40095 | const Type c = vovoc->t2(); 40096 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40097 | const details::operator_type o0 = expr_gen.get_operator(vovoc->f0()); 40098 | const details::operator_type o1 = expr_gen.get_operator(vovoc->f1()); 40099 | const details::operator_type o2 = operation; 40100 | 40101 | binary_functor_t f0 = vovoc->f0(); 40102 | binary_functor_t f1 = vovoc->f1(); 40103 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40104 | 40105 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40106 | 40107 | expression_node_ptr result = error_node(); 40108 | 40109 | const bool synthesis_result = 40110 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40111 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result); 40112 | 40113 | if (synthesis_result) 40114 | return result; 40115 | else if (!expr_gen.valid_operator(o2,f2)) 40116 | return error_node(); 40117 | 40118 | exprtk_debug(("((v0 o0 v1) o1 c) o2 v2\n")); 40119 | 40120 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2); 40121 | } 40122 | 40123 | static inline std::string id(expression_generator<Type>& expr_gen, 40124 | const details::operator_type o0, 40125 | const details::operator_type o1, 40126 | const details::operator_type o2) 40127 | { 40128 | return details::build_string() 40129 | << "((t" << expr_gen.to_str(o0) 40130 | << "t)" << expr_gen.to_str(o1) 40131 | << "t)" << expr_gen.to_str(o2) 40132 | << "t" 40133 | } 40134 | }; 40135 | 40136 | struct synthesize_vocovov_expression3 40137 | { 40138 | typedef typename vocovov_t::type3 node_type; 40139 | typedef typename vocovov_t::sf4_type sf4_type; 40140 | typedef typename node_type::T0 T0; 40141 | typedef typename node_type::T1 T1; 40142 | typedef typename node_type::T2 T2; 40143 | typedef typename node_type::T3 T3; 40144 | 40145 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40146 | const details::operator_type& operation, 40147 | expression_node_ptr (&branch)[2]) 40148 | { 40149 | // ((v0 o0 c) o1 v1) o2 v2 40150 | typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t; 40151 | 40152 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]); 40153 | const Type& v0 = vocov->t0(); 40154 | const Type c = vocov->t1(); 40155 | const Type& v1 = vocov->t2(); 40156 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40157 | const details::operator_type o0 = expr_gen.get_operator(vocov->f0()); 40158 | const details::operator_type o1 = expr_gen.get_operator(vocov->f1()); 40159 | const details::operator_type o2 = operation; 40160 | 40161 | binary_functor_t f0 = vocov->f0(); 40162 | binary_functor_t f1 = vocov->f1(); 40163 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40164 | 40165 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40166 | 40167 | expression_node_ptr result = error_node(); 40168 | 40169 | const bool synthesis_result = 40170 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40171 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result); 40172 | 40173 | if (synthesis_result) 40174 | return result; 40175 | else if (!expr_gen.valid_operator(o2,f2)) 40176 | return error_node(); 40177 | 40178 | exprtk_debug(("((v0 o0 c) o1 v1) o2 v2\n")); 40179 | 40180 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2); 40181 | } 40182 | 40183 | static inline std::string id(expression_generator<Type>& expr_gen, 40184 | const details::operator_type o0, 40185 | const details::operator_type o1, 40186 | const details::operator_type o2) 40187 | { 40188 | return details::build_string() 40189 | << "((t" << expr_gen.to_str(o0) 40190 | << "t)" << expr_gen.to_str(o1) 40191 | << "t)" << expr_gen.to_str(o2) 40192 | << "t" 40193 | } 40194 | }; 40195 | 40196 | struct synthesize_covovov_expression3 40197 | { 40198 | typedef typename covovov_t::type3 node_type; 40199 | typedef typename covovov_t::sf4_type sf4_type; 40200 | typedef typename node_type::T0 T0; 40201 | typedef typename node_type::T1 T1; 40202 | typedef typename node_type::T2 T2; 40203 | typedef typename node_type::T3 T3; 40204 | 40205 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40206 | const details::operator_type& operation, 40207 | expression_node_ptr (&branch)[2]) 40208 | { 40209 | // ((c o0 v0) o1 v1) o2 v2 40210 | typedef typename synthesize_covov_expression0::node_type lcl_covov_t; 40211 | 40212 | const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]); 40213 | const Type c = covov->t0(); 40214 | const Type& v0 = covov->t1(); 40215 | const Type& v1 = covov->t2(); 40216 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40217 | const details::operator_type o0 = expr_gen.get_operator(covov->f0()); 40218 | const details::operator_type o1 = expr_gen.get_operator(covov->f1()); 40219 | const details::operator_type o2 = operation; 40220 | 40221 | binary_functor_t f0 = covov->f0(); 40222 | binary_functor_t f1 = covov->f1(); 40223 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40224 | 40225 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40226 | 40227 | expression_node_ptr result = error_node(); 40228 | 40229 | const bool synthesis_result = 40230 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40231 | (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result); 40232 | 40233 | if (synthesis_result) 40234 | return result; 40235 | else if (!expr_gen.valid_operator(o2,f2)) 40236 | return error_node(); 40237 | 40238 | exprtk_debug(("((c o0 v0) o1 v1) o2 v2\n")); 40239 | 40240 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2); 40241 | } 40242 | 40243 | static inline std::string id(expression_generator<Type>& expr_gen, 40244 | const details::operator_type o0, 40245 | const details::operator_type o1, 40246 | const details::operator_type o2) 40247 | { 40248 | return details::build_string() 40249 | << "((t" << expr_gen.to_str(o0) 40250 | << "t)" << expr_gen.to_str(o1) 40251 | << "t)" << expr_gen.to_str(o2) 40252 | << "t" 40253 | } 40254 | }; 40255 | 40256 | struct synthesize_covocov_expression3 40257 | { 40258 | typedef typename covocov_t::type3 node_type; 40259 | typedef typename covocov_t::sf4_type sf4_type; 40260 | typedef typename node_type::T0 T0; 40261 | typedef typename node_type::T1 T1; 40262 | typedef typename node_type::T2 T2; 40263 | typedef typename node_type::T3 T3; 40264 | 40265 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40266 | const details::operator_type& operation, 40267 | expression_node_ptr (&branch)[2]) 40268 | { 40269 | // ((c0 o0 v0) o1 c1) o2 v1 40270 | typedef typename synthesize_covoc_expression0::node_type lcl_covoc_t; 40271 | 40272 | const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[0]); 40273 | const Type c0 = covoc->t0(); 40274 | const Type& v0 = covoc->t1(); 40275 | const Type c1 = covoc->t2(); 40276 | const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40277 | const details::operator_type o0 = expr_gen.get_operator(covoc->f0()); 40278 | const details::operator_type o1 = expr_gen.get_operator(covoc->f1()); 40279 | const details::operator_type o2 = operation; 40280 | 40281 | binary_functor_t f0 = covoc->f0(); 40282 | binary_functor_t f1 = covoc->f1(); 40283 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40284 | 40285 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40286 | 40287 | expression_node_ptr result = error_node(); 40288 | 40289 | const bool synthesis_result = 40290 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40291 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result); 40292 | 40293 | if (synthesis_result) 40294 | return result; 40295 | else if (!expr_gen.valid_operator(o2,f2)) 40296 | return error_node(); 40297 | 40298 | exprtk_debug(("((c0 o0 v0) o1 c1) o2 v1\n")); 40299 | 40300 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2); 40301 | } 40302 | 40303 | static inline std::string id(expression_generator<Type>& expr_gen, 40304 | const details::operator_type o0, 40305 | const details::operator_type o1, 40306 | const details::operator_type o2) 40307 | { 40308 | return details::build_string() 40309 | << "((t" << expr_gen.to_str(o0) 40310 | << "t)" << expr_gen.to_str(o1) 40311 | << "t)" << expr_gen.to_str(o2) 40312 | << "t" 40313 | } 40314 | }; 40315 | 40316 | struct synthesize_vocovoc_expression3 40317 | { 40318 | typedef typename vocovoc_t::type3 node_type; 40319 | typedef typename vocovoc_t::sf4_type sf4_type; 40320 | typedef typename node_type::T0 T0; 40321 | typedef typename node_type::T1 T1; 40322 | typedef typename node_type::T2 T2; 40323 | typedef typename node_type::T3 T3; 40324 | 40325 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40326 | const details::operator_type& operation, 40327 | expression_node_ptr (&branch)[2]) 40328 | { 40329 | // ((v0 o0 c0) o1 v1) o2 c1 40330 | typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t; 40331 | 40332 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]); 40333 | const Type& v0 = vocov->t0(); 40334 | const Type c0 = vocov->t1(); 40335 | const Type& v1 = vocov->t2(); 40336 | const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); 40337 | const details::operator_type o0 = expr_gen.get_operator(vocov->f0()); 40338 | const details::operator_type o1 = expr_gen.get_operator(vocov->f1()); 40339 | const details::operator_type o2 = operation; 40340 | 40341 | binary_functor_t f0 = vocov->f0(); 40342 | binary_functor_t f1 = vocov->f1(); 40343 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40344 | 40345 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40346 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 40347 | 40348 | expression_node_ptr result = error_node(); 40349 | 40350 | const bool synthesis_result = 40351 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40352 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result); 40353 | 40354 | if (synthesis_result) 40355 | return result; 40356 | else if (!expr_gen.valid_operator(o2,f2)) 40357 | return error_node(); 40358 | 40359 | exprtk_debug(("((v0 o0 c0) o1 v1) o2 c1\n")); 40360 | 40361 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2); 40362 | } 40363 | 40364 | static inline std::string id(expression_generator<Type>& expr_gen, 40365 | const details::operator_type o0, 40366 | const details::operator_type o1, 40367 | const details::operator_type o2) 40368 | { 40369 | return details::build_string() 40370 | << "((t" << expr_gen.to_str(o0) 40371 | << "t)" << expr_gen.to_str(o1) 40372 | << "t)" << expr_gen.to_str(o2) 40373 | << "t" 40374 | } 40375 | }; 40376 | 40377 | struct synthesize_covovoc_expression3 40378 | { 40379 | typedef typename covovoc_t::type3 node_type; 40380 | typedef typename covovoc_t::sf4_type sf4_type; 40381 | typedef typename node_type::T0 T0; 40382 | typedef typename node_type::T1 T1; 40383 | typedef typename node_type::T2 T2; 40384 | typedef typename node_type::T3 T3; 40385 | 40386 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40387 | const details::operator_type& operation, 40388 | expression_node_ptr (&branch)[2]) 40389 | { 40390 | // ((c0 o0 v0) o1 v1) o2 c1 40391 | typedef typename synthesize_covov_expression0::node_type lcl_covov_t; 40392 | 40393 | const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]); 40394 | const Type c0 = covov->t0(); 40395 | const Type& v0 = covov->t1(); 40396 | const Type& v1 = covov->t2(); 40397 | const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); 40398 | const details::operator_type o0 = expr_gen.get_operator(covov->f0()); 40399 | const details::operator_type o1 = expr_gen.get_operator(covov->f1()); 40400 | const details::operator_type o2 = operation; 40401 | 40402 | binary_functor_t f0 = covov->f0(); 40403 | binary_functor_t f1 = covov->f1(); 40404 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40405 | 40406 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40407 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 40408 | 40409 | expression_node_ptr result = error_node(); 40410 | 40411 | const bool synthesis_result = 40412 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40413 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result); 40414 | 40415 | if (synthesis_result) 40416 | return result; 40417 | else if (!expr_gen.valid_operator(o2,f2)) 40418 | return error_node(); 40419 | 40420 | exprtk_debug(("((c0 o0 v0) o1 v1) o2 c1\n")); 40421 | 40422 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2); 40423 | } 40424 | 40425 | static inline std::string id(expression_generator<Type>& expr_gen, 40426 | const details::operator_type o0, 40427 | const details::operator_type o1, 40428 | const details::operator_type o2) 40429 | { 40430 | return details::build_string() 40431 | << "((t" << expr_gen.to_str(o0) 40432 | << "t)" << expr_gen.to_str(o1) 40433 | << "t)" << expr_gen.to_str(o2) 40434 | << "t" 40435 | } 40436 | }; 40437 | 40438 | struct synthesize_vococov_expression3 40439 | { 40440 | typedef typename vococov_t::type3 node_type; 40441 | typedef typename vococov_t::sf4_type sf4_type; 40442 | typedef typename node_type::T0 T0; 40443 | typedef typename node_type::T1 T1; 40444 | typedef typename node_type::T2 T2; 40445 | typedef typename node_type::T3 T3; 40446 | 40447 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40448 | const details::operator_type& operation, 40449 | expression_node_ptr (&branch)[2]) 40450 | { 40451 | // ((v0 o0 c0) o1 c1) o2 v1 40452 | typedef typename synthesize_vococ_expression0::node_type lcl_vococ_t; 40453 | 40454 | const lcl_vococ_t* vococ = static_cast<const lcl_vococ_t*>(branch[0]); 40455 | const Type& v0 = vococ->t0(); 40456 | const Type c0 = vococ->t1(); 40457 | const Type c1 = vococ->t2(); 40458 | const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40459 | const details::operator_type o0 = expr_gen.get_operator(vococ->f0()); 40460 | const details::operator_type o1 = expr_gen.get_operator(vococ->f1()); 40461 | const details::operator_type o2 = operation; 40462 | 40463 | binary_functor_t f0 = vococ->f0(); 40464 | binary_functor_t f1 = vococ->f1(); 40465 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40466 | 40467 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40468 | 40469 | expression_node_ptr result = error_node(); 40470 | 40471 | const bool synthesis_result = 40472 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40473 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result); 40474 | 40475 | if (synthesis_result) 40476 | return result; 40477 | else if (!expr_gen.valid_operator(o2,f2)) 40478 | return error_node(); 40479 | 40480 | exprtk_debug(("((v0 o0 c0) o1 c1) o2 v1\n")); 40481 | 40482 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2); 40483 | } 40484 | 40485 | static inline std::string id(expression_generator<Type>& expr_gen, 40486 | const details::operator_type o0, 40487 | const details::operator_type o1, 40488 | const details::operator_type o2) 40489 | { 40490 | return details::build_string() 40491 | << "((t" << expr_gen.to_str(o0) 40492 | << "t)" << expr_gen.to_str(o1) 40493 | << "t)" << expr_gen.to_str(o2) 40494 | << "t" 40495 | } 40496 | }; 40497 | 40498 | struct synthesize_vovovov_expression4 40499 | { 40500 | typedef typename vovovov_t::type4 node_type; 40501 | typedef typename vovovov_t::sf4_type sf4_type; 40502 | typedef typename node_type::T0 T0; 40503 | typedef typename node_type::T1 T1; 40504 | typedef typename node_type::T2 T2; 40505 | typedef typename node_type::T3 T3; 40506 | 40507 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40508 | const details::operator_type& operation, 40509 | expression_node_ptr (&branch)[2]) 40510 | { 40511 | // (v0 o0 (v1 o1 v2)) o2 v3 40512 | typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t; 40513 | 40514 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]); 40515 | const Type& v0 = vovov->t0(); 40516 | const Type& v1 = vovov->t1(); 40517 | const Type& v2 = vovov->t2(); 40518 | const Type& v3 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40519 | const details::operator_type o0 = expr_gen.get_operator(vovov->f0()); 40520 | const details::operator_type o1 = expr_gen.get_operator(vovov->f1()); 40521 | const details::operator_type o2 = operation; 40522 | 40523 | binary_functor_t f0 = vovov->f0(); 40524 | binary_functor_t f1 = vovov->f1(); 40525 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40526 | 40527 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40528 | 40529 | expression_node_ptr result = error_node(); 40530 | 40531 | const bool synthesis_result = 40532 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40533 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result); 40534 | 40535 | if (synthesis_result) 40536 | return result; 40537 | else if (!expr_gen.valid_operator(o2,f2)) 40538 | return error_node(); 40539 | 40540 | exprtk_debug(("(v0 o0 (v1 o1 v2)) o2 v3\n")); 40541 | 40542 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2); 40543 | } 40544 | 40545 | static inline std::string id(expression_generator<Type>& expr_gen, 40546 | const details::operator_type o0, 40547 | const details::operator_type o1, 40548 | const details::operator_type o2) 40549 | { 40550 | return details::build_string() 40551 | << "(t" << expr_gen.to_str(o0) 40552 | << "(t" << expr_gen.to_str(o1) 40553 | << "t)" << expr_gen.to_str(o2) 40554 | << "t" 40555 | } 40556 | }; 40557 | 40558 | struct synthesize_vovovoc_expression4 40559 | { 40560 | typedef typename vovovoc_t::type4 node_type; 40561 | typedef typename vovovoc_t::sf4_type sf4_type; 40562 | typedef typename node_type::T0 T0; 40563 | typedef typename node_type::T1 T1; 40564 | typedef typename node_type::T2 T2; 40565 | typedef typename node_type::T3 T3; 40566 | 40567 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40568 | const details::operator_type& operation, 40569 | expression_node_ptr (&branch)[2]) 40570 | { 40571 | // ((v0 o0 (v1 o1 v2)) o2 c) 40572 | typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t; 40573 | 40574 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]); 40575 | const Type& v0 = vovov->t0(); 40576 | const Type& v1 = vovov->t1(); 40577 | const Type& v2 = vovov->t2(); 40578 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 40579 | const details::operator_type o0 = expr_gen.get_operator(vovov->f0()); 40580 | const details::operator_type o1 = expr_gen.get_operator(vovov->f1()); 40581 | const details::operator_type o2 = operation; 40582 | 40583 | binary_functor_t f0 = vovov->f0(); 40584 | binary_functor_t f1 = vovov->f1(); 40585 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40586 | 40587 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40588 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 40589 | 40590 | expression_node_ptr result = error_node(); 40591 | 40592 | const bool synthesis_result = 40593 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40594 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result); 40595 | 40596 | if (synthesis_result) 40597 | return result; 40598 | else if (!expr_gen.valid_operator(o2,f2)) 40599 | return error_node(); 40600 | 40601 | exprtk_debug(("((v0 o0 (v1 o1 v2)) o2 c)\n")); 40602 | 40603 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2); 40604 | } 40605 | 40606 | static inline std::string id(expression_generator<Type>& expr_gen, 40607 | const details::operator_type o0, 40608 | const details::operator_type o1, 40609 | const details::operator_type o2) 40610 | { 40611 | return details::build_string() 40612 | << "(t" << expr_gen.to_str(o0) 40613 | << "(t" << expr_gen.to_str(o1) 40614 | << "t)" << expr_gen.to_str(o2) 40615 | << "t" 40616 | } 40617 | }; 40618 | 40619 | struct synthesize_vovocov_expression4 40620 | { 40621 | typedef typename vovocov_t::type4 node_type; 40622 | typedef typename vovocov_t::sf4_type sf4_type; 40623 | typedef typename node_type::T0 T0; 40624 | typedef typename node_type::T1 T1; 40625 | typedef typename node_type::T2 T2; 40626 | typedef typename node_type::T3 T3; 40627 | 40628 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40629 | const details::operator_type& operation, 40630 | expression_node_ptr (&branch)[2]) 40631 | { 40632 | // ((v0 o0 (v1 o1 c)) o2 v1) 40633 | typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t; 40634 | 40635 | const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[0]); 40636 | const Type& v0 = vovoc->t0(); 40637 | const Type& v1 = vovoc->t1(); 40638 | const Type c = vovoc->t2(); 40639 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40640 | const details::operator_type o0 = expr_gen.get_operator(vovoc->f0()); 40641 | const details::operator_type o1 = expr_gen.get_operator(vovoc->f1()); 40642 | const details::operator_type o2 = operation; 40643 | 40644 | binary_functor_t f0 = vovoc->f0(); 40645 | binary_functor_t f1 = vovoc->f1(); 40646 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40647 | 40648 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40649 | 40650 | expression_node_ptr result = error_node(); 40651 | 40652 | const bool synthesis_result = 40653 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40654 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result); 40655 | 40656 | if (synthesis_result) 40657 | return result; 40658 | else if (!expr_gen.valid_operator(o2,f2)) 40659 | return error_node(); 40660 | 40661 | exprtk_debug(("((v0 o0 (v1 o1 c)) o2 v1)\n")); 40662 | 40663 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2); 40664 | } 40665 | 40666 | static inline std::string id(expression_generator<Type>& expr_gen, 40667 | const details::operator_type o0, 40668 | const details::operator_type o1, 40669 | const details::operator_type o2) 40670 | { 40671 | return details::build_string() 40672 | << "(t" << expr_gen.to_str(o0) 40673 | << "(t" << expr_gen.to_str(o1) 40674 | << "t)" << expr_gen.to_str(o2) 40675 | << "t" 40676 | } 40677 | }; 40678 | 40679 | struct synthesize_vocovov_expression4 40680 | { 40681 | typedef typename vocovov_t::type4 node_type; 40682 | typedef typename vocovov_t::sf4_type sf4_type; 40683 | typedef typename node_type::T0 T0; 40684 | typedef typename node_type::T1 T1; 40685 | typedef typename node_type::T2 T2; 40686 | typedef typename node_type::T3 T3; 40687 | 40688 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40689 | const details::operator_type& operation, 40690 | expression_node_ptr (&branch)[2]) 40691 | { 40692 | // ((v0 o0 (c o1 v1)) o2 v2) 40693 | typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t; 40694 | 40695 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]); 40696 | const Type& v0 = vocov->t0(); 40697 | const Type c = vocov->t1(); 40698 | const Type& v1 = vocov->t2(); 40699 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40700 | const details::operator_type o0 = expr_gen.get_operator(vocov->f0()); 40701 | const details::operator_type o1 = expr_gen.get_operator(vocov->f1()); 40702 | const details::operator_type o2 = operation; 40703 | 40704 | binary_functor_t f0 = vocov->f0(); 40705 | binary_functor_t f1 = vocov->f1(); 40706 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40707 | 40708 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40709 | expression_node_ptr result = error_node(); 40710 | 40711 | const bool synthesis_result = 40712 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40713 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result); 40714 | 40715 | if (synthesis_result) 40716 | return result; 40717 | else if (!expr_gen.valid_operator(o2,f2)) 40718 | return error_node(); 40719 | 40720 | exprtk_debug(("((v0 o0 (c o1 v1)) o2 v2)\n")); 40721 | 40722 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2); 40723 | } 40724 | 40725 | static inline std::string id(expression_generator<Type>& expr_gen, 40726 | const details::operator_type o0, 40727 | const details::operator_type o1, 40728 | const details::operator_type o2) 40729 | { 40730 | return details::build_string() 40731 | << "(t" << expr_gen.to_str(o0) 40732 | << "(t" << expr_gen.to_str(o1) 40733 | << "t)" << expr_gen.to_str(o2) 40734 | << "t" 40735 | } 40736 | }; 40737 | 40738 | struct synthesize_covovov_expression4 40739 | { 40740 | typedef typename covovov_t::type4 node_type; 40741 | typedef typename covovov_t::sf4_type sf4_type; 40742 | typedef typename node_type::T0 T0; 40743 | typedef typename node_type::T1 T1; 40744 | typedef typename node_type::T2 T2; 40745 | typedef typename node_type::T3 T3; 40746 | 40747 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40748 | const details::operator_type& operation, 40749 | expression_node_ptr (&branch)[2]) 40750 | { 40751 | // ((c o0 (v0 o1 v1)) o2 v2) 40752 | typedef typename synthesize_covov_expression1::node_type lcl_covov_t; 40753 | 40754 | const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]); 40755 | const Type c = covov->t0(); 40756 | const Type& v0 = covov->t1(); 40757 | const Type& v1 = covov->t2(); 40758 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40759 | const details::operator_type o0 = expr_gen.get_operator(covov->f0()); 40760 | const details::operator_type o1 = expr_gen.get_operator(covov->f1()); 40761 | const details::operator_type o2 = operation; 40762 | 40763 | binary_functor_t f0 = covov->f0(); 40764 | binary_functor_t f1 = covov->f1(); 40765 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40766 | 40767 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40768 | 40769 | expression_node_ptr result = error_node(); 40770 | 40771 | const bool synthesis_result = 40772 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40773 | (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result); 40774 | 40775 | if (synthesis_result) 40776 | return result; 40777 | else if (!expr_gen.valid_operator(o2,f2)) 40778 | return error_node(); 40779 | 40780 | exprtk_debug(("((c o0 (v0 o1 v1)) o2 v2)\n")); 40781 | 40782 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2); 40783 | } 40784 | 40785 | static inline std::string id(expression_generator<Type>& expr_gen, 40786 | const details::operator_type o0, 40787 | const details::operator_type o1, 40788 | const details::operator_type o2) 40789 | { 40790 | return details::build_string() 40791 | << "(t" << expr_gen.to_str(o0) 40792 | << "(t" << expr_gen.to_str(o1) 40793 | << "t)" << expr_gen.to_str(o2) 40794 | << "t" 40795 | } 40796 | }; 40797 | 40798 | struct synthesize_covocov_expression4 40799 | { 40800 | typedef typename covocov_t::type4 node_type; 40801 | typedef typename covocov_t::sf4_type sf4_type; 40802 | typedef typename node_type::T0 T0; 40803 | typedef typename node_type::T1 T1; 40804 | typedef typename node_type::T2 T2; 40805 | typedef typename node_type::T3 T3; 40806 | 40807 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40808 | const details::operator_type& operation, 40809 | expression_node_ptr (&branch)[2]) 40810 | { 40811 | // ((c0 o0 (v0 o1 c1)) o2 v1) 40812 | typedef typename synthesize_covoc_expression1::node_type lcl_covoc_t; 40813 | 40814 | const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[0]); 40815 | const Type c0 = covoc->t0(); 40816 | const Type& v0 = covoc->t1(); 40817 | const Type c1 = covoc->t2(); 40818 | const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40819 | const details::operator_type o0 = expr_gen.get_operator(covoc->f0()); 40820 | const details::operator_type o1 = expr_gen.get_operator(covoc->f1()); 40821 | const details::operator_type o2 = operation; 40822 | 40823 | binary_functor_t f0 = covoc->f0(); 40824 | binary_functor_t f1 = covoc->f1(); 40825 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40826 | 40827 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40828 | 40829 | expression_node_ptr result = error_node(); 40830 | 40831 | const bool synthesis_result = 40832 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40833 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result); 40834 | 40835 | if (synthesis_result) 40836 | return result; 40837 | else if (!expr_gen.valid_operator(o2,f2)) 40838 | return error_node(); 40839 | 40840 | exprtk_debug(("((c0 o0 (v0 o1 c1)) o2 v1)\n")); 40841 | 40842 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2); 40843 | } 40844 | 40845 | static inline std::string id(expression_generator<Type>& expr_gen, 40846 | const details::operator_type o0, 40847 | const details::operator_type o1, 40848 | const details::operator_type o2) 40849 | { 40850 | return details::build_string() 40851 | << "(t" << expr_gen.to_str(o0) 40852 | << "(t" << expr_gen.to_str(o1) 40853 | << "t)" << expr_gen.to_str(o2) 40854 | << "t" 40855 | } 40856 | }; 40857 | 40858 | struct synthesize_vocovoc_expression4 40859 | { 40860 | typedef typename vocovoc_t::type4 node_type; 40861 | typedef typename vocovoc_t::sf4_type sf4_type; 40862 | typedef typename node_type::T0 T0; 40863 | typedef typename node_type::T1 T1; 40864 | typedef typename node_type::T2 T2; 40865 | typedef typename node_type::T3 T3; 40866 | 40867 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40868 | const details::operator_type& operation, 40869 | expression_node_ptr (&branch)[2]) 40870 | { 40871 | // ((v0 o0 (c0 o1 v1)) o2 c1) 40872 | typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t; 40873 | 40874 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]); 40875 | const Type& v0 = vocov->t0(); 40876 | const Type c0 = vocov->t1(); 40877 | const Type& v1 = vocov->t2(); 40878 | const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); 40879 | const details::operator_type o0 = expr_gen.get_operator(vocov->f0()); 40880 | const details::operator_type o1 = expr_gen.get_operator(vocov->f1()); 40881 | const details::operator_type o2 = operation; 40882 | 40883 | binary_functor_t f0 = vocov->f0(); 40884 | binary_functor_t f1 = vocov->f1(); 40885 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40886 | 40887 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40888 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 40889 | 40890 | expression_node_ptr result = error_node(); 40891 | 40892 | const bool synthesis_result = 40893 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40894 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result); 40895 | 40896 | if (synthesis_result) 40897 | return result; 40898 | else if (!expr_gen.valid_operator(o2,f2)) 40899 | return error_node(); 40900 | 40901 | exprtk_debug(("((v0 o0 (c0 o1 v1)) o2 c1)\n")); 40902 | 40903 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2); 40904 | } 40905 | 40906 | static inline std::string id(expression_generator<Type>& expr_gen, 40907 | const details::operator_type o0, 40908 | const details::operator_type o1, 40909 | const details::operator_type o2) 40910 | { 40911 | return details::build_string() 40912 | << "(t" << expr_gen.to_str(o0) 40913 | << "(t" << expr_gen.to_str(o1) 40914 | << "t)" << expr_gen.to_str(o2) 40915 | << "t" 40916 | } 40917 | }; 40918 | 40919 | struct synthesize_covovoc_expression4 40920 | { 40921 | typedef typename covovoc_t::type4 node_type; 40922 | typedef typename covovoc_t::sf4_type sf4_type; 40923 | typedef typename node_type::T0 T0; 40924 | typedef typename node_type::T1 T1; 40925 | typedef typename node_type::T2 T2; 40926 | typedef typename node_type::T3 T3; 40927 | 40928 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40929 | const details::operator_type& operation, 40930 | expression_node_ptr (&branch)[2]) 40931 | { 40932 | // ((c0 o0 (v0 o1 v1)) o2 c1) 40933 | typedef typename synthesize_covov_expression1::node_type lcl_covov_t; 40934 | 40935 | const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]); 40936 | const Type c0 = covov->t0(); 40937 | const Type& v0 = covov->t1(); 40938 | const Type& v1 = covov->t2(); 40939 | const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); 40940 | const details::operator_type o0 = expr_gen.get_operator(covov->f0()); 40941 | const details::operator_type o1 = expr_gen.get_operator(covov->f1()); 40942 | const details::operator_type o2 = operation; 40943 | 40944 | binary_functor_t f0 = covov->f0(); 40945 | binary_functor_t f1 = covov->f1(); 40946 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40947 | 40948 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40949 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 40950 | 40951 | expression_node_ptr result = error_node(); 40952 | 40953 | const bool synthesis_result = 40954 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40955 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result); 40956 | 40957 | if (synthesis_result) 40958 | return result; 40959 | else if (!expr_gen.valid_operator(o2,f2)) 40960 | return error_node(); 40961 | 40962 | exprtk_debug(("((c0 o0 (v0 o1 v1)) o2 c1)\n")); 40963 | 40964 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2); 40965 | } 40966 | 40967 | static inline std::string id(expression_generator<Type>& expr_gen, 40968 | const details::operator_type o0, 40969 | const details::operator_type o1, 40970 | const details::operator_type o2) 40971 | { 40972 | return details::build_string() 40973 | << "(t" << expr_gen.to_str(o0) 40974 | << "(t" << expr_gen.to_str(o1) 40975 | << "t)" << expr_gen.to_str(o2) 40976 | << "t" 40977 | } 40978 | }; 40979 | 40980 | struct synthesize_vococov_expression4 40981 | { 40982 | typedef typename vococov_t::type4 node_type; 40983 | static inline expression_node_ptr process(expression_generator<Type>&, 40984 | const details::operator_type&, 40985 | expression_node_ptr (&)[2]) 40986 | { 40987 | // ((v0 o0 (c0 o1 c1)) o2 v1) - Not possible 40988 | exprtk_debug(("((v0 o0 (c0 o1 c1)) o2 v1) - Not possible\n")); 40989 | return error_node(); 40990 | } 40991 | 40992 | static inline std::string id(expression_generator<Type>&, 40993 | const details::operator_type, 40994 | const details::operator_type, 40995 | const details::operator_type) 40996 | { 40997 | return "INVALID" 40998 | } 40999 | }; 41000 | #endif 41001 | 41002 | inline expression_node_ptr synthesize_uvouv_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2]) 41003 | { 41004 | // Definition: uv o uv 41005 | details::operator_type o0 = static_cast<details::uv_base_node<Type>*>(branch[0])->operation(); 41006 | details::operator_type o1 = static_cast<details::uv_base_node<Type>*>(branch[1])->operation(); 41007 | const Type& v0 = static_cast<details::uv_base_node<Type>*>(branch[0])->v(); 41008 | const Type& v1 = static_cast<details::uv_base_node<Type>*>(branch[1])->v(); 41009 | unary_functor_t u0 = reinterpret_cast<unary_functor_t> (0); 41010 | unary_functor_t u1 = reinterpret_cast<unary_functor_t> (0); 41011 | binary_functor_t f = reinterpret_cast<binary_functor_t>(0); 41012 | 41013 | if (!valid_operator(o0,u0)) 41014 | return error_node(); 41015 | else if (!valid_operator(o1,u1)) 41016 | return error_node(); 41017 | else if (!valid_operator(operation,f)) 41018 | return error_node(); 41019 | 41020 | expression_node_ptr result = error_node(); 41021 | 41022 | if ( 41023 | (details::e_neg == o0) && 41024 | (details::e_neg == o1) 41025 | ) 41026 | { 41027 | switch (operation) 41028 | { 41029 | // (-v0 + -v1) --> -(v0 + v1) 41030 | case details::e_add : result = (*this)(details::e_neg, 41031 | node_allocator_-> 41032 | allocate_rr<typename details:: 41033 | vov_node<Type,details::add_op<Type> > >(v0, v1)); 41034 | exprtk_debug(("(-v0 + -v1) --> -(v0 + v1)\n")); 41035 | break; 41036 | 41037 | // (-v0 - -v1) --> (v1 - v0) 41038 | case details::e_sub : result = node_allocator_-> 41039 | allocate_rr<typename details:: 41040 | vov_node<Type,details::sub_op<Type> > >(v1, v0); 41041 | exprtk_debug(("(-v0 - -v1) --> (v1 - v0)\n")); 41042 | break; 41043 | 41044 | // (-v0 * -v1) --> (v0 * v1) 41045 | case details::e_mul : result = node_allocator_-> 41046 | allocate_rr<typename details:: 41047 | vov_node<Type,details::mul_op<Type> > >(v0, v1); 41048 | exprtk_debug(("(-v0 * -v1) --> (v0 * v1)\n")); 41049 | break; 41050 | 41051 | // (-v0 / -v1) --> (v0 / v1) 41052 | case details::e_div : result = node_allocator_-> 41053 | allocate_rr<typename details:: 41054 | vov_node<Type,details::div_op<Type> > >(v0, v1); 41055 | exprtk_debug(("(-v0 / -v1) --> (v0 / v1)\n")); 41056 | break; 41057 | 41058 | default : break; 41059 | } 41060 | } 41061 | 41062 | if (0 == result) 41063 | { 41064 | result = node_allocator_-> 41065 | allocate_rrrrr<typename details::uvouv_node<Type> >(v0, v1, u0, u1, f); 41066 | } 41067 | 41068 | details::free_all_nodes(*node_allocator_,branch); 41069 | return result; 41070 | } 41071 | 41072 | #undef basic_opr_switch_statements 41073 | #undef extended_opr_switch_statements 41074 | #undef unary_opr_switch_statements 41075 | 41076 | #ifndef exprtk_disable_string_capabilities 41077 | 41078 | #define string_opr_switch_statements \ 41079 | case_stmt(details::e_lt , details::lt_op ) \ 41080 | case_stmt(details::e_lte , details::lte_op ) \ 41081 | case_stmt(details::e_gt , details::gt_op ) \ 41082 | case_stmt(details::e_gte , details::gte_op ) \ 41083 | case_stmt(details::e_eq , details::eq_op ) \ 41084 | case_stmt(details::e_ne , details::ne_op ) \ 41085 | case_stmt(details::e_in , details::in_op ) \ 41086 | case_stmt(details::e_like , details::like_op ) \ 41087 | case_stmt(details::e_ilike , details::ilike_op) \ 41088 | 41089 | template <typename T0, typename T1> 41090 | inline expression_node_ptr synthesize_str_xrox_expression_impl(const details::operator_type& opr, 41091 | T0 s0, T1 s1, 41092 | range_t rp0) 41093 | { 41094 | switch (opr) 41095 | { 41096 | #define case_stmt(op0, op1) \ 41097 | case op0 : return node_allocator_-> \ 41098 | allocate_ttt<typename details::str_xrox_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \ 41099 | (s0, s1, rp0); \ 41100 | 41101 | string_opr_switch_statements 41102 | #undef case_stmt 41103 | default : return error_node(); 41104 | } 41105 | } 41106 | 41107 | template <typename T0, typename T1> 41108 | inline expression_node_ptr synthesize_str_xoxr_expression_impl(const details::operator_type& opr, 41109 | T0 s0, T1 s1, 41110 | range_t rp1) 41111 | { 41112 | switch (opr) 41113 | { 41114 | #define case_stmt(op0, op1) \ 41115 | case op0 : return node_allocator_-> \ 41116 | allocate_ttt<typename details::str_xoxr_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \ 41117 | (s0, s1, rp1); \ 41118 | 41119 | string_opr_switch_statements 41120 | #undef case_stmt 41121 | default : return error_node(); 41122 | } 41123 | } 41124 | 41125 | template <typename T0, typename T1> 41126 | inline expression_node_ptr synthesize_str_xroxr_expression_impl(const details::operator_type& opr, 41127 | T0 s0, T1 s1, 41128 | range_t rp0, range_t rp1) 41129 | { 41130 | switch (opr) 41131 | { 41132 | #define case_stmt(op0, op1) \ 41133 | case op0 : return node_allocator_-> \ 41134 | allocate_tttt<typename details::str_xroxr_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \ 41135 | (s0, s1, rp0, rp1); \ 41136 | 41137 | string_opr_switch_statements 41138 | #undef case_stmt 41139 | default : return error_node(); 41140 | } 41141 | } 41142 | 41143 | template <typename T0, typename T1> 41144 | inline expression_node_ptr synthesize_sos_expression_impl(const details::operator_type& opr, T0 s0, T1 s1) 41145 | { 41146 | switch (opr) 41147 | { 41148 | #define case_stmt(op0, op1) \ 41149 | case op0 : return node_allocator_-> \ 41150 | allocate_tt<typename details::sos_node<Type,T0,T1,op1<Type> >,T0,T1>(s0, s1); \ 41151 | 41152 | string_opr_switch_statements 41153 | #undef case_stmt 41154 | default : return error_node(); 41155 | } 41156 | } 41157 | 41158 | inline expression_node_ptr synthesize_sos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41159 | { 41160 | std::string& s0 = static_cast<details::stringvar_node<Type>*>(branch[0])->ref(); 41161 | std::string& s1 = static_cast<details::stringvar_node<Type>*>(branch[1])->ref(); 41162 | 41163 | return synthesize_sos_expression_impl<std::string&,std::string&>(opr, s0, s1); 41164 | } 41165 | 41166 | inline expression_node_ptr synthesize_sros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41167 | { 41168 | std::string& s0 = static_cast<details::string_range_node<Type>*>(branch[0])->ref (); 41169 | std::string& s1 = static_cast<details::stringvar_node<Type>*> (branch[1])->ref (); 41170 | range_t rp0 = static_cast<details::string_range_node<Type>*>(branch[0])->range(); 41171 | 41172 | static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear(); 41173 | 41174 | details::free_node(*node_allocator_,branch[0]); 41175 | 41176 | return synthesize_str_xrox_expression_impl<std::string&,std::string&>(opr, s0, s1, rp0); 41177 | } 41178 | 41179 | inline expression_node_ptr synthesize_sosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41180 | { 41181 | std::string& s0 = static_cast<details::stringvar_node<Type>*> (branch[0])->ref (); 41182 | std::string& s1 = static_cast<details::string_range_node<Type>*>(branch[1])->ref (); 41183 | range_t rp1 = static_cast<details::string_range_node<Type>*>(branch[1])->range(); 41184 | 41185 | static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear(); 41186 | 41187 | details::free_node(*node_allocator_,branch[1]); 41188 | 41189 | return synthesize_str_xoxr_expression_impl<std::string&,std::string&>(opr, s0, s1, rp1); 41190 | } 41191 | 41192 | inline expression_node_ptr synthesize_socsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41193 | { 41194 | std::string& s0 = static_cast<details::stringvar_node<Type>*> (branch[0])->ref (); 41195 | std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str (); 41196 | range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range(); 41197 | 41198 | static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear(); 41199 | 41200 | details::free_node(*node_allocator_,branch[1]); 41201 | 41202 | return synthesize_str_xoxr_expression_impl<std::string&, const std::string>(opr, s0, s1, rp1); 41203 | } 41204 | 41205 | inline expression_node_ptr synthesize_srosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41206 | { 41207 | std::string& s0 = static_cast<details::string_range_node<Type>*>(branch[0])->ref (); 41208 | std::string& s1 = static_cast<details::string_range_node<Type>*>(branch[1])->ref (); 41209 | range_t rp0 = static_cast<details::string_range_node<Type>*>(branch[0])->range(); 41210 | range_t rp1 = static_cast<details::string_range_node<Type>*>(branch[1])->range(); 41211 | 41212 | static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear(); 41213 | static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear(); 41214 | 41215 | details::free_node(*node_allocator_,branch[0]); 41216 | details::free_node(*node_allocator_,branch[1]); 41217 | 41218 | return synthesize_str_xroxr_expression_impl<std::string&,std::string&>(opr, s0, s1, rp0, rp1); 41219 | } 41220 | 41221 | inline expression_node_ptr synthesize_socs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41222 | { 41223 | std::string& s0 = static_cast< details::stringvar_node<Type>*>(branch[0])->ref(); 41224 | std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str(); 41225 | 41226 | details::free_node(*node_allocator_,branch[1]); 41227 | 41228 | return synthesize_sos_expression_impl<std::string&, const std::string>(opr, s0, s1); 41229 | } 41230 | 41231 | inline expression_node_ptr synthesize_csos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41232 | { 41233 | std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str(); 41234 | std::string& s1 = static_cast<details::stringvar_node<Type>* >(branch[1])->ref(); 41235 | 41236 | details::free_node(*node_allocator_,branch[0]); 41237 | 41238 | return synthesize_sos_expression_impl<const std::string,std::string&>(opr, s0, s1); 41239 | } 41240 | 41241 | inline expression_node_ptr synthesize_csosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41242 | { 41243 | std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str (); 41244 | std::string& s1 = static_cast<details::string_range_node<Type>* >(branch[1])->ref (); 41245 | range_t rp1 = static_cast<details::string_range_node<Type>* >(branch[1])->range(); 41246 | 41247 | static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear(); 41248 | 41249 | details::free_node(*node_allocator_,branch[0]); 41250 | details::free_node(*node_allocator_,branch[1]); 41251 | 41252 | return synthesize_str_xoxr_expression_impl<const std::string,std::string&>(opr, s0, s1, rp1); 41253 | } 41254 | 41255 | inline expression_node_ptr synthesize_srocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41256 | { 41257 | std::string& s0 = static_cast<details::string_range_node<Type>* >(branch[0])->ref (); 41258 | std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str (); 41259 | range_t rp0 = static_cast<details::string_range_node<Type>* >(branch[0])->range(); 41260 | 41261 | static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear(); 41262 | 41263 | details::free_node(*node_allocator_,branch[0]); 41264 | details::free_node(*node_allocator_,branch[1]); 41265 | 41266 | return synthesize_str_xrox_expression_impl<std::string&, const std::string>(opr, s0, s1, rp0); 41267 | } 41268 | 41269 | inline expression_node_ptr synthesize_srocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41270 | { 41271 | std::string& s0 = static_cast<details::string_range_node<Type>* >(branch[0])->ref (); 41272 | std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str (); 41273 | range_t rp0 = static_cast<details::string_range_node<Type>* >(branch[0])->range(); 41274 | range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range(); 41275 | 41276 | static_cast<details::string_range_node<Type>*> (branch[0])->range_ref().clear(); 41277 | static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear(); 41278 | 41279 | details::free_node(*node_allocator_,branch[0]); 41280 | details::free_node(*node_allocator_,branch[1]); 41281 | 41282 | return synthesize_str_xroxr_expression_impl<std::string&, const std::string>(opr, s0, s1, rp0, rp1); 41283 | } 41284 | 41285 | inline expression_node_ptr synthesize_csocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41286 | { 41287 | const std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str(); 41288 | const std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str(); 41289 | 41290 | expression_node_ptr result = error_node(); 41291 | 41292 | if (details::e_add == opr) 41293 | result = node_allocator_->allocate_c<details::string_literal_node<Type> >(s0 + s1); 41294 | else if (details::e_in == opr) 41295 | result = node_allocator_->allocate_c<details::literal_node<Type> >(details::in_op <Type>::process(s0,s1)); 41296 | else if (details::e_like == opr) 41297 | result = node_allocator_->allocate_c<details::literal_node<Type> >(details::like_op <Type>::process(s0,s1)); 41298 | else if (details::e_ilike == opr) 41299 | result = node_allocator_->allocate_c<details::literal_node<Type> >(details::ilike_op<Type>::process(s0,s1)); 41300 | else 41301 | { 41302 | expression_node_ptr temp = synthesize_sos_expression_impl<const std::string, const std::string>(opr, s0, s1); 41303 | 41304 | const Type v = temp->value(); 41305 | 41306 | details::free_node(*node_allocator_,temp); 41307 | 41308 | result = node_allocator_->allocate<literal_node_t>(v); 41309 | } 41310 | 41311 | details::free_all_nodes(*node_allocator_,branch); 41312 | 41313 | return result; 41314 | } 41315 | 41316 | inline expression_node_ptr synthesize_csocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41317 | { 41318 | const std::string s0 = static_cast<details::string_literal_node<Type>* >(branch[0])->str (); 41319 | std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str (); 41320 | range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range(); 41321 | 41322 | static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear(); 41323 | 41324 | details::free_node(*node_allocator_,branch[0]); 41325 | details::free_node(*node_allocator_,branch[1]); 41326 | 41327 | return synthesize_str_xoxr_expression_impl<const std::string, const std::string>(opr, s0, s1, rp1); 41328 | } 41329 | 41330 | inline expression_node_ptr synthesize_csros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41331 | { 41332 | std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str (); 41333 | std::string& s1 = static_cast<details::stringvar_node<Type>* >(branch[1])->ref (); 41334 | range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range(); 41335 | 41336 | static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear(); 41337 | 41338 | details::free_node(*node_allocator_,branch[0]); 41339 | 41340 | return synthesize_str_xrox_expression_impl<const std::string,std::string&>(opr, s0, s1, rp0); 41341 | } 41342 | 41343 | inline expression_node_ptr synthesize_csrosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41344 | { 41345 | const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str (); 41346 | std::string& s1 = static_cast<details::string_range_node<Type>* >(branch[1])->ref (); 41347 | const range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range(); 41348 | const range_t rp1 = static_cast<details::string_range_node<Type>* >(branch[1])->range(); 41349 | 41350 | static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear(); 41351 | static_cast<details::string_range_node<Type>*> (branch[1])->range_ref().clear(); 41352 | 41353 | details::free_node(*node_allocator_,branch[0]); 41354 | details::free_node(*node_allocator_,branch[1]); 41355 | 41356 | return synthesize_str_xroxr_expression_impl<const std::string,std::string&>(opr, s0, s1, rp0, rp1); 41357 | } 41358 | 41359 | inline expression_node_ptr synthesize_csrocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41360 | { 41361 | const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str (); 41362 | const std::string s1 = static_cast<details::string_literal_node<Type>* >(branch[1])->str (); 41363 | const range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range(); 41364 | 41365 | static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear(); 41366 | 41367 | details::free_all_nodes(*node_allocator_,branch); 41368 | 41369 | return synthesize_str_xrox_expression_impl<const std::string,std::string>(opr, s0, s1, rp0); 41370 | } 41371 | 41372 | inline expression_node_ptr synthesize_csrocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41373 | { 41374 | const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str (); 41375 | const std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str (); 41376 | const range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range(); 41377 | const range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range(); 41378 | 41379 | static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear(); 41380 | static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear(); 41381 | 41382 | details::free_all_nodes(*node_allocator_,branch); 41383 | 41384 | return synthesize_str_xroxr_expression_impl<const std::string, const std::string>(opr, s0, s1, rp0, rp1); 41385 | } 41386 | 41387 | inline expression_node_ptr synthesize_strogen_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41388 | { 41389 | switch (opr) 41390 | { 41391 | #define case_stmt(op0, op1) \ 41392 | case op0 : return node_allocator_-> \ 41393 | allocate_ttt<typename details::str_sogens_node<Type,op1<Type> > > \ 41394 | (opr, branch[0], branch[1]); \ 41395 | 41396 | string_opr_switch_statements 41397 | #undef case_stmt 41398 | default : return error_node(); 41399 | } 41400 | } 41401 | 41402 | #undef string_opr_switch_statements 41403 | #endif 41404 | 41405 | #ifndef exprtk_disable_string_capabilities 41406 | inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41407 | { 41408 | if ((0 == branch[0]) || (0 == branch[1])) 41409 | { 41410 | details::free_all_nodes(*node_allocator_,branch); 41411 | 41412 | return error_node(); 41413 | } 41414 | 41415 | const bool b0_is_s = details::is_string_node (branch[0]); 41416 | const bool b0_is_cs = details::is_const_string_node (branch[0]); 41417 | const bool b0_is_sr = details::is_string_range_node (branch[0]); 41418 | const bool b0_is_csr = details::is_const_string_range_node(branch[0]); 41419 | 41420 | const bool b1_is_s = details::is_string_node (branch[1]); 41421 | const bool b1_is_cs = details::is_const_string_node (branch[1]); 41422 | const bool b1_is_sr = details::is_string_range_node (branch[1]); 41423 | const bool b1_is_csr = details::is_const_string_range_node(branch[1]); 41424 | 41425 | const bool b0_is_gen = details::is_string_assignment_node (branch[0]) || 41426 | details::is_genricstring_range_node(branch[0]) || 41427 | details::is_string_concat_node (branch[0]) || 41428 | details::is_string_function_node (branch[0]) || 41429 | details::is_string_condition_node (branch[0]) || 41430 | details::is_string_ccondition_node (branch[0]) || 41431 | details::is_string_vararg_node (branch[0]) ; 41432 | 41433 | const bool b1_is_gen = details::is_string_assignment_node (branch[1]) || 41434 | details::is_genricstring_range_node(branch[1]) || 41435 | details::is_string_concat_node (branch[1]) || 41436 | details::is_string_function_node (branch[1]) || 41437 | details::is_string_condition_node (branch[1]) || 41438 | details::is_string_ccondition_node (branch[1]) || 41439 | details::is_string_vararg_node (branch[1]) ; 41440 | 41441 | if (details::e_add == opr) 41442 | { 41443 | if (!b0_is_cs || !b1_is_cs) 41444 | { 41445 | return synthesize_expression<string_concat_node_t,2>(opr,branch); 41446 | } 41447 | } 41448 | 41449 | if (b0_is_gen || b1_is_gen) 41450 | { 41451 | return synthesize_strogen_expression(opr,branch); 41452 | } 41453 | else if (b0_is_s) 41454 | { 41455 | if (b1_is_s ) return synthesize_sos_expression (opr,branch); 41456 | else if (b1_is_cs ) return synthesize_socs_expression (opr,branch); 41457 | else if (b1_is_sr ) return synthesize_sosr_expression (opr,branch); 41458 | else if (b1_is_csr) return synthesize_socsr_expression (opr,branch); 41459 | } 41460 | else if (b0_is_cs) 41461 | { 41462 | if (b1_is_s ) return synthesize_csos_expression (opr,branch); 41463 | else if (b1_is_cs ) return synthesize_csocs_expression (opr,branch); 41464 | else if (b1_is_sr ) return synthesize_csosr_expression (opr,branch); 41465 | else if (b1_is_csr) return synthesize_csocsr_expression(opr,branch); 41466 | } 41467 | else if (b0_is_sr) 41468 | { 41469 | if (b1_is_s ) return synthesize_sros_expression (opr,branch); 41470 | else if (b1_is_sr ) return synthesize_srosr_expression (opr,branch); 41471 | else if (b1_is_cs ) return synthesize_srocs_expression (opr,branch); 41472 | else if (b1_is_csr) return synthesize_srocsr_expression(opr,branch); 41473 | } 41474 | else if (b0_is_csr) 41475 | { 41476 | if (b1_is_s ) return synthesize_csros_expression (opr,branch); 41477 | else if (b1_is_sr ) return synthesize_csrosr_expression (opr,branch); 41478 | else if (b1_is_cs ) return synthesize_csrocs_expression (opr,branch); 41479 | else if (b1_is_csr) return synthesize_csrocsr_expression(opr,branch); 41480 | } 41481 | 41482 | return error_node(); 41483 | } 41484 | #else 41485 | inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&branch)[2]) 41486 | { 41487 | details::free_all_nodes(*node_allocator_,branch); 41488 | return error_node(); 41489 | } 41490 | #endif 41491 | 41492 | #ifndef exprtk_disable_string_capabilities 41493 | inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[3]) 41494 | { 41495 | if (details::e_inrange != opr) 41496 | return error_node(); 41497 | else if ((0 == branch[0]) || (0 == branch[1]) || (0 == branch[2])) 41498 | { 41499 | details::free_all_nodes(*node_allocator_,branch); 41500 | 41501 | return error_node(); 41502 | } 41503 | else if ( 41504 | details::is_const_string_node(branch[0]) && 41505 | details::is_const_string_node(branch[1]) && 41506 | details::is_const_string_node(branch[2]) 41507 | ) 41508 | { 41509 | const std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str(); 41510 | const std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str(); 41511 | const std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str(); 41512 | 41513 | const Type v = (((s0 <= s1) && (s1 <= s2)) ? Type(1) : Type(0)); 41514 | 41515 | details::free_all_nodes(*node_allocator_,branch); 41516 | 41517 | return node_allocator_->allocate_c<details::literal_node<Type> >(v); 41518 | } 41519 | else if ( 41520 | details::is_string_node(branch[0]) && 41521 | details::is_string_node(branch[1]) && 41522 | details::is_string_node(branch[2]) 41523 | ) 41524 | { 41525 | std::string& s0 = static_cast<details::stringvar_node<Type>*>(branch[0])->ref(); 41526 | std::string& s1 = static_cast<details::stringvar_node<Type>*>(branch[1])->ref(); 41527 | std::string& s2 = static_cast<details::stringvar_node<Type>*>(branch[2])->ref(); 41528 | 41529 | typedef typename details::sosos_node<Type, std::string&, std::string&, std::string&, details::inrange_op<Type> > inrange_t; 41530 | 41531 | return node_allocator_->allocate_type<inrange_t, std::string&, std::string&, std::string&>(s0, s1, s2); 41532 | } 41533 | else if ( 41534 | details::is_const_string_node(branch[0]) && 41535 | details::is_string_node(branch[1]) && 41536 | details::is_const_string_node(branch[2]) 41537 | ) 41538 | { 41539 | std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str(); 41540 | std::string& s1 = static_cast<details::stringvar_node<Type>* >(branch[1])->ref(); 41541 | std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str(); 41542 | 41543 | typedef typename details::sosos_node<Type, std::string, std::string&, std::string, details::inrange_op<Type> > inrange_t; 41544 | 41545 | details::free_node(*node_allocator_,branch[0]); 41546 | details::free_node(*node_allocator_,branch[2]); 41547 | 41548 | return node_allocator_->allocate_type<inrange_t, std::string, std::string&, std::string>(s0, s1, s2); 41549 | } 41550 | else if ( 41551 | details::is_string_node(branch[0]) && 41552 | details::is_const_string_node(branch[1]) && 41553 | details::is_string_node(branch[2]) 41554 | ) 41555 | { 41556 | std::string& s0 = static_cast<details::stringvar_node<Type>* >(branch[0])->ref(); 41557 | std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str(); 41558 | std::string& s2 = static_cast<details::stringvar_node<Type>* >(branch[2])->ref(); 41559 | 41560 | typedef typename details::sosos_node<Type, std::string&, std::string, std::string&, details::inrange_op<Type> > inrange_t; 41561 | 41562 | details::free_node(*node_allocator_,branch[1]); 41563 | 41564 | return node_allocator_->allocate_type<inrange_t, std::string&, std::string, std::string&>(s0, s1, s2); 41565 | } 41566 | else if ( 41567 | details::is_string_node(branch[0]) && 41568 | details::is_string_node(branch[1]) && 41569 | details::is_const_string_node(branch[2]) 41570 | ) 41571 | { 41572 | std::string& s0 = static_cast<details::stringvar_node<Type>* >(branch[0])->ref(); 41573 | std::string& s1 = static_cast<details::stringvar_node<Type>* >(branch[1])->ref(); 41574 | std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str(); 41575 | 41576 | typedef typename details::sosos_node<Type, std::string&, std::string&, std::string, details::inrange_op<Type> > inrange_t; 41577 | 41578 | details::free_node(*node_allocator_,branch[2]); 41579 | 41580 | return node_allocator_->allocate_type<inrange_t, std::string&, std::string&, std::string>(s0, s1, s2); 41581 | } 41582 | else if ( 41583 | details::is_const_string_node(branch[0]) && 41584 | details:: is_string_node(branch[1]) && 41585 | details:: is_string_node(branch[2]) 41586 | ) 41587 | { 41588 | std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str(); 41589 | std::string& s1 = static_cast<details::stringvar_node<Type>* >(branch[1])->ref(); 41590 | std::string& s2 = static_cast<details::stringvar_node<Type>* >(branch[2])->ref(); 41591 | 41592 | typedef typename details::sosos_node<Type, std::string, std::string&, std::string&, details::inrange_op<Type> > inrange_t; 41593 | 41594 | details::free_node(*node_allocator_,branch[0]); 41595 | 41596 | return node_allocator_->allocate_type<inrange_t, std::string, std::string&, std::string&>(s0, s1, s2); 41597 | } 41598 | else 41599 | return error_node(); 41600 | } 41601 | #else 41602 | inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&branch)[3]) 41603 | { 41604 | details::free_all_nodes(*node_allocator_,branch); 41605 | return error_node(); 41606 | } 41607 | #endif 41608 | 41609 | inline expression_node_ptr synthesize_null_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2]) 41610 | { 41611 | /* 41612 | Note: The following are the type promotion rules 41613 | that relate to operations that include 'null': 41614 | 0. null ==/!= null --> true false 41615 | 1. null operation null --> null 41616 | 2. x ==/!= null --> true/false 41617 | 3. null ==/!= x --> true/false 41618 | 4. x operation null --> x 41619 | 5. null operation x --> x 41620 | */ 41621 | 41622 | typedef typename details::null_eq_node<T> nulleq_node_t; 41623 | 41624 | const bool b0_null = details::is_null_node(branch[0]); 41625 | const bool b1_null = details::is_null_node(branch[1]); 41626 | 41627 | if (b0_null && b1_null) 41628 | { 41629 | expression_node_ptr result = error_node(); 41630 | 41631 | if (details::e_eq == operation) 41632 | result = node_allocator_->allocate_c<literal_node_t>(T(1)); 41633 | else if (details::e_ne == operation) 41634 | result = node_allocator_->allocate_c<literal_node_t>(T(0)); 41635 | 41636 | if (result) 41637 | { 41638 | details::free_node(*node_allocator_,branch[0]); 41639 | details::free_node(*node_allocator_,branch[1]); 41640 | 41641 | return result; 41642 | } 41643 | 41644 | details::free_node(*node_allocator_,branch[1]); 41645 | 41646 | return branch[0]; 41647 | } 41648 | else if (details::e_eq == operation) 41649 | { 41650 | expression_node_ptr result = node_allocator_-> 41651 | allocate_rc<nulleq_node_t>(branch[b0_null ? 0 : 1],true); 41652 | 41653 | details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]); 41654 | 41655 | return result; 41656 | } 41657 | else if (details::e_ne == operation) 41658 | { 41659 | expression_node_ptr result = node_allocator_-> 41660 | allocate_rc<nulleq_node_t>(branch[b0_null ? 0 : 1],false); 41661 | 41662 | details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]); 41663 | 41664 | return result; 41665 | } 41666 | else if (b0_null) 41667 | { 41668 | details::free_node(*node_allocator_,branch[0]); 41669 | branch[0] = branch[1]; 41670 | branch[1] = error_node(); 41671 | } 41672 | else if (b1_null) 41673 | { 41674 | details::free_node(*node_allocator_,branch[1]); 41675 | branch[1] = error_node(); 41676 | } 41677 | 41678 | if ( 41679 | (details::e_add == operation) || (details::e_sub == operation) || 41680 | (details::e_mul == operation) || (details::e_div == operation) || 41681 | (details::e_mod == operation) || (details::e_pow == operation) 41682 | ) 41683 | { 41684 | return branch[0]; 41685 | } 41686 | 41687 | details::free_node(*node_allocator_, branch[0]); 41688 | 41689 | if ( 41690 | (details::e_lt == operation) || (details::e_lte == operation) || 41691 | (details::e_gt == operation) || (details::e_gte == operation) || 41692 | (details::e_and == operation) || (details::e_nand == operation) || 41693 | (details::e_or == operation) || (details::e_nor == operation) || 41694 | (details::e_xor == operation) || (details::e_xnor == operation) || 41695 | (details::e_in == operation) || (details::e_like == operation) || 41696 | (details::e_ilike == operation) 41697 | ) 41698 | { 41699 | return node_allocator_->allocate_c<literal_node_t>(T(0)); 41700 | } 41701 | 41702 | return node_allocator_->allocate<details::null_node<Type> >(); 41703 | } 41704 | 41705 | template <typename NodeType, std::size_t N> 41706 | inline expression_node_ptr synthesize_expression(const details::operator_type& operation, expression_node_ptr (&branch)[N]) 41707 | { 41708 | if ( 41709 | (details::e_in == operation) || 41710 | (details::e_like == operation) || 41711 | (details::e_ilike == operation) 41712 | ) 41713 | { 41714 | free_all_nodes(*node_allocator_,branch); 41715 | 41716 | return error_node(); 41717 | } 41718 | else if (!details::all_nodes_valid<N>(branch)) 41719 | { 41720 | free_all_nodes(*node_allocator_,branch); 41721 | 41722 | return error_node(); 41723 | } 41724 | else if ((details::e_default != operation)) 41725 | { 41726 | // Attempt simple constant folding optimisation. 41727 | expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(operation,branch); 41728 | 41729 | if (is_constant_foldable<N>(branch)) 41730 | { 41731 | const Type v = expression_point->value(); 41732 | details::free_node(*node_allocator_,expression_point); 41733 | 41734 | return node_allocator_->allocate<literal_node_t>(v); 41735 | } 41736 | 41737 | if (expression_point && expression_point->valid()) 41738 | { 41739 | return expression_point; 41740 | } 41741 | 41742 | parser_->set_error(parser_error::make_error( 41743 | parser_error::e_parser, 41744 | token_t(), 41745 | "ERR281 - Failed to synthesize node: NodeType", 41746 | exprtk_error_location)); 41747 | 41748 | details::free_node(*node_allocator_, expression_point); 41749 | } 41750 | 41751 | return error_node(); 41752 | } 41753 | 41754 | template <typename NodeType, std::size_t N> 41755 | inline expression_node_ptr synthesize_expression(F* f, expression_node_ptr (&branch)[N]) 41756 | { 41757 | if (!details::all_nodes_valid<N>(branch)) 41758 | { 41759 | free_all_nodes(*node_allocator_,branch); 41760 | 41761 | return error_node(); 41762 | } 41763 | 41764 | typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t; 41765 | 41766 | // Attempt simple constant folding optimisation. 41767 | 41768 | expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(f); 41769 | function_N_node_t* func_node_ptr = dynamic_cast<function_N_node_t*>(expression_point); 41770 | 41771 | if (0 == func_node_ptr) 41772 | { 41773 | free_all_nodes(*node_allocator_,branch); 41774 | 41775 | return error_node(); 41776 | } 41777 | else 41778 | func_node_ptr->init_branches(branch); 41779 | 41780 | if (is_constant_foldable<N>(branch) && !f->has_side_effects()) 41781 | { 41782 | Type v = expression_point->value(); 41783 | details::free_node(*node_allocator_,expression_point); 41784 | 41785 | return node_allocator_->allocate<literal_node_t>(v); 41786 | } 41787 | 41788 | parser_->state_.activate_side_effect("synthesize_expression(function<NT,N>)"); 41789 | 41790 | return expression_point; 41791 | } 41792 | 41793 | bool strength_reduction_enabled_; 41794 | details::node_allocator* node_allocator_; 41795 | synthesize_map_t synthesize_map_; 41796 | unary_op_map_t* unary_op_map_; 41797 | binary_op_map_t* binary_op_map_; 41798 | inv_binary_op_map_t* inv_binary_op_map_; 41799 | sf3_map_t* sf3_map_; 41800 | sf4_map_t* sf4_map_; 41801 | parser_t* parser_; 41802 | }; // class expression_generator 41803 | 41804 | inline void set_error(const parser_error::type& error_type) 41805 | { 41806 | error_list_.push_back(error_type); 41807 | } 41808 | 41809 | inline void remove_last_error() 41810 | { 41811 | if (!error_list_.empty()) 41812 | { 41813 | error_list_.pop_back(); 41814 | } 41815 | } 41816 | 41817 | inline void set_synthesis_error(const std::string& synthesis_error_message) 41818 | { 41819 | if (synthesis_error_.empty()) 41820 | { 41821 | synthesis_error_ = synthesis_error_message; 41822 | } 41823 | } 41824 | 41825 | inline void register_local_vars(expression<T>& e) 41826 | { 41827 | for (std::size_t i = 0; i < sem_.size(); ++i) 41828 | { 41829 | scope_element& se = sem_.get_element(i); 41830 | 41831 | exprtk_debug(("register_local_vars() - se[%s]\n", se.name.c_str())); 41832 | 41833 | if ( 41834 | (scope_element::e_variable == se.type) || 41835 | (scope_element::e_literal == se.type) || 41836 | (scope_element::e_vecelem == se.type) 41837 | ) 41838 | { 41839 | if (se.var_node) 41840 | { 41841 | e.register_local_var(se.var_node); 41842 | } 41843 | 41844 | if (se.data) 41845 | { 41846 | e.register_local_data(se.data, 1, 0); 41847 | } 41848 | } 41849 | else if (scope_element::e_vector == se.type) 41850 | { 41851 | if (se.vec_node) 41852 | { 41853 | e.register_local_var(se.vec_node); 41854 | } 41855 | 41856 | if (se.data) 41857 | { 41858 | e.register_local_data(se.data, se.size, 1); 41859 | } 41860 | } 41861 | #ifndef exprtk_disable_string_capabilities 41862 | else if (scope_element::e_string == se.type) 41863 | { 41864 | if (se.str_node) 41865 | { 41866 | e.register_local_var(se.str_node); 41867 | } 41868 | 41869 | if (se.data) 41870 | { 41871 | e.register_local_data(se.data, se.size, 2); 41872 | } 41873 | } 41874 | #endif 41875 | 41876 | se.var_node = 0; 41877 | se.vec_node = 0; 41878 | #ifndef exprtk_disable_string_capabilities 41879 | se.str_node = 0; 41880 | #endif 41881 | se.data = 0; 41882 | se.ref_count = 0; 41883 | se.active = false; 41884 | } 41885 | } 41886 | 41887 | inline void register_return_results(expression<T>& e) 41888 | { 41889 | e.register_return_results(results_context_); 41890 | results_context_ = 0; 41891 | } 41892 | 41893 | inline void load_unary_operations_map(unary_op_map_t& m) 41894 | { 41895 | #define register_unary_op(Op, UnaryFunctor) \ 41896 | m.insert(std::make_pair(Op,UnaryFunctor<T>::process)); \ 41897 | 41898 | register_unary_op(details::e_abs , details::abs_op ) 41899 | register_unary_op(details::e_acos , details::acos_op ) 41900 | register_unary_op(details::e_acosh , details::acosh_op) 41901 | register_unary_op(details::e_asin , details::asin_op ) 41902 | register_unary_op(details::e_asinh , details::asinh_op) 41903 | register_unary_op(details::e_atanh , details::atanh_op) 41904 | register_unary_op(details::e_ceil , details::ceil_op ) 41905 | register_unary_op(details::e_cos , details::cos_op ) 41906 | register_unary_op(details::e_cosh , details::cosh_op ) 41907 | register_unary_op(details::e_exp , details::exp_op ) 41908 | register_unary_op(details::e_expm1 , details::expm1_op) 41909 | register_unary_op(details::e_floor , details::floor_op) 41910 | register_unary_op(details::e_log , details::log_op ) 41911 | register_unary_op(details::e_log10 , details::log10_op) 41912 | register_unary_op(details::e_log2 , details::log2_op ) 41913 | register_unary_op(details::e_log1p , details::log1p_op) 41914 | register_unary_op(details::e_neg , details::neg_op ) 41915 | register_unary_op(details::e_pos , details::pos_op ) 41916 | register_unary_op(details::e_round , details::round_op) 41917 | register_unary_op(details::e_sin , details::sin_op ) 41918 | register_unary_op(details::e_sinc , details::sinc_op ) 41919 | register_unary_op(details::e_sinh , details::sinh_op ) 41920 | register_unary_op(details::e_sqrt , details::sqrt_op ) 41921 | register_unary_op(details::e_tan , details::tan_op ) 41922 | register_unary_op(details::e_tanh , details::tanh_op ) 41923 | register_unary_op(details::e_cot , details::cot_op ) 41924 | register_unary_op(details::e_sec , details::sec_op ) 41925 | register_unary_op(details::e_csc , details::csc_op ) 41926 | register_unary_op(details::e_r2d , details::r2d_op ) 41927 | register_unary_op(details::e_d2r , details::d2r_op ) 41928 | register_unary_op(details::e_d2g , details::d2g_op ) 41929 | register_unary_op(details::e_g2d , details::g2d_op ) 41930 | register_unary_op(details::e_notl , details::notl_op ) 41931 | register_unary_op(details::e_sgn , details::sgn_op ) 41932 | register_unary_op(details::e_erf , details::erf_op ) 41933 | register_unary_op(details::e_erfc , details::erfc_op ) 41934 | register_unary_op(details::e_ncdf , details::ncdf_op ) 41935 | register_unary_op(details::e_frac , details::frac_op ) 41936 | register_unary_op(details::e_trunc , details::trunc_op) 41937 | #undef register_unary_op 41938 | } 41939 | 41940 | inline void load_binary_operations_map(binary_op_map_t& m) 41941 | { 41942 | typedef typename binary_op_map_t::value_type value_type; 41943 | 41944 | #define register_binary_op(Op, BinaryFunctor) \ 41945 | m.insert(value_type(Op,BinaryFunctor<T>::process)); \ 41946 | 41947 | register_binary_op(details::e_add , details::add_op ) 41948 | register_binary_op(details::e_sub , details::sub_op ) 41949 | register_binary_op(details::e_mul , details::mul_op ) 41950 | register_binary_op(details::e_div , details::div_op ) 41951 | register_binary_op(details::e_mod , details::mod_op ) 41952 | register_binary_op(details::e_pow , details::pow_op ) 41953 | register_binary_op(details::e_lt , details::lt_op ) 41954 | register_binary_op(details::e_lte , details::lte_op ) 41955 | register_binary_op(details::e_gt , details::gt_op ) 41956 | register_binary_op(details::e_gte , details::gte_op ) 41957 | register_binary_op(details::e_eq , details::eq_op ) 41958 | register_binary_op(details::e_ne , details::ne_op ) 41959 | register_binary_op(details::e_and , details::and_op ) 41960 | register_binary_op(details::e_nand , details::nand_op) 41961 | register_binary_op(details::e_or , details::or_op ) 41962 | register_binary_op(details::e_nor , details::nor_op ) 41963 | register_binary_op(details::e_xor , details::xor_op ) 41964 | register_binary_op(details::e_xnor , details::xnor_op) 41965 | #undef register_binary_op 41966 | } 41967 | 41968 | inline void load_inv_binary_operations_map(inv_binary_op_map_t& m) 41969 | { 41970 | typedef typename inv_binary_op_map_t::value_type value_type; 41971 | 41972 | #define register_binary_op(Op, BinaryFunctor) \ 41973 | m.insert(value_type(BinaryFunctor<T>::process,Op)); \ 41974 | 41975 | register_binary_op(details::e_add , details::add_op ) 41976 | register_binary_op(details::e_sub , details::sub_op ) 41977 | register_binary_op(details::e_mul , details::mul_op ) 41978 | register_binary_op(details::e_div , details::div_op ) 41979 | register_binary_op(details::e_mod , details::mod_op ) 41980 | register_binary_op(details::e_pow , details::pow_op ) 41981 | register_binary_op(details::e_lt , details::lt_op ) 41982 | register_binary_op(details::e_lte , details::lte_op ) 41983 | register_binary_op(details::e_gt , details::gt_op ) 41984 | register_binary_op(details::e_gte , details::gte_op ) 41985 | register_binary_op(details::e_eq , details::eq_op ) 41986 | register_binary_op(details::e_ne , details::ne_op ) 41987 | register_binary_op(details::e_and , details::and_op ) 41988 | register_binary_op(details::e_nand , details::nand_op) 41989 | register_binary_op(details::e_or , details::or_op ) 41990 | register_binary_op(details::e_nor , details::nor_op ) 41991 | register_binary_op(details::e_xor , details::xor_op ) 41992 | register_binary_op(details::e_xnor , details::xnor_op) 41993 | #undef register_binary_op 41994 | } 41995 | 41996 | inline void load_sf3_map(sf3_map_t& sf3_map) 41997 | { 41998 | typedef std::pair<trinary_functor_t,details::operator_type> pair_t; 41999 | 42000 | #define register_sf3(Op) \ 42001 | sf3_map[details::sf##Op##_op<T>::id()] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \ 42002 | 42003 | register_sf3(00) register_sf3(01) register_sf3(02) register_sf3(03) 42004 | register_sf3(04) register_sf3(05) register_sf3(06) register_sf3(07) 42005 | register_sf3(08) register_sf3(09) register_sf3(10) register_sf3(11) 42006 | register_sf3(12) register_sf3(13) register_sf3(14) register_sf3(15) 42007 | register_sf3(16) register_sf3(17) register_sf3(18) register_sf3(19) 42008 | register_sf3(20) register_sf3(21) register_sf3(22) register_sf3(23) 42009 | register_sf3(24) register_sf3(25) register_sf3(26) register_sf3(27) 42010 | register_sf3(28) register_sf3(29) register_sf3(30) 42011 | #undef register_sf3 42012 | 42013 | #define register_sf3_extid(Id, Op) \ 42014 | sf3_map[Id] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \ 42015 | 42016 | register_sf3_extid("(t-t)-t",23) // (t-t)-t --> t-(t+t) 42017 | #undef register_sf3_extid 42018 | } 42019 | 42020 | inline void load_sf4_map(sf4_map_t& sf4_map) 42021 | { 42022 | typedef std::pair<quaternary_functor_t,details::operator_type> pair_t; 42023 | 42024 | #define register_sf4(Op) \ 42025 | sf4_map[details::sf##Op##_op<T>::id()] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \ 42026 | 42027 | register_sf4(48) register_sf4(49) register_sf4(50) register_sf4(51) 42028 | register_sf4(52) register_sf4(53) register_sf4(54) register_sf4(55) 42029 | register_sf4(56) register_sf4(57) register_sf4(58) register_sf4(59) 42030 | register_sf4(60) register_sf4(61) register_sf4(62) register_sf4(63) 42031 | register_sf4(64) register_sf4(65) register_sf4(66) register_sf4(67) 42032 | register_sf4(68) register_sf4(69) register_sf4(70) register_sf4(71) 42033 | register_sf4(72) register_sf4(73) register_sf4(74) register_sf4(75) 42034 | register_sf4(76) register_sf4(77) register_sf4(78) register_sf4(79) 42035 | register_sf4(80) register_sf4(81) register_sf4(82) register_sf4(83) 42036 | #undef register_sf4 42037 | 42038 | #define register_sf4ext(Op) \ 42039 | sf4_map[details::sfext##Op##_op<T>::id()] = pair_t(details::sfext##Op##_op<T>::process,details::e_sf4ext##Op); \ 42040 | 42041 | register_sf4ext(00) register_sf4ext(01) register_sf4ext(02) register_sf4ext(03) 42042 | register_sf4ext(04) register_sf4ext(05) register_sf4ext(06) register_sf4ext(07) 42043 | register_sf4ext(08) register_sf4ext(09) register_sf4ext(10) register_sf4ext(11) 42044 | register_sf4ext(12) register_sf4ext(13) register_sf4ext(14) register_sf4ext(15) 42045 | register_sf4ext(16) register_sf4ext(17) register_sf4ext(18) register_sf4ext(19) 42046 | register_sf4ext(20) register_sf4ext(21) register_sf4ext(22) register_sf4ext(23) 42047 | register_sf4ext(24) register_sf4ext(25) register_sf4ext(26) register_sf4ext(27) 42048 | register_sf4ext(28) register_sf4ext(29) register_sf4ext(30) register_sf4ext(31) 42049 | register_sf4ext(32) register_sf4ext(33) register_sf4ext(34) register_sf4ext(35) 42050 | register_sf4ext(36) register_sf4ext(36) register_sf4ext(38) register_sf4ext(39) 42051 | register_sf4ext(40) register_sf4ext(41) register_sf4ext(42) register_sf4ext(43) 42052 | register_sf4ext(44) register_sf4ext(45) register_sf4ext(46) register_sf4ext(47) 42053 | register_sf4ext(48) register_sf4ext(49) register_sf4ext(50) register_sf4ext(51) 42054 | register_sf4ext(52) register_sf4ext(53) register_sf4ext(54) register_sf4ext(55) 42055 | register_sf4ext(56) register_sf4ext(57) register_sf4ext(58) register_sf4ext(59) 42056 | register_sf4ext(60) register_sf4ext(61) 42057 | #undef register_sf4ext 42058 | } 42059 | 42060 | inline results_context_t& results_ctx() 42061 | { 42062 | if (0 == results_context_) 42063 | { 42064 | results_context_ = new results_context_t(); 42065 | } 42066 | 42067 | return (*results_context_); 42068 | } 42069 | 42070 | inline void return_cleanup() 42071 | { 42072 | #ifndef exprtk_disable_return_statement 42073 | if (results_context_) 42074 | { 42075 | delete results_context_; 42076 | results_context_ = 0; 42077 | } 42078 | 42079 | state_.return_stmt_present = false; 42080 | #endif 42081 | } 42082 | 42083 | inline bool valid_settings() 42084 | { 42085 | const std::size_t max_local_vector_size_bytes = sizeof(T) * settings_.max_local_vector_size(); 42086 | 42087 | if (max_local_vector_size_bytes > settings_.max_total_local_symbol_size_bytes()) 42088 | { 42089 | set_error(make_error( 42090 | parser_error::e_parser, 42091 | "ERR282 - Max local vector size of " + details::to_str(max_local_vector_size_bytes) + " bytes " 42092 | "is larger than max total local symbol size of " + details::to_str(settings_.max_total_local_symbol_size_bytes()) + " bytes", 42093 | exprtk_error_location)); 42094 | 42095 | return false; 42096 | } 42097 | 42098 | return true; 42099 | } 42100 | 42101 | private: 42102 | 42103 | parser(const parser<T>&) exprtk_delete; 42104 | parser<T>& operator=(const parser<T>&) exprtk_delete; 42105 | 42106 | settings_store settings_; 42107 | expression_generator<T> expression_generator_; 42108 | details::node_allocator node_allocator_; 42109 | symtab_store symtab_store_; 42110 | dependent_entity_collector dec_; 42111 | std::deque<parser_error::type> error_list_; 42112 | std::deque<bool> brkcnt_list_; 42113 | parser_state state_; 42114 | bool resolve_unknown_symbol_; 42115 | results_context_t* results_context_; 42116 | unknown_symbol_resolver* unknown_symbol_resolver_; 42117 | unknown_symbol_resolver default_usr_; 42118 | base_ops_map_t base_ops_map_; 42119 | unary_op_map_t unary_op_map_; 42120 | binary_op_map_t binary_op_map_; 42121 | inv_binary_op_map_t inv_binary_op_map_; 42122 | sf3_map_t sf3_map_; 42123 | sf4_map_t sf4_map_; 42124 | std::string synthesis_error_; 42125 | scope_element_manager sem_; 42126 | std::vector<state_t> current_state_stack_; 42127 | 42128 | immutable_memory_map_t immutable_memory_map_; 42129 | immutable_symtok_map_t immutable_symtok_map_; 42130 | 42131 | lexer::helper::helper_assembly helper_assembly_; 42132 | 42133 | lexer::helper::commutative_inserter commutative_inserter_; 42134 | lexer::helper::operator_joiner operator_joiner_2_; 42135 | lexer::helper::operator_joiner operator_joiner_3_; 42136 | lexer::helper::symbol_replacer symbol_replacer_; 42137 | lexer::helper::bracket_checker bracket_checker_; 42138 | lexer::helper::numeric_checker<T> numeric_checker_; 42139 | lexer::helper::sequence_validator sequence_validator_; 42140 | lexer::helper::sequence_validator_3tokens sequence_validator_3tkns_; 42141 | 42142 | loop_runtime_check_ptr loop_runtime_check_; 42143 | vector_access_runtime_check_ptr vector_access_runtime_check_; 42144 | compilation_check_ptr compilation_check_ptr_; 42145 | assert_check_ptr assert_check_; 42146 | std::set<std::string> assert_ids_; 42147 | 42148 | template <typename ParserType> 42149 | friend void details::disable_type_checking(ParserType& p); 42150 | }; // class parser 42151 | 42152 | namespace details 42153 | { 42154 | template <typename T> 42155 | struct collector_helper 42156 | { 42157 | typedef exprtk::symbol_table<T> symbol_table_t; 42158 | typedef exprtk::expression<T> expression_t; 42159 | typedef exprtk::parser<T> parser_t; 42160 | typedef typename parser_t::dependent_entity_collector::symbol_t symbol_t; 42161 | typedef typename parser_t::unknown_symbol_resolver usr_t; 42162 | 42163 | struct resolve_as_vector : public usr_t 42164 | { 42165 | typedef exprtk::parser<T> parser_t; 42166 | 42167 | using usr_t::process; 42168 | 42169 | resolve_as_vector() 42170 | : usr_t(usr_t::e_usrmode_extended) 42171 | {} 42172 | 42173 | virtual bool process(const std::string& unknown_symbol, 42174 | symbol_table_t& symbol_table, 42175 | std::string&) exprtk_override 42176 | { 42177 | static T v[1]; 42178 | symbol_table.add_vector(unknown_symbol,v); 42179 | return true; 42180 | } 42181 | }; 42182 | 42183 | static inline bool collection_pass(const std::string& expression_string, 42184 | std::set<std::string>& symbol_set, 42185 | const bool collect_variables, 42186 | const bool collect_functions, 42187 | const bool vector_pass, 42188 | symbol_table_t& ext_symbol_table) 42189 | { 42190 | symbol_table_t symbol_table; 42191 | expression_t expression; 42192 | parser_t parser; 42193 | 42194 | resolve_as_vector vect_resolver; 42195 | 42196 | expression.register_symbol_table(symbol_table ); 42197 | expression.register_symbol_table(ext_symbol_table); 42198 | 42199 | if (vector_pass) 42200 | parser.enable_unknown_symbol_resolver(&vect_resolver); 42201 | else 42202 | parser.enable_unknown_symbol_resolver(); 42203 | 42204 | if (collect_variables) 42205 | parser.dec().collect_variables() = true; 42206 | 42207 | if (collect_functions) 42208 | parser.dec().collect_functions() = true; 42209 | 42210 | bool pass_result = false; 42211 | 42212 | details::disable_type_checking(parser); 42213 | 42214 | if (parser.compile(expression_string, expression)) 42215 | { 42216 | pass_result = true; 42217 | 42218 | std::deque<symbol_t> symb_list; 42219 | parser.dec().symbols(symb_list); 42220 | 42221 | for (std::size_t i = 0; i < symb_list.size(); ++i) 42222 | { 42223 | symbol_set.insert(symb_list[i].first); 42224 | } 42225 | } 42226 | 42227 | return pass_result; 42228 | } 42229 | }; 42230 | } 42231 | 42232 | template <typename Allocator, 42233 | template <typename, typename> class Sequence> 42234 | inline bool collect_variables(const std::string& expression, 42235 | Sequence<std::string, Allocator>& symbol_list) 42236 | { 42237 | typedef double T; 42238 | typedef details::collector_helper<T> collect_t; 42239 | 42240 | collect_t::symbol_table_t null_symbol_table; 42241 | 42242 | std::set<std::string> symbol_set; 42243 | 42244 | const bool variable_pass = collect_t::collection_pass 42245 | (expression, symbol_set, true, false, false, null_symbol_table); 42246 | const bool vector_pass = collect_t::collection_pass 42247 | (expression, symbol_set, true, false, true, null_symbol_table); 42248 | 42249 | if (!variable_pass && !vector_pass) 42250 | return false; 42251 | 42252 | std::set<std::string>::iterator itr = symbol_set.begin(); 42253 | 42254 | while (symbol_set.end() != itr) 42255 | { 42256 | symbol_list.push_back(*itr); 42257 | ++itr; 42258 | } 42259 | 42260 | return true; 42261 | } 42262 | 42263 | template <typename T, 42264 | typename Allocator, 42265 | template <typename, typename> class Sequence> 42266 | inline bool collect_variables(const std::string& expression, 42267 | exprtk::symbol_table<T>& extrnl_symbol_table, 42268 | Sequence<std::string, Allocator>& symbol_list) 42269 | { 42270 | typedef details::collector_helper<T> collect_t; 42271 | 42272 | std::set<std::string> symbol_set; 42273 | 42274 | const bool variable_pass = collect_t::collection_pass 42275 | (expression, symbol_set, true, false, false, extrnl_symbol_table); 42276 | const bool vector_pass = collect_t::collection_pass 42277 | (expression, symbol_set, true, false, true, extrnl_symbol_table); 42278 | 42279 | if (!variable_pass && !vector_pass) 42280 | return false; 42281 | 42282 | std::set<std::string>::iterator itr = symbol_set.begin(); 42283 | 42284 | while (symbol_set.end() != itr) 42285 | { 42286 | symbol_list.push_back(*itr); 42287 | ++itr; 42288 | } 42289 | 42290 | return true; 42291 | } 42292 | 42293 | template <typename Allocator, 42294 | template <typename, typename> class Sequence> 42295 | inline bool collect_functions(const std::string& expression, 42296 | Sequence<std::string, Allocator>& symbol_list) 42297 | { 42298 | typedef double T; 42299 | typedef details::collector_helper<T> collect_t; 42300 | 42301 | collect_t::symbol_table_t null_symbol_table; 42302 | 42303 | std::set<std::string> symbol_set; 42304 | 42305 | const bool variable_pass = collect_t::collection_pass 42306 | (expression, symbol_set, false, true, false, null_symbol_table); 42307 | const bool vector_pass = collect_t::collection_pass 42308 | (expression, symbol_set, false, true, true, null_symbol_table); 42309 | 42310 | if (!variable_pass && !vector_pass) 42311 | return false; 42312 | 42313 | std::set<std::string>::iterator itr = symbol_set.begin(); 42314 | 42315 | while (symbol_set.end() != itr) 42316 | { 42317 | symbol_list.push_back(*itr); 42318 | ++itr; 42319 | } 42320 | 42321 | return true; 42322 | } 42323 | 42324 | template <typename T, 42325 | typename Allocator, 42326 | template <typename, typename> class Sequence> 42327 | inline bool collect_functions(const std::string& expression, 42328 | exprtk::symbol_table<T>& extrnl_symbol_table, 42329 | Sequence<std::string, Allocator>& symbol_list) 42330 | { 42331 | typedef details::collector_helper<T> collect_t; 42332 | 42333 | std::set<std::string> symbol_set; 42334 | 42335 | const bool variable_pass = collect_t::collection_pass 42336 | (expression, symbol_set, false, true, false, extrnl_symbol_table); 42337 | const bool vector_pass = collect_t::collection_pass 42338 | (expression, symbol_set, false, true, true, extrnl_symbol_table); 42339 | 42340 | if (!variable_pass && !vector_pass) 42341 | return false; 42342 | 42343 | std::set<std::string>::iterator itr = symbol_set.begin(); 42344 | 42345 | while (symbol_set.end() != itr) 42346 | { 42347 | symbol_list.push_back(*itr); 42348 | ++itr; 42349 | } 42350 | 42351 | return true; 42352 | } 42353 | 42354 | template <typename T> 42355 | inline T integrate(const expression<T>& e, 42356 | T& x, 42357 | const T& r0, const T& r1, 42358 | const std::size_t number_of_intervals = 1000000) 42359 | { 42360 | if (r0 > r1) 42361 | return T(0); 42362 | 42363 | const T h = (r1 - r0) / (T(2) * number_of_intervals); 42364 | T total_area = T(0); 42365 | 42366 | for (std::size_t i = 0; i < number_of_intervals; ++i) 42367 | { 42368 | x = r0 + T(2) * i * h; 42369 | const T y0 = e.value(); x += h; 42370 | const T y1 = e.value(); x += h; 42371 | const T y2 = e.value(); x += h; 42372 | total_area += h * (y0 + T(4) * y1 + y2) / T(3); 42373 | } 42374 | 42375 | return total_area; 42376 | } 42377 | 42378 | template <typename T> 42379 | inline T integrate(const expression<T>& e, 42380 | const std::string& variable_name, 42381 | const T& r0, const T& r1, 42382 | const std::size_t number_of_intervals = 1000000) 42383 | { 42384 | const symbol_table<T>& sym_table = e.get_symbol_table(); 42385 | 42386 | if (!sym_table.valid()) 42387 | { 42388 | return std::numeric_limits<T>::quiet_NaN(); 42389 | } 42390 | 42391 | details::variable_node<T>* var = sym_table.get_variable(variable_name); 42392 | 42393 | if (var) 42394 | { 42395 | T& x = var->ref(); 42396 | const T x_original = x; 42397 | const T result = integrate(e, x, r0, r1, number_of_intervals); 42398 | x = x_original; 42399 | 42400 | return result; 42401 | } 42402 | 42403 | return std::numeric_limits<T>::quiet_NaN(); 42404 | } 42405 | 42406 | template <typename T> 42407 | inline T derivative(const expression<T>& e, 42408 | T& x, 42409 | const T& h = T(0.00000001)) 42410 | { 42411 | const T x_init = x; 42412 | const T _2h = T(2) * h; 42413 | 42414 | x = x_init + _2h; 42415 | const T y0 = e.value(); 42416 | x = x_init + h; 42417 | const T y1 = e.value(); 42418 | x = x_init - h; 42419 | const T y2 = e.value(); 42420 | x = x_init - _2h; 42421 | const T y3 = e.value(); 42422 | x = x_init; 42423 | 42424 | return (-y0 + T(8) * (y1 - y2) + y3) / (T(12) * h); 42425 | } 42426 | 42427 | template <typename T> 42428 | inline T second_derivative(const expression<T>& e, 42429 | T& x, 42430 | const T& h = T(0.00001)) 42431 | { 42432 | const T x_init = x; 42433 | const T _2h = T(2) * h; 42434 | 42435 | const T y = e.value(); 42436 | x = x_init + _2h; 42437 | const T y0 = e.value(); 42438 | x = x_init + h; 42439 | const T y1 = e.value(); 42440 | x = x_init - h; 42441 | const T y2 = e.value(); 42442 | x = x_init - _2h; 42443 | const T y3 = e.value(); 42444 | x = x_init; 42445 | 42446 | return (-y0 + T(16) * (y1 + y2) - T(30) * y - y3) / (T(12) * h * h); 42447 | } 42448 | 42449 | template <typename T> 42450 | inline T third_derivative(const expression<T>& e, 42451 | T& x, 42452 | const T& h = T(0.0001)) 42453 | { 42454 | const T x_init = x; 42455 | const T _2h = T(2) * h; 42456 | 42457 | x = x_init + _2h; 42458 | const T y0 = e.value(); 42459 | x = x_init + h; 42460 | const T y1 = e.value(); 42461 | x = x_init - h; 42462 | const T y2 = e.value(); 42463 | x = x_init - _2h; 42464 | const T y3 = e.value(); 42465 | x = x_init; 42466 | 42467 | return (y0 + T(2) * (y2 - y1) - y3) / (T(2) * h * h * h); 42468 | } 42469 | 42470 | template <typename T> 42471 | inline T derivative(const expression<T>& e, 42472 | const std::string& variable_name, 42473 | const T& h = T(0.00000001)) 42474 | { 42475 | const symbol_table<T>& sym_table = e.get_symbol_table(); 42476 | 42477 | if (!sym_table.valid()) 42478 | { 42479 | return std::numeric_limits<T>::quiet_NaN(); 42480 | } 42481 | 42482 | details::variable_node<T>* var = sym_table.get_variable(variable_name); 42483 | 42484 | if (var) 42485 | { 42486 | T& x = var->ref(); 42487 | const T x_original = x; 42488 | const T result = derivative(e, x, h); 42489 | x = x_original; 42490 | 42491 | return result; 42492 | } 42493 | 42494 | return std::numeric_limits<T>::quiet_NaN(); 42495 | } 42496 | 42497 | template <typename T> 42498 | inline T second_derivative(const expression<T>& e, 42499 | const std::string& variable_name, 42500 | const T& h = T(0.00001)) 42501 | { 42502 | const symbol_table<T>& sym_table = e.get_symbol_table(); 42503 | 42504 | if (!sym_table.valid()) 42505 | { 42506 | return std::numeric_limits<T>::quiet_NaN(); 42507 | } 42508 | 42509 | details::variable_node<T>* var = sym_table.get_variable(variable_name); 42510 | 42511 | if (var) 42512 | { 42513 | T& x = var->ref(); 42514 | const T x_original = x; 42515 | const T result = second_derivative(e, x, h); 42516 | x = x_original; 42517 | 42518 | return result; 42519 | } 42520 | 42521 | return std::numeric_limits<T>::quiet_NaN(); 42522 | } 42523 | 42524 | template <typename T> 42525 | inline T third_derivative(const expression<T>& e, 42526 | const std::string& variable_name, 42527 | const T& h = T(0.0001)) 42528 | { 42529 | const symbol_table<T>& sym_table = e.get_symbol_table(); 42530 | 42531 | if (!sym_table.valid()) 42532 | { 42533 | return std::numeric_limits<T>::quiet_NaN(); 42534 | } 42535 | 42536 | details::variable_node<T>* var = sym_table.get_variable(variable_name); 42537 | 42538 | if (var) 42539 | { 42540 | T& x = var->ref(); 42541 | const T x_original = x; 42542 | const T result = third_derivative(e, x, h); 42543 | x = x_original; 42544 | 42545 | return result; 42546 | } 42547 | 42548 | return std::numeric_limits<T>::quiet_NaN(); 42549 | } 42550 | 42551 | /* 42552 | Note: The following 'compute' routines are simple helpers, 42553 | for quickly setting up the required pieces of code in order 42554 | to evaluate an expression. By virtue of how they operate 42555 | there will be an overhead with regards to their setup and 42556 | teardown and hence should not be used in time critical 42557 | sections of code. 42558 | Furthermore they only assume a small sub set of variables, 42559 | no string variables or user defined functions. 42560 | */ 42561 | template <typename T> 42562 | inline bool compute(const std::string& expression_string, T& result) 42563 | { 42564 | // No variables 42565 | symbol_table<T> symbol_table; 42566 | symbol_table.add_constants(); 42567 | 42568 | expression<T> expression; 42569 | expression.register_symbol_table(symbol_table); 42570 | 42571 | parser<T> parser; 42572 | 42573 | if (parser.compile(expression_string,expression)) 42574 | { 42575 | result = expression.value(); 42576 | 42577 | return true; 42578 | } 42579 | else 42580 | return false; 42581 | } 42582 | 42583 | template <typename T> 42584 | inline bool compute(const std::string& expression_string, 42585 | const T& x, 42586 | T& result) 42587 | { 42588 | // Only 'x' 42589 | static const std::string x_var("x"); 42590 | 42591 | symbol_table<T> symbol_table; 42592 | symbol_table.add_constants(); 42593 | symbol_table.add_constant(x_var,x); 42594 | 42595 | expression<T> expression; 42596 | expression.register_symbol_table(symbol_table); 42597 | 42598 | parser<T> parser; 42599 | 42600 | if (parser.compile(expression_string,expression)) 42601 | { 42602 | result = expression.value(); 42603 | 42604 | return true; 42605 | } 42606 | else 42607 | return false; 42608 | } 42609 | 42610 | template <typename T> 42611 | inline bool compute(const std::string& expression_string, 42612 | const T&x, const T& y, 42613 | T& result) 42614 | { 42615 | // Only 'x' and 'y' 42616 | static const std::string x_var("x"); 42617 | static const std::string y_var("y"); 42618 | 42619 | symbol_table<T> symbol_table; 42620 | symbol_table.add_constants(); 42621 | symbol_table.add_constant(x_var,x); 42622 | symbol_table.add_constant(y_var,y); 42623 | 42624 | expression<T> expression; 42625 | expression.register_symbol_table(symbol_table); 42626 | 42627 | parser<T> parser; 42628 | 42629 | if (parser.compile(expression_string,expression)) 42630 | { 42631 | result = expression.value(); 42632 | 42633 | return true; 42634 | } 42635 | else 42636 | return false; 42637 | } 42638 | 42639 | template <typename T> 42640 | inline bool compute(const std::string& expression_string, 42641 | const T& x, const T& y, const T& z, 42642 | T& result) 42643 | { 42644 | // Only 'x', 'y' or 'z' 42645 | static const std::string x_var("x"); 42646 | static const std::string y_var("y"); 42647 | static const std::string z_var("z"); 42648 | 42649 | symbol_table<T> symbol_table; 42650 | symbol_table.add_constants(); 42651 | symbol_table.add_constant(x_var,x); 42652 | symbol_table.add_constant(y_var,y); 42653 | symbol_table.add_constant(z_var,z); 42654 | 42655 | expression<T> expression; 42656 | expression.register_symbol_table(symbol_table); 42657 | 42658 | parser<T> parser; 42659 | 42660 | if (parser.compile(expression_string,expression)) 42661 | { 42662 | result = expression.value(); 42663 | 42664 | return true; 42665 | } 42666 | else 42667 | return false; 42668 | } 42669 | 42670 | template <typename T, std::size_t N> 42671 | class polynomial : public ifunction<T> 42672 | { 42673 | private: 42674 | 42675 | template <typename Type, std::size_t NumberOfCoefficients> 42676 | struct poly_impl { }; 42677 | 42678 | template <typename Type> 42679 | struct poly_impl <Type,12> 42680 | { 42681 | static inline T evaluate(const Type x, 42682 | const Type c12, const Type c11, const Type c10, const Type c9, const Type c8, 42683 | const Type c7, const Type c6, const Type c5, const Type c4, const Type c3, 42684 | const Type c2, const Type c1, const Type c0) 42685 | { 42686 | // 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 42687 | 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); 42688 | } 42689 | }; 42690 | 42691 | template <typename Type> 42692 | struct poly_impl <Type,11> 42693 | { 42694 | static inline T evaluate(const Type x, 42695 | const Type c11, const Type c10, const Type c9, const Type c8, const Type c7, 42696 | const Type c6, const Type c5, const Type c4, const Type c3, const Type c2, 42697 | const Type c1, const Type c0) 42698 | { 42699 | // 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 42700 | return (((((((((((c11 * x + c10) * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42701 | } 42702 | }; 42703 | 42704 | template <typename Type> 42705 | struct poly_impl <Type,10> 42706 | { 42707 | static inline T evaluate(const Type x, 42708 | const Type c10, const Type c9, const Type c8, const Type c7, const Type c6, 42709 | const Type c5, const Type c4, const Type c3, const Type c2, const Type c1, 42710 | const Type c0) 42711 | { 42712 | // 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 42713 | return ((((((((((c10 * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42714 | } 42715 | }; 42716 | 42717 | template <typename Type> 42718 | struct poly_impl <Type,9> 42719 | { 42720 | static inline T evaluate(const Type x, 42721 | const Type c9, const Type c8, const Type c7, const Type c6, const Type c5, 42722 | const Type c4, const Type c3, const Type c2, const Type c1, const Type c0) 42723 | { 42724 | // 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 42725 | return (((((((((c9 * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42726 | } 42727 | }; 42728 | 42729 | template <typename Type> 42730 | struct poly_impl <Type,8> 42731 | { 42732 | static inline T evaluate(const Type x, 42733 | const Type c8, const Type c7, const Type c6, const Type c5, const Type c4, 42734 | const Type c3, const Type c2, const Type c1, const Type c0) 42735 | { 42736 | // 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 42737 | return ((((((((c8 * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42738 | } 42739 | }; 42740 | 42741 | template <typename Type> 42742 | struct poly_impl <Type,7> 42743 | { 42744 | static inline T evaluate(const Type x, 42745 | const Type c7, const Type c6, const Type c5, const Type c4, const Type c3, 42746 | const Type c2, const Type c1, const Type c0) 42747 | { 42748 | // 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 42749 | return (((((((c7 * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42750 | } 42751 | }; 42752 | 42753 | template <typename Type> 42754 | struct poly_impl <Type,6> 42755 | { 42756 | static inline T evaluate(const Type x, 42757 | const Type c6, const Type c5, const Type c4, const Type c3, const Type c2, 42758 | const Type c1, const Type c0) 42759 | { 42760 | // p(x) = c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 42761 | return ((((((c6 * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42762 | } 42763 | }; 42764 | 42765 | template <typename Type> 42766 | struct poly_impl <Type,5> 42767 | { 42768 | static inline T evaluate(const Type x, 42769 | const Type c5, const Type c4, const Type c3, const Type c2, 42770 | const Type c1, const Type c0) 42771 | { 42772 | // p(x) = c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 42773 | return (((((c5 * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42774 | } 42775 | }; 42776 | 42777 | template <typename Type> 42778 | struct poly_impl <Type,4> 42779 | { 42780 | static inline T evaluate(const Type x, const Type c4, const Type c3, const Type c2, const Type c1, const Type c0) 42781 | { 42782 | // p(x) = c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 42783 | return ((((c4 * x + c3) * x + c2) * x + c1) * x + c0); 42784 | } 42785 | }; 42786 | 42787 | template <typename Type> 42788 | struct poly_impl <Type,3> 42789 | { 42790 | static inline T evaluate(const Type x, const Type c3, const Type c2, const Type c1, const Type c0) 42791 | { 42792 | // p(x) = c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 42793 | return (((c3 * x + c2) * x + c1) * x + c0); 42794 | } 42795 | }; 42796 | 42797 | template <typename Type> 42798 | struct poly_impl <Type,2> 42799 | { 42800 | static inline T evaluate(const Type x, const Type c2, const Type c1, const Type c0) 42801 | { 42802 | // p(x) = c_2x^2 + c_1x^1 + c_0x^0 42803 | return ((c2 * x + c1) * x + c0); 42804 | } 42805 | }; 42806 | 42807 | template <typename Type> 42808 | struct poly_impl <Type,1> 42809 | { 42810 | static inline T evaluate(const Type x, const Type c1, const Type c0) 42811 | { 42812 | // p(x) = c_1x^1 + c_0x^0 42813 | return (c1 * x + c0); 42814 | } 42815 | }; 42816 | 42817 | public: 42818 | 42819 | using ifunction<T>::operator(); 42820 | 42821 | polynomial() 42822 | : ifunction<T>((N+2 <= 20) ? (N + 2) : std::numeric_limits<std::size_t>::max()) 42823 | { 42824 | disable_has_side_effects(*this); 42825 | } 42826 | 42827 | virtual ~polynomial() exprtk_override 42828 | {} 42829 | 42830 | #define poly_rtrn(NN) \ 42831 | return (NN != N) ? std::numeric_limits<T>::quiet_NaN() : 42832 | 42833 | inline virtual T operator() (const T& x, const T& c1, const T& c0) exprtk_override 42834 | { 42835 | poly_rtrn(1) (poly_impl<T,1>::evaluate(x, c1, c0)); 42836 | } 42837 | 42838 | inline virtual T operator() (const T& x, const T& c2, const T& c1, const T& c0) exprtk_override 42839 | { 42840 | poly_rtrn(2) (poly_impl<T,2>::evaluate(x, c2, c1, c0)); 42841 | } 42842 | 42843 | inline virtual T operator() (const T& x, const T& c3, const T& c2, const T& c1, const T& c0) exprtk_override 42844 | { 42845 | poly_rtrn(3) (poly_impl<T,3>::evaluate(x, c3, c2, c1, c0)); 42846 | } 42847 | 42848 | inline virtual T operator() (const T& x, const T& c4, const T& c3, const T& c2, const T& c1, 42849 | const T& c0) exprtk_override 42850 | { 42851 | poly_rtrn(4) (poly_impl<T,4>::evaluate(x, c4, c3, c2, c1, c0)); 42852 | } 42853 | 42854 | inline virtual T operator() (const T& x, const T& c5, const T& c4, const T& c3, const T& c2, 42855 | const T& c1, const T& c0) exprtk_override 42856 | { 42857 | poly_rtrn(5) (poly_impl<T,5>::evaluate(x, c5, c4, c3, c2, c1, c0)); 42858 | } 42859 | 42860 | inline virtual T operator() (const T& x, const T& c6, const T& c5, const T& c4, const T& c3, 42861 | const T& c2, const T& c1, const T& c0) exprtk_override 42862 | { 42863 | poly_rtrn(6) (poly_impl<T,6>::evaluate(x, c6, c5, c4, c3, c2, c1, c0)); 42864 | } 42865 | 42866 | inline virtual T operator() (const T& x, const T& c7, const T& c6, const T& c5, const T& c4, 42867 | const T& c3, const T& c2, const T& c1, const T& c0) exprtk_override 42868 | { 42869 | poly_rtrn(7) (poly_impl<T,7>::evaluate(x, c7, c6, c5, c4, c3, c2, c1, c0)); 42870 | } 42871 | 42872 | inline virtual T operator() (const T& x, const T& c8, const T& c7, const T& c6, const T& c5, 42873 | const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) exprtk_override 42874 | { 42875 | poly_rtrn(8) (poly_impl<T,8>::evaluate(x, c8, c7, c6, c5, c4, c3, c2, c1, c0)); 42876 | } 42877 | 42878 | inline virtual T operator() (const T& x, const T& c9, const T& c8, const T& c7, const T& c6, 42879 | const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, 42880 | const T& c0) exprtk_override 42881 | { 42882 | poly_rtrn(9) (poly_impl<T,9>::evaluate(x, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0)); 42883 | } 42884 | 42885 | inline virtual T operator() (const T& x, const T& c10, const T& c9, const T& c8, const T& c7, 42886 | const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, 42887 | const T& c1, const T& c0) exprtk_override 42888 | { 42889 | poly_rtrn(10) (poly_impl<T,10>::evaluate(x, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0)); 42890 | } 42891 | 42892 | inline virtual T operator() (const T& x, const T& c11, const T& c10, const T& c9, const T& c8, 42893 | const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, 42894 | const T& c2, const T& c1, const T& c0) exprtk_override 42895 | { 42896 | poly_rtrn(11) (poly_impl<T,11>::evaluate(x, c11, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0)); 42897 | } 42898 | 42899 | inline virtual T operator() (const T& x, const T& c12, const T& c11, const T& c10, const T& c9, 42900 | const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, 42901 | const T& c3, const T& c2, const T& c1, const T& c0) exprtk_override 42902 | { 42903 | poly_rtrn(12) (poly_impl<T,12>::evaluate(x, c12, c11, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0)); 42904 | } 42905 | 42906 | #undef poly_rtrn 42907 | 42908 | inline virtual T operator() () exprtk_override 42909 | { 42910 | return std::numeric_limits<T>::quiet_NaN(); 42911 | } 42912 | 42913 | inline virtual T operator() (const T&) exprtk_override 42914 | { 42915 | return std::numeric_limits<T>::quiet_NaN(); 42916 | } 42917 | 42918 | inline virtual T operator() (const T&, const T&) exprtk_override 42919 | { 42920 | return std::numeric_limits<T>::quiet_NaN(); 42921 | } 42922 | }; 42923 | 42924 | template <typename T> 42925 | class function_compositor 42926 | { 42927 | public: 42928 | 42929 | typedef exprtk::expression<T> expression_t; 42930 | typedef exprtk::symbol_table<T> symbol_table_t; 42931 | typedef exprtk::parser<T> parser_t; 42932 | typedef typename parser_t::settings_store settings_t; 42933 | 42934 | struct function 42935 | { 42936 | function() 42937 | {} 42938 | 42939 | explicit function(const std::string& n) 42940 | : name_(n) 42941 | {} 42942 | 42943 | function(const std::string& name, 42944 | const std::string& expression) 42945 | : name_(name) 42946 | , expression_(expression) 42947 | {} 42948 | 42949 | function(const std::string& name, 42950 | const std::string& expression, 42951 | const std::string& v0) 42952 | : name_(name) 42953 | , expression_(expression) 42954 | { 42955 | v_.push_back(v0); 42956 | } 42957 | 42958 | function(const std::string& name, 42959 | const std::string& expression, 42960 | const std::string& v0, const std::string& v1) 42961 | : name_(name) 42962 | , expression_(expression) 42963 | { 42964 | v_.push_back(v0); v_.push_back(v1); 42965 | } 42966 | 42967 | function(const std::string& name, 42968 | const std::string& expression, 42969 | const std::string& v0, const std::string& v1, 42970 | const std::string& v2) 42971 | : name_(name) 42972 | , expression_(expression) 42973 | { 42974 | v_.push_back(v0); v_.push_back(v1); 42975 | v_.push_back(v2); 42976 | } 42977 | 42978 | function(const std::string& name, 42979 | const std::string& expression, 42980 | const std::string& v0, const std::string& v1, 42981 | const std::string& v2, const std::string& v3) 42982 | : name_(name) 42983 | , expression_(expression) 42984 | { 42985 | v_.push_back(v0); v_.push_back(v1); 42986 | v_.push_back(v2); v_.push_back(v3); 42987 | } 42988 | 42989 | function(const std::string& name, 42990 | const std::string& expression, 42991 | const std::string& v0, const std::string& v1, 42992 | const std::string& v2, const std::string& v3, 42993 | const std::string& v4) 42994 | : name_(name) 42995 | , expression_(expression) 42996 | { 42997 | v_.push_back(v0); v_.push_back(v1); 42998 | v_.push_back(v2); v_.push_back(v3); 42999 | v_.push_back(v4); 43000 | } 43001 | 43002 | inline function& name(const std::string& n) 43003 | { 43004 | name_ = n; 43005 | return (*this); 43006 | } 43007 | 43008 | inline function& expression(const std::string& e) 43009 | { 43010 | expression_ = e; 43011 | return (*this); 43012 | } 43013 | 43014 | inline function& var(const std::string& v) 43015 | { 43016 | v_.push_back(v); 43017 | return (*this); 43018 | } 43019 | 43020 | inline function& vars(const std::string& v0, 43021 | const std::string& v1) 43022 | { 43023 | v_.push_back(v0); 43024 | v_.push_back(v1); 43025 | return (*this); 43026 | } 43027 | 43028 | inline function& vars(const std::string& v0, 43029 | const std::string& v1, 43030 | const std::string& v2) 43031 | { 43032 | v_.push_back(v0); 43033 | v_.push_back(v1); 43034 | v_.push_back(v2); 43035 | return (*this); 43036 | } 43037 | 43038 | inline function& vars(const std::string& v0, 43039 | const std::string& v1, 43040 | const std::string& v2, 43041 | const std::string& v3) 43042 | { 43043 | v_.push_back(v0); 43044 | v_.push_back(v1); 43045 | v_.push_back(v2); 43046 | v_.push_back(v3); 43047 | return (*this); 43048 | } 43049 | 43050 | inline function& vars(const std::string& v0, 43051 | const std::string& v1, 43052 | const std::string& v2, 43053 | const std::string& v3, 43054 | const std::string& v4) 43055 | { 43056 | v_.push_back(v0); 43057 | v_.push_back(v1); 43058 | v_.push_back(v2); 43059 | v_.push_back(v3); 43060 | v_.push_back(v4); 43061 | return (*this); 43062 | } 43063 | 43064 | std::string name_; 43065 | std::string expression_; 43066 | std::deque<std::string> v_; 43067 | }; 43068 | 43069 | private: 43070 | 43071 | struct base_func : public exprtk::ifunction<T> 43072 | { 43073 | typedef const T& type; 43074 | typedef exprtk::ifunction<T> function_t; 43075 | typedef std::vector<T*> varref_t; 43076 | typedef std::vector<T> var_t; 43077 | typedef std::vector<std::string> str_t; 43078 | typedef std::pair<T*,std::size_t> lvarref_t; 43079 | typedef std::vector<lvarref_t> lvr_vec_t; 43080 | typedef std::vector<std::string*> lstr_vec_t; 43081 | 43082 | using exprtk::ifunction<T>::operator(); 43083 | 43084 | explicit base_func(const std::size_t& pc = 0) 43085 | : exprtk::ifunction<T>(pc) 43086 | , local_var_stack_size(0) 43087 | , stack_depth(0) 43088 | { 43089 | v.resize(pc); 43090 | } 43091 | 43092 | virtual ~base_func() 43093 | {} 43094 | 43095 | #define exprtk_assign(Index) \ 43096 | (*v[Index]) = v##Index; \ 43097 | 43098 | inline void update(const T& v0) 43099 | { 43100 | exprtk_assign(0) 43101 | } 43102 | 43103 | inline void update(const T& v0, const T& v1) 43104 | { 43105 | exprtk_assign(0) exprtk_assign(1) 43106 | } 43107 | 43108 | inline void update(const T& v0, const T& v1, const T& v2) 43109 | { 43110 | exprtk_assign(0) exprtk_assign(1) 43111 | exprtk_assign(2) 43112 | } 43113 | 43114 | inline void update(const T& v0, const T& v1, const T& v2, const T& v3) 43115 | { 43116 | exprtk_assign(0) exprtk_assign(1) 43117 | exprtk_assign(2) exprtk_assign(3) 43118 | } 43119 | 43120 | inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4) 43121 | { 43122 | exprtk_assign(0) exprtk_assign(1) 43123 | exprtk_assign(2) exprtk_assign(3) 43124 | exprtk_assign(4) 43125 | } 43126 | 43127 | inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5) 43128 | { 43129 | exprtk_assign(0) exprtk_assign(1) 43130 | exprtk_assign(2) exprtk_assign(3) 43131 | exprtk_assign(4) exprtk_assign(5) 43132 | } 43133 | 43134 | #ifdef exprtk_assign 43135 | #undef exprtk_assign 43136 | #endif 43137 | 43138 | inline function_t& setup(expression_t& expr) 43139 | { 43140 | expression = expr; 43141 | 43142 | typedef typename expression_t::control_block ctrlblk_t; 43143 | typedef typename ctrlblk_t::local_data_list_t ldl_t; 43144 | typedef typename ctrlblk_t::data_type data_t; 43145 | typedef typename ldl_t::value_type ldl_value_type; 43146 | 43147 | const ldl_t ldl = expr.local_data_list(); 43148 | 43149 | std::vector<std::pair<std::size_t,data_t> > index_list; 43150 | 43151 | for (std::size_t i = 0; i < ldl.size(); ++i) 43152 | { 43153 | exprtk_debug(("base_func::setup() - element[%02d] type: %s size: %d\n", 43154 | static_cast<int>(i), 43155 | expression_t::control_block::to_str(ldl[i].type).c_str(), 43156 | static_cast<int>(ldl[i].size))); 43157 | 43158 | switch (ldl[i].type) 43159 | { 43160 | case ctrlblk_t::e_unknown : continue; 43161 | case ctrlblk_t::e_expr : continue; 43162 | case ctrlblk_t::e_vecholder : continue; 43163 | default : break; 43164 | } 43165 | 43166 | if (ldl[i].size) 43167 | { 43168 | index_list.push_back(std::make_pair(i,ldl[i].type)); 43169 | } 43170 | } 43171 | 43172 | std::size_t input_param_count = 0; 43173 | 43174 | for (std::size_t i = 0; i < index_list.size(); ++i) 43175 | { 43176 | const std::size_t index = index_list[i].first; 43177 | const ldl_value_type& local_var = ldl[index]; 43178 | 43179 | assert(local_var.pointer); 43180 | 43181 | if (i < (index_list.size() - v.size())) 43182 | { 43183 | if (local_var.type == ctrlblk_t::e_string) 43184 | { 43185 | local_str_vars.push_back( 43186 | reinterpret_cast<std::string*>(local_var.pointer)); 43187 | } 43188 | else if ( 43189 | (local_var.type == ctrlblk_t::e_data ) || 43190 | (local_var.type == ctrlblk_t::e_vecdata) 43191 | ) 43192 | { 43193 | local_vars.push_back(std::make_pair( 43194 | reinterpret_cast<T*>(local_var.pointer), 43195 | local_var.size)); 43196 | 43197 | local_var_stack_size += local_var.size; 43198 | } 43199 | } 43200 | else 43201 | { 43202 | v[input_param_count++] = reinterpret_cast<T*>(local_var.pointer); 43203 | } 43204 | } 43205 | 43206 | clear_stack(); 43207 | 43208 | return (*this); 43209 | } 43210 | 43211 | inline void pre() 43212 | { 43213 | if (stack_depth++) 43214 | { 43215 | if (!v.empty()) 43216 | { 43217 | var_t var_stack(v.size(),T(0)); 43218 | copy(v,var_stack); 43219 | input_params_stack.push_back(var_stack); 43220 | } 43221 | 43222 | if (!local_vars.empty()) 43223 | { 43224 | var_t local_vec_frame(local_var_stack_size,T(0)); 43225 | copy(local_vars,local_vec_frame); 43226 | local_var_stack.push_back(local_vec_frame); 43227 | } 43228 | 43229 | if (!local_str_vars.empty()) 43230 | { 43231 | str_t local_str_frame(local_str_vars.size()); 43232 | copy(local_str_vars,local_str_frame); 43233 | local_str_stack.push_back(local_str_frame); 43234 | } 43235 | } 43236 | } 43237 | 43238 | inline void post() 43239 | { 43240 | if (--stack_depth) 43241 | { 43242 | if (!v.empty()) 43243 | { 43244 | copy(input_params_stack.back(), v); 43245 | input_params_stack.pop_back(); 43246 | } 43247 | 43248 | if (!local_vars.empty()) 43249 | { 43250 | copy(local_var_stack.back(), local_vars); 43251 | local_var_stack.pop_back(); 43252 | } 43253 | 43254 | if (!local_str_vars.empty()) 43255 | { 43256 | copy(local_str_stack.back(), local_str_vars); 43257 | local_str_stack.pop_back(); 43258 | } 43259 | } 43260 | } 43261 | 43262 | void copy(const varref_t& src_v, var_t& dest_v) 43263 | { 43264 | for (std::size_t i = 0; i < src_v.size(); ++i) 43265 | { 43266 | dest_v[i] = (*src_v[i]); 43267 | } 43268 | } 43269 | 43270 | void copy(const lstr_vec_t& src_v, str_t& dest_v) 43271 | { 43272 | for (std::size_t i = 0; i < src_v.size(); ++i) 43273 | { 43274 | dest_v[i] = (*src_v[i]); 43275 | } 43276 | } 43277 | 43278 | void copy(const var_t& src_v, varref_t& dest_v) 43279 | { 43280 | for (std::size_t i = 0; i < src_v.size(); ++i) 43281 | { 43282 | (*dest_v[i]) = src_v[i]; 43283 | } 43284 | } 43285 | 43286 | void copy(const lvr_vec_t& src_v, var_t& dest_v) 43287 | { 43288 | typename var_t::iterator itr = dest_v.begin(); 43289 | typedef typename std::iterator_traits<typename var_t::iterator>::difference_type diff_t; 43290 | 43291 | for (std::size_t i = 0; i < src_v.size(); ++i) 43292 | { 43293 | lvarref_t vr = src_v[i]; 43294 | 43295 | if (1 == vr.second) 43296 | *itr++ = (*vr.first); 43297 | else 43298 | { 43299 | std::copy(vr.first, vr.first + vr.second, itr); 43300 | itr += static_cast<diff_t>(vr.second); 43301 | } 43302 | } 43303 | } 43304 | 43305 | void copy(const var_t& src_v, lvr_vec_t& dest_v) 43306 | { 43307 | typename var_t::const_iterator itr = src_v.begin(); 43308 | typedef typename std::iterator_traits<typename var_t::iterator>::difference_type diff_t; 43309 | 43310 | for (std::size_t i = 0; i < dest_v.size(); ++i) 43311 | { 43312 | lvarref_t& vr = dest_v[i]; 43313 | 43314 | assert(vr.first != 0); 43315 | assert(vr.second > 0); 43316 | 43317 | if (1 == vr.second) 43318 | (*vr.first) = *itr++; 43319 | else 43320 | { 43321 | std::copy(itr, itr + static_cast<diff_t>(vr.second), vr.first); 43322 | itr += static_cast<diff_t>(vr.second); 43323 | } 43324 | } 43325 | } 43326 | 43327 | void copy(const str_t& src_str, lstr_vec_t& dest_str) 43328 | { 43329 | assert(src_str.size() == dest_str.size()); 43330 | 43331 | for (std::size_t i = 0; i < dest_str.size(); ++i) 43332 | { 43333 | *dest_str[i] = src_str[i]; 43334 | } 43335 | } 43336 | 43337 | inline void clear_stack() 43338 | { 43339 | for (std::size_t i = 0; i < v.size(); ++i) 43340 | { 43341 | (*v[i]) = 0; 43342 | } 43343 | } 43344 | 43345 | inline virtual T value(expression_t& e) 43346 | { 43347 | return e.value(); 43348 | } 43349 | 43350 | expression_t expression; 43351 | varref_t v; 43352 | lvr_vec_t local_vars; 43353 | lstr_vec_t local_str_vars; 43354 | std::size_t local_var_stack_size; 43355 | std::size_t stack_depth; 43356 | std::deque<var_t> input_params_stack; 43357 | std::deque<var_t> local_var_stack; 43358 | std::deque<str_t> local_str_stack; 43359 | }; 43360 | 43361 | typedef std::map<std::string,base_func*> funcparam_t; 43362 | 43363 | typedef const T& type; 43364 | 43365 | template <typename BaseFuncType> 43366 | struct scoped_bft 43367 | { 43368 | explicit scoped_bft(BaseFuncType& bft) 43369 | : bft_(bft) 43370 | { 43371 | bft_.pre (); 43372 | } 43373 | 43374 | ~scoped_bft() 43375 | { 43376 | bft_.post(); 43377 | } 43378 | 43379 | BaseFuncType& bft_; 43380 | 43381 | private: 43382 | 43383 | scoped_bft(const scoped_bft&) exprtk_delete; 43384 | scoped_bft& operator=(const scoped_bft&) exprtk_delete; 43385 | }; 43386 | 43387 | struct func_0param : public base_func 43388 | { 43389 | using exprtk::ifunction<T>::operator(); 43390 | 43391 | func_0param() : base_func(0) {} 43392 | 43393 | inline T operator() () exprtk_override 43394 | { 43395 | scoped_bft<func_0param> sb(*this); 43396 | return this->value(base_func::expression); 43397 | } 43398 | }; 43399 | 43400 | struct func_1param : public base_func 43401 | { 43402 | using exprtk::ifunction<T>::operator(); 43403 | 43404 | func_1param() : base_func(1) {} 43405 | 43406 | inline T operator() (type v0) exprtk_override 43407 | { 43408 | scoped_bft<func_1param> sb(*this); 43409 | base_func::update(v0); 43410 | return this->value(base_func::expression); 43411 | } 43412 | }; 43413 | 43414 | struct func_2param : public base_func 43415 | { 43416 | using exprtk::ifunction<T>::operator(); 43417 | 43418 | func_2param() : base_func(2) {} 43419 | 43420 | inline T operator() (type v0, type v1) exprtk_override 43421 | { 43422 | scoped_bft<func_2param> sb(*this); 43423 | base_func::update(v0, v1); 43424 | return this->value(base_func::expression); 43425 | } 43426 | }; 43427 | 43428 | struct func_3param : public base_func 43429 | { 43430 | using exprtk::ifunction<T>::operator(); 43431 | 43432 | func_3param() : base_func(3) {} 43433 | 43434 | inline T operator() (type v0, type v1, type v2) exprtk_override 43435 | { 43436 | scoped_bft<func_3param> sb(*this); 43437 | base_func::update(v0, v1, v2); 43438 | return this->value(base_func::expression); 43439 | } 43440 | }; 43441 | 43442 | struct func_4param : public base_func 43443 | { 43444 | using exprtk::ifunction<T>::operator(); 43445 | 43446 | func_4param() : base_func(4) {} 43447 | 43448 | inline T operator() (type v0, type v1, type v2, type v3) exprtk_override 43449 | { 43450 | scoped_bft<func_4param> sb(*this); 43451 | base_func::update(v0, v1, v2, v3); 43452 | return this->value(base_func::expression); 43453 | } 43454 | }; 43455 | 43456 | struct func_5param : public base_func 43457 | { 43458 | using exprtk::ifunction<T>::operator(); 43459 | 43460 | func_5param() : base_func(5) {} 43461 | 43462 | inline T operator() (type v0, type v1, type v2, type v3, type v4) exprtk_override 43463 | { 43464 | scoped_bft<func_5param> sb(*this); 43465 | base_func::update(v0, v1, v2, v3, v4); 43466 | return this->value(base_func::expression); 43467 | } 43468 | }; 43469 | 43470 | struct func_6param : public base_func 43471 | { 43472 | using exprtk::ifunction<T>::operator(); 43473 | 43474 | func_6param() : base_func(6) {} 43475 | 43476 | inline T operator() (type v0, type v1, type v2, type v3, type v4, type v5) exprtk_override 43477 | { 43478 | scoped_bft<func_6param> sb(*this); 43479 | base_func::update(v0, v1, v2, v3, v4, v5); 43480 | return this->value(base_func::expression); 43481 | } 43482 | }; 43483 | 43484 | static T return_value(expression_t& e) 43485 | { 43486 | typedef exprtk::results_context<T> results_context_t; 43487 | typedef typename results_context_t::type_store_t type_t; 43488 | typedef typename type_t::scalar_view scalar_t; 43489 | 43490 | const T result = e.value(); 43491 | 43492 | if (e.return_invoked()) 43493 | { 43494 | // Due to the post compilation checks, it can be safely 43495 | // assumed that there will be at least one parameter 43496 | // and that the first parameter will always be scalar. 43497 | return scalar_t(e.results()[0])(); 43498 | } 43499 | 43500 | return result; 43501 | } 43502 | 43503 | #define def_fp_retval(N) \ 43504 | struct func_##N##param_retval exprtk_final : public func_##N##param \ 43505 | { \ 43506 | inline T value(expression_t& e) exprtk_override \ 43507 | { \ 43508 | return return_value(e); \ 43509 | } \ 43510 | }; \ 43511 | 43512 | def_fp_retval(0) 43513 | def_fp_retval(1) 43514 | def_fp_retval(2) 43515 | def_fp_retval(3) 43516 | def_fp_retval(4) 43517 | def_fp_retval(5) 43518 | def_fp_retval(6) 43519 | 43520 | #undef def_fp_retval 43521 | 43522 | template <typename Allocator, 43523 | template <typename, typename> class Sequence> 43524 | inline bool add(const std::string& name, 43525 | const std::string& expression, 43526 | const Sequence<std::string,Allocator>& var_list, 43527 | const bool override = false) 43528 | { 43529 | const typename std::map<std::string,expression_t>::iterator itr = expr_map_.find(name); 43530 | 43531 | if (expr_map_.end() != itr) 43532 | { 43533 | if (!override) 43534 | { 43535 | exprtk_debug(("Compositor error(add): function '%s' already defined\n", 43536 | name.c_str())); 43537 | 43538 | return false; 43539 | } 43540 | 43541 | remove(name, var_list.size()); 43542 | } 43543 | 43544 | if (compile_expression(name, expression, var_list)) 43545 | { 43546 | const std::size_t n = var_list.size(); 43547 | 43548 | fp_map_[n][name]->setup(expr_map_[name]); 43549 | 43550 | return true; 43551 | } 43552 | else 43553 | { 43554 | exprtk_debug(("Compositor error(add): Failed to compile function '%s'\n", 43555 | name.c_str())); 43556 | 43557 | return false; 43558 | } 43559 | } 43560 | 43561 | public: 43562 | 43563 | function_compositor() 43564 | : parser_(settings_t::default_compile_all_opts + 43565 | settings_t::e_disable_zero_return) 43566 | , fp_map_(7) 43567 | , load_variables_(false) 43568 | , load_vectors_(false) 43569 | {} 43570 | 43571 | explicit function_compositor(const symbol_table_t& st) 43572 | : symbol_table_(st) 43573 | , parser_(settings_t::default_compile_all_opts + 43574 | settings_t::e_disable_zero_return) 43575 | , fp_map_(7) 43576 | , load_variables_(false) 43577 | , load_vectors_(false) 43578 | {} 43579 | 43580 | ~function_compositor() 43581 | { 43582 | clear(); 43583 | } 43584 | 43585 | inline symbol_table_t& symbol_table() 43586 | { 43587 | return symbol_table_; 43588 | } 43589 | 43590 | inline const symbol_table_t& symbol_table() const 43591 | { 43592 | return symbol_table_; 43593 | } 43594 | 43595 | inline void add_auxiliary_symtab(symbol_table_t& symtab) 43596 | { 43597 | auxiliary_symtab_list_.push_back(&symtab); 43598 | } 43599 | 43600 | void load_variables(const bool load = true) 43601 | { 43602 | load_variables_ = load; 43603 | } 43604 | 43605 | void load_vectors(const bool load = true) 43606 | { 43607 | load_vectors_ = load; 43608 | } 43609 | 43610 | inline void register_loop_runtime_check(loop_runtime_check& lrtchk) 43611 | { 43612 | parser_.register_loop_runtime_check(lrtchk); 43613 | } 43614 | 43615 | inline void register_vector_access_runtime_check(vector_access_runtime_check& vartchk) 43616 | { 43617 | parser_.register_vector_access_runtime_check(vartchk); 43618 | } 43619 | 43620 | inline void register_compilation_timeout_check(compilation_check& compchk) 43621 | { 43622 | parser_.register_compilation_timeout_check(compchk); 43623 | } 43624 | 43625 | inline void clear_loop_runtime_check() 43626 | { 43627 | parser_.clear_loop_runtime_check(); 43628 | } 43629 | 43630 | inline void clear_vector_access_runtime_check() 43631 | { 43632 | parser_.clear_vector_access_runtime_check(); 43633 | } 43634 | 43635 | inline void clear_compilation_timeout_check() 43636 | { 43637 | parser_.clear_compilation_timeout_check(); 43638 | } 43639 | 43640 | void clear() 43641 | { 43642 | symbol_table_.clear(); 43643 | expr_map_ .clear(); 43644 | 43645 | for (std::size_t i = 0; i < fp_map_.size(); ++i) 43646 | { 43647 | typename funcparam_t::iterator itr = fp_map_[i].begin(); 43648 | typename funcparam_t::iterator end = fp_map_[i].end (); 43649 | 43650 | while (itr != end) 43651 | { 43652 | delete itr->second; 43653 | ++itr; 43654 | } 43655 | 43656 | fp_map_[i].clear(); 43657 | } 43658 | 43659 | clear_loop_runtime_check (); 43660 | clear_vector_access_runtime_check(); 43661 | clear_compilation_timeout_check (); 43662 | } 43663 | 43664 | inline bool add(const function& f, const bool override = false) 43665 | { 43666 | return add(f.name_, f.expression_, f.v_,override); 43667 | } 43668 | 43669 | inline std::string error() const 43670 | { 43671 | if (!error_list_.empty()) 43672 | { 43673 | return error_list_[0].diagnostic; 43674 | } 43675 | else 43676 | return std::string("No Error"); 43677 | } 43678 | 43679 | inline std::size_t error_count() const 43680 | { 43681 | return error_list_.size(); 43682 | } 43683 | 43684 | inline parser_error::type get_error(const std::size_t& index) const 43685 | { 43686 | if (index < error_list_.size()) 43687 | { 43688 | return error_list_[index]; 43689 | } 43690 | 43691 | throw std::invalid_argument("compositor::get_error() - Invalid error index specified"); 43692 | } 43693 | 43694 | private: 43695 | 43696 | template <typename Allocator, 43697 | template <typename, typename> class Sequence> 43698 | bool compile_expression(const std::string& name, 43699 | const std::string& expression, 43700 | const Sequence<std::string,Allocator>& input_var_list, 43701 | bool return_present = false) 43702 | { 43703 | expression_t compiled_expression; 43704 | symbol_table_t local_symbol_table; 43705 | 43706 | local_symbol_table.load_from(symbol_table_); 43707 | local_symbol_table.add_constants(); 43708 | 43709 | if (load_variables_) 43710 | { 43711 | local_symbol_table.load_variables_from(symbol_table_); 43712 | } 43713 | 43714 | if (load_vectors_) 43715 | { 43716 | local_symbol_table.load_vectors_from(symbol_table_); 43717 | } 43718 | 43719 | error_list_.clear(); 43720 | 43721 | if (!valid(name,input_var_list.size())) 43722 | { 43723 | parser_error::type error = 43724 | parser_error::make_error( 43725 | parser_error::e_parser, 43726 | lexer::token(), 43727 | "ERR283 - Function '" + name + "' is an invalid overload", 43728 | exprtk_error_location); 43729 | 43730 | error_list_.push_back(error); 43731 | return false; 43732 | } 43733 | 43734 | if (!forward(name, 43735 | input_var_list.size(), 43736 | local_symbol_table, 43737 | return_present)) 43738 | return false; 43739 | 43740 | compiled_expression.register_symbol_table(local_symbol_table); 43741 | 43742 | for (std::size_t i = 0; i < auxiliary_symtab_list_.size(); ++i) 43743 | { 43744 | compiled_expression.register_symbol_table((*auxiliary_symtab_list_[i])); 43745 | } 43746 | 43747 | std::string mod_expression; 43748 | 43749 | for (std::size_t i = 0; i < input_var_list.size(); ++i) 43750 | { 43751 | mod_expression += " var " + input_var_list[i] + "{};\n" 43752 | } 43753 | 43754 | if ( 43755 | ('{' == details::front(expression)) && 43756 | ('}' == details::back (expression)) 43757 | ) 43758 | mod_expression += "~" + expression + "" 43759 | else 43760 | mod_expression += "~{" + expression + "};" 43761 | 43762 | if (!parser_.compile(mod_expression,compiled_expression)) 43763 | { 43764 | exprtk_debug(("Compositor Error: %s\n", parser_.error().c_str())); 43765 | exprtk_debug(("Compositor modified expression: \n%s\n", mod_expression.c_str())); 43766 | 43767 | remove(name,input_var_list.size()); 43768 | 43769 | for (std::size_t err_index = 0; err_index < parser_.error_count(); ++err_index) 43770 | { 43771 | error_list_.push_back(parser_.get_error(err_index)); 43772 | } 43773 | 43774 | return false; 43775 | } 43776 | 43777 | if (!return_present && parser_.dec().return_present()) 43778 | { 43779 | remove(name,input_var_list.size()); 43780 | return compile_expression(name, expression, input_var_list, true); 43781 | } 43782 | 43783 | // Make sure every return point has a scalar as its first parameter 43784 | if (parser_.dec().return_present()) 43785 | { 43786 | typedef std::vector<std::string> str_list_t; 43787 | 43788 | str_list_t ret_param_list = parser_.dec().return_param_type_list(); 43789 | 43790 | for (std::size_t i = 0; i < ret_param_list.size(); ++i) 43791 | { 43792 | const std::string& params = ret_param_list[i]; 43793 | 43794 | if (params.empty() || ('T' != params[0])) 43795 | { 43796 | exprtk_debug(("Compositor Error: Return statement in function '%s' is invalid\n", 43797 | name.c_str())); 43798 | 43799 | remove(name,input_var_list.size()); 43800 | 43801 | return false; 43802 | } 43803 | } 43804 | } 43805 | 43806 | expr_map_[name] = compiled_expression; 43807 | 43808 | exprtk::ifunction<T>& ifunc = (*(fp_map_[input_var_list.size()])[name]); 43809 | 43810 | if (symbol_table_.add_function(name,ifunc)) 43811 | return true; 43812 | else 43813 | { 43814 | exprtk_debug(("Compositor Error: Failed to add function '%s' to symbol table\n", 43815 | name.c_str())); 43816 | return false; 43817 | } 43818 | } 43819 | 43820 | inline bool symbol_used(const std::string& symbol) const 43821 | { 43822 | return ( 43823 | symbol_table_.is_variable (symbol) || 43824 | symbol_table_.is_stringvar (symbol) || 43825 | symbol_table_.is_function (symbol) || 43826 | symbol_table_.is_vector (symbol) || 43827 | symbol_table_.is_vararg_function(symbol) 43828 | ); 43829 | } 43830 | 43831 | inline bool valid(const std::string& name, 43832 | const std::size_t& arg_count) const 43833 | { 43834 | if (arg_count > 6) 43835 | return false; 43836 | else if (symbol_used(name)) 43837 | return false; 43838 | else if (fp_map_[arg_count].end() != fp_map_[arg_count].find(name)) 43839 | return false; 43840 | else 43841 | return true; 43842 | } 43843 | 43844 | inline bool forward(const std::string& name, 43845 | const std::size_t& arg_count, 43846 | symbol_table_t& sym_table, 43847 | const bool ret_present = false) 43848 | { 43849 | switch (arg_count) 43850 | { 43851 | #define case_stmt(N) \ 43852 | case N : (fp_map_[arg_count])[name] = \ 43853 | (!ret_present) ? static_cast<base_func*> \ 43854 | (new func_##N##param) : \ 43855 | static_cast<base_func*> \ 43856 | (new func_##N##param_retval) ; \ 43857 | break; \ 43858 | 43859 | case_stmt(0) case_stmt(1) case_stmt(2) 43860 | case_stmt(3) case_stmt(4) case_stmt(5) 43861 | case_stmt(6) 43862 | #undef case_stmt 43863 | } 43864 | 43865 | exprtk::ifunction<T>& ifunc = (*(fp_map_[arg_count])[name]); 43866 | 43867 | return sym_table.add_function(name,ifunc); 43868 | } 43869 | 43870 | inline void remove(const std::string& name, const std::size_t& arg_count) 43871 | { 43872 | if (arg_count > 6) 43873 | return; 43874 | 43875 | const typename std::map<std::string,expression_t>::iterator em_itr = expr_map_.find(name); 43876 | 43877 | if (expr_map_.end() != em_itr) 43878 | { 43879 | expr_map_.erase(em_itr); 43880 | } 43881 | 43882 | const typename funcparam_t::iterator fp_itr = fp_map_[arg_count].find(name); 43883 | 43884 | if (fp_map_[arg_count].end() != fp_itr) 43885 | { 43886 | delete fp_itr->second; 43887 | fp_map_[arg_count].erase(fp_itr); 43888 | } 43889 | 43890 | symbol_table_.remove_function(name); 43891 | } 43892 | 43893 | private: 43894 | 43895 | symbol_table_t symbol_table_; 43896 | parser_t parser_; 43897 | std::map<std::string,expression_t> expr_map_; 43898 | std::vector<funcparam_t> fp_map_; 43899 | std::vector<symbol_table_t*> auxiliary_symtab_list_; 43900 | std::deque<parser_error::type> error_list_; 43901 | bool load_variables_; 43902 | bool load_vectors_; 43903 | }; // class function_compositor 43904 | 43905 | } // namespace exprtk 43906 | 43907 | #if defined(_MSC_VER) || defined(_WIN32) || defined(__WIN32__) || defined(WIN32) 43908 | # ifndef NOMINMAX 43909 | # define NOMINMAX 43910 | # endif 43911 | # ifndef WIN32_LEAN_AND_MEAN 43912 | # define WIN32_LEAN_AND_MEAN 43913 | # endif 43914 | # include 43915 | # include 43916 | #else 43917 | # include 43918 | # include 43919 | # include 43920 | #endif 43921 | 43922 | namespace exprtk 43923 | { 43924 | class timer 43925 | { 43926 | public: 43927 | 43928 | #if defined(_MSC_VER) || defined(_WIN32) || defined(__WIN32__) || defined(WIN32) 43929 | timer() 43930 | : in_use_(false) 43931 | , start_time_{ {0, 0} } 43932 | , stop_time_ { {0, 0} } 43933 | { 43934 | QueryPerformanceFrequency(&clock_frequency_); 43935 | } 43936 | 43937 | inline void start() 43938 | { 43939 | in_use_ = true; 43940 | QueryPerformanceCounter(&start_time_); 43941 | } 43942 | 43943 | inline void stop() 43944 | { 43945 | QueryPerformanceCounter(&stop_time_); 43946 | in_use_ = false; 43947 | } 43948 | 43949 | inline double time() const 43950 | { 43951 | return (1.0 * (stop_time_.QuadPart - start_time_.QuadPart)) / (1.0 * clock_frequency_.QuadPart); 43952 | } 43953 | 43954 | #else 43955 | 43956 | timer() 43957 | : in_use_(false) 43958 | { 43959 | start_time_.tv_sec = 0; 43960 | start_time_.tv_usec = 0; 43961 | 43962 | stop_time_.tv_sec = 0; 43963 | stop_time_.tv_usec = 0; 43964 | } 43965 | 43966 | inline void start() 43967 | { 43968 | in_use_ = true; 43969 | gettimeofday(&start_time_,0); 43970 | } 43971 | 43972 | inline void stop() 43973 | { 43974 | gettimeofday(&stop_time_, 0); 43975 | in_use_ = false; 43976 | } 43977 | 43978 | inline unsigned long long int usec_time() const 43979 | { 43980 | if (!in_use_) 43981 | { 43982 | if (stop_time_.tv_sec >= start_time_.tv_sec) 43983 | { 43984 | return 1000000LLU * static_cast<details::_uint64_t>(stop_time_.tv_sec - start_time_.tv_sec ) + 43985 | static_cast<details::_uint64_t>(stop_time_.tv_usec - start_time_.tv_usec) ; 43986 | } 43987 | else 43988 | return std::numeric_limits<details::_uint64_t>::max(); 43989 | } 43990 | else 43991 | return std::numeric_limits<details::_uint64_t>::max(); 43992 | } 43993 | 43994 | inline double time() const 43995 | { 43996 | return usec_time() * 0.000001; 43997 | } 43998 | 43999 | #endif 44000 | 44001 | inline bool in_use() const 44002 | { 44003 | return in_use_; 44004 | } 44005 | 44006 | private: 44007 | 44008 | bool in_use_; 44009 | 44010 | #if defined(_MSC_VER) || defined(_WIN32) || defined(__WIN32__) || defined(WIN32) 44011 | LARGE_INTEGER start_time_; 44012 | LARGE_INTEGER stop_time_; 44013 | LARGE_INTEGER clock_frequency_; 44014 | #else 44015 | struct timeval start_time_; 44016 | struct timeval stop_time_; 44017 | #endif 44018 | }; 44019 | 44020 | template <typename T> 44021 | struct type_defs 44022 | { 44023 | typedef symbol_table<T> symbol_table_t; 44024 | typedef expression<T> expression_t; 44025 | typedef parser<T> parser_t; 44026 | typedef parser_error::type error_t; 44027 | typedef function_compositor<T> compositor_t; 44028 | typedef typename compositor_t::function function_t; 44029 | }; 44030 | 44031 | } // namespace exprtk 44032 | 44033 | #ifndef exprtk_disable_rtl_io 44034 | namespace exprtk 44035 | { 44036 | namespace rtl { namespace io { namespace details 44037 | { 44038 | template <typename T> 44039 | inline void print_type(const std::string& fmt, 44040 | const T v, 44041 | exprtk::details::numeric::details::real_type_tag) 44042 | { 44043 | #if defined(__clang__) 44044 | #pragma clang diagnostic push 44045 | #pragma clang diagnostic ignored "-Wformat-nonliteral" 44046 | #elif defined(__GNUC__) || defined(__GNUG__) 44047 | #pragma GCC diagnostic push 44048 | #pragma GCC diagnostic ignored "-Wformat-nonliteral" 44049 | #elif defined(_MSC_VER) 44050 | #endif 44051 | 44052 | printf(fmt.c_str(), v); 44053 | 44054 | #if defined(__clang__) 44055 | #pragma clang diagnostic pop 44056 | #elif defined(__GNUC__) || defined(__GNUG__) 44057 | #pragma GCC diagnostic pop 44058 | #elif defined(_MSC_VER) 44059 | #endif 44060 | } 44061 | 44062 | template <typename T> 44063 | struct print_impl 44064 | { 44065 | typedef typename igeneric_function<T>::generic_type generic_type; 44066 | typedef typename igeneric_function<T>::parameter_list_t parameter_list_t; 44067 | typedef typename generic_type::scalar_view scalar_t; 44068 | typedef typename generic_type::vector_view vector_t; 44069 | typedef typename generic_type::string_view string_t; 44070 | typedef typename exprtk::details::numeric::details::number_type<T>::type num_type; 44071 | 44072 | static void process(const std::string& scalar_format, parameter_list_t parameters) 44073 | { 44074 | for (std::size_t i = 0; i < parameters.size(); ++i) 44075 | { 44076 | generic_type& gt = parameters[i]; 44077 | 44078 | switch (gt.type) 44079 | { 44080 | case generic_type::e_scalar : print(scalar_format,scalar_t(gt)); 44081 | break; 44082 | 44083 | case generic_type::e_vector : print(scalar_format,vector_t(gt)); 44084 | break; 44085 | 44086 | case generic_type::e_string : print(string_t(gt)); 44087 | break; 44088 | 44089 | default : continue; 44090 | } 44091 | } 44092 | } 44093 | 44094 | static inline void print(const std::string& scalar_format, const scalar_t& s) 44095 | { 44096 | print_type(scalar_format,s(),num_type()); 44097 | } 44098 | 44099 | static inline void print(const std::string& scalar_format, const vector_t& v) 44100 | { 44101 | for (std::size_t i = 0; i < v.size(); ++i) 44102 | { 44103 | print_type(scalar_format,v[i],num_type()); 44104 | 44105 | if ((i + 1) < v.size()) 44106 | printf(" "); 44107 | } 44108 | } 44109 | 44110 | static inline void print(const string_t& s) 44111 | { 44112 | printf("%s",to_str(s).c_str()); 44113 | } 44114 | }; 44115 | 44116 | } // namespace exprtk::rtl::io::details 44117 | 44118 | template <typename T> 44119 | struct print exprtk_final : public exprtk::igeneric_function<T> 44120 | { 44121 | typedef typename igeneric_function<T>::parameter_list_t parameter_list_t; 44122 | 44123 | using exprtk::igeneric_function<T>::operator(); 44124 | 44125 | explicit print(const std::string& scalar_format = "%10.5f") 44126 | : scalar_format_(scalar_format) 44127 | { 44128 | exprtk::enable_zero_parameters(*this); 44129 | } 44130 | 44131 | inline T operator() (parameter_list_t parameters) exprtk_override 44132 | { 44133 | details::print_impl<T>::process(scalar_format_,parameters); 44134 | return T(0); 44135 | } 44136 | 44137 | std::string scalar_format_; 44138 | }; 44139 | 44140 | template <typename T> 44141 | struct println exprtk_final : public exprtk::igeneric_function<T> 44142 | { 44143 | typedef typename igeneric_function<T>::parameter_list_t parameter_list_t; 44144 | 44145 | using exprtk::igeneric_function<T>::operator(); 44146 | 44147 | explicit println(const std::string& scalar_format = "%10.5f") 44148 | : scalar_format_(scalar_format) 44149 | { 44150 | exprtk::enable_zero_parameters(*this); 44151 | } 44152 | 44153 | inline T operator() (parameter_list_t parameters) exprtk_override 44154 | { 44155 | details::print_impl<T>::process(scalar_format_,parameters); 44156 | printf("\n"); 44157 | return T(0); 44158 | } 44159 | 44160 | std::string scalar_format_; 44161 | }; 44162 | 44163 | template <typename T> 44164 | struct package 44165 | { 44166 | print <T> p; 44167 | println<T> pl; 44168 | 44169 | bool register_package(exprtk::symbol_table<T>& symtab) 44170 | { 44171 | #define exprtk_register_function(FunctionName, FunctionType) \ 44172 | if (!symtab.add_function(FunctionName,FunctionType)) \ 44173 | { \ 44174 | exprtk_debug(( \ 44175 | "exprtk::rtl::io::register_package - Failed to add function: %s\n", \ 44176 | FunctionName)); \ 44177 | return false; \ 44178 | } \ 44179 | 44180 | exprtk_register_function("print" , p ) 44181 | exprtk_register_function("println", pl) 44182 | #undef exprtk_register_function 44183 | 44184 | return true; 44185 | } 44186 | }; 44187 | 44188 | } // namespace exprtk::rtl::io 44189 | } // namespace exprtk::rtl 44190 | } // namespace exprtk 44191 | #endif 44192 | 44193 | #ifndef exprtk_disable_rtl_io_file 44194 | #include 44195 | namespace exprtk 44196 | { 44197 | namespace rtl { namespace io { namespace file { namespace details 44198 | { 44199 | using ::exprtk::details::char_ptr; 44200 | using ::exprtk::details::char_cptr; 44201 | 44202 | enum file_mode 44203 | { 44204 | e_error = 0, 44205 | e_read = 1, 44206 | e_write = 2, 44207 | e_rdwrt = 4 44208 | }; 44209 | 44210 | struct file_descriptor 44211 | { 44212 | file_descriptor(const std::string& fname, const std::string& access) 44213 | : stream_ptr(0) 44214 | , mode(get_file_mode(access)) 44215 | , file_name(fname) 44216 | {} 44217 | 44218 | void* stream_ptr; 44219 | file_mode mode; 44220 | std::string file_name; 44221 | 44222 | bool open() 44223 | { 44224 | if (e_read == mode) 44225 | { 44226 | std::ifstream* stream = new std::ifstream(file_name.c_str(),std::ios::binary); 44227 | 44228 | if (!(*stream)) 44229 | { 44230 | file_name.clear(); 44231 | delete stream; 44232 | 44233 | return false; 44234 | } 44235 | 44236 | stream_ptr = stream; 44237 | 44238 | return true; 44239 | } 44240 | else if (e_write == mode) 44241 | { 44242 | std::ofstream* stream = new std::ofstream(file_name.c_str(),std::ios::binary); 44243 | 44244 | if (!(*stream)) 44245 | { 44246 | file_name.clear(); 44247 | delete stream; 44248 | 44249 | return false; 44250 | } 44251 | 44252 | stream_ptr = stream; 44253 | 44254 | return true; 44255 | } 44256 | else if (e_rdwrt == mode) 44257 | { 44258 | std::fstream* stream = new std::fstream(file_name.c_str(),std::ios::binary); 44259 | 44260 | if (!(*stream)) 44261 | { 44262 | file_name.clear(); 44263 | delete stream; 44264 | 44265 | return false; 44266 | } 44267 | 44268 | stream_ptr = stream; 44269 | 44270 | return true; 44271 | } 44272 | 44273 | return false; 44274 | } 44275 | 44276 | template <typename Stream, typename Ptr> 44277 | void close(Ptr& p) 44278 | { 44279 | Stream* stream = reinterpret_cast<Stream*>(p); 44280 | stream->close(); 44281 | delete stream; 44282 | p = reinterpret_cast<Ptr>(0); 44283 | } 44284 | 44285 | bool close() 44286 | { 44287 | switch (mode) 44288 | { 44289 | case e_read : close<std::ifstream>(stream_ptr); 44290 | break; 44291 | 44292 | case e_write : close<std::ofstream>(stream_ptr); 44293 | break; 44294 | 44295 | case e_rdwrt : close<std::fstream> (stream_ptr); 44296 | break; 44297 | 44298 | default : return false; 44299 | } 44300 | 44301 | return true; 44302 | } 44303 | 44304 | template <typename View> 44305 | bool write(const View& view, const std::size_t amount, const std::size_t offset = 0) 44306 | { 44307 | switch (mode) 44308 | { 44309 | case e_write : reinterpret_cast<std::ofstream*>(stream_ptr)-> 44310 | write(reinterpret_cast<char_cptr>(view.begin() + offset), amount * sizeof(typename View::value_t)); 44311 | break; 44312 | 44313 | case e_rdwrt : reinterpret_cast<std::fstream*>(stream_ptr)-> 44314 | write(reinterpret_cast<char_cptr>(view.begin() + offset) , amount * sizeof(typename View::value_t)); 44315 | break; 44316 | 44317 | default : return false; 44318 | } 44319 | 44320 | return true; 44321 | } 44322 | 44323 | template <typename View> 44324 | bool read(View& view, const std::size_t amount, const std::size_t offset = 0) 44325 | { 44326 | switch (mode) 44327 | { 44328 | case e_read : reinterpret_cast<std::ifstream*>(stream_ptr)-> 44329 | read(reinterpret_cast<char_ptr>(view.begin() + offset), amount * sizeof(typename View::value_t)); 44330 | break; 44331 | 44332 | case e_rdwrt : reinterpret_cast<std::fstream*>(stream_ptr)-> 44333 | read(reinterpret_cast<char_ptr>(view.begin() + offset) , amount * sizeof(typename View::value_t)); 44334 | break; 44335 | 44336 | default : return false; 44337 | } 44338 | 44339 | return true; 44340 | } 44341 | 44342 | bool getline(std::string& s) 44343 | { 44344 | switch (mode) 44345 | { 44346 | case e_read : return (!!std::getline(*reinterpret_cast<std::ifstream*>(stream_ptr),s)); 44347 | case e_rdwrt : return (!!std::getline(*reinterpret_cast<std::fstream* >(stream_ptr),s)); 44348 | default : return false; 44349 | } 44350 | } 44351 | 44352 | bool eof() const 44353 | { 44354 | switch (mode) 44355 | { 44356 | case e_read : return reinterpret_cast<std::ifstream*>(stream_ptr)->eof(); 44357 | case e_write : return reinterpret_cast<std::ofstream*>(stream_ptr)->eof(); 44358 | case e_rdwrt : return reinterpret_cast<std::fstream* >(stream_ptr)->eof(); 44359 | default : return true; 44360 | } 44361 | } 44362 | 44363 | file_mode get_file_mode(const std::string& access) const 44364 | { 44365 | if (access.empty() || access.size() > 2) 44366 | return e_error; 44367 | 44368 | std::size_t w_cnt = 0; 44369 | std::size_t r_cnt = 0; 44370 | 44371 | for (std::size_t i = 0; i < access.size(); ++i) 44372 | { 44373 | switch (std::tolower(access[i])) 44374 | { 44375 | case 'r' : r_cnt++; break; 44376 | case 'w' : w_cnt++; break; 44377 | default : return e_error; 44378 | } 44379 | } 44380 | 44381 | if ((0 == r_cnt) && (0 == w_cnt)) 44382 | return e_error; 44383 | else if ((r_cnt > 1) || (w_cnt > 1)) 44384 | return e_error; 44385 | else if ((1 == r_cnt) && (1 == w_cnt)) 44386 | return e_rdwrt; 44387 | else if (1 == r_cnt) 44388 | return e_read; 44389 | else 44390 | return e_write; 44391 | } 44392 | }; 44393 | 44394 | template <typename T> 44395 | file_descriptor* make_handle(T v) 44396 | { 44397 | const std::size_t fd_size = sizeof(details::file_descriptor*); 44398 | details::file_descriptor* fd = reinterpret_cast<file_descriptor*>(0); 44399 | 44400 | std::memcpy(reinterpret_cast<char_ptr >(&fd), 44401 | reinterpret_cast<char_cptr>(&v ), 44402 | fd_size); 44403 | return fd; 44404 | } 44405 | 44406 | template <typename T> 44407 | void perform_check() 44408 | { 44409 | #ifdef _MSC_VER 44410 | #pragma warning(push) 44411 | #pragma warning(disable: 4127) 44412 | #endif 44413 | if (sizeof(T) < sizeof(void*)) 44414 | { 44415 | throw std::runtime_error("exprtk::rtl::io::file - Error - pointer size larger than holder."); 44416 | } 44417 | #ifdef _MSC_VER 44418 | #pragma warning(pop) 44419 | #endif 44420 | assert(sizeof(T) <= sizeof(void*)); 44421 | } 44422 | 44423 | } // namespace exprtk::rtl::io::file::details 44424 | 44425 | template <typename T> 44426 | class open exprtk_final : public exprtk::igeneric_function<T> 44427 | { 44428 | public: 44429 | 44430 | typedef typename exprtk::igeneric_function<T> igfun_t; 44431 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44432 | typedef typename igfun_t::generic_type generic_type; 44433 | typedef typename generic_type::string_view string_t; 44434 | 44435 | using igfun_t::operator(); 44436 | 44437 | open() 44438 | : exprtk::igeneric_function<T>("S|SS") 44439 | { details::perform_check<T>(); } 44440 | 44441 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44442 | { 44443 | const std::string file_name = to_str(string_t(parameters[0])); 44444 | 44445 | if (file_name.empty()) 44446 | { 44447 | return T(0); 44448 | } 44449 | 44450 | if ((1 == ps_index) && (0 == string_t(parameters[1]).size())) 44451 | { 44452 | return T(0); 44453 | } 44454 | 44455 | const std::string access = 44456 | (0 == ps_index) ? "r" : to_str(string_t(parameters[1])); 44457 | 44458 | details::file_descriptor* fd = new details::file_descriptor(file_name,access); 44459 | 44460 | if (fd->open()) 44461 | { 44462 | T t = T(0); 44463 | 44464 | const std::size_t fd_size = sizeof(details::file_descriptor*); 44465 | 44466 | std::memcpy(reinterpret_cast<char*>(&t ), 44467 | reinterpret_cast<char*>(&fd), 44468 | fd_size); 44469 | return t; 44470 | } 44471 | else 44472 | { 44473 | delete fd; 44474 | return T(0); 44475 | } 44476 | } 44477 | }; 44478 | 44479 | template <typename T> 44480 | struct close exprtk_final : public exprtk::ifunction<T> 44481 | { 44482 | using exprtk::ifunction<T>::operator(); 44483 | 44484 | close() 44485 | : exprtk::ifunction<T>(1) 44486 | { details::perform_check<T>(); } 44487 | 44488 | inline T operator() (const T& v) exprtk_override 44489 | { 44490 | details::file_descriptor* fd = details::make_handle(v); 44491 | 44492 | if (!fd->close()) 44493 | return T(0); 44494 | 44495 | delete fd; 44496 | 44497 | return T(1); 44498 | } 44499 | }; 44500 | 44501 | template <typename T> 44502 | class write exprtk_final : public exprtk::igeneric_function<T> 44503 | { 44504 | public: 44505 | 44506 | typedef typename exprtk::igeneric_function<T> igfun_t; 44507 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44508 | typedef typename igfun_t::generic_type generic_type; 44509 | typedef typename generic_type::string_view string_t; 44510 | typedef typename generic_type::scalar_view scalar_t; 44511 | typedef typename generic_type::vector_view vector_t; 44512 | 44513 | using igfun_t::operator(); 44514 | 44515 | write() 44516 | : igfun_t("TS|TST|TV|TVT") 44517 | { details::perform_check<T>(); } 44518 | 44519 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44520 | { 44521 | details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])()); 44522 | 44523 | switch (ps_index) 44524 | { 44525 | case 0 : { 44526 | const string_t buffer(parameters[1]); 44527 | const std::size_t amount = buffer.size(); 44528 | return T(fd->write(buffer, amount) ? 1 : 0); 44529 | } 44530 | 44531 | case 1 : { 44532 | const string_t buffer(parameters[1]); 44533 | const std::size_t amount = 44534 | std::min(buffer.size(), 44535 | static_cast<std::size_t>(scalar_t(parameters[2])())); 44536 | return T(fd->write(buffer, amount) ? 1 : 0); 44537 | } 44538 | 44539 | case 2 : { 44540 | const vector_t vec(parameters[1]); 44541 | const std::size_t amount = vec.size(); 44542 | return T(fd->write(vec, amount) ? 1 : 0); 44543 | } 44544 | 44545 | case 3 : { 44546 | const vector_t vec(parameters[1]); 44547 | const std::size_t amount = 44548 | std::min(vec.size(), 44549 | static_cast<std::size_t>(scalar_t(parameters[2])())); 44550 | return T(fd->write(vec, amount) ? 1 : 0); 44551 | } 44552 | } 44553 | 44554 | return T(0); 44555 | } 44556 | }; 44557 | 44558 | template <typename T> 44559 | class read exprtk_final : public exprtk::igeneric_function<T> 44560 | { 44561 | public: 44562 | 44563 | typedef typename exprtk::igeneric_function<T> igfun_t; 44564 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44565 | typedef typename igfun_t::generic_type generic_type; 44566 | typedef typename generic_type::string_view string_t; 44567 | typedef typename generic_type::scalar_view scalar_t; 44568 | typedef typename generic_type::vector_view vector_t; 44569 | 44570 | using igfun_t::operator(); 44571 | 44572 | read() 44573 | : igfun_t("TS|TST|TV|TVT") 44574 | { details::perform_check<T>(); } 44575 | 44576 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44577 | { 44578 | details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])()); 44579 | 44580 | switch (ps_index) 44581 | { 44582 | case 0 : { 44583 | string_t buffer(parameters[1]); 44584 | const std::size_t amount = buffer.size(); 44585 | return T(fd->read(buffer,amount) ? 1 : 0); 44586 | } 44587 | 44588 | case 1 : { 44589 | string_t buffer(parameters[1]); 44590 | const std::size_t amount = 44591 | std::min(buffer.size(), 44592 | static_cast<std::size_t>(scalar_t(parameters[2])())); 44593 | return T(fd->read(buffer,amount) ? 1 : 0); 44594 | } 44595 | 44596 | case 2 : { 44597 | vector_t vec(parameters[1]); 44598 | const std::size_t amount = vec.size(); 44599 | return T(fd->read(vec,amount) ? 1 : 0); 44600 | } 44601 | 44602 | case 3 : { 44603 | vector_t vec(parameters[1]); 44604 | const std::size_t amount = 44605 | std::min(vec.size(), 44606 | static_cast<std::size_t>(scalar_t(parameters[2])())); 44607 | return T(fd->read(vec,amount) ? 1 : 0); 44608 | } 44609 | } 44610 | 44611 | return T(0); 44612 | } 44613 | }; 44614 | 44615 | template <typename T> 44616 | class getline exprtk_final : public exprtk::igeneric_function<T> 44617 | { 44618 | public: 44619 | 44620 | typedef typename exprtk::igeneric_function<T> igfun_t; 44621 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44622 | typedef typename igfun_t::generic_type generic_type; 44623 | typedef typename generic_type::string_view string_t; 44624 | typedef typename generic_type::scalar_view scalar_t; 44625 | 44626 | using igfun_t::operator(); 44627 | 44628 | getline() 44629 | : igfun_t("T",igfun_t::e_rtrn_string) 44630 | { details::perform_check<T>(); } 44631 | 44632 | inline T operator() (std::string& result, parameter_list_t parameters) exprtk_override 44633 | { 44634 | details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])()); 44635 | return T(fd->getline(result) ? 1 : 0); 44636 | } 44637 | }; 44638 | 44639 | template <typename T> 44640 | struct eof exprtk_final : public exprtk::ifunction<T> 44641 | { 44642 | using exprtk::ifunction<T>::operator(); 44643 | 44644 | eof() 44645 | : exprtk::ifunction<T>(1) 44646 | { details::perform_check<T>(); } 44647 | 44648 | inline T operator() (const T& v) exprtk_override 44649 | { 44650 | details::file_descriptor* fd = details::make_handle(v); 44651 | return (fd->eof() ? T(1) : T(0)); 44652 | } 44653 | }; 44654 | 44655 | template <typename T> 44656 | struct package 44657 | { 44658 | open <T> o; 44659 | close <T> c; 44660 | write <T> w; 44661 | read <T> r; 44662 | getline<T> g; 44663 | eof <T> e; 44664 | 44665 | bool register_package(exprtk::symbol_table<T>& symtab) 44666 | { 44667 | #define exprtk_register_function(FunctionName, FunctionType) \ 44668 | if (!symtab.add_function(FunctionName,FunctionType)) \ 44669 | { \ 44670 | exprtk_debug(( \ 44671 | "exprtk::rtl::io::file::register_package - Failed to add function: %s\n", \ 44672 | FunctionName)); \ 44673 | return false; \ 44674 | } \ 44675 | 44676 | exprtk_register_function("open" , o) 44677 | exprtk_register_function("close" , c) 44678 | exprtk_register_function("write" , w) 44679 | exprtk_register_function("read" , r) 44680 | exprtk_register_function("getline" , g) 44681 | exprtk_register_function("eof" , e) 44682 | #undef exprtk_register_function 44683 | 44684 | return true; 44685 | } 44686 | }; 44687 | 44688 | } // namespace exprtk::rtl::io::file 44689 | } // namespace exprtk::rtl::io 44690 | } // namespace exprtk::rtl 44691 | } // namespace exprtk 44692 | #endif 44693 | 44694 | #ifndef exprtk_disable_rtl_vecops 44695 | namespace exprtk 44696 | { 44697 | namespace rtl { namespace vecops { 44698 | 44699 | namespace helper 44700 | { 44701 | template <typename Vector> 44702 | inline bool invalid_range(const Vector& v, const std::size_t r0, const std::size_t r1) 44703 | { 44704 | if (r0 > (v.size() - 1)) 44705 | return true; 44706 | else if (r1 > (v.size() - 1)) 44707 | return true; 44708 | else if (r1 < r0) 44709 | return true; 44710 | else 44711 | return false; 44712 | } 44713 | 44714 | template <typename T> 44715 | struct load_vector_range 44716 | { 44717 | typedef typename exprtk::igeneric_function<T> igfun_t; 44718 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44719 | typedef typename igfun_t::generic_type generic_type; 44720 | typedef typename generic_type::scalar_view scalar_t; 44721 | typedef typename generic_type::vector_view vector_t; 44722 | 44723 | static inline bool process(parameter_list_t& parameters, 44724 | std::size_t& r0, std::size_t& r1, 44725 | const std::size_t& r0_prmidx, 44726 | const std::size_t& r1_prmidx, 44727 | const std::size_t vec_idx = 0) 44728 | { 44729 | if (r0_prmidx >= parameters.size()) 44730 | return false; 44731 | 44732 | if (r1_prmidx >= parameters.size()) 44733 | return false; 44734 | 44735 | if (!scalar_t(parameters[r0_prmidx]).to_uint(r0)) 44736 | return false; 44737 | 44738 | if (!scalar_t(parameters[r1_prmidx]).to_uint(r1)) 44739 | return false; 44740 | 44741 | return !invalid_range(vector_t(parameters[vec_idx]), r0, r1); 44742 | } 44743 | }; 44744 | } 44745 | 44746 | namespace details 44747 | { 44748 | template <typename T> 44749 | inline void kahan_sum(T& sum, T& error, const T v) 44750 | { 44751 | const T x = v - error; 44752 | const T y = sum + x; 44753 | error = (y - sum) - x; 44754 | sum = y; 44755 | } 44756 | 44757 | } // namespace exprtk::rtl::details 44758 | 44759 | template <typename T> 44760 | class all_true exprtk_final : public exprtk::igeneric_function<T> 44761 | { 44762 | public: 44763 | 44764 | typedef typename exprtk::igeneric_function<T> igfun_t; 44765 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44766 | typedef typename igfun_t::generic_type generic_type; 44767 | typedef typename generic_type::scalar_view scalar_t; 44768 | typedef typename generic_type::vector_view vector_t; 44769 | 44770 | using igfun_t::operator(); 44771 | 44772 | all_true() 44773 | : exprtk::igeneric_function<T>("V|VTT|T*") 44774 | /* 44775 | Overloads: 44776 | 0. V - vector 44777 | 1. VTT - vector, r0, r1 44778 | 2. T* - T....T 44779 | */ 44780 | {} 44781 | 44782 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44783 | { 44784 | if (2 == ps_index) 44785 | { 44786 | for (std::size_t i = 0; i < parameters.size(); ++i) 44787 | { 44788 | if (scalar_t(parameters[i])() == T(0)) 44789 | { 44790 | return T(0); 44791 | } 44792 | } 44793 | } 44794 | else 44795 | { 44796 | const vector_t vec(parameters[0]); 44797 | 44798 | std::size_t r0 = 0; 44799 | std::size_t r1 = vec.size() - 1; 44800 | 44801 | if ( 44802 | (1 == ps_index) && 44803 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 44804 | ) 44805 | { 44806 | return std::numeric_limits<T>::quiet_NaN(); 44807 | } 44808 | 44809 | for (std::size_t i = r0; i <= r1; ++i) 44810 | { 44811 | if (vec[i] == T(0)) 44812 | { 44813 | return T(0); 44814 | } 44815 | } 44816 | } 44817 | 44818 | return T(1); 44819 | } 44820 | }; 44821 | 44822 | template <typename T> 44823 | class all_false exprtk_final : public exprtk::igeneric_function<T> 44824 | { 44825 | public: 44826 | 44827 | typedef typename exprtk::igeneric_function<T> igfun_t; 44828 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44829 | typedef typename igfun_t::generic_type generic_type; 44830 | typedef typename generic_type::scalar_view scalar_t; 44831 | typedef typename generic_type::vector_view vector_t; 44832 | 44833 | using igfun_t::operator(); 44834 | 44835 | all_false() 44836 | : exprtk::igeneric_function<T>("V|VTT|T*") 44837 | /* 44838 | Overloads: 44839 | 0. V - vector 44840 | 1. VTT - vector, r0, r1 44841 | 2. T* - T....T 44842 | */ 44843 | {} 44844 | 44845 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44846 | { 44847 | if (2 == ps_index) 44848 | { 44849 | for (std::size_t i = 0; i < parameters.size(); ++i) 44850 | { 44851 | if (scalar_t(parameters[i])() != T(0)) 44852 | { 44853 | return T(0); 44854 | } 44855 | } 44856 | } 44857 | else 44858 | { 44859 | const vector_t vec(parameters[0]); 44860 | 44861 | std::size_t r0 = 0; 44862 | std::size_t r1 = vec.size() - 1; 44863 | 44864 | if ( 44865 | (1 == ps_index) && 44866 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 44867 | ) 44868 | { 44869 | return std::numeric_limits<T>::quiet_NaN(); 44870 | } 44871 | 44872 | for (std::size_t i = r0; i <= r1; ++i) 44873 | { 44874 | if (vec[i] != T(0)) 44875 | { 44876 | return T(0); 44877 | } 44878 | } 44879 | } 44880 | 44881 | return T(1); 44882 | } 44883 | }; 44884 | 44885 | template <typename T> 44886 | class any_true exprtk_final : public exprtk::igeneric_function<T> 44887 | { 44888 | public: 44889 | 44890 | typedef typename exprtk::igeneric_function<T> igfun_t; 44891 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44892 | typedef typename igfun_t::generic_type generic_type; 44893 | typedef typename generic_type::scalar_view scalar_t; 44894 | typedef typename generic_type::vector_view vector_t; 44895 | 44896 | using igfun_t::operator(); 44897 | 44898 | any_true() 44899 | : exprtk::igeneric_function<T>("V|VTT|T*") 44900 | /* 44901 | Overloads: 44902 | 0. V - vector 44903 | 1. VTT - vector, r0, r1 44904 | 2. T* - T....T 44905 | */ 44906 | {} 44907 | 44908 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44909 | { 44910 | if (2 == ps_index) 44911 | { 44912 | for (std::size_t i = 0; i < parameters.size(); ++i) 44913 | { 44914 | if (scalar_t(parameters[i])() != T(0)) 44915 | { 44916 | return T(1); 44917 | } 44918 | } 44919 | } 44920 | else 44921 | { 44922 | const vector_t vec(parameters[0]); 44923 | 44924 | std::size_t r0 = 0; 44925 | std::size_t r1 = vec.size() - 1; 44926 | 44927 | if ( 44928 | (1 == ps_index) && 44929 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 44930 | ) 44931 | { 44932 | return std::numeric_limits<T>::quiet_NaN(); 44933 | } 44934 | 44935 | for (std::size_t i = r0; i <= r1; ++i) 44936 | { 44937 | if (vec[i] != T(0)) 44938 | { 44939 | return T(1); 44940 | } 44941 | } 44942 | } 44943 | 44944 | return T(0); 44945 | } 44946 | }; 44947 | 44948 | template <typename T> 44949 | class any_false exprtk_final : public exprtk::igeneric_function<T> 44950 | { 44951 | public: 44952 | 44953 | typedef typename exprtk::igeneric_function<T> igfun_t; 44954 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44955 | typedef typename igfun_t::generic_type generic_type; 44956 | typedef typename generic_type::scalar_view scalar_t; 44957 | typedef typename generic_type::vector_view vector_t; 44958 | 44959 | using igfun_t::operator(); 44960 | 44961 | any_false() 44962 | : exprtk::igeneric_function<T>("V|VTT|T*") 44963 | /* 44964 | Overloads: 44965 | 0. V - vector 44966 | 1. VTT - vector, r0, r1 44967 | 2. T* - T....T 44968 | */ 44969 | {} 44970 | 44971 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44972 | { 44973 | if (2 == ps_index) 44974 | { 44975 | for (std::size_t i = 0; i < parameters.size(); ++i) 44976 | { 44977 | if (scalar_t(parameters[i])() == T(0)) 44978 | { 44979 | return T(1); 44980 | } 44981 | } 44982 | } 44983 | else 44984 | { 44985 | const vector_t vec(parameters[0]); 44986 | 44987 | std::size_t r0 = 0; 44988 | std::size_t r1 = vec.size() - 1; 44989 | 44990 | if ( 44991 | (1 == ps_index) && 44992 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 44993 | ) 44994 | { 44995 | return std::numeric_limits<T>::quiet_NaN(); 44996 | } 44997 | 44998 | for (std::size_t i = r0; i <= r1; ++i) 44999 | { 45000 | if (vec[i] == T(0)) 45001 | { 45002 | return T(1); 45003 | } 45004 | } 45005 | } 45006 | 45007 | return T(0); 45008 | } 45009 | }; 45010 | 45011 | template <typename T> 45012 | class count exprtk_final : public exprtk::igeneric_function<T> 45013 | { 45014 | public: 45015 | 45016 | typedef typename exprtk::igeneric_function<T> igfun_t; 45017 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45018 | typedef typename igfun_t::generic_type generic_type; 45019 | typedef typename generic_type::scalar_view scalar_t; 45020 | typedef typename generic_type::vector_view vector_t; 45021 | 45022 | using igfun_t::operator(); 45023 | 45024 | count() 45025 | : exprtk::igeneric_function<T>("V|VTT|T*") 45026 | /* 45027 | Overloads: 45028 | 0. V - vector 45029 | 1. VTT - vector, r0, r1 45030 | 2. T* - T....T 45031 | */ 45032 | {} 45033 | 45034 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45035 | { 45036 | std::size_t cnt = 0; 45037 | 45038 | if (2 == ps_index) 45039 | { 45040 | for (std::size_t i = 0; i < parameters.size(); ++i) 45041 | { 45042 | if (scalar_t(parameters[i])() != T(0)) ++cnt; 45043 | } 45044 | } 45045 | else 45046 | { 45047 | const vector_t vec(parameters[0]); 45048 | 45049 | std::size_t r0 = 0; 45050 | std::size_t r1 = vec.size() - 1; 45051 | 45052 | if ( 45053 | (1 == ps_index) && 45054 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 45055 | ) 45056 | { 45057 | return std::numeric_limits<T>::quiet_NaN(); 45058 | } 45059 | 45060 | for (std::size_t i = r0; i <= r1; ++i) 45061 | { 45062 | if (vec[i] != T(0)) ++cnt; 45063 | } 45064 | } 45065 | 45066 | return T(cnt); 45067 | } 45068 | }; 45069 | 45070 | template <typename T> 45071 | class copy exprtk_final : public exprtk::igeneric_function<T> 45072 | { 45073 | public: 45074 | 45075 | typedef typename exprtk::igeneric_function<T> igfun_t; 45076 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45077 | typedef typename igfun_t::generic_type generic_type; 45078 | typedef typename generic_type::scalar_view scalar_t; 45079 | typedef typename generic_type::vector_view vector_t; 45080 | 45081 | using igfun_t::operator(); 45082 | 45083 | copy() 45084 | : exprtk::igeneric_function<T>("VV|VTTVTT") 45085 | /* 45086 | Overloads: 45087 | 0. VV - x(vector), y(vector) 45088 | 1. VTTVTT - x(vector), xr0, xr1, y(vector), yr0, yr1, 45089 | */ 45090 | {} 45091 | 45092 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45093 | { 45094 | const vector_t x(parameters[0]); 45095 | vector_t y(parameters[(0 == ps_index) ? 1 : 3]); 45096 | 45097 | std::size_t xr0 = 0; 45098 | std::size_t xr1 = x.size() - 1; 45099 | 45100 | std::size_t yr0 = 0; 45101 | std::size_t yr1 = y.size() - 1; 45102 | 45103 | if (1 == ps_index) 45104 | { 45105 | if ( 45106 | !helper::load_vector_range<T>::process(parameters, xr0, xr1, 1, 2, 0) || 45107 | !helper::load_vector_range<T>::process(parameters, yr0, yr1, 4, 5, 3) 45108 | ) 45109 | return T(0); 45110 | } 45111 | 45112 | const std::size_t n = std::min(xr1 - xr0 + 1, yr1 - yr0 + 1); 45113 | 45114 | std::copy( 45115 | x.begin() + xr0, 45116 | x.begin() + xr0 + n, 45117 | y.begin() + yr0); 45118 | 45119 | return T(n); 45120 | } 45121 | }; 45122 | 45123 | template <typename T> 45124 | class rol exprtk_final : public exprtk::igeneric_function<T> 45125 | { 45126 | public: 45127 | 45128 | typedef typename exprtk::igeneric_function<T> igfun_t; 45129 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45130 | typedef typename igfun_t::generic_type generic_type; 45131 | typedef typename generic_type::scalar_view scalar_t; 45132 | typedef typename generic_type::vector_view vector_t; 45133 | 45134 | using igfun_t::operator(); 45135 | 45136 | rol() 45137 | : exprtk::igeneric_function<T>("VT|VTTT") 45138 | /* 45139 | Overloads: 45140 | 0. VT - vector, N 45141 | 1. VTTT - vector, N, r0, r1 45142 | */ 45143 | {} 45144 | 45145 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45146 | { 45147 | vector_t vec(parameters[0]); 45148 | 45149 | std::size_t n = 0; 45150 | std::size_t r0 = 0; 45151 | std::size_t r1 = vec.size() - 1; 45152 | 45153 | if (!scalar_t(parameters[1]).to_uint(n)) 45154 | return T(0); 45155 | 45156 | if ( 45157 | (1 == ps_index) && 45158 | !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0) 45159 | ) 45160 | return T(0); 45161 | 45162 | const std::size_t dist = r1 - r0 + 1; 45163 | const std::size_t shift = n % dist; 45164 | 45165 | std::rotate( 45166 | vec.begin() + r0, 45167 | vec.begin() + r0 + shift, 45168 | vec.begin() + r1 + 1); 45169 | 45170 | return T(1); 45171 | } 45172 | }; 45173 | 45174 | template <typename T> 45175 | class ror exprtk_final : public exprtk::igeneric_function<T> 45176 | { 45177 | public: 45178 | 45179 | typedef typename exprtk::igeneric_function<T> igfun_t; 45180 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45181 | typedef typename igfun_t::generic_type generic_type; 45182 | typedef typename generic_type::scalar_view scalar_t; 45183 | typedef typename generic_type::vector_view vector_t; 45184 | 45185 | using igfun_t::operator(); 45186 | 45187 | ror() 45188 | : exprtk::igeneric_function<T>("VT|VTTT") 45189 | /* 45190 | Overloads: 45191 | 0. VT - vector, N 45192 | 1. VTTT - vector, N, r0, r1 45193 | */ 45194 | {} 45195 | 45196 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45197 | { 45198 | vector_t vec(parameters[0]); 45199 | 45200 | std::size_t n = 0; 45201 | std::size_t r0 = 0; 45202 | std::size_t r1 = vec.size() - 1; 45203 | 45204 | if (!scalar_t(parameters[1]).to_uint(n)) 45205 | return T(0); 45206 | 45207 | if ( 45208 | (1 == ps_index) && 45209 | !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0) 45210 | ) 45211 | return T(0); 45212 | 45213 | const std::size_t dist = r1 - r0 + 1; 45214 | const std::size_t shift = (dist - (n % dist)) % dist; 45215 | 45216 | std::rotate( 45217 | vec.begin() + r0, 45218 | vec.begin() + r0 + shift, 45219 | vec.begin() + r1 + 1); 45220 | 45221 | return T(1); 45222 | } 45223 | }; 45224 | 45225 | template <typename T> 45226 | class reverse exprtk_final : public exprtk::igeneric_function<T> 45227 | { 45228 | public: 45229 | 45230 | typedef typename exprtk::igeneric_function<T> igfun_t; 45231 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45232 | typedef typename igfun_t::generic_type generic_type; 45233 | typedef typename generic_type::scalar_view scalar_t; 45234 | typedef typename generic_type::vector_view vector_t; 45235 | 45236 | using igfun_t::operator(); 45237 | 45238 | reverse() 45239 | : exprtk::igeneric_function<T>("V|VTT") 45240 | /* 45241 | Overloads: 45242 | 0. V - vector 45243 | 1. VTT - vector, r0, r1 45244 | */ 45245 | {} 45246 | 45247 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45248 | { 45249 | vector_t vec(parameters[0]); 45250 | 45251 | std::size_t r0 = 0; 45252 | std::size_t r1 = vec.size() - 1; 45253 | 45254 | if ( 45255 | (1 == ps_index) && 45256 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 45257 | ) 45258 | return T(0); 45259 | 45260 | std::reverse(vec.begin() + r0, vec.begin() + r1 + 1); 45261 | 45262 | return T(1); 45263 | } 45264 | }; 45265 | 45266 | template <typename T> 45267 | class shift_left exprtk_final : public exprtk::igeneric_function<T> 45268 | { 45269 | public: 45270 | 45271 | typedef typename exprtk::igeneric_function<T> igfun_t; 45272 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45273 | typedef typename igfun_t::generic_type generic_type; 45274 | typedef typename generic_type::scalar_view scalar_t; 45275 | typedef typename generic_type::vector_view vector_t; 45276 | 45277 | using igfun_t::operator(); 45278 | 45279 | shift_left() 45280 | : exprtk::igeneric_function<T>("VT|VTTT") 45281 | /* 45282 | Overloads: 45283 | 0. VT - vector, N 45284 | 1. VTTT - vector, N, r0, r1 45285 | */ 45286 | {} 45287 | 45288 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45289 | { 45290 | vector_t vec(parameters[0]); 45291 | 45292 | std::size_t n = 0; 45293 | std::size_t r0 = 0; 45294 | std::size_t r1 = vec.size() - 1; 45295 | 45296 | if (!scalar_t(parameters[1]).to_uint(n)) 45297 | return T(0); 45298 | 45299 | if ( 45300 | (1 == ps_index) && 45301 | !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0) 45302 | ) 45303 | return T(0); 45304 | 45305 | const std::size_t dist = r1 - r0 + 1; 45306 | 45307 | if (n > dist) 45308 | return T(0); 45309 | 45310 | std::rotate( 45311 | vec.begin() + r0, 45312 | vec.begin() + r0 + n, 45313 | vec.begin() + r1 + 1); 45314 | 45315 | for (std::size_t i = r1 - n + 1ULL; i <= r1; ++i) 45316 | { 45317 | vec[i] = T(0); 45318 | } 45319 | 45320 | return T(1); 45321 | } 45322 | }; 45323 | 45324 | template <typename T> 45325 | class shift_right exprtk_final : public exprtk::igeneric_function<T> 45326 | { 45327 | public: 45328 | 45329 | typedef typename exprtk::igeneric_function<T> igfun_t; 45330 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45331 | typedef typename igfun_t::generic_type generic_type; 45332 | typedef typename generic_type::scalar_view scalar_t; 45333 | typedef typename generic_type::vector_view vector_t; 45334 | 45335 | using igfun_t::operator(); 45336 | 45337 | shift_right() 45338 | : exprtk::igeneric_function<T>("VT|VTTT") 45339 | /* 45340 | Overloads: 45341 | 0. VT - vector, N 45342 | 1. VTTT - vector, N, r0, r1 45343 | */ 45344 | {} 45345 | 45346 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45347 | { 45348 | vector_t vec(parameters[0]); 45349 | 45350 | std::size_t n = 0; 45351 | std::size_t r0 = 0; 45352 | std::size_t r1 = vec.size() - 1; 45353 | 45354 | if (!scalar_t(parameters[1]).to_uint(n)) 45355 | return T(0); 45356 | 45357 | if ( 45358 | (1 == ps_index) && 45359 | !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0) 45360 | ) 45361 | return T(0); 45362 | 45363 | const std::size_t dist = r1 - r0 + 1; 45364 | 45365 | if (n > dist) 45366 | return T(0); 45367 | 45368 | const std::size_t shift = (dist - (n % dist)) % dist; 45369 | 45370 | std::rotate( 45371 | vec.begin() + r0, 45372 | vec.begin() + r0 + shift, 45373 | vec.begin() + r1 + 1); 45374 | 45375 | for (std::size_t i = r0; i < r0 + n; ++i) 45376 | { 45377 | vec[i] = T(0); 45378 | } 45379 | 45380 | return T(1); 45381 | } 45382 | }; 45383 | 45384 | template <typename T> 45385 | class sort exprtk_final : public exprtk::igeneric_function<T> 45386 | { 45387 | public: 45388 | 45389 | typedef typename exprtk::igeneric_function<T> igfun_t; 45390 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45391 | typedef typename igfun_t::generic_type generic_type; 45392 | typedef typename generic_type::string_view string_t; 45393 | typedef typename generic_type::vector_view vector_t; 45394 | 45395 | using igfun_t::operator(); 45396 | 45397 | sort() 45398 | : exprtk::igeneric_function<T>("V|VTT|VS|VSTT") 45399 | /* 45400 | Overloads: 45401 | 0. V - vector 45402 | 1. VTT - vector, r0, r1 45403 | 2. VS - vector, string 45404 | 3. VSTT - vector, string, r0, r1 45405 | */ 45406 | {} 45407 | 45408 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45409 | { 45410 | vector_t vec(parameters[0]); 45411 | 45412 | std::size_t r0 = 0; 45413 | std::size_t r1 = vec.size() - 1; 45414 | 45415 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)) 45416 | return T(0); 45417 | if ((3 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)) 45418 | return T(0); 45419 | 45420 | bool ascending = true; 45421 | 45422 | if ((2 == ps_index) || (3 == ps_index)) 45423 | { 45424 | if (exprtk::details::imatch(to_str(string_t(parameters[1])),"ascending")) 45425 | ascending = true; 45426 | else if (exprtk::details::imatch(to_str(string_t(parameters[1])),"descending")) 45427 | ascending = false; 45428 | else 45429 | return T(0); 45430 | } 45431 | 45432 | if (ascending) 45433 | std::sort( 45434 | vec.begin() + r0, 45435 | vec.begin() + r1 + 1, 45436 | std::less<T>()); 45437 | else 45438 | std::sort( 45439 | vec.begin() + r0, 45440 | vec.begin() + r1 + 1, 45441 | std::greater<T>()); 45442 | 45443 | return T(1); 45444 | } 45445 | }; 45446 | 45447 | template <typename T> 45448 | class nthelement exprtk_final : public exprtk::igeneric_function<T> 45449 | { 45450 | public: 45451 | 45452 | typedef typename exprtk::igeneric_function<T> igfun_t; 45453 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45454 | typedef typename igfun_t::generic_type generic_type; 45455 | typedef typename generic_type::scalar_view scalar_t; 45456 | typedef typename generic_type::vector_view vector_t; 45457 | 45458 | using igfun_t::operator(); 45459 | 45460 | nthelement() 45461 | : exprtk::igeneric_function<T>("VT|VTTT") 45462 | /* 45463 | Overloads: 45464 | 0. VT - vector, nth-element 45465 | 1. VTTT - vector, nth-element, r0, r1 45466 | */ 45467 | {} 45468 | 45469 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45470 | { 45471 | vector_t vec(parameters[0]); 45472 | 45473 | std::size_t n = 0; 45474 | std::size_t r0 = 0; 45475 | std::size_t r1 = vec.size() - 1; 45476 | 45477 | if (!scalar_t(parameters[1]).to_uint(n)) 45478 | return T(0); 45479 | 45480 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)) 45481 | { 45482 | return std::numeric_limits<T>::quiet_NaN(); 45483 | } 45484 | 45485 | std::nth_element( 45486 | vec.begin() + r0, 45487 | vec.begin() + r0 + n , 45488 | vec.begin() + r1 + 1); 45489 | 45490 | return T(1); 45491 | } 45492 | }; 45493 | 45494 | template <typename T> 45495 | class assign exprtk_final : public exprtk::igeneric_function<T> 45496 | { 45497 | public: 45498 | 45499 | typedef typename exprtk::igeneric_function<T> igfun_t; 45500 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45501 | typedef typename igfun_t::generic_type generic_type; 45502 | typedef typename generic_type::scalar_view scalar_t; 45503 | typedef typename generic_type::vector_view vector_t; 45504 | 45505 | using igfun_t::operator(); 45506 | 45507 | assign() 45508 | : exprtk::igeneric_function<T>("VT|VTTT|VTTTT") 45509 | /* 45510 | Overloads: 45511 | 0. VT - vector, V 45512 | 1. VTTT - vector, V, r0, r1 45513 | 2. VTTTT - vector, V, r0, r1, SS 45514 | */ 45515 | {} 45516 | 45517 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45518 | { 45519 | vector_t vec(parameters[0]); 45520 | 45521 | const T assign_value = scalar_t(parameters[1]); 45522 | 45523 | const std::size_t step_size = (2 != ps_index) ? 1 : 45524 | static_cast<std::size_t>(scalar_t(parameters.back())()); 45525 | 45526 | std::size_t r0 = 0; 45527 | std::size_t r1 = vec.size() - 1; 45528 | 45529 | if ( 45530 | ((ps_index == 1) || (ps_index == 2)) && 45531 | !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0) 45532 | ) 45533 | { 45534 | return T(0); 45535 | } 45536 | 45537 | for (std::size_t i = r0; i <= r1; i += step_size) 45538 | { 45539 | vec[i] = assign_value; 45540 | } 45541 | 45542 | return T(1); 45543 | } 45544 | }; 45545 | 45546 | template <typename T> 45547 | class iota exprtk_final : public exprtk::igeneric_function<T> 45548 | { 45549 | public: 45550 | 45551 | typedef typename exprtk::igeneric_function<T> igfun_t; 45552 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45553 | typedef typename igfun_t::generic_type generic_type; 45554 | typedef typename generic_type::scalar_view scalar_t; 45555 | typedef typename generic_type::vector_view vector_t; 45556 | 45557 | using igfun_t::operator(); 45558 | 45559 | iota() 45560 | : exprtk::igeneric_function<T>("VTT|VT|VTTTT|VTTT") 45561 | /* 45562 | Overloads: 45563 | 0. VTT - vector, SV, SS 45564 | 1. VT - vector, SV, SS (+1) 45565 | 2. VTTT - vector, r0, r1, SV, SS 45566 | 3. VTT - vector, r0, r1, SV, SS (+1) 45567 | 45568 | Where: 45569 | 1. SV - Start value 45570 | 2. SS - Step size 45571 | */ 45572 | {} 45573 | 45574 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45575 | { 45576 | vector_t vec(parameters[0]); 45577 | 45578 | const T start_value = (ps_index <= 1) ? 45579 | scalar_t(parameters[1]) : 45580 | scalar_t(parameters[3]) ; 45581 | 45582 | const T step_size = ((0 == ps_index) || (2 == ps_index)) ? 45583 | scalar_t(parameters.back())() : 45584 | T(1) ; 45585 | 45586 | std::size_t r0 = 0; 45587 | std::size_t r1 = vec.size() - 1; 45588 | 45589 | if ( 45590 | ((ps_index == 2) || (ps_index == 3)) && 45591 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 45592 | ) 45593 | { 45594 | return T(0); 45595 | } 45596 | 45597 | for (std::size_t i = r0; i <= r1; ++i) 45598 | { 45599 | vec[i] = start_value + ((i - r0) * step_size); 45600 | } 45601 | 45602 | return T(1); 45603 | } 45604 | }; 45605 | 45606 | template <typename T> 45607 | class sumk exprtk_final : public exprtk::igeneric_function<T> 45608 | { 45609 | public: 45610 | 45611 | typedef typename exprtk::igeneric_function<T> igfun_t; 45612 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45613 | typedef typename igfun_t::generic_type generic_type; 45614 | typedef typename generic_type::scalar_view scalar_t; 45615 | typedef typename generic_type::vector_view vector_t; 45616 | 45617 | using igfun_t::operator(); 45618 | 45619 | sumk() 45620 | : exprtk::igeneric_function<T>("V|VTT|VTTT") 45621 | /* 45622 | Overloads: 45623 | 0. V - vector 45624 | 1. VTT - vector, r0, r1 45625 | 2. VTTT - vector, r0, r1, stride 45626 | */ 45627 | {} 45628 | 45629 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45630 | { 45631 | const vector_t vec(parameters[0]); 45632 | 45633 | const std::size_t stride = (2 != ps_index) ? 1 : 45634 | static_cast<std::size_t>(scalar_t(parameters[3])()); 45635 | 45636 | std::size_t r0 = 0; 45637 | std::size_t r1 = vec.size() - 1; 45638 | 45639 | if ( 45640 | ((1 == ps_index) || (2 == ps_index)) && 45641 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 45642 | ) 45643 | { 45644 | return std::numeric_limits<T>::quiet_NaN(); 45645 | } 45646 | 45647 | T result = T(0); 45648 | T error = T(0); 45649 | 45650 | for (std::size_t i = r0; i <= r1; i += stride) 45651 | { 45652 | details::kahan_sum(result, error, vec[i]); 45653 | } 45654 | 45655 | return result; 45656 | } 45657 | }; 45658 | 45659 | template <typename T> 45660 | class axpy exprtk_final : public exprtk::igeneric_function<T> 45661 | { 45662 | public: 45663 | 45664 | typedef typename exprtk::igeneric_function<T> igfun_t; 45665 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45666 | typedef typename igfun_t::generic_type generic_type; 45667 | typedef typename generic_type::scalar_view scalar_t; 45668 | typedef typename generic_type::vector_view vector_t; 45669 | 45670 | using igfun_t::operator(); 45671 | 45672 | axpy() 45673 | : exprtk::igeneric_function<T>("TVV|TVVTT") 45674 | /* 45675 | y <- ax + y 45676 | Overloads: 45677 | 0. TVV - a, x(vector), y(vector) 45678 | 1. TVVTT - a, x(vector), y(vector), r0, r1 45679 | */ 45680 | {} 45681 | 45682 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45683 | { 45684 | const vector_t x(parameters[1]); 45685 | vector_t y(parameters[2]); 45686 | 45687 | std::size_t r0 = 0; 45688 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 45689 | 45690 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 3, 4, 1)) 45691 | return std::numeric_limits<T>::quiet_NaN(); 45692 | else if (helper::invalid_range(y, r0, r1)) 45693 | return std::numeric_limits<T>::quiet_NaN(); 45694 | 45695 | const T a = scalar_t(parameters[0])(); 45696 | 45697 | for (std::size_t i = r0; i <= r1; ++i) 45698 | { 45699 | y[i] = (a * x[i]) + y[i]; 45700 | } 45701 | 45702 | return T(1); 45703 | } 45704 | }; 45705 | 45706 | template <typename T> 45707 | class axpby exprtk_final : public exprtk::igeneric_function<T> 45708 | { 45709 | public: 45710 | 45711 | typedef typename exprtk::igeneric_function<T> igfun_t; 45712 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45713 | typedef typename igfun_t::generic_type generic_type; 45714 | typedef typename generic_type::scalar_view scalar_t; 45715 | typedef typename generic_type::vector_view vector_t; 45716 | 45717 | using igfun_t::operator(); 45718 | 45719 | axpby() 45720 | : exprtk::igeneric_function<T>("TVTV|TVTVTT") 45721 | /* 45722 | y <- ax + by 45723 | Overloads: 45724 | 0. TVTV - a, x(vector), b, y(vector) 45725 | 1. TVTVTT - a, x(vector), b, y(vector), r0, r1 45726 | */ 45727 | {} 45728 | 45729 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45730 | { 45731 | const vector_t x(parameters[1]); 45732 | vector_t y(parameters[3]); 45733 | 45734 | std::size_t r0 = 0; 45735 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 45736 | 45737 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1)) 45738 | return std::numeric_limits<T>::quiet_NaN(); 45739 | else if (helper::invalid_range(y, r0, r1)) 45740 | return std::numeric_limits<T>::quiet_NaN(); 45741 | 45742 | const T a = scalar_t(parameters[0])(); 45743 | const T b = scalar_t(parameters[2])(); 45744 | 45745 | for (std::size_t i = r0; i <= r1; ++i) 45746 | { 45747 | y[i] = (a * x[i]) + (b * y[i]); 45748 | } 45749 | 45750 | return T(1); 45751 | } 45752 | }; 45753 | 45754 | template <typename T> 45755 | class axpyz exprtk_final : public exprtk::igeneric_function<T> 45756 | { 45757 | public: 45758 | 45759 | typedef typename exprtk::igeneric_function<T> igfun_t; 45760 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45761 | typedef typename igfun_t::generic_type generic_type; 45762 | typedef typename generic_type::scalar_view scalar_t; 45763 | typedef typename generic_type::vector_view vector_t; 45764 | 45765 | using igfun_t::operator(); 45766 | 45767 | axpyz() 45768 | : exprtk::igeneric_function<T>("TVVV|TVVVTT") 45769 | /* 45770 | z <- ax + y 45771 | Overloads: 45772 | 0. TVVV - a, x(vector), y(vector), z(vector) 45773 | 1. TVVVTT - a, x(vector), y(vector), z(vector), r0, r1 45774 | */ 45775 | {} 45776 | 45777 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45778 | { 45779 | const vector_t x(parameters[1]); 45780 | const vector_t y(parameters[2]); 45781 | vector_t z(parameters[3]); 45782 | 45783 | std::size_t r0 = 0; 45784 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 45785 | 45786 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1)) 45787 | return std::numeric_limits<T>::quiet_NaN(); 45788 | else if (helper::invalid_range(y, r0, r1)) 45789 | return std::numeric_limits<T>::quiet_NaN(); 45790 | else if (helper::invalid_range(z, r0, r1)) 45791 | return std::numeric_limits<T>::quiet_NaN(); 45792 | 45793 | const T a = scalar_t(parameters[0])(); 45794 | 45795 | for (std::size_t i = r0; i <= r1; ++i) 45796 | { 45797 | z[i] = (a * x[i]) + y[i]; 45798 | } 45799 | 45800 | return T(1); 45801 | } 45802 | }; 45803 | 45804 | template <typename T> 45805 | class axpbyz exprtk_final : public exprtk::igeneric_function<T> 45806 | { 45807 | public: 45808 | 45809 | typedef typename exprtk::igeneric_function<T> igfun_t; 45810 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45811 | typedef typename igfun_t::generic_type generic_type; 45812 | typedef typename generic_type::scalar_view scalar_t; 45813 | typedef typename generic_type::vector_view vector_t; 45814 | 45815 | using igfun_t::operator(); 45816 | 45817 | axpbyz() 45818 | : exprtk::igeneric_function<T>("TVTVV|TVTVVTT") 45819 | /* 45820 | z <- ax + by 45821 | Overloads: 45822 | 0. TVTVV - a, x(vector), b, y(vector), z(vector) 45823 | 1. TVTVVTT - a, x(vector), b, y(vector), z(vector), r0, r1 45824 | */ 45825 | {} 45826 | 45827 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45828 | { 45829 | const vector_t x(parameters[1]); 45830 | const vector_t y(parameters[3]); 45831 | vector_t z(parameters[4]); 45832 | 45833 | std::size_t r0 = 0; 45834 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 45835 | 45836 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 5, 6, 1)) 45837 | return std::numeric_limits<T>::quiet_NaN(); 45838 | else if (helper::invalid_range(y, r0, r1)) 45839 | return std::numeric_limits<T>::quiet_NaN(); 45840 | else if (helper::invalid_range(z, r0, r1)) 45841 | return std::numeric_limits<T>::quiet_NaN(); 45842 | 45843 | const T a = scalar_t(parameters[0])(); 45844 | const T b = scalar_t(parameters[2])(); 45845 | 45846 | for (std::size_t i = r0; i <= r1; ++i) 45847 | { 45848 | z[i] = (a * x[i]) + (b * y[i]); 45849 | } 45850 | 45851 | return T(1); 45852 | } 45853 | }; 45854 | 45855 | template <typename T> 45856 | class axpbsy exprtk_final : public exprtk::igeneric_function<T> 45857 | { 45858 | public: 45859 | 45860 | typedef typename exprtk::igeneric_function<T> igfun_t; 45861 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45862 | typedef typename igfun_t::generic_type generic_type; 45863 | typedef typename generic_type::scalar_view scalar_t; 45864 | typedef typename generic_type::vector_view vector_t; 45865 | 45866 | using igfun_t::operator(); 45867 | 45868 | axpbsy() 45869 | : exprtk::igeneric_function<T>("TVTTV|TVTTVTT") 45870 | /* 45871 | y <- ax + by 45872 | Overloads: 45873 | 0. TVTVV - a, x(vector), b, shift, y(vector), z(vector) 45874 | 1. TVTVVTT - a, x(vector), b, shift, y(vector), z(vector), r0, r1 45875 | */ 45876 | {} 45877 | 45878 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45879 | { 45880 | const vector_t x(parameters[1]); 45881 | vector_t y(parameters[4]); 45882 | 45883 | std::size_t r0 = 0; 45884 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 45885 | 45886 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 5, 6, 1)) 45887 | return std::numeric_limits<T>::quiet_NaN(); 45888 | else if (helper::invalid_range(y, r0, r1)) 45889 | return std::numeric_limits<T>::quiet_NaN(); 45890 | 45891 | const T a = scalar_t(parameters[0])(); 45892 | const T b = scalar_t(parameters[2])(); 45893 | 45894 | const std::size_t s = static_cast<std::size_t>(scalar_t(parameters[3])()); 45895 | 45896 | for (std::size_t i = r0; i <= r1; ++i) 45897 | { 45898 | y[i] = (a * x[i]) + (b * y[i + s]); 45899 | } 45900 | 45901 | return T(1); 45902 | } 45903 | }; 45904 | 45905 | template <typename T> 45906 | class axpbsyz exprtk_final : public exprtk::igeneric_function<T> 45907 | { 45908 | public: 45909 | 45910 | typedef typename exprtk::igeneric_function<T> igfun_t; 45911 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45912 | typedef typename igfun_t::generic_type generic_type; 45913 | typedef typename generic_type::scalar_view scalar_t; 45914 | typedef typename generic_type::vector_view vector_t; 45915 | 45916 | using igfun_t::operator(); 45917 | 45918 | axpbsyz() 45919 | : exprtk::igeneric_function<T>("TVTTVV|TVTTVVTT") 45920 | /* 45921 | z <- ax + by 45922 | Overloads: 45923 | 0. TVTVV - a, x(vector), b, shift, y(vector), z(vector) 45924 | 1. TVTVVTT - a, x(vector), b, shift, y(vector), z(vector), r0, r1 45925 | */ 45926 | {} 45927 | 45928 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45929 | { 45930 | const vector_t x(parameters[1]); 45931 | const vector_t y(parameters[4]); 45932 | vector_t z(parameters[5]); 45933 | 45934 | std::size_t r0 = 0; 45935 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 45936 | 45937 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 6, 7, 1)) 45938 | return std::numeric_limits<T>::quiet_NaN(); 45939 | else if (helper::invalid_range(y, r0, r1)) 45940 | return std::numeric_limits<T>::quiet_NaN(); 45941 | else if (helper::invalid_range(z, r0, r1)) 45942 | return std::numeric_limits<T>::quiet_NaN(); 45943 | 45944 | const T a = scalar_t(parameters[0])(); 45945 | const T b = scalar_t(parameters[2])(); 45946 | 45947 | const std::size_t s = static_cast<std::size_t>(scalar_t(parameters[3])()); 45948 | 45949 | for (std::size_t i = r0; i <= r1; ++i) 45950 | { 45951 | z[i] = (a * x[i]) + (b * y[i + s]); 45952 | } 45953 | 45954 | return T(1); 45955 | } 45956 | }; 45957 | 45958 | template <typename T> 45959 | class axpbz exprtk_final : public exprtk::igeneric_function<T> 45960 | { 45961 | public: 45962 | 45963 | typedef typename exprtk::igeneric_function<T> igfun_t; 45964 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45965 | typedef typename igfun_t::generic_type generic_type; 45966 | typedef typename generic_type::scalar_view scalar_t; 45967 | typedef typename generic_type::vector_view vector_t; 45968 | 45969 | using igfun_t::operator(); 45970 | 45971 | axpbz() 45972 | : exprtk::igeneric_function<T>("TVTV|TVTVTT") 45973 | /* 45974 | z <- ax + b 45975 | Overloads: 45976 | 0. TVTV - a, x(vector), b, z(vector) 45977 | 1. TVTVTT - a, x(vector), b, z(vector), r0, r1 45978 | */ 45979 | {} 45980 | 45981 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45982 | { 45983 | const vector_t x(parameters[1]); 45984 | vector_t z(parameters[3]); 45985 | 45986 | std::size_t r0 = 0; 45987 | std::size_t r1 = x.size() - 1; 45988 | 45989 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1)) 45990 | return std::numeric_limits<T>::quiet_NaN(); 45991 | else if (helper::invalid_range(z, r0, r1)) 45992 | return std::numeric_limits<T>::quiet_NaN(); 45993 | 45994 | const T a = scalar_t(parameters[0])(); 45995 | const T b = scalar_t(parameters[2])(); 45996 | 45997 | for (std::size_t i = r0; i <= r1; ++i) 45998 | { 45999 | z[i] = (a * x[i]) + b; 46000 | } 46001 | 46002 | return T(1); 46003 | } 46004 | }; 46005 | 46006 | template <typename T> 46007 | class diff exprtk_final : public exprtk::igeneric_function<T> 46008 | { 46009 | public: 46010 | 46011 | typedef typename exprtk::igeneric_function<T> igfun_t; 46012 | typedef typename igfun_t::parameter_list_t parameter_list_t; 46013 | typedef typename igfun_t::generic_type generic_type; 46014 | typedef typename generic_type::scalar_view scalar_t; 46015 | typedef typename generic_type::vector_view vector_t; 46016 | 46017 | using igfun_t::operator(); 46018 | 46019 | diff() 46020 | : exprtk::igeneric_function<T>("VV|VVT") 46021 | /* 46022 | x_(i - stride) - x_i 46023 | Overloads: 46024 | 0. VV - x(vector), y(vector) 46025 | 1. VVT - x(vector), y(vector), stride 46026 | */ 46027 | {} 46028 | 46029 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 46030 | { 46031 | const vector_t x(parameters[0]); 46032 | vector_t y(parameters[1]); 46033 | 46034 | const std::size_t r0 = 0; 46035 | const std::size_t r1 = std::min(x.size(),y.size()) - 1; 46036 | 46037 | const std::size_t stride = (1 != ps_index) ? 1 : 46038 | std::min(r1,static_cast<std::size_t>(scalar_t(parameters[2])())); 46039 | 46040 | for (std::size_t i = 0; i < stride; ++i) 46041 | { 46042 | y[i] = std::numeric_limits<T>::quiet_NaN(); 46043 | } 46044 | 46045 | for (std::size_t i = (r0 + stride); i <= r1; ++i) 46046 | { 46047 | y[i] = x[i] - x[i - stride]; 46048 | } 46049 | 46050 | return T(1); 46051 | } 46052 | }; 46053 | 46054 | template <typename T> 46055 | class dot exprtk_final : public exprtk::igeneric_function<T> 46056 | { 46057 | public: 46058 | 46059 | typedef typename exprtk::igeneric_function<T> igfun_t; 46060 | typedef typename igfun_t::parameter_list_t parameter_list_t; 46061 | typedef typename igfun_t::generic_type generic_type; 46062 | typedef typename generic_type::scalar_view scalar_t; 46063 | typedef typename generic_type::vector_view vector_t; 46064 | 46065 | using igfun_t::operator(); 46066 | 46067 | dot() 46068 | : exprtk::igeneric_function<T>("VV|VVTT") 46069 | /* 46070 | Overloads: 46071 | 0. VV - x(vector), y(vector) 46072 | 1. VVTT - x(vector), y(vector), r0, r1 46073 | */ 46074 | {} 46075 | 46076 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 46077 | { 46078 | const vector_t x(parameters[0]); 46079 | const vector_t y(parameters[1]); 46080 | 46081 | std::size_t r0 = 0; 46082 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 46083 | 46084 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)) 46085 | return std::numeric_limits<T>::quiet_NaN(); 46086 | else if (helper::invalid_range(y, r0, r1)) 46087 | return std::numeric_limits<T>::quiet_NaN(); 46088 | 46089 | T result = T(0); 46090 | 46091 | for (std::size_t i = r0; i <= r1; ++i) 46092 | { 46093 | result += (x[i] * y[i]); 46094 | } 46095 | 46096 | return result; 46097 | } 46098 | }; 46099 | 46100 | template <typename T> 46101 | class dotk exprtk_final : public exprtk::igeneric_function<T> 46102 | { 46103 | public: 46104 | 46105 | typedef typename exprtk::igeneric_function<T> igfun_t; 46106 | typedef typename igfun_t::parameter_list_t parameter_list_t; 46107 | typedef typename igfun_t::generic_type generic_type; 46108 | typedef typename generic_type::scalar_view scalar_t; 46109 | typedef typename generic_type::vector_view vector_t; 46110 | 46111 | using igfun_t::operator(); 46112 | 46113 | dotk() 46114 | : exprtk::igeneric_function<T>("VV|VVTT") 46115 | /* 46116 | Overloads: 46117 | 0. VV - x(vector), y(vector) 46118 | 1. VVTT - x(vector), y(vector), r0, r1 46119 | */ 46120 | {} 46121 | 46122 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 46123 | { 46124 | const vector_t x(parameters[0]); 46125 | const vector_t y(parameters[1]); 46126 | 46127 | std::size_t r0 = 0; 46128 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 46129 | 46130 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)) 46131 | return std::numeric_limits<T>::quiet_NaN(); 46132 | else if (helper::invalid_range(y, r0, r1)) 46133 | return std::numeric_limits<T>::quiet_NaN(); 46134 | 46135 | T result = T(0); 46136 | T error = T(0); 46137 | 46138 | for (std::size_t i = r0; i <= r1; ++i) 46139 | { 46140 | details::kahan_sum(result, error, (x[i] * y[i])); 46141 | } 46142 | 46143 | return result; 46144 | } 46145 | }; 46146 | 46147 | template <typename T> 46148 | class threshold_below exprtk_final : public exprtk::igeneric_function<T> 46149 | { 46150 | public: 46151 | 46152 | typedef typename exprtk::igeneric_function<T> igfun_t; 46153 | typedef typename igfun_t::parameter_list_t parameter_list_t; 46154 | typedef typename igfun_t::generic_type generic_type; 46155 | typedef typename generic_type::scalar_view scalar_t; 46156 | typedef typename generic_type::vector_view vector_t; 46157 | 46158 | using igfun_t::operator(); 46159 | 46160 | threshold_below() 46161 | : exprtk::igeneric_function<T>("VTT|VTTTT") 46162 | /* 46163 | Overloads: 46164 | 0. VTT - vector, TV, SV 46165 | 1. VTTTT - vector, r0, r1, TV, SV 46166 | 46167 | Where: 46168 | TV - Threshold value 46169 | SV - Snap-to value 46170 | */ 46171 | {} 46172 | 46173 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 46174 | { 46175 | vector_t vec(parameters[0]); 46176 | 46177 | const T threshold_value = (0 == ps_index) ? 46178 | scalar_t(parameters[1]) : 46179 | scalar_t(parameters[3]) ; 46180 | 46181 | const T snap_value = scalar_t(parameters.back()); 46182 | 46183 | std::size_t r0 = 0; 46184 | std::size_t r1 = vec.size() - 1; 46185 | 46186 | if ( 46187 | (1 == ps_index) && 46188 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 46189 | ) 46190 | { 46191 | return T(0); 46192 | } 46193 | 46194 | for (std::size_t i = r0; i <= r1; ++i) 46195 | { 46196 | if (vec[i] < threshold_value) 46197 | { 46198 | vec[i] = snap_value; 46199 | } 46200 | } 46201 | 46202 | return T(1); 46203 | } 46204 | }; 46205 | 46206 | template <typename T> 46207 | class threshold_above exprtk_final : public exprtk::igeneric_function<T> 46208 | { 46209 | public: 46210 | 46211 | typedef typename exprtk::igeneric_function<T> igfun_t; 46212 | typedef typename igfun_t::parameter_list_t parameter_list_t; 46213 | typedef typename igfun_t::generic_type generic_type; 46214 | typedef typename generic_type::scalar_view scalar_t; 46215 | typedef typename generic_type::vector_view vector_t; 46216 | 46217 | using igfun_t::operator(); 46218 | 46219 | threshold_above() 46220 | : exprtk::igeneric_function<T>("VTT|VTTTT") 46221 | /* 46222 | Overloads: 46223 | 0. VTT - vector, TV, SV 46224 | 1. VTTTT - vector, r0, r1, TV, SV 46225 | 46226 | Where: 46227 | TV - Threshold value 46228 | SV - Snap-to value 46229 | */ 46230 | {} 46231 | 46232 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 46233 | { 46234 | vector_t vec(parameters[0]); 46235 | 46236 | const T threshold_value = (0 == ps_index) ? 46237 | scalar_t(parameters[1]) : 46238 | scalar_t(parameters[3]) ; 46239 | 46240 | const T snap_value = scalar_t(parameters.back()); 46241 | 46242 | std::size_t r0 = 0; 46243 | std::size_t r1 = vec.size() - 1; 46244 | 46245 | if ( 46246 | (1 == ps_index) && 46247 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 46248 | ) 46249 | { 46250 | return T(0); 46251 | } 46252 | 46253 | for (std::size_t i = r0; i <= r1; ++i) 46254 | { 46255 | if (vec[i] > threshold_value) 46256 | { 46257 | vec[i] = snap_value; 46258 | } 46259 | } 46260 | 46261 | return T(1); 46262 | } 46263 | }; 46264 | 46265 | template <typename T> 46266 | class min_elemwise exprtk_final : public exprtk::igeneric_function<T> 46267 | { 46268 | public: 46269 | 46270 | typedef typename exprtk::igeneric_function<T> igfun_t; 46271 | typedef typename igfun_t::parameter_list_t parameter_list_t; 46272 | typedef typename igfun_t::generic_type generic_type; 46273 | typedef typename generic_type::scalar_view scalar_t; 46274 | typedef typename generic_type::vector_view vector_t; 46275 | 46276 | using igfun_t::operator(); 46277 | 46278 | min_elemwise() 46279 | : exprtk::igeneric_function<T>("VT|VVT|VTTT|VVTTT") 46280 | /* 46281 | Overloads: 46282 | 0. VT - vector, T 46283 | 0. VVT - vector, vector, T 46284 | 0. VTTT - vector, r0, r1, T 46285 | 0. VVTTT - vector, vector, r0, r1, T 46286 | */ 46287 | {} 46288 | 46289 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 46290 | { 46291 | std::size_t out_vec_index = 0; 46292 | std::size_t in_vec_index = (ps_index & 1) ? 1 : 0; 46293 | std::size_t scalar_index = parameters.size() - 1; 46294 | 46295 | vector_t out_vec(parameters[out_vec_index]); 46296 | vector_t in_vec (parameters[in_vec_index ]); 46297 | 46298 | const T s = scalar_t(parameters[scalar_index ])(); 46299 | 46300 | std::size_t r0 = 0; 46301 | std::size_t r1 = in_vec.size() - 1; 46302 | 46303 | if ((2 == ps_index) || (3 == ps_index)) 46304 | { 46305 | std::size_t rng_idx0 = 0; 46306 | std::size_t rng_idx1 = 0; 46307 | 46308 | switch (ps_index) 46309 | { 46310 | case 2 : { rng_idx0 = 1; rng_idx1 = 2; }; break; 46311 | case 3 : { rng_idx0 = 2; rng_idx1 = 3; }; break; 46312 | } 46313 | 46314 | if (!helper::load_vector_range<T>::process(parameters, r0, r1, rng_idx0, rng_idx1, 0)) 46315 | { 46316 | return T(0); 46317 | } 46318 | } 46319 | 46320 | for (std::size_t i = r0; i <= r1; ++i) 46321 | { 46322 | out_vec[i] = exprtk::details::numeric::min(in_vec[i], s); 46323 | } 46324 | 46325 | return T(1); 46326 | } 46327 | }; 46328 | 46329 | template <typename T> 46330 | class max_elemwise exprtk_final : public exprtk::igeneric_function<T> 46331 | { 46332 | public: 46333 | 46334 | typedef typename exprtk::igeneric_function<T> igfun_t; 46335 | typedef typename igfun_t::parameter_list_t parameter_list_t; 46336 | typedef typename igfun_t::generic_type generic_type; 46337 | typedef typename generic_type::scalar_view scalar_t; 46338 | typedef typename generic_type::vector_view vector_t; 46339 | 46340 | using igfun_t::operator(); 46341 | 46342 | max_elemwise() 46343 | : exprtk::igeneric_function<T>("VT|VVT|VTTT|VVTTT") 46344 | /* 46345 | Overloads: 46346 | 0. VT - vector, T 46347 | 1. VVT - vector, vector, T 46348 | 2. VTTT - vector, r0, r1, T 46349 | 3. VVTTT - vector, vector, r0, r1, T 46350 | */ 46351 | {} 46352 | 46353 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 46354 | { 46355 | std::size_t out_vec_index = 0; 46356 | std::size_t in_vec_index = (ps_index & 1) ? 1 : 0; 46357 | std::size_t scalar_index = parameters.size() - 1; 46358 | 46359 | vector_t out_vec(parameters[out_vec_index]); 46360 | vector_t in_vec (parameters[in_vec_index ]); 46361 | 46362 | const T s = scalar_t(parameters[scalar_index ])(); 46363 | 46364 | std::size_t r0 = 0; 46365 | std::size_t r1 = in_vec.size() - 1; 46366 | 46367 | if ((2 == ps_index) || (3 == ps_index)) 46368 | { 46369 | std::size_t rng_idx0 = 0; 46370 | std::size_t rng_idx1 = 0; 46371 | 46372 | switch (ps_index) 46373 | { 46374 | case 2 : { rng_idx0 = 1; rng_idx1 = 2; }; break; 46375 | case 3 : { rng_idx0 = 2; rng_idx1 = 3; }; break; 46376 | } 46377 | 46378 | if (!helper::load_vector_range<T>::process(parameters, r0, r1, rng_idx0, rng_idx1, 0)) 46379 | { 46380 | return T(0); 46381 | } 46382 | } 46383 | 46384 | for (std::size_t i = r0; i <= r1; ++i) 46385 | { 46386 | out_vec[i] = exprtk::details::numeric::max(in_vec[i], s); 46387 | } 46388 | 46389 | return T(1); 46390 | } 46391 | }; 46392 | 46393 | template <typename T> 46394 | struct package 46395 | { 46396 | all_true <T> at; 46397 | all_false <T> af; 46398 | any_true <T> nt; 46399 | any_false <T> nf; 46400 | count <T> c; 46401 | copy <T> cp; 46402 | rol <T> rl; 46403 | ror <T> rr; 46404 | reverse <T> rev; 46405 | shift_left <T> sl; 46406 | shift_right <T> sr; 46407 | sort <T> st; 46408 | nthelement <T> ne; 46409 | assign <T> an; 46410 | iota <T> ia; 46411 | sumk <T> sk; 46412 | axpy <T> b1_axpy; 46413 | axpby <T> b1_axpby; 46414 | axpyz <T> b1_axpyz; 46415 | axpbyz <T> b1_axpbyz; 46416 | axpbsy <T> b1_axpbsy; 46417 | axpbsyz <T> b1_axpbsyz; 46418 | axpbz <T> b1_axpbz; 46419 | diff <T> df; 46420 | dot <T> dt; 46421 | dotk <T> dtk; 46422 | threshold_above<T> ta; 46423 | threshold_below<T> tb; 46424 | min_elemwise<T> miew; 46425 | max_elemwise<T> maew; 46426 | 46427 | bool register_package(exprtk::symbol_table<T>& symtab) 46428 | { 46429 | #define exprtk_register_function(FunctionName, FunctionType) \ 46430 | if (!symtab.add_function(FunctionName,FunctionType)) \ 46431 | { \ 46432 | exprtk_debug(( \ 46433 | "exprtk::rtl::vecops::register_package - Failed to add function: %s\n", \ 46434 | FunctionName)); \ 46435 | return false; \ 46436 | } \ 46437 | 46438 | exprtk_register_function("all_true" , at ) 46439 | exprtk_register_function("all_false" , af ) 46440 | exprtk_register_function("any_true" , nt ) 46441 | exprtk_register_function("any_false" , nf ) 46442 | exprtk_register_function("count" , c ) 46443 | exprtk_register_function("copy" , cp ) 46444 | exprtk_register_function("rotate_left" , rl ) 46445 | exprtk_register_function("rol" , rl ) 46446 | exprtk_register_function("rotate_right" , rr ) 46447 | exprtk_register_function("ror" , rr ) 46448 | exprtk_register_function("reverse" , rev ) 46449 | exprtk_register_function("shftl" , sl ) 46450 | exprtk_register_function("shftr" , sr ) 46451 | exprtk_register_function("sort" , st ) 46452 | exprtk_register_function("nth_element" , ne ) 46453 | exprtk_register_function("assign" , an ) 46454 | exprtk_register_function("iota" , ia ) 46455 | exprtk_register_function("sumk" , sk ) 46456 | exprtk_register_function("axpy" , b1_axpy ) 46457 | exprtk_register_function("axpby" , b1_axpby ) 46458 | exprtk_register_function("axpyz" , b1_axpyz ) 46459 | exprtk_register_function("axpbyz" , b1_axpbyz ) 46460 | exprtk_register_function("axpbsy" , b1_axpbsy ) 46461 | exprtk_register_function("axpbsyz" , b1_axpbsyz) 46462 | exprtk_register_function("axpbz" , b1_axpbz ) 46463 | exprtk_register_function("diff" , df ) 46464 | exprtk_register_function("dot" , dt ) 46465 | exprtk_register_function("dotk" , dtk ) 46466 | exprtk_register_function("threshold_above" , ta ) 46467 | exprtk_register_function("threshold_below" , tb ) 46468 | exprtk_register_function("min_elemwise" , miew ) 46469 | exprtk_register_function("max_elemwise" , maew ) 46470 | 46471 | #undef exprtk_register_function 46472 | 46473 | return true; 46474 | } 46475 | }; 46476 | 46477 | } // namespace exprtk::rtl::vecops 46478 | } // namespace exprtk::rtl 46479 | } // namespace exprtk 46480 | #endif 46481 | 46482 | namespace exprtk 46483 | { 46484 | namespace information 46485 | { 46486 | using ::exprtk::details::char_cptr; 46487 | 46488 | static char_cptr library = "Mathematical Expression Toolkit" 46489 | static char_cptr version = "2.718281828459045235360287471352662497757" 46490 | "24709369995957496696762772407663035354759" 46491 | "45713821785251664274274663919320030599218" 46492 | "17413596629043572900334295260595630738132" 46493 | static char_cptr date = "20240101" 46494 | static char_cptr min_cpp = "199711L" 46495 | 46496 | static inline std::string data() 46497 | { 46498 | static const std::string info_str = std::string(library) + 46499 | std::string(" v") + std::string(version) + 46500 | std::string(" (") + date + std::string(")") + 46501 | std::string(" (") + min_cpp + std::string(")"); 46502 | return info_str; 46503 | } 46504 | 46505 | } // namespace information 46506 | 46507 | #ifdef exprtk_debug 46508 | #undef exprtk_debug 46509 | #endif 46510 | 46511 | #ifdef exprtk_error_location 46512 | #undef exprtk_error_location 46513 | #endif 46514 | 46515 | #ifdef exprtk_fallthrough 46516 | #undef exprtk_fallthrough 46517 | #endif 46518 | 46519 | #ifdef exprtk_override 46520 | #undef exprtk_override 46521 | #endif 46522 | 46523 | #ifdef exprtk_final 46524 | #undef exprtk_final 46525 | #endif 46526 | 46527 | #ifdef exprtk_delete 46528 | #undef exprtk_delete 46529 | #endif 46530 | 46531 | } // namespace exprtk 46532 | 46533 | #endif