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 | #include <algorithm> 00038 | #include <cassert> 00039 | #include <cctype> 00040 | #include <cmath> 00041 | #include <cstdio> 00042 | #include <cstdlib> 00043 | #include <cstring> 00044 | #include <deque> 00045 | #include <functional> 00046 | #include <iterator> 00047 | #include <limits> 00048 | #include <list> 00049 | #include <map> 00050 | #include <set> 00051 | #include <stack> 00052 | #include <stdexcept> 00053 | #include <string> 00054 | #include <utility> 00055 | #include <vector> 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 = hex_to_bin(static_cast<uchar_t>(*(itr + 2))) << 4 | 00345 | hex_to_bin(static_cast<uchar_t>(*(itr + 3))) ; 00346 | 00347 | return true; 00348 | } 00349 | 00350 | inline bool cleanup_escapes(std::string& s) 00351 | { 00352 | typedef std::string::iterator str_itr_t; 00353 | 00354 | str_itr_t itr1 = s.begin(); 00355 | str_itr_t itr2 = s.begin(); 00356 | str_itr_t end = s.end (); 00357 | 00358 | std::size_t removal_count = 0; 00359 | 00360 | while (end != itr1) 00361 | { 00362 | if ('\\' == (*itr1)) 00363 | { 00364 | if (end == ++itr1) 00365 | { 00366 | return false; 00367 | } 00368 | else if (parse_hex(itr1, end, *itr2)) 00369 | { 00370 | itr1 += 4; 00371 | itr2 += 1; 00372 | removal_count += 4; 00373 | } 00374 | else if ('a' == (*itr1)) { (*itr2++) = '\a'; ++itr1; ++removal_count; } 00375 | else if ('b' == (*itr1)) { (*itr2++) = '\b'; ++itr1; ++removal_count; } 00376 | else if ('f' == (*itr1)) { (*itr2++) = '\f'; ++itr1; ++removal_count; } 00377 | else if ('n' == (*itr1)) { (*itr2++) = '\n'; ++itr1; ++removal_count; } 00378 | else if ('r' == (*itr1)) { (*itr2++) = '\r'; ++itr1; ++removal_count; } 00379 | else if ('t' == (*itr1)) { (*itr2++) = '\t'; ++itr1; ++removal_count; } 00380 | else if ('v' == (*itr1)) { (*itr2++) = '\v'; ++itr1; ++removal_count; } 00381 | else if ('0' == (*itr1)) { (*itr2++) = '\0'; ++itr1; ++removal_count; } 00382 | else 00383 | { 00384 | (*itr2++) = (*itr1++); 00385 | ++removal_count; 00386 | } 00387 | 00388 | continue; 00389 | } 00390 | else 00391 | (*itr2++) = (*itr1++); 00392 | } 00393 | 00394 | if ((removal_count > s.size()) || (0 == removal_count)) 00395 | return false; 00396 | 00397 | s.resize(s.size() - removal_count); 00398 | 00399 | return true; 00400 | } 00401 | 00402 | class build_string 00403 | { 00404 | public: 00405 | 00406 | explicit build_string(const std::size_t& initial_size = 64) 00407 | { 00408 | data_.reserve(initial_size); 00409 | } 00410 | 00411 | inline build_string& operator << (const std::string& s) 00412 | { 00413 | data_ += s; 00414 | return (*this); 00415 | } 00416 | 00417 | inline build_string& operator << (char_cptr s) 00418 | { 00419 | data_ += std::string(s); 00420 | return (*this); 00421 | } 00422 | 00423 | inline operator std::string () const 00424 | { 00425 | return data_; 00426 | } 00427 | 00428 | inline std::string as_string() const 00429 | { 00430 | return data_; 00431 | } 00432 | 00433 | private: 00434 | 00435 | std::string data_; 00436 | }; 00437 | 00438 | static const std::string reserved_words[] = 00439 | { 00440 | "assert", "break", "case", "continue", "const", "default", 00441 | "false", "for", "if", "else", "ilike", "in", "like", "and", 00442 | "nand", "nor", "not", "null", "or", "repeat", "return", 00443 | "shl", "shr", "swap", "switch", "true", "until", "var", 00444 | "while", "xnor", "xor", "&", "|" 00445 | }; 00446 | 00447 | static const std::size_t reserved_words_size = sizeof(reserved_words) / sizeof(std::string); 00448 | 00449 | static const std::string reserved_symbols[] = 00450 | { 00451 | "abs", "acos", "acosh", "and", "asin", "asinh", "assert", 00452 | "atan", "atanh", "atan2", "avg", "break", "case", "ceil", 00453 | "clamp", "continue", "const", "cos", "cosh", "cot", "csc", 00454 | "default", "deg2grad", "deg2rad", "equal", "erf", "erfc", 00455 | "exp", "expm1", "false", "floor", "for", "frac", "grad2deg", 00456 | "hypot", "iclamp", "if", "else", "ilike", "in", "inrange", 00457 | "like", "log", "log10", "log2", "logn", "log1p", "mand", 00458 | "max", "min", "mod", "mor", "mul", "ncdf", "nand", "nor", 00459 | "not", "not_equal", "null", "or", "pow", "rad2deg", 00460 | "repeat", "return", "root", "round", "roundn", "sec", "sgn", 00461 | "shl", "shr", "sin", "sinc", "sinh", "sqrt", "sum", "swap", 00462 | "switch", "tan", "tanh", "true", "trunc", "until", "var", 00463 | "while", "xnor", "xor", "&", "|" 00464 | }; 00465 | 00466 | static const std::size_t reserved_symbols_size = sizeof(reserved_symbols) / sizeof(std::string); 00467 | 00468 | static const std::string base_function_list[] = 00469 | { 00470 | "abs", "acos", "acosh", "asin", "asinh", "atan", "atanh", 00471 | "atan2", "avg", "ceil", "clamp", "cos", "cosh", "cot", 00472 | "csc", "equal", "erf", "erfc", "exp", "expm1", "floor", 00473 | "frac", "hypot", "iclamp", "like", "log", "log10", "log2", 00474 | "logn", "log1p", "mand", "max", "min", "mod", "mor", "mul", 00475 | "ncdf", "pow", "root", "round", "roundn", "sec", "sgn", 00476 | "sin", "sinc", "sinh", "sqrt", "sum", "swap", "tan", "tanh", 00477 | "trunc", "not_equal", "inrange", "deg2grad", "deg2rad", 00478 | "rad2deg", "grad2deg" 00479 | }; 00480 | 00481 | static const std::size_t base_function_list_size = sizeof(base_function_list) / sizeof(std::string); 00482 | 00483 | static const std::string logic_ops_list[] = 00484 | { 00485 | "and", "nand", "nor", "not", "or", "xnor", "xor", "&", "|" 00486 | }; 00487 | 00488 | static const std::size_t logic_ops_list_size = sizeof(logic_ops_list) / sizeof(std::string); 00489 | 00490 | static const std::string cntrl_struct_list[] = 00491 | { 00492 | "if", "switch", "for", "while", "repeat", "return" 00493 | }; 00494 | 00495 | static const std::size_t cntrl_struct_list_size = sizeof(cntrl_struct_list) / sizeof(std::string); 00496 | 00497 | static const std::string arithmetic_ops_list[] = 00498 | { 00499 | "+", "-", "*", "/", "%", "^" 00500 | }; 00501 | 00502 | static const std::size_t arithmetic_ops_list_size = sizeof(arithmetic_ops_list) / sizeof(std::string); 00503 | 00504 | static const std::string assignment_ops_list[] = 00505 | { 00506 | ":=", "+=", "-=", 00507 | "*=", "/=", "%=" 00508 | }; 00509 | 00510 | static const std::size_t assignment_ops_list_size = sizeof(assignment_ops_list) / sizeof(std::string); 00511 | 00512 | static const std::string inequality_ops_list[] = 00513 | { 00514 | "<", "<=", "==", 00515 | "=", "!=", "<>", 00516 | ">=", ">" 00517 | }; 00518 | 00519 | static const std::size_t inequality_ops_list_size = sizeof(inequality_ops_list) / sizeof(std::string); 00520 | 00521 | inline bool is_reserved_word(const std::string& symbol) 00522 | { 00523 | for (std::size_t i = 0; i < reserved_words_size; ++i) 00524 | { 00525 | if (imatch(symbol, reserved_words[i])) 00526 | { 00527 | return true; 00528 | } 00529 | } 00530 | 00531 | return false; 00532 | } 00533 | 00534 | inline bool is_reserved_symbol(const std::string& symbol) 00535 | { 00536 | for (std::size_t i = 0; i < reserved_symbols_size; ++i) 00537 | { 00538 | if (imatch(symbol, reserved_symbols[i])) 00539 | { 00540 | return true; 00541 | } 00542 | } 00543 | 00544 | return false; 00545 | } 00546 | 00547 | inline bool is_base_function(const std::string& function_name) 00548 | { 00549 | for (std::size_t i = 0; i < base_function_list_size; ++i) 00550 | { 00551 | if (imatch(function_name, base_function_list[i])) 00552 | { 00553 | return true; 00554 | } 00555 | } 00556 | 00557 | return false; 00558 | } 00559 | 00560 | inline bool is_control_struct(const std::string& cntrl_strct) 00561 | { 00562 | for (std::size_t i = 0; i < cntrl_struct_list_size; ++i) 00563 | { 00564 | if (imatch(cntrl_strct, cntrl_struct_list[i])) 00565 | { 00566 | return true; 00567 | } 00568 | } 00569 | 00570 | return false; 00571 | } 00572 | 00573 | inline bool is_logic_opr(const std::string& lgc_opr) 00574 | { 00575 | for (std::size_t i = 0; i < logic_ops_list_size; ++i) 00576 | { 00577 | if (imatch(lgc_opr, logic_ops_list[i])) 00578 | { 00579 | return true; 00580 | } 00581 | } 00582 | 00583 | return false; 00584 | } 00585 | 00586 | struct cs_match 00587 | { 00588 | static inline bool cmp(const char_t c0, const char_t c1) 00589 | { 00590 | return (c0 == c1); 00591 | } 00592 | }; 00593 | 00594 | struct cis_match 00595 | { 00596 | static inline bool cmp(const char_t c0, const char_t c1) 00597 | { 00598 | return (std::tolower(c0) == std::tolower(c1)); 00599 | } 00600 | }; 00601 | 00602 | template <typename Iterator, typename Compare> 00603 | inline bool match_impl(const Iterator pattern_begin, 00604 | const Iterator pattern_end , 00605 | const Iterator data_begin , 00606 | const Iterator data_end , 00607 | const typename std::iterator_traits<Iterator>::value_type& zero_or_more, 00608 | const typename std::iterator_traits<Iterator>::value_type& exactly_one ) 00609 | { 00610 | typedef typename std::iterator_traits<Iterator>::value_type type; 00611 | 00612 | const Iterator null_itr(0); 00613 | 00614 | Iterator p_itr = pattern_begin; 00615 | Iterator d_itr = data_begin; 00616 | Iterator np_itr = null_itr; 00617 | Iterator nd_itr = null_itr; 00618 | 00619 | for ( ; ; ) 00620 | { 00621 | if (p_itr != pattern_end) 00622 | { 00623 | const type c = *(p_itr); 00624 | 00625 | if ((data_end != d_itr) && (Compare::cmp(c,*(d_itr)) || (exactly_one == c))) 00626 | { 00627 | ++d_itr; 00628 | ++p_itr; 00629 | continue; 00630 | } 00631 | else if (zero_or_more == c) 00632 | { 00633 | while ((pattern_end != p_itr) && (zero_or_more == *(p_itr))) 00634 | { 00635 | ++p_itr; 00636 | } 00637 | 00638 | const type d = *(p_itr); 00639 | 00640 | while ((data_end != d_itr) && !(Compare::cmp(d,*(d_itr)) || (exactly_one == d))) 00641 | { 00642 | ++d_itr; 00643 | } 00644 | 00645 | // set backtrack iterators 00646 | np_itr = p_itr - 1; 00647 | nd_itr = d_itr + 1; 00648 | 00649 | continue; 00650 | } 00651 | } 00652 | else if (data_end == d_itr) 00653 | break; 00654 | 00655 | if ((data_end == d_itr) || (null_itr == nd_itr)) 00656 | return false; 00657 | 00658 | p_itr = np_itr; 00659 | d_itr = nd_itr; 00660 | } 00661 | 00662 | return true; 00663 | } 00664 | 00665 | inline bool wc_match(const std::string& wild_card, 00666 | const std::string& str) 00667 | { 00668 | return match_impl<char_cptr,cs_match> 00669 | ( 00670 | wild_card.data(), 00671 | wild_card.data() + wild_card.size(), 00672 | str.data(), 00673 | str.data() + str.size(), 00674 | '*', '?' 00675 | ); 00676 | } 00677 | 00678 | inline bool wc_imatch(const std::string& wild_card, 00679 | const std::string& str) 00680 | { 00681 | return match_impl<char_cptr,cis_match> 00682 | ( 00683 | wild_card.data(), 00684 | wild_card.data() + wild_card.size(), 00685 | str.data(), 00686 | str.data() + str.size(), 00687 | '*', '?' 00688 | ); 00689 | } 00690 | 00691 | inline bool sequence_match(const std::string& pattern, 00692 | const std::string& str, 00693 | std::size_t& diff_index, 00694 | char_t& diff_value) 00695 | { 00696 | if (str.empty()) 00697 | { 00698 | return ("Z" == pattern); 00699 | } 00700 | else if ('*' == pattern[0]) 00701 | return false; 00702 | 00703 | typedef std::string::const_iterator itr_t; 00704 | 00705 | itr_t p_itr = pattern.begin(); 00706 | itr_t s_itr = str .begin(); 00707 | 00708 | const itr_t p_end = pattern.end(); 00709 | const itr_t s_end = str .end(); 00710 | 00711 | while ((s_end != s_itr) && (p_end != p_itr)) 00712 | { 00713 | if ('*' == (*p_itr)) 00714 | { 00715 | const char_t target = static_cast<char_t>(std::toupper(*(p_itr - 1))); 00716 | 00717 | if ('*' == target) 00718 | { 00719 | diff_index = static_cast<std::size_t>(std::distance(str.begin(),s_itr)); 00720 | diff_value = static_cast<char_t>(std::toupper(*p_itr)); 00721 | 00722 | return false; 00723 | } 00724 | else 00725 | ++p_itr; 00726 | 00727 | while (s_itr != s_end) 00728 | { 00729 | if (target != std::toupper(*s_itr)) 00730 | break; 00731 | else 00732 | ++s_itr; 00733 | } 00734 | 00735 | continue; 00736 | } 00737 | else if ( 00738 | ('?' != *p_itr) && 00739 | std::toupper(*p_itr) != std::toupper(*s_itr) 00740 | ) 00741 | { 00742 | diff_index = static_cast<std::size_t>(std::distance(str.begin(),s_itr)); 00743 | diff_value = static_cast<char_t>(std::toupper(*p_itr)); 00744 | 00745 | return false; 00746 | } 00747 | 00748 | ++p_itr; 00749 | ++s_itr; 00750 | } 00751 | 00752 | return ( 00753 | (s_end == s_itr) && 00754 | ( 00755 | (p_end == p_itr) || 00756 | ('*' == *p_itr) 00757 | ) 00758 | ); 00759 | } 00760 | 00761 | template<typename T> 00762 | struct set_zero_value_impl 00763 | { 00764 | static inline void process(T* base_ptr, const std::size_t size) 00765 | { 00766 | const T zero = T(0); 00767 | for (std::size_t i = 0; i < size; ++i) 00768 | { 00769 | base_ptr[i] = zero; 00770 | } 00771 | } 00772 | }; 00773 | 00774 | #define pod_set_zero_value(T) \ 00775 | template <> \ 00776 | struct set_zero_value_impl<T> \ 00777 | { \ 00778 | static inline void process(T* base_ptr, const std::size_t size) \ 00779 | { std::memset(base_ptr, 0x00, size * sizeof(T)); } \ 00780 | }; \ 00781 | 00782 | pod_set_zero_value(float ) 00783 | pod_set_zero_value(double ) 00784 | pod_set_zero_value(long double) 00785 | 00786 | #ifdef pod_set_zero_value 00787 | #undef pod_set_zero_value 00788 | #endif 00789 | 00790 | template<typename T> 00791 | inline void set_zero_value(T* data, const std::size_t size) 00792 | { 00793 | set_zero_value_impl<T>::process(data,size); 00794 | } 00795 | 00796 | template<typename T> 00797 | inline void set_zero_value(std::vector<T>& v) 00798 | { 00799 | set_zero_value(v.data(),v.size()); 00800 | } 00801 | 00802 | static const double pow10[] = 00803 | { 00804 | 1.0, 00805 | 1.0E+001, 1.0E+002, 1.0E+003, 1.0E+004, 00806 | 1.0E+005, 1.0E+006, 1.0E+007, 1.0E+008, 00807 | 1.0E+009, 1.0E+010, 1.0E+011, 1.0E+012, 00808 | 1.0E+013, 1.0E+014, 1.0E+015, 1.0E+016 00809 | }; 00810 | 00811 | static const std::size_t pow10_size = sizeof(pow10) / sizeof(double); 00812 | 00813 | namespace numeric 00814 | { 00815 | namespace constant 00816 | { 00817 | static const double e = 2.71828182845904523536028747135266249775724709369996; 00818 | static const double pi = 3.14159265358979323846264338327950288419716939937510; 00819 | static const double pi_2 = 1.57079632679489661923132169163975144209858469968755; 00820 | static const double pi_4 = 0.78539816339744830961566084581987572104929234984378; 00821 | static const double pi_180 = 0.01745329251994329576923690768488612713442871888542; 00822 | static const double _1_pi = 0.31830988618379067153776752674502872406891929148091; 00823 | static const double _2_pi = 0.63661977236758134307553505349005744813783858296183; 00824 | static const double _180_pi = 57.29577951308232087679815481410517033240547246656443; 00825 | static const double log2 = 0.69314718055994530941723212145817656807550013436026; 00826 | static const double sqrt2 = 1.41421356237309504880168872420969807856967187537695; 00827 | } 00828 | 00829 | namespace details 00830 | { 00831 | struct unknown_type_tag { unknown_type_tag() {} }; 00832 | struct real_type_tag { real_type_tag () {} }; 00833 | struct int_type_tag { int_type_tag () {} }; 00834 | 00835 | template <typename T> 00836 | struct number_type 00837 | { 00838 | typedef unknown_type_tag type; 00839 | number_type() {} 00840 | }; 00841 | 00842 | #define exprtk_register_real_type_tag(T) \ 00843 | template <> struct number_type<T> \ 00844 | { typedef real_type_tag type; number_type() {} }; \ 00845 | 00846 | #define exprtk_register_int_type_tag(T) \ 00847 | template <> struct number_type<T> \ 00848 | { typedef int_type_tag type; number_type() {} }; \ 00849 | 00850 | exprtk_register_real_type_tag(float ) 00851 | exprtk_register_real_type_tag(double ) 00852 | exprtk_register_real_type_tag(long double) 00853 | 00854 | exprtk_register_int_type_tag(short ) 00855 | exprtk_register_int_type_tag(int ) 00856 | exprtk_register_int_type_tag(_int64_t ) 00857 | exprtk_register_int_type_tag(unsigned short) 00858 | exprtk_register_int_type_tag(unsigned int ) 00859 | exprtk_register_int_type_tag(_uint64_t ) 00860 | 00861 | #undef exprtk_register_real_type_tag 00862 | #undef exprtk_register_int_type_tag 00863 | 00864 | template <typename T> 00865 | struct epsilon_type {}; 00866 | 00867 | #define exprtk_define_epsilon_type(Type, Epsilon) \ 00868 | template <> struct epsilon_type<Type> \ 00869 | { \ 00870 | static inline Type value() \ 00871 | { \ 00872 | const Type epsilon = static_cast<Type>(Epsilon); \ 00873 | return epsilon; \ 00874 | } \ 00875 | }; \ 00876 | 00877 | exprtk_define_epsilon_type(float , 0.00000100000f) 00878 | exprtk_define_epsilon_type(double , 0.000000000100) 00879 | exprtk_define_epsilon_type(long double, 0.000000000001) 00880 | 00881 | #undef exprtk_define_epsilon_type 00882 | 00883 | template <typename T> 00884 | inline bool is_nan_impl(const T v, real_type_tag) 00885 | { 00886 | return std::not_equal_to<T>()(v,v); 00887 | } 00888 | 00889 | template <typename T> 00890 | inline int to_int32_impl(const T v, real_type_tag) 00891 | { 00892 | return static_cast<int>(v); 00893 | } 00894 | 00895 | template <typename T> 00896 | inline _int64_t to_int64_impl(const T v, real_type_tag) 00897 | { 00898 | return static_cast<_int64_t>(v); 00899 | } 00900 | 00901 | template <typename T> 00902 | inline _uint64_t to_uint64_impl(const T v, real_type_tag) 00903 | { 00904 | return static_cast<_uint64_t>(v); 00905 | } 00906 | 00907 | template <typename T> 00908 | inline bool is_true_impl(const T v) 00909 | { 00910 | return std::not_equal_to<T>()(T(0),v); 00911 | } 00912 | 00913 | template <typename T> 00914 | inline bool is_false_impl(const T v) 00915 | { 00916 | return std::equal_to<T>()(T(0),v); 00917 | } 00918 | 00919 | template <typename T> 00920 | inline T abs_impl(const T v, real_type_tag) 00921 | { 00922 | return ((v < T(0)) ? -v : v); 00923 | } 00924 | 00925 | template <typename T> 00926 | inline T min_impl(const T v0, const T v1, real_type_tag) 00927 | { 00928 | return std::min<T>(v0,v1); 00929 | } 00930 | 00931 | template <typename T> 00932 | inline T max_impl(const T v0, const T v1, real_type_tag) 00933 | { 00934 | return std::max<T>(v0,v1); 00935 | } 00936 | 00937 | template <typename T> 00938 | inline T equal_impl(const T v0, const T v1, real_type_tag) 00939 | { 00940 | const T epsilon = epsilon_type<T>::value(); 00941 | 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); 00942 | } 00943 | 00944 | inline float equal_impl(const float v0, const float v1, real_type_tag) 00945 | { 00946 | const float epsilon = epsilon_type<float>::value(); 00947 | 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; 00948 | } 00949 | 00950 | template <typename T> 00951 | inline T equal_impl(const T v0, const T v1, int_type_tag) 00952 | { 00953 | return (v0 == v1) ? 1 : 0; 00954 | } 00955 | 00956 | template <typename T> 00957 | inline T nequal_impl(const T v0, const T v1, real_type_tag) 00958 | { 00959 | typedef real_type_tag rtg; 00960 | const T epsilon = epsilon_type<T>::value(); 00961 | 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); 00962 | } 00963 | 00964 | inline float nequal_impl(const float v0, const float v1, real_type_tag) 00965 | { 00966 | typedef real_type_tag rtg; 00967 | const float epsilon = epsilon_type<float>::value(); 00968 | 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; 00969 | } 00970 | 00971 | template <typename T> 00972 | inline T nequal_impl(const T v0, const T v1, int_type_tag) 00973 | { 00974 | return (v0 != v1) ? 1 : 0; 00975 | } 00976 | 00977 | template <typename T> 00978 | inline T modulus_impl(const T v0, const T v1, real_type_tag) 00979 | { 00980 | return std::fmod(v0,v1); 00981 | } 00982 | 00983 | template <typename T> 00984 | inline T modulus_impl(const T v0, const T v1, int_type_tag) 00985 | { 00986 | return v0 % v1; 00987 | } 00988 | 00989 | template <typename T> 00990 | inline T pow_impl(const T v0, const T v1, real_type_tag) 00991 | { 00992 | return std::pow(v0,v1); 00993 | } 00994 | 00995 | template <typename T> 00996 | inline T pow_impl(const T v0, const T v1, int_type_tag) 00997 | { 00998 | return std::pow(static_cast<double>(v0),static_cast<double>(v1)); 00999 | } 01000 | 01001 | template <typename T> 01002 | inline T logn_impl(const T v0, const T v1, real_type_tag) 01003 | { 01004 | return std::log(v0) / std::log(v1); 01005 | } 01006 | 01007 | template <typename T> 01008 | inline T logn_impl(const T v0, const T v1, int_type_tag) 01009 | { 01010 | return static_cast<T>(logn_impl<double>(static_cast<double>(v0),static_cast<double>(v1),real_type_tag())); 01011 | } 01012 | 01013 | template <typename T> 01014 | inline T root_impl(const T v0, const T v1, real_type_tag) 01015 | { 01016 | if (v0 < T(0)) 01017 | { 01018 | return (v1 == trunc_impl(v1, real_type_tag())) && 01019 | (modulus_impl(v1, T(2), real_type_tag()) != T(0)) ? 01020 | -std::pow(abs_impl(v0, real_type_tag()), T(1) / v1) : 01021 | std::numeric_limits<double>::quiet_NaN(); 01022 | } 01023 | 01024 | return std::pow(v0, T(1) / v1); 01025 | } 01026 | 01027 | template <typename T> 01028 | inline T root_impl(const T v0, const T v1, int_type_tag) 01029 | { 01030 | return root_impl<double>(static_cast<double>(v0),static_cast<double>(v1),real_type_tag()); 01031 | } 01032 | 01033 | template <typename T> 01034 | inline T round_impl(const T v, real_type_tag) 01035 | { 01036 | return ((v < T(0)) ? std::ceil(v - T(0.5)) : std::floor(v + T(0.5))); 01037 | } 01038 | 01039 | template <typename T> 01040 | inline T roundn_impl(const T v0, const T v1, real_type_tag) 01041 | { 01042 | const int index = std::max<int>(0, std::min<int>(pow10_size - 1, static_cast<int>(std::floor(v1)))); 01043 | const T p10 = T(pow10[index]); 01044 | 01045 | if (v0 < T(0)) 01046 | return T(std::ceil ((v0 * p10) - T(0.5)) / p10); 01047 | else 01048 | return T(std::floor((v0 * p10) + T(0.5)) / p10); 01049 | } 01050 | 01051 | template <typename T> 01052 | inline T roundn_impl(const T v0, const T, int_type_tag) 01053 | { 01054 | return v0; 01055 | } 01056 | 01057 | template <typename T> 01058 | inline T hypot_impl(const T v0, const T v1, real_type_tag) 01059 | { 01060 | return std::sqrt((v0 * v0) + (v1 * v1)); 01061 | } 01062 | 01063 | template <typename T> 01064 | inline T hypot_impl(const T v0, const T v1, int_type_tag) 01065 | { 01066 | return static_cast<T>(std::sqrt(static_cast<double>((v0 * v0) + (v1 * v1)))); 01067 | } 01068 | 01069 | template <typename T> 01070 | inline T atan2_impl(const T v0, const T v1, real_type_tag) 01071 | { 01072 | return std::atan2(v0,v1); 01073 | } 01074 | 01075 | template <typename T> 01076 | inline T atan2_impl(const T, const T, int_type_tag) 01077 | { 01078 | return 0; 01079 | } 01080 | 01081 | template <typename T> 01082 | inline T shr_impl(const T v0, const T v1, real_type_tag) 01083 | { 01084 | return v0 * (T(1) / std::pow(T(2),static_cast<T>(static_cast<int>(v1)))); 01085 | } 01086 | 01087 | template <typename T> 01088 | inline T shr_impl(const T v0, const T v1, int_type_tag) 01089 | { 01090 | return v0 >> v1; 01091 | } 01092 | 01093 | template <typename T> 01094 | inline T shl_impl(const T v0, const T v1, real_type_tag) 01095 | { 01096 | return v0 * std::pow(T(2),static_cast<T>(static_cast<int>(v1))); 01097 | } 01098 | 01099 | template <typename T> 01100 | inline T shl_impl(const T v0, const T v1, int_type_tag) 01101 | { 01102 | return v0 << v1; 01103 | } 01104 | 01105 | template <typename T> 01106 | inline T sgn_impl(const T v, real_type_tag) 01107 | { 01108 | if (v > T(0)) return T(+1); 01109 | else if (v < T(0)) return T(-1); 01110 | else return T( 0); 01111 | } 01112 | 01113 | template <typename T> 01114 | inline T sgn_impl(const T v, int_type_tag) 01115 | { 01116 | if (v > T(0)) return T(+1); 01117 | else if (v < T(0)) return T(-1); 01118 | else return T( 0); 01119 | } 01120 | 01121 | template <typename T> 01122 | inline T and_impl(const T v0, const T v1, real_type_tag) 01123 | { 01124 | return (is_true_impl(v0) && is_true_impl(v1)) ? T(1) : T(0); 01125 | } 01126 | 01127 | template <typename T> 01128 | inline T and_impl(const T v0, const T v1, int_type_tag) 01129 | { 01130 | return v0 && v1; 01131 | } 01132 | 01133 | template <typename T> 01134 | inline T nand_impl(const T v0, const T v1, real_type_tag) 01135 | { 01136 | return (is_false_impl(v0) || is_false_impl(v1)) ? T(1) : T(0); 01137 | } 01138 | 01139 | template <typename T> 01140 | inline T nand_impl(const T v0, const T v1, int_type_tag) 01141 | { 01142 | return !(v0 && v1); 01143 | } 01144 | 01145 | template <typename T> 01146 | inline T or_impl(const T v0, const T v1, real_type_tag) 01147 | { 01148 | return (is_true_impl(v0) || is_true_impl(v1)) ? T(1) : T(0); 01149 | } 01150 | 01151 | template <typename T> 01152 | inline T or_impl(const T v0, const T v1, int_type_tag) 01153 | { 01154 | return (v0 || v1); 01155 | } 01156 | 01157 | template <typename T> 01158 | inline T nor_impl(const T v0, const T v1, real_type_tag) 01159 | { 01160 | return (is_false_impl(v0) && is_false_impl(v1)) ? T(1) : T(0); 01161 | } 01162 | 01163 | template <typename T> 01164 | inline T nor_impl(const T v0, const T v1, int_type_tag) 01165 | { 01166 | return !(v0 || v1); 01167 | } 01168 | 01169 | template <typename T> 01170 | inline T xor_impl(const T v0, const T v1, real_type_tag) 01171 | { 01172 | return (is_false_impl(v0) != is_false_impl(v1)) ? T(1) : T(0); 01173 | } 01174 | 01175 | template <typename T> 01176 | inline T xor_impl(const T v0, const T v1, int_type_tag) 01177 | { 01178 | return v0 ^ v1; 01179 | } 01180 | 01181 | template <typename T> 01182 | inline T xnor_impl(const T v0, const T v1, real_type_tag) 01183 | { 01184 | const bool v0_true = is_true_impl(v0); 01185 | const bool v1_true = is_true_impl(v1); 01186 | 01187 | if ((v0_true && v1_true) || (!v0_true && !v1_true)) 01188 | return T(1); 01189 | else 01190 | return T(0); 01191 | } 01192 | 01193 | template <typename T> 01194 | inline T xnor_impl(const T v0, const T v1, int_type_tag) 01195 | { 01196 | const bool v0_true = is_true_impl(v0); 01197 | const bool v1_true = is_true_impl(v1); 01198 | 01199 | if ((v0_true && v1_true) || (!v0_true && !v1_true)) 01200 | return T(1); 01201 | else 01202 | return T(0); 01203 | } 01204 | 01205 | #if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || !defined(_MSC_VER) 01206 | #define exprtk_define_erf(TT, impl) \ 01207 | inline TT erf_impl(const TT v) { return impl(v); } \ 01208 | 01209 | exprtk_define_erf(float , ::erff) 01210 | exprtk_define_erf(double , ::erf ) 01211 | exprtk_define_erf(long double, ::erfl) 01212 | #undef exprtk_define_erf 01213 | #endif 01214 | 01215 | template <typename T> 01216 | inline T erf_impl(const T v, real_type_tag) 01217 | { 01218 | #if defined(_MSC_VER) && (_MSC_VER < 1900) 01219 | // Credits: Abramowitz & Stegun Equations 7.1.25-28 01220 | static const T c[] = 01221 | { 01222 | T( 1.26551223), T(1.00002368), 01223 | T( 0.37409196), T(0.09678418), 01224 | T(-0.18628806), T(0.27886807), 01225 | T(-1.13520398), T(1.48851587), 01226 | T(-0.82215223), T(0.17087277) 01227 | }; 01228 | 01229 | const T t = T(1) / (T(1) + T(0.5) * abs_impl(v,real_type_tag())); 01230 | 01231 | const T result = T(1) - t * std::exp((-v * v) - 01232 | c[0] + t * (c[1] + t * 01233 | (c[2] + t * (c[3] + t * 01234 | (c[4] + t * (c[5] + t * 01235 | (c[6] + t * (c[7] + t * 01236 | (c[8] + t * (c[9])))))))))); 01237 | 01238 | return (v >= T(0)) ? result : -result; 01239 | #else 01240 | return erf_impl(v); 01241 | #endif 01242 | } 01243 | 01244 | template <typename T> 01245 | inline T erf_impl(const T v, int_type_tag) 01246 | { 01247 | return erf_impl(static_cast<double>(v),real_type_tag()); 01248 | } 01249 | 01250 | #if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || !defined(_MSC_VER) 01251 | #define exprtk_define_erfc(TT, impl) \ 01252 | inline TT erfc_impl(const TT v) { return impl(v); } \ 01253 | 01254 | exprtk_define_erfc(float ,::erfcf) 01255 | exprtk_define_erfc(double ,::erfc ) 01256 | exprtk_define_erfc(long double,::erfcl) 01257 | #undef exprtk_define_erfc 01258 | #endif 01259 | 01260 | template <typename T> 01261 | inline T erfc_impl(const T v, real_type_tag) 01262 | { 01263 | #if defined(_MSC_VER) && (_MSC_VER < 1900) 01264 | return T(1) - erf_impl(v,real_type_tag()); 01265 | #else 01266 | return erfc_impl(v); 01267 | #endif 01268 | } 01269 | 01270 | template <typename T> 01271 | inline T erfc_impl(const T v, int_type_tag) 01272 | { 01273 | return erfc_impl(static_cast<double>(v),real_type_tag()); 01274 | } 01275 | 01276 | template <typename T> 01277 | inline T ncdf_impl(const T v, real_type_tag) 01278 | { 01279 | return T(0.5) * erfc_impl(-(v / T(numeric::constant::sqrt2)),real_type_tag()); 01280 | } 01281 | 01282 | template <typename T> 01283 | inline T ncdf_impl(const T v, int_type_tag) 01284 | { 01285 | return ncdf_impl(static_cast<double>(v),real_type_tag()); 01286 | } 01287 | 01288 | template <typename T> 01289 | inline T sinc_impl(const T v, real_type_tag) 01290 | { 01291 | if (std::abs(v) >= std::numeric_limits<T>::epsilon()) 01292 | return(std::sin(v) / v); 01293 | else 01294 | return T(1); 01295 | } 01296 | 01297 | template <typename T> 01298 | inline T sinc_impl(const T v, int_type_tag) 01299 | { 01300 | return sinc_impl(static_cast<double>(v),real_type_tag()); 01301 | } 01302 | 01303 | #if __cplusplus >= 201103L 01304 | template <typename T> 01305 | inline T acosh_impl(const T v, real_type_tag) 01306 | { 01307 | return std::acosh(v); 01308 | } 01309 | 01310 | template <typename T> 01311 | inline T asinh_impl(const T v, real_type_tag) 01312 | { 01313 | return std::asinh(v); 01314 | } 01315 | 01316 | template <typename T> 01317 | inline T atanh_impl(const T v, real_type_tag) 01318 | { 01319 | return std::atanh(v); 01320 | } 01321 | 01322 | template <typename T> 01323 | inline T trunc_impl(const T v, real_type_tag) 01324 | { 01325 | return std::trunc(v); 01326 | } 01327 | 01328 | template <typename T> 01329 | inline T expm1_impl(const T v, real_type_tag) 01330 | { 01331 | return std::expm1(v); 01332 | } 01333 | 01334 | template <typename T> 01335 | inline T expm1_impl(const T v, int_type_tag) 01336 | { 01337 | return std::expm1(v); 01338 | } 01339 | 01340 | template <typename T> 01341 | inline T log1p_impl(const T v, real_type_tag) 01342 | { 01343 | return std::log1p(v); 01344 | } 01345 | 01346 | template <typename T> 01347 | inline T log1p_impl(const T v, int_type_tag) 01348 | { 01349 | return std::log1p(v); 01350 | } 01351 | #else 01352 | template <typename T> 01353 | inline T acosh_impl(const T v, real_type_tag) 01354 | { 01355 | return std::log(v + std::sqrt((v * v) - T(1))); 01356 | } 01357 | 01358 | template <typename T> 01359 | inline T asinh_impl(const T v, real_type_tag) 01360 | { 01361 | return std::log(v + std::sqrt((v * v) + T(1))); 01362 | } 01363 | 01364 | template <typename T> 01365 | inline T atanh_impl(const T v, real_type_tag) 01366 | { 01367 | return (std::log(T(1) + v) - std::log(T(1) - v)) / T(2); 01368 | } 01369 | 01370 | template <typename T> 01371 | inline T trunc_impl(const T v, real_type_tag) 01372 | { 01373 | return T(static_cast<long long>(v)); 01374 | } 01375 | 01376 | template <typename T> 01377 | inline T expm1_impl(const T v, real_type_tag) 01378 | { 01379 | if (abs_impl(v,real_type_tag()) < T(0.00001)) 01380 | return v + (T(0.5) * v * v); 01381 | else 01382 | return std::exp(v) - T(1); 01383 | } 01384 | 01385 | template <typename T> 01386 | inline T expm1_impl(const T v, int_type_tag) 01387 | { 01388 | return T(std::exp<double>(v)) - T(1); 01389 | } 01390 | 01391 | template <typename T> 01392 | inline T log1p_impl(const T v, real_type_tag) 01393 | { 01394 | if (v > T(-1)) 01395 | { 01396 | if (abs_impl(v,real_type_tag()) > T(0.0001)) 01397 | { 01398 | return std::log(T(1) + v); 01399 | } 01400 | else 01401 | return (T(-0.5) * v + T(1)) * v; 01402 | } 01403 | 01404 | return std::numeric_limits<T>::quiet_NaN(); 01405 | } 01406 | 01407 | template <typename T> 01408 | inline T log1p_impl(const T v, int_type_tag) 01409 | { 01410 | if (v > T(-1)) 01411 | { 01412 | return std::log(T(1) + v); 01413 | } 01414 | 01415 | return std::numeric_limits<T>::quiet_NaN(); 01416 | } 01417 | #endif 01418 | 01419 | template <typename T> inline T acos_impl(const T v, real_type_tag) { return std::acos (v); } 01420 | template <typename T> inline T asin_impl(const T v, real_type_tag) { return std::asin (v); } 01421 | template <typename T> inline T atan_impl(const T v, real_type_tag) { return std::atan (v); } 01422 | template <typename T> inline T ceil_impl(const T v, real_type_tag) { return std::ceil (v); } 01423 | template <typename T> inline T cos_impl(const T v, real_type_tag) { return std::cos (v); } 01424 | template <typename T> inline T cosh_impl(const T v, real_type_tag) { return std::cosh (v); } 01425 | template <typename T> inline T exp_impl(const T v, real_type_tag) { return std::exp (v); } 01426 | template <typename T> inline T floor_impl(const T v, real_type_tag) { return std::floor(v); } 01427 | template <typename T> inline T log_impl(const T v, real_type_tag) { return std::log (v); } 01428 | template <typename T> inline T log10_impl(const T v, real_type_tag) { return std::log10(v); } 01429 | template <typename T> inline T log2_impl(const T v, real_type_tag) { return std::log(v)/T(numeric::constant::log2); } 01430 | template <typename T> inline T neg_impl(const T v, real_type_tag) { return -v; } 01431 | template <typename T> inline T pos_impl(const T v, real_type_tag) { return +v; } 01432 | template <typename T> inline T sin_impl(const T v, real_type_tag) { return std::sin (v); } 01433 | template <typename T> inline T sinh_impl(const T v, real_type_tag) { return std::sinh (v); } 01434 | template <typename T> inline T sqrt_impl(const T v, real_type_tag) { return std::sqrt (v); } 01435 | template <typename T> inline T tan_impl(const T v, real_type_tag) { return std::tan (v); } 01436 | template <typename T> inline T tanh_impl(const T v, real_type_tag) { return std::tanh (v); } 01437 | template <typename T> inline T cot_impl(const T v, real_type_tag) { return T(1) / std::tan(v); } 01438 | template <typename T> inline T sec_impl(const T v, real_type_tag) { return T(1) / std::cos(v); } 01439 | template <typename T> inline T csc_impl(const T v, real_type_tag) { return T(1) / std::sin(v); } 01440 | template <typename T> inline T r2d_impl(const T v, real_type_tag) { return (v * T(numeric::constant::_180_pi)); } 01441 | template <typename T> inline T d2r_impl(const T v, real_type_tag) { return (v * T(numeric::constant::pi_180)); } 01442 | template <typename T> inline T d2g_impl(const T v, real_type_tag) { return (v * T(10.0/9.0)); } 01443 | template <typename T> inline T g2d_impl(const T v, real_type_tag) { return (v * T(9.0/10.0)); } 01444 | 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)); } 01445 | template <typename T> inline T frac_impl(const T v, real_type_tag) { return (v - trunc_impl(v,real_type_tag())); } 01446 | 01447 | template <typename T> inline T const_pi_impl(real_type_tag) { return T(numeric::constant::pi); } 01448 | template <typename T> inline T const_e_impl(real_type_tag) { return T(numeric::constant::e); } 01449 | template <typename T> inline T const_qnan_impl(real_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01450 | 01451 | template <typename T> inline T abs_impl(const T v, int_type_tag) { return ((v >= T(0)) ? v : -v); } 01452 | template <typename T> inline T exp_impl(const T v, int_type_tag) { return std::exp (v); } 01453 | template <typename T> inline T log_impl(const T v, int_type_tag) { return std::log (v); } 01454 | template <typename T> inline T log10_impl(const T v, int_type_tag) { return std::log10(v); } 01455 | template <typename T> inline T log2_impl(const T v, int_type_tag) { return std::log(v)/T(numeric::constant::log2); } 01456 | template <typename T> inline T neg_impl(const T v, int_type_tag) { return -v; } 01457 | template <typename T> inline T pos_impl(const T v, int_type_tag) { return +v; } 01458 | template <typename T> inline T ceil_impl(const T v, int_type_tag) { return v; } 01459 | template <typename T> inline T floor_impl(const T v, int_type_tag) { return v; } 01460 | template <typename T> inline T round_impl(const T v, int_type_tag) { return v; } 01461 | template <typename T> inline T notl_impl(const T v, int_type_tag) { return !v; } 01462 | template <typename T> inline T sqrt_impl(const T v, int_type_tag) { return std::sqrt (v); } 01463 | template <typename T> inline T frac_impl(const T , int_type_tag) { return T(0); } 01464 | template <typename T> inline T trunc_impl(const T v, int_type_tag) { return v; } 01465 | template <typename T> inline T acos_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01466 | template <typename T> inline T acosh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01467 | template <typename T> inline T asin_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01468 | template <typename T> inline T asinh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01469 | template <typename T> inline T atan_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01470 | template <typename T> inline T atanh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01471 | template <typename T> inline T cos_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01472 | template <typename T> inline T cosh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01473 | template <typename T> inline T sin_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01474 | template <typename T> inline T sinh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01475 | template <typename T> inline T tan_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01476 | template <typename T> inline T tanh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01477 | template <typename T> inline T cot_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01478 | template <typename T> inline T sec_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01479 | template <typename T> inline T csc_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01480 | 01481 | template <typename T> 01482 | inline bool is_integer_impl(const T& v, real_type_tag) 01483 | { 01484 | return std::equal_to<T>()(T(0),std::fmod(v,T(1))); 01485 | } 01486 | 01487 | template <typename T> 01488 | inline bool is_integer_impl(const T&, int_type_tag) 01489 | { 01490 | return true; 01491 | } 01492 | } 01493 | 01494 | template <typename Type> 01495 | struct numeric_info { enum { length = 0, size = 32, bound_length = 0, min_exp = 0, max_exp = 0 }; }; 01496 | 01497 | template <> struct numeric_info<int > { enum { length = 10, size = 16, bound_length = 9 }; }; 01498 | template <> struct numeric_info<float > { enum { min_exp = -38, max_exp = +38 }; }; 01499 | template <> struct numeric_info<double > { enum { min_exp = -308, max_exp = +308 }; }; 01500 | template <> struct numeric_info<long double> { enum { min_exp = -308, max_exp = +308 }; }; 01501 | 01502 | template <typename T> 01503 | inline int to_int32(const T v) 01504 | { 01505 | const typename details::number_type<T>::type num_type; 01506 | return to_int32_impl(v, num_type); 01507 | } 01508 | 01509 | template <typename T> 01510 | inline _int64_t to_int64(const T v) 01511 | { 01512 | const typename details::number_type<T>::type num_type; 01513 | return to_int64_impl(v, num_type); 01514 | } 01515 | 01516 | template <typename T> 01517 | inline _uint64_t to_uint64(const T v) 01518 | { 01519 | const typename details::number_type<T>::type num_type; 01520 | return to_uint64_impl(v, num_type); 01521 | } 01522 | 01523 | template <typename T> 01524 | inline bool is_nan(const T v) 01525 | { 01526 | const typename details::number_type<T>::type num_type; 01527 | return is_nan_impl(v, num_type); 01528 | } 01529 | 01530 | template <typename T> 01531 | inline T min(const T v0, const T v1) 01532 | { 01533 | const typename details::number_type<T>::type num_type; 01534 | return min_impl(v0, v1, num_type); 01535 | } 01536 | 01537 | template <typename T> 01538 | inline T max(const T v0, const T v1) 01539 | { 01540 | const typename details::number_type<T>::type num_type; 01541 | return max_impl(v0, v1, num_type); 01542 | } 01543 | 01544 | template <typename T> 01545 | inline T equal(const T v0, const T v1) 01546 | { 01547 | const typename details::number_type<T>::type num_type; 01548 | return equal_impl(v0, v1, num_type); 01549 | } 01550 | 01551 | template <typename T> 01552 | inline T nequal(const T v0, const T v1) 01553 | { 01554 | const typename details::number_type<T>::type num_type; 01555 | return nequal_impl(v0, v1, num_type); 01556 | } 01557 | 01558 | template <typename T> 01559 | inline T modulus(const T v0, const T v1) 01560 | { 01561 | const typename details::number_type<T>::type num_type; 01562 | return modulus_impl(v0, v1, num_type); 01563 | } 01564 | 01565 | template <typename T> 01566 | inline T pow(const T v0, const T v1) 01567 | { 01568 | const typename details::number_type<T>::type num_type; 01569 | return pow_impl(v0, v1, num_type); 01570 | } 01571 | 01572 | template <typename T> 01573 | inline T logn(const T v0, const T v1) 01574 | { 01575 | const typename details::number_type<T>::type num_type; 01576 | return logn_impl(v0, v1, num_type); 01577 | } 01578 | 01579 | template <typename T> 01580 | inline T root(const T v0, const T v1) 01581 | { 01582 | const typename details::number_type<T>::type num_type; 01583 | return root_impl(v0, v1, num_type); 01584 | } 01585 | 01586 | template <typename T> 01587 | inline T roundn(const T v0, const T v1) 01588 | { 01589 | const typename details::number_type<T>::type num_type; 01590 | return roundn_impl(v0, v1, num_type); 01591 | } 01592 | 01593 | template <typename T> 01594 | inline T hypot(const T v0, const T v1) 01595 | { 01596 | const typename details::number_type<T>::type num_type; 01597 | return hypot_impl(v0, v1, num_type); 01598 | } 01599 | 01600 | template <typename T> 01601 | inline T atan2(const T v0, const T v1) 01602 | { 01603 | const typename details::number_type<T>::type num_type; 01604 | return atan2_impl(v0, v1, num_type); 01605 | } 01606 | 01607 | template <typename T> 01608 | inline T shr(const T v0, const T v1) 01609 | { 01610 | const typename details::number_type<T>::type num_type; 01611 | return shr_impl(v0, v1, num_type); 01612 | } 01613 | 01614 | template <typename T> 01615 | inline T shl(const T v0, const T v1) 01616 | { 01617 | const typename details::number_type<T>::type num_type; 01618 | return shl_impl(v0, v1, num_type); 01619 | } 01620 | 01621 | template <typename T> 01622 | inline T and_opr(const T v0, const T v1) 01623 | { 01624 | const typename details::number_type<T>::type num_type; 01625 | return and_impl(v0, v1, num_type); 01626 | } 01627 | 01628 | template <typename T> 01629 | inline T nand_opr(const T v0, const T v1) 01630 | { 01631 | const typename details::number_type<T>::type num_type; 01632 | return nand_impl(v0, v1, num_type); 01633 | } 01634 | 01635 | template <typename T> 01636 | inline T or_opr(const T v0, const T v1) 01637 | { 01638 | const typename details::number_type<T>::type num_type; 01639 | return or_impl(v0, v1, num_type); 01640 | } 01641 | 01642 | template <typename T> 01643 | inline T nor_opr(const T v0, const T v1) 01644 | { 01645 | const typename details::number_type<T>::type num_type; 01646 | return nor_impl(v0, v1, num_type); 01647 | } 01648 | 01649 | template <typename T> 01650 | inline T xor_opr(const T v0, const T v1) 01651 | { 01652 | const typename details::number_type<T>::type num_type; 01653 | return xor_impl(v0, v1, num_type); 01654 | } 01655 | 01656 | template <typename T> 01657 | inline T xnor_opr(const T v0, const T v1) 01658 | { 01659 | const typename details::number_type<T>::type num_type; 01660 | return xnor_impl(v0, v1, num_type); 01661 | } 01662 | 01663 | template <typename T> 01664 | inline bool is_integer(const T v) 01665 | { 01666 | const typename details::number_type<T>::type num_type; 01667 | return is_integer_impl(v, num_type); 01668 | } 01669 | 01670 | template <typename T, unsigned int N> 01671 | struct fast_exp 01672 | { 01673 | static inline T result(T v) 01674 | { 01675 | unsigned int k = N; 01676 | T l = T(1); 01677 | 01678 | while (k) 01679 | { 01680 | if (1 == (k % 2)) 01681 | { 01682 | l *= v; 01683 | --k; 01684 | } 01685 | 01686 | v *= v; 01687 | k /= 2; 01688 | } 01689 | 01690 | return l; 01691 | } 01692 | }; 01693 | 01694 | 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; } }; 01695 | template <typename T> struct fast_exp<T, 9> { static inline T result(const T v) { return fast_exp<T,8>::result(v) * v; } }; 01696 | 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; } }; 01697 | template <typename T> struct fast_exp<T, 7> { static inline T result(const T v) { return fast_exp<T,6>::result(v) * v; } }; 01698 | 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; } }; 01699 | template <typename T> struct fast_exp<T, 5> { static inline T result(const T v) { return fast_exp<T,4>::result(v) * v; } }; 01700 | 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; } }; 01701 | template <typename T> struct fast_exp<T, 3> { static inline T result(const T v) { return v * v * v; } }; 01702 | template <typename T> struct fast_exp<T, 2> { static inline T result(const T v) { return v * v; } }; 01703 | template <typename T> struct fast_exp<T, 1> { static inline T result(const T v) { return v; } }; 01704 | template <typename T> struct fast_exp<T, 0> { static inline T result(const T ) { return T(1); } }; 01705 | 01706 | #define exprtk_define_unary_function(FunctionName) \ 01707 | template <typename T> \ 01708 | inline T FunctionName (const T v) \ 01709 | { \ 01710 | const typename details::number_type<T>::type num_type; \ 01711 | return FunctionName##_impl(v,num_type); \ 01712 | } \ 01713 | 01714 | exprtk_define_unary_function(abs ) 01715 | exprtk_define_unary_function(acos ) 01716 | exprtk_define_unary_function(acosh) 01717 | exprtk_define_unary_function(asin ) 01718 | exprtk_define_unary_function(asinh) 01719 | exprtk_define_unary_function(atan ) 01720 | exprtk_define_unary_function(atanh) 01721 | exprtk_define_unary_function(ceil ) 01722 | exprtk_define_unary_function(cos ) 01723 | exprtk_define_unary_function(cosh ) 01724 | exprtk_define_unary_function(exp ) 01725 | exprtk_define_unary_function(expm1) 01726 | exprtk_define_unary_function(floor) 01727 | exprtk_define_unary_function(log ) 01728 | exprtk_define_unary_function(log10) 01729 | exprtk_define_unary_function(log2 ) 01730 | exprtk_define_unary_function(log1p) 01731 | exprtk_define_unary_function(neg ) 01732 | exprtk_define_unary_function(pos ) 01733 | exprtk_define_unary_function(round) 01734 | exprtk_define_unary_function(sin ) 01735 | exprtk_define_unary_function(sinc ) 01736 | exprtk_define_unary_function(sinh ) 01737 | exprtk_define_unary_function(sqrt ) 01738 | exprtk_define_unary_function(tan ) 01739 | exprtk_define_unary_function(tanh ) 01740 | exprtk_define_unary_function(cot ) 01741 | exprtk_define_unary_function(sec ) 01742 | exprtk_define_unary_function(csc ) 01743 | exprtk_define_unary_function(r2d ) 01744 | exprtk_define_unary_function(d2r ) 01745 | exprtk_define_unary_function(d2g ) 01746 | exprtk_define_unary_function(g2d ) 01747 | exprtk_define_unary_function(notl ) 01748 | exprtk_define_unary_function(sgn ) 01749 | exprtk_define_unary_function(erf ) 01750 | exprtk_define_unary_function(erfc ) 01751 | exprtk_define_unary_function(ncdf ) 01752 | exprtk_define_unary_function(frac ) 01753 | exprtk_define_unary_function(trunc) 01754 | #undef exprtk_define_unary_function 01755 | } 01756 | 01757 | template <typename T> 01758 | inline T compute_pow10(T d, const int exponent) 01759 | { 01760 | static const double fract10[] = 01761 | { 01762 | 0.0, 01763 | 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, 01764 | 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, 01765 | 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, 01766 | 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, 01767 | 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, 01768 | 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, 01769 | 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, 01770 | 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, 01771 | 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, 01772 | 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, 01773 | 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, 01774 | 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, 01775 | 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, 01776 | 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, 01777 | 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, 01778 | 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, 01779 | 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, 01780 | 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, 01781 | 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, 01782 | 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, 01783 | 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, 01784 | 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, 01785 | 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, 01786 | 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, 01787 | 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, 01788 | 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, 01789 | 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, 01790 | 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, 01791 | 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, 01792 | 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, 01793 | 1.0E+301, 1.0E+302, 1.0E+303, 1.0E+304, 1.0E+305, 1.0E+306, 1.0E+307, 1.0E+308 01794 | }; 01795 | 01796 | static const int fract10_size = static_cast<int>(sizeof(fract10) / sizeof(double)); 01797 | 01798 | const int e = std::abs(exponent); 01799 | 01800 | if (exponent >= std::numeric_limits<T>::min_exponent10) 01801 | { 01802 | if (e < fract10_size) 01803 | { 01804 | if (exponent > 0) 01805 | return T(d * fract10[e]); 01806 | else 01807 | return T(d / fract10[e]); 01808 | } 01809 | else 01810 | return T(d * std::pow(10.0, 10.0 * exponent)); 01811 | } 01812 | else 01813 | { 01814 | d /= T(fract10[ -std::numeric_limits<T>::min_exponent10]); 01815 | return T(d / fract10[-exponent + std::numeric_limits<T>::min_exponent10]); 01816 | } 01817 | } 01818 | 01819 | template <typename Iterator, typename T> 01820 | inline bool string_to_type_converter_impl_ref(Iterator& itr, const Iterator end, T& result) 01821 | { 01822 | if (itr == end) 01823 | return false; 01824 | 01825 | const bool negative = ('-' == (*itr)); 01826 | 01827 | if (negative || ('+' == (*itr))) 01828 | { 01829 | if (end == ++itr) 01830 | return false; 01831 | } 01832 | 01833 | static const uchar_t zero = static_cast<uchar_t>('0'); 01834 | 01835 | while ((end != itr) && (zero == (*itr))) ++itr; 01836 | 01837 | bool return_result = true; 01838 | unsigned int digit = 0; 01839 | const std::size_t length = static_cast<std::size_t>(std::distance(itr,end)); 01840 | 01841 | if (length <= 4) 01842 | { 01843 | switch (length) 01844 | { 01845 | #ifdef exprtk_use_lut 01846 | 01847 | #define exprtk_process_digit \ 01848 | if ((digit = details::digit_table[(int)*itr++]) < 10) \ 01849 | result = result * 10 + (digit); \ 01850 | else \ 01851 | { \ 01852 | return_result = false; \ 01853 | break; \ 01854 | } \ 01855 | exprtk_fallthrough \ 01856 | 01857 | #else 01858 | 01859 | #define exprtk_process_digit \ 01860 | if ((digit = (*itr++ - zero)) < 10) \ 01861 | result = result * T(10) + digit; \ 01862 | else \ 01863 | { \ 01864 | return_result = false; \ 01865 | break; \ 01866 | } \ 01867 | exprtk_fallthrough \ 01868 | 01869 | #endif 01870 | 01871 | case 4 : exprtk_process_digit 01872 | case 3 : exprtk_process_digit 01873 | case 2 : exprtk_process_digit 01874 | case 1 : if ((digit = (*itr - zero))>= 10) 01875 | { 01876 | digit = 0; 01877 | return_result = false; 01878 | } 01879 | 01880 | #undef exprtk_process_digit 01881 | } 01882 | } 01883 | else 01884 | return_result = false; 01885 | 01886 | if (length && return_result) 01887 | { 01888 | result = result * 10 + static_cast<T>(digit); 01889 | ++itr; 01890 | } 01891 | 01892 | result = negative ? -result : result; 01893 | return return_result; 01894 | } 01895 | 01896 | template <typename Iterator, typename T> 01897 | static inline bool parse_nan(Iterator& itr, const Iterator end, T& t) 01898 | { 01899 | typedef typename std::iterator_traits<Iterator>::value_type type; 01900 | 01901 | static const std::size_t nan_length = 3; 01902 | 01903 | if (std::distance(itr,end) != static_cast<int>(nan_length)) 01904 | return false; 01905 | 01906 | if (static_cast<type>('n') == (*itr)) 01907 | { 01908 | if ( 01909 | (static_cast<type>('a') != *(itr + 1)) || 01910 | (static_cast<type>('n') != *(itr + 2)) 01911 | ) 01912 | { 01913 | return false; 01914 | } 01915 | } 01916 | else if ( 01917 | (static_cast<type>('A') != *(itr + 1)) || 01918 | (static_cast<type>('N') != *(itr + 2)) 01919 | ) 01920 | { 01921 | return false; 01922 | } 01923 | 01924 | t = std::numeric_limits<T>::quiet_NaN(); 01925 | 01926 | return true; 01927 | } 01928 | 01929 | template <typename Iterator, typename T> 01930 | static inline bool parse_inf(Iterator& itr, const Iterator end, T& t, const bool negative) 01931 | { 01932 | static const char_t inf_uc[] = "INFINITY" 01933 | static const char_t inf_lc[] = "infinity" 01934 | static const std::size_t inf_length = 8; 01935 | 01936 | const std::size_t length = static_cast<std::size_t>(std::distance(itr,end)); 01937 | 01938 | if ((3 != length) && (inf_length != length)) 01939 | return false; 01940 | 01941 | char_cptr inf_itr = ('i' == (*itr)) ? inf_lc : inf_uc; 01942 | 01943 | while (end != itr) 01944 | { 01945 | if (*inf_itr == static_cast<char_t>(*itr)) 01946 | { 01947 | ++itr; 01948 | ++inf_itr; 01949 | continue; 01950 | } 01951 | else 01952 | return false; 01953 | } 01954 | 01955 | if (negative) 01956 | t = -std::numeric_limits<T>::infinity(); 01957 | else 01958 | t = std::numeric_limits<T>::infinity(); 01959 | 01960 | return true; 01961 | } 01962 | 01963 | template <typename T> 01964 | inline bool valid_exponent(const int exponent, numeric::details::real_type_tag) 01965 | { 01966 | using namespace details::numeric; 01967 | return (numeric_info<T>::min_exp <= exponent) && (exponent <= numeric_info<T>::max_exp); 01968 | } 01969 | 01970 | template <typename Iterator, typename T> 01971 | inline bool string_to_real(Iterator& itr_external, const Iterator end, T& t, numeric::details::real_type_tag) 01972 | { 01973 | if (end == itr_external) return false; 01974 | 01975 | Iterator itr = itr_external; 01976 | 01977 | T d = T(0); 01978 | 01979 | const bool negative = ('-' == (*itr)); 01980 | 01981 | if (negative || '+' == (*itr)) 01982 | { 01983 | if (end == ++itr) 01984 | return false; 01985 | } 01986 | 01987 | bool instate = false; 01988 | 01989 | static const char_t zero = static_cast<uchar_t>('0'); 01990 | 01991 | #define parse_digit_1(d) \ 01992 | if ((digit = (*itr - zero)) < 10) \ 01993 | { d = d * T(10) + digit; } \ 01994 | else \ 01995 | { break; } \ 01996 | if (end == ++itr) break; \ 01997 | 01998 | #define parse_digit_2(d) \ 01999 | if ((digit = (*itr - zero)) < 10) \ 02000 | { d = d * T(10) + digit; } \ 02001 | else \ 02002 | { break; } \ 02003 | ++itr; \ 02004 | 02005 | if ('.' != (*itr)) 02006 | { 02007 | const Iterator curr = itr; 02008 | 02009 | while ((end != itr) && (zero == (*itr))) ++itr; 02010 | 02011 | while (end != itr) 02012 | { 02013 | unsigned int digit; 02014 | parse_digit_1(d) 02015 | parse_digit_1(d) 02016 | parse_digit_2(d) 02017 | } 02018 | 02019 | if (curr != itr) instate = true; 02020 | } 02021 | 02022 | int exponent = 0; 02023 | 02024 | if (end != itr) 02025 | { 02026 | if ('.' == (*itr)) 02027 | { 02028 | const Iterator curr = ++itr; 02029 | T tmp_d = T(0); 02030 | 02031 | while (end != itr) 02032 | { 02033 | unsigned int digit; 02034 | parse_digit_1(tmp_d) 02035 | parse_digit_1(tmp_d) 02036 | parse_digit_2(tmp_d) 02037 | } 02038 | 02039 | if (curr != itr) 02040 | { 02041 | instate = true; 02042 | 02043 | const int frac_exponent = static_cast<int>(-std::distance(curr, itr)); 02044 | 02045 | if (!valid_exponent<T>(frac_exponent, numeric::details::real_type_tag())) 02046 | return false; 02047 | 02048 | d += compute_pow10(tmp_d, frac_exponent); 02049 | } 02050 | 02051 | #undef parse_digit_1 02052 | #undef parse_digit_2 02053 | } 02054 | 02055 | if (end != itr) 02056 | { 02057 | typename std::iterator_traits<Iterator>::value_type c = (*itr); 02058 | 02059 | if (('e' == c) || ('E' == c)) 02060 | { 02061 | int exp = 0; 02062 | 02063 | if (!details::string_to_type_converter_impl_ref(++itr, end, exp)) 02064 | { 02065 | if (end == itr) 02066 | return false; 02067 | else 02068 | c = (*itr); 02069 | } 02070 | 02071 | exponent += exp; 02072 | } 02073 | 02074 | if (end != itr) 02075 | { 02076 | if (('f' == c) || ('F' == c) || ('l' == c) || ('L' == c)) 02077 | ++itr; 02078 | else if ('#' == c) 02079 | { 02080 | if (end == ++itr) 02081 | return false; 02082 | else if (('I' <= (*itr)) && ((*itr) <= 'n')) 02083 | { 02084 | if (('i' == (*itr)) || ('I' == (*itr))) 02085 | { 02086 | return parse_inf(itr, end, t, negative); 02087 | } 02088 | else if (('n' == (*itr)) || ('N' == (*itr))) 02089 | { 02090 | return parse_nan(itr, end, t); 02091 | } 02092 | else 02093 | return false; 02094 | } 02095 | else 02096 | return false; 02097 | } 02098 | else if (('I' <= (*itr)) && ((*itr) <= 'n')) 02099 | { 02100 | if (('i' == (*itr)) || ('I' == (*itr))) 02101 | { 02102 | return parse_inf(itr, end, t, negative); 02103 | } 02104 | else if (('n' == (*itr)) || ('N' == (*itr))) 02105 | { 02106 | return parse_nan(itr, end, t); 02107 | } 02108 | else 02109 | return false; 02110 | } 02111 | else 02112 | return false; 02113 | } 02114 | } 02115 | } 02116 | 02117 | if ((end != itr) || (!instate)) 02118 | return false; 02119 | else if (!valid_exponent<T>(exponent, numeric::details::real_type_tag())) 02120 | return false; 02121 | else if (exponent) 02122 | d = compute_pow10(d,exponent); 02123 | 02124 | t = static_cast<T>((negative) ? -d : d); 02125 | return true; 02126 | } 02127 | 02128 | template <typename T> 02129 | inline bool string_to_real(const std::string& s, T& t) 02130 | { 02131 | const typename numeric::details::number_type<T>::type num_type; 02132 | 02133 | char_cptr begin = s.data(); 02134 | char_cptr end = s.data() + s.size(); 02135 | 02136 | return string_to_real(begin, end, t, num_type); 02137 | } 02138 | 02139 | template <typename T> 02140 | struct functor_t 02141 | { 02142 | /* 02143 | Note: The following definitions for Type, may require tweaking 02144 | based on the compiler and target architecture. The benchmark 02145 | should provide enough information to make the right choice. 02146 | */ 02147 | //typedef T Type; 02148 | //typedef const T Type; 02149 | typedef const T& Type; 02150 | typedef T& RefType; 02151 | typedef T (*qfunc_t)(Type t0, Type t1, Type t2, Type t3); 02152 | typedef T (*tfunc_t)(Type t0, Type t1, Type t2); 02153 | typedef T (*bfunc_t)(Type t0, Type t1); 02154 | typedef T (*ufunc_t)(Type t0); 02155 | }; 02156 | 02157 | } // namespace details 02158 | 02159 | struct loop_runtime_check 02160 | { 02161 | enum loop_types 02162 | { 02163 | e_invalid = 0, 02164 | e_for_loop = 1, 02165 | e_while_loop = 2, 02166 | e_repeat_until_loop = 4, 02167 | e_all_loops = 7 02168 | }; 02169 | 02170 | enum violation_type 02171 | { 02172 | e_unknown = 0, 02173 | e_iteration_count = 1, 02174 | e_timeout = 2 02175 | }; 02176 | 02177 | loop_types loop_set; 02178 | 02179 | loop_runtime_check() 02180 | : loop_set(e_invalid) 02181 | , max_loop_iterations(0) 02182 | {} 02183 | 02184 | details::_uint64_t max_loop_iterations; 02185 | 02186 | struct violation_context 02187 | { 02188 | loop_types loop; 02189 | violation_type violation; 02190 | details::_uint64_t iteration_count; 02191 | }; 02192 | 02193 | virtual bool check() 02194 | { 02195 | return true; 02196 | } 02197 | 02198 | virtual void handle_runtime_violation(const violation_context&) 02199 | { 02200 | throw std::runtime_error("ExprTk Loop runtime violation."); 02201 | } 02202 | 02203 | virtual ~loop_runtime_check() 02204 | {} 02205 | }; 02206 | 02207 | typedef loop_runtime_check* loop_runtime_check_ptr; 02208 | 02209 | struct vector_access_runtime_check 02210 | { 02211 | struct violation_context 02212 | { 02213 | void* base_ptr; 02214 | void* end_ptr; 02215 | void* access_ptr; 02216 | std::size_t type_size; 02217 | }; 02218 | 02219 | virtual ~vector_access_runtime_check() 02220 | {} 02221 | 02222 | virtual bool handle_runtime_violation(violation_context& /*context*/) 02223 | { 02224 | throw std::runtime_error("ExprTk runtime vector access violation."); 02225 | #if !defined(_MSC_VER) && !defined(__NVCOMPILER) 02226 | return false; 02227 | #endif 02228 | } 02229 | }; 02230 | 02231 | typedef vector_access_runtime_check* vector_access_runtime_check_ptr; 02232 | 02233 | struct assert_check 02234 | { 02235 | struct assert_context 02236 | { 02237 | std::string condition; 02238 | std::string message; 02239 | std::string id; 02240 | std::size_t offet; 02241 | }; 02242 | 02243 | virtual ~assert_check() 02244 | {} 02245 | 02246 | virtual void handle_assert(const assert_context& /*context*/) 02247 | {} 02248 | }; 02249 | 02250 | typedef assert_check* assert_check_ptr; 02251 | 02252 | struct compilation_check 02253 | { 02254 | struct compilation_context 02255 | { 02256 | std::string error_message; 02257 | }; 02258 | 02259 | virtual bool continue_compilation(compilation_context& /*context*/) = 0; 02260 | 02261 | virtual ~compilation_check() 02262 | {} 02263 | }; 02264 | 02265 | typedef compilation_check* compilation_check_ptr; 02266 | 02267 | namespace lexer 02268 | { 02269 | struct token 02270 | { 02271 | enum token_type 02272 | { 02273 | e_none = 0, e_error = 1, e_err_symbol = 2, 02274 | e_err_number = 3, e_err_string = 4, e_err_sfunc = 5, 02275 | e_eof = 6, e_number = 7, e_symbol = 8, 02276 | e_string = 9, e_assign = 10, e_addass = 11, 02277 | e_subass = 12, e_mulass = 13, e_divass = 14, 02278 | e_modass = 15, e_shr = 16, e_shl = 17, 02279 | e_lte = 18, e_ne = 19, e_gte = 20, 02280 | e_swap = 21, e_lt = '<', e_gt = '>', 02281 | e_eq = '=', e_rbracket = ')', e_lbracket = '(', 02282 | e_rsqrbracket = ']', e_lsqrbracket = '[', e_rcrlbracket = '}', 02283 | e_lcrlbracket = '{', e_comma = ',', e_add = '+', 02284 | e_sub = '-', e_div = '/', e_mul = '*', 02285 | e_mod = '%', e_pow = '^', e_colon = ':', 02286 | e_ternary = '?' 02287 | }; 02288 | 02289 | token() 02290 | : type(e_none) 02291 | , value("") 02292 | , position(std::numeric_limits<std::size_t>::max()) 02293 | {} 02294 | 02295 | void clear() 02296 | { 02297 | type = e_none; 02298 | value = "" 02299 | position = std::numeric_limits<std::size_t>::max(); 02300 | } 02301 | 02302 | template <typename Iterator> 02303 | inline token& set_operator(const token_type tt, 02304 | const Iterator begin, const Iterator end, 02305 | const Iterator base_begin = Iterator(0)) 02306 | { 02307 | type = tt; 02308 | value.assign(begin,end); 02309 | if (base_begin) 02310 | position = static_cast<std::size_t>(std::distance(base_begin,begin)); 02311 | return (*this); 02312 | } 02313 | 02314 | template <typename Iterator> 02315 | inline token& set_symbol(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0)) 02316 | { 02317 | type = e_symbol; 02318 | value.assign(begin,end); 02319 | if (base_begin) 02320 | position = static_cast<std::size_t>(std::distance(base_begin,begin)); 02321 | return (*this); 02322 | } 02323 | 02324 | template <typename Iterator> 02325 | inline token& set_numeric(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0)) 02326 | { 02327 | type = e_number; 02328 | value.assign(begin,end); 02329 | if (base_begin) 02330 | position = static_cast<std::size_t>(std::distance(base_begin,begin)); 02331 | return (*this); 02332 | } 02333 | 02334 | template <typename Iterator> 02335 | inline token& set_string(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0)) 02336 | { 02337 | type = e_string; 02338 | value.assign(begin,end); 02339 | if (base_begin) 02340 | position = static_cast<std::size_t>(std::distance(base_begin,begin)); 02341 | return (*this); 02342 | } 02343 | 02344 | inline token& set_string(const std::string& s, const std::size_t p) 02345 | { 02346 | type = e_string; 02347 | value = s; 02348 | position = p; 02349 | return (*this); 02350 | } 02351 | 02352 | template <typename Iterator> 02353 | inline token& set_error(const token_type et, 02354 | const Iterator begin, const Iterator end, 02355 | const Iterator base_begin = Iterator(0)) 02356 | { 02357 | if ( 02358 | (e_error == et) || 02359 | (e_err_symbol == et) || 02360 | (e_err_number == et) || 02361 | (e_err_string == et) || 02362 | (e_err_sfunc == et) 02363 | ) 02364 | { 02365 | type = et; 02366 | } 02367 | else 02368 | type = e_error; 02369 | 02370 | value.assign(begin,end); 02371 | 02372 | if (base_begin) 02373 | position = static_cast<std::size_t>(std::distance(base_begin,begin)); 02374 | 02375 | return (*this); 02376 | } 02377 | 02378 | static inline std::string to_str(token_type t) 02379 | { 02380 | switch (t) 02381 | { 02382 | case e_none : return "NONE" 02383 | case e_error : return "ERROR" 02384 | case e_err_symbol : return "ERROR_SYMBOL" 02385 | case e_err_number : return "ERROR_NUMBER" 02386 | case e_err_string : return "ERROR_STRING" 02387 | case e_eof : return "EOF" 02388 | case e_number : return "NUMBER" 02389 | case e_symbol : return "SYMBOL" 02390 | case e_string : return "STRING" 02391 | case e_assign : return ":=" 02392 | case e_addass : return "+=" 02393 | case e_subass : return "-=" 02394 | case e_mulass : return "*=" 02395 | case e_divass : return "/=" 02396 | case e_modass : return "%=" 02397 | case e_shr : return ">>" 02398 | case e_shl : return "<<" 02399 | case e_lte : return "<=" 02400 | case e_ne : return "!=" 02401 | case e_gte : return ">=" 02402 | case e_lt : return "<" 02403 | case e_gt : return ">" 02404 | case e_eq : return "=" 02405 | case e_rbracket : return ")" 02406 | case e_lbracket : return "(" 02407 | case e_rsqrbracket : return "]" 02408 | case e_lsqrbracket : return "[" 02409 | case e_rcrlbracket : return "}" 02410 | case e_lcrlbracket : return "{" 02411 | case e_comma : return "," 02412 | case e_add : return "+" 02413 | case e_sub : return "-" 02414 | case e_div : return "/" 02415 | case e_mul : return "*" 02416 | case e_mod : return "%" 02417 | case e_pow : return "^" 02418 | case e_colon : return ":" 02419 | case e_ternary : return "?" 02420 | case e_swap : return "<=>" 02421 | default : return "UNKNOWN" 02422 | } 02423 | } 02424 | 02425 | static inline std::string seperator_to_str(const token_type t) 02426 | { 02427 | switch (t) 02428 | { 02429 | case e_comma : return "," 02430 | case e_colon : return ":" 02431 | case e_eof : return "" 02432 | default : return "UNKNOWN" 02433 | } 02434 | 02435 | #if !defined(_MSC_VER) && !defined(__NVCOMPILER) 02436 | return "UNKNOWN" 02437 | #endif 02438 | } 02439 | 02440 | inline bool is_error() const 02441 | { 02442 | return (e_error == type) || 02443 | (e_err_symbol == type) || 02444 | (e_err_number == type) || 02445 | (e_err_string == type) || 02446 | (e_err_sfunc == type) ; 02447 | } 02448 | 02449 | token_type type; 02450 | std::string value; 02451 | std::size_t position; 02452 | }; 02453 | 02454 | class generator 02455 | { 02456 | public: 02457 | 02458 | typedef token token_t; 02459 | typedef std::vector<token_t> token_list_t; 02460 | typedef token_list_t::iterator token_list_itr_t; 02461 | typedef details::char_t char_t; 02462 | 02463 | generator() 02464 | : base_itr_(0) 02465 | , s_itr_ (0) 02466 | , s_end_ (0) 02467 | { 02468 | clear(); 02469 | } 02470 | 02471 | inline void clear() 02472 | { 02473 | base_itr_ = 0; 02474 | s_itr_ = 0; 02475 | s_end_ = 0; 02476 | token_list_.clear(); 02477 | token_itr_ = token_list_.end(); 02478 | store_token_itr_ = token_list_.end(); 02479 | } 02480 | 02481 | inline bool process(const std::string& str) 02482 | { 02483 | base_itr_ = str.data(); 02484 | s_itr_ = str.data(); 02485 | s_end_ = str.data() + str.size(); 02486 | 02487 | eof_token_.set_operator(token_t::e_eof, s_end_, s_end_, base_itr_); 02488 | token_list_.clear(); 02489 | 02490 | while (!is_end(s_itr_)) 02491 | { 02492 | scan_token(); 02493 | 02494 | if (!token_list_.empty() && token_list_.back().is_error()) 02495 | return false; 02496 | } 02497 | 02498 | return true; 02499 | } 02500 | 02501 | inline bool empty() const 02502 | { 02503 | return token_list_.empty(); 02504 | } 02505 | 02506 | inline std::size_t size() const 02507 | { 02508 | return token_list_.size(); 02509 | } 02510 | 02511 | inline void begin() 02512 | { 02513 | token_itr_ = token_list_.begin(); 02514 | store_token_itr_ = token_list_.begin(); 02515 | } 02516 | 02517 | inline void store() 02518 | { 02519 | store_token_itr_ = token_itr_; 02520 | } 02521 | 02522 | inline void restore() 02523 | { 02524 | token_itr_ = store_token_itr_; 02525 | } 02526 | 02527 | inline token_t& next_token() 02528 | { 02529 | if (token_list_.end() != token_itr_) 02530 | { 02531 | return *token_itr_++; 02532 | } 02533 | else 02534 | return eof_token_; 02535 | } 02536 | 02537 | inline token_t& peek_next_token() 02538 | { 02539 | if (token_list_.end() != token_itr_) 02540 | { 02541 | return *token_itr_; 02542 | } 02543 | else 02544 | return eof_token_; 02545 | } 02546 | 02547 | inline token_t& operator[](const std::size_t& index) 02548 | { 02549 | if (index < token_list_.size()) 02550 | { 02551 | return token_list_[index]; 02552 | } 02553 | else 02554 | return eof_token_; 02555 | } 02556 | 02557 | inline token_t operator[](const std::size_t& index) const 02558 | { 02559 | if (index < token_list_.size()) 02560 | { 02561 | return token_list_[index]; 02562 | } 02563 | else 02564 | return eof_token_; 02565 | } 02566 | 02567 | inline bool finished() const 02568 | { 02569 | return (token_list_.end() == token_itr_); 02570 | } 02571 | 02572 | inline void insert_front(token_t::token_type tk_type) 02573 | { 02574 | if ( 02575 | !token_list_.empty() && 02576 | (token_list_.end() != token_itr_) 02577 | ) 02578 | { 02579 | token_t t = *token_itr_; 02580 | 02581 | t.type = tk_type; 02582 | token_itr_ = token_list_.insert(token_itr_,t); 02583 | } 02584 | } 02585 | 02586 | inline std::string substr(const std::size_t& begin, const std::size_t& end) const 02587 | { 02588 | const details::char_cptr begin_itr = ((base_itr_ + begin) < s_end_) ? (base_itr_ + begin) : s_end_; 02589 | const details::char_cptr end_itr = ((base_itr_ + end ) < s_end_) ? (base_itr_ + end ) : s_end_; 02590 | 02591 | return std::string(begin_itr,end_itr); 02592 | } 02593 | 02594 | inline std::string remaining() const 02595 | { 02596 | if (finished()) 02597 | return "" 02598 | else if (token_list_.begin() != token_itr_) 02599 | return std::string(base_itr_ + (token_itr_ - 1)->position, s_end_); 02600 | else 02601 | return std::string(base_itr_ + token_itr_->position, s_end_); 02602 | } 02603 | 02604 | private: 02605 | 02606 | inline bool is_end(details::char_cptr itr) const 02607 | { 02608 | return (s_end_ == itr); 02609 | } 02610 | 02611 | #ifndef exprtk_disable_comments 02612 | inline bool is_comment_start(details::char_cptr itr) const 02613 | { 02614 | const char_t c0 = *(itr + 0); 02615 | const char_t c1 = *(itr + 1); 02616 | 02617 | if ('#' == c0) 02618 | return true; 02619 | else if (!is_end(itr + 1)) 02620 | { 02621 | if (('/' == c0) && ('/' == c1)) return true; 02622 | if (('/' == c0) && ('*' == c1)) return true; 02623 | } 02624 | return false; 02625 | } 02626 | #else 02627 | inline bool is_comment_start(details::char_cptr) const 02628 | { 02629 | return false; 02630 | } 02631 | #endif 02632 | 02633 | inline void skip_whitespace() 02634 | { 02635 | while (!is_end(s_itr_) && details::is_whitespace(*s_itr_)) 02636 | { 02637 | ++s_itr_; 02638 | } 02639 | } 02640 | 02641 | inline void skip_comments() 02642 | { 02643 | #ifndef exprtk_disable_comments 02644 | // The following comment styles are supported: 02645 | // 1. // .... \n 02646 | // 2. # .... \n 02647 | // 3. /* .... */ 02648 | struct test 02649 | { 02650 | static inline bool comment_start(const char_t c0, const char_t c1, int& mode, int& incr) 02651 | { 02652 | mode = 0; 02653 | if ('#' == c0) { mode = 1; incr = 1; } 02654 | else if ('/' == c0) 02655 | { 02656 | if ('/' == c1) { mode = 1; incr = 2; } 02657 | else if ('*' == c1) { mode = 2; incr = 2; } 02658 | } 02659 | return (0 != mode); 02660 | } 02661 | 02662 | static inline bool comment_end(const char_t c0, const char_t c1, int& mode) 02663 | { 02664 | if ( 02665 | ((1 == mode) && ('\n' == c0)) || 02666 | ((2 == mode) && ( '*' == c0) && ('/' == c1)) 02667 | ) 02668 | { 02669 | mode = 0; 02670 | return true; 02671 | } 02672 | else 02673 | return false; 02674 | } 02675 | }; 02676 | 02677 | int mode = 0; 02678 | int increment = 0; 02679 | 02680 | if (is_end(s_itr_)) 02681 | return; 02682 | else if (!test::comment_start(*s_itr_, *(s_itr_ + 1), mode, increment)) 02683 | return; 02684 | 02685 | details::char_cptr cmt_start = s_itr_; 02686 | 02687 | s_itr_ += increment; 02688 | 02689 | while (!is_end(s_itr_)) 02690 | { 02691 | if ((1 == mode) && test::comment_end(*s_itr_, 0, mode)) 02692 | { 02693 | ++s_itr_; 02694 | return; 02695 | } 02696 | 02697 | if ((2 == mode)) 02698 | { 02699 | if (!is_end((s_itr_ + 1)) && test::comment_end(*s_itr_, *(s_itr_ + 1), mode)) 02700 | { 02701 | s_itr_ += 2; 02702 | return; 02703 | } 02704 | } 02705 | 02706 | ++s_itr_; 02707 | } 02708 | 02709 | if (2 == mode) 02710 | { 02711 | token_t t; 02712 | t.set_error(token::e_error, cmt_start, cmt_start + mode, base_itr_); 02713 | token_list_.push_back(t); 02714 | } 02715 | #endif 02716 | } 02717 | 02718 | inline bool next_is_digit(const details::char_cptr itr) const 02719 | { 02720 | return ((itr + 1) != s_end_) && 02721 | details::is_digit(*(itr + 1)); 02722 | } 02723 | 02724 | inline void scan_token() 02725 | { 02726 | const char_t c = *s_itr_; 02727 | 02728 | if (details::is_whitespace(c)) 02729 | { 02730 | skip_whitespace(); 02731 | return; 02732 | } 02733 | else if (is_comment_start(s_itr_)) 02734 | { 02735 | skip_comments(); 02736 | return; 02737 | } 02738 | else if (details::is_operator_char(c)) 02739 | { 02740 | scan_operator(); 02741 | return; 02742 | } 02743 | else if (details::is_letter(c)) 02744 | { 02745 | scan_symbol(); 02746 | return; 02747 | } 02748 | else if (('.' == c) && !next_is_digit(s_itr_)) 02749 | { 02750 | scan_operator(); 02751 | return; 02752 | } 02753 | else if (details::is_digit(c) || ('.' == c)) 02754 | { 02755 | scan_number(); 02756 | return; 02757 | } 02758 | else if ('$' == c) 02759 | { 02760 | scan_special_function(); 02761 | return; 02762 | } 02763 | #ifndef exprtk_disable_string_capabilities 02764 | else if ('\'' == c) 02765 | { 02766 | scan_string(); 02767 | return; 02768 | } 02769 | #endif 02770 | else if ('~' == c) 02771 | { 02772 | token_t t; 02773 | t.set_symbol(s_itr_, s_itr_ + 1, base_itr_); 02774 | token_list_.push_back(t); 02775 | ++s_itr_; 02776 | return; 02777 | } 02778 | else 02779 | { 02780 | token_t t; 02781 | t.set_error(token::e_error, s_itr_, s_itr_ + 2, base_itr_); 02782 | token_list_.push_back(t); 02783 | ++s_itr_; 02784 | } 02785 | } 02786 | 02787 | inline void scan_operator() 02788 | { 02789 | token_t t; 02790 | 02791 | const char_t c0 = s_itr_[0]; 02792 | 02793 | if (!is_end(s_itr_ + 1)) 02794 | { 02795 | const char_t c1 = s_itr_[1]; 02796 | 02797 | if (!is_end(s_itr_ + 2)) 02798 | { 02799 | const char_t c2 = s_itr_[2]; 02800 | 02801 | if ((c0 == '<') && (c1 == '=') && (c2 == '>')) 02802 | { 02803 | t.set_operator(token_t::e_swap, s_itr_, s_itr_ + 3, base_itr_); 02804 | token_list_.push_back(t); 02805 | s_itr_ += 3; 02806 | return; 02807 | } 02808 | } 02809 | 02810 | token_t::token_type ttype = token_t::e_none; 02811 | 02812 | if ((c0 == '<') && (c1 == '=')) ttype = token_t::e_lte; 02813 | else if ((c0 == '>') && (c1 == '=')) ttype = token_t::e_gte; 02814 | else if ((c0 == '<') && (c1 == '>')) ttype = token_t::e_ne; 02815 | else if ((c0 == '!') && (c1 == '=')) ttype = token_t::e_ne; 02816 | else if ((c0 == '=') && (c1 == '=')) ttype = token_t::e_eq; 02817 | else if ((c0 == ':') && (c1 == '=')) ttype = token_t::e_assign; 02818 | else if ((c0 == '<') && (c1 == '<')) ttype = token_t::e_shl; 02819 | else if ((c0 == '>') && (c1 == '>')) ttype = token_t::e_shr; 02820 | else if ((c0 == '+') && (c1 == '=')) ttype = token_t::e_addass; 02821 | else if ((c0 == '-') && (c1 == '=')) ttype = token_t::e_subass; 02822 | else if ((c0 == '*') && (c1 == '=')) ttype = token_t::e_mulass; 02823 | else if ((c0 == '/') && (c1 == '=')) ttype = token_t::e_divass; 02824 | else if ((c0 == '%') && (c1 == '=')) ttype = token_t::e_modass; 02825 | 02826 | if (token_t::e_none != ttype) 02827 | { 02828 | t.set_operator(ttype, s_itr_, s_itr_ + 2, base_itr_); 02829 | token_list_.push_back(t); 02830 | s_itr_ += 2; 02831 | return; 02832 | } 02833 | } 02834 | 02835 | if ('<' == c0) 02836 | t.set_operator(token_t::e_lt , s_itr_, s_itr_ + 1, base_itr_); 02837 | else if ('>' == c0) 02838 | t.set_operator(token_t::e_gt , s_itr_, s_itr_ + 1, base_itr_); 02839 | else if (';' == c0) 02840 | t.set_operator(token_t::e_eof, s_itr_, s_itr_ + 1, base_itr_); 02841 | else if ('&' == c0) 02842 | t.set_symbol(s_itr_, s_itr_ + 1, base_itr_); 02843 | else if ('|' == c0) 02844 | t.set_symbol(s_itr_, s_itr_ + 1, base_itr_); 02845 | else 02846 | t.set_operator(token_t::token_type(c0), s_itr_, s_itr_ + 1, base_itr_); 02847 | 02848 | token_list_.push_back(t); 02849 | ++s_itr_; 02850 | } 02851 | 02852 | inline void scan_symbol() 02853 | { 02854 | details::char_cptr initial_itr = s_itr_; 02855 | 02856 | while (!is_end(s_itr_)) 02857 | { 02858 | if (!details::is_letter_or_digit(*s_itr_) && ('_' != (*s_itr_))) 02859 | { 02860 | if ('.' != (*s_itr_)) 02861 | break; 02862 | /* 02863 | Permit symbols that contain a 'dot' 02864 | Allowed : abc.xyz, a123.xyz, abc.123, abc_.xyz a123_.xyz abc._123 02865 | Disallowed: .abc, abc.<white-space>, abc.<eof>, abc.<operator +,-,*,/...> 02866 | */ 02867 | if ( 02868 | (s_itr_ != initial_itr) && 02869 | !is_end(s_itr_ + 1) && 02870 | !details::is_letter_or_digit(*(s_itr_ + 1)) && 02871 | ('_' != (*(s_itr_ + 1))) 02872 | ) 02873 | break; 02874 | } 02875 | 02876 | ++s_itr_; 02877 | } 02878 | 02879 | token_t t; 02880 | t.set_symbol(initial_itr, s_itr_, base_itr_); 02881 | token_list_.push_back(t); 02882 | } 02883 | 02884 | inline void scan_number() 02885 | { 02886 | /* 02887 | Attempt to match a valid numeric value in one of the following formats: 02888 | (01) 123456 02889 | (02) 123456. 02890 | (03) 123.456 02891 | (04) 123.456e3 02892 | (05) 123.456E3 02893 | (06) 123.456e+3 02894 | (07) 123.456E+3 02895 | (08) 123.456e-3 02896 | (09) 123.456E-3 02897 | (00) .1234 02898 | (11) .1234e3 02899 | (12) .1234E+3 02900 | (13) .1234e+3 02901 | (14) .1234E-3 02902 | (15) .1234e-3 02903 | */ 02904 | 02905 | details::char_cptr initial_itr = s_itr_; 02906 | bool dot_found = false; 02907 | bool e_found = false; 02908 | bool post_e_sign_found = false; 02909 | bool post_e_digit_found = false; 02910 | token_t t; 02911 | 02912 | while (!is_end(s_itr_)) 02913 | { 02914 | if ('.' == (*s_itr_)) 02915 | { 02916 | if (dot_found) 02917 | { 02918 | t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_); 02919 | token_list_.push_back(t); 02920 | 02921 | return; 02922 | } 02923 | 02924 | dot_found = true; 02925 | ++s_itr_; 02926 | 02927 | continue; 02928 | } 02929 | else if ('e' == std::tolower(*s_itr_)) 02930 | { 02931 | const char_t& c = *(s_itr_ + 1); 02932 | 02933 | if (is_end(s_itr_ + 1)) 02934 | { 02935 | t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_); 02936 | token_list_.push_back(t); 02937 | 02938 | return; 02939 | } 02940 | else if ( 02941 | ('+' != c) && 02942 | ('-' != c) && 02943 | !details::is_digit(c) 02944 | ) 02945 | { 02946 | t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_); 02947 | token_list_.push_back(t); 02948 | 02949 | return; 02950 | } 02951 | 02952 | e_found = true; 02953 | ++s_itr_; 02954 | 02955 | continue; 02956 | } 02957 | else if (e_found && details::is_sign(*s_itr_) && !post_e_digit_found) 02958 | { 02959 | if (post_e_sign_found) 02960 | { 02961 | t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_); 02962 | token_list_.push_back(t); 02963 | 02964 | return; 02965 | } 02966 | 02967 | post_e_sign_found = true; 02968 | ++s_itr_; 02969 | 02970 | continue; 02971 | } 02972 | else if (e_found && details::is_digit(*s_itr_)) 02973 | { 02974 | post_e_digit_found = true; 02975 | ++s_itr_; 02976 | 02977 | continue; 02978 | } 02979 | else if (('.' != (*s_itr_)) && !details::is_digit(*s_itr_)) 02980 | break; 02981 | else 02982 | ++s_itr_; 02983 | } 02984 | 02985 | t.set_numeric(initial_itr, s_itr_, base_itr_); 02986 | token_list_.push_back(t); 02987 | 02988 | return; 02989 | } 02990 | 02991 | inline void scan_special_function() 02992 | { 02993 | details::char_cptr initial_itr = s_itr_; 02994 | token_t t; 02995 | 02996 | // $fdd(x,x,x) = at least 11 chars 02997 | if (std::distance(s_itr_,s_end_) < 11) 02998 | { 02999 | t.set_error( 03000 | token::e_err_sfunc, 03001 | initial_itr, std::min(initial_itr + 11, s_end_), 03002 | base_itr_); 03003 | token_list_.push_back(t); 03004 | 03005 | return; 03006 | } 03007 | 03008 | if ( 03009 | !(('$' == *s_itr_) && 03010 | (details::imatch ('f',*(s_itr_ + 1))) && 03011 | (details::is_digit(*(s_itr_ + 2))) && 03012 | (details::is_digit(*(s_itr_ + 3)))) 03013 | ) 03014 | { 03015 | t.set_error( 03016 | token::e_err_sfunc, 03017 | initial_itr, std::min(initial_itr + 4, s_end_), 03018 | base_itr_); 03019 | token_list_.push_back(t); 03020 | 03021 | return; 03022 | } 03023 | 03024 | s_itr_ += 4; // $fdd = 4chars 03025 | 03026 | t.set_symbol(initial_itr, s_itr_, base_itr_); 03027 | token_list_.push_back(t); 03028 | 03029 | return; 03030 | } 03031 | 03032 | #ifndef exprtk_disable_string_capabilities 03033 | inline void scan_string() 03034 | { 03035 | details::char_cptr initial_itr = s_itr_ + 1; 03036 | token_t t; 03037 | 03038 | if (std::distance(s_itr_,s_end_) < 2) 03039 | { 03040 | t.set_error(token::e_err_string, s_itr_, s_end_, base_itr_); 03041 | token_list_.push_back(t); 03042 | 03043 | return; 03044 | } 03045 | 03046 | ++s_itr_; 03047 | 03048 | bool escaped_found = false; 03049 | bool escaped = false; 03050 | 03051 | while (!is_end(s_itr_)) 03052 | { 03053 | if (!details::is_valid_string_char(*s_itr_)) 03054 | { 03055 | t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_); 03056 | token_list_.push_back(t); 03057 | 03058 | return; 03059 | } 03060 | else if (!escaped && ('\\' == *s_itr_)) 03061 | { 03062 | escaped_found = true; 03063 | escaped = true; 03064 | ++s_itr_; 03065 | 03066 | continue; 03067 | } 03068 | else if (!escaped) 03069 | { 03070 | if ('\'' == *s_itr_) 03071 | break; 03072 | } 03073 | else if (escaped) 03074 | { 03075 | if ( 03076 | !is_end(s_itr_) && ('0' == *(s_itr_)) && 03077 | ((s_itr_ + 4) <= s_end_) 03078 | ) 03079 | { 03080 | const bool x_separator = ('X' == std::toupper(*(s_itr_ + 1))); 03081 | 03082 | const bool both_digits = details::is_hex_digit(*(s_itr_ + 2)) && 03083 | details::is_hex_digit(*(s_itr_ + 3)) ; 03084 | 03085 | if (!(x_separator && both_digits)) 03086 | { 03087 | t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_); 03088 | token_list_.push_back(t); 03089 | 03090 | return; 03091 | } 03092 | else 03093 | s_itr_ += 3; 03094 | } 03095 | 03096 | escaped = false; 03097 | } 03098 | 03099 | ++s_itr_; 03100 | } 03101 | 03102 | if (is_end(s_itr_)) 03103 | { 03104 | t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_); 03105 | token_list_.push_back(t); 03106 | 03107 | return; 03108 | } 03109 | 03110 | if (!escaped_found) 03111 | t.set_string(initial_itr, s_itr_, base_itr_); 03112 | else 03113 | { 03114 | std::string parsed_string(initial_itr,s_itr_); 03115 | 03116 | if (!details::cleanup_escapes(parsed_string)) 03117 | { 03118 | t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_); 03119 | token_list_.push_back(t); 03120 | 03121 | return; 03122 | } 03123 | 03124 | t.set_string( 03125 | parsed_string, 03126 | static_cast<std::size_t>(std::distance(base_itr_,initial_itr))); 03127 | } 03128 | 03129 | token_list_.push_back(t); 03130 | ++s_itr_; 03131 | 03132 | return; 03133 | } 03134 | #endif 03135 | 03136 | private: 03137 | 03138 | token_list_t token_list_; 03139 | token_list_itr_t token_itr_; 03140 | token_list_itr_t store_token_itr_; 03141 | token_t eof_token_; 03142 | details::char_cptr base_itr_; 03143 | details::char_cptr s_itr_; 03144 | details::char_cptr s_end_; 03145 | 03146 | friend class token_scanner; 03147 | friend class token_modifier; 03148 | friend class token_inserter; 03149 | friend class token_joiner; 03150 | }; // class generator 03151 | 03152 | class helper_interface 03153 | { 03154 | public: 03155 | 03156 | virtual void init() { } 03157 | virtual void reset() { } 03158 | virtual bool result() { return true; } 03159 | virtual std::size_t process(generator&) { return 0; } 03160 | virtual ~helper_interface() { } 03161 | }; 03162 | 03163 | class token_scanner : public helper_interface 03164 | { 03165 | public: 03166 | 03167 | virtual ~token_scanner() exprtk_override 03168 | {} 03169 | 03170 | explicit token_scanner(const std::size_t& stride) 03171 | : stride_(stride) 03172 | { 03173 | if (stride > 4) 03174 | { 03175 | throw std::invalid_argument("token_scanner() - Invalid stride value"); 03176 | } 03177 | } 03178 | 03179 | inline std::size_t process(generator& g) exprtk_override 03180 | { 03181 | if (g.token_list_.size() >= stride_) 03182 | { 03183 | for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i) 03184 | { 03185 | token t; 03186 | 03187 | switch (stride_) 03188 | { 03189 | case 1 : 03190 | { 03191 | const token& t0 = g.token_list_[i]; 03192 | 03193 | if (!operator()(t0)) 03194 | { 03195 | return 0; 03196 | } 03197 | } 03198 | break; 03199 | 03200 | case 2 : 03201 | { 03202 | const token& t0 = g.token_list_[i ]; 03203 | const token& t1 = g.token_list_[i + 1]; 03204 | 03205 | if (!operator()(t0, t1)) 03206 | { 03207 | return 0; 03208 | } 03209 | } 03210 | break; 03211 | 03212 | case 3 : 03213 | { 03214 | const token& t0 = g.token_list_[i ]; 03215 | const token& t1 = g.token_list_[i + 1]; 03216 | const token& t2 = g.token_list_[i + 2]; 03217 | 03218 | if (!operator()(t0, t1, t2)) 03219 | { 03220 | return 0; 03221 | } 03222 | } 03223 | break; 03224 | 03225 | case 4 : 03226 | { 03227 | const token& t0 = g.token_list_[i ]; 03228 | const token& t1 = g.token_list_[i + 1]; 03229 | const token& t2 = g.token_list_[i + 2]; 03230 | const token& t3 = g.token_list_[i + 3]; 03231 | 03232 | if (!operator()(t0, t1, t2, t3)) 03233 | { 03234 | return 0; 03235 | } 03236 | } 03237 | break; 03238 | } 03239 | } 03240 | } 03241 | 03242 | return 0; 03243 | } 03244 | 03245 | virtual bool operator() (const token&) 03246 | { 03247 | return false; 03248 | } 03249 | 03250 | virtual bool operator() (const token&, const token&) 03251 | { 03252 | return false; 03253 | } 03254 | 03255 | virtual bool operator() (const token&, const token&, const token&) 03256 | { 03257 | return false; 03258 | } 03259 | 03260 | virtual bool operator() (const token&, const token&, const token&, const token&) 03261 | { 03262 | return false; 03263 | } 03264 | 03265 | private: 03266 | 03267 | const std::size_t stride_; 03268 | }; // class token_scanner 03269 | 03270 | class token_modifier : public helper_interface 03271 | { 03272 | public: 03273 | 03274 | inline std::size_t process(generator& g) exprtk_override 03275 | { 03276 | std::size_t changes = 0; 03277 | 03278 | for (std::size_t i = 0; i < g.token_list_.size(); ++i) 03279 | { 03280 | if (modify(g.token_list_[i])) changes++; 03281 | } 03282 | 03283 | return changes; 03284 | } 03285 | 03286 | virtual bool modify(token& t) = 0; 03287 | }; 03288 | 03289 | class token_inserter : public helper_interface 03290 | { 03291 | public: 03292 | 03293 | explicit token_inserter(const std::size_t& stride) 03294 | : stride_(stride) 03295 | { 03296 | if (stride > 5) 03297 | { 03298 | throw std::invalid_argument("token_inserter() - Invalid stride value"); 03299 | } 03300 | } 03301 | 03302 | inline std::size_t process(generator& g) exprtk_override 03303 | { 03304 | if (g.token_list_.empty()) 03305 | return 0; 03306 | else if (g.token_list_.size() < stride_) 03307 | return 0; 03308 | 03309 | std::size_t changes = 0; 03310 | 03311 | typedef std::pair<std::size_t, token> insert_t; 03312 | std::vector<insert_t> insert_list; 03313 | insert_list.reserve(10000); 03314 | 03315 | for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i) 03316 | { 03317 | int insert_index = -1; 03318 | token t; 03319 | 03320 | switch (stride_) 03321 | { 03322 | case 1 : insert_index = insert(g.token_list_[i],t); 03323 | break; 03324 | 03325 | case 2 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], t); 03326 | break; 03327 | 03328 | case 3 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], g.token_list_[i + 2], t); 03329 | break; 03330 | 03331 | 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); 03332 | break; 03333 | 03334 | 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); 03335 | break; 03336 | } 03337 | 03338 | if ((insert_index >= 0) && (insert_index <= (static_cast<int>(stride_) + 1))) 03339 | { 03340 | insert_list.push_back(insert_t(i, t)); 03341 | changes++; 03342 | } 03343 | } 03344 | 03345 | if (!insert_list.empty()) 03346 | { 03347 | generator::token_list_t token_list; 03348 | 03349 | std::size_t insert_index = 0; 03350 | 03351 | for (std::size_t i = 0; i < g.token_list_.size(); ++i) 03352 | { 03353 | token_list.push_back(g.token_list_[i]); 03354 | 03355 | if ( 03356 | (insert_index < insert_list.size()) && 03357 | (insert_list[insert_index].first == i) 03358 | ) 03359 | { 03360 | token_list.push_back(insert_list[insert_index].second); 03361 | insert_index++; 03362 | } 03363 | } 03364 | 03365 | std::swap(g.token_list_,token_list); 03366 | } 03367 | 03368 | return changes; 03369 | } 03370 | 03371 | #define token_inserter_empty_body \ 03372 | { \ 03373 | return -1; \ 03374 | } \ 03375 | 03376 | inline virtual int insert(const token&, token&) 03377 | token_inserter_empty_body 03378 | 03379 | inline virtual int insert(const token&, const token&, token&) 03380 | token_inserter_empty_body 03381 | 03382 | inline virtual int insert(const token&, const token&, const token&, token&) 03383 | token_inserter_empty_body 03384 | 03385 | inline virtual int insert(const token&, const token&, const token&, const token&, token&) 03386 | token_inserter_empty_body 03387 | 03388 | inline virtual int insert(const token&, const token&, const token&, const token&, const token&, token&) 03389 | token_inserter_empty_body 03390 | 03391 | #undef token_inserter_empty_body 03392 | 03393 | private: 03394 | 03395 | const std::size_t stride_; 03396 | }; 03397 | 03398 | class token_joiner : public helper_interface 03399 | { 03400 | public: 03401 | 03402 | explicit token_joiner(const std::size_t& stride) 03403 | : stride_(stride) 03404 | {} 03405 | 03406 | inline std::size_t process(generator& g) exprtk_override 03407 | { 03408 | if (g.token_list_.empty()) 03409 | return 0; 03410 | 03411 | switch (stride_) 03412 | { 03413 | case 2 : return process_stride_2(g); 03414 | case 3 : return process_stride_3(g); 03415 | default : return 0; 03416 | } 03417 | } 03418 | 03419 | virtual bool join(const token&, const token&, token&) { return false; } 03420 | virtual bool join(const token&, const token&, const token&, token&) { return false; } 03421 | 03422 | private: 03423 | 03424 | inline std::size_t process_stride_2(generator& g) 03425 | { 03426 | if (g.token_list_.size() < 2) 03427 | return 0; 03428 | 03429 | std::size_t changes = 0; 03430 | 03431 | generator::token_list_t token_list; 03432 | token_list.reserve(10000); 03433 | 03434 | for (int i = 0; i < static_cast<int>(g.token_list_.size() - 1); ++i) 03435 | { 03436 | token t; 03437 | 03438 | for ( ; ; ) 03439 | { 03440 | if (!join(g[i], g[i + 1], t)) 03441 | { 03442 | token_list.push_back(g[i]); 03443 | break; 03444 | } 03445 | 03446 | token_list.push_back(t); 03447 | 03448 | ++changes; 03449 | 03450 | i += 2; 03451 | 03452 | if (static_cast<std::size_t>(i) >= (g.token_list_.size() - 1)) 03453 | break; 03454 | } 03455 | } 03456 | 03457 | token_list.push_back(g.token_list_.back()); 03458 | 03459 | assert(token_list.size() <= g.token_list_.size()); 03460 | 03461 | std::swap(token_list, g.token_list_); 03462 | 03463 | return changes; 03464 | } 03465 | 03466 | inline std::size_t process_stride_3(generator& g) 03467 | { 03468 | if (g.token_list_.size() < 3) 03469 | return 0; 03470 | 03471 | std::size_t changes = 0; 03472 | 03473 | generator::token_list_t token_list; 03474 | token_list.reserve(10000); 03475 | 03476 | for (int i = 0; i < static_cast<int>(g.token_list_.size() - 2); ++i) 03477 | { 03478 | token t; 03479 | 03480 | for ( ; ; ) 03481 | { 03482 | if (!join(g[i], g[i + 1], g[i + 2], t)) 03483 | { 03484 | token_list.push_back(g[i]); 03485 | break; 03486 | } 03487 | 03488 | token_list.push_back(t); 03489 | 03490 | ++changes; 03491 | 03492 | i += 3; 03493 | 03494 | if (static_cast<std::size_t>(i) >= (g.token_list_.size() - 2)) 03495 | break; 03496 | } 03497 | } 03498 | 03499 | token_list.push_back(*(g.token_list_.begin() + g.token_list_.size() - 2)); 03500 | token_list.push_back(*(g.token_list_.begin() + g.token_list_.size() - 1)); 03501 | 03502 | assert(token_list.size() <= g.token_list_.size()); 03503 | 03504 | std::swap(token_list, g.token_list_); 03505 | 03506 | return changes; 03507 | } 03508 | 03509 | const std::size_t stride_; 03510 | }; 03511 | 03512 | namespace helper 03513 | { 03514 | 03515 | inline void dump(const lexer::generator& generator) 03516 | { 03517 | for (std::size_t i = 0; i < generator.size(); ++i) 03518 | { 03519 | const lexer::token& t = generator[i]; 03520 | printf("Token[%02d] @ %03d %6s --> '%s'\n", 03521 | static_cast<int>(i), 03522 | static_cast<int>(t.position), 03523 | t.to_str(t.type).c_str(), 03524 | t.value.c_str()); 03525 | } 03526 | } 03527 | 03528 | class commutative_inserter : public lexer::token_inserter 03529 | { 03530 | public: 03531 | 03532 | using lexer::token_inserter::insert; 03533 | 03534 | commutative_inserter() 03535 | : lexer::token_inserter(2) 03536 | {} 03537 | 03538 | inline void ignore_symbol(const std::string& symbol) 03539 | { 03540 | ignore_set_.insert(symbol); 03541 | } 03542 | 03543 | inline int insert(const lexer::token& t0, const lexer::token& t1, lexer::token& new_token) exprtk_override 03544 | { 03545 | bool match = false; 03546 | new_token.type = lexer::token::e_mul; 03547 | new_token.value = "*" 03548 | new_token.position = t1.position; 03549 | 03550 | if (t0.type == lexer::token::e_symbol) 03551 | { 03552 | if (ignore_set_.end() != ignore_set_.find(t0.value)) 03553 | { 03554 | return -1; 03555 | } 03556 | else if (!t0.value.empty() && ('$' == t0.value[0])) 03557 | { 03558 | return -1; 03559 | } 03560 | } 03561 | 03562 | if (t1.type == lexer::token::e_symbol) 03563 | { 03564 | if (ignore_set_.end() != ignore_set_.find(t1.value)) 03565 | { 03566 | return -1; 03567 | } 03568 | } 03569 | if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_symbol )) match = true; 03570 | else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lbracket )) match = true; 03571 | else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lcrlbracket)) match = true; 03572 | else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lsqrbracket)) match = true; 03573 | else if ((t0.type == lexer::token::e_symbol ) && (t1.type == lexer::token::e_number )) match = true; 03574 | else if ((t0.type == lexer::token::e_rbracket ) && (t1.type == lexer::token::e_number )) match = true; 03575 | else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_number )) match = true; 03576 | else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_number )) match = true; 03577 | else if ((t0.type == lexer::token::e_rbracket ) && (t1.type == lexer::token::e_symbol )) match = true; 03578 | else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_symbol )) match = true; 03579 | else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_symbol )) match = true; 03580 | else if ((t0.type == lexer::token::e_symbol ) && (t1.type == lexer::token::e_symbol )) match = true; 03581 | 03582 | return (match) ? 1 : -1; 03583 | } 03584 | 03585 | private: 03586 | 03587 | std::set<std::string,details::ilesscompare> ignore_set_; 03588 | }; 03589 | 03590 | class operator_joiner exprtk_final : public token_joiner 03591 | { 03592 | public: 03593 | 03594 | explicit operator_joiner(const std::size_t& stride) 03595 | : token_joiner(stride) 03596 | {} 03597 | 03598 | inline bool join(const lexer::token& t0, const lexer::token& t1, lexer::token& t) exprtk_override 03599 | { 03600 | // ': =' --> ':=' 03601 | if ((t0.type == lexer::token::e_colon) && (t1.type == lexer::token::e_eq)) 03602 | { 03603 | t.type = lexer::token::e_assign; 03604 | t.value = ":=" 03605 | t.position = t0.position; 03606 | 03607 | return true; 03608 | } 03609 | // '+ =' --> '+=' 03610 | else if ((t0.type == lexer::token::e_add) && (t1.type == lexer::token::e_eq)) 03611 | { 03612 | t.type = lexer::token::e_addass; 03613 | t.value = "+=" 03614 | t.position = t0.position; 03615 | 03616 | return true; 03617 | } 03618 | // '- =' --> '-=' 03619 | else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_eq)) 03620 | { 03621 | t.type = lexer::token::e_subass; 03622 | t.value = "-=" 03623 | t.position = t0.position; 03624 | 03625 | return true; 03626 | } 03627 | // '* =' --> '*=' 03628 | else if ((t0.type == lexer::token::e_mul) && (t1.type == lexer::token::e_eq)) 03629 | { 03630 | t.type = lexer::token::e_mulass; 03631 | t.value = "*=" 03632 | t.position = t0.position; 03633 | 03634 | return true; 03635 | } 03636 | // '/ =' --> '/=' 03637 | else if ((t0.type == lexer::token::e_div) && (t1.type == lexer::token::e_eq)) 03638 | { 03639 | t.type = lexer::token::e_divass; 03640 | t.value = "/=" 03641 | t.position = t0.position; 03642 | 03643 | return true; 03644 | } 03645 | // '% =' --> '%=' 03646 | else if ((t0.type == lexer::token::e_mod) && (t1.type == lexer::token::e_eq)) 03647 | { 03648 | t.type = lexer::token::e_modass; 03649 | t.value = "%=" 03650 | t.position = t0.position; 03651 | 03652 | return true; 03653 | } 03654 | // '> =' --> '>=' 03655 | else if ((t0.type == lexer::token::e_gt) && (t1.type == lexer::token::e_eq)) 03656 | { 03657 | t.type = lexer::token::e_gte; 03658 | t.value = ">=" 03659 | t.position = t0.position; 03660 | 03661 | return true; 03662 | } 03663 | // '< =' --> '<=' 03664 | else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_eq)) 03665 | { 03666 | t.type = lexer::token::e_lte; 03667 | t.value = "<=" 03668 | t.position = t0.position; 03669 | 03670 | return true; 03671 | } 03672 | // '= =' --> '==' 03673 | else if ((t0.type == lexer::token::e_eq) && (t1.type == lexer::token::e_eq)) 03674 | { 03675 | t.type = lexer::token::e_eq; 03676 | t.value = "==" 03677 | t.position = t0.position; 03678 | 03679 | return true; 03680 | } 03681 | // '! =' --> '!=' 03682 | else if ((static_cast<details::char_t>(t0.type) == '!') && (t1.type == lexer::token::e_eq)) 03683 | { 03684 | t.type = lexer::token::e_ne; 03685 | t.value = "!=" 03686 | t.position = t0.position; 03687 | 03688 | return true; 03689 | } 03690 | // '< >' --> '<>' 03691 | else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_gt)) 03692 | { 03693 | t.type = lexer::token::e_ne; 03694 | t.value = "<>" 03695 | t.position = t0.position; 03696 | 03697 | return true; 03698 | } 03699 | // '<= >' --> '<=>' 03700 | else if ((t0.type == lexer::token::e_lte) && (t1.type == lexer::token::e_gt)) 03701 | { 03702 | t.type = lexer::token::e_swap; 03703 | t.value = "<=>" 03704 | t.position = t0.position; 03705 | 03706 | return true; 03707 | } 03708 | // '+ -' --> '-' 03709 | else if ((t0.type == lexer::token::e_add) && (t1.type == lexer::token::e_sub)) 03710 | { 03711 | t.type = lexer::token::e_sub; 03712 | t.value = "-" 03713 | t.position = t0.position; 03714 | 03715 | return true; 03716 | } 03717 | // '- +' --> '-' 03718 | else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_add)) 03719 | { 03720 | t.type = lexer::token::e_sub; 03721 | t.value = "-" 03722 | t.position = t0.position; 03723 | 03724 | return true; 03725 | } 03726 | // '- -' --> '+' 03727 | else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_sub)) 03728 | { 03729 | /* 03730 | Note: May need to reconsider this when wanting to implement 03731 | pre/postfix decrement operator 03732 | */ 03733 | t.type = lexer::token::e_add; 03734 | t.value = "+" 03735 | t.position = t0.position; 03736 | 03737 | return true; 03738 | } 03739 | else 03740 | return false; 03741 | } 03742 | 03743 | inline bool join(const lexer::token& t0, 03744 | const lexer::token& t1, 03745 | const lexer::token& t2, 03746 | lexer::token& t) exprtk_override 03747 | { 03748 | // '[ * ]' --> '[*]' 03749 | if ( 03750 | (t0.type == lexer::token::e_lsqrbracket) && 03751 | (t1.type == lexer::token::e_mul ) && 03752 | (t2.type == lexer::token::e_rsqrbracket) 03753 | ) 03754 | { 03755 | t.type = lexer::token::e_symbol; 03756 | t.value = "[*]" 03757 | t.position = t0.position; 03758 | 03759 | return true; 03760 | } 03761 | else 03762 | return false; 03763 | } 03764 | }; 03765 | 03766 | class bracket_checker exprtk_final : public lexer::token_scanner 03767 | { 03768 | public: 03769 | 03770 | using lexer::token_scanner::operator(); 03771 | 03772 | bracket_checker() 03773 | : token_scanner(1) 03774 | , state_(true) 03775 | {} 03776 | 03777 | bool result() exprtk_override 03778 | { 03779 | if (!stack_.empty()) 03780 | { 03781 | lexer::token t; 03782 | t.value = stack_.top().first; 03783 | t.position = stack_.top().second; 03784 | error_token_ = t; 03785 | state_ = false; 03786 | 03787 | return false; 03788 | } 03789 | else 03790 | return state_; 03791 | } 03792 | 03793 | lexer::token error_token() const 03794 | { 03795 | return error_token_; 03796 | } 03797 | 03798 | void reset() exprtk_override 03799 | { 03800 | // Why? because msvc doesn't support swap properly. 03801 | stack_ = std::stack<std::pair<char,std::size_t> >(); 03802 | state_ = true; 03803 | error_token_.clear(); 03804 | } 03805 | 03806 | bool operator() (const lexer::token& t) exprtk_override 03807 | { 03808 | if ( 03809 | !t.value.empty() && 03810 | (lexer::token::e_string != t.type) && 03811 | (lexer::token::e_symbol != t.type) && 03812 | exprtk::details::is_bracket(t.value[0]) 03813 | ) 03814 | { 03815 | details::char_t c = t.value[0]; 03816 | 03817 | if (t.type == lexer::token::e_lbracket ) stack_.push(std::make_pair(')',t.position)); 03818 | else if (t.type == lexer::token::e_lcrlbracket) stack_.push(std::make_pair('}',t.position)); 03819 | else if (t.type == lexer::token::e_lsqrbracket) stack_.push(std::make_pair(']',t.position)); 03820 | else if (exprtk::details::is_right_bracket(c)) 03821 | { 03822 | if (stack_.empty()) 03823 | { 03824 | state_ = false; 03825 | error_token_ = t; 03826 | 03827 | return false; 03828 | } 03829 | else if (c != stack_.top().first) 03830 | { 03831 | state_ = false; 03832 | error_token_ = t; 03833 | 03834 | return false; 03835 | } 03836 | else 03837 | stack_.pop(); 03838 | } 03839 | } 03840 | 03841 | return true; 03842 | } 03843 | 03844 | private: 03845 | 03846 | bool state_; 03847 | std::stack<std::pair<char,std::size_t> > stack_; 03848 | lexer::token error_token_; 03849 | }; 03850 | 03851 | template <typename T> 03852 | class numeric_checker exprtk_final : public lexer::token_scanner 03853 | { 03854 | public: 03855 | 03856 | using lexer::token_scanner::operator(); 03857 | 03858 | numeric_checker() 03859 | : token_scanner (1) 03860 | , current_index_(0) 03861 | {} 03862 | 03863 | bool result() exprtk_override 03864 | { 03865 | return error_list_.empty(); 03866 | } 03867 | 03868 | void reset() exprtk_override 03869 | { 03870 | error_list_.clear(); 03871 | current_index_ = 0; 03872 | } 03873 | 03874 | bool operator() (const lexer::token& t) exprtk_override 03875 | { 03876 | if (token::e_number == t.type) 03877 | { 03878 | T v; 03879 | 03880 | if (!exprtk::details::string_to_real(t.value,v)) 03881 | { 03882 | error_list_.push_back(current_index_); 03883 | } 03884 | } 03885 | 03886 | ++current_index_; 03887 | 03888 | return true; 03889 | } 03890 | 03891 | std::size_t error_count() const 03892 | { 03893 | return error_list_.size(); 03894 | } 03895 | 03896 | std::size_t error_index(const std::size_t& i) const 03897 | { 03898 | if (i < error_list_.size()) 03899 | return error_list_[i]; 03900 | else 03901 | return std::numeric_limits<std::size_t>::max(); 03902 | } 03903 | 03904 | void clear_errors() 03905 | { 03906 | error_list_.clear(); 03907 | } 03908 | 03909 | private: 03910 | 03911 | std::size_t current_index_; 03912 | std::vector<std::size_t> error_list_; 03913 | }; 03914 | 03915 | class symbol_replacer exprtk_final : public lexer::token_modifier 03916 | { 03917 | private: 03918 | 03919 | typedef std::map<std::string,std::pair<std::string,token::token_type>,details::ilesscompare> replace_map_t; 03920 | 03921 | public: 03922 | 03923 | bool remove(const std::string& target_symbol) 03924 | { 03925 | const replace_map_t::iterator itr = replace_map_.find(target_symbol); 03926 | 03927 | if (replace_map_.end() == itr) 03928 | return false; 03929 | 03930 | replace_map_.erase(itr); 03931 | 03932 | return true; 03933 | } 03934 | 03935 | bool add_replace(const std::string& target_symbol, 03936 | const std::string& replace_symbol, 03937 | const lexer::token::token_type token_type = lexer::token::e_symbol) 03938 | { 03939 | const replace_map_t::iterator itr = replace_map_.find(target_symbol); 03940 | 03941 | if (replace_map_.end() != itr) 03942 | { 03943 | return false; 03944 | } 03945 | 03946 | replace_map_[target_symbol] = std::make_pair(replace_symbol,token_type); 03947 | 03948 | return true; 03949 | } 03950 | 03951 | void clear() 03952 | { 03953 | replace_map_.clear(); 03954 | } 03955 | 03956 | private: 03957 | 03958 | bool modify(lexer::token& t) exprtk_override 03959 | { 03960 | if (lexer::token::e_symbol == t.type) 03961 | { 03962 | if (replace_map_.empty()) 03963 | return false; 03964 | 03965 | const replace_map_t::iterator itr = replace_map_.find(t.value); 03966 | 03967 | if (replace_map_.end() != itr) 03968 | { 03969 | t.value = itr->second.first; 03970 | t.type = itr->second.second; 03971 | 03972 | return true; 03973 | } 03974 | } 03975 | 03976 | return false; 03977 | } 03978 | 03979 | replace_map_t replace_map_; 03980 | }; 03981 | 03982 | class sequence_validator exprtk_final : public lexer::token_scanner 03983 | { 03984 | private: 03985 | 03986 | typedef std::pair<lexer::token::token_type,lexer::token::token_type> token_pair_t; 03987 | typedef std::set<token_pair_t> set_t; 03988 | 03989 | public: 03990 | 03991 | using lexer::token_scanner::operator(); 03992 | 03993 | sequence_validator() 03994 | : lexer::token_scanner(2) 03995 | { 03996 | add_invalid(lexer::token::e_number, lexer::token::e_number); 03997 | add_invalid(lexer::token::e_string, lexer::token::e_string); 03998 | add_invalid(lexer::token::e_number, lexer::token::e_string); 03999 | add_invalid(lexer::token::e_string, lexer::token::e_number); 04000 | 04001 | add_invalid_set1(lexer::token::e_assign ); 04002 | add_invalid_set1(lexer::token::e_shr ); 04003 | add_invalid_set1(lexer::token::e_shl ); 04004 | add_invalid_set1(lexer::token::e_lte ); 04005 | add_invalid_set1(lexer::token::e_ne ); 04006 | add_invalid_set1(lexer::token::e_gte ); 04007 | add_invalid_set1(lexer::token::e_lt ); 04008 | add_invalid_set1(lexer::token::e_gt ); 04009 | add_invalid_set1(lexer::token::e_eq ); 04010 | add_invalid_set1(lexer::token::e_comma ); 04011 | add_invalid_set1(lexer::token::e_add ); 04012 | add_invalid_set1(lexer::token::e_sub ); 04013 | add_invalid_set1(lexer::token::e_div ); 04014 | add_invalid_set1(lexer::token::e_mul ); 04015 | add_invalid_set1(lexer::token::e_mod ); 04016 | add_invalid_set1(lexer::token::e_pow ); 04017 | add_invalid_set1(lexer::token::e_colon ); 04018 | add_invalid_set1(lexer::token::e_ternary); 04019 | } 04020 | 04021 | bool result() exprtk_override 04022 | { 04023 | return error_list_.empty(); 04024 | } 04025 | 04026 | bool operator() (const lexer::token& t0, const lexer::token& t1) exprtk_override 04027 | { 04028 | const set_t::value_type p = std::make_pair(t0.type,t1.type); 04029 | 04030 | if (invalid_bracket_check(t0.type,t1.type)) 04031 | { 04032 | error_list_.push_back(std::make_pair(t0,t1)); 04033 | } 04034 | else if (invalid_comb_.find(p) != invalid_comb_.end()) 04035 | { 04036 | error_list_.push_back(std::make_pair(t0,t1)); 04037 | } 04038 | 04039 | return true; 04040 | } 04041 | 04042 | std::size_t error_count() const 04043 | { 04044 | return error_list_.size(); 04045 | } 04046 | 04047 | std::pair<lexer::token,lexer::token> error(const std::size_t index) 04048 | { 04049 | if (index < error_list_.size()) 04050 | { 04051 | return error_list_[index]; 04052 | } 04053 | else 04054 | { 04055 | static const lexer::token error_token; 04056 | return std::make_pair(error_token,error_token); 04057 | } 04058 | } 04059 | 04060 | void clear_errors() 04061 | { 04062 | error_list_.clear(); 04063 | } 04064 | 04065 | private: 04066 | 04067 | void add_invalid(const lexer::token::token_type base, const lexer::token::token_type t) 04068 | { 04069 | invalid_comb_.insert(std::make_pair(base,t)); 04070 | } 04071 | 04072 | void add_invalid_set1(const lexer::token::token_type t) 04073 | { 04074 | add_invalid(t, lexer::token::e_assign); 04075 | add_invalid(t, lexer::token::e_shr ); 04076 | add_invalid(t, lexer::token::e_shl ); 04077 | add_invalid(t, lexer::token::e_lte ); 04078 | add_invalid(t, lexer::token::e_ne ); 04079 | add_invalid(t, lexer::token::e_gte ); 04080 | add_invalid(t, lexer::token::e_lt ); 04081 | add_invalid(t, lexer::token::e_gt ); 04082 | add_invalid(t, lexer::token::e_eq ); 04083 | add_invalid(t, lexer::token::e_comma ); 04084 | add_invalid(t, lexer::token::e_div ); 04085 | add_invalid(t, lexer::token::e_mul ); 04086 | add_invalid(t, lexer::token::e_mod ); 04087 | add_invalid(t, lexer::token::e_pow ); 04088 | add_invalid(t, lexer::token::e_colon ); 04089 | } 04090 | 04091 | bool invalid_bracket_check(const lexer::token::token_type base, const lexer::token::token_type t) 04092 | { 04093 | if (details::is_right_bracket(static_cast<details::char_t>(base))) 04094 | { 04095 | switch (t) 04096 | { 04097 | case lexer::token::e_assign : return (']' != base); 04098 | case lexer::token::e_string : return (')' != base); 04099 | default : return false; 04100 | } 04101 | } 04102 | else if (details::is_left_bracket(static_cast<details::char_t>(base))) 04103 | { 04104 | if (details::is_right_bracket(static_cast<details::char_t>(t))) 04105 | return false; 04106 | else if (details::is_left_bracket(static_cast<details::char_t>(t))) 04107 | return false; 04108 | else 04109 | { 04110 | switch (t) 04111 | { 04112 | case lexer::token::e_number : return false; 04113 | case lexer::token::e_symbol : return false; 04114 | case lexer::token::e_string : return false; 04115 | case lexer::token::e_add : return false; 04116 | case lexer::token::e_sub : return false; 04117 | case lexer::token::e_colon : return false; 04118 | case lexer::token::e_ternary : return false; 04119 | default : return true ; 04120 | } 04121 | } 04122 | } 04123 | else if (details::is_right_bracket(static_cast<details::char_t>(t))) 04124 | { 04125 | switch (base) 04126 | { 04127 | case lexer::token::e_number : return false; 04128 | case lexer::token::e_symbol : return false; 04129 | case lexer::token::e_string : return false; 04130 | case lexer::token::e_eof : return false; 04131 | case lexer::token::e_colon : return false; 04132 | case lexer::token::e_ternary : return false; 04133 | default : return true ; 04134 | } 04135 | } 04136 | else if (details::is_left_bracket(static_cast<details::char_t>(t))) 04137 | { 04138 | switch (base) 04139 | { 04140 | case lexer::token::e_rbracket : return true; 04141 | case lexer::token::e_rsqrbracket : return true; 04142 | case lexer::token::e_rcrlbracket : return true; 04143 | default : return false; 04144 | } 04145 | } 04146 | 04147 | return false; 04148 | } 04149 | 04150 | set_t invalid_comb_; 04151 | std::vector<std::pair<lexer::token,lexer::token> > error_list_; 04152 | }; 04153 | 04154 | class sequence_validator_3tokens exprtk_final : public lexer::token_scanner 04155 | { 04156 | private: 04157 | 04158 | typedef lexer::token::token_type token_t; 04159 | typedef std::pair<token_t,std::pair<token_t,token_t> > token_triplet_t; 04160 | typedef std::set<token_triplet_t> set_t; 04161 | 04162 | public: 04163 | 04164 | using lexer::token_scanner::operator(); 04165 | 04166 | sequence_validator_3tokens() 04167 | : lexer::token_scanner(3) 04168 | { 04169 | add_invalid(lexer::token::e_number , lexer::token::e_number , lexer::token::e_number); 04170 | add_invalid(lexer::token::e_string , lexer::token::e_string , lexer::token::e_string); 04171 | add_invalid(lexer::token::e_comma , lexer::token::e_comma , lexer::token::e_comma ); 04172 | 04173 | add_invalid(lexer::token::e_add , lexer::token::e_add , lexer::token::e_add ); 04174 | add_invalid(lexer::token::e_sub , lexer::token::e_sub , lexer::token::e_sub ); 04175 | add_invalid(lexer::token::e_div , lexer::token::e_div , lexer::token::e_div ); 04176 | add_invalid(lexer::token::e_mul , lexer::token::e_mul , lexer::token::e_mul ); 04177 | add_invalid(lexer::token::e_mod , lexer::token::e_mod , lexer::token::e_mod ); 04178 | add_invalid(lexer::token::e_pow , lexer::token::e_pow , lexer::token::e_pow ); 04179 | 04180 | add_invalid(lexer::token::e_add , lexer::token::e_sub , lexer::token::e_add ); 04181 | add_invalid(lexer::token::e_sub , lexer::token::e_add , lexer::token::e_sub ); 04182 | add_invalid(lexer::token::e_div , lexer::token::e_mul , lexer::token::e_div ); 04183 | add_invalid(lexer::token::e_mul , lexer::token::e_div , lexer::token::e_mul ); 04184 | add_invalid(lexer::token::e_mod , lexer::token::e_pow , lexer::token::e_mod ); 04185 | add_invalid(lexer::token::e_pow , lexer::token::e_mod , lexer::token::e_pow ); 04186 | } 04187 | 04188 | bool result() exprtk_override 04189 | { 04190 | return error_list_.empty(); 04191 | } 04192 | 04193 | bool operator() (const lexer::token& t0, const lexer::token& t1, const lexer::token& t2) exprtk_override 04194 | { 04195 | const set_t::value_type p = std::make_pair(t0.type,std::make_pair(t1.type,t2.type)); 04196 | 04197 | if (invalid_comb_.find(p) != invalid_comb_.end()) 04198 | { 04199 | error_list_.push_back(std::make_pair(t0,t1)); 04200 | } 04201 | 04202 | return true; 04203 | } 04204 | 04205 | std::size_t error_count() const 04206 | { 04207 | return error_list_.size(); 04208 | } 04209 | 04210 | std::pair<lexer::token,lexer::token> error(const std::size_t index) 04211 | { 04212 | if (index < error_list_.size()) 04213 | { 04214 | return error_list_[index]; 04215 | } 04216 | else 04217 | { 04218 | static const lexer::token error_token; 04219 | return std::make_pair(error_token,error_token); 04220 | } 04221 | } 04222 | 04223 | void clear_errors() 04224 | { 04225 | error_list_.clear(); 04226 | } 04227 | 04228 | private: 04229 | 04230 | void add_invalid(const token_t t0, const token_t t1, const token_t t2) 04231 | { 04232 | invalid_comb_.insert(std::make_pair(t0,std::make_pair(t1,t2))); 04233 | } 04234 | 04235 | set_t invalid_comb_; 04236 | std::vector<std::pair<lexer::token,lexer::token> > error_list_; 04237 | }; 04238 | 04239 | struct helper_assembly 04240 | { 04241 | inline bool register_scanner(lexer::token_scanner* scanner) 04242 | { 04243 | if (token_scanner_list.end() != std::find(token_scanner_list.begin(), 04244 | token_scanner_list.end (), 04245 | scanner)) 04246 | { 04247 | return false; 04248 | } 04249 | 04250 | token_scanner_list.push_back(scanner); 04251 | 04252 | return true; 04253 | } 04254 | 04255 | inline bool register_modifier(lexer::token_modifier* modifier) 04256 | { 04257 | if (token_modifier_list.end() != std::find(token_modifier_list.begin(), 04258 | token_modifier_list.end (), 04259 | modifier)) 04260 | { 04261 | return false; 04262 | } 04263 | 04264 | token_modifier_list.push_back(modifier); 04265 | 04266 | return true; 04267 | } 04268 | 04269 | inline bool register_joiner(lexer::token_joiner* joiner) 04270 | { 04271 | if (token_joiner_list.end() != std::find(token_joiner_list.begin(), 04272 | token_joiner_list.end (), 04273 | joiner)) 04274 | { 04275 | return false; 04276 | } 04277 | 04278 | token_joiner_list.push_back(joiner); 04279 | 04280 | return true; 04281 | } 04282 | 04283 | inline bool register_inserter(lexer::token_inserter* inserter) 04284 | { 04285 | if (token_inserter_list.end() != std::find(token_inserter_list.begin(), 04286 | token_inserter_list.end (), 04287 | inserter)) 04288 | { 04289 | return false; 04290 | } 04291 | 04292 | token_inserter_list.push_back(inserter); 04293 | 04294 | return true; 04295 | } 04296 | 04297 | inline bool run_modifiers(lexer::generator& g) 04298 | { 04299 | error_token_modifier = reinterpret_cast<lexer::token_modifier*>(0); 04300 | 04301 | for (std::size_t i = 0; i < token_modifier_list.size(); ++i) 04302 | { 04303 | lexer::token_modifier& modifier = (*token_modifier_list[i]); 04304 | 04305 | modifier.reset(); 04306 | modifier.process(g); 04307 | 04308 | if (!modifier.result()) 04309 | { 04310 | error_token_modifier = token_modifier_list[i]; 04311 | 04312 | return false; 04313 | } 04314 | } 04315 | 04316 | return true; 04317 | } 04318 | 04319 | inline bool run_joiners(lexer::generator& g) 04320 | { 04321 | error_token_joiner = reinterpret_cast<lexer::token_joiner*>(0); 04322 | 04323 | for (std::size_t i = 0; i < token_joiner_list.size(); ++i) 04324 | { 04325 | lexer::token_joiner& joiner = (*token_joiner_list[i]); 04326 | 04327 | joiner.reset(); 04328 | joiner.process(g); 04329 | 04330 | if (!joiner.result()) 04331 | { 04332 | error_token_joiner = token_joiner_list[i]; 04333 | 04334 | return false; 04335 | } 04336 | } 04337 | 04338 | return true; 04339 | } 04340 | 04341 | inline bool run_inserters(lexer::generator& g) 04342 | { 04343 | error_token_inserter = reinterpret_cast<lexer::token_inserter*>(0); 04344 | 04345 | for (std::size_t i = 0; i < token_inserter_list.size(); ++i) 04346 | { 04347 | lexer::token_inserter& inserter = (*token_inserter_list[i]); 04348 | 04349 | inserter.reset(); 04350 | inserter.process(g); 04351 | 04352 | if (!inserter.result()) 04353 | { 04354 | error_token_inserter = token_inserter_list[i]; 04355 | 04356 | return false; 04357 | } 04358 | } 04359 | 04360 | return true; 04361 | } 04362 | 04363 | inline bool run_scanners(lexer::generator& g) 04364 | { 04365 | error_token_scanner = reinterpret_cast<lexer::token_scanner*>(0); 04366 | 04367 | for (std::size_t i = 0; i < token_scanner_list.size(); ++i) 04368 | { 04369 | lexer::token_scanner& scanner = (*token_scanner_list[i]); 04370 | 04371 | scanner.reset(); 04372 | scanner.process(g); 04373 | 04374 | if (!scanner.result()) 04375 | { 04376 | error_token_scanner = token_scanner_list[i]; 04377 | 04378 | return false; 04379 | } 04380 | } 04381 | 04382 | return true; 04383 | } 04384 | 04385 | std::vector<lexer::token_scanner*> token_scanner_list; 04386 | std::vector<lexer::token_modifier*> token_modifier_list; 04387 | std::vector<lexer::token_joiner*> token_joiner_list; 04388 | std::vector<lexer::token_inserter*> token_inserter_list; 04389 | 04390 | lexer::token_scanner* error_token_scanner; 04391 | lexer::token_modifier* error_token_modifier; 04392 | lexer::token_joiner* error_token_joiner; 04393 | lexer::token_inserter* error_token_inserter; 04394 | }; 04395 | } 04396 | 04397 | class parser_helper 04398 | { 04399 | public: 04400 | 04401 | typedef token token_t; 04402 | typedef generator generator_t; 04403 | 04404 | inline bool init(const std::string& str) 04405 | { 04406 | if (!lexer_.process(str)) 04407 | { 04408 | return false; 04409 | } 04410 | 04411 | lexer_.begin(); 04412 | 04413 | next_token(); 04414 | 04415 | return true; 04416 | } 04417 | 04418 | inline generator_t& lexer() 04419 | { 04420 | return lexer_; 04421 | } 04422 | 04423 | inline const generator_t& lexer() const 04424 | { 04425 | return lexer_; 04426 | } 04427 | 04428 | inline void store_token() 04429 | { 04430 | lexer_.store(); 04431 | store_current_token_ = current_token_; 04432 | } 04433 | 04434 | inline void restore_token() 04435 | { 04436 | lexer_.restore(); 04437 | current_token_ = store_current_token_; 04438 | } 04439 | 04440 | inline void next_token() 04441 | { 04442 | current_token_ = lexer_.next_token(); 04443 | } 04444 | 04445 | inline const token_t& current_token() const 04446 | { 04447 | return current_token_; 04448 | } 04449 | 04450 | inline const token_t& peek_next_token() 04451 | { 04452 | return lexer_.peek_next_token(); 04453 | } 04454 | 04455 | enum token_advance_mode 04456 | { 04457 | e_hold = 0, 04458 | e_advance = 1 04459 | }; 04460 | 04461 | inline void advance_token(const token_advance_mode mode) 04462 | { 04463 | if (e_advance == mode) 04464 | { 04465 | next_token(); 04466 | } 04467 | } 04468 | 04469 | inline bool token_is(const token_t::token_type& ttype, const token_advance_mode mode = e_advance) 04470 | { 04471 | if (current_token().type != ttype) 04472 | { 04473 | return false; 04474 | } 04475 | 04476 | advance_token(mode); 04477 | 04478 | return true; 04479 | } 04480 | 04481 | inline bool token_is(const token_t::token_type& ttype, 04482 | const std::string& value, 04483 | const token_advance_mode mode = e_advance) 04484 | { 04485 | if ( 04486 | (current_token().type != ttype) || 04487 | !exprtk::details::imatch(value,current_token().value) 04488 | ) 04489 | { 04490 | return false; 04491 | } 04492 | 04493 | advance_token(mode); 04494 | 04495 | return true; 04496 | } 04497 | 04498 | inline bool token_is(const std::string& value, 04499 | const token_advance_mode mode = e_advance) 04500 | { 04501 | if (!exprtk::details::imatch(value,current_token().value)) 04502 | { 04503 | return false; 04504 | } 04505 | 04506 | advance_token(mode); 04507 | 04508 | return true; 04509 | } 04510 | 04511 | inline bool token_is_arithmetic_opr(const token_advance_mode mode = e_advance) 04512 | { 04513 | switch (current_token().type) 04514 | { 04515 | case token_t::e_add : 04516 | case token_t::e_sub : 04517 | case token_t::e_div : 04518 | case token_t::e_mul : 04519 | case token_t::e_mod : 04520 | case token_t::e_pow : break; 04521 | default : return false; 04522 | } 04523 | 04524 | advance_token(mode); 04525 | 04526 | return true; 04527 | } 04528 | 04529 | inline bool token_is_ineq_opr(const token_advance_mode mode = e_advance) 04530 | { 04531 | switch (current_token().type) 04532 | { 04533 | case token_t::e_eq : 04534 | case token_t::e_lte : 04535 | case token_t::e_ne : 04536 | case token_t::e_gte : 04537 | case token_t::e_lt : 04538 | case token_t::e_gt : break; 04539 | default : return false; 04540 | } 04541 | 04542 | advance_token(mode); 04543 | 04544 | return true; 04545 | } 04546 | 04547 | inline bool token_is_left_bracket(const token_advance_mode mode = e_advance) 04548 | { 04549 | switch (current_token().type) 04550 | { 04551 | case token_t::e_lbracket : 04552 | case token_t::e_lcrlbracket : 04553 | case token_t::e_lsqrbracket : break; 04554 | default : return false; 04555 | } 04556 | 04557 | advance_token(mode); 04558 | 04559 | return true; 04560 | } 04561 | 04562 | inline bool token_is_right_bracket(const token_advance_mode mode = e_advance) 04563 | { 04564 | switch (current_token().type) 04565 | { 04566 | case token_t::e_rbracket : 04567 | case token_t::e_rcrlbracket : 04568 | case token_t::e_rsqrbracket : break; 04569 | default : return false; 04570 | } 04571 | 04572 | advance_token(mode); 04573 | 04574 | return true; 04575 | } 04576 | 04577 | inline bool token_is_bracket(const token_advance_mode mode = e_advance) 04578 | { 04579 | switch (current_token().type) 04580 | { 04581 | case token_t::e_rbracket : 04582 | case token_t::e_rcrlbracket : 04583 | case token_t::e_rsqrbracket : 04584 | case token_t::e_lbracket : 04585 | case token_t::e_lcrlbracket : 04586 | case token_t::e_lsqrbracket : break; 04587 | default : return false; 04588 | } 04589 | 04590 | advance_token(mode); 04591 | 04592 | return true; 04593 | } 04594 | 04595 | inline bool token_is_loop(const token_advance_mode mode = e_advance) 04596 | { 04597 | return token_is("for" , mode) || 04598 | token_is("while" , mode) || 04599 | token_is("repeat", mode) ; 04600 | } 04601 | 04602 | inline bool peek_token_is(const token_t::token_type& ttype) 04603 | { 04604 | return (lexer_.peek_next_token().type == ttype); 04605 | } 04606 | 04607 | inline bool peek_token_is(const std::string& s) 04608 | { 04609 | return (exprtk::details::imatch(lexer_.peek_next_token().value,s)); 04610 | } 04611 | 04612 | private: 04613 | 04614 | generator_t lexer_; 04615 | token_t current_token_; 04616 | token_t store_current_token_; 04617 | }; 04618 | } 04619 | 04620 | template <typename T> 04621 | class vector_view 04622 | { 04623 | public: 04624 | 04625 | typedef T* data_ptr_t; 04626 | 04627 | vector_view(data_ptr_t data, const std::size_t& size) 04628 | : base_size_(size) 04629 | , size_(size) 04630 | , data_(data) 04631 | , data_ref_(0) 04632 | { 04633 | assert(size_ > 0); 04634 | } 04635 | 04636 | vector_view(const vector_view<T>& vv) 04637 | : base_size_(vv.base_size_) 04638 | , size_(vv.size_) 04639 | , data_(vv.data_) 04640 | , data_ref_(0) 04641 | { 04642 | assert(size_ > 0); 04643 | } 04644 | 04645 | inline void rebase(data_ptr_t data) 04646 | { 04647 | data_ = data; 04648 | 04649 | if (!data_ref_.empty()) 04650 | { 04651 | for (std::size_t i = 0; i < data_ref_.size(); ++i) 04652 | { 04653 | (*data_ref_[i]) = data; 04654 | } 04655 | } 04656 | } 04657 | 04658 | inline data_ptr_t data() const 04659 | { 04660 | return data_; 04661 | } 04662 | 04663 | inline std::size_t base_size() const 04664 | { 04665 | return base_size_; 04666 | } 04667 | 04668 | inline std::size_t size() const 04669 | { 04670 | return size_; 04671 | } 04672 | 04673 | inline const T& operator[](const std::size_t index) const 04674 | { 04675 | assert(index < size_); 04676 | return data_[index]; 04677 | } 04678 | 04679 | inline T& operator[](const std::size_t index) 04680 | { 04681 | assert(index < size_); 04682 | return data_[index]; 04683 | } 04684 | 04685 | void set_ref(data_ptr_t* data_ref) 04686 | { 04687 | data_ref_.push_back(data_ref); 04688 | exprtk_debug(("vector_view::set_ref() - data_ref: %p data_ref_.size(): %d\n", 04689 | reinterpret_cast<void*>(data_ref), 04690 | static_cast<int>(data_ref_.size()))); 04691 | } 04692 | 04693 | void remove_ref(data_ptr_t* data_ref) 04694 | { 04695 | data_ref_.erase( 04696 | std::remove(data_ref_.begin(), data_ref_.end(), data_ref), 04697 | data_ref_.end()); 04698 | exprtk_debug(("vector_view::remove_ref() - data_ref: %p data_ref_.size(): %d\n", 04699 | reinterpret_cast<void*>(data_ref), 04700 | static_cast<int>(data_ref_.size()))); 04701 | } 04702 | 04703 | bool set_size(const std::size_t new_size) 04704 | { 04705 | if ((new_size > 0) && (new_size <= base_size_)) 04706 | { 04707 | size_ = new_size; 04708 | exprtk_debug(("vector_view::set_size() - data_: %p size: %lu\n", 04709 | reinterpret_cast<void*>(data_), 04710 | size_)); 04711 | return true; 04712 | } 04713 | 04714 | exprtk_debug(("vector_view::set_size() - error invalid new_size: %lu base_size: %lu\n", 04715 | new_size, 04716 | base_size_)); 04717 | return false; 04718 | } 04719 | 04720 | private: 04721 | 04722 | const std::size_t base_size_; 04723 | std::size_t size_; 04724 | data_ptr_t data_; 04725 | std::vector<data_ptr_t*> data_ref_; 04726 | }; 04727 | 04728 | template <typename T> 04729 | inline vector_view<T> make_vector_view(T* data, 04730 | const std::size_t size, const std::size_t offset = 0) 04731 | { 04732 | return vector_view<T>(data + offset, size); 04733 | } 04734 | 04735 | template <typename T> 04736 | inline vector_view<T> make_vector_view(std::vector<T>& v, 04737 | const std::size_t size, const std::size_t offset = 0) 04738 | { 04739 | return vector_view<T>(v.data() + offset, size); 04740 | } 04741 | 04742 | template <typename T> class results_context; 04743 | 04744 | template <typename T> 04745 | struct type_store 04746 | { 04747 | enum store_type 04748 | { 04749 | e_unknown, 04750 | e_scalar , 04751 | e_vector , 04752 | e_string 04753 | }; 04754 | 04755 | type_store() 04756 | : data(0) 04757 | , size(0) 04758 | , type(e_unknown) 04759 | {} 04760 | 04761 | union 04762 | { 04763 | void* data; 04764 | T* vec_data; 04765 | }; 04766 | 04767 | std::size_t size; 04768 | store_type type; 04769 | 04770 | class parameter_list 04771 | { 04772 | public: 04773 | 04774 | explicit parameter_list(std::vector<type_store>& pl) 04775 | : parameter_list_(pl) 04776 | {} 04777 | 04778 | inline bool empty() const 04779 | { 04780 | return parameter_list_.empty(); 04781 | } 04782 | 04783 | inline std::size_t size() const 04784 | { 04785 | return parameter_list_.size(); 04786 | } 04787 | 04788 | inline type_store& operator[](const std::size_t& index) 04789 | { 04790 | return parameter_list_[index]; 04791 | } 04792 | 04793 | inline const type_store& operator[](const std::size_t& index) const 04794 | { 04795 | return parameter_list_[index]; 04796 | } 04797 | 04798 | inline type_store& front() 04799 | { 04800 | return parameter_list_[0]; 04801 | } 04802 | 04803 | inline const type_store& front() const 04804 | { 04805 | return parameter_list_[0]; 04806 | } 04807 | 04808 | inline type_store& back() 04809 | { 04810 | return parameter_list_.back(); 04811 | } 04812 | 04813 | inline const type_store& back() const 04814 | { 04815 | return parameter_list_.back(); 04816 | } 04817 | 04818 | private: 04819 | 04820 | std::vector<type_store>& parameter_list_; 04821 | 04822 | friend class results_context<T>; 04823 | }; 04824 | 04825 | template <typename ViewType> 04826 | struct type_view 04827 | { 04828 | typedef type_store<T> type_store_t; 04829 | typedef ViewType value_t; 04830 | 04831 | explicit type_view(type_store_t& ts) 04832 | : ts_(ts) 04833 | , data_(reinterpret_cast<value_t*>(ts_.data)) 04834 | {} 04835 | 04836 | explicit type_view(const type_store_t& ts) 04837 | : ts_(const_cast<type_store_t&>(ts)) 04838 | , data_(reinterpret_cast<value_t*>(ts_.data)) 04839 | {} 04840 | 04841 | inline std::size_t size() const 04842 | { 04843 | return ts_.size; 04844 | } 04845 | 04846 | inline value_t& operator[](const std::size_t& i) 04847 | { 04848 | return data_[i]; 04849 | } 04850 | 04851 | inline const value_t& operator[](const std::size_t& i) const 04852 | { 04853 | return data_[i]; 04854 | } 04855 | 04856 | inline const value_t* begin() const { return data_; } 04857 | inline value_t* begin() { return data_; } 04858 | 04859 | inline const value_t* end() const 04860 | { 04861 | return static_cast<value_t*>(data_ + ts_.size); 04862 | } 04863 | 04864 | inline value_t* end() 04865 | { 04866 | return static_cast<value_t*>(data_ + ts_.size); 04867 | } 04868 | 04869 | type_store_t& ts_; 04870 | value_t* data_; 04871 | }; 04872 | 04873 | typedef type_view<T> vector_view; 04874 | typedef type_view<char> string_view; 04875 | 04876 | struct scalar_view 04877 | { 04878 | typedef type_store<T> type_store_t; 04879 | typedef T value_t; 04880 | 04881 | explicit scalar_view(type_store_t& ts) 04882 | : v_(*reinterpret_cast<value_t*>(ts.data)) 04883 | {} 04884 | 04885 | explicit scalar_view(const type_store_t& ts) 04886 | : v_(*reinterpret_cast<value_t*>(const_cast<type_store_t&>(ts).data)) 04887 | {} 04888 | 04889 | inline value_t& operator() () 04890 | { 04891 | return v_; 04892 | } 04893 | 04894 | inline const value_t& operator() () const 04895 | { 04896 | return v_; 04897 | } 04898 | 04899 | inline operator value_t() const 04900 | { 04901 | return v_; 04902 | } 04903 | 04904 | inline operator value_t() 04905 | { 04906 | return v_; 04907 | } 04908 | 04909 | template <typename IntType> 04910 | inline bool to_int(IntType& i) const 04911 | { 04912 | if (!exprtk::details::numeric::is_integer(v_)) 04913 | return false; 04914 | 04915 | i = static_cast<IntType>(v_); 04916 | 04917 | return true; 04918 | } 04919 | 04920 | template <typename UIntType> 04921 | inline bool to_uint(UIntType& u) const 04922 | { 04923 | if (v_ < T(0)) 04924 | return false; 04925 | else if (!exprtk::details::numeric::is_integer(v_)) 04926 | return false; 04927 | 04928 | u = static_cast<UIntType>(v_); 04929 | 04930 | return true; 04931 | } 04932 | 04933 | T& v_; 04934 | }; 04935 | }; 04936 | 04937 | template <typename StringView> 04938 | inline std::string to_str(const StringView& view) 04939 | { 04940 | return std::string(view.begin(),view.size()); 04941 | } 04942 | 04943 | #ifndef exprtk_disable_return_statement 04944 | namespace details 04945 | { 04946 | template <typename T> class return_node; 04947 | template <typename T> class return_envelope_node; 04948 | } 04949 | #endif 04950 | 04951 | template <typename T> 04952 | class results_context 04953 | { 04954 | public: 04955 | 04956 | typedef type_store<T> type_store_t; 04957 | typedef typename type_store_t::scalar_view scalar_t; 04958 | typedef typename type_store_t::vector_view vector_t; 04959 | typedef typename type_store_t::string_view string_t; 04960 | 04961 | results_context() 04962 | : results_available_(false) 04963 | {} 04964 | 04965 | inline std::size_t count() const 04966 | { 04967 | if (results_available_) 04968 | return parameter_list_.size(); 04969 | else 04970 | return 0; 04971 | } 04972 | 04973 | inline type_store_t& operator[](const std::size_t& index) 04974 | { 04975 | return parameter_list_[index]; 04976 | } 04977 | 04978 | inline const type_store_t& operator[](const std::size_t& index) const 04979 | { 04980 | return parameter_list_[index]; 04981 | } 04982 | 04983 | inline bool get_scalar(const std::size_t& index, T& out) const 04984 | { 04985 | if ( 04986 | (index < parameter_list_.size()) && 04987 | (parameter_list_[index].type == type_store_t::e_scalar) 04988 | ) 04989 | { 04990 | const scalar_t scalar(parameter_list_[index]); 04991 | out = scalar(); 04992 | return true; 04993 | } 04994 | 04995 | return false; 04996 | } 04997 | 04998 | template <typename OutputIterator> 04999 | inline bool get_vector(const std::size_t& index, OutputIterator out_itr) const 05000 | { 05001 | if ( 05002 | (index < parameter_list_.size()) && 05003 | (parameter_list_[index].type == type_store_t::e_vector) 05004 | ) 05005 | { 05006 | const vector_t vector(parameter_list_[index]); 05007 | for (std::size_t i = 0; i < vector.size(); ++i) 05008 | { 05009 | *(out_itr++) = vector[i]; 05010 | } 05011 | 05012 | return true; 05013 | } 05014 | 05015 | return false; 05016 | } 05017 | 05018 | inline bool get_vector(const std::size_t& index, std::vector<T>& out) const 05019 | { 05020 | return get_vector(index,std::back_inserter(out)); 05021 | } 05022 | 05023 | inline bool get_string(const std::size_t& index, std::string& out) const 05024 | { 05025 | if ( 05026 | (index < parameter_list_.size()) && 05027 | (parameter_list_[index].type == type_store_t::e_string) 05028 | ) 05029 | { 05030 | const string_t str(parameter_list_[index]); 05031 | out.assign(str.begin(),str.size()); 05032 | return true; 05033 | } 05034 | 05035 | return false; 05036 | } 05037 | 05038 | private: 05039 | 05040 | inline void clear() 05041 | { 05042 | results_available_ = false; 05043 | } 05044 | 05045 | typedef std::vector<type_store_t> ts_list_t; 05046 | typedef typename type_store_t::parameter_list parameter_list_t; 05047 | 05048 | inline void assign(const parameter_list_t& pl) 05049 | { 05050 | parameter_list_ = pl.parameter_list_; 05051 | results_available_ = true; 05052 | } 05053 | 05054 | bool results_available_; 05055 | ts_list_t parameter_list_; 05056 | 05057 | #ifndef exprtk_disable_return_statement 05058 | friend class details::return_node<T>; 05059 | friend class details::return_envelope_node<T>; 05060 | #endif 05061 | }; 05062 | 05063 | namespace details 05064 | { 05065 | enum operator_type 05066 | { 05067 | e_default , e_null , e_add , e_sub , 05068 | e_mul , e_div , e_mod , e_pow , 05069 | e_atan2 , e_min , e_max , e_avg , 05070 | e_sum , e_prod , e_lt , e_lte , 05071 | e_eq , e_equal , e_ne , e_nequal , 05072 | e_gte , e_gt , e_and , e_nand , 05073 | e_or , e_nor , e_xor , e_xnor , 05074 | e_mand , e_mor , e_scand , e_scor , 05075 | e_shr , e_shl , e_abs , e_acos , 05076 | e_acosh , e_asin , e_asinh , e_atan , 05077 | e_atanh , e_ceil , e_cos , e_cosh , 05078 | e_exp , e_expm1 , e_floor , e_log , 05079 | e_log10 , e_log2 , e_log1p , e_logn , 05080 | e_neg , e_pos , e_round , e_roundn , 05081 | e_root , e_sqrt , e_sin , e_sinc , 05082 | e_sinh , e_sec , e_csc , e_tan , 05083 | e_tanh , e_cot , e_clamp , e_iclamp , 05084 | e_inrange , e_sgn , e_r2d , e_d2r , 05085 | e_d2g , e_g2d , e_hypot , e_notl , 05086 | e_erf , e_erfc , e_ncdf , e_frac , 05087 | e_trunc , e_assign , e_addass , e_subass , 05088 | e_mulass , e_divass , e_modass , e_in , 05089 | e_like , e_ilike , e_multi , e_smulti , 05090 | e_swap , 05091 | 05092 | // Do not add new functions/operators after this point. 05093 | e_sf00 = 1000, e_sf01 = 1001, e_sf02 = 1002, e_sf03 = 1003, 05094 | e_sf04 = 1004, e_sf05 = 1005, e_sf06 = 1006, e_sf07 = 1007, 05095 | e_sf08 = 1008, e_sf09 = 1009, e_sf10 = 1010, e_sf11 = 1011, 05096 | e_sf12 = 1012, e_sf13 = 1013, e_sf14 = 1014, e_sf15 = 1015, 05097 | e_sf16 = 1016, e_sf17 = 1017, e_sf18 = 1018, e_sf19 = 1019, 05098 | e_sf20 = 1020, e_sf21 = 1021, e_sf22 = 1022, e_sf23 = 1023, 05099 | e_sf24 = 1024, e_sf25 = 1025, e_sf26 = 1026, e_sf27 = 1027, 05100 | e_sf28 = 1028, e_sf29 = 1029, e_sf30 = 1030, e_sf31 = 1031, 05101 | e_sf32 = 1032, e_sf33 = 1033, e_sf34 = 1034, e_sf35 = 1035, 05102 | e_sf36 = 1036, e_sf37 = 1037, e_sf38 = 1038, e_sf39 = 1039, 05103 | e_sf40 = 1040, e_sf41 = 1041, e_sf42 = 1042, e_sf43 = 1043, 05104 | e_sf44 = 1044, e_sf45 = 1045, e_sf46 = 1046, e_sf47 = 1047, 05105 | e_sf48 = 1048, e_sf49 = 1049, e_sf50 = 1050, e_sf51 = 1051, 05106 | e_sf52 = 1052, e_sf53 = 1053, e_sf54 = 1054, e_sf55 = 1055, 05107 | e_sf56 = 1056, e_sf57 = 1057, e_sf58 = 1058, e_sf59 = 1059, 05108 | e_sf60 = 1060, e_sf61 = 1061, e_sf62 = 1062, e_sf63 = 1063, 05109 | e_sf64 = 1064, e_sf65 = 1065, e_sf66 = 1066, e_sf67 = 1067, 05110 | e_sf68 = 1068, e_sf69 = 1069, e_sf70 = 1070, e_sf71 = 1071, 05111 | e_sf72 = 1072, e_sf73 = 1073, e_sf74 = 1074, e_sf75 = 1075, 05112 | e_sf76 = 1076, e_sf77 = 1077, e_sf78 = 1078, e_sf79 = 1079, 05113 | e_sf80 = 1080, e_sf81 = 1081, e_sf82 = 1082, e_sf83 = 1083, 05114 | e_sf84 = 1084, e_sf85 = 1085, e_sf86 = 1086, e_sf87 = 1087, 05115 | e_sf88 = 1088, e_sf89 = 1089, e_sf90 = 1090, e_sf91 = 1091, 05116 | e_sf92 = 1092, e_sf93 = 1093, e_sf94 = 1094, e_sf95 = 1095, 05117 | e_sf96 = 1096, e_sf97 = 1097, e_sf98 = 1098, e_sf99 = 1099, 05118 | e_sffinal = 1100, 05119 | e_sf4ext00 = 2000, e_sf4ext01 = 2001, e_sf4ext02 = 2002, e_sf4ext03 = 2003, 05120 | e_sf4ext04 = 2004, e_sf4ext05 = 2005, e_sf4ext06 = 2006, e_sf4ext07 = 2007, 05121 | e_sf4ext08 = 2008, e_sf4ext09 = 2009, e_sf4ext10 = 2010, e_sf4ext11 = 2011, 05122 | e_sf4ext12 = 2012, e_sf4ext13 = 2013, e_sf4ext14 = 2014, e_sf4ext15 = 2015, 05123 | e_sf4ext16 = 2016, e_sf4ext17 = 2017, e_sf4ext18 = 2018, e_sf4ext19 = 2019, 05124 | e_sf4ext20 = 2020, e_sf4ext21 = 2021, e_sf4ext22 = 2022, e_sf4ext23 = 2023, 05125 | e_sf4ext24 = 2024, e_sf4ext25 = 2025, e_sf4ext26 = 2026, e_sf4ext27 = 2027, 05126 | e_sf4ext28 = 2028, e_sf4ext29 = 2029, e_sf4ext30 = 2030, e_sf4ext31 = 2031, 05127 | e_sf4ext32 = 2032, e_sf4ext33 = 2033, e_sf4ext34 = 2034, e_sf4ext35 = 2035, 05128 | e_sf4ext36 = 2036, e_sf4ext37 = 2037, e_sf4ext38 = 2038, e_sf4ext39 = 2039, 05129 | e_sf4ext40 = 2040, e_sf4ext41 = 2041, e_sf4ext42 = 2042, e_sf4ext43 = 2043, 05130 | e_sf4ext44 = 2044, e_sf4ext45 = 2045, e_sf4ext46 = 2046, e_sf4ext47 = 2047, 05131 | e_sf4ext48 = 2048, e_sf4ext49 = 2049, e_sf4ext50 = 2050, e_sf4ext51 = 2051, 05132 | e_sf4ext52 = 2052, e_sf4ext53 = 2053, e_sf4ext54 = 2054, e_sf4ext55 = 2055, 05133 | e_sf4ext56 = 2056, e_sf4ext57 = 2057, e_sf4ext58 = 2058, e_sf4ext59 = 2059, 05134 | e_sf4ext60 = 2060, e_sf4ext61 = 2061 05135 | }; 05136 | 05137 | inline std::string to_str(const operator_type opr) 05138 | { 05139 | switch (opr) 05140 | { 05141 | case e_add : return "+" ; 05142 | case e_sub : return "-" ; 05143 | case e_mul : return "*" ; 05144 | case e_div : return "/" ; 05145 | case e_mod : return "%" ; 05146 | case e_pow : return "^" ; 05147 | case e_assign : return ":=" ; 05148 | case e_addass : return "+=" ; 05149 | case e_subass : return "-=" ; 05150 | case e_mulass : return "*=" ; 05151 | case e_divass : return "/=" ; 05152 | case e_modass : return "%=" ; 05153 | case e_lt : return "<" ; 05154 | case e_lte : return "<=" ; 05155 | case e_eq : return "==" ; 05156 | case e_equal : return "=" ; 05157 | case e_ne : return "!=" ; 05158 | case e_nequal : return "<>" ; 05159 | case e_gte : return ">=" ; 05160 | case e_gt : return ">" ; 05161 | case e_and : return "and" ; 05162 | case e_or : return "or" ; 05163 | case e_xor : return "xor" ; 05164 | case e_nand : return "nand" 05165 | case e_nor : return "nor" ; 05166 | case e_xnor : return "xnor" 05167 | default : return "N/A" ; 05168 | } 05169 | } 05170 | 05171 | struct base_operation_t 05172 | { 05173 | base_operation_t(const operator_type t, const unsigned int& np) 05174 | : type(t) 05175 | , num_params(np) 05176 | {} 05177 | 05178 | operator_type type; 05179 | unsigned int num_params; 05180 | }; 05181 | 05182 | namespace loop_unroll 05183 | { 05184 | const unsigned int global_loop_batch_size = 05185 | #ifndef exprtk_disable_superscalar_unroll 05186 | 16; 05187 | #else 05188 | 4; 05189 | #endif 05190 | 05191 | struct details 05192 | { 05193 | explicit details(const std::size_t& vsize, 05194 | const unsigned int loop_batch_size = global_loop_batch_size) 05195 | : batch_size(loop_batch_size ) 05196 | , remainder (vsize % batch_size) 05197 | , upper_bound(static_cast<int>(vsize - (remainder ? loop_batch_size : 0))) 05198 | {} 05199 | 05200 | unsigned int batch_size; 05201 | int remainder; 05202 | int upper_bound; 05203 | }; 05204 | } 05205 | 05206 | #ifdef exprtk_enable_debugging 05207 | inline void dump_ptr(const std::string& s, const void* ptr, const std::size_t size = 0) 05208 | { 05209 | if (size) 05210 | exprtk_debug(("%s - addr: %p size: %d\n", 05211 | s.c_str(), 05212 | ptr, 05213 | static_cast<unsigned int>(size))); 05214 | else 05215 | exprtk_debug(("%s - addr: %p\n", s.c_str(), ptr)); 05216 | } 05217 | 05218 | template <typename T> 05219 | inline void dump_vector(const std::string& vec_name, const T* data, const std::size_t size) 05220 | { 05221 | printf("----- %s (%p) -----\n", 05222 | vec_name.c_str(), 05223 | static_cast<const void*>(data)); 05224 | printf("[ "); 05225 | for (std::size_t i = 0; i < size; ++i) 05226 | { 05227 | printf("%8.3f\t", data[i]); 05228 | } 05229 | printf(" ]\n"); 05230 | printf("---------------------\n"); 05231 | } 05232 | #else 05233 | inline void dump_ptr(const std::string&, const void*) {} 05234 | inline void dump_ptr(const std::string&, const void*, const std::size_t) {} 05235 | template <typename T> 05236 | inline void dump_vector(const std::string&, const T*, const std::size_t) {} 05237 | #endif 05238 | 05239 | template <typename T> 05240 | class vec_data_store 05241 | { 05242 | public: 05243 | 05244 | typedef vec_data_store<T> type; 05245 | typedef T* data_t; 05246 | 05247 | private: 05248 | 05249 | struct control_block 05250 | { 05251 | control_block() 05252 | : ref_count(1) 05253 | , size (0) 05254 | , data (0) 05255 | , destruct (true) 05256 | {} 05257 | 05258 | explicit control_block(const std::size_t& dsize) 05259 | : ref_count(1 ) 05260 | , size (dsize) 05261 | , data (0 ) 05262 | , destruct (true ) 05263 | { create_data(); } 05264 | 05265 | control_block(const std::size_t& dsize, data_t dptr, bool dstrct = false) 05266 | : ref_count(1 ) 05267 | , size (dsize ) 05268 | , data (dptr ) 05269 | , destruct (dstrct) 05270 | {} 05271 | 05272 | ~control_block() 05273 | { 05274 | if (data && destruct && (0 == ref_count)) 05275 | { 05276 | dump_ptr("~vec_data_store::control_block() data",data); 05277 | delete[] data; 05278 | data = reinterpret_cast<data_t>(0); 05279 | } 05280 | } 05281 | 05282 | static inline control_block* create(const std::size_t& dsize, data_t data_ptr = data_t(0), bool dstrct = false) 05283 | { 05284 | if (dsize) 05285 | { 05286 | if (0 == data_ptr) 05287 | return (new control_block(dsize)); 05288 | else 05289 | return (new control_block(dsize, data_ptr, dstrct)); 05290 | } 05291 | else 05292 | return (new control_block); 05293 | } 05294 | 05295 | static inline void destroy(control_block*& cntrl_blck) 05296 | { 05297 | if (cntrl_blck) 05298 | { 05299 | if ( 05300 | (0 != cntrl_blck->ref_count) && 05301 | (0 == --cntrl_blck->ref_count) 05302 | ) 05303 | { 05304 | delete cntrl_blck; 05305 | } 05306 | 05307 | cntrl_blck = 0; 05308 | } 05309 | } 05310 | 05311 | std::size_t ref_count; 05312 | std::size_t size; 05313 | data_t data; 05314 | bool destruct; 05315 | 05316 | private: 05317 | 05318 | control_block(const control_block&) exprtk_delete; 05319 | control_block& operator=(const control_block&) exprtk_delete; 05320 | 05321 | inline void create_data() 05322 | { 05323 | destruct = true; 05324 | data = new T[size]; 05325 | std::fill_n(data, size, T(0)); 05326 | dump_ptr("control_block::create_data() - data", data, size); 05327 | } 05328 | }; 05329 | 05330 | public: 05331 | 05332 | vec_data_store() 05333 | : control_block_(control_block::create(0)) 05334 | {} 05335 | 05336 | explicit vec_data_store(const std::size_t& size) 05337 | : control_block_(control_block::create(size,reinterpret_cast<data_t>(0),true)) 05338 | {} 05339 | 05340 | vec_data_store(const std::size_t& size, data_t data, bool dstrct = false) 05341 | : control_block_(control_block::create(size, data, dstrct)) 05342 | {} 05343 | 05344 | vec_data_store(const type& vds) 05345 | { 05346 | control_block_ = vds.control_block_; 05347 | control_block_->ref_count++; 05348 | } 05349 | 05350 | ~vec_data_store() 05351 | { 05352 | control_block::destroy(control_block_); 05353 | } 05354 | 05355 | type& operator=(const type& vds) 05356 | { 05357 | if (this != &vds) 05358 | { 05359 | const std::size_t final_size = min_size(control_block_, vds.control_block_); 05360 | 05361 | vds.control_block_->size = final_size; 05362 | control_block_->size = final_size; 05363 | 05364 | if (control_block_->destruct || (0 == control_block_->data)) 05365 | { 05366 | control_block::destroy(control_block_); 05367 | 05368 | control_block_ = vds.control_block_; 05369 | control_block_->ref_count++; 05370 | } 05371 | } 05372 | 05373 | return (*this); 05374 | } 05375 | 05376 | inline data_t data() 05377 | { 05378 | return control_block_->data; 05379 | } 05380 | 05381 | inline data_t data() const 05382 | { 05383 | return control_block_->data; 05384 | } 05385 | 05386 | inline std::size_t size() const 05387 | { 05388 | return control_block_->size; 05389 | } 05390 | 05391 | inline data_t& ref() 05392 | { 05393 | return control_block_->data; 05394 | } 05395 | 05396 | inline void dump() const 05397 | { 05398 | #ifdef exprtk_enable_debugging 05399 | exprtk_debug(("size: %d\taddress:%p\tdestruct:%c\n", 05400 | size(), 05401 | data(), 05402 | (control_block_->destruct ? 'T' : 'F'))); 05403 | 05404 | for (std::size_t i = 0; i < size(); ++i) 05405 | { 05406 | if (5 == i) 05407 | exprtk_debug(("\n")); 05408 | 05409 | exprtk_debug(("%15.10f ", data()[i])); 05410 | } 05411 | exprtk_debug(("\n")); 05412 | #endif 05413 | } 05414 | 05415 | static inline void match_sizes(type& vds0, type& vds1) 05416 | { 05417 | const std::size_t size = min_size(vds0.control_block_,vds1.control_block_); 05418 | vds0.control_block_->size = size; 05419 | vds1.control_block_->size = size; 05420 | } 05421 | 05422 | private: 05423 | 05424 | static inline std::size_t min_size(const control_block* cb0, const control_block* cb1) 05425 | { 05426 | const std::size_t size0 = cb0->size; 05427 | const std::size_t size1 = cb1->size; 05428 | 05429 | if (size0 && size1) 05430 | return std::min(size0,size1); 05431 | else 05432 | return (size0) ? size0 : size1; 05433 | } 05434 | 05435 | control_block* control_block_; 05436 | }; 05437 | 05438 | namespace numeric 05439 | { 05440 | namespace details 05441 | { 05442 | template <typename T> 05443 | inline T process_impl(const operator_type operation, const T arg) 05444 | { 05445 | switch (operation) 05446 | { 05447 | case e_abs : return numeric::abs (arg); 05448 | case e_acos : return numeric::acos (arg); 05449 | case e_acosh : return numeric::acosh(arg); 05450 | case e_asin : return numeric::asin (arg); 05451 | case e_asinh : return numeric::asinh(arg); 05452 | case e_atan : return numeric::atan (arg); 05453 | case e_atanh : return numeric::atanh(arg); 05454 | case e_ceil : return numeric::ceil (arg); 05455 | case e_cos : return numeric::cos (arg); 05456 | case e_cosh : return numeric::cosh (arg); 05457 | case e_exp : return numeric::exp (arg); 05458 | case e_expm1 : return numeric::expm1(arg); 05459 | case e_floor : return numeric::floor(arg); 05460 | case e_log : return numeric::log (arg); 05461 | case e_log10 : return numeric::log10(arg); 05462 | case e_log2 : return numeric::log2 (arg); 05463 | case e_log1p : return numeric::log1p(arg); 05464 | case e_neg : return numeric::neg (arg); 05465 | case e_pos : return numeric::pos (arg); 05466 | case e_round : return numeric::round(arg); 05467 | case e_sin : return numeric::sin (arg); 05468 | case e_sinc : return numeric::sinc (arg); 05469 | case e_sinh : return numeric::sinh (arg); 05470 | case e_sqrt : return numeric::sqrt (arg); 05471 | case e_tan : return numeric::tan (arg); 05472 | case e_tanh : return numeric::tanh (arg); 05473 | case e_cot : return numeric::cot (arg); 05474 | case e_sec : return numeric::sec (arg); 05475 | case e_csc : return numeric::csc (arg); 05476 | case e_r2d : return numeric::r2d (arg); 05477 | case e_d2r : return numeric::d2r (arg); 05478 | case e_d2g : return numeric::d2g (arg); 05479 | case e_g2d : return numeric::g2d (arg); 05480 | case e_notl : return numeric::notl (arg); 05481 | case e_sgn : return numeric::sgn (arg); 05482 | case e_erf : return numeric::erf (arg); 05483 | case e_erfc : return numeric::erfc (arg); 05484 | case e_ncdf : return numeric::ncdf (arg); 05485 | case e_frac : return numeric::frac (arg); 05486 | case e_trunc : return numeric::trunc(arg); 05487 | 05488 | default : exprtk_debug(("numeric::details::process_impl<T> - Invalid unary operation.\n")); 05489 | return std::numeric_limits<T>::quiet_NaN(); 05490 | } 05491 | } 05492 | 05493 | template <typename T> 05494 | inline T process_impl(const operator_type operation, const T arg0, const T arg1) 05495 | { 05496 | switch (operation) 05497 | { 05498 | case e_add : return (arg0 + arg1); 05499 | case e_sub : return (arg0 - arg1); 05500 | case e_mul : return (arg0 * arg1); 05501 | case e_div : return (arg0 / arg1); 05502 | case e_mod : return modulus<T>(arg0,arg1); 05503 | case e_pow : return pow<T>(arg0,arg1); 05504 | case e_atan2 : return atan2<T>(arg0,arg1); 05505 | case e_min : return std::min<T>(arg0,arg1); 05506 | case e_max : return std::max<T>(arg0,arg1); 05507 | case e_logn : return logn<T>(arg0,arg1); 05508 | case e_lt : return (arg0 < arg1) ? T(1) : T(0); 05509 | case e_lte : return (arg0 <= arg1) ? T(1) : T(0); 05510 | case e_eq : return std::equal_to<T>()(arg0,arg1) ? T(1) : T(0); 05511 | case e_ne : return std::not_equal_to<T>()(arg0,arg1) ? T(1) : T(0); 05512 | case e_gte : return (arg0 >= arg1) ? T(1) : T(0); 05513 | case e_gt : return (arg0 > arg1) ? T(1) : T(0); 05514 | case e_and : return and_opr <T>(arg0,arg1); 05515 | case e_nand : return nand_opr<T>(arg0,arg1); 05516 | case e_or : return or_opr <T>(arg0,arg1); 05517 | case e_nor : return nor_opr <T>(arg0,arg1); 05518 | case e_xor : return xor_opr <T>(arg0,arg1); 05519 | case e_xnor : return xnor_opr<T>(arg0,arg1); 05520 | case e_root : return root <T>(arg0,arg1); 05521 | case e_roundn : return roundn <T>(arg0,arg1); 05522 | case e_equal : return equal <T>(arg0,arg1); 05523 | case e_nequal : return nequal <T>(arg0,arg1); 05524 | case e_hypot : return hypot <T>(arg0,arg1); 05525 | case e_shr : return shr <T>(arg0,arg1); 05526 | case e_shl : return shl <T>(arg0,arg1); 05527 | 05528 | default : exprtk_debug(("numeric::details::process_impl<T> - Invalid binary operation.\n")); 05529 | return std::numeric_limits<T>::quiet_NaN(); 05530 | } 05531 | } 05532 | 05533 | template <typename T> 05534 | inline T process_impl(const operator_type operation, const T arg0, const T arg1, int_type_tag) 05535 | { 05536 | switch (operation) 05537 | { 05538 | case e_add : return (arg0 + arg1); 05539 | case e_sub : return (arg0 - arg1); 05540 | case e_mul : return (arg0 * arg1); 05541 | case e_div : return (arg0 / arg1); 05542 | case e_mod : return arg0 % arg1; 05543 | case e_pow : return pow<T>(arg0,arg1); 05544 | case e_min : return std::min<T>(arg0,arg1); 05545 | case e_max : return std::max<T>(arg0,arg1); 05546 | case e_logn : return logn<T>(arg0,arg1); 05547 | case e_lt : return (arg0 < arg1) ? T(1) : T(0); 05548 | case e_lte : return (arg0 <= arg1) ? T(1) : T(0); 05549 | case e_eq : return (arg0 == arg1) ? T(1) : T(0); 05550 | case e_ne : return (arg0 != arg1) ? T(1) : T(0); 05551 | case e_gte : return (arg0 >= arg1) ? T(1) : T(0); 05552 | case e_gt : return (arg0 > arg1) ? T(1) : T(0); 05553 | case e_and : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(1) : T(0); 05554 | case e_nand : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(0) : T(1); 05555 | case e_or : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(1) : T(0); 05556 | case e_nor : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(0) : T(1); 05557 | case e_xor : return arg0 ^ arg1; 05558 | case e_xnor : return !(arg0 ^ arg1); 05559 | case e_root : return root<T>(arg0,arg1); 05560 | case e_equal : return arg0 == arg1; 05561 | case e_nequal : return arg0 != arg1; 05562 | case e_hypot : return hypot<T>(arg0,arg1); 05563 | case e_shr : return arg0 >> arg1; 05564 | case e_shl : return arg0 << arg1; 05565 | 05566 | default : exprtk_debug(("numeric::details::process_impl<IntType> - Invalid binary operation.\n")); 05567 | return std::numeric_limits<T>::quiet_NaN(); 05568 | } 05569 | } 05570 | } 05571 | 05572 | template <typename T> 05573 | inline T process(const operator_type operation, const T arg) 05574 | { 05575 | return exprtk::details::numeric::details::process_impl(operation,arg); 05576 | } 05577 | 05578 | template <typename T> 05579 | inline T process(const operator_type operation, const T arg0, const T arg1) 05580 | { 05581 | return exprtk::details::numeric::details::process_impl(operation, arg0, arg1); 05582 | } 05583 | } 05584 | 05585 | template <typename Node> 05586 | struct node_collector_interface 05587 | { 05588 | typedef Node* node_ptr_t; 05589 | typedef Node** node_pp_t; 05590 | typedef std::vector<node_pp_t> noderef_list_t; 05591 | 05592 | virtual ~node_collector_interface() 05593 | {} 05594 | 05595 | virtual void collect_nodes(noderef_list_t&) 05596 | {} 05597 | }; 05598 | 05599 | template <typename Node> 05600 | struct node_depth_base; 05601 | 05602 | template <typename T> 05603 | class expression_node : public node_collector_interface<expression_node<T> > 05604 | , public node_depth_base<expression_node<T> > 05605 | { 05606 | public: 05607 | 05608 | enum node_type 05609 | { 05610 | e_none , e_null , e_constant , e_unary , 05611 | e_binary , e_binary_ext , e_trinary , e_quaternary , 05612 | e_vararg , e_conditional , e_while , e_repeat , 05613 | e_for , e_switch , e_mswitch , e_return , 05614 | e_retenv , e_variable , e_stringvar , e_stringconst , 05615 | e_stringvarrng , e_cstringvarrng , e_strgenrange , e_strconcat , 05616 | e_stringvarsize , e_strswap , e_stringsize , e_stringvararg , 05617 | e_function , e_vafunction , e_genfunction , e_strfunction , 05618 | e_strcondition , e_strccondition , e_add , e_sub , 05619 | e_mul , e_div , e_mod , e_pow , 05620 | e_lt , e_lte , e_gt , e_gte , 05621 | e_eq , e_ne , e_and , e_nand , 05622 | e_or , e_nor , e_xor , e_xnor , 05623 | e_in , e_like , e_ilike , e_inranges , 05624 | e_ipow , e_ipowinv , e_abs , e_acos , 05625 | e_acosh , e_asin , e_asinh , e_atan , 05626 | e_atanh , e_ceil , e_cos , e_cosh , 05627 | e_exp , e_expm1 , e_floor , e_log , 05628 | e_log10 , e_log2 , e_log1p , e_neg , 05629 | e_pos , e_round , e_sin , e_sinc , 05630 | e_sinh , e_sqrt , e_tan , e_tanh , 05631 | e_cot , e_sec , e_csc , e_r2d , 05632 | e_d2r , e_d2g , e_g2d , e_notl , 05633 | e_sgn , e_erf , e_erfc , e_ncdf , 05634 | e_frac , e_trunc , e_uvouv , e_vov , 05635 | e_cov , e_voc , e_vob , e_bov , 05636 | e_cob , e_boc , e_vovov , e_vovoc , 05637 | e_vocov , e_covov , e_covoc , e_vovovov , 05638 | e_vovovoc , e_vovocov , e_vocovov , e_covovov , 05639 | e_covocov , e_vocovoc , e_covovoc , e_vococov , 05640 | e_sf3ext , e_sf4ext , e_nulleq , e_strass , 05641 | e_vector , e_vecsize , e_vecelem , e_veccelem , 05642 | e_vecelemrtc , e_veccelemrtc , e_rbvecelem , e_rbvecelemrtc , 05643 | e_rbveccelem , e_rbveccelemrtc , e_vecinit , e_vecvalass , 05644 | e_vecvecass , e_vecopvalass , e_vecopvecass , e_vecfunc , 05645 | e_vecvecswap , e_vecvecineq , e_vecvalineq , e_valvecineq , 05646 | e_vecvecarith , e_vecvalarith , e_valvecarith , e_vecunaryop , 05647 | e_vecondition , e_break , e_continue , e_swap , 05648 | e_assert 05649 | }; 05650 | 05651 | typedef T value_type; 05652 | typedef expression_node<T>* expression_ptr; 05653 | typedef node_collector_interface<expression_node<T> > nci_t; 05654 | typedef typename nci_t::noderef_list_t noderef_list_t; 05655 | typedef node_depth_base<expression_node<T> > ndb_t; 05656 | 05657 | virtual ~expression_node() 05658 | {} 05659 | 05660 | inline virtual T value() const 05661 | { 05662 | return std::numeric_limits<T>::quiet_NaN(); 05663 | } 05664 | 05665 | inline virtual expression_node<T>* branch(const std::size_t& index = 0) const 05666 | { 05667 | return reinterpret_cast<expression_ptr>(index * 0); 05668 | } 05669 | 05670 | inline virtual node_type type() const 05671 | { 05672 | return e_none; 05673 | } 05674 | 05675 | inline virtual bool valid() const 05676 | { 05677 | return true; 05678 | } 05679 | }; // class expression_node 05680 | 05681 | template <typename T> 05682 | inline bool is_generally_string_node(const expression_node<T>* node); 05683 | 05684 | inline bool is_true(const double v) 05685 | { 05686 | return std::not_equal_to<double>()(0.0,v); 05687 | } 05688 | 05689 | inline bool is_true(const long double v) 05690 | { 05691 | return std::not_equal_to<long double>()(0.0L,v); 05692 | } 05693 | 05694 | inline bool is_true(const float v) 05695 | { 05696 | return std::not_equal_to<float>()(0.0f,v); 05697 | } 05698 | 05699 | template <typename T> 05700 | inline bool is_true(const expression_node<T>* node) 05701 | { 05702 | return std::not_equal_to<T>()(T(0),node->value()); 05703 | } 05704 | 05705 | template <typename T> 05706 | inline bool is_true(const std::pair<expression_node<T>*,bool>& node) 05707 | { 05708 | return std::not_equal_to<T>()(T(0),node.first->value()); 05709 | } 05710 | 05711 | template <typename T> 05712 | inline bool is_false(const expression_node<T>* node) 05713 | { 05714 | return std::equal_to<T>()(T(0),node->value()); 05715 | } 05716 | 05717 | template <typename T> 05718 | inline bool is_false(const std::pair<expression_node<T>*,bool>& node) 05719 | { 05720 | return std::equal_to<T>()(T(0),node.first->value()); 05721 | } 05722 | 05723 | template <typename T> 05724 | inline bool is_literal_node(const expression_node<T>* node) 05725 | { 05726 | return node && (details::expression_node<T>::e_constant == node->type()); 05727 | } 05728 | 05729 | template <typename T> 05730 | inline bool is_unary_node(const expression_node<T>* node) 05731 | { 05732 | return node && (details::expression_node<T>::e_unary == node->type()); 05733 | } 05734 | 05735 | template <typename T> 05736 | inline bool is_neg_unary_node(const expression_node<T>* node) 05737 | { 05738 | return node && (details::expression_node<T>::e_neg == node->type()); 05739 | } 05740 | 05741 | template <typename T> 05742 | inline bool is_binary_node(const expression_node<T>* node) 05743 | { 05744 | return node && (details::expression_node<T>::e_binary == node->type()); 05745 | } 05746 | 05747 | template <typename T> 05748 | inline bool is_variable_node(const expression_node<T>* node) 05749 | { 05750 | return node && (details::expression_node<T>::e_variable == node->type()); 05751 | } 05752 | 05753 | template <typename T> 05754 | inline bool is_ivariable_node(const expression_node<T>* node) 05755 | { 05756 | return node && 05757 | ( 05758 | details::expression_node<T>::e_variable == node->type() || 05759 | details::expression_node<T>::e_vecelem == node->type() || 05760 | details::expression_node<T>::e_veccelem == node->type() || 05761 | details::expression_node<T>::e_vecelemrtc == node->type() || 05762 | details::expression_node<T>::e_veccelemrtc == node->type() || 05763 | details::expression_node<T>::e_rbvecelem == node->type() || 05764 | details::expression_node<T>::e_rbveccelem == node->type() || 05765 | details::expression_node<T>::e_rbvecelemrtc == node->type() || 05766 | details::expression_node<T>::e_rbveccelemrtc == node->type() 05767 | ); 05768 | } 05769 | 05770 | template <typename T> 05771 | inline bool is_vector_elem_node(const expression_node<T>* node) 05772 | { 05773 | return node && (details::expression_node<T>::e_vecelem == node->type()); 05774 | } 05775 | 05776 | template <typename T> 05777 | inline bool is_vector_celem_node(const expression_node<T>* node) 05778 | { 05779 | return node && (details::expression_node<T>::e_veccelem == node->type()); 05780 | } 05781 | 05782 | template <typename T> 05783 | inline bool is_vector_elem_rtc_node(const expression_node<T>* node) 05784 | { 05785 | return node && (details::expression_node<T>::e_vecelemrtc == node->type()); 05786 | } 05787 | 05788 | template <typename T> 05789 | inline bool is_vector_celem_rtc_node(const expression_node<T>* node) 05790 | { 05791 | return node && (details::expression_node<T>::e_veccelemrtc == node->type()); 05792 | } 05793 | 05794 | template <typename T> 05795 | inline bool is_rebasevector_elem_node(const expression_node<T>* node) 05796 | { 05797 | return node && (details::expression_node<T>::e_rbvecelem == node->type()); 05798 | } 05799 | 05800 | template <typename T> 05801 | inline bool is_rebasevector_elem_rtc_node(const expression_node<T>* node) 05802 | { 05803 | return node && (details::expression_node<T>::e_rbvecelemrtc == node->type()); 05804 | } 05805 | 05806 | template <typename T> 05807 | inline bool is_rebasevector_celem_rtc_node(const expression_node<T>* node) 05808 | { 05809 | return node && (details::expression_node<T>::e_rbveccelemrtc == node->type()); 05810 | } 05811 | 05812 | template <typename T> 05813 | inline bool is_rebasevector_celem_node(const expression_node<T>* node) 05814 | { 05815 | return node && (details::expression_node<T>::e_rbveccelem == node->type()); 05816 | } 05817 | 05818 | template <typename T> 05819 | inline bool is_vector_node(const expression_node<T>* node) 05820 | { 05821 | return node && (details::expression_node<T>::e_vector == node->type()); 05822 | } 05823 | 05824 | template <typename T> 05825 | inline bool is_ivector_node(const expression_node<T>* node) 05826 | { 05827 | if (node) 05828 | { 05829 | switch (node->type()) 05830 | { 05831 | case details::expression_node<T>::e_vector : 05832 | case details::expression_node<T>::e_vecvalass : 05833 | case details::expression_node<T>::e_vecvecass : 05834 | case details::expression_node<T>::e_vecopvalass : 05835 | case details::expression_node<T>::e_vecopvecass : 05836 | case details::expression_node<T>::e_vecvecswap : 05837 | case details::expression_node<T>::e_vecvecarith : 05838 | case details::expression_node<T>::e_vecvalarith : 05839 | case details::expression_node<T>::e_valvecarith : 05840 | case details::expression_node<T>::e_vecunaryop : 05841 | case details::expression_node<T>::e_vecondition : return true; 05842 | default : return false; 05843 | } 05844 | } 05845 | else 05846 | return false; 05847 | } 05848 | 05849 | template <typename T> 05850 | inline bool is_constant_node(const expression_node<T>* node) 05851 | { 05852 | return node && 05853 | ( 05854 | details::expression_node<T>::e_constant == node->type() || 05855 | details::expression_node<T>::e_stringconst == node->type() 05856 | ); 05857 | } 05858 | 05859 | template <typename T> 05860 | inline bool is_null_node(const expression_node<T>* node) 05861 | { 05862 | return node && (details::expression_node<T>::e_null == node->type()); 05863 | } 05864 | 05865 | template <typename T> 05866 | inline bool is_break_node(const expression_node<T>* node) 05867 | { 05868 | return node && (details::expression_node<T>::e_break == node->type()); 05869 | } 05870 | 05871 | template <typename T> 05872 | inline bool is_continue_node(const expression_node<T>* node) 05873 | { 05874 | return node && (details::expression_node<T>::e_continue == node->type()); 05875 | } 05876 | 05877 | template <typename T> 05878 | inline bool is_swap_node(const expression_node<T>* node) 05879 | { 05880 | return node && (details::expression_node<T>::e_swap == node->type()); 05881 | } 05882 | 05883 | template <typename T> 05884 | inline bool is_function(const expression_node<T>* node) 05885 | { 05886 | return node && (details::expression_node<T>::e_function == node->type()); 05887 | } 05888 | 05889 | template <typename T> 05890 | inline bool is_vararg_node(const expression_node<T>* node) 05891 | { 05892 | return node && (details::expression_node<T>::e_vararg == node->type()); 05893 | } 05894 | 05895 | template <typename T> 05896 | inline bool is_return_node(const expression_node<T>* node) 05897 | { 05898 | return node && (details::expression_node<T>::e_return == node->type()); 05899 | } 05900 | 05901 | template <typename T> class unary_node; 05902 | 05903 | template <typename T> 05904 | inline bool is_negate_node(const expression_node<T>* node) 05905 | { 05906 | if (node && is_unary_node(node)) 05907 | { 05908 | return (details::e_neg == static_cast<const unary_node<T>*>(node)->operation()); 05909 | } 05910 | else 05911 | return false; 05912 | } 05913 | 05914 | template <typename T> 05915 | inline bool is_assert_node(const expression_node<T>* node) 05916 | { 05917 | return node && (details::expression_node<T>::e_assert == node->type()); 05918 | } 05919 | 05920 | template <typename T> 05921 | inline bool branch_deletable(const expression_node<T>* node) 05922 | { 05923 | return (0 != node) && 05924 | !is_variable_node(node) && 05925 | !is_string_node (node) ; 05926 | } 05927 | 05928 | template <std::size_t N, typename T> 05929 | inline bool all_nodes_valid(expression_node<T>* const (&b)[N]) 05930 | { 05931 | for (std::size_t i = 0; i < N; ++i) 05932 | { 05933 | if (0 == b[i]) return false; 05934 | } 05935 | 05936 | return true; 05937 | } 05938 | 05939 | template <typename T, 05940 | typename Allocator, 05941 | template <typename, typename> class Sequence> 05942 | inline bool all_nodes_valid(const Sequence<expression_node<T>*,Allocator>& b) 05943 | { 05944 | for (std::size_t i = 0; i < b.size(); ++i) 05945 | { 05946 | if (0 == b[i]) return false; 05947 | } 05948 | 05949 | return true; 05950 | } 05951 | 05952 | template <std::size_t N, typename T> 05953 | inline bool all_nodes_variables(expression_node<T>* const (&b)[N]) 05954 | { 05955 | for (std::size_t i = 0; i < N; ++i) 05956 | { 05957 | if (0 == b[i]) 05958 | return false; 05959 | else if (!is_variable_node(b[i])) 05960 | return false; 05961 | } 05962 | 05963 | return true; 05964 | } 05965 | 05966 | template <typename T, 05967 | typename Allocator, 05968 | template <typename, typename> class Sequence> 05969 | inline bool all_nodes_variables(const Sequence<expression_node<T>*,Allocator>& b) 05970 | { 05971 | for (std::size_t i = 0; i < b.size(); ++i) 05972 | { 05973 | if (0 == b[i]) 05974 | return false; 05975 | else if (!is_variable_node(b[i])) 05976 | return false; 05977 | } 05978 | 05979 | return true; 05980 | } 05981 | 05982 | template <typename Node> 05983 | class node_collection_destructor 05984 | { 05985 | public: 05986 | 05987 | typedef node_collector_interface<Node> nci_t; 05988 | 05989 | typedef typename nci_t::node_ptr_t node_ptr_t; 05990 | typedef typename nci_t::node_pp_t node_pp_t; 05991 | typedef typename nci_t::noderef_list_t noderef_list_t; 05992 | 05993 | static void delete_nodes(node_ptr_t& root) 05994 | { 05995 | std::vector<node_pp_t> node_delete_list; 05996 | node_delete_list.reserve(1000); 05997 | 05998 | collect_nodes(root, node_delete_list); 05999 | 06000 | for (std::size_t i = 0; i < node_delete_list.size(); ++i) 06001 | { 06002 | node_ptr_t& node = *node_delete_list[i]; 06003 | exprtk_debug(("ncd::delete_nodes() - deleting: %p\n", reinterpret_cast<void*>(node))); 06004 | delete node; 06005 | node = reinterpret_cast<node_ptr_t>(0); 06006 | } 06007 | } 06008 | 06009 | private: 06010 | 06011 | static void collect_nodes(node_ptr_t& root, noderef_list_t& node_delete_list) 06012 | { 06013 | std::deque<node_ptr_t> node_list; 06014 | node_list.push_back(root); 06015 | node_delete_list.push_back(&root); 06016 | 06017 | noderef_list_t child_node_delete_list; 06018 | child_node_delete_list.reserve(1000); 06019 | 06020 | while (!node_list.empty()) 06021 | { 06022 | node_list.front()->collect_nodes(child_node_delete_list); 06023 | 06024 | if (!child_node_delete_list.empty()) 06025 | { 06026 | for (std::size_t i = 0; i < child_node_delete_list.size(); ++i) 06027 | { 06028 | node_pp_t& node = child_node_delete_list[i]; 06029 | 06030 | if (0 == (*node)) 06031 | { 06032 | exprtk_debug(("ncd::collect_nodes() - null node encountered.\n")); 06033 | } 06034 | 06035 | node_list.push_back(*node); 06036 | } 06037 | 06038 | node_delete_list.insert( 06039 | node_delete_list.end(), 06040 | child_node_delete_list.begin(), child_node_delete_list.end()); 06041 | 06042 | child_node_delete_list.clear(); 06043 | } 06044 | 06045 | node_list.pop_front(); 06046 | } 06047 | 06048 | std::reverse(node_delete_list.begin(), node_delete_list.end()); 06049 | } 06050 | }; 06051 | 06052 | template <typename NodeAllocator, typename T, std::size_t N> 06053 | inline void free_all_nodes(NodeAllocator& node_allocator, expression_node<T>* (&b)[N]) 06054 | { 06055 | for (std::size_t i = 0; i < N; ++i) 06056 | { 06057 | free_node(node_allocator,b[i]); 06058 | } 06059 | } 06060 | 06061 | template <typename NodeAllocator, 06062 | typename T, 06063 | typename Allocator, 06064 | template <typename, typename> class Sequence> 06065 | inline void free_all_nodes(NodeAllocator& node_allocator, Sequence<expression_node<T>*,Allocator>& b) 06066 | { 06067 | for (std::size_t i = 0; i < b.size(); ++i) 06068 | { 06069 | free_node(node_allocator,b[i]); 06070 | } 06071 | 06072 | b.clear(); 06073 | } 06074 | 06075 | template <typename NodeAllocator, typename T> 06076 | inline void free_node(NodeAllocator&, expression_node<T>*& node) 06077 | { 06078 | if ((0 == node) || is_variable_node(node) || is_string_node(node)) 06079 | { 06080 | return; 06081 | } 06082 | 06083 | node_collection_destructor<expression_node<T> > 06084 | ::delete_nodes(node); 06085 | } 06086 | 06087 | template <typename T> 06088 | inline void destroy_node(expression_node<T>*& node) 06089 | { 06090 | if (0 != node) 06091 | { 06092 | node_collection_destructor<expression_node<T> > 06093 | ::delete_nodes(node); 06094 | } 06095 | } 06096 | 06097 | template <typename Node> 06098 | struct node_depth_base 06099 | { 06100 | typedef Node* node_ptr_t; 06101 | typedef std::pair<node_ptr_t,bool> nb_pair_t; 06102 | 06103 | node_depth_base() 06104 | : depth_set(false) 06105 | , depth(0) 06106 | {} 06107 | 06108 | virtual ~node_depth_base() 06109 | {} 06110 | 06111 | virtual std::size_t node_depth() const { return 1; } 06112 | 06113 | std::size_t compute_node_depth(const Node* const& node) const 06114 | { 06115 | if (!depth_set) 06116 | { 06117 | depth = 1 + (node ? node->node_depth() : 0); 06118 | depth_set = true; 06119 | } 06120 | 06121 | return depth; 06122 | } 06123 | 06124 | std::size_t compute_node_depth(const nb_pair_t& branch) const 06125 | { 06126 | if (!depth_set) 06127 | { 06128 | depth = 1 + (branch.first ? branch.first->node_depth() : 0); 06129 | depth_set = true; 06130 | } 06131 | 06132 | return depth; 06133 | } 06134 | 06135 | template <std::size_t N> 06136 | std::size_t compute_node_depth(const nb_pair_t (&branch)[N]) const 06137 | { 06138 | if (!depth_set) 06139 | { 06140 | depth = 0; 06141 | 06142 | for (std::size_t i = 0; i < N; ++i) 06143 | { 06144 | if (branch[i].first) 06145 | { 06146 | depth = std::max(depth,branch[i].first->node_depth()); 06147 | } 06148 | } 06149 | 06150 | depth += 1; 06151 | depth_set = true; 06152 | } 06153 | 06154 | return depth; 06155 | } 06156 | 06157 | template <typename BranchType> 06158 | std::size_t max_node_depth(const BranchType& n0, const BranchType& n1) const 06159 | { 06160 | return std::max(compute_node_depth(n0), compute_node_depth(n1)); 06161 | } 06162 | 06163 | template <typename BranchType> 06164 | std::size_t max_node_depth(const BranchType& n0, const BranchType& n1, const BranchType& n2) const 06165 | { 06166 | return std::max(compute_node_depth(n0), 06167 | std::max(compute_node_depth(n1), compute_node_depth(n2))); 06168 | } 06169 | 06170 | template <typename BranchType> 06171 | std::size_t max_node_depth(const BranchType& n0, const BranchType& n1, 06172 | const BranchType& n2, const BranchType& n3) const 06173 | { 06174 | return std::max( 06175 | std::max(compute_node_depth(n0), compute_node_depth(n1)), 06176 | std::max(compute_node_depth(n2), compute_node_depth(n3))); 06177 | } 06178 | 06179 | template <typename BranchType> 06180 | std::size_t compute_node_depth(const BranchType& n0, const BranchType& n1) const 06181 | { 06182 | if (!depth_set) 06183 | { 06184 | depth = 1 + max_node_depth(n0, n1); 06185 | depth_set = true; 06186 | } 06187 | 06188 | return depth; 06189 | } 06190 | 06191 | template <typename BranchType> 06192 | std::size_t compute_node_depth(const BranchType& n0, const BranchType& n1, 06193 | const BranchType& n2) const 06194 | { 06195 | if (!depth_set) 06196 | { 06197 | depth = 1 + max_node_depth(n0, n1, n2); 06198 | depth_set = true; 06199 | } 06200 | 06201 | return depth; 06202 | } 06203 | 06204 | template <typename BranchType> 06205 | std::size_t compute_node_depth(const BranchType& n0, const BranchType& n1, 06206 | const BranchType& n2, const BranchType& n3) const 06207 | { 06208 | if (!depth_set) 06209 | { 06210 | depth = 1 + max_node_depth(n0, n1, n2, n3); 06211 | depth_set = true; 06212 | } 06213 | 06214 | return depth; 06215 | } 06216 | 06217 | template <typename Allocator, 06218 | template <typename, typename> class Sequence> 06219 | std::size_t compute_node_depth(const Sequence<node_ptr_t, Allocator>& branch_list) const 06220 | { 06221 | if (!depth_set) 06222 | { 06223 | for (std::size_t i = 0; i < branch_list.size(); ++i) 06224 | { 06225 | if (branch_list[i]) 06226 | { 06227 | depth = std::max(depth, compute_node_depth(branch_list[i])); 06228 | } 06229 | } 06230 | 06231 | depth_set = true; 06232 | } 06233 | 06234 | return depth; 06235 | } 06236 | 06237 | template <typename Allocator, 06238 | template <typename, typename> class Sequence> 06239 | std::size_t compute_node_depth(const Sequence<nb_pair_t,Allocator>& branch_list) const 06240 | { 06241 | if (!depth_set) 06242 | { 06243 | for (std::size_t i = 0; i < branch_list.size(); ++i) 06244 | { 06245 | if (branch_list[i].first) 06246 | { 06247 | depth = std::max(depth, compute_node_depth(branch_list[i].first)); 06248 | } 06249 | } 06250 | 06251 | depth_set = true; 06252 | } 06253 | 06254 | return depth; 06255 | } 06256 | 06257 | mutable bool depth_set; 06258 | mutable std::size_t depth; 06259 | 06260 | template <typename NodeSequence> 06261 | void collect(node_ptr_t const& node, 06262 | const bool deletable, 06263 | NodeSequence& delete_node_list) const 06264 | { 06265 | if ((0 != node) && deletable) 06266 | { 06267 | delete_node_list.push_back(const_cast<node_ptr_t*>(&node)); 06268 | } 06269 | } 06270 | 06271 | template <typename NodeSequence> 06272 | void collect(const nb_pair_t& branch, 06273 | NodeSequence& delete_node_list) const 06274 | { 06275 | collect(branch.first, branch.second, delete_node_list); 06276 | } 06277 | 06278 | template <typename NodeSequence> 06279 | void collect(Node*& node, 06280 | NodeSequence& delete_node_list) const 06281 | { 06282 | collect(node, branch_deletable(node), delete_node_list); 06283 | } 06284 | 06285 | template <std::size_t N, typename NodeSequence> 06286 | void collect(const nb_pair_t(&branch)[N], 06287 | NodeSequence& delete_node_list) const 06288 | { 06289 | for (std::size_t i = 0; i < N; ++i) 06290 | { 06291 | collect(branch[i].first, branch[i].second, delete_node_list); 06292 | } 06293 | } 06294 | 06295 | template <typename Allocator, 06296 | template <typename, typename> class Sequence, 06297 | typename NodeSequence> 06298 | void collect(const Sequence<nb_pair_t, Allocator>& branch, 06299 | NodeSequence& delete_node_list) const 06300 | { 06301 | for (std::size_t i = 0; i < branch.size(); ++i) 06302 | { 06303 | collect(branch[i].first, branch[i].second, delete_node_list); 06304 | } 06305 | } 06306 | 06307 | template <typename Allocator, 06308 | template <typename, typename> class Sequence, 06309 | typename NodeSequence> 06310 | void collect(const Sequence<node_ptr_t, Allocator>& branch_list, 06311 | NodeSequence& delete_node_list) const 06312 | { 06313 | for (std::size_t i = 0; i < branch_list.size(); ++i) 06314 | { 06315 | collect(branch_list[i], branch_deletable(branch_list[i]), delete_node_list); 06316 | } 06317 | } 06318 | 06319 | template <typename Boolean, 06320 | typename AllocatorT, 06321 | typename AllocatorB, 06322 | template <typename, typename> class Sequence, 06323 | typename NodeSequence> 06324 | void collect(const Sequence<node_ptr_t, AllocatorT>& branch_list, 06325 | const Sequence<Boolean, AllocatorB>& branch_deletable_list, 06326 | NodeSequence& delete_node_list) const 06327 | { 06328 | for (std::size_t i = 0; i < branch_list.size(); ++i) 06329 | { 06330 | collect(branch_list[i], branch_deletable_list[i], delete_node_list); 06331 | } 06332 | } 06333 | }; 06334 | 06335 | template <typename Type> 06336 | class vector_holder 06337 | { 06338 | private: 06339 | 06340 | typedef Type value_type; 06341 | typedef value_type* value_ptr; 06342 | typedef const value_ptr const_value_ptr; 06343 | typedef vector_holder<Type> vector_holder_t; 06344 | 06345 | class vector_holder_base 06346 | { 06347 | public: 06348 | 06349 | virtual ~vector_holder_base() 06350 | {} 06351 | 06352 | inline value_ptr operator[](const std::size_t& index) const 06353 | { 06354 | return value_at(index); 06355 | } 06356 | 06357 | inline std::size_t size() const 06358 | { 06359 | return vector_size(); 06360 | } 06361 | 06362 | inline std::size_t base_size() const 06363 | { 06364 | return vector_base_size(); 06365 | } 06366 | 06367 | inline value_ptr data() const 06368 | { 06369 | return value_at(0); 06370 | } 06371 | 06372 | virtual inline bool rebaseable() const 06373 | { 06374 | return false; 06375 | } 06376 | 06377 | virtual void set_ref(value_ptr*) 06378 | {} 06379 | 06380 | virtual void remove_ref(value_ptr*) 06381 | {} 06382 | 06383 | virtual vector_view<Type>* rebaseable_instance() 06384 | { 06385 | return reinterpret_cast<vector_view<Type>*>(0); 06386 | } 06387 | 06388 | protected: 06389 | 06390 | virtual value_ptr value_at(const std::size_t&) const = 0; 06391 | virtual std::size_t vector_size() const = 0; 06392 | virtual std::size_t vector_base_size() const = 0; 06393 | }; 06394 | 06395 | class array_vector_impl exprtk_final : public vector_holder_base 06396 | { 06397 | public: 06398 | 06399 | array_vector_impl(const Type* vec, const std::size_t& vec_size) 06400 | : vec_(vec) 06401 | , size_(vec_size) 06402 | {} 06403 | 06404 | protected: 06405 | 06406 | value_ptr value_at(const std::size_t& index) const exprtk_override 06407 | { 06408 | assert(index < size_); 06409 | return const_cast<const_value_ptr>(vec_ + index); 06410 | } 06411 | 06412 | std::size_t vector_size() const exprtk_override 06413 | { 06414 | return size_; 06415 | } 06416 | 06417 | std::size_t vector_base_size() const exprtk_override 06418 | { 06419 | return vector_size(); 06420 | } 06421 | 06422 | private: 06423 | 06424 | array_vector_impl(const array_vector_impl&) exprtk_delete; 06425 | array_vector_impl& operator=(const array_vector_impl&) exprtk_delete; 06426 | 06427 | const Type* vec_; 06428 | const std::size_t size_; 06429 | }; 06430 | 06431 | template <typename Allocator, 06432 | template <typename, typename> class Sequence> 06433 | class sequence_vector_impl exprtk_final : public vector_holder_base 06434 | { 06435 | public: 06436 | 06437 | typedef Sequence<Type,Allocator> sequence_t; 06438 | 06439 | explicit sequence_vector_impl(sequence_t& seq) 06440 | : sequence_(seq) 06441 | {} 06442 | 06443 | protected: 06444 | 06445 | value_ptr value_at(const std::size_t& index) const exprtk_override 06446 | { 06447 | assert(index < sequence_.size()); 06448 | return (&sequence_[index]); 06449 | } 06450 | 06451 | std::size_t vector_size() const exprtk_override 06452 | { 06453 | return sequence_.size(); 06454 | } 06455 | 06456 | std::size_t vector_base_size() const exprtk_override 06457 | { 06458 | return vector_size(); 06459 | } 06460 | 06461 | private: 06462 | 06463 | sequence_vector_impl(const sequence_vector_impl&) exprtk_delete; 06464 | sequence_vector_impl& operator=(const sequence_vector_impl&) exprtk_delete; 06465 | 06466 | sequence_t& sequence_; 06467 | }; 06468 | 06469 | class vector_view_impl exprtk_final : public vector_holder_base 06470 | { 06471 | public: 06472 | 06473 | typedef exprtk::vector_view<Type> vector_view_t; 06474 | 06475 | explicit vector_view_impl(vector_view_t& vec_view) 06476 | : vec_view_(vec_view) 06477 | { 06478 | assert(vec_view_.size() > 0); 06479 | } 06480 | 06481 | void set_ref(value_ptr* ref) exprtk_override 06482 | { 06483 | vec_view_.set_ref(ref); 06484 | } 06485 | 06486 | void remove_ref(value_ptr* ref) exprtk_override 06487 | { 06488 | vec_view_.remove_ref(ref); 06489 | } 06490 | 06491 | bool rebaseable() const exprtk_override 06492 | { 06493 | return true; 06494 | } 06495 | 06496 | vector_view<Type>* rebaseable_instance() exprtk_override 06497 | { 06498 | return &vec_view_; 06499 | } 06500 | 06501 | protected: 06502 | 06503 | value_ptr value_at(const std::size_t& index) const exprtk_override 06504 | { 06505 | assert(index < vec_view_.size()); 06506 | return (&vec_view_[index]); 06507 | } 06508 | 06509 | std::size_t vector_size() const exprtk_override 06510 | { 06511 | return vec_view_.size(); 06512 | } 06513 | 06514 | std::size_t vector_base_size() const exprtk_override 06515 | { 06516 | return vec_view_.base_size(); 06517 | } 06518 | 06519 | private: 06520 | 06521 | vector_view_impl(const vector_view_impl&) exprtk_delete; 06522 | vector_view_impl& operator=(const vector_view_impl&) exprtk_delete; 06523 | 06524 | vector_view_t& vec_view_; 06525 | }; 06526 | 06527 | class resizable_vector_impl exprtk_final : public vector_holder_base 06528 | { 06529 | public: 06530 | 06531 | resizable_vector_impl(vector_holder& vec_view_holder, 06532 | const Type* vec, 06533 | const std::size_t& vec_size) 06534 | : vec_(vec) 06535 | , size_(vec_size) 06536 | , vec_view_holder_(*vec_view_holder.rebaseable_instance()) 06537 | { 06538 | assert(vec_view_holder.rebaseable_instance()); 06539 | assert(size_ <= vector_base_size()); 06540 | } 06541 | 06542 | virtual ~resizable_vector_impl() exprtk_override 06543 | {} 06544 | 06545 | protected: 06546 | 06547 | value_ptr value_at(const std::size_t& index) const exprtk_override 06548 | { 06549 | assert(index < vector_size()); 06550 | return const_cast<const_value_ptr>(vec_ + index); 06551 | } 06552 | 06553 | std::size_t vector_size() const exprtk_override 06554 | { 06555 | return vec_view_holder_.size(); 06556 | } 06557 | 06558 | std::size_t vector_base_size() const exprtk_override 06559 | { 06560 | return vec_view_holder_.base_size(); 06561 | } 06562 | 06563 | bool rebaseable() const exprtk_override 06564 | { 06565 | return true; 06566 | } 06567 | 06568 | virtual vector_view<Type>* rebaseable_instance() exprtk_override 06569 | { 06570 | return &vec_view_holder_; 06571 | } 06572 | 06573 | private: 06574 | 06575 | resizable_vector_impl(const resizable_vector_impl&) exprtk_delete; 06576 | resizable_vector_impl& operator=(const resizable_vector_impl&) exprtk_delete; 06577 | 06578 | const Type* vec_; 06579 | const std::size_t size_; 06580 | vector_view<Type>& vec_view_holder_; 06581 | }; 06582 | 06583 | public: 06584 | 06585 | typedef typename details::vec_data_store<Type> vds_t; 06586 | 06587 | vector_holder(Type* vec, const std::size_t& vec_size) 06588 | : vector_holder_base_(new(buffer)array_vector_impl(vec,vec_size)) 06589 | {} 06590 | 06591 | explicit vector_holder(const vds_t& vds) 06592 | : vector_holder_base_(new(buffer)array_vector_impl(vds.data(),vds.size())) 06593 | {} 06594 | 06595 | template <typename Allocator> 06596 | explicit vector_holder(std::vector<Type,Allocator>& vec) 06597 | : vector_holder_base_(new(buffer)sequence_vector_impl<Allocator,std::vector>(vec)) 06598 | {} 06599 | 06600 | explicit vector_holder(exprtk::vector_view<Type>& vec) 06601 | : vector_holder_base_(new(buffer)vector_view_impl(vec)) 06602 | {} 06603 | 06604 | explicit vector_holder(vector_holder_t& vec_holder, const vds_t& vds) 06605 | : vector_holder_base_(new(buffer)resizable_vector_impl(vec_holder, vds.data(), vds.size())) 06606 | {} 06607 | 06608 | inline value_ptr operator[](const std::size_t& index) const 06609 | { 06610 | return (*vector_holder_base_)[index]; 06611 | } 06612 | 06613 | inline std::size_t size() const 06614 | { 06615 | return vector_holder_base_->size(); 06616 | } 06617 | 06618 | inline std::size_t base_size() const 06619 | { 06620 | return vector_holder_base_->base_size(); 06621 | } 06622 | 06623 | inline value_ptr data() const 06624 | { 06625 | return vector_holder_base_->data(); 06626 | } 06627 | 06628 | void set_ref(value_ptr* ref) 06629 | { 06630 | if (rebaseable()) 06631 | { 06632 | vector_holder_base_->set_ref(ref); 06633 | } 06634 | } 06635 | 06636 | void remove_ref(value_ptr* ref) 06637 | { 06638 | if (rebaseable()) 06639 | { 06640 | vector_holder_base_->remove_ref(ref); 06641 | } 06642 | } 06643 | 06644 | bool rebaseable() const 06645 | { 06646 | return vector_holder_base_->rebaseable(); 06647 | } 06648 | 06649 | vector_view<Type>* rebaseable_instance() 06650 | { 06651 | return vector_holder_base_->rebaseable_instance(); 06652 | } 06653 | 06654 | private: 06655 | 06656 | vector_holder(const vector_holder<Type>&) exprtk_delete; 06657 | vector_holder<Type>& operator=(const vector_holder<Type>&) exprtk_delete; 06658 | 06659 | mutable vector_holder_base* vector_holder_base_; 06660 | uchar_t buffer[64]; 06661 | }; 06662 | 06663 | template <typename T> 06664 | class null_node exprtk_final : public expression_node<T> 06665 | { 06666 | public: 06667 | 06668 | inline T value() const exprtk_override 06669 | { 06670 | return std::numeric_limits<T>::quiet_NaN(); 06671 | } 06672 | 06673 | inline typename expression_node<T>::node_type type() const exprtk_override 06674 | { 06675 | return expression_node<T>::e_null; 06676 | } 06677 | }; 06678 | 06679 | template <typename T, std::size_t N> 06680 | inline void construct_branch_pair(std::pair<expression_node<T>*,bool> (&branch)[N], 06681 | expression_node<T>* b, 06682 | const std::size_t& index) 06683 | { 06684 | if (b && (index < N)) 06685 | { 06686 | branch[index] = std::make_pair(b,branch_deletable(b)); 06687 | } 06688 | } 06689 | 06690 | template <typename T> 06691 | inline void construct_branch_pair(std::pair<expression_node<T>*,bool>& branch, expression_node<T>* b) 06692 | { 06693 | if (b) 06694 | { 06695 | branch = std::make_pair(b,branch_deletable(b)); 06696 | } 06697 | } 06698 | 06699 | template <std::size_t N, typename T> 06700 | inline void init_branches(std::pair<expression_node<T>*,bool> (&branch)[N], 06701 | expression_node<T>* b0, 06702 | expression_node<T>* b1 = reinterpret_cast<expression_node<T>*>(0), 06703 | expression_node<T>* b2 = reinterpret_cast<expression_node<T>*>(0), 06704 | expression_node<T>* b3 = reinterpret_cast<expression_node<T>*>(0), 06705 | expression_node<T>* b4 = reinterpret_cast<expression_node<T>*>(0), 06706 | expression_node<T>* b5 = reinterpret_cast<expression_node<T>*>(0), 06707 | expression_node<T>* b6 = reinterpret_cast<expression_node<T>*>(0), 06708 | expression_node<T>* b7 = reinterpret_cast<expression_node<T>*>(0), 06709 | expression_node<T>* b8 = reinterpret_cast<expression_node<T>*>(0), 06710 | expression_node<T>* b9 = reinterpret_cast<expression_node<T>*>(0)) 06711 | { 06712 | construct_branch_pair(branch, b0, 0); 06713 | construct_branch_pair(branch, b1, 1); 06714 | construct_branch_pair(branch, b2, 2); 06715 | construct_branch_pair(branch, b3, 3); 06716 | construct_branch_pair(branch, b4, 4); 06717 | construct_branch_pair(branch, b5, 5); 06718 | construct_branch_pair(branch, b6, 6); 06719 | construct_branch_pair(branch, b7, 7); 06720 | construct_branch_pair(branch, b8, 8); 06721 | construct_branch_pair(branch, b9, 9); 06722 | } 06723 | 06724 | template <typename T> 06725 | class null_eq_node exprtk_final : public expression_node<T> 06726 | { 06727 | public: 06728 | 06729 | typedef expression_node<T>* expression_ptr; 06730 | typedef std::pair<expression_ptr,bool> branch_t; 06731 | 06732 | explicit null_eq_node(expression_ptr branch, const bool equality = true) 06733 | : equality_(equality) 06734 | { 06735 | construct_branch_pair(branch_, branch); 06736 | assert(valid()); 06737 | } 06738 | 06739 | inline T value() const exprtk_override 06740 | { 06741 | const T v = branch_.first->value(); 06742 | const bool result = details::numeric::is_nan(v); 06743 | 06744 | if (result) 06745 | return equality_ ? T(1) : T(0); 06746 | else 06747 | return equality_ ? T(0) : T(1); 06748 | } 06749 | 06750 | inline typename expression_node<T>::node_type type() const exprtk_override 06751 | { 06752 | return expression_node<T>::e_nulleq; 06753 | } 06754 | 06755 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 06756 | { 06757 | return branch_.first; 06758 | } 06759 | 06760 | inline bool valid() const exprtk_override 06761 | { 06762 | return branch_.first; 06763 | } 06764 | 06765 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 06766 | { 06767 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 06768 | } 06769 | 06770 | std::size_t node_depth() const exprtk_override 06771 | { 06772 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 06773 | } 06774 | 06775 | private: 06776 | 06777 | bool equality_; 06778 | branch_t branch_; 06779 | }; 06780 | 06781 | template <typename T> 06782 | class literal_node exprtk_final : public expression_node<T> 06783 | { 06784 | public: 06785 | 06786 | explicit literal_node(const T& v) 06787 | : value_(v) 06788 | {} 06789 | 06790 | inline T value() const exprtk_override 06791 | { 06792 | return value_; 06793 | } 06794 | 06795 | inline typename expression_node<T>::node_type type() const exprtk_override 06796 | { 06797 | return expression_node<T>::e_constant; 06798 | } 06799 | 06800 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 06801 | { 06802 | return reinterpret_cast<expression_node<T>*>(0); 06803 | } 06804 | 06805 | private: 06806 | 06807 | literal_node(const literal_node<T>&) exprtk_delete; 06808 | literal_node<T>& operator=(const literal_node<T>&) exprtk_delete; 06809 | 06810 | const T value_; 06811 | }; 06812 | 06813 | template <typename T> 06814 | struct range_pack; 06815 | 06816 | template <typename T> 06817 | struct range_data_type; 06818 | 06819 | template <typename T> 06820 | class range_interface 06821 | { 06822 | public: 06823 | 06824 | typedef range_pack<T> range_t; 06825 | 06826 | virtual ~range_interface() 06827 | {} 06828 | 06829 | virtual range_t& range_ref() = 0; 06830 | 06831 | virtual const range_t& range_ref() const = 0; 06832 | }; 06833 | 06834 | #ifndef exprtk_disable_string_capabilities 06835 | template <typename T> 06836 | class string_base_node 06837 | { 06838 | public: 06839 | 06840 | typedef range_data_type<T> range_data_type_t; 06841 | 06842 | virtual ~string_base_node() 06843 | {} 06844 | 06845 | virtual std::string str () const = 0; 06846 | 06847 | virtual char_cptr base() const = 0; 06848 | 06849 | virtual std::size_t size() const = 0; 06850 | }; 06851 | 06852 | template <typename T> 06853 | class string_literal_node exprtk_final 06854 | : public expression_node <T> 06855 | , public string_base_node<T> 06856 | , public range_interface <T> 06857 | { 06858 | public: 06859 | 06860 | typedef range_pack<T> range_t; 06861 | 06862 | explicit string_literal_node(const std::string& v) 06863 | : value_(v) 06864 | { 06865 | rp_.n0_c = std::make_pair<bool,std::size_t>(true, 0); 06866 | rp_.n1_c = std::make_pair<bool,std::size_t>(true, v.size()); 06867 | rp_.cache.first = rp_.n0_c.second; 06868 | rp_.cache.second = rp_.n1_c.second; 06869 | } 06870 | 06871 | inline T value() const exprtk_override 06872 | { 06873 | return std::numeric_limits<T>::quiet_NaN(); 06874 | } 06875 | 06876 | inline typename expression_node<T>::node_type type() const exprtk_override 06877 | { 06878 | return expression_node<T>::e_stringconst; 06879 | } 06880 | 06881 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 06882 | { 06883 | return reinterpret_cast<expression_node<T>*>(0); 06884 | } 06885 | 06886 | std::string str() const exprtk_override 06887 | { 06888 | return value_; 06889 | } 06890 | 06891 | char_cptr base() const exprtk_override 06892 | { 06893 | return value_.data(); 06894 | } 06895 | 06896 | std::size_t size() const exprtk_override 06897 | { 06898 | return value_.size(); 06899 | } 06900 | 06901 | range_t& range_ref() exprtk_override 06902 | { 06903 | return rp_; 06904 | } 06905 | 06906 | const range_t& range_ref() const exprtk_override 06907 | { 06908 | return rp_; 06909 | } 06910 | 06911 | private: 06912 | 06913 | string_literal_node(const string_literal_node<T>&) exprtk_delete; 06914 | string_literal_node<T>& operator=(const string_literal_node<T>&) exprtk_delete; 06915 | 06916 | const std::string value_; 06917 | range_t rp_; 06918 | }; 06919 | #endif 06920 | 06921 | template <typename T> 06922 | class unary_node : public expression_node<T> 06923 | { 06924 | public: 06925 | 06926 | typedef expression_node<T>* expression_ptr; 06927 | typedef std::pair<expression_ptr,bool> branch_t; 06928 | 06929 | unary_node(const operator_type& opr, expression_ptr branch) 06930 | : operation_(opr) 06931 | { 06932 | construct_branch_pair(branch_,branch); 06933 | assert(valid()); 06934 | } 06935 | 06936 | inline T value() const exprtk_override 06937 | { 06938 | return numeric::process<T> 06939 | (operation_,branch_.first->value()); 06940 | } 06941 | 06942 | inline typename expression_node<T>::node_type type() const exprtk_override 06943 | { 06944 | return expression_node<T>::e_unary; 06945 | } 06946 | 06947 | inline operator_type operation() 06948 | { 06949 | return operation_; 06950 | } 06951 | 06952 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 06953 | { 06954 | return branch_.first; 06955 | } 06956 | 06957 | inline bool valid() const exprtk_override 06958 | { 06959 | return branch_.first && branch_.first->valid(); 06960 | } 06961 | 06962 | inline void release() 06963 | { 06964 | branch_.second = false; 06965 | } 06966 | 06967 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 06968 | { 06969 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 06970 | } 06971 | 06972 | std::size_t node_depth() const exprtk_final 06973 | { 06974 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 06975 | } 06976 | 06977 | private: 06978 | 06979 | operator_type operation_; 06980 | branch_t branch_; 06981 | }; 06982 | 06983 | template <typename T> 06984 | class binary_node : public expression_node<T> 06985 | { 06986 | public: 06987 | 06988 | typedef expression_node<T>* expression_ptr; 06989 | typedef std::pair<expression_ptr,bool> branch_t; 06990 | 06991 | binary_node(const operator_type& opr, 06992 | expression_ptr branch0, 06993 | expression_ptr branch1) 06994 | : operation_(opr) 06995 | { 06996 | init_branches<2>(branch_, branch0, branch1); 06997 | assert(valid()); 06998 | } 06999 | 07000 | inline T value() const exprtk_override 07001 | { 07002 | return numeric::process<T> 07003 | ( 07004 | operation_, 07005 | branch_[0].first->value(), 07006 | branch_[1].first->value() 07007 | ); 07008 | } 07009 | 07010 | inline typename expression_node<T>::node_type type() const exprtk_override 07011 | { 07012 | return expression_node<T>::e_binary; 07013 | } 07014 | 07015 | inline operator_type operation() 07016 | { 07017 | return operation_; 07018 | } 07019 | 07020 | inline expression_node<T>* branch(const std::size_t& index = 0) const exprtk_override 07021 | { 07022 | assert(index < 2); 07023 | return branch_[index].first; 07024 | } 07025 | 07026 | inline bool valid() const exprtk_override 07027 | { 07028 | return 07029 | branch_[0].first && branch_[0].first->valid() && 07030 | branch_[1].first && branch_[1].first->valid() ; 07031 | } 07032 | 07033 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07034 | { 07035 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 07036 | } 07037 | 07038 | std::size_t node_depth() const exprtk_final 07039 | { 07040 | return expression_node<T>::ndb_t::template compute_node_depth<2>(branch_); 07041 | } 07042 | 07043 | private: 07044 | 07045 | operator_type operation_; 07046 | branch_t branch_[2]; 07047 | }; 07048 | 07049 | template <typename T, typename Operation> 07050 | class binary_ext_node exprtk_final : public expression_node<T> 07051 | { 07052 | public: 07053 | 07054 | typedef expression_node<T>* expression_ptr; 07055 | typedef std::pair<expression_ptr,bool> branch_t; 07056 | 07057 | binary_ext_node(expression_ptr branch0, expression_ptr branch1) 07058 | { 07059 | init_branches<2>(branch_, branch0, branch1); 07060 | assert(valid()); 07061 | } 07062 | 07063 | inline T value() const exprtk_override 07064 | { 07065 | const T arg0 = branch_[0].first->value(); 07066 | const T arg1 = branch_[1].first->value(); 07067 | return Operation::process(arg0,arg1); 07068 | } 07069 | 07070 | inline typename expression_node<T>::node_type type() const exprtk_override 07071 | { 07072 | return expression_node<T>::e_binary_ext; 07073 | } 07074 | 07075 | inline operator_type operation() 07076 | { 07077 | return Operation::operation(); 07078 | } 07079 | 07080 | inline expression_node<T>* branch(const std::size_t& index = 0) const exprtk_override 07081 | { 07082 | assert(index < 2); 07083 | return branch_[index].first; 07084 | } 07085 | 07086 | inline bool valid() const exprtk_override 07087 | { 07088 | return 07089 | branch_[0].first && branch_[0].first->valid() && 07090 | branch_[1].first && branch_[1].first->valid() ; 07091 | } 07092 | 07093 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07094 | { 07095 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 07096 | } 07097 | 07098 | std::size_t node_depth() const exprtk_override 07099 | { 07100 | return expression_node<T>::ndb_t::template compute_node_depth<2>(branch_); 07101 | } 07102 | 07103 | protected: 07104 | 07105 | branch_t branch_[2]; 07106 | }; 07107 | 07108 | template <typename T> 07109 | class trinary_node : public expression_node<T> 07110 | { 07111 | public: 07112 | 07113 | typedef expression_node<T>* expression_ptr; 07114 | typedef std::pair<expression_ptr,bool> branch_t; 07115 | 07116 | trinary_node(const operator_type& opr, 07117 | expression_ptr branch0, 07118 | expression_ptr branch1, 07119 | expression_ptr branch2) 07120 | : operation_(opr) 07121 | { 07122 | init_branches<3>(branch_, branch0, branch1, branch2); 07123 | assert(valid()); 07124 | } 07125 | 07126 | inline T value() const exprtk_override 07127 | { 07128 | const T arg0 = branch_[0].first->value(); 07129 | const T arg1 = branch_[1].first->value(); 07130 | const T arg2 = branch_[2].first->value(); 07131 | 07132 | switch (operation_) 07133 | { 07134 | case e_inrange : return (arg1 < arg0) ? T(0) : ((arg1 > arg2) ? T(0) : T(1)); 07135 | 07136 | case e_clamp : return (arg1 < arg0) ? arg0 : (arg1 > arg2 ? arg2 : arg1); 07137 | 07138 | case e_iclamp : if ((arg1 <= arg0) || (arg1 >= arg2)) 07139 | return arg1; 07140 | else 07141 | return ((T(2) * arg1 <= (arg2 + arg0)) ? arg0 : arg2); 07142 | 07143 | default : exprtk_debug(("trinary_node::value() - Error: Invalid operation\n")); 07144 | return std::numeric_limits<T>::quiet_NaN(); 07145 | } 07146 | } 07147 | 07148 | inline typename expression_node<T>::node_type type() const exprtk_override 07149 | { 07150 | return expression_node<T>::e_trinary; 07151 | } 07152 | 07153 | inline bool valid() const exprtk_override 07154 | { 07155 | return 07156 | branch_[0].first && branch_[0].first->valid() && 07157 | branch_[1].first && branch_[1].first->valid() && 07158 | branch_[2].first && branch_[2].first->valid() ; 07159 | } 07160 | 07161 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07162 | { 07163 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 07164 | } 07165 | 07166 | std::size_t node_depth() const exprtk_override exprtk_final 07167 | { 07168 | return expression_node<T>::ndb_t::template compute_node_depth<3>(branch_); 07169 | } 07170 | 07171 | protected: 07172 | 07173 | operator_type operation_; 07174 | branch_t branch_[3]; 07175 | }; 07176 | 07177 | template <typename T> 07178 | class quaternary_node : public expression_node<T> 07179 | { 07180 | public: 07181 | 07182 | typedef expression_node<T>* expression_ptr; 07183 | typedef std::pair<expression_ptr,bool> branch_t; 07184 | 07185 | quaternary_node(const operator_type& opr, 07186 | expression_ptr branch0, 07187 | expression_ptr branch1, 07188 | expression_ptr branch2, 07189 | expression_ptr branch3) 07190 | : operation_(opr) 07191 | { 07192 | init_branches<4>(branch_, branch0, branch1, branch2, branch3); 07193 | } 07194 | 07195 | inline T value() const exprtk_override 07196 | { 07197 | return std::numeric_limits<T>::quiet_NaN(); 07198 | } 07199 | 07200 | inline typename expression_node<T>::node_type type() const exprtk_override 07201 | { 07202 | return expression_node<T>::e_quaternary; 07203 | } 07204 | 07205 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07206 | { 07207 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 07208 | } 07209 | 07210 | std::size_t node_depth() const exprtk_override exprtk_final 07211 | { 07212 | return expression_node<T>::ndb_t::template compute_node_depth<4>(branch_); 07213 | } 07214 | 07215 | inline bool valid() const exprtk_override 07216 | { 07217 | return 07218 | branch_[0].first && branch_[0].first->valid() && 07219 | branch_[1].first && branch_[1].first->valid() && 07220 | branch_[2].first && branch_[2].first->valid() && 07221 | branch_[3].first && branch_[3].first->valid() ; 07222 | } 07223 | 07224 | protected: 07225 | 07226 | operator_type operation_; 07227 | branch_t branch_[4]; 07228 | }; 07229 | 07230 | template <typename T> 07231 | class conditional_node exprtk_final : public expression_node<T> 07232 | { 07233 | public: 07234 | 07235 | typedef expression_node<T>* expression_ptr; 07236 | typedef std::pair<expression_ptr,bool> branch_t; 07237 | 07238 | conditional_node(expression_ptr condition, 07239 | expression_ptr consequent, 07240 | expression_ptr alternative) 07241 | { 07242 | construct_branch_pair(condition_ , condition ); 07243 | construct_branch_pair(consequent_ , consequent ); 07244 | construct_branch_pair(alternative_, alternative); 07245 | assert(valid()); 07246 | } 07247 | 07248 | inline T value() const exprtk_override 07249 | { 07250 | if (is_true(condition_)) 07251 | return consequent_.first->value(); 07252 | else 07253 | return alternative_.first->value(); 07254 | } 07255 | 07256 | inline typename expression_node<T>::node_type type() const exprtk_override 07257 | { 07258 | return expression_node<T>::e_conditional; 07259 | } 07260 | 07261 | inline bool valid() const exprtk_override 07262 | { 07263 | return 07264 | condition_ .first && condition_ .first->valid() && 07265 | consequent_ .first && consequent_ .first->valid() && 07266 | alternative_.first && alternative_.first->valid() ; 07267 | } 07268 | 07269 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07270 | { 07271 | expression_node<T>::ndb_t::collect(condition_ , node_delete_list); 07272 | expression_node<T>::ndb_t::collect(consequent_ , node_delete_list); 07273 | expression_node<T>::ndb_t::collect(alternative_ , node_delete_list); 07274 | } 07275 | 07276 | std::size_t node_depth() const exprtk_override 07277 | { 07278 | return expression_node<T>::ndb_t::compute_node_depth 07279 | (condition_, consequent_, alternative_); 07280 | } 07281 | 07282 | private: 07283 | 07284 | branch_t condition_; 07285 | branch_t consequent_; 07286 | branch_t alternative_; 07287 | }; 07288 | 07289 | template <typename T> 07290 | class cons_conditional_node exprtk_final : public expression_node<T> 07291 | { 07292 | public: 07293 | 07294 | // Consequent only conditional statement node 07295 | typedef expression_node<T>* expression_ptr; 07296 | typedef std::pair<expression_ptr,bool> branch_t; 07297 | 07298 | cons_conditional_node(expression_ptr condition, 07299 | expression_ptr consequent) 07300 | { 07301 | construct_branch_pair(condition_ , condition ); 07302 | construct_branch_pair(consequent_, consequent); 07303 | assert(valid()); 07304 | } 07305 | 07306 | inline T value() const exprtk_override 07307 | { 07308 | if (is_true(condition_)) 07309 | return consequent_.first->value(); 07310 | else 07311 | return std::numeric_limits<T>::quiet_NaN(); 07312 | } 07313 | 07314 | inline typename expression_node<T>::node_type type() const exprtk_override 07315 | { 07316 | return expression_node<T>::e_conditional; 07317 | } 07318 | 07319 | inline bool valid() const exprtk_override 07320 | { 07321 | return 07322 | condition_ .first && condition_ .first->valid() && 07323 | consequent_.first && consequent_.first->valid() ; 07324 | } 07325 | 07326 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07327 | { 07328 | expression_node<T>::ndb_t::collect(condition_ , node_delete_list); 07329 | expression_node<T>::ndb_t::collect(consequent_ , node_delete_list); 07330 | } 07331 | 07332 | std::size_t node_depth() const exprtk_override 07333 | { 07334 | return expression_node<T>::ndb_t:: 07335 | compute_node_depth(condition_, consequent_); 07336 | } 07337 | 07338 | private: 07339 | 07340 | branch_t condition_; 07341 | branch_t consequent_; 07342 | }; 07343 | 07344 | #ifndef exprtk_disable_break_continue 07345 | template <typename T> 07346 | class break_exception 07347 | { 07348 | public: 07349 | 07350 | explicit break_exception(const T& v) 07351 | : value(v) 07352 | {} 07353 | 07354 | T value; 07355 | }; 07356 | 07357 | class continue_exception {}; 07358 | 07359 | template <typename T> 07360 | class break_node exprtk_final : public expression_node<T> 07361 | { 07362 | public: 07363 | 07364 | typedef expression_node<T>* expression_ptr; 07365 | typedef std::pair<expression_ptr,bool> branch_t; 07366 | 07367 | explicit break_node(expression_ptr ret = expression_ptr(0)) 07368 | { 07369 | construct_branch_pair(return_, ret); 07370 | } 07371 | 07372 | inline T value() const exprtk_override 07373 | { 07374 | const T result = return_.first ? 07375 | return_.first->value() : 07376 | std::numeric_limits<T>::quiet_NaN(); 07377 | 07378 | throw break_exception<T>(result); 07379 | 07380 | #if !defined(_MSC_VER) && !defined(__NVCOMPILER) 07381 | return std::numeric_limits<T>::quiet_NaN(); 07382 | #endif 07383 | } 07384 | 07385 | inline typename expression_node<T>::node_type type() const exprtk_override 07386 | { 07387 | return expression_node<T>::e_break; 07388 | } 07389 | 07390 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07391 | { 07392 | expression_node<T>::ndb_t::collect(return_, node_delete_list); 07393 | } 07394 | 07395 | std::size_t node_depth() const exprtk_override 07396 | { 07397 | return expression_node<T>::ndb_t::compute_node_depth(return_); 07398 | } 07399 | 07400 | private: 07401 | 07402 | branch_t return_; 07403 | }; 07404 | 07405 | template <typename T> 07406 | class continue_node exprtk_final : public expression_node<T> 07407 | { 07408 | public: 07409 | 07410 | inline T value() const exprtk_override 07411 | { 07412 | throw continue_exception(); 07413 | #if !defined(_MSC_VER) && !defined(__NVCOMPILER) 07414 | return std::numeric_limits<T>::quiet_NaN(); 07415 | #endif 07416 | } 07417 | 07418 | inline typename expression_node<T>::node_type type() const exprtk_override 07419 | { 07420 | return expression_node<T>::e_break; 07421 | } 07422 | }; 07423 | #endif 07424 | 07425 | struct loop_runtime_checker 07426 | { 07427 | loop_runtime_checker(loop_runtime_check_ptr loop_runtime_check, 07428 | loop_runtime_check::loop_types lp_typ = loop_runtime_check::e_invalid) 07429 | : iteration_count_(0) 07430 | , loop_runtime_check_(loop_runtime_check) 07431 | , max_loop_iterations_(loop_runtime_check_->max_loop_iterations) 07432 | , loop_type_(lp_typ) 07433 | { 07434 | assert(loop_runtime_check_); 07435 | } 07436 | 07437 | inline void reset(const _uint64_t initial_value = 0) const 07438 | { 07439 | iteration_count_ = initial_value; 07440 | } 07441 | 07442 | inline bool check() const 07443 | { 07444 | assert(loop_runtime_check_); 07445 | 07446 | if ( 07447 | (++iteration_count_ <= max_loop_iterations_) && 07448 | loop_runtime_check_->check() 07449 | ) 07450 | { 07451 | return true; 07452 | } 07453 | 07454 | loop_runtime_check::violation_context ctxt; 07455 | ctxt.loop = loop_type_; 07456 | ctxt.violation = loop_runtime_check::e_iteration_count; 07457 | 07458 | loop_runtime_check_->handle_runtime_violation(ctxt); 07459 | 07460 | return false; 07461 | } 07462 | 07463 | bool valid() const 07464 | { 07465 | return 0 != loop_runtime_check_; 07466 | } 07467 | 07468 | mutable _uint64_t iteration_count_; 07469 | mutable loop_runtime_check_ptr loop_runtime_check_; 07470 | const details::_uint64_t& max_loop_iterations_; 07471 | loop_runtime_check::loop_types loop_type_; 07472 | }; 07473 | 07474 | template <typename T> 07475 | class while_loop_node : public expression_node<T> 07476 | { 07477 | public: 07478 | 07479 | typedef expression_node<T>* expression_ptr; 07480 | typedef std::pair<expression_ptr,bool> branch_t; 07481 | 07482 | while_loop_node(expression_ptr condition, 07483 | expression_ptr loop_body) 07484 | { 07485 | construct_branch_pair(condition_, condition); 07486 | construct_branch_pair(loop_body_, loop_body); 07487 | assert(valid()); 07488 | } 07489 | 07490 | inline T value() const exprtk_override 07491 | { 07492 | T result = T(0); 07493 | 07494 | while (is_true(condition_)) 07495 | { 07496 | result = loop_body_.first->value(); 07497 | } 07498 | 07499 | return result; 07500 | } 07501 | 07502 | inline typename expression_node<T>::node_type type() const exprtk_override 07503 | { 07504 | return expression_node<T>::e_while; 07505 | } 07506 | 07507 | inline bool valid() const exprtk_override 07508 | { 07509 | return 07510 | condition_.first && condition_.first->valid() && 07511 | loop_body_.first && loop_body_.first->valid() ; 07512 | } 07513 | 07514 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07515 | { 07516 | expression_node<T>::ndb_t::collect(condition_ , node_delete_list); 07517 | expression_node<T>::ndb_t::collect(loop_body_ , node_delete_list); 07518 | } 07519 | 07520 | std::size_t node_depth() const exprtk_override 07521 | { 07522 | return expression_node<T>::ndb_t::compute_node_depth(condition_, loop_body_); 07523 | } 07524 | 07525 | protected: 07526 | 07527 | branch_t condition_; 07528 | branch_t loop_body_; 07529 | }; 07530 | 07531 | template <typename T> 07532 | class while_loop_rtc_node exprtk_final 07533 | : public while_loop_node<T> 07534 | , public loop_runtime_checker 07535 | { 07536 | public: 07537 | 07538 | typedef while_loop_node<T> parent_t; 07539 | typedef expression_node<T>* expression_ptr; 07540 | 07541 | while_loop_rtc_node(expression_ptr condition, 07542 | expression_ptr loop_body, 07543 | loop_runtime_check_ptr loop_rt_chk) 07544 | : parent_t(condition, loop_body) 07545 | , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_while_loop) 07546 | { 07547 | assert(valid()); 07548 | } 07549 | 07550 | inline T value() const exprtk_override 07551 | { 07552 | 07553 | T result = T(0); 07554 | 07555 | loop_runtime_checker::reset(); 07556 | 07557 | while (is_true(parent_t::condition_) && loop_runtime_checker::check()) 07558 | { 07559 | result = parent_t::loop_body_.first->value(); 07560 | } 07561 | 07562 | return result; 07563 | } 07564 | 07565 | using parent_t::valid; 07566 | 07567 | bool valid() const exprtk_override exprtk_final 07568 | { 07569 | return parent_t::valid() && 07570 | loop_runtime_checker::valid(); 07571 | } 07572 | }; 07573 | 07574 | template <typename T> 07575 | class repeat_until_loop_node : public expression_node<T> 07576 | { 07577 | public: 07578 | 07579 | typedef expression_node<T>* expression_ptr; 07580 | typedef std::pair<expression_ptr,bool> branch_t; 07581 | 07582 | repeat_until_loop_node(expression_ptr condition, 07583 | expression_ptr loop_body) 07584 | { 07585 | construct_branch_pair(condition_, condition); 07586 | construct_branch_pair(loop_body_, loop_body); 07587 | assert(valid()); 07588 | } 07589 | 07590 | inline T value() const exprtk_override 07591 | { 07592 | T result = T(0); 07593 | 07594 | do 07595 | { 07596 | result = loop_body_.first->value(); 07597 | } 07598 | while (is_false(condition_.first)); 07599 | 07600 | return result; 07601 | } 07602 | 07603 | inline typename expression_node<T>::node_type type() const exprtk_override 07604 | { 07605 | return expression_node<T>::e_repeat; 07606 | } 07607 | 07608 | inline bool valid() const exprtk_override 07609 | { 07610 | return 07611 | condition_.first && condition_.first->valid() && 07612 | loop_body_.first && loop_body_.first->valid() ; 07613 | } 07614 | 07615 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07616 | { 07617 | expression_node<T>::ndb_t::collect(condition_ , node_delete_list); 07618 | expression_node<T>::ndb_t::collect(loop_body_ , node_delete_list); 07619 | } 07620 | 07621 | std::size_t node_depth() const exprtk_override 07622 | { 07623 | return expression_node<T>::ndb_t::compute_node_depth(condition_, loop_body_); 07624 | } 07625 | 07626 | protected: 07627 | 07628 | branch_t condition_; 07629 | branch_t loop_body_; 07630 | }; 07631 | 07632 | template <typename T> 07633 | class repeat_until_loop_rtc_node exprtk_final 07634 | : public repeat_until_loop_node<T> 07635 | , public loop_runtime_checker 07636 | { 07637 | public: 07638 | 07639 | typedef repeat_until_loop_node<T> parent_t; 07640 | typedef expression_node<T>* expression_ptr; 07641 | 07642 | repeat_until_loop_rtc_node(expression_ptr condition, 07643 | expression_ptr loop_body, 07644 | loop_runtime_check_ptr loop_rt_chk) 07645 | : parent_t(condition, loop_body) 07646 | , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_repeat_until_loop) 07647 | { 07648 | assert(valid()); 07649 | } 07650 | 07651 | inline T value() const exprtk_override 07652 | { 07653 | T result = T(0); 07654 | 07655 | loop_runtime_checker::reset(1); 07656 | 07657 | do 07658 | { 07659 | result = parent_t::loop_body_.first->value(); 07660 | } 07661 | while (is_false(parent_t::condition_.first) && loop_runtime_checker::check()); 07662 | 07663 | return result; 07664 | } 07665 | 07666 | using parent_t::valid; 07667 | 07668 | inline bool valid() const exprtk_override exprtk_final 07669 | { 07670 | return parent_t::valid() && 07671 | loop_runtime_checker::valid(); 07672 | } 07673 | }; 07674 | 07675 | template <typename T> 07676 | class for_loop_node : public expression_node<T> 07677 | { 07678 | public: 07679 | 07680 | typedef expression_node<T>* expression_ptr; 07681 | typedef std::pair<expression_ptr,bool> branch_t; 07682 | 07683 | for_loop_node(expression_ptr initialiser, 07684 | expression_ptr condition, 07685 | expression_ptr incrementor, 07686 | expression_ptr loop_body) 07687 | { 07688 | construct_branch_pair(initialiser_, initialiser); 07689 | construct_branch_pair(condition_ , condition ); 07690 | construct_branch_pair(incrementor_, incrementor); 07691 | construct_branch_pair(loop_body_ , loop_body ); 07692 | assert(valid()); 07693 | } 07694 | 07695 | inline T value() const exprtk_override 07696 | { 07697 | T result = T(0); 07698 | 07699 | if (initialiser_.first) 07700 | initialiser_.first->value(); 07701 | 07702 | if (incrementor_.first) 07703 | { 07704 | while (is_true(condition_)) 07705 | { 07706 | result = loop_body_.first->value(); 07707 | incrementor_.first->value(); 07708 | } 07709 | } 07710 | else 07711 | { 07712 | while (is_true(condition_)) 07713 | { 07714 | result = loop_body_.first->value(); 07715 | } 07716 | } 07717 | 07718 | return result; 07719 | } 07720 | 07721 | inline typename expression_node<T>::node_type type() const exprtk_override 07722 | { 07723 | return expression_node<T>::e_for; 07724 | } 07725 | 07726 | inline bool valid() const exprtk_override 07727 | { 07728 | return condition_.first && loop_body_.first; 07729 | } 07730 | 07731 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07732 | { 07733 | expression_node<T>::ndb_t::collect(initialiser_ , node_delete_list); 07734 | expression_node<T>::ndb_t::collect(condition_ , node_delete_list); 07735 | expression_node<T>::ndb_t::collect(incrementor_ , node_delete_list); 07736 | expression_node<T>::ndb_t::collect(loop_body_ , node_delete_list); 07737 | } 07738 | 07739 | std::size_t node_depth() const exprtk_override 07740 | { 07741 | return expression_node<T>::ndb_t::compute_node_depth 07742 | (initialiser_, condition_, incrementor_, loop_body_); 07743 | } 07744 | 07745 | protected: 07746 | 07747 | branch_t initialiser_; 07748 | branch_t condition_ ; 07749 | branch_t incrementor_; 07750 | branch_t loop_body_ ; 07751 | }; 07752 | 07753 | template <typename T> 07754 | class for_loop_rtc_node exprtk_final 07755 | : public for_loop_node<T> 07756 | , public loop_runtime_checker 07757 | { 07758 | public: 07759 | 07760 | typedef for_loop_node<T> parent_t; 07761 | typedef expression_node<T>* expression_ptr; 07762 | 07763 | for_loop_rtc_node(expression_ptr initialiser, 07764 | expression_ptr condition, 07765 | expression_ptr incrementor, 07766 | expression_ptr loop_body, 07767 | loop_runtime_check_ptr loop_rt_chk) 07768 | : parent_t(initialiser, condition, incrementor, loop_body) 07769 | , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_for_loop) 07770 | { 07771 | assert(valid()); 07772 | } 07773 | 07774 | inline T value() const exprtk_override 07775 | { 07776 | T result = T(0); 07777 | 07778 | loop_runtime_checker::reset(); 07779 | 07780 | if (parent_t::initialiser_.first) 07781 | parent_t::initialiser_.first->value(); 07782 | 07783 | if (parent_t::incrementor_.first) 07784 | { 07785 | while (is_true(parent_t::condition_) && loop_runtime_checker::check()) 07786 | { 07787 | result = parent_t::loop_body_.first->value(); 07788 | parent_t::incrementor_.first->value(); 07789 | } 07790 | } 07791 | else 07792 | { 07793 | while (is_true(parent_t::condition_) && loop_runtime_checker::check()) 07794 | { 07795 | result = parent_t::loop_body_.first->value(); 07796 | } 07797 | } 07798 | 07799 | return result; 07800 | } 07801 | 07802 | using parent_t::valid; 07803 | 07804 | inline bool valid() const exprtk_override exprtk_final 07805 | { 07806 | return parent_t::valid() && 07807 | loop_runtime_checker::valid(); 07808 | } 07809 | }; 07810 | 07811 | #ifndef exprtk_disable_break_continue 07812 | template <typename T> 07813 | class while_loop_bc_node : public while_loop_node<T> 07814 | { 07815 | public: 07816 | 07817 | typedef while_loop_node<T> parent_t; 07818 | typedef expression_node<T>* expression_ptr; 07819 | 07820 | while_loop_bc_node(expression_ptr condition, 07821 | expression_ptr loop_body) 07822 | : parent_t(condition, loop_body) 07823 | { 07824 | assert(parent_t::valid()); 07825 | } 07826 | 07827 | inline T value() const exprtk_override 07828 | { 07829 | T result = T(0); 07830 | 07831 | while (is_true(parent_t::condition_)) 07832 | { 07833 | try 07834 | { 07835 | result = parent_t::loop_body_.first->value(); 07836 | } 07837 | catch(const break_exception<T>& e) 07838 | { 07839 | return e.value; 07840 | } 07841 | catch(const continue_exception&) 07842 | {} 07843 | } 07844 | 07845 | return result; 07846 | } 07847 | }; 07848 | 07849 | template <typename T> 07850 | class while_loop_bc_rtc_node exprtk_final 07851 | : public while_loop_bc_node<T> 07852 | , public loop_runtime_checker 07853 | { 07854 | public: 07855 | 07856 | typedef while_loop_bc_node<T> parent_t; 07857 | typedef expression_node<T>* expression_ptr; 07858 | 07859 | while_loop_bc_rtc_node(expression_ptr condition, 07860 | expression_ptr loop_body, 07861 | loop_runtime_check_ptr loop_rt_chk) 07862 | : parent_t(condition, loop_body) 07863 | , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_while_loop) 07864 | { 07865 | assert(valid()); 07866 | } 07867 | 07868 | inline T value() const exprtk_override 07869 | { 07870 | T result = T(0); 07871 | 07872 | loop_runtime_checker::reset(); 07873 | 07874 | while (is_true(parent_t::condition_) && loop_runtime_checker::check()) 07875 | { 07876 | try 07877 | { 07878 | result = parent_t::loop_body_.first->value(); 07879 | } 07880 | catch(const break_exception<T>& e) 07881 | { 07882 | return e.value; 07883 | } 07884 | catch(const continue_exception&) 07885 | {} 07886 | } 07887 | 07888 | return result; 07889 | } 07890 | 07891 | using parent_t::valid; 07892 | 07893 | inline bool valid() const exprtk_override exprtk_final 07894 | { 07895 | return parent_t::valid() && 07896 | loop_runtime_checker::valid(); 07897 | } 07898 | }; 07899 | 07900 | template <typename T> 07901 | class repeat_until_loop_bc_node : public repeat_until_loop_node<T> 07902 | { 07903 | public: 07904 | 07905 | typedef repeat_until_loop_node<T> parent_t; 07906 | typedef expression_node<T>* expression_ptr; 07907 | 07908 | repeat_until_loop_bc_node(expression_ptr condition, 07909 | expression_ptr loop_body) 07910 | : parent_t(condition, loop_body) 07911 | { 07912 | assert(parent_t::valid()); 07913 | } 07914 | 07915 | inline T value() const exprtk_override 07916 | { 07917 | T result = T(0); 07918 | 07919 | do 07920 | { 07921 | try 07922 | { 07923 | result = parent_t::loop_body_.first->value(); 07924 | } 07925 | catch(const break_exception<T>& e) 07926 | { 07927 | return e.value; 07928 | } 07929 | catch(const continue_exception&) 07930 | {} 07931 | } 07932 | while (is_false(parent_t::condition_.first)); 07933 | 07934 | return result; 07935 | } 07936 | }; 07937 | 07938 | template <typename T> 07939 | class repeat_until_loop_bc_rtc_node exprtk_final 07940 | : public repeat_until_loop_bc_node<T> 07941 | , public loop_runtime_checker 07942 | { 07943 | public: 07944 | 07945 | typedef repeat_until_loop_bc_node<T> parent_t; 07946 | typedef expression_node<T>* expression_ptr; 07947 | 07948 | repeat_until_loop_bc_rtc_node(expression_ptr condition, 07949 | expression_ptr loop_body, 07950 | loop_runtime_check_ptr loop_rt_chk) 07951 | : parent_t(condition, loop_body) 07952 | , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_repeat_until_loop) 07953 | { 07954 | assert(valid()); 07955 | } 07956 | 07957 | inline T value() const exprtk_override 07958 | { 07959 | T result = T(0); 07960 | 07961 | loop_runtime_checker::reset(); 07962 | 07963 | do 07964 | { 07965 | try 07966 | { 07967 | result = parent_t::loop_body_.first->value(); 07968 | } 07969 | catch(const break_exception<T>& e) 07970 | { 07971 | return e.value; 07972 | } 07973 | catch(const continue_exception&) 07974 | {} 07975 | } 07976 | while (is_false(parent_t::condition_.first) && loop_runtime_checker::check()); 07977 | 07978 | return result; 07979 | } 07980 | 07981 | using parent_t::valid; 07982 | 07983 | inline bool valid() const exprtk_override exprtk_final 07984 | { 07985 | return parent_t::valid() && 07986 | loop_runtime_checker::valid(); 07987 | } 07988 | }; 07989 | 07990 | template <typename T> 07991 | class for_loop_bc_node : public for_loop_node<T> 07992 | { 07993 | public: 07994 | 07995 | typedef for_loop_node<T> parent_t; 07996 | typedef expression_node<T>* expression_ptr; 07997 | 07998 | for_loop_bc_node(expression_ptr initialiser, 07999 | expression_ptr condition, 08000 | expression_ptr incrementor, 08001 | expression_ptr loop_body) 08002 | : parent_t(initialiser, condition, incrementor, loop_body) 08003 | { 08004 | assert(parent_t::valid()); 08005 | } 08006 | 08007 | inline T value() const exprtk_override 08008 | { 08009 | T result = T(0); 08010 | 08011 | if (parent_t::initialiser_.first) 08012 | parent_t::initialiser_.first->value(); 08013 | 08014 | if (parent_t::incrementor_.first) 08015 | { 08016 | while (is_true(parent_t::condition_)) 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 | parent_t::incrementor_.first->value(); 08030 | } 08031 | } 08032 | else 08033 | { 08034 | while (is_true(parent_t::condition_)) 08035 | { 08036 | try 08037 | { 08038 | result = parent_t::loop_body_.first->value(); 08039 | } 08040 | catch(const break_exception<T>& e) 08041 | { 08042 | return e.value; 08043 | } 08044 | catch(const continue_exception&) 08045 | {} 08046 | } 08047 | } 08048 | 08049 | return result; 08050 | } 08051 | }; 08052 | 08053 | template <typename T> 08054 | class for_loop_bc_rtc_node exprtk_final 08055 | : public for_loop_bc_node<T> 08056 | , public loop_runtime_checker 08057 | { 08058 | public: 08059 | 08060 | typedef for_loop_bc_node<T> parent_t; 08061 | typedef expression_node<T>* expression_ptr; 08062 | 08063 | for_loop_bc_rtc_node(expression_ptr initialiser, 08064 | expression_ptr condition, 08065 | expression_ptr incrementor, 08066 | expression_ptr loop_body, 08067 | loop_runtime_check_ptr loop_rt_chk) 08068 | : parent_t(initialiser, condition, incrementor, loop_body) 08069 | , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_for_loop) 08070 | { 08071 | assert(valid()); 08072 | } 08073 | 08074 | inline T value() const exprtk_override 08075 | { 08076 | T result = T(0); 08077 | 08078 | loop_runtime_checker::reset(); 08079 | 08080 | if (parent_t::initialiser_.first) 08081 | parent_t::initialiser_.first->value(); 08082 | 08083 | if (parent_t::incrementor_.first) 08084 | { 08085 | while (is_true(parent_t::condition_) && loop_runtime_checker::check()) 08086 | { 08087 | try 08088 | { 08089 | result = parent_t::loop_body_.first->value(); 08090 | } 08091 | catch(const break_exception<T>& e) 08092 | { 08093 | return e.value; 08094 | } 08095 | catch(const continue_exception&) 08096 | {} 08097 | 08098 | parent_t::incrementor_.first->value(); 08099 | } 08100 | } 08101 | else 08102 | { 08103 | while (is_true(parent_t::condition_) && loop_runtime_checker::check()) 08104 | { 08105 | try 08106 | { 08107 | result = parent_t::loop_body_.first->value(); 08108 | } 08109 | catch(const break_exception<T>& e) 08110 | { 08111 | return e.value; 08112 | } 08113 | catch(const continue_exception&) 08114 | {} 08115 | } 08116 | } 08117 | 08118 | return result; 08119 | } 08120 | 08121 | using parent_t::valid; 08122 | 08123 | inline bool valid() const exprtk_override exprtk_final 08124 | { 08125 | return parent_t::valid() && 08126 | loop_runtime_checker::valid(); 08127 | } 08128 | }; 08129 | #endif 08130 | 08131 | template <typename T> 08132 | class switch_node : public expression_node<T> 08133 | { 08134 | public: 08135 | 08136 | typedef expression_node<T>* expression_ptr; 08137 | typedef std::pair<expression_ptr,bool> branch_t; 08138 | 08139 | template <typename Allocator, 08140 | template <typename, typename> class Sequence> 08141 | explicit switch_node(const Sequence<expression_ptr,Allocator>& arg_list) 08142 | { 08143 | if (1 != (arg_list.size() & 1)) 08144 | return; 08145 | 08146 | arg_list_.resize(arg_list.size()); 08147 | 08148 | for (std::size_t i = 0; i < arg_list.size(); ++i) 08149 | { 08150 | if (arg_list[i] && arg_list[i]->valid()) 08151 | { 08152 | construct_branch_pair(arg_list_[i], arg_list[i]); 08153 | } 08154 | else 08155 | { 08156 | arg_list_.clear(); 08157 | return; 08158 | } 08159 | } 08160 | 08161 | assert(valid()); 08162 | } 08163 | 08164 | inline T value() const exprtk_override 08165 | { 08166 | const std::size_t upper_bound = (arg_list_.size() - 1); 08167 | 08168 | for (std::size_t i = 0; i < upper_bound; i += 2) 08169 | { 08170 | expression_ptr condition = arg_list_[i ].first; 08171 | expression_ptr consequent = arg_list_[i + 1].first; 08172 | 08173 | if (is_true(condition)) 08174 | { 08175 | return consequent->value(); 08176 | } 08177 | } 08178 | 08179 | return arg_list_[upper_bound].first->value(); 08180 | } 08181 | 08182 | inline typename expression_node<T>::node_type type() const exprtk_override exprtk_final 08183 | { 08184 | return expression_node<T>::e_switch; 08185 | } 08186 | 08187 | inline bool valid() const exprtk_override 08188 | { 08189 | return !arg_list_.empty(); 08190 | } 08191 | 08192 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 08193 | { 08194 | expression_node<T>::ndb_t::collect(arg_list_, node_delete_list); 08195 | } 08196 | 08197 | std::size_t node_depth() const exprtk_override exprtk_final 08198 | { 08199 | return expression_node<T>::ndb_t::compute_node_depth(arg_list_); 08200 | } 08201 | 08202 | protected: 08203 | 08204 | std::vector<branch_t> arg_list_; 08205 | }; 08206 | 08207 | template <typename T, typename Switch_N> 08208 | class switch_n_node exprtk_final : public switch_node<T> 08209 | { 08210 | public: 08211 | 08212 | typedef expression_node<T>* expression_ptr; 08213 | 08214 | template <typename Allocator, 08215 | template <typename, typename> class Sequence> 08216 | explicit switch_n_node(const Sequence<expression_ptr,Allocator>& arg_list) 08217 | : switch_node<T>(arg_list) 08218 | {} 08219 | 08220 | inline T value() const exprtk_override 08221 | { 08222 | return Switch_N::process(switch_node<T>::arg_list_); 08223 | } 08224 | }; 08225 | 08226 | template <typename T> 08227 | class multi_switch_node exprtk_final : public expression_node<T> 08228 | { 08229 | public: 08230 | 08231 | typedef expression_node<T>* expression_ptr; 08232 | typedef std::pair<expression_ptr,bool> branch_t; 08233 | 08234 | template <typename Allocator, 08235 | template <typename, typename> class Sequence> 08236 | explicit multi_switch_node(const Sequence<expression_ptr,Allocator>& arg_list) 08237 | { 08238 | if (0 != (arg_list.size() & 1)) 08239 | return; 08240 | 08241 | arg_list_.resize(arg_list.size()); 08242 | 08243 | for (std::size_t i = 0; i < arg_list.size(); ++i) 08244 | { 08245 | if (arg_list[i] && arg_list[i]->valid()) 08246 | { 08247 | construct_branch_pair(arg_list_[i], arg_list[i]); 08248 | } 08249 | else 08250 | { 08251 | arg_list_.clear(); 08252 | return; 08253 | } 08254 | } 08255 | 08256 | assert(valid()); 08257 | } 08258 | 08259 | inline T value() const exprtk_override 08260 | { 08261 | const std::size_t upper_bound = (arg_list_.size() - 1); 08262 | 08263 | T result = T(0); 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 | result = consequent->value(); 08273 | } 08274 | } 08275 | 08276 | return result; 08277 | } 08278 | 08279 | inline typename expression_node<T>::node_type type() const exprtk_override 08280 | { 08281 | return expression_node<T>::e_mswitch; 08282 | } 08283 | 08284 | inline bool valid() const exprtk_override 08285 | { 08286 | return !arg_list_.empty() && (0 == (arg_list_.size() % 2)); 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 | private: 08300 | 08301 | std::vector<branch_t> arg_list_; 08302 | }; 08303 | 08304 | template <typename T> 08305 | class ivariable 08306 | { 08307 | public: 08308 | 08309 | virtual ~ivariable() 08310 | {} 08311 | 08312 | virtual T& ref() = 0; 08313 | virtual const T& ref() const = 0; 08314 | }; 08315 | 08316 | template <typename T> 08317 | class variable_node exprtk_final 08318 | : public expression_node<T> 08319 | , public ivariable <T> 08320 | { 08321 | public: 08322 | 08323 | static T null_value; 08324 | 08325 | explicit variable_node() 08326 | : value_(&null_value) 08327 | {} 08328 | 08329 | explicit variable_node(T& v) 08330 | : value_(&v) 08331 | {} 08332 | 08333 | inline bool operator <(const variable_node<T>& v) const 08334 | { 08335 | return this < (&v); 08336 | } 08337 | 08338 | inline T value() const exprtk_override 08339 | { 08340 | return (*value_); 08341 | } 08342 | 08343 | inline T& ref() exprtk_override 08344 | { 08345 | return (*value_); 08346 | } 08347 | 08348 | inline const T& ref() const exprtk_override 08349 | { 08350 | return (*value_); 08351 | } 08352 | 08353 | inline typename expression_node<T>::node_type type() const exprtk_override 08354 | { 08355 | return expression_node<T>::e_variable; 08356 | } 08357 | 08358 | private: 08359 | 08360 | T* value_; 08361 | }; 08362 | 08363 | template <typename T> 08364 | T variable_node<T>::null_value = T(std::numeric_limits<T>::quiet_NaN()); 08365 | 08366 | template <typename T> 08367 | struct range_pack 08368 | { 08369 | typedef expression_node<T>* expression_node_ptr; 08370 | typedef std::pair<std::size_t,std::size_t> cached_range_t; 08371 | 08372 | range_pack() 08373 | : n0_e (std::make_pair(false,expression_node_ptr(0))) 08374 | , n1_e (std::make_pair(false,expression_node_ptr(0))) 08375 | , n0_c (std::make_pair(false,0)) 08376 | , n1_c (std::make_pair(false,0)) 08377 | , cache(std::make_pair(0,0)) 08378 | {} 08379 | 08380 | void clear() 08381 | { 08382 | n0_e = std::make_pair(false,expression_node_ptr(0)); 08383 | n1_e = std::make_pair(false,expression_node_ptr(0)); 08384 | n0_c = std::make_pair(false,0); 08385 | n1_c = std::make_pair(false,0); 08386 | cache = std::make_pair(0,0); 08387 | } 08388 | 08389 | void free() 08390 | { 08391 | if (n0_e.first && n0_e.second) 08392 | { 08393 | n0_e.first = false; 08394 | 08395 | if ( 08396 | !is_variable_node(n0_e.second) && 08397 | !is_string_node (n0_e.second) 08398 | ) 08399 | { 08400 | destroy_node(n0_e.second); 08401 | } 08402 | } 08403 | 08404 | if (n1_e.first && n1_e.second) 08405 | { 08406 | n1_e.first = false; 08407 | 08408 | if ( 08409 | !is_variable_node(n1_e.second) && 08410 | !is_string_node (n1_e.second) 08411 | ) 08412 | { 08413 | destroy_node(n1_e.second); 08414 | } 08415 | } 08416 | } 08417 | 08418 | bool const_range() const 08419 | { 08420 | return ( n0_c.first && n1_c.first) && 08421 | (!n0_e.first && !n1_e.first); 08422 | } 08423 | 08424 | bool var_range() const 08425 | { 08426 | return ( n0_e.first && n1_e.first) && 08427 | (!n0_c.first && !n1_c.first); 08428 | } 08429 | 08430 | bool operator() (std::size_t& r0, std::size_t& r1, 08431 | const std::size_t& size = std::numeric_limits<std::size_t>::max()) const 08432 | { 08433 | if (n0_c.first) 08434 | r0 = n0_c.second; 08435 | else if (n0_e.first) 08436 | { 08437 | r0 = static_cast<std::size_t>(details::numeric::to_int64(n0_e.second->value())); 08438 | } 08439 | else 08440 | return false; 08441 | 08442 | if (n1_c.first) 08443 | r1 = n1_c.second; 08444 | else if (n1_e.first) 08445 | { 08446 | r1 = static_cast<std::size_t>(details::numeric::to_int64(n1_e.second->value())); 08447 | } 08448 | else 08449 | return false; 08450 | 08451 | if ( 08452 | (std::numeric_limits<std::size_t>::max() != size) && 08453 | (std::numeric_limits<std::size_t>::max() == r1 ) 08454 | ) 08455 | { 08456 | r1 = size; 08457 | } 08458 | 08459 | cache.first = r0; 08460 | cache.second = r1; 08461 | 08462 | #ifndef exprtk_enable_range_runtime_checks 08463 | return (r0 <= r1); 08464 | #else 08465 | return range_runtime_check(r0, r1, size); 08466 | #endif 08467 | } 08468 | 08469 | inline std::size_t const_size() const 08470 | { 08471 | return (n1_c.second - n0_c.second); 08472 | } 08473 | 08474 | inline std::size_t cache_size() const 08475 | { 08476 | return (cache.second - cache.first); 08477 | } 08478 | 08479 | std::pair<bool,expression_node_ptr> n0_e; 08480 | std::pair<bool,expression_node_ptr> n1_e; 08481 | std::pair<bool,std::size_t > n0_c; 08482 | std::pair<bool,std::size_t > n1_c; 08483 | mutable cached_range_t cache; 08484 | 08485 | #ifdef exprtk_enable_range_runtime_checks 08486 | bool range_runtime_check(const std::size_t r0, 08487 | const std::size_t r1, 08488 | const std::size_t size) const 08489 | { 08490 | if (r0 > size) 08491 | { 08492 | throw std::runtime_error("range error: (r0 < 0) || (r0 > size)"); 08493 | #if !defined(_MSC_VER) && !defined(__NVCOMPILER) 08494 | return false; 08495 | #endif 08496 | } 08497 | 08498 | if (r1 > size) 08499 | { 08500 | throw std::runtime_error("range error: (r1 < 0) || (r1 > size)"); 08501 | #if !defined(_MSC_VER) && !defined(__NVCOMPILER) 08502 | return false; 08503 | #endif 08504 | } 08505 | 08506 | return (r0 <= r1); 08507 | } 08508 | #endif 08509 | }; 08510 | 08511 | template <typename T> 08512 | class string_base_node; 08513 | 08514 | template <typename T> 08515 | struct range_data_type 08516 | { 08517 | typedef range_pack<T> range_t; 08518 | typedef string_base_node<T>* strbase_ptr_t; 08519 | 08520 | range_data_type() 08521 | : range(0) 08522 | , data (0) 08523 | , size (0) 08524 | , type_size(0) 08525 | , str_node (0) 08526 | {} 08527 | 08528 | range_t* range; 08529 | void* data; 08530 | std::size_t size; 08531 | std::size_t type_size; 08532 | strbase_ptr_t str_node; 08533 | }; 08534 | 08535 | template <typename T> class vector_node; 08536 | 08537 | template <typename T> 08538 | class vector_interface 08539 | { 08540 | public: 08541 | 08542 | typedef vector_node<T>* vector_node_ptr; 08543 | typedef vec_data_store<T> vds_t; 08544 | 08545 | virtual ~vector_interface() 08546 | {} 08547 | 08548 | virtual std::size_t size () const = 0; 08549 | 08550 | virtual std::size_t base_size() const = 0; 08551 | 08552 | virtual vector_node_ptr vec () const = 0; 08553 | 08554 | virtual vector_node_ptr vec () = 0; 08555 | 08556 | virtual vds_t& vds () = 0; 08557 | 08558 | virtual const vds_t& vds () const = 0; 08559 | 08560 | virtual bool side_effect () const { return false; } 08561 | }; 08562 | 08563 | template <typename T> 08564 | class vector_node exprtk_final 08565 | : public expression_node <T> 08566 | , public vector_interface<T> 08567 | { 08568 | public: 08569 | 08570 | typedef expression_node<T>* expression_ptr; 08571 | typedef vector_holder<T> vector_holder_t; 08572 | typedef vector_node<T>* vector_node_ptr; 08573 | typedef vec_data_store<T> vds_t; 08574 | 08575 | explicit vector_node(vector_holder_t* vh) 08576 | : vector_holder_(vh) 08577 | , vds_((*vector_holder_).size(),(*vector_holder_)[0]) 08578 | { 08579 | vector_holder_->set_ref(&vds_.ref()); 08580 | } 08581 | 08582 | vector_node(const vds_t& vds, vector_holder_t* vh) 08583 | : vector_holder_(vh) 08584 | , vds_(vds) 08585 | {} 08586 | 08587 | ~vector_node() exprtk_override 08588 | { 08589 | assert(valid()); 08590 | vector_holder_->remove_ref(&vds_.ref()); 08591 | } 08592 | 08593 | inline T value() const exprtk_override 08594 | { 08595 | return vds().data()[0]; 08596 | } 08597 | 08598 | vector_node_ptr vec() const exprtk_override 08599 | { 08600 | return const_cast<vector_node_ptr>(this); 08601 | } 08602 | 08603 | vector_node_ptr vec() exprtk_override 08604 | { 08605 | return this; 08606 | } 08607 | 08608 | inline typename expression_node<T>::node_type type() const exprtk_override 08609 | { 08610 | return expression_node<T>::e_vector; 08611 | } 08612 | 08613 | inline bool valid() const exprtk_override 08614 | { 08615 | return vector_holder_; 08616 | } 08617 | 08618 | std::size_t size() const exprtk_override 08619 | { 08620 | return vec_holder().size(); 08621 | } 08622 | 08623 | std::size_t base_size() const exprtk_override 08624 | { 08625 | return vec_holder().base_size(); 08626 | } 08627 | 08628 | vds_t& vds() exprtk_override 08629 | { 08630 | return vds_; 08631 | } 08632 | 08633 | const vds_t& vds() const exprtk_override 08634 | { 08635 | return vds_; 08636 | } 08637 | 08638 | inline vector_holder_t& vec_holder() 08639 | { 08640 | return (*vector_holder_); 08641 | } 08642 | 08643 | inline vector_holder_t& vec_holder() const 08644 | { 08645 | return (*vector_holder_); 08646 | } 08647 | 08648 | private: 08649 | 08650 | vector_holder_t* vector_holder_; 08651 | vds_t vds_; 08652 | }; 08653 | 08654 | template <typename T> 08655 | class vector_size_node exprtk_final 08656 | : public expression_node <T> 08657 | { 08658 | public: 08659 | 08660 | typedef expression_node<T>* expression_ptr; 08661 | typedef vector_holder<T> vector_holder_t; 08662 | 08663 | explicit vector_size_node(vector_holder_t* vh) 08664 | : vector_holder_(vh) 08665 | {} 08666 | 08667 | ~vector_size_node() exprtk_override 08668 | { 08669 | assert(valid()); 08670 | } 08671 | 08672 | inline T value() const exprtk_override 08673 | { 08674 | assert(vector_holder_); 08675 | return static_cast<T>(vector_holder_->size()); 08676 | } 08677 | 08678 | inline typename expression_node<T>::node_type type() const exprtk_override 08679 | { 08680 | return expression_node<T>::e_vecsize; 08681 | } 08682 | 08683 | inline bool valid() const exprtk_override 08684 | { 08685 | return vector_holder_ && vector_holder_->size(); 08686 | } 08687 | 08688 | inline vector_holder_t* vec_holder() 08689 | { 08690 | return vector_holder_; 08691 | } 08692 | 08693 | private: 08694 | 08695 | vector_holder_t* vector_holder_; 08696 | }; 08697 | 08698 | template <typename T> 08699 | class vector_elem_node exprtk_final 08700 | : public expression_node<T> 08701 | , public ivariable <T> 08702 | { 08703 | public: 08704 | 08705 | typedef expression_node<T>* expression_ptr; 08706 | typedef vector_holder<T> vector_holder_t; 08707 | typedef vector_holder_t* vector_holder_ptr; 08708 | typedef std::pair<expression_ptr,bool> branch_t; 08709 | 08710 | vector_elem_node(expression_ptr vec_node, 08711 | expression_ptr index, 08712 | vector_holder_ptr vec_holder) 08713 | : vector_holder_(vec_holder) 08714 | , vector_base_((*vec_holder)[0]) 08715 | { 08716 | construct_branch_pair(vector_node_, vec_node); 08717 | construct_branch_pair(index_ , index ); 08718 | assert(valid()); 08719 | } 08720 | 08721 | inline T value() const exprtk_override 08722 | { 08723 | return *access_vector(); 08724 | } 08725 | 08726 | inline T& ref() exprtk_override 08727 | { 08728 | return *access_vector(); 08729 | } 08730 | 08731 | inline const T& ref() const exprtk_override 08732 | { 08733 | return *access_vector(); 08734 | } 08735 | 08736 | inline typename expression_node<T>::node_type type() const exprtk_override 08737 | { 08738 | return expression_node<T>::e_vecelem; 08739 | } 08740 | 08741 | inline bool valid() const exprtk_override 08742 | { 08743 | return 08744 | vector_holder_ && 08745 | index_.first && 08746 | vector_node_.first && 08747 | index_.first->valid() && 08748 | vector_node_.first->valid(); 08749 | } 08750 | 08751 | inline vector_holder_t& vec_holder() 08752 | { 08753 | return (*vector_holder_); 08754 | } 08755 | 08756 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 08757 | { 08758 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 08759 | expression_node<T>::ndb_t::collect(index_ , node_delete_list); 08760 | } 08761 | 08762 | std::size_t node_depth() const exprtk_override 08763 | { 08764 | return expression_node<T>::ndb_t::compute_node_depth 08765 | (vector_node_, index_); 08766 | } 08767 | 08768 | private: 08769 | 08770 | inline T* access_vector() const 08771 | { 08772 | vector_node_.first->value(); 08773 | return (vector_base_ + details::numeric::to_uint64(index_.first->value())); 08774 | } 08775 | 08776 | vector_holder_ptr vector_holder_; 08777 | T* vector_base_; 08778 | branch_t vector_node_; 08779 | branch_t index_; 08780 | }; 08781 | 08782 | template <typename T> 08783 | class vector_celem_node exprtk_final 08784 | : public expression_node<T> 08785 | , public ivariable <T> 08786 | { 08787 | public: 08788 | 08789 | typedef expression_node<T>* expression_ptr; 08790 | typedef vector_holder<T> vector_holder_t; 08791 | typedef vector_holder_t* vector_holder_ptr; 08792 | typedef std::pair<expression_ptr,bool> branch_t; 08793 | 08794 | vector_celem_node(expression_ptr vec_node, 08795 | const std::size_t index, 08796 | vector_holder_ptr vec_holder) 08797 | : index_(index) 08798 | , vector_holder_(vec_holder) 08799 | , vector_base_((*vec_holder)[0]) 08800 | { 08801 | construct_branch_pair(vector_node_, vec_node); 08802 | assert(valid()); 08803 | } 08804 | 08805 | inline T value() const exprtk_override 08806 | { 08807 | return *access_vector(); 08808 | } 08809 | 08810 | inline T& ref() exprtk_override 08811 | { 08812 | return *access_vector(); 08813 | } 08814 | 08815 | inline const T& ref() const exprtk_override 08816 | { 08817 | return *access_vector(); 08818 | } 08819 | 08820 | inline typename expression_node<T>::node_type type() const exprtk_override 08821 | { 08822 | return expression_node<T>::e_veccelem; 08823 | } 08824 | 08825 | inline bool valid() const exprtk_override 08826 | { 08827 | return 08828 | vector_holder_ && 08829 | vector_node_.first && 08830 | vector_node_.first->valid(); 08831 | } 08832 | 08833 | inline vector_holder_t& vec_holder() 08834 | { 08835 | return (*vector_holder_); 08836 | } 08837 | 08838 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 08839 | { 08840 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 08841 | } 08842 | 08843 | std::size_t node_depth() const exprtk_override 08844 | { 08845 | return expression_node<T>::ndb_t::compute_node_depth(vector_node_); 08846 | } 08847 | 08848 | private: 08849 | 08850 | inline T* access_vector() const 08851 | { 08852 | vector_node_.first->value(); 08853 | return (vector_base_ + index_); 08854 | } 08855 | 08856 | const std::size_t index_; 08857 | vector_holder_ptr vector_holder_; 08858 | T* vector_base_; 08859 | branch_t vector_node_; 08860 | }; 08861 | 08862 | template <typename T> 08863 | class vector_elem_rtc_node exprtk_final 08864 | : public expression_node<T> 08865 | , public ivariable <T> 08866 | { 08867 | public: 08868 | 08869 | typedef expression_node<T>* expression_ptr; 08870 | typedef vector_holder<T> vector_holder_t; 08871 | typedef vector_holder_t* vector_holder_ptr; 08872 | typedef std::pair<expression_ptr,bool> branch_t; 08873 | 08874 | vector_elem_rtc_node(expression_ptr vec_node, 08875 | expression_ptr index, 08876 | vector_holder_ptr vec_holder, 08877 | vector_access_runtime_check_ptr vec_rt_chk) 08878 | : vector_holder_(vec_holder) 08879 | , vector_base_((*vec_holder)[0]) 08880 | , vec_rt_chk_(vec_rt_chk) 08881 | , max_vector_index_(vector_holder_->size() - 1) 08882 | { 08883 | construct_branch_pair(vector_node_, vec_node); 08884 | construct_branch_pair(index_ , index ); 08885 | assert(valid()); 08886 | } 08887 | 08888 | inline T value() const exprtk_override 08889 | { 08890 | return *access_vector(); 08891 | } 08892 | 08893 | inline T& ref() exprtk_override 08894 | { 08895 | return *access_vector(); 08896 | } 08897 | 08898 | inline const T& ref() const exprtk_override 08899 | { 08900 | return *access_vector(); 08901 | } 08902 | 08903 | inline typename expression_node<T>::node_type type() const exprtk_override 08904 | { 08905 | return expression_node<T>::e_vecelemrtc; 08906 | } 08907 | 08908 | inline bool valid() const exprtk_override 08909 | { 08910 | return 08911 | vector_holder_ && 08912 | index_.first && 08913 | vector_node_.first && 08914 | index_.first->valid() && 08915 | vector_node_.first->valid(); 08916 | } 08917 | 08918 | inline vector_holder_t& vec_holder() 08919 | { 08920 | return (*vector_holder_); 08921 | } 08922 | 08923 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 08924 | { 08925 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 08926 | expression_node<T>::ndb_t::collect(index_, node_delete_list); 08927 | } 08928 | 08929 | std::size_t node_depth() const exprtk_override 08930 | { 08931 | return expression_node<T>::ndb_t::compute_node_depth 08932 | (vector_node_, index_); 08933 | } 08934 | 08935 | private: 08936 | 08937 | inline T* access_vector() const 08938 | { 08939 | const _uint64_t index = details::numeric::to_uint64(index_.first->value()); 08940 | vector_node_.first->value(); 08941 | 08942 | if (index <= max_vector_index_) 08943 | { 08944 | return (vector_holder_->data() + index); 08945 | } 08946 | 08947 | assert(vec_rt_chk_); 08948 | 08949 | vector_access_runtime_check::violation_context context; 08950 | context.base_ptr = reinterpret_cast<void*>(vector_base_); 08951 | context.end_ptr = reinterpret_cast<void*>(vector_base_ + vector_holder_->size()); 08952 | context.access_ptr = reinterpret_cast<void*>(vector_base_ + index); 08953 | context.type_size = sizeof(T); 08954 | 08955 | return vec_rt_chk_->handle_runtime_violation(context) ? 08956 | reinterpret_cast<T*>(context.access_ptr) : 08957 | vector_base_ ; 08958 | } 08959 | 08960 | vector_holder_ptr vector_holder_; 08961 | T* vector_base_; 08962 | branch_t vector_node_; 08963 | branch_t index_; 08964 | vector_access_runtime_check_ptr vec_rt_chk_; 08965 | const std::size_t max_vector_index_; 08966 | }; 08967 | 08968 | template <typename T> 08969 | class vector_celem_rtc_node exprtk_final 08970 | : public expression_node<T> 08971 | , public ivariable <T> 08972 | { 08973 | public: 08974 | 08975 | typedef expression_node<T>* expression_ptr; 08976 | typedef vector_holder<T> vector_holder_t; 08977 | typedef vector_holder_t* vector_holder_ptr; 08978 | typedef std::pair<expression_ptr,bool> branch_t; 08979 | 08980 | vector_celem_rtc_node(expression_ptr vec_node, 08981 | const std::size_t index, 08982 | vector_holder_ptr vec_holder, 08983 | vector_access_runtime_check_ptr vec_rt_chk) 08984 | : index_(index) 08985 | , max_vector_index_(vec_holder->size() - 1) 08986 | , vector_holder_(vec_holder) 08987 | , vector_base_((*vec_holder)[0]) 08988 | , vec_rt_chk_(vec_rt_chk) 08989 | { 08990 | construct_branch_pair(vector_node_, vec_node); 08991 | assert(valid()); 08992 | } 08993 | 08994 | inline T value() const exprtk_override 08995 | { 08996 | return *access_vector(); 08997 | } 08998 | 08999 | inline T& ref() exprtk_override 09000 | { 09001 | return *access_vector(); 09002 | } 09003 | 09004 | inline const T& ref() const exprtk_override 09005 | { 09006 | return *access_vector(); 09007 | } 09008 | 09009 | inline typename expression_node<T>::node_type type() const exprtk_override 09010 | { 09011 | return expression_node<T>::e_veccelemrtc; 09012 | } 09013 | 09014 | inline bool valid() const exprtk_override 09015 | { 09016 | return 09017 | vector_holder_ && 09018 | vector_node_.first && 09019 | vector_node_.first->valid(); 09020 | } 09021 | 09022 | inline vector_holder_t& vec_holder() 09023 | { 09024 | return (*vector_holder_); 09025 | } 09026 | 09027 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09028 | { 09029 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 09030 | } 09031 | 09032 | std::size_t node_depth() const exprtk_override 09033 | { 09034 | return expression_node<T>::ndb_t::compute_node_depth(vector_node_); 09035 | } 09036 | 09037 | private: 09038 | 09039 | inline T* access_vector() const 09040 | { 09041 | vector_node_.first->value(); 09042 | 09043 | if (index_ <= max_vector_index_) 09044 | { 09045 | return (vector_holder_->data() + index_); 09046 | } 09047 | 09048 | assert(vec_rt_chk_); 09049 | 09050 | vector_access_runtime_check::violation_context context; 09051 | context.base_ptr = reinterpret_cast<void*>(vector_base_); 09052 | context.end_ptr = reinterpret_cast<void*>(vector_base_ + vector_holder_->size()); 09053 | context.access_ptr = reinterpret_cast<void*>(vector_base_ + index_); 09054 | context.type_size = sizeof(T); 09055 | 09056 | return vec_rt_chk_->handle_runtime_violation(context) ? 09057 | reinterpret_cast<T*>(context.access_ptr) : 09058 | vector_base_ ; 09059 | } 09060 | 09061 | const std::size_t index_; 09062 | const std::size_t max_vector_index_; 09063 | vector_holder_ptr vector_holder_; 09064 | T* vector_base_; 09065 | branch_t vector_node_; 09066 | vector_access_runtime_check_ptr vec_rt_chk_; 09067 | }; 09068 | 09069 | template <typename T> 09070 | class rebasevector_elem_node exprtk_final 09071 | : public expression_node<T> 09072 | , public ivariable <T> 09073 | { 09074 | public: 09075 | 09076 | typedef expression_node<T>* expression_ptr; 09077 | typedef vector_holder<T> vector_holder_t; 09078 | typedef vector_holder_t* vector_holder_ptr; 09079 | typedef vec_data_store<T> vds_t; 09080 | typedef std::pair<expression_ptr,bool> branch_t; 09081 | 09082 | rebasevector_elem_node(expression_ptr vec_node, 09083 | expression_ptr index, 09084 | vector_holder_ptr vec_holder) 09085 | : vector_holder_(vec_holder) 09086 | { 09087 | construct_branch_pair(vector_node_, vec_node); 09088 | construct_branch_pair(index_ , index ); 09089 | assert(valid()); 09090 | } 09091 | 09092 | inline T value() const exprtk_override 09093 | { 09094 | return *access_vector(); 09095 | } 09096 | 09097 | inline T& ref() exprtk_override 09098 | { 09099 | return *access_vector(); 09100 | } 09101 | 09102 | inline const T& ref() const exprtk_override 09103 | { 09104 | return *access_vector(); 09105 | } 09106 | 09107 | inline typename expression_node<T>::node_type type() const exprtk_override 09108 | { 09109 | return expression_node<T>::e_rbvecelem; 09110 | } 09111 | 09112 | inline bool valid() const exprtk_override 09113 | { 09114 | return 09115 | vector_holder_ && 09116 | index_.first && 09117 | vector_node_.first && 09118 | index_.first->valid() && 09119 | vector_node_.first->valid(); 09120 | } 09121 | 09122 | inline vector_holder_t& vec_holder() 09123 | { 09124 | return (*vector_holder_); 09125 | } 09126 | 09127 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09128 | { 09129 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 09130 | expression_node<T>::ndb_t::collect(index_, node_delete_list); 09131 | } 09132 | 09133 | std::size_t node_depth() const exprtk_override 09134 | { 09135 | return expression_node<T>::ndb_t::compute_node_depth 09136 | (vector_node_, index_); 09137 | } 09138 | 09139 | private: 09140 | 09141 | inline T* access_vector() const 09142 | { 09143 | vector_node_.first->value(); 09144 | return (vector_holder_->data() + details::numeric::to_uint64(index_.first->value())); 09145 | } 09146 | 09147 | vector_holder_ptr vector_holder_; 09148 | branch_t vector_node_; 09149 | branch_t index_; 09150 | }; 09151 | 09152 | template <typename T> 09153 | class rebasevector_celem_node exprtk_final 09154 | : public expression_node<T> 09155 | , public ivariable <T> 09156 | { 09157 | public: 09158 | 09159 | typedef expression_node<T>* expression_ptr; 09160 | typedef vector_holder<T> vector_holder_t; 09161 | typedef vector_holder_t* vector_holder_ptr; 09162 | typedef std::pair<expression_ptr,bool> branch_t; 09163 | 09164 | rebasevector_celem_node(expression_ptr vec_node, 09165 | const std::size_t index, 09166 | vector_holder_ptr vec_holder) 09167 | : index_(index) 09168 | , vector_holder_(vec_holder) 09169 | { 09170 | construct_branch_pair(vector_node_, vec_node); 09171 | assert(valid()); 09172 | } 09173 | 09174 | inline T value() const exprtk_override 09175 | { 09176 | vector_node_.first->value(); 09177 | return ref(); 09178 | } 09179 | 09180 | inline T& ref() exprtk_override 09181 | { 09182 | return *(vector_holder_->data() + index_); 09183 | } 09184 | 09185 | inline const T& ref() const exprtk_override 09186 | { 09187 | return *(vector_holder_->data() + index_); 09188 | } 09189 | 09190 | inline typename expression_node<T>::node_type type() const exprtk_override 09191 | { 09192 | return expression_node<T>::e_rbveccelem; 09193 | } 09194 | 09195 | inline bool valid() const exprtk_override 09196 | { 09197 | return 09198 | vector_holder_ && 09199 | vector_node_.first && 09200 | vector_node_.first->valid(); 09201 | } 09202 | 09203 | inline vector_holder_t& vec_holder() 09204 | { 09205 | return (*vector_holder_); 09206 | } 09207 | 09208 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09209 | { 09210 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 09211 | } 09212 | 09213 | std::size_t node_depth() const exprtk_override 09214 | { 09215 | return expression_node<T>::ndb_t::compute_node_depth(vector_node_); 09216 | } 09217 | 09218 | private: 09219 | 09220 | const std::size_t index_; 09221 | vector_holder_ptr vector_holder_; 09222 | branch_t vector_node_; 09223 | }; 09224 | 09225 | template <typename T> 09226 | class rebasevector_elem_rtc_node exprtk_final 09227 | : public expression_node<T> 09228 | , public ivariable <T> 09229 | { 09230 | public: 09231 | 09232 | typedef expression_node<T>* expression_ptr; 09233 | typedef vector_holder<T> vector_holder_t; 09234 | typedef vector_holder_t* vector_holder_ptr; 09235 | typedef std::pair<expression_ptr,bool> branch_t; 09236 | 09237 | rebasevector_elem_rtc_node(expression_ptr vec_node, 09238 | expression_ptr index, 09239 | vector_holder_ptr vec_holder, 09240 | vector_access_runtime_check_ptr vec_rt_chk) 09241 | : vector_holder_(vec_holder) 09242 | , vec_rt_chk_(vec_rt_chk) 09243 | { 09244 | construct_branch_pair(vector_node_, vec_node); 09245 | construct_branch_pair(index_ , index ); 09246 | assert(valid()); 09247 | } 09248 | 09249 | inline T value() const exprtk_override 09250 | { 09251 | return *access_vector(); 09252 | } 09253 | 09254 | inline T& ref() exprtk_override 09255 | { 09256 | return *access_vector(); 09257 | } 09258 | 09259 | inline const T& ref() const exprtk_override 09260 | { 09261 | return *access_vector(); 09262 | } 09263 | 09264 | inline typename expression_node<T>::node_type type() const exprtk_override 09265 | { 09266 | return expression_node<T>::e_rbvecelemrtc; 09267 | } 09268 | 09269 | inline bool valid() const exprtk_override 09270 | { 09271 | return 09272 | vector_holder_ && 09273 | index_.first && 09274 | vector_node_.first && 09275 | index_.first->valid() && 09276 | vector_node_.first->valid(); 09277 | } 09278 | 09279 | inline vector_holder_t& vec_holder() 09280 | { 09281 | return (*vector_holder_); 09282 | } 09283 | 09284 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09285 | { 09286 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 09287 | expression_node<T>::ndb_t::collect(index_ , node_delete_list); 09288 | } 09289 | 09290 | std::size_t node_depth() const exprtk_override 09291 | { 09292 | return expression_node<T>::ndb_t::compute_node_depth 09293 | (vector_node_, index_); 09294 | } 09295 | 09296 | private: 09297 | 09298 | inline T* access_vector() const 09299 | { 09300 | vector_node_.first->value(); 09301 | const _uint64_t index = details::numeric::to_uint64(index_.first->value()); 09302 | 09303 | if (index <= (vector_holder_->size() - 1)) 09304 | { 09305 | return (vector_holder_->data() + index); 09306 | } 09307 | 09308 | assert(vec_rt_chk_); 09309 | 09310 | vector_access_runtime_check::violation_context context; 09311 | context.base_ptr = reinterpret_cast<void*>(vector_holder_->data()); 09312 | context.end_ptr = reinterpret_cast<void*>(vector_holder_->data() + vector_holder_->size()); 09313 | context.access_ptr = reinterpret_cast<void*>(vector_holder_->data() + index); 09314 | context.type_size = sizeof(T); 09315 | 09316 | return vec_rt_chk_->handle_runtime_violation(context) ? 09317 | reinterpret_cast<T*>(context.access_ptr) : 09318 | vector_holder_->data() ; 09319 | } 09320 | 09321 | vector_holder_ptr vector_holder_; 09322 | branch_t vector_node_; 09323 | branch_t index_; 09324 | vector_access_runtime_check_ptr vec_rt_chk_; 09325 | }; 09326 | 09327 | template <typename T> 09328 | class rebasevector_celem_rtc_node exprtk_final 09329 | : public expression_node<T> 09330 | , public ivariable <T> 09331 | { 09332 | public: 09333 | 09334 | typedef expression_node<T>* expression_ptr; 09335 | typedef vector_holder<T> vector_holder_t; 09336 | typedef vector_holder_t* vector_holder_ptr; 09337 | typedef std::pair<expression_ptr,bool> branch_t; 09338 | 09339 | rebasevector_celem_rtc_node(expression_ptr vec_node, 09340 | const std::size_t index, 09341 | vector_holder_ptr vec_holder, 09342 | vector_access_runtime_check_ptr vec_rt_chk) 09343 | : index_(index) 09344 | , vector_holder_(vec_holder) 09345 | , vector_base_((*vec_holder)[0]) 09346 | , vec_rt_chk_(vec_rt_chk) 09347 | { 09348 | construct_branch_pair(vector_node_, vec_node); 09349 | assert(valid()); 09350 | } 09351 | 09352 | inline T value() const exprtk_override 09353 | { 09354 | return *access_vector(); 09355 | } 09356 | 09357 | inline T& ref() exprtk_override 09358 | { 09359 | return *access_vector(); 09360 | } 09361 | 09362 | inline const T& ref() const exprtk_override 09363 | { 09364 | return *access_vector(); 09365 | } 09366 | 09367 | inline typename expression_node<T>::node_type type() const exprtk_override 09368 | { 09369 | return expression_node<T>::e_rbveccelemrtc; 09370 | } 09371 | 09372 | inline bool valid() const exprtk_override 09373 | { 09374 | return 09375 | vector_holder_ && 09376 | vector_node_.first && 09377 | vector_node_.first->valid(); 09378 | } 09379 | 09380 | inline vector_holder_t& vec_holder() 09381 | { 09382 | return (*vector_holder_); 09383 | } 09384 | 09385 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09386 | { 09387 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 09388 | } 09389 | 09390 | std::size_t node_depth() const exprtk_override 09391 | { 09392 | return expression_node<T>::ndb_t::compute_node_depth(vector_node_); 09393 | } 09394 | 09395 | private: 09396 | 09397 | inline T* access_vector() const 09398 | { 09399 | vector_node_.first->value(); 09400 | 09401 | if (index_ <= vector_holder_->size() - 1) 09402 | { 09403 | return (vector_holder_->data() + index_); 09404 | } 09405 | 09406 | assert(vec_rt_chk_); 09407 | 09408 | vector_access_runtime_check::violation_context context; 09409 | context.base_ptr = reinterpret_cast<void*>(vector_base_); 09410 | context.end_ptr = reinterpret_cast<void*>(vector_base_ + vector_holder_->size()); 09411 | context.access_ptr = reinterpret_cast<void*>(vector_base_ + index_); 09412 | context.type_size = sizeof(T); 09413 | 09414 | return vec_rt_chk_->handle_runtime_violation(context) ? 09415 | reinterpret_cast<T*>(context.access_ptr) : 09416 | vector_base_ ; 09417 | } 09418 | 09419 | const std::size_t index_; 09420 | vector_holder_ptr vector_holder_; 09421 | T* vector_base_; 09422 | branch_t vector_node_; 09423 | vector_access_runtime_check_ptr vec_rt_chk_; 09424 | }; 09425 | 09426 | template <typename T> 09427 | class vector_initialisation_node exprtk_final : public expression_node<T> 09428 | { 09429 | public: 09430 | 09431 | typedef expression_node<T>* expression_ptr; 09432 | 09433 | vector_initialisation_node(T* vector_base, 09434 | const std::size_t& size, 09435 | const std::vector<expression_ptr>& initialiser_list, 09436 | const bool single_value_initialse) 09437 | : vector_base_(vector_base) 09438 | , initialiser_list_(initialiser_list) 09439 | , size_(size) 09440 | , single_value_initialse_(single_value_initialse) 09441 | , zero_value_initialse_(false) 09442 | , const_nonzero_literal_value_initialse_(false) 09443 | , single_initialiser_value_(T(0)) 09444 | { 09445 | if (single_value_initialse_) 09446 | { 09447 | if (initialiser_list_.empty()) 09448 | zero_value_initialse_ = true; 09449 | else if ( 09450 | (initialiser_list_.size() == 1) && 09451 | details::is_constant_node(initialiser_list_[0]) && 09452 | (T(0) == initialiser_list_[0]->value()) 09453 | ) 09454 | { 09455 | zero_value_initialse_ = true; 09456 | } 09457 | else 09458 | { 09459 | assert(initialiser_list_.size() == 1); 09460 | 09461 | if (details::is_constant_node(initialiser_list_[0])) 09462 | { 09463 | const_nonzero_literal_value_initialse_ = true; 09464 | single_initialiser_value_ = initialiser_list_[0]->value(); 09465 | assert(T(0) != single_initialiser_value_); 09466 | } 09467 | } 09468 | } 09469 | } 09470 | 09471 | inline T value() const exprtk_override 09472 | { 09473 | if (single_value_initialse_) 09474 | { 09475 | if (zero_value_initialse_) 09476 | { 09477 | details::set_zero_value(vector_base_, size_); 09478 | } 09479 | else if (const_nonzero_literal_value_initialse_) 09480 | { 09481 | for (std::size_t i = 0; i < size_; ++i) 09482 | { 09483 | *(vector_base_ + i) = single_initialiser_value_; 09484 | } 09485 | } 09486 | else 09487 | { 09488 | for (std::size_t i = 0; i < size_; ++i) 09489 | { 09490 | *(vector_base_ + i) = initialiser_list_[0]->value(); 09491 | } 09492 | } 09493 | } 09494 | else 09495 | { 09496 | const std::size_t initialiser_list_size = initialiser_list_.size(); 09497 | 09498 | for (std::size_t i = 0; i < initialiser_list_size; ++i) 09499 | { 09500 | *(vector_base_ + i) = initialiser_list_[i]->value(); 09501 | } 09502 | 09503 | if (initialiser_list_size < size_) 09504 | { 09505 | details::set_zero_value( 09506 | vector_base_ + initialiser_list_size, 09507 | (size_ - initialiser_list_size)); 09508 | } 09509 | } 09510 | 09511 | return *(vector_base_); 09512 | } 09513 | 09514 | inline typename expression_node<T>::node_type type() const exprtk_override 09515 | { 09516 | return expression_node<T>::e_vecinit; 09517 | } 09518 | 09519 | inline bool valid() const exprtk_override 09520 | { 09521 | return vector_base_; 09522 | } 09523 | 09524 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09525 | { 09526 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09527 | } 09528 | 09529 | std::size_t node_depth() const exprtk_override 09530 | { 09531 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09532 | } 09533 | 09534 | private: 09535 | 09536 | vector_initialisation_node(const vector_initialisation_node<T>&) exprtk_delete; 09537 | vector_initialisation_node<T>& operator=(const vector_initialisation_node<T>&) exprtk_delete; 09538 | 09539 | mutable T* vector_base_; 09540 | std::vector<expression_ptr> initialiser_list_; 09541 | const std::size_t size_; 09542 | const bool single_value_initialse_; 09543 | bool zero_value_initialse_; 09544 | bool const_nonzero_literal_value_initialse_; 09545 | T single_initialiser_value_; 09546 | }; 09547 | 09548 | template <typename T> 09549 | class vector_init_zero_value_node exprtk_final : public expression_node<T> 09550 | { 09551 | public: 09552 | 09553 | typedef expression_node<T>* expression_ptr; 09554 | 09555 | vector_init_zero_value_node(T* vector_base, 09556 | const std::size_t& size, 09557 | const std::vector<expression_ptr>& initialiser_list) 09558 | : vector_base_(vector_base) 09559 | , size_(size) 09560 | , initialiser_list_(initialiser_list) 09561 | {} 09562 | 09563 | inline T value() const exprtk_override 09564 | { 09565 | details::set_zero_value(vector_base_, size_); 09566 | return *(vector_base_); 09567 | } 09568 | 09569 | inline typename expression_node<T>::node_type type() const exprtk_override 09570 | { 09571 | return expression_node<T>::e_vecinit; 09572 | } 09573 | 09574 | inline bool valid() const exprtk_override 09575 | { 09576 | return vector_base_; 09577 | } 09578 | 09579 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09580 | { 09581 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09582 | } 09583 | 09584 | std::size_t node_depth() const exprtk_override 09585 | { 09586 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09587 | } 09588 | 09589 | private: 09590 | 09591 | vector_init_zero_value_node(const vector_init_zero_value_node<T>&) exprtk_delete; 09592 | vector_init_zero_value_node<T>& operator=(const vector_init_zero_value_node<T>&) exprtk_delete; 09593 | 09594 | mutable T* vector_base_; 09595 | const std::size_t size_; 09596 | std::vector<expression_ptr> initialiser_list_; 09597 | }; 09598 | 09599 | template <typename T> 09600 | class vector_init_single_constvalue_node exprtk_final : public expression_node<T> 09601 | { 09602 | public: 09603 | 09604 | typedef expression_node<T>* expression_ptr; 09605 | 09606 | vector_init_single_constvalue_node(T* vector_base, 09607 | const std::size_t& size, 09608 | const std::vector<expression_ptr>& initialiser_list) 09609 | : vector_base_(vector_base) 09610 | , size_(size) 09611 | , initialiser_list_(initialiser_list) 09612 | { 09613 | single_initialiser_value_ = initialiser_list_[0]->value(); 09614 | assert(valid()); 09615 | } 09616 | 09617 | inline T value() const exprtk_override 09618 | { 09619 | for (std::size_t i = 0; i < size_; ++i) 09620 | { 09621 | *(vector_base_ + i) = single_initialiser_value_; 09622 | } 09623 | 09624 | return *(vector_base_); 09625 | } 09626 | 09627 | inline typename expression_node<T>::node_type type() const exprtk_override 09628 | { 09629 | return expression_node<T>::e_vecinit; 09630 | } 09631 | 09632 | inline bool valid() const exprtk_override 09633 | { 09634 | return vector_base_ && 09635 | (initialiser_list_.size() == 1) && 09636 | (details::is_constant_node(initialiser_list_[0])) && 09637 | (single_initialiser_value_ != T(0)); 09638 | } 09639 | 09640 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09641 | { 09642 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09643 | } 09644 | 09645 | std::size_t node_depth() const exprtk_override 09646 | { 09647 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09648 | } 09649 | 09650 | private: 09651 | 09652 | vector_init_single_constvalue_node(const vector_init_single_constvalue_node<T>&) exprtk_delete; 09653 | vector_init_single_constvalue_node<T>& operator=(const vector_init_single_constvalue_node<T>&) exprtk_delete; 09654 | 09655 | mutable T* vector_base_; 09656 | const std::size_t size_; 09657 | std::vector<expression_ptr> initialiser_list_; 09658 | T single_initialiser_value_; 09659 | }; 09660 | 09661 | template <typename T> 09662 | class vector_init_single_value_node exprtk_final : public expression_node<T> 09663 | { 09664 | public: 09665 | 09666 | typedef expression_node<T>* expression_ptr; 09667 | 09668 | vector_init_single_value_node(T* vector_base, 09669 | const std::size_t& size, 09670 | const std::vector<expression_ptr>& initialiser_list) 09671 | : vector_base_(vector_base) 09672 | , size_(size) 09673 | , initialiser_list_(initialiser_list) 09674 | { 09675 | assert(valid()); 09676 | } 09677 | 09678 | inline T value() const exprtk_override 09679 | { 09680 | expression_node<T>& node = *initialiser_list_[0]; 09681 | 09682 | for (std::size_t i = 0; i < size_; ++i) 09683 | { 09684 | *(vector_base_ + i) = node.value(); 09685 | } 09686 | 09687 | return *(vector_base_); 09688 | } 09689 | 09690 | inline typename expression_node<T>::node_type type() const exprtk_override 09691 | { 09692 | return expression_node<T>::e_vecinit; 09693 | } 09694 | 09695 | inline bool valid() const exprtk_override 09696 | { 09697 | return vector_base_ && 09698 | (initialiser_list_.size() == 1) && 09699 | !details::is_constant_node(initialiser_list_[0]); 09700 | } 09701 | 09702 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09703 | { 09704 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09705 | } 09706 | 09707 | std::size_t node_depth() const exprtk_override 09708 | { 09709 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09710 | } 09711 | 09712 | private: 09713 | 09714 | vector_init_single_value_node(const vector_init_single_value_node<T>&) exprtk_delete; 09715 | vector_init_single_value_node<T>& operator=(const vector_init_single_value_node<T>&) exprtk_delete; 09716 | 09717 | mutable T* vector_base_; 09718 | const std::size_t size_; 09719 | std::vector<expression_ptr> initialiser_list_; 09720 | }; 09721 | 09722 | template <typename T> 09723 | class vector_init_iota_constconst_node exprtk_final : public expression_node<T> 09724 | { 09725 | public: 09726 | 09727 | typedef expression_node<T>* expression_ptr; 09728 | 09729 | vector_init_iota_constconst_node(T* vector_base, 09730 | const std::size_t& size, 09731 | const std::vector<expression_ptr>& initialiser_list) 09732 | : vector_base_(vector_base) 09733 | , size_(size) 09734 | , initialiser_list_(initialiser_list) 09735 | { 09736 | base_value_ = initialiser_list_[0]->value(); 09737 | increment_value_ = initialiser_list_[1]->value(); 09738 | 09739 | assert(valid()); 09740 | } 09741 | 09742 | inline T value() const exprtk_override 09743 | { 09744 | T value = base_value_; 09745 | 09746 | for (std::size_t i = 0; i < size_; ++i, value += increment_value_) 09747 | { 09748 | *(vector_base_ + i) = value; 09749 | } 09750 | 09751 | return *(vector_base_); 09752 | } 09753 | 09754 | inline typename expression_node<T>::node_type type() const exprtk_override 09755 | { 09756 | return expression_node<T>::e_vecinit; 09757 | } 09758 | 09759 | inline bool valid() const exprtk_override 09760 | { 09761 | return vector_base_ && 09762 | (initialiser_list_.size() == 2) && 09763 | (details::is_constant_node(initialiser_list_[0])) && 09764 | (details::is_constant_node(initialiser_list_[1])) ; 09765 | } 09766 | 09767 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09768 | { 09769 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09770 | } 09771 | 09772 | std::size_t node_depth() const exprtk_override 09773 | { 09774 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09775 | } 09776 | 09777 | private: 09778 | 09779 | vector_init_iota_constconst_node(const vector_init_iota_constconst_node<T>&) exprtk_delete; 09780 | vector_init_iota_constconst_node<T>& operator=(const vector_init_iota_constconst_node<T>&) exprtk_delete; 09781 | 09782 | mutable T* vector_base_; 09783 | const std::size_t size_; 09784 | std::vector<expression_ptr> initialiser_list_; 09785 | T base_value_; 09786 | T increment_value_; 09787 | }; 09788 | 09789 | template <typename T> 09790 | class vector_init_iota_constnconst_node exprtk_final : public expression_node<T> 09791 | { 09792 | public: 09793 | 09794 | typedef expression_node<T>* expression_ptr; 09795 | 09796 | vector_init_iota_constnconst_node(T* vector_base, 09797 | const std::size_t& size, 09798 | const std::vector<expression_ptr>& initialiser_list) 09799 | : vector_base_(vector_base) 09800 | , size_(size) 09801 | , initialiser_list_(initialiser_list) 09802 | { 09803 | assert(valid()); 09804 | base_value_ = initialiser_list_[0]->value(); 09805 | } 09806 | 09807 | inline T value() const exprtk_override 09808 | { 09809 | T value = base_value_; 09810 | expression_node<T>& increment = *initialiser_list_[1]; 09811 | 09812 | for (std::size_t i = 0; i < size_; ++i, value += increment.value()) 09813 | { 09814 | *(vector_base_ + i) = value; 09815 | } 09816 | 09817 | return *(vector_base_); 09818 | } 09819 | 09820 | inline typename expression_node<T>::node_type type() const exprtk_override 09821 | { 09822 | return expression_node<T>::e_vecinit; 09823 | } 09824 | 09825 | inline bool valid() const exprtk_override 09826 | { 09827 | return vector_base_ && 09828 | (initialiser_list_.size() == 2) && 09829 | ( details::is_constant_node(initialiser_list_[0])) && 09830 | (!details::is_constant_node(initialiser_list_[1])); 09831 | } 09832 | 09833 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09834 | { 09835 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09836 | } 09837 | 09838 | std::size_t node_depth() const exprtk_override 09839 | { 09840 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09841 | } 09842 | 09843 | private: 09844 | 09845 | vector_init_iota_constnconst_node(const vector_init_iota_constnconst_node<T>&) exprtk_delete; 09846 | vector_init_iota_constnconst_node<T>& operator=(const vector_init_iota_constnconst_node<T>&) exprtk_delete; 09847 | 09848 | mutable T* vector_base_; 09849 | const std::size_t size_; 09850 | std::vector<expression_ptr> initialiser_list_; 09851 | T base_value_; 09852 | }; 09853 | 09854 | template <typename T> 09855 | class vector_init_iota_nconstconst_node exprtk_final : public expression_node<T> 09856 | { 09857 | public: 09858 | 09859 | typedef expression_node<T>* expression_ptr; 09860 | 09861 | vector_init_iota_nconstconst_node(T* vector_base, 09862 | const std::size_t& size, 09863 | const std::vector<expression_ptr>& initialiser_list) 09864 | : vector_base_(vector_base) 09865 | , size_(size) 09866 | , initialiser_list_(initialiser_list) 09867 | { 09868 | assert(valid()); 09869 | } 09870 | 09871 | inline T value() const exprtk_override 09872 | { 09873 | T value = initialiser_list_[0]->value(); 09874 | const T increment = initialiser_list_[1]->value(); 09875 | 09876 | for (std::size_t i = 0; i < size_; ++i, value += increment) 09877 | { 09878 | *(vector_base_ + i) = value; 09879 | } 09880 | 09881 | return *(vector_base_); 09882 | } 09883 | 09884 | inline typename expression_node<T>::node_type type() const exprtk_override 09885 | { 09886 | return expression_node<T>::e_vecinit; 09887 | } 09888 | 09889 | inline bool valid() const exprtk_override 09890 | { 09891 | return vector_base_ && 09892 | (initialiser_list_.size() == 2) && 09893 | (!details::is_constant_node(initialiser_list_[0])) && 09894 | (details::is_constant_node(initialiser_list_[1])); 09895 | } 09896 | 09897 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09898 | { 09899 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09900 | } 09901 | 09902 | std::size_t node_depth() const exprtk_override 09903 | { 09904 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09905 | } 09906 | 09907 | private: 09908 | 09909 | vector_init_iota_nconstconst_node(const vector_init_iota_nconstconst_node<T>&) exprtk_delete; 09910 | vector_init_iota_nconstconst_node<T>& operator=(const vector_init_iota_nconstconst_node<T>&) exprtk_delete; 09911 | 09912 | mutable T* vector_base_; 09913 | const std::size_t size_; 09914 | std::vector<expression_ptr> initialiser_list_; 09915 | }; 09916 | 09917 | template <typename T> 09918 | class vector_init_iota_nconstnconst_node exprtk_final : public expression_node<T> 09919 | { 09920 | public: 09921 | 09922 | typedef expression_node<T>* expression_ptr; 09923 | 09924 | vector_init_iota_nconstnconst_node(T* vector_base, 09925 | const std::size_t& size, 09926 | const std::vector<expression_ptr>& initialiser_list) 09927 | : vector_base_(vector_base) 09928 | , size_(size) 09929 | , initialiser_list_(initialiser_list) 09930 | { 09931 | assert(valid()); 09932 | } 09933 | 09934 | inline T value() const exprtk_override 09935 | { 09936 | T value = initialiser_list_[0]->value(); 09937 | expression_node<T>& increment = *initialiser_list_[1]; 09938 | 09939 | for (std::size_t i = 0; i < size_; ++i, value += increment.value()) 09940 | { 09941 | *(vector_base_ + i) = value; 09942 | } 09943 | 09944 | return *(vector_base_); 09945 | } 09946 | 09947 | inline typename expression_node<T>::node_type type() const exprtk_override 09948 | { 09949 | return expression_node<T>::e_vecinit; 09950 | } 09951 | 09952 | inline bool valid() const exprtk_override 09953 | { 09954 | return vector_base_ && 09955 | (initialiser_list_.size() == 2) && 09956 | (!details::is_constant_node(initialiser_list_[0])) && 09957 | (!details::is_constant_node(initialiser_list_[1])); 09958 | } 09959 | 09960 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09961 | { 09962 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09963 | } 09964 | 09965 | std::size_t node_depth() const exprtk_override 09966 | { 09967 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09968 | } 09969 | 09970 | private: 09971 | 09972 | vector_init_iota_nconstnconst_node(const vector_init_iota_nconstnconst_node<T>&) exprtk_delete; 09973 | vector_init_iota_nconstnconst_node<T>& operator=(const vector_init_iota_nconstnconst_node<T>&) exprtk_delete; 09974 | 09975 | mutable T* vector_base_; 09976 | const std::size_t size_; 09977 | std::vector<expression_ptr> initialiser_list_; 09978 | }; 09979 | 09980 | template <typename T> 09981 | class swap_node exprtk_final : public expression_node<T> 09982 | { 09983 | public: 09984 | 09985 | typedef expression_node<T>* expression_ptr; 09986 | typedef variable_node<T>* variable_node_ptr; 09987 | 09988 | swap_node(variable_node_ptr var0, variable_node_ptr var1) 09989 | : var0_(var0) 09990 | , var1_(var1) 09991 | {} 09992 | 09993 | inline T value() const exprtk_override 09994 | { 09995 | std::swap(var0_->ref(),var1_->ref()); 09996 | return var1_->ref(); 09997 | } 09998 | 09999 | inline typename expression_node<T>::node_type type() const exprtk_override 10000 | { 10001 | return expression_node<T>::e_swap; 10002 | } 10003 | 10004 | private: 10005 | 10006 | variable_node_ptr var0_; 10007 | variable_node_ptr var1_; 10008 | }; 10009 | 10010 | template <typename T> 10011 | class swap_generic_node exprtk_final : public binary_node<T> 10012 | { 10013 | public: 10014 | 10015 | typedef expression_node<T>* expression_ptr; 10016 | typedef ivariable<T>* ivariable_ptr; 10017 | 10018 | swap_generic_node(expression_ptr var0, expression_ptr var1) 10019 | : binary_node<T>(details::e_swap, var0, var1) 10020 | , var0_(dynamic_cast<ivariable_ptr>(var0)) 10021 | , var1_(dynamic_cast<ivariable_ptr>(var1)) 10022 | {} 10023 | 10024 | inline T value() const exprtk_override 10025 | { 10026 | std::swap(var0_->ref(),var1_->ref()); 10027 | return var1_->ref(); 10028 | } 10029 | 10030 | inline typename expression_node<T>::node_type type() const exprtk_override 10031 | { 10032 | return expression_node<T>::e_swap; 10033 | } 10034 | 10035 | private: 10036 | 10037 | ivariable_ptr var0_; 10038 | ivariable_ptr var1_; 10039 | }; 10040 | 10041 | template <typename T> 10042 | class swap_vecvec_node exprtk_final 10043 | : public binary_node <T> 10044 | , public vector_interface<T> 10045 | { 10046 | public: 10047 | 10048 | typedef expression_node<T>* expression_ptr; 10049 | typedef vector_node <T>* vector_node_ptr; 10050 | typedef vec_data_store <T> vds_t; 10051 | 10052 | using binary_node<T>::branch; 10053 | 10054 | swap_vecvec_node(expression_ptr branch0, 10055 | expression_ptr branch1) 10056 | : binary_node<T>(details::e_swap, branch0, branch1) 10057 | , vec0_node_ptr_(0) 10058 | , vec1_node_ptr_(0) 10059 | , initialised_ (false) 10060 | { 10061 | if (is_ivector_node(branch(0))) 10062 | { 10063 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 10064 | 10065 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(0)))) 10066 | { 10067 | vec0_node_ptr_ = vi->vec(); 10068 | vds() = vi->vds(); 10069 | } 10070 | } 10071 | 10072 | if (is_ivector_node(branch(1))) 10073 | { 10074 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 10075 | 10076 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1)))) 10077 | { 10078 | vec1_node_ptr_ = vi->vec(); 10079 | } 10080 | } 10081 | 10082 | if (vec0_node_ptr_ && vec1_node_ptr_) 10083 | { 10084 | initialised_ = size() <= base_size(); 10085 | } 10086 | 10087 | assert(valid()); 10088 | } 10089 | 10090 | inline T value() const exprtk_override 10091 | { 10092 | binary_node<T>::branch(0)->value(); 10093 | binary_node<T>::branch(1)->value(); 10094 | 10095 | T* vec0 = vec0_node_ptr_->vds().data(); 10096 | T* vec1 = vec1_node_ptr_->vds().data(); 10097 | 10098 | assert(size() <= base_size()); 10099 | const std::size_t n = size(); 10100 | 10101 | for (std::size_t i = 0; i < n; ++i) 10102 | { 10103 | std::swap(vec0[i],vec1[i]); 10104 | } 10105 | 10106 | return vec1_node_ptr_->value(); 10107 | } 10108 | 10109 | vector_node_ptr vec() const exprtk_override 10110 | { 10111 | return vec0_node_ptr_; 10112 | } 10113 | 10114 | vector_node_ptr vec() exprtk_override 10115 | { 10116 | return vec0_node_ptr_; 10117 | } 10118 | 10119 | inline typename expression_node<T>::node_type type() const exprtk_override 10120 | { 10121 | return expression_node<T>::e_vecvecswap; 10122 | } 10123 | 10124 | inline bool valid() const exprtk_override 10125 | { 10126 | return initialised_ && binary_node<T>::valid(); 10127 | } 10128 | 10129 | std::size_t size() const exprtk_override 10130 | { 10131 | return std::min( 10132 | vec0_node_ptr_->vec_holder().size(), 10133 | vec1_node_ptr_->vec_holder().size()); 10134 | } 10135 | 10136 | std::size_t base_size() const exprtk_override 10137 | { 10138 | return std::min( 10139 | vec0_node_ptr_->vec_holder().base_size(), 10140 | vec1_node_ptr_->vec_holder().base_size()); 10141 | } 10142 | 10143 | vds_t& vds() exprtk_override 10144 | { 10145 | return vds_; 10146 | } 10147 | 10148 | const vds_t& vds() const exprtk_override 10149 | { 10150 | return vds_; 10151 | } 10152 | 10153 | private: 10154 | 10155 | vector_node<T>* vec0_node_ptr_; 10156 | vector_node<T>* vec1_node_ptr_; 10157 | bool initialised_; 10158 | vds_t vds_; 10159 | }; 10160 | 10161 | #ifndef exprtk_disable_string_capabilities 10162 | template <typename T> 10163 | class stringvar_node exprtk_final 10164 | : public expression_node <T> 10165 | , public string_base_node<T> 10166 | , public range_interface <T> 10167 | { 10168 | public: 10169 | 10170 | typedef typename range_interface<T>::range_t range_t; 10171 | 10172 | static std::string null_value; 10173 | 10174 | explicit stringvar_node() 10175 | : value_(&null_value) 10176 | {} 10177 | 10178 | explicit stringvar_node(std::string& v) 10179 | : value_(&v) 10180 | { 10181 | rp_.n0_c = std::make_pair<bool,std::size_t>(true,0); 10182 | rp_.n1_c = std::make_pair<bool,std::size_t>(true,v.size()); 10183 | rp_.cache.first = rp_.n0_c.second; 10184 | rp_.cache.second = rp_.n1_c.second; 10185 | } 10186 | 10187 | inline bool operator <(const stringvar_node<T>& v) const 10188 | { 10189 | return this < (&v); 10190 | } 10191 | 10192 | inline T value() const exprtk_override 10193 | { 10194 | rp_.n1_c.second = (*value_).size(); 10195 | rp_.cache.second = rp_.n1_c.second; 10196 | 10197 | return std::numeric_limits<T>::quiet_NaN(); 10198 | } 10199 | 10200 | std::string str() const exprtk_override 10201 | { 10202 | return ref(); 10203 | } 10204 | 10205 | char_cptr base() const exprtk_override 10206 | { 10207 | return &(*value_)[0]; 10208 | } 10209 | 10210 | std::size_t size() const exprtk_override 10211 | { 10212 | return ref().size(); 10213 | } 10214 | 10215 | std::string& ref() 10216 | { 10217 | return (*value_); 10218 | } 10219 | 10220 | const std::string& ref() const 10221 | { 10222 | return (*value_); 10223 | } 10224 | 10225 | range_t& range_ref() exprtk_override 10226 | { 10227 | return rp_; 10228 | } 10229 | 10230 | const range_t& range_ref() const exprtk_override 10231 | { 10232 | return rp_; 10233 | } 10234 | 10235 | inline typename expression_node<T>::node_type type() const exprtk_override 10236 | { 10237 | return expression_node<T>::e_stringvar; 10238 | } 10239 | 10240 | void rebase(std::string& s) 10241 | { 10242 | value_ = &s; 10243 | rp_.n0_c = std::make_pair<bool,std::size_t>(true,0); 10244 | rp_.n1_c = std::make_pair<bool,std::size_t>(true,value_->size() - 1); 10245 | rp_.cache.first = rp_.n0_c.second; 10246 | rp_.cache.second = rp_.n1_c.second; 10247 | } 10248 | 10249 | private: 10250 | 10251 | std::string* value_; 10252 | mutable range_t rp_; 10253 | }; 10254 | 10255 | template <typename T> 10256 | std::string stringvar_node<T>::null_value = std::string(""); 10257 | 10258 | template <typename T> 10259 | class string_range_node exprtk_final 10260 | : public expression_node <T> 10261 | , public string_base_node<T> 10262 | , public range_interface <T> 10263 | { 10264 | public: 10265 | 10266 | typedef typename range_interface<T>::range_t range_t; 10267 | 10268 | static std::string null_value; 10269 | 10270 | explicit string_range_node(std::string& v, const range_t& rp) 10271 | : value_(&v) 10272 | , rp_(rp) 10273 | {} 10274 | 10275 | virtual ~string_range_node() 10276 | { 10277 | rp_.free(); 10278 | } 10279 | 10280 | inline bool operator <(const string_range_node<T>& v) const 10281 | { 10282 | return this < (&v); 10283 | } 10284 | 10285 | inline T value() const exprtk_override 10286 | { 10287 | return std::numeric_limits<T>::quiet_NaN(); 10288 | } 10289 | 10290 | inline std::string str() const exprtk_override 10291 | { 10292 | return (*value_); 10293 | } 10294 | 10295 | char_cptr base() const exprtk_override 10296 | { 10297 | return &(*value_)[0]; 10298 | } 10299 | 10300 | std::size_t size() const exprtk_override 10301 | { 10302 | return ref().size(); 10303 | } 10304 | 10305 | inline range_t range() const 10306 | { 10307 | return rp_; 10308 | } 10309 | 10310 | inline virtual std::string& ref() 10311 | { 10312 | return (*value_); 10313 | } 10314 | 10315 | inline virtual const std::string& ref() const 10316 | { 10317 | return (*value_); 10318 | } 10319 | 10320 | inline range_t& range_ref() exprtk_override 10321 | { 10322 | return rp_; 10323 | } 10324 | 10325 | inline const range_t& range_ref() const exprtk_override 10326 | { 10327 | return rp_; 10328 | } 10329 | 10330 | inline typename expression_node<T>::node_type type() const exprtk_override 10331 | { 10332 | return expression_node<T>::e_stringvarrng; 10333 | } 10334 | 10335 | private: 10336 | 10337 | std::string* value_; 10338 | range_t rp_; 10339 | }; 10340 | 10341 | template <typename T> 10342 | std::string string_range_node<T>::null_value = std::string(""); 10343 | 10344 | template <typename T> 10345 | class const_string_range_node exprtk_final 10346 | : public expression_node <T> 10347 | , public string_base_node<T> 10348 | , public range_interface <T> 10349 | { 10350 | public: 10351 | 10352 | typedef typename range_interface<T>::range_t range_t; 10353 | 10354 | explicit const_string_range_node(const std::string& v, const range_t& rp) 10355 | : value_(v) 10356 | , rp_(rp) 10357 | {} 10358 | 10359 | ~const_string_range_node() exprtk_override 10360 | { 10361 | rp_.free(); 10362 | } 10363 | 10364 | inline T value() const exprtk_override 10365 | { 10366 | return std::numeric_limits<T>::quiet_NaN(); 10367 | } 10368 | 10369 | std::string str() const exprtk_override 10370 | { 10371 | return value_; 10372 | } 10373 | 10374 | char_cptr base() const exprtk_override 10375 | { 10376 | return value_.data(); 10377 | } 10378 | 10379 | std::size_t size() const exprtk_override 10380 | { 10381 | return value_.size(); 10382 | } 10383 | 10384 | range_t range() const 10385 | { 10386 | return rp_; 10387 | } 10388 | 10389 | range_t& range_ref() exprtk_override 10390 | { 10391 | return rp_; 10392 | } 10393 | 10394 | const range_t& range_ref() const exprtk_override 10395 | { 10396 | return rp_; 10397 | } 10398 | 10399 | inline typename expression_node<T>::node_type type() const exprtk_override 10400 | { 10401 | return expression_node<T>::e_cstringvarrng; 10402 | } 10403 | 10404 | private: 10405 | 10406 | const_string_range_node(const const_string_range_node<T>&) exprtk_delete; 10407 | const_string_range_node<T>& operator=(const const_string_range_node<T>&) exprtk_delete; 10408 | 10409 | const std::string value_; 10410 | range_t rp_; 10411 | }; 10412 | 10413 | template <typename T> 10414 | class generic_string_range_node exprtk_final 10415 | : public expression_node <T> 10416 | , public string_base_node<T> 10417 | , public range_interface <T> 10418 | { 10419 | public: 10420 | 10421 | typedef expression_node <T>* expression_ptr; 10422 | typedef stringvar_node <T>* strvar_node_ptr; 10423 | typedef string_base_node<T>* str_base_ptr; 10424 | typedef typename range_interface<T>::range_t range_t; 10425 | typedef range_t* range_ptr; 10426 | typedef range_interface<T> irange_t; 10427 | typedef irange_t* irange_ptr; 10428 | typedef std::pair<expression_ptr,bool> branch_t; 10429 | 10430 | generic_string_range_node(expression_ptr str_branch, const range_t& brange) 10431 | : initialised_(false) 10432 | , str_base_ptr_ (0) 10433 | , str_range_ptr_(0) 10434 | , base_range_(brange) 10435 | { 10436 | range_.n0_c = std::make_pair<bool,std::size_t>(true,0); 10437 | range_.n1_c = std::make_pair<bool,std::size_t>(true,0); 10438 | range_.cache.first = range_.n0_c.second; 10439 | range_.cache.second = range_.n1_c.second; 10440 | 10441 | construct_branch_pair(branch_, str_branch); 10442 | 10443 | if (is_generally_string_node(branch_.first)) 10444 | { 10445 | str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_.first); 10446 | 10447 | if (0 == str_base_ptr_) 10448 | return; 10449 | 10450 | str_range_ptr_ = dynamic_cast<irange_ptr>(branch_.first); 10451 | 10452 | if (0 == str_range_ptr_) 10453 | return; 10454 | } 10455 | 10456 | initialised_ = (str_base_ptr_ && str_range_ptr_); 10457 | assert(valid()); 10458 | } 10459 | 10460 | ~generic_string_range_node() exprtk_override 10461 | { 10462 | base_range_.free(); 10463 | } 10464 | 10465 | inline T value() const exprtk_override 10466 | { 10467 | branch_.first->value(); 10468 | 10469 | std::size_t str_r0 = 0; 10470 | std::size_t str_r1 = 0; 10471 | 10472 | std::size_t r0 = 0; 10473 | std::size_t r1 = 0; 10474 | 10475 | const range_t& range = str_range_ptr_->range_ref(); 10476 | 10477 | const std::size_t base_str_size = str_base_ptr_->size(); 10478 | 10479 | if ( 10480 | range (str_r0, str_r1, base_str_size ) && 10481 | base_range_(r0 , r1 , base_str_size - str_r0) 10482 | ) 10483 | { 10484 | const std::size_t size = r1 - r0; 10485 | 10486 | range_.n1_c.second = size; 10487 | range_.cache.second = range_.n1_c.second; 10488 | 10489 | value_.assign(str_base_ptr_->base() + str_r0 + r0, size); 10490 | } 10491 | 10492 | return std::numeric_limits<T>::quiet_NaN(); 10493 | } 10494 | 10495 | std::string str() const exprtk_override 10496 | { 10497 | return value_; 10498 | } 10499 | 10500 | char_cptr base() const exprtk_override 10501 | { 10502 | return &value_[0]; 10503 | } 10504 | 10505 | std::size_t size() const exprtk_override 10506 | { 10507 | return value_.size(); 10508 | } 10509 | 10510 | range_t& range_ref() exprtk_override 10511 | { 10512 | return range_; 10513 | } 10514 | 10515 | const range_t& range_ref() const exprtk_override 10516 | { 10517 | return range_; 10518 | } 10519 | 10520 | inline typename expression_node<T>::node_type type() const exprtk_override 10521 | { 10522 | return expression_node<T>::e_strgenrange; 10523 | } 10524 | 10525 | inline bool valid() const exprtk_override 10526 | { 10527 | return initialised_ && branch_.first; 10528 | } 10529 | 10530 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 10531 | { 10532 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 10533 | } 10534 | 10535 | std::size_t node_depth() const exprtk_override 10536 | { 10537 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 10538 | } 10539 | 10540 | private: 10541 | 10542 | bool initialised_; 10543 | branch_t branch_; 10544 | str_base_ptr str_base_ptr_; 10545 | irange_ptr str_range_ptr_; 10546 | mutable range_t base_range_; 10547 | mutable range_t range_; 10548 | mutable std::string value_; 10549 | }; 10550 | 10551 | template <typename T> 10552 | class string_concat_node exprtk_final 10553 | : public binary_node <T> 10554 | , public string_base_node<T> 10555 | , public range_interface <T> 10556 | { 10557 | public: 10558 | 10559 | typedef typename range_interface<T>::range_t range_t; 10560 | typedef range_interface<T> irange_t; 10561 | typedef irange_t* irange_ptr; 10562 | typedef range_t* range_ptr; 10563 | typedef expression_node <T>* expression_ptr; 10564 | typedef string_base_node<T>* str_base_ptr; 10565 | 10566 | using binary_node<T>::branch; 10567 | 10568 | string_concat_node(const operator_type& opr, 10569 | expression_ptr branch0, 10570 | expression_ptr branch1) 10571 | : binary_node<T>(opr, branch0, branch1) 10572 | , initialised_(false) 10573 | , str0_base_ptr_ (0) 10574 | , str1_base_ptr_ (0) 10575 | , str0_range_ptr_(0) 10576 | , str1_range_ptr_(0) 10577 | { 10578 | range_.n0_c = std::make_pair<bool,std::size_t>(true,0); 10579 | range_.n1_c = std::make_pair<bool,std::size_t>(true,0); 10580 | 10581 | range_.cache.first = range_.n0_c.second; 10582 | range_.cache.second = range_.n1_c.second; 10583 | 10584 | if (is_generally_string_node(branch(0))) 10585 | { 10586 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0)); 10587 | 10588 | if (0 == str0_base_ptr_) 10589 | return; 10590 | 10591 | str0_range_ptr_ = dynamic_cast<irange_ptr>(branch(0)); 10592 | 10593 | if (0 == str0_range_ptr_) 10594 | return; 10595 | } 10596 | 10597 | if (is_generally_string_node(branch(1))) 10598 | { 10599 | str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1)); 10600 | 10601 | if (0 == str1_base_ptr_) 10602 | return; 10603 | 10604 | str1_range_ptr_ = dynamic_cast<irange_ptr>(branch(1)); 10605 | 10606 | if (0 == str1_range_ptr_) 10607 | return; 10608 | } 10609 | 10610 | initialised_ = str0_base_ptr_ && 10611 | str1_base_ptr_ && 10612 | str0_range_ptr_ && 10613 | str1_range_ptr_ ; 10614 | 10615 | assert(valid()); 10616 | } 10617 | 10618 | inline T value() const exprtk_override 10619 | { 10620 | branch(0)->value(); 10621 | branch(1)->value(); 10622 | 10623 | std::size_t str0_r0 = 0; 10624 | std::size_t str0_r1 = 0; 10625 | 10626 | std::size_t str1_r0 = 0; 10627 | std::size_t str1_r1 = 0; 10628 | 10629 | const range_t& range0 = str0_range_ptr_->range_ref(); 10630 | const range_t& range1 = str1_range_ptr_->range_ref(); 10631 | 10632 | if ( 10633 | range0(str0_r0, str0_r1, str0_base_ptr_->size()) && 10634 | range1(str1_r0, str1_r1, str1_base_ptr_->size()) 10635 | ) 10636 | { 10637 | const std::size_t size0 = (str0_r1 - str0_r0); 10638 | const std::size_t size1 = (str1_r1 - str1_r0); 10639 | 10640 | value_.assign(str0_base_ptr_->base() + str0_r0, size0); 10641 | value_.append(str1_base_ptr_->base() + str1_r0, size1); 10642 | 10643 | range_.n1_c.second = value_.size(); 10644 | range_.cache.second = range_.n1_c.second; 10645 | } 10646 | 10647 | return std::numeric_limits<T>::quiet_NaN(); 10648 | } 10649 | 10650 | std::string str() const exprtk_override 10651 | { 10652 | return value_; 10653 | } 10654 | 10655 | char_cptr base() const exprtk_override 10656 | { 10657 | return &value_[0]; 10658 | } 10659 | 10660 | std::size_t size() const exprtk_override 10661 | { 10662 | return value_.size(); 10663 | } 10664 | 10665 | range_t& range_ref() exprtk_override 10666 | { 10667 | return range_; 10668 | } 10669 | 10670 | const range_t& range_ref() const exprtk_override 10671 | { 10672 | return range_; 10673 | } 10674 | 10675 | inline typename expression_node<T>::node_type type() const exprtk_override 10676 | { 10677 | return expression_node<T>::e_strconcat; 10678 | } 10679 | 10680 | inline bool valid() const exprtk_override 10681 | { 10682 | return initialised_ && binary_node<T>::valid(); 10683 | } 10684 | 10685 | private: 10686 | 10687 | bool initialised_; 10688 | str_base_ptr str0_base_ptr_; 10689 | str_base_ptr str1_base_ptr_; 10690 | irange_ptr str0_range_ptr_; 10691 | irange_ptr str1_range_ptr_; 10692 | mutable range_t range_; 10693 | mutable std::string value_; 10694 | }; 10695 | 10696 | template <typename T> 10697 | class swap_string_node exprtk_final 10698 | : public binary_node <T> 10699 | , public string_base_node<T> 10700 | , public range_interface <T> 10701 | { 10702 | public: 10703 | 10704 | typedef typename range_interface<T>::range_t range_t; 10705 | typedef range_t* range_ptr; 10706 | typedef range_interface<T> irange_t; 10707 | typedef irange_t* irange_ptr; 10708 | typedef expression_node <T>* expression_ptr; 10709 | typedef stringvar_node <T>* strvar_node_ptr; 10710 | typedef string_base_node<T>* str_base_ptr; 10711 | 10712 | using binary_node<T>::branch; 10713 | 10714 | swap_string_node(expression_ptr branch0, expression_ptr branch1) 10715 | : binary_node<T>(details::e_swap, branch0, branch1) 10716 | , initialised_(false) 10717 | , str0_node_ptr_(0) 10718 | , str1_node_ptr_(0) 10719 | { 10720 | if (is_string_node(branch(0))) 10721 | { 10722 | str0_node_ptr_ = static_cast<strvar_node_ptr>(branch(0)); 10723 | } 10724 | 10725 | if (is_string_node(branch(1))) 10726 | { 10727 | str1_node_ptr_ = static_cast<strvar_node_ptr>(branch(1)); 10728 | } 10729 | 10730 | initialised_ = (str0_node_ptr_ && str1_node_ptr_); 10731 | assert(valid()); 10732 | } 10733 | 10734 | inline T value() const exprtk_override 10735 | { 10736 | branch(0)->value(); 10737 | branch(1)->value(); 10738 | 10739 | std::swap(str0_node_ptr_->ref(), str1_node_ptr_->ref()); 10740 | 10741 | return std::numeric_limits<T>::quiet_NaN(); 10742 | } 10743 | 10744 | std::string str() const exprtk_override 10745 | { 10746 | return str0_node_ptr_->str(); 10747 | } 10748 | 10749 | char_cptr base() const exprtk_override 10750 | { 10751 | return str0_node_ptr_->base(); 10752 | } 10753 | 10754 | std::size_t size() const exprtk_override 10755 | { 10756 | return str0_node_ptr_->size(); 10757 | } 10758 | 10759 | range_t& range_ref() exprtk_override 10760 | { 10761 | return str0_node_ptr_->range_ref(); 10762 | } 10763 | 10764 | const range_t& range_ref() const exprtk_override 10765 | { 10766 | return str0_node_ptr_->range_ref(); 10767 | } 10768 | 10769 | inline typename expression_node<T>::node_type type() const exprtk_override 10770 | { 10771 | return expression_node<T>::e_strswap; 10772 | } 10773 | 10774 | inline bool valid() const exprtk_override 10775 | { 10776 | return initialised_ && binary_node<T>::valid(); 10777 | } 10778 | 10779 | private: 10780 | 10781 | bool initialised_; 10782 | strvar_node_ptr str0_node_ptr_; 10783 | strvar_node_ptr str1_node_ptr_; 10784 | }; 10785 | 10786 | template <typename T> 10787 | class swap_genstrings_node exprtk_final : public binary_node<T> 10788 | { 10789 | public: 10790 | 10791 | typedef typename range_interface<T>::range_t range_t; 10792 | typedef range_t* range_ptr; 10793 | typedef range_interface<T> irange_t; 10794 | typedef irange_t* irange_ptr; 10795 | typedef expression_node <T>* expression_ptr; 10796 | typedef string_base_node<T>* str_base_ptr; 10797 | 10798 | using binary_node<T>::branch; 10799 | 10800 | swap_genstrings_node(expression_ptr branch0, 10801 | expression_ptr branch1) 10802 | : binary_node<T>(details::e_default, branch0, branch1) 10803 | , str0_base_ptr_ (0) 10804 | , str1_base_ptr_ (0) 10805 | , str0_range_ptr_(0) 10806 | , str1_range_ptr_(0) 10807 | , initialised_(false) 10808 | { 10809 | if (is_generally_string_node(branch(0))) 10810 | { 10811 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0)); 10812 | 10813 | if (0 == str0_base_ptr_) 10814 | return; 10815 | 10816 | irange_ptr range = dynamic_cast<irange_ptr>(branch(0)); 10817 | 10818 | if (0 == range) 10819 | return; 10820 | 10821 | str0_range_ptr_ = &(range->range_ref()); 10822 | } 10823 | 10824 | if (is_generally_string_node(branch(1))) 10825 | { 10826 | str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1)); 10827 | 10828 | if (0 == str1_base_ptr_) 10829 | return; 10830 | 10831 | irange_ptr range = dynamic_cast<irange_ptr>(branch(1)); 10832 | 10833 | if (0 == range) 10834 | return; 10835 | 10836 | str1_range_ptr_ = &(range->range_ref()); 10837 | } 10838 | 10839 | initialised_ = str0_base_ptr_ && 10840 | str1_base_ptr_ && 10841 | str0_range_ptr_ && 10842 | str1_range_ptr_ ; 10843 | 10844 | assert(valid()); 10845 | } 10846 | 10847 | inline T value() const exprtk_override 10848 | { 10849 | branch(0)->value(); 10850 | branch(1)->value(); 10851 | 10852 | std::size_t str0_r0 = 0; 10853 | std::size_t str0_r1 = 0; 10854 | 10855 | std::size_t str1_r0 = 0; 10856 | std::size_t str1_r1 = 0; 10857 | 10858 | const range_t& range0 = (*str0_range_ptr_); 10859 | const range_t& range1 = (*str1_range_ptr_); 10860 | 10861 | if ( 10862 | range0(str0_r0, str0_r1, str0_base_ptr_->size()) && 10863 | range1(str1_r0, str1_r1, str1_base_ptr_->size()) 10864 | ) 10865 | { 10866 | const std::size_t size0 = range0.cache_size(); 10867 | const std::size_t size1 = range1.cache_size(); 10868 | const std::size_t max_size = std::min(size0,size1); 10869 | 10870 | char_ptr s0 = const_cast<char_ptr>(str0_base_ptr_->base() + str0_r0); 10871 | char_ptr s1 = const_cast<char_ptr>(str1_base_ptr_->base() + str1_r0); 10872 | 10873 | loop_unroll::details lud(max_size); 10874 | char_cptr upper_bound = s0 + lud.upper_bound; 10875 | 10876 | while (s0 < upper_bound) 10877 | { 10878 | #define exprtk_loop(N) \ 10879 | std::swap(s0[N], s1[N]); \ 10880 | 10881 | exprtk_loop( 0) exprtk_loop( 1) 10882 | exprtk_loop( 2) exprtk_loop( 3) 10883 | #ifndef exprtk_disable_superscalar_unroll 10884 | exprtk_loop( 4) exprtk_loop( 5) 10885 | exprtk_loop( 6) exprtk_loop( 7) 10886 | exprtk_loop( 8) exprtk_loop( 9) 10887 | exprtk_loop(10) exprtk_loop(11) 10888 | exprtk_loop(12) exprtk_loop(13) 10889 | exprtk_loop(14) exprtk_loop(15) 10890 | #endif 10891 | 10892 | s0 += lud.batch_size; 10893 | s1 += lud.batch_size; 10894 | } 10895 | 10896 | int i = 0; 10897 | 10898 | switch (lud.remainder) 10899 | { 10900 | #define case_stmt(N) \ 10901 | case N : { std::swap(s0[i], s1[i]); ++i; } \ 10902 | exprtk_fallthrough \ 10903 | 10904 | #ifndef exprtk_disable_superscalar_unroll 10905 | case_stmt(15) case_stmt(14) 10906 | case_stmt(13) case_stmt(12) 10907 | case_stmt(11) case_stmt(10) 10908 | case_stmt( 9) case_stmt( 8) 10909 | case_stmt( 7) case_stmt( 6) 10910 | case_stmt( 5) case_stmt( 4) 10911 | #endif 10912 | case_stmt( 3) case_stmt( 2) 10913 | case_stmt( 1) 10914 | default: break; 10915 | } 10916 | 10917 | #undef exprtk_loop 10918 | #undef case_stmt 10919 | } 10920 | 10921 | return std::numeric_limits<T>::quiet_NaN(); 10922 | } 10923 | 10924 | inline typename expression_node<T>::node_type type() const exprtk_override 10925 | { 10926 | return expression_node<T>::e_strswap; 10927 | } 10928 | 10929 | inline bool valid() const exprtk_override 10930 | { 10931 | return initialised_ && binary_node<T>::valid(); 10932 | } 10933 | 10934 | private: 10935 | 10936 | swap_genstrings_node(const swap_genstrings_node<T>&) exprtk_delete; 10937 | swap_genstrings_node<T>& operator=(const swap_genstrings_node<T>&) exprtk_delete; 10938 | 10939 | str_base_ptr str0_base_ptr_; 10940 | str_base_ptr str1_base_ptr_; 10941 | range_ptr str0_range_ptr_; 10942 | range_ptr str1_range_ptr_; 10943 | bool initialised_; 10944 | }; 10945 | 10946 | template <typename T> 10947 | class stringvar_size_node exprtk_final : public expression_node<T> 10948 | { 10949 | public: 10950 | 10951 | static const std::string null_value; 10952 | 10953 | explicit stringvar_size_node() 10954 | : value_(&null_value) 10955 | {} 10956 | 10957 | explicit stringvar_size_node(std::string& v) 10958 | : value_(&v) 10959 | {} 10960 | 10961 | inline T value() const exprtk_override 10962 | { 10963 | return T((*value_).size()); 10964 | } 10965 | 10966 | inline typename expression_node<T>::node_type type() const exprtk_override 10967 | { 10968 | return expression_node<T>::e_stringvarsize; 10969 | } 10970 | 10971 | private: 10972 | 10973 | const std::string* value_; 10974 | }; 10975 | 10976 | template <typename T> 10977 | const std::string stringvar_size_node<T>::null_value = std::string(""); 10978 | 10979 | template <typename T> 10980 | class string_size_node exprtk_final : public expression_node<T> 10981 | { 10982 | public: 10983 | 10984 | typedef expression_node <T>* expression_ptr; 10985 | typedef string_base_node<T>* str_base_ptr; 10986 | typedef std::pair<expression_ptr,bool> branch_t; 10987 | 10988 | explicit string_size_node(expression_ptr branch) 10989 | : str_base_ptr_(0) 10990 | { 10991 | construct_branch_pair(branch_, branch); 10992 | 10993 | if (is_generally_string_node(branch_.first)) 10994 | { 10995 | str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_.first); 10996 | } 10997 | 10998 | assert(valid()); 10999 | } 11000 | 11001 | inline T value() const exprtk_override 11002 | { 11003 | branch_.first->value(); 11004 | return T(str_base_ptr_->size()); 11005 | } 11006 | 11007 | inline typename expression_node<T>::node_type type() const exprtk_override 11008 | { 11009 | return expression_node<T>::e_stringsize; 11010 | } 11011 | 11012 | inline bool valid() const exprtk_override 11013 | { 11014 | return str_base_ptr_; 11015 | } 11016 | 11017 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 11018 | { 11019 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 11020 | } 11021 | 11022 | std::size_t node_depth() const exprtk_override 11023 | { 11024 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 11025 | } 11026 | 11027 | private: 11028 | 11029 | branch_t branch_; 11030 | str_base_ptr str_base_ptr_; 11031 | }; 11032 | 11033 | struct asn_assignment 11034 | { 11035 | static inline void execute(std::string& s, char_cptr data, const std::size_t size) 11036 | { s.assign(data,size); } 11037 | }; 11038 | 11039 | struct asn_addassignment 11040 | { 11041 | static inline void execute(std::string& s, char_cptr data, const std::size_t size) 11042 | { s.append(data,size); } 11043 | }; 11044 | 11045 | template <typename T, typename AssignmentProcess = asn_assignment> 11046 | class assignment_string_node exprtk_final 11047 | : public binary_node <T> 11048 | , public string_base_node<T> 11049 | , public range_interface <T> 11050 | { 11051 | public: 11052 | 11053 | typedef typename range_interface<T>::range_t range_t; 11054 | typedef range_t* range_ptr; 11055 | typedef range_interface <T> irange_t; 11056 | typedef irange_t* irange_ptr; 11057 | typedef expression_node <T>* expression_ptr; 11058 | typedef stringvar_node <T>* strvar_node_ptr; 11059 | typedef string_base_node<T>* str_base_ptr; 11060 | 11061 | using binary_node<T>::branch; 11062 | 11063 | assignment_string_node(const operator_type& opr, 11064 | expression_ptr branch0, 11065 | expression_ptr branch1) 11066 | : binary_node<T>(opr, branch0, branch1) 11067 | , initialised_(false) 11068 | , str0_base_ptr_ (0) 11069 | , str1_base_ptr_ (0) 11070 | , str0_node_ptr_ (0) 11071 | , str1_range_ptr_(0) 11072 | { 11073 | if (is_string_node(branch(0))) 11074 | { 11075 | str0_node_ptr_ = static_cast<strvar_node_ptr>(branch(0)); 11076 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0)); 11077 | } 11078 | 11079 | if (is_generally_string_node(branch(1))) 11080 | { 11081 | str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1)); 11082 | 11083 | if (0 == str1_base_ptr_) 11084 | return; 11085 | 11086 | irange_ptr range = dynamic_cast<irange_ptr>(branch(1)); 11087 | 11088 | if (0 == range) 11089 | return; 11090 | 11091 | str1_range_ptr_ = &(range->range_ref()); 11092 | } 11093 | 11094 | initialised_ = str0_base_ptr_ && 11095 | str1_base_ptr_ && 11096 | str0_node_ptr_ && 11097 | str1_range_ptr_ ; 11098 | 11099 | assert(valid()); 11100 | } 11101 | 11102 | inline T value() const exprtk_override 11103 | { 11104 | branch(1)->value(); 11105 | 11106 | std::size_t r0 = 0; 11107 | std::size_t r1 = 0; 11108 | 11109 | const range_t& range = (*str1_range_ptr_); 11110 | 11111 | if (range(r0, r1, str1_base_ptr_->size())) 11112 | { 11113 | AssignmentProcess::execute( 11114 | str0_node_ptr_->ref(), 11115 | str1_base_ptr_->base() + r0, (r1 - r0)); 11116 | 11117 | branch(0)->value(); 11118 | } 11119 | 11120 | return std::numeric_limits<T>::quiet_NaN(); 11121 | } 11122 | 11123 | std::string str() const exprtk_override 11124 | { 11125 | return str0_node_ptr_->str(); 11126 | } 11127 | 11128 | char_cptr base() const exprtk_override 11129 | { 11130 | return str0_node_ptr_->base(); 11131 | } 11132 | 11133 | std::size_t size() const exprtk_override 11134 | { 11135 | return str0_node_ptr_->size(); 11136 | } 11137 | 11138 | range_t& range_ref() exprtk_override 11139 | { 11140 | return str0_node_ptr_->range_ref(); 11141 | } 11142 | 11143 | const range_t& range_ref() const exprtk_override 11144 | { 11145 | return str0_node_ptr_->range_ref(); 11146 | } 11147 | 11148 | inline typename expression_node<T>::node_type type() const exprtk_override 11149 | { 11150 | return expression_node<T>::e_strass; 11151 | } 11152 | 11153 | inline bool valid() const exprtk_override 11154 | { 11155 | return initialised_ && binary_node<T>::valid(); 11156 | } 11157 | 11158 | private: 11159 | 11160 | bool initialised_; 11161 | str_base_ptr str0_base_ptr_; 11162 | str_base_ptr str1_base_ptr_; 11163 | strvar_node_ptr str0_node_ptr_; 11164 | range_ptr str1_range_ptr_; 11165 | }; 11166 | 11167 | template <typename T, typename AssignmentProcess = asn_assignment> 11168 | class assignment_string_range_node exprtk_final 11169 | : public binary_node <T> 11170 | , public string_base_node<T> 11171 | , public range_interface <T> 11172 | { 11173 | public: 11174 | 11175 | typedef typename range_interface<T>::range_t range_t; 11176 | typedef range_t* range_ptr; 11177 | typedef range_interface <T> irange_t; 11178 | typedef irange_t* irange_ptr; 11179 | typedef expression_node <T>* expression_ptr; 11180 | typedef stringvar_node <T>* strvar_node_ptr; 11181 | typedef string_range_node<T>* str_rng_node_ptr; 11182 | typedef string_base_node <T>* str_base_ptr; 11183 | 11184 | using binary_node<T>::branch; 11185 | 11186 | assignment_string_range_node(const operator_type& opr, 11187 | expression_ptr branch0, 11188 | expression_ptr branch1) 11189 | : binary_node<T>(opr, branch0, branch1) 11190 | , initialised_(false) 11191 | , str0_base_ptr_ (0) 11192 | , str1_base_ptr_ (0) 11193 | , str0_rng_node_ptr_(0) 11194 | , str0_range_ptr_ (0) 11195 | , str1_range_ptr_ (0) 11196 | { 11197 | if (is_string_range_node(branch(0))) 11198 | { 11199 | str0_rng_node_ptr_ = static_cast<str_rng_node_ptr>(branch(0)); 11200 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0)); 11201 | irange_ptr range = dynamic_cast<irange_ptr>(branch(0)); 11202 | 11203 | if (0 == range) 11204 | return; 11205 | 11206 | str0_range_ptr_ = &(range->range_ref()); 11207 | } 11208 | 11209 | if (is_generally_string_node(branch(1))) 11210 | { 11211 | str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1)); 11212 | 11213 | if (0 == str1_base_ptr_) 11214 | return; 11215 | 11216 | irange_ptr range = dynamic_cast<irange_ptr>(branch(1)); 11217 | 11218 | if (0 == range) 11219 | return; 11220 | 11221 | str1_range_ptr_ = &(range->range_ref()); 11222 | } 11223 | 11224 | initialised_ = str0_base_ptr_ && 11225 | str1_base_ptr_ && 11226 | str0_rng_node_ptr_ && 11227 | str0_range_ptr_ && 11228 | str1_range_ptr_ ; 11229 | 11230 | assert(valid()); 11231 | } 11232 | 11233 | inline T value() const exprtk_override 11234 | { 11235 | branch(0)->value(); 11236 | branch(1)->value(); 11237 | 11238 | std::size_t s0_r0 = 0; 11239 | std::size_t s0_r1 = 0; 11240 | 11241 | std::size_t s1_r0 = 0; 11242 | std::size_t s1_r1 = 0; 11243 | 11244 | const range_t& range0 = (*str0_range_ptr_); 11245 | const range_t& range1 = (*str1_range_ptr_); 11246 | 11247 | if ( 11248 | range0(s0_r0, s0_r1, str0_base_ptr_->size()) && 11249 | range1(s1_r0, s1_r1, str1_base_ptr_->size()) 11250 | ) 11251 | { 11252 | const std::size_t size = std::min((s0_r1 - s0_r0), (s1_r1 - s1_r0)); 11253 | 11254 | std::copy( 11255 | str1_base_ptr_->base() + s1_r0, 11256 | str1_base_ptr_->base() + s1_r0 + size, 11257 | const_cast<char_ptr>(base() + s0_r0)); 11258 | } 11259 | 11260 | return std::numeric_limits<T>::quiet_NaN(); 11261 | } 11262 | 11263 | std::string str() const exprtk_override 11264 | { 11265 | return str0_base_ptr_->str(); 11266 | } 11267 | 11268 | char_cptr base() const exprtk_override 11269 | { 11270 | return str0_base_ptr_->base(); 11271 | } 11272 | 11273 | std::size_t size() const exprtk_override 11274 | { 11275 | return str0_base_ptr_->size(); 11276 | } 11277 | 11278 | range_t& range_ref() exprtk_override 11279 | { 11280 | return str0_rng_node_ptr_->range_ref(); 11281 | } 11282 | 11283 | const range_t& range_ref() const exprtk_override 11284 | { 11285 | return str0_rng_node_ptr_->range_ref(); 11286 | } 11287 | 11288 | inline typename expression_node<T>::node_type type() const exprtk_override 11289 | { 11290 | return expression_node<T>::e_strass; 11291 | } 11292 | 11293 | inline bool valid() const exprtk_override 11294 | { 11295 | return initialised_ && binary_node<T>::valid(); 11296 | } 11297 | 11298 | private: 11299 | 11300 | bool initialised_; 11301 | str_base_ptr str0_base_ptr_; 11302 | str_base_ptr str1_base_ptr_; 11303 | str_rng_node_ptr str0_rng_node_ptr_; 11304 | range_ptr str0_range_ptr_; 11305 | range_ptr str1_range_ptr_; 11306 | }; 11307 | 11308 | template <typename T> 11309 | class conditional_string_node exprtk_final 11310 | : public trinary_node <T> 11311 | , public string_base_node<T> 11312 | , public range_interface <T> 11313 | { 11314 | public: 11315 | 11316 | typedef typename range_interface<T>::range_t range_t; 11317 | typedef range_t* range_ptr; 11318 | typedef range_interface <T> irange_t; 11319 | typedef irange_t* irange_ptr; 11320 | typedef expression_node <T>* expression_ptr; 11321 | typedef string_base_node<T>* str_base_ptr; 11322 | 11323 | conditional_string_node(expression_ptr condition, 11324 | expression_ptr consequent, 11325 | expression_ptr alternative) 11326 | : trinary_node<T>(details::e_default, consequent, alternative, condition) 11327 | , initialised_(false) 11328 | , str0_base_ptr_ (0) 11329 | , str1_base_ptr_ (0) 11330 | , str0_range_ptr_(0) 11331 | , str1_range_ptr_(0) 11332 | , condition_ (condition ) 11333 | , consequent_ (consequent ) 11334 | , alternative_(alternative) 11335 | { 11336 | range_.n0_c = std::make_pair<bool,std::size_t>(true,0); 11337 | range_.n1_c = std::make_pair<bool,std::size_t>(true,0); 11338 | 11339 | range_.cache.first = range_.n0_c.second; 11340 | range_.cache.second = range_.n1_c.second; 11341 | 11342 | if (is_generally_string_node(trinary_node<T>::branch_[0].first)) 11343 | { 11344 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(trinary_node<T>::branch_[0].first); 11345 | 11346 | if (0 == str0_base_ptr_) 11347 | return; 11348 | 11349 | str0_range_ptr_ = dynamic_cast<irange_ptr>(trinary_node<T>::branch_[0].first); 11350 | 11351 | if (0 == str0_range_ptr_) 11352 | return; 11353 | } 11354 | 11355 | if (is_generally_string_node(trinary_node<T>::branch_[1].first)) 11356 | { 11357 | str1_base_ptr_ = dynamic_cast<str_base_ptr>(trinary_node<T>::branch_[1].first); 11358 | 11359 | if (0 == str1_base_ptr_) 11360 | return; 11361 | 11362 | str1_range_ptr_ = dynamic_cast<irange_ptr>(trinary_node<T>::branch_[1].first); 11363 | 11364 | if (0 == str1_range_ptr_) 11365 | return; 11366 | } 11367 | 11368 | initialised_ = str0_base_ptr_ && 11369 | str1_base_ptr_ && 11370 | str0_range_ptr_ && 11371 | str1_range_ptr_ ; 11372 | 11373 | assert(valid()); 11374 | } 11375 | 11376 | inline T value() const exprtk_override 11377 | { 11378 | std::size_t r0 = 0; 11379 | std::size_t r1 = 0; 11380 | 11381 | if (is_true(condition_)) 11382 | { 11383 | consequent_->value(); 11384 | 11385 | const range_t& range = str0_range_ptr_->range_ref(); 11386 | 11387 | if (range(r0, r1, str0_base_ptr_->size())) 11388 | { 11389 | const std::size_t size = (r1 - r0); 11390 | 11391 | value_.assign(str0_base_ptr_->base() + r0, size); 11392 | 11393 | range_.n1_c.second = value_.size(); 11394 | range_.cache.second = range_.n1_c.second; 11395 | 11396 | return T(1); 11397 | } 11398 | } 11399 | else 11400 | { 11401 | alternative_->value(); 11402 | 11403 | const range_t& range = str1_range_ptr_->range_ref(); 11404 | 11405 | if (range(r0, r1, str1_base_ptr_->size())) 11406 | { 11407 | const std::size_t size = (r1 - r0); 11408 | 11409 | value_.assign(str1_base_ptr_->base() + r0, size); 11410 | 11411 | range_.n1_c.second = value_.size(); 11412 | range_.cache.second = range_.n1_c.second; 11413 | 11414 | return T(0); 11415 | } 11416 | } 11417 | 11418 | return std::numeric_limits<T>::quiet_NaN(); 11419 | } 11420 | 11421 | std::string str() const exprtk_override 11422 | { 11423 | return value_; 11424 | } 11425 | 11426 | char_cptr base() const exprtk_override 11427 | { 11428 | return &value_[0]; 11429 | } 11430 | 11431 | std::size_t size() const exprtk_override 11432 | { 11433 | return value_.size(); 11434 | } 11435 | 11436 | range_t& range_ref() exprtk_override 11437 | { 11438 | return range_; 11439 | } 11440 | 11441 | const range_t& range_ref() const exprtk_override 11442 | { 11443 | return range_; 11444 | } 11445 | 11446 | inline typename expression_node<T>::node_type type() const exprtk_override 11447 | { 11448 | return expression_node<T>::e_strcondition; 11449 | } 11450 | 11451 | inline bool valid() const exprtk_override 11452 | { 11453 | return 11454 | initialised_ && 11455 | condition_ && condition_ ->valid() && 11456 | consequent_ && consequent_ ->valid() && 11457 | alternative_&& alternative_->valid() ; 11458 | } 11459 | 11460 | private: 11461 | 11462 | bool initialised_; 11463 | str_base_ptr str0_base_ptr_; 11464 | str_base_ptr str1_base_ptr_; 11465 | irange_ptr str0_range_ptr_; 11466 | irange_ptr str1_range_ptr_; 11467 | mutable range_t range_; 11468 | mutable std::string value_; 11469 | 11470 | expression_ptr condition_; 11471 | expression_ptr consequent_; 11472 | expression_ptr alternative_; 11473 | }; 11474 | 11475 | template <typename T> 11476 | class cons_conditional_str_node exprtk_final 11477 | : public binary_node <T> 11478 | , public string_base_node<T> 11479 | , public range_interface <T> 11480 | { 11481 | public: 11482 | 11483 | typedef typename range_interface<T>::range_t range_t; 11484 | typedef range_t* range_ptr; 11485 | typedef range_interface <T> irange_t; 11486 | typedef irange_t* irange_ptr; 11487 | typedef expression_node <T>* expression_ptr; 11488 | typedef string_base_node<T>* str_base_ptr; 11489 | 11490 | using binary_node<T>::branch; 11491 | 11492 | cons_conditional_str_node(expression_ptr condition, 11493 | expression_ptr consequent) 11494 | : binary_node<T>(details::e_default, consequent, condition) 11495 | , initialised_(false) 11496 | , str0_base_ptr_ (0) 11497 | , str0_range_ptr_(0) 11498 | , condition_ (condition ) 11499 | , consequent_(consequent) 11500 | { 11501 | range_.n0_c = std::make_pair<bool,std::size_t>(true,0); 11502 | range_.n1_c = std::make_pair<bool,std::size_t>(true,0); 11503 | 11504 | range_.cache.first = range_.n0_c.second; 11505 | range_.cache.second = range_.n1_c.second; 11506 | 11507 | if (is_generally_string_node(branch(0))) 11508 | { 11509 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0)); 11510 | 11511 | if (0 == str0_base_ptr_) 11512 | return; 11513 | 11514 | str0_range_ptr_ = dynamic_cast<irange_ptr>(branch(0)); 11515 | 11516 | if (0 == str0_range_ptr_) 11517 | return; 11518 | } 11519 | 11520 | initialised_ = str0_base_ptr_ && str0_range_ptr_ ; 11521 | assert(valid()); 11522 | } 11523 | 11524 | inline T value() const exprtk_override 11525 | { 11526 | if (is_true(condition_)) 11527 | { 11528 | consequent_->value(); 11529 | 11530 | const range_t& range = str0_range_ptr_->range_ref(); 11531 | 11532 | std::size_t r0 = 0; 11533 | std::size_t r1 = 0; 11534 | 11535 | if (range(r0, r1, str0_base_ptr_->size())) 11536 | { 11537 | const std::size_t size = (r1 - r0); 11538 | 11539 | value_.assign(str0_base_ptr_->base() + r0, size); 11540 | 11541 | range_.n1_c.second = value_.size(); 11542 | range_.cache.second = range_.n1_c.second; 11543 | 11544 | return T(1); 11545 | } 11546 | } 11547 | 11548 | return std::numeric_limits<T>::quiet_NaN(); 11549 | } 11550 | 11551 | std::string str() const 11552 | { 11553 | return value_; 11554 | } 11555 | 11556 | char_cptr base() const 11557 | { 11558 | return &value_[0]; 11559 | } 11560 | 11561 | std::size_t size() const 11562 | { 11563 | return value_.size(); 11564 | } 11565 | 11566 | range_t& range_ref() 11567 | { 11568 | return range_; 11569 | } 11570 | 11571 | const range_t& range_ref() const 11572 | { 11573 | return range_; 11574 | } 11575 | 11576 | inline typename expression_node<T>::node_type type() const exprtk_override 11577 | { 11578 | return expression_node<T>::e_strccondition; 11579 | } 11580 | 11581 | inline bool valid() const exprtk_override 11582 | { 11583 | return 11584 | initialised_ && 11585 | condition_ && condition_ ->valid() && 11586 | consequent_ && consequent_ ->valid() ; 11587 | } 11588 | 11589 | private: 11590 | 11591 | bool initialised_; 11592 | str_base_ptr str0_base_ptr_; 11593 | irange_ptr str0_range_ptr_; 11594 | mutable range_t range_; 11595 | mutable std::string value_; 11596 | 11597 | expression_ptr condition_; 11598 | expression_ptr consequent_; 11599 | }; 11600 | 11601 | template <typename T, typename VarArgFunction> 11602 | class str_vararg_node exprtk_final 11603 | : public expression_node <T> 11604 | , public string_base_node<T> 11605 | , public range_interface <T> 11606 | { 11607 | public: 11608 | 11609 | typedef typename range_interface<T>::range_t range_t; 11610 | typedef range_t* range_ptr; 11611 | typedef range_interface <T> irange_t; 11612 | typedef irange_t* irange_ptr; 11613 | typedef expression_node <T>* expression_ptr; 11614 | typedef string_base_node<T>* str_base_ptr; 11615 | typedef std::pair<expression_ptr,bool> branch_t; 11616 | 11617 | template <typename Allocator, 11618 | template <typename, typename> class Sequence> 11619 | explicit str_vararg_node(const Sequence<expression_ptr,Allocator>& arg_list) 11620 | : initialised_(false) 11621 | , str_base_ptr_ (0) 11622 | , str_range_ptr_(0) 11623 | { 11624 | construct_branch_pair(final_node_, const_cast<expression_ptr>(arg_list.back())); 11625 | 11626 | if (0 == final_node_.first) 11627 | return; 11628 | else if (!is_generally_string_node(final_node_.first)) 11629 | return; 11630 | 11631 | str_base_ptr_ = dynamic_cast<str_base_ptr>(final_node_.first); 11632 | 11633 | if (0 == str_base_ptr_) 11634 | return; 11635 | 11636 | str_range_ptr_ = dynamic_cast<irange_ptr>(final_node_.first); 11637 | 11638 | if (0 == str_range_ptr_) 11639 | return; 11640 | 11641 | if (arg_list.size() > 1) 11642 | { 11643 | const std::size_t arg_list_size = arg_list.size() - 1; 11644 | 11645 | arg_list_.resize(arg_list_size); 11646 | 11647 | for (std::size_t i = 0; i < arg_list_size; ++i) 11648 | { 11649 | if (arg_list[i] && arg_list[i]->valid()) 11650 | { 11651 | construct_branch_pair(arg_list_[i], arg_list[i]); 11652 | } 11653 | else 11654 | { 11655 | arg_list_.clear(); 11656 | return; 11657 | } 11658 | } 11659 | 11660 | initialised_ = true; 11661 | } 11662 | 11663 | initialised_ &= str_base_ptr_ && str_range_ptr_; 11664 | assert(valid()); 11665 | } 11666 | 11667 | inline T value() const exprtk_override 11668 | { 11669 | if (!arg_list_.empty()) 11670 | { 11671 | VarArgFunction::process(arg_list_); 11672 | } 11673 | 11674 | final_node_.first->value(); 11675 | 11676 | return std::numeric_limits<T>::quiet_NaN(); 11677 | } 11678 | 11679 | std::string str() const exprtk_override 11680 | { 11681 | return str_base_ptr_->str(); 11682 | } 11683 | 11684 | char_cptr base() const exprtk_override 11685 | { 11686 | return str_base_ptr_->base(); 11687 | } 11688 | 11689 | std::size_t size() const exprtk_override 11690 | { 11691 | return str_base_ptr_->size(); 11692 | } 11693 | 11694 | range_t& range_ref() exprtk_override 11695 | { 11696 | return str_range_ptr_->range_ref(); 11697 | } 11698 | 11699 | const range_t& range_ref() const exprtk_override 11700 | { 11701 | return str_range_ptr_->range_ref(); 11702 | } 11703 | 11704 | inline typename expression_node<T>::node_type type() const exprtk_override 11705 | { 11706 | return expression_node<T>::e_stringvararg; 11707 | } 11708 | 11709 | inline bool valid() const exprtk_override 11710 | { 11711 | return 11712 | initialised_ && 11713 | final_node_.first && final_node_.first->valid(); 11714 | } 11715 | 11716 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 11717 | { 11718 | expression_node<T>::ndb_t::collect(final_node_ , node_delete_list); 11719 | expression_node<T>::ndb_t::collect(arg_list_ , node_delete_list); 11720 | } 11721 | 11722 | std::size_t node_depth() const exprtk_override 11723 | { 11724 | return std::max( 11725 | expression_node<T>::ndb_t::compute_node_depth(final_node_), 11726 | expression_node<T>::ndb_t::compute_node_depth(arg_list_ )); 11727 | } 11728 | 11729 | private: 11730 | 11731 | bool initialised_; 11732 | branch_t final_node_; 11733 | str_base_ptr str_base_ptr_; 11734 | irange_ptr str_range_ptr_; 11735 | std::vector<branch_t> arg_list_; 11736 | }; 11737 | #endif 11738 | 11739 | template <typename T> 11740 | class assert_node exprtk_final : public expression_node<T> 11741 | { 11742 | public: 11743 | 11744 | typedef expression_node<T>* expression_ptr; 11745 | typedef std::pair<expression_ptr,bool> branch_t; 11746 | typedef string_base_node<T>* str_base_ptr; 11747 | typedef assert_check::assert_context assert_context_t; 11748 | 11749 | assert_node(expression_ptr assert_condition_node, 11750 | expression_ptr assert_message_node, 11751 | assert_check_ptr assert_check, 11752 | assert_context_t context) 11753 | : assert_message_str_base_(0) 11754 | , assert_check_(assert_check) 11755 | , context_(context) 11756 | { 11757 | construct_branch_pair(assert_condition_node_, assert_condition_node); 11758 | construct_branch_pair(assert_message_node_ , assert_message_node ); 11759 | 11760 | #ifndef exprtk_disable_string_capabilities 11761 | if ( 11762 | assert_message_node_.first && 11763 | details::is_generally_string_node(assert_message_node_.first) 11764 | ) 11765 | { 11766 | assert_message_str_base_ = dynamic_cast<str_base_ptr>(assert_message_node_.first); 11767 | } 11768 | #endif 11769 | 11770 | assert(valid()); 11771 | } 11772 | 11773 | inline T value() const exprtk_override 11774 | { 11775 | if (details::is_true(assert_condition_node_.first->value())) 11776 | { 11777 | return T(1); 11778 | } 11779 | 11780 | #ifndef exprtk_disable_string_capabilities 11781 | if (assert_message_node_.first) 11782 | { 11783 | assert_message_node_.first->value(); 11784 | assert(assert_message_str_base_); 11785 | context_.message = assert_message_str_base_->str(); 11786 | } 11787 | #endif 11788 | 11789 | assert_check_->handle_assert(context_); 11790 | return T(0); 11791 | } 11792 | 11793 | inline typename expression_node<T>::node_type type() const exprtk_override 11794 | { 11795 | return expression_node<T>::e_assert; 11796 | } 11797 | 11798 | inline bool valid() const exprtk_override 11799 | { 11800 | return ( 11801 | assert_check_ && 11802 | assert_condition_node_.first && 11803 | assert_condition_node_.first->valid() 11804 | ) && 11805 | ( 11806 | (0 == assert_message_node_.first) || 11807 | ( 11808 | assert_message_node_.first && 11809 | assert_message_str_base_ && 11810 | assert_message_node_.first->valid() && 11811 | details::is_generally_string_node(assert_message_node_.first) 11812 | ) 11813 | ); 11814 | } 11815 | 11816 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 11817 | { 11818 | expression_node<T>::ndb_t::collect(assert_condition_node_, node_delete_list); 11819 | expression_node<T>::ndb_t::collect(assert_message_node_ , node_delete_list); 11820 | } 11821 | 11822 | std::size_t node_depth() const exprtk_override 11823 | { 11824 | return expression_node<T>::ndb_t::compute_node_depth 11825 | (assert_condition_node_, assert_message_node_); 11826 | } 11827 | 11828 | private: 11829 | 11830 | branch_t assert_condition_node_; 11831 | branch_t assert_message_node_; 11832 | str_base_ptr assert_message_str_base_; 11833 | assert_check_ptr assert_check_; 11834 | mutable assert_context_t context_; 11835 | }; 11836 | 11837 | template <typename T, std::size_t N> 11838 | inline T axn(const T a, const T x) 11839 | { 11840 | // a*x^n 11841 | return a * exprtk::details::numeric::fast_exp<T,N>::result(x); 11842 | } 11843 | 11844 | template <typename T, std::size_t N> 11845 | inline T axnb(const T a, const T x, const T b) 11846 | { 11847 | // a*x^n+b 11848 | return a * exprtk::details::numeric::fast_exp<T,N>::result(x) + b; 11849 | } 11850 | 11851 | template <typename T> 11852 | struct sf_base 11853 | { 11854 | typedef typename details::functor_t<T>::Type Type; 11855 | typedef typename details::functor_t<T> functor_t; 11856 | typedef typename functor_t::qfunc_t quaternary_functor_t; 11857 | typedef typename functor_t::tfunc_t trinary_functor_t; 11858 | typedef typename functor_t::bfunc_t binary_functor_t; 11859 | typedef typename functor_t::ufunc_t unary_functor_t; 11860 | }; 11861 | 11862 | #define define_sfop3(NN, OP0, OP1) \ 11863 | template <typename T> \ 11864 | struct sf##NN##_op : public sf_base<T> \ 11865 | { \ 11866 | typedef typename sf_base<T>::Type const Type; \ 11867 | static inline T process(Type x, Type y, Type z) \ 11868 | { \ 11869 | return (OP0); \ 11870 | } \ 11871 | static inline std::string id() \ 11872 | { \ 11873 | return (OP1); \ 11874 | } \ 11875 | }; \ 11876 | 11877 | define_sfop3(00,(x + y) / z ,"(t+t)/t") 11878 | define_sfop3(01,(x + y) * z ,"(t+t)*t") 11879 | define_sfop3(02,(x + y) - z ,"(t+t)-t") 11880 | define_sfop3(03,(x + y) + z ,"(t+t)+t") 11881 | define_sfop3(04,(x - y) + z ,"(t-t)+t") 11882 | define_sfop3(05,(x - y) / z ,"(t-t)/t") 11883 | define_sfop3(06,(x - y) * z ,"(t-t)*t") 11884 | define_sfop3(07,(x * y) + z ,"(t*t)+t") 11885 | define_sfop3(08,(x * y) - z ,"(t*t)-t") 11886 | define_sfop3(09,(x * y) / z ,"(t*t)/t") 11887 | define_sfop3(10,(x * y) * z ,"(t*t)*t") 11888 | define_sfop3(11,(x / y) + z ,"(t/t)+t") 11889 | define_sfop3(12,(x / y) - z ,"(t/t)-t") 11890 | define_sfop3(13,(x / y) / z ,"(t/t)/t") 11891 | define_sfop3(14,(x / y) * z ,"(t/t)*t") 11892 | define_sfop3(15,x / (y + z) ,"t/(t+t)") 11893 | define_sfop3(16,x / (y - z) ,"t/(t-t)") 11894 | define_sfop3(17,x / (y * z) ,"t/(t*t)") 11895 | define_sfop3(18,x / (y / z) ,"t/(t/t)") 11896 | define_sfop3(19,x * (y + z) ,"t*(t+t)") 11897 | define_sfop3(20,x * (y - z) ,"t*(t-t)") 11898 | define_sfop3(21,x * (y * z) ,"t*(t*t)") 11899 | define_sfop3(22,x * (y / z) ,"t*(t/t)") 11900 | define_sfop3(23,x - (y + z) ,"t-(t+t)") 11901 | define_sfop3(24,x - (y - z) ,"t-(t-t)") 11902 | define_sfop3(25,x - (y / z) ,"t-(t/t)") 11903 | define_sfop3(26,x - (y * z) ,"t-(t*t)") 11904 | define_sfop3(27,x + (y * z) ,"t+(t*t)") 11905 | define_sfop3(28,x + (y / z) ,"t+(t/t)") 11906 | define_sfop3(29,x + (y + z) ,"t+(t+t)") 11907 | define_sfop3(30,x + (y - z) ,"t+(t-t)") 11908 | define_sfop3(31,(axnb<T,2>(x,y,z))," ") 11909 | define_sfop3(32,(axnb<T,3>(x,y,z))," ") 11910 | define_sfop3(33,(axnb<T,4>(x,y,z))," ") 11911 | define_sfop3(34,(axnb<T,5>(x,y,z))," ") 11912 | define_sfop3(35,(axnb<T,6>(x,y,z))," ") 11913 | define_sfop3(36,(axnb<T,7>(x,y,z))," ") 11914 | define_sfop3(37,(axnb<T,8>(x,y,z))," ") 11915 | define_sfop3(38,(axnb<T,9>(x,y,z))," ") 11916 | define_sfop3(39,x * numeric::log(y) + z,"") 11917 | define_sfop3(40,x * numeric::log(y) - z,"") 11918 | define_sfop3(41,x * numeric::log10(y) + z,"") 11919 | define_sfop3(42,x * numeric::log10(y) - z,"") 11920 | define_sfop3(43,x * numeric::sin(y) + z ,"") 11921 | define_sfop3(44,x * numeric::sin(y) - z ,"") 11922 | define_sfop3(45,x * numeric::cos(y) + z ,"") 11923 | define_sfop3(46,x * numeric::cos(y) - z ,"") 11924 | define_sfop3(47,details::is_true(x) ? y : z,"") 11925 | 11926 | #define define_sfop4(NN, OP0, OP1) \ 11927 | template <typename T> \ 11928 | struct sf##NN##_op : public sf_base<T> \ 11929 | { \ 11930 | typedef typename sf_base<T>::Type const Type; \ 11931 | static inline T process(Type x, Type y, Type z, Type w) \ 11932 | { \ 11933 | return (OP0); \ 11934 | } \ 11935 | static inline std::string id() \ 11936 | { \ 11937 | return (OP1); \ 11938 | } \ 11939 | }; \ 11940 | 11941 | define_sfop4(48,(x + ((y + z) / w)),"t+((t+t)/t)") 11942 | define_sfop4(49,(x + ((y + z) * w)),"t+((t+t)*t)") 11943 | define_sfop4(50,(x + ((y - z) / w)),"t+((t-t)/t)") 11944 | define_sfop4(51,(x + ((y - z) * w)),"t+((t-t)*t)") 11945 | define_sfop4(52,(x + ((y * z) / w)),"t+((t*t)/t)") 11946 | define_sfop4(53,(x + ((y * z) * w)),"t+((t*t)*t)") 11947 | define_sfop4(54,(x + ((y / z) + w)),"t+((t/t)+t)") 11948 | define_sfop4(55,(x + ((y / z) / w)),"t+((t/t)/t)") 11949 | define_sfop4(56,(x + ((y / z) * w)),"t+((t/t)*t)") 11950 | define_sfop4(57,(x - ((y + z) / w)),"t-((t+t)/t)") 11951 | define_sfop4(58,(x - ((y + z) * w)),"t-((t+t)*t)") 11952 | define_sfop4(59,(x - ((y - z) / w)),"t-((t-t)/t)") 11953 | define_sfop4(60,(x - ((y - z) * w)),"t-((t-t)*t)") 11954 | define_sfop4(61,(x - ((y * z) / w)),"t-((t*t)/t)") 11955 | define_sfop4(62,(x - ((y * z) * w)),"t-((t*t)*t)") 11956 | define_sfop4(63,(x - ((y / z) / w)),"t-((t/t)/t)") 11957 | define_sfop4(64,(x - ((y / z) * w)),"t-((t/t)*t)") 11958 | define_sfop4(65,(((x + y) * z) - w),"((t+t)*t)-t") 11959 | define_sfop4(66,(((x - y) * z) - w),"((t-t)*t)-t") 11960 | define_sfop4(67,(((x * y) * z) - w),"((t*t)*t)-t") 11961 | define_sfop4(68,(((x / y) * z) - w),"((t/t)*t)-t") 11962 | define_sfop4(69,(((x + y) / z) - w),"((t+t)/t)-t") 11963 | define_sfop4(70,(((x - y) / z) - w),"((t-t)/t)-t") 11964 | define_sfop4(71,(((x * y) / z) - w),"((t*t)/t)-t") 11965 | define_sfop4(72,(((x / y) / z) - w),"((t/t)/t)-t") 11966 | define_sfop4(73,((x * y) + (z * w)),"(t*t)+(t*t)") 11967 | define_sfop4(74,((x * y) - (z * w)),"(t*t)-(t*t)") 11968 | define_sfop4(75,((x * y) + (z / w)),"(t*t)+(t/t)") 11969 | define_sfop4(76,((x * y) - (z / w)),"(t*t)-(t/t)") 11970 | define_sfop4(77,((x / y) + (z / w)),"(t/t)+(t/t)") 11971 | define_sfop4(78,((x / y) - (z / w)),"(t/t)-(t/t)") 11972 | define_sfop4(79,((x / y) - (z * w)),"(t/t)-(t*t)") 11973 | define_sfop4(80,(x / (y + (z * w))),"t/(t+(t*t))") 11974 | define_sfop4(81,(x / (y - (z * w))),"t/(t-(t*t))") 11975 | define_sfop4(82,(x * (y + (z * w))),"t*(t+(t*t))") 11976 | define_sfop4(83,(x * (y - (z * w))),"t*(t-(t*t))") 11977 | 11978 | define_sfop4(84,(axn<T,2>(x,y) + axn<T,2>(z,w)),"") 11979 | define_sfop4(85,(axn<T,3>(x,y) + axn<T,3>(z,w)),"") 11980 | define_sfop4(86,(axn<T,4>(x,y) + axn<T,4>(z,w)),"") 11981 | define_sfop4(87,(axn<T,5>(x,y) + axn<T,5>(z,w)),"") 11982 | define_sfop4(88,(axn<T,6>(x,y) + axn<T,6>(z,w)),"") 11983 | define_sfop4(89,(axn<T,7>(x,y) + axn<T,7>(z,w)),"") 11984 | define_sfop4(90,(axn<T,8>(x,y) + axn<T,8>(z,w)),"") 11985 | define_sfop4(91,(axn<T,9>(x,y) + axn<T,9>(z,w)),"") 11986 | define_sfop4(92,((details::is_true(x) && details::is_true(y)) ? z : w),"") 11987 | define_sfop4(93,((details::is_true(x) || details::is_true(y)) ? z : w),"") 11988 | define_sfop4(94,((x < y) ? z : w),"") 11989 | define_sfop4(95,((x <= y) ? z : w),"") 11990 | define_sfop4(96,((x > y) ? z : w),"") 11991 | define_sfop4(97,((x >= y) ? z : w),"") 11992 | define_sfop4(98,(details::is_true(numeric::equal(x,y)) ? z : w),"") 11993 | define_sfop4(99,(x * numeric::sin(y) + z * numeric::cos(w)),"") 11994 | 11995 | define_sfop4(ext00,((x + y) - (z * w)),"(t+t)-(t*t)") 11996 | define_sfop4(ext01,((x + y) - (z / w)),"(t+t)-(t/t)") 11997 | define_sfop4(ext02,((x + y) + (z * w)),"(t+t)+(t*t)") 11998 | define_sfop4(ext03,((x + y) + (z / w)),"(t+t)+(t/t)") 11999 | define_sfop4(ext04,((x - y) + (z * w)),"(t-t)+(t*t)") 12000 | define_sfop4(ext05,((x - y) + (z / w)),"(t-t)+(t/t)") 12001 | define_sfop4(ext06,((x - y) - (z * w)),"(t-t)-(t*t)") 12002 | define_sfop4(ext07,((x - y) - (z / w)),"(t-t)-(t/t)") 12003 | define_sfop4(ext08,((x + y) - (z - w)),"(t+t)-(t-t)") 12004 | define_sfop4(ext09,((x + y) + (z - w)),"(t+t)+(t-t)") 12005 | define_sfop4(ext10,((x + y) + (z + w)),"(t+t)+(t+t)") 12006 | define_sfop4(ext11,((x + y) * (z - w)),"(t+t)*(t-t)") 12007 | define_sfop4(ext12,((x + y) / (z - w)),"(t+t)/(t-t)") 12008 | define_sfop4(ext13,((x - y) - (z + w)),"(t-t)-(t+t)") 12009 | define_sfop4(ext14,((x - y) + (z + w)),"(t-t)+(t+t)") 12010 | define_sfop4(ext15,((x - y) * (z + w)),"(t-t)*(t+t)") 12011 | define_sfop4(ext16,((x - y) / (z + w)),"(t-t)/(t+t)") 12012 | define_sfop4(ext17,((x * y) - (z + w)),"(t*t)-(t+t)") 12013 | define_sfop4(ext18,((x / y) - (z + w)),"(t/t)-(t+t)") 12014 | define_sfop4(ext19,((x * y) + (z + w)),"(t*t)+(t+t)") 12015 | define_sfop4(ext20,((x / y) + (z + w)),"(t/t)+(t+t)") 12016 | define_sfop4(ext21,((x * y) + (z - w)),"(t*t)+(t-t)") 12017 | define_sfop4(ext22,((x / y) + (z - w)),"(t/t)+(t-t)") 12018 | define_sfop4(ext23,((x * y) - (z - w)),"(t*t)-(t-t)") 12019 | define_sfop4(ext24,((x / y) - (z - w)),"(t/t)-(t-t)") 12020 | define_sfop4(ext25,((x + y) * (z * w)),"(t+t)*(t*t)") 12021 | define_sfop4(ext26,((x + y) * (z / w)),"(t+t)*(t/t)") 12022 | define_sfop4(ext27,((x + y) / (z * w)),"(t+t)/(t*t)") 12023 | define_sfop4(ext28,((x + y) / (z / w)),"(t+t)/(t/t)") 12024 | define_sfop4(ext29,((x - y) / (z * w)),"(t-t)/(t*t)") 12025 | define_sfop4(ext30,((x - y) / (z / w)),"(t-t)/(t/t)") 12026 | define_sfop4(ext31,((x - y) * (z * w)),"(t-t)*(t*t)") 12027 | define_sfop4(ext32,((x - y) * (z / w)),"(t-t)*(t/t)") 12028 | define_sfop4(ext33,((x * y) * (z + w)),"(t*t)*(t+t)") 12029 | define_sfop4(ext34,((x / y) * (z + w)),"(t/t)*(t+t)") 12030 | define_sfop4(ext35,((x * y) / (z + w)),"(t*t)/(t+t)") 12031 | define_sfop4(ext36,((x / y) / (z + w)),"(t/t)/(t+t)") 12032 | define_sfop4(ext37,((x * y) / (z - w)),"(t*t)/(t-t)") 12033 | define_sfop4(ext38,((x / y) / (z - w)),"(t/t)/(t-t)") 12034 | define_sfop4(ext39,((x * y) * (z - w)),"(t*t)*(t-t)") 12035 | define_sfop4(ext40,((x * y) / (z * w)),"(t*t)/(t*t)") 12036 | define_sfop4(ext41,((x / y) * (z / w)),"(t/t)*(t/t)") 12037 | define_sfop4(ext42,((x / y) * (z - w)),"(t/t)*(t-t)") 12038 | define_sfop4(ext43,((x * y) * (z * w)),"(t*t)*(t*t)") 12039 | define_sfop4(ext44,(x + (y * (z / w))),"t+(t*(t/t))") 12040 | define_sfop4(ext45,(x - (y * (z / w))),"t-(t*(t/t))") 12041 | define_sfop4(ext46,(x + (y / (z * w))),"t+(t/(t*t))") 12042 | define_sfop4(ext47,(x - (y / (z * w))),"t-(t/(t*t))") 12043 | define_sfop4(ext48,(((x - y) - z) * w),"((t-t)-t)*t") 12044 | define_sfop4(ext49,(((x - y) - z) / w),"((t-t)-t)/t") 12045 | define_sfop4(ext50,(((x - y) + z) * w),"((t-t)+t)*t") 12046 | define_sfop4(ext51,(((x - y) + z) / w),"((t-t)+t)/t") 12047 | define_sfop4(ext52,((x + (y - z)) * w),"(t+(t-t))*t") 12048 | define_sfop4(ext53,((x + (y - z)) / w),"(t+(t-t))/t") 12049 | define_sfop4(ext54,((x + y) / (z + w)),"(t+t)/(t+t)") 12050 | define_sfop4(ext55,((x - y) / (z - w)),"(t-t)/(t-t)") 12051 | define_sfop4(ext56,((x + y) * (z + w)),"(t+t)*(t+t)") 12052 | define_sfop4(ext57,((x - y) * (z - w)),"(t-t)*(t-t)") 12053 | define_sfop4(ext58,((x - y) + (z - w)),"(t-t)+(t-t)") 12054 | define_sfop4(ext59,((x - y) - (z - w)),"(t-t)-(t-t)") 12055 | define_sfop4(ext60,((x / y) + (z * w)),"(t/t)+(t*t)") 12056 | define_sfop4(ext61,(((x * y) * z) / w),"((t*t)*t)/t") 12057 | 12058 | #undef define_sfop3 12059 | #undef define_sfop4 12060 | 12061 | template <typename T, typename SpecialFunction> 12062 | class sf3_node exprtk_final : public trinary_node<T> 12063 | { 12064 | public: 12065 | 12066 | typedef expression_node<T>* expression_ptr; 12067 | 12068 | sf3_node(const operator_type& opr, 12069 | expression_ptr branch0, 12070 | expression_ptr branch1, 12071 | expression_ptr branch2) 12072 | : trinary_node<T>(opr, branch0, branch1, branch2) 12073 | {} 12074 | 12075 | inline T value() const exprtk_override 12076 | { 12077 | const T x = trinary_node<T>::branch_[0].first->value(); 12078 | const T y = trinary_node<T>::branch_[1].first->value(); 12079 | const T z = trinary_node<T>::branch_[2].first->value(); 12080 | 12081 | return SpecialFunction::process(x, y, z); 12082 | } 12083 | }; 12084 | 12085 | template <typename T, typename SpecialFunction> 12086 | class sf4_node exprtk_final : public quaternary_node<T> 12087 | { 12088 | public: 12089 | 12090 | typedef expression_node<T>* expression_ptr; 12091 | 12092 | sf4_node(const operator_type& opr, 12093 | expression_ptr branch0, 12094 | expression_ptr branch1, 12095 | expression_ptr branch2, 12096 | expression_ptr branch3) 12097 | : quaternary_node<T>(opr, branch0, branch1, branch2, branch3) 12098 | {} 12099 | 12100 | inline T value() const exprtk_override 12101 | { 12102 | const T x = quaternary_node<T>::branch_[0].first->value(); 12103 | const T y = quaternary_node<T>::branch_[1].first->value(); 12104 | const T z = quaternary_node<T>::branch_[2].first->value(); 12105 | const T w = quaternary_node<T>::branch_[3].first->value(); 12106 | 12107 | return SpecialFunction::process(x, y, z, w); 12108 | } 12109 | }; 12110 | 12111 | template <typename T, typename SpecialFunction> 12112 | class sf3_var_node exprtk_final : public expression_node<T> 12113 | { 12114 | public: 12115 | 12116 | typedef expression_node<T>* expression_ptr; 12117 | 12118 | sf3_var_node(const T& v0, const T& v1, const T& v2) 12119 | : v0_(v0) 12120 | , v1_(v1) 12121 | , v2_(v2) 12122 | {} 12123 | 12124 | inline T value() const exprtk_override 12125 | { 12126 | return SpecialFunction::process(v0_, v1_, v2_); 12127 | } 12128 | 12129 | inline typename expression_node<T>::node_type type() const exprtk_override 12130 | { 12131 | return expression_node<T>::e_trinary; 12132 | } 12133 | 12134 | private: 12135 | 12136 | sf3_var_node(const sf3_var_node<T,SpecialFunction>&) exprtk_delete; 12137 | sf3_var_node<T,SpecialFunction>& operator=(const sf3_var_node<T,SpecialFunction>&) exprtk_delete; 12138 | 12139 | const T& v0_; 12140 | const T& v1_; 12141 | const T& v2_; 12142 | }; 12143 | 12144 | template <typename T, typename SpecialFunction> 12145 | class sf4_var_node exprtk_final : public expression_node<T> 12146 | { 12147 | public: 12148 | 12149 | typedef expression_node<T>* expression_ptr; 12150 | 12151 | sf4_var_node(const T& v0, const T& v1, const T& v2, const T& v3) 12152 | : v0_(v0) 12153 | , v1_(v1) 12154 | , v2_(v2) 12155 | , v3_(v3) 12156 | {} 12157 | 12158 | inline T value() const exprtk_override 12159 | { 12160 | return SpecialFunction::process(v0_, v1_, v2_, v3_); 12161 | } 12162 | 12163 | inline typename expression_node<T>::node_type type() const exprtk_override 12164 | { 12165 | return expression_node<T>::e_trinary; 12166 | } 12167 | 12168 | private: 12169 | 12170 | sf4_var_node(const sf4_var_node<T,SpecialFunction>&) exprtk_delete; 12171 | sf4_var_node<T,SpecialFunction>& operator=(const sf4_var_node<T,SpecialFunction>&) exprtk_delete; 12172 | 12173 | const T& v0_; 12174 | const T& v1_; 12175 | const T& v2_; 12176 | const T& v3_; 12177 | }; 12178 | 12179 | template <typename T, typename VarArgFunction> 12180 | class vararg_node exprtk_final : public expression_node<T> 12181 | { 12182 | public: 12183 | 12184 | typedef expression_node<T>* expression_ptr; 12185 | typedef std::pair<expression_ptr,bool> branch_t; 12186 | 12187 | template <typename Allocator, 12188 | template <typename, typename> class Sequence> 12189 | explicit vararg_node(const Sequence<expression_ptr,Allocator>& arg_list) 12190 | : initialised_(false) 12191 | { 12192 | arg_list_.resize(arg_list.size()); 12193 | 12194 | for (std::size_t i = 0; i < arg_list.size(); ++i) 12195 | { 12196 | if (arg_list[i] && arg_list[i]->valid()) 12197 | { 12198 | construct_branch_pair(arg_list_[i],arg_list[i]); 12199 | } 12200 | else 12201 | { 12202 | arg_list_.clear(); 12203 | return; 12204 | } 12205 | } 12206 | 12207 | initialised_ = (arg_list_.size() == arg_list.size()); 12208 | assert(valid()); 12209 | } 12210 | 12211 | inline T value() const exprtk_override 12212 | { 12213 | return VarArgFunction::process(arg_list_); 12214 | } 12215 | 12216 | inline typename expression_node<T>::node_type type() const exprtk_override 12217 | { 12218 | return expression_node<T>::e_vararg; 12219 | } 12220 | 12221 | inline bool valid() const exprtk_override 12222 | { 12223 | return initialised_; 12224 | } 12225 | 12226 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 12227 | { 12228 | expression_node<T>::ndb_t::collect(arg_list_, node_delete_list); 12229 | } 12230 | 12231 | std::size_t node_depth() const exprtk_override 12232 | { 12233 | return expression_node<T>::ndb_t::compute_node_depth(arg_list_); 12234 | } 12235 | 12236 | std::size_t size() const 12237 | { 12238 | return arg_list_.size(); 12239 | } 12240 | 12241 | expression_ptr operator[](const std::size_t& index) const 12242 | { 12243 | return arg_list_[index].first; 12244 | } 12245 | 12246 | private: 12247 | 12248 | std::vector<branch_t> arg_list_; 12249 | bool initialised_; 12250 | }; 12251 | 12252 | template <typename T, typename VarArgFunction> 12253 | class vararg_varnode exprtk_final : public expression_node<T> 12254 | { 12255 | public: 12256 | 12257 | typedef expression_node<T>* expression_ptr; 12258 | 12259 | template <typename Allocator, 12260 | template <typename, typename> class Sequence> 12261 | explicit vararg_varnode(const Sequence<expression_ptr,Allocator>& arg_list) 12262 | : initialised_(false) 12263 | { 12264 | arg_list_.resize(arg_list.size()); 12265 | 12266 | for (std::size_t i = 0; i < arg_list.size(); ++i) 12267 | { 12268 | if (arg_list[i] && arg_list[i]->valid() && is_variable_node(arg_list[i])) 12269 | { 12270 | variable_node<T>* var_node_ptr = static_cast<variable_node<T>*>(arg_list[i]); 12271 | arg_list_[i] = (&var_node_ptr->ref()); 12272 | } 12273 | else 12274 | { 12275 | arg_list_.clear(); 12276 | return; 12277 | } 12278 | } 12279 | 12280 | initialised_ = (arg_list.size() == arg_list_.size()); 12281 | assert(valid()); 12282 | } 12283 | 12284 | inline T value() const exprtk_override 12285 | { 12286 | return VarArgFunction::process(arg_list_); 12287 | } 12288 | 12289 | inline typename expression_node<T>::node_type type() const exprtk_override 12290 | { 12291 | return expression_node<T>::e_vararg; 12292 | } 12293 | 12294 | inline bool valid() const exprtk_override 12295 | { 12296 | return initialised_; 12297 | } 12298 | 12299 | private: 12300 | 12301 | std::vector<const T*> arg_list_; 12302 | bool initialised_; 12303 | }; 12304 | 12305 | template <typename T, typename VecFunction> 12306 | class vectorize_node exprtk_final : public expression_node<T> 12307 | { 12308 | public: 12309 | 12310 | typedef expression_node<T>* expression_ptr; 12311 | typedef std::pair<expression_ptr,bool> branch_t; 12312 | 12313 | explicit vectorize_node(const expression_ptr v) 12314 | : ivec_ptr_(0) 12315 | { 12316 | construct_branch_pair(v_, v); 12317 | 12318 | if (is_ivector_node(v_.first)) 12319 | { 12320 | ivec_ptr_ = dynamic_cast<vector_interface<T>*>(v_.first); 12321 | } 12322 | } 12323 | 12324 | inline T value() const exprtk_override 12325 | { 12326 | v_.first->value(); 12327 | return VecFunction::process(ivec_ptr_); 12328 | } 12329 | 12330 | inline typename expression_node<T>::node_type type() const exprtk_override 12331 | { 12332 | return expression_node<T>::e_vecfunc; 12333 | } 12334 | 12335 | inline bool valid() const exprtk_override 12336 | { 12337 | return ivec_ptr_ && v_.first && v_.first->valid(); 12338 | } 12339 | 12340 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 12341 | { 12342 | expression_node<T>::ndb_t::collect(v_, node_delete_list); 12343 | } 12344 | 12345 | std::size_t node_depth() const exprtk_override 12346 | { 12347 | return expression_node<T>::ndb_t::compute_node_depth(v_); 12348 | } 12349 | 12350 | private: 12351 | 12352 | vector_interface<T>* ivec_ptr_; 12353 | branch_t v_; 12354 | }; 12355 | 12356 | template <typename T> 12357 | class assignment_node exprtk_final : public binary_node<T> 12358 | { 12359 | public: 12360 | 12361 | typedef expression_node<T>* expression_ptr; 12362 | using binary_node<T>::branch; 12363 | 12364 | assignment_node(const operator_type& opr, 12365 | expression_ptr branch0, 12366 | expression_ptr branch1) 12367 | : binary_node<T>(opr, branch0, branch1) 12368 | , var_node_ptr_(0) 12369 | { 12370 | if (is_variable_node(branch(0))) 12371 | { 12372 | var_node_ptr_ = static_cast<variable_node<T>*>(branch(0)); 12373 | } 12374 | } 12375 | 12376 | inline T value() const exprtk_override 12377 | { 12378 | T& result = var_node_ptr_->ref(); 12379 | result = branch(1)->value(); 12380 | 12381 | return result; 12382 | } 12383 | 12384 | inline bool valid() const exprtk_override 12385 | { 12386 | return var_node_ptr_ && binary_node<T>::valid(); 12387 | } 12388 | 12389 | private: 12390 | 12391 | variable_node<T>* var_node_ptr_; 12392 | }; 12393 | 12394 | template <typename T> 12395 | class assignment_vec_elem_node exprtk_final : public binary_node<T> 12396 | { 12397 | public: 12398 | 12399 | typedef expression_node<T>* expression_ptr; 12400 | using binary_node<T>::branch; 12401 | 12402 | assignment_vec_elem_node(const operator_type& opr, 12403 | expression_ptr branch0, 12404 | expression_ptr branch1) 12405 | : binary_node<T>(opr, branch0, branch1) 12406 | , vec_node_ptr_(0) 12407 | { 12408 | if (is_vector_elem_node(branch(0))) 12409 | { 12410 | vec_node_ptr_ = static_cast<vector_elem_node<T>*>(branch(0)); 12411 | } 12412 | 12413 | assert(valid()); 12414 | } 12415 | 12416 | inline T value() const exprtk_override 12417 | { 12418 | T& result = vec_node_ptr_->ref(); 12419 | result = branch(1)->value(); 12420 | 12421 | return result; 12422 | } 12423 | 12424 | inline bool valid() const exprtk_override 12425 | { 12426 | return vec_node_ptr_ && binary_node<T>::valid(); 12427 | } 12428 | 12429 | private: 12430 | 12431 | vector_elem_node<T>* vec_node_ptr_; 12432 | }; 12433 | 12434 | template <typename T> 12435 | class assignment_vec_elem_rtc_node exprtk_final : public binary_node<T> 12436 | { 12437 | public: 12438 | 12439 | typedef expression_node<T>* expression_ptr; 12440 | using binary_node<T>::branch; 12441 | 12442 | assignment_vec_elem_rtc_node(const operator_type& opr, 12443 | expression_ptr branch0, 12444 | expression_ptr branch1) 12445 | : binary_node<T>(opr, branch0, branch1) 12446 | , vec_node_ptr_(0) 12447 | { 12448 | if (is_vector_elem_rtc_node(branch(0))) 12449 | { 12450 | vec_node_ptr_ = static_cast<vector_elem_rtc_node<T>*>(branch(0)); 12451 | } 12452 | 12453 | assert(valid()); 12454 | } 12455 | 12456 | inline T value() const exprtk_override 12457 | { 12458 | T& result = vec_node_ptr_->ref(); 12459 | result = branch(1)->value(); 12460 | 12461 | return result; 12462 | } 12463 | 12464 | inline bool valid() const exprtk_override 12465 | { 12466 | return vec_node_ptr_ && binary_node<T>::valid(); 12467 | } 12468 | 12469 | private: 12470 | 12471 | vector_elem_rtc_node<T>* vec_node_ptr_; 12472 | }; 12473 | 12474 | template <typename T> 12475 | class assignment_rebasevec_elem_node exprtk_final : public binary_node<T> 12476 | { 12477 | public: 12478 | 12479 | typedef expression_node<T>* expression_ptr; 12480 | using expression_node<T>::branch; 12481 | 12482 | assignment_rebasevec_elem_node(const operator_type& opr, 12483 | expression_ptr branch0, 12484 | expression_ptr branch1) 12485 | : binary_node<T>(opr, branch0, branch1) 12486 | , rbvec_node_ptr_(0) 12487 | { 12488 | if (is_rebasevector_elem_node(branch(0))) 12489 | { 12490 | rbvec_node_ptr_ = static_cast<rebasevector_elem_node<T>*>(branch(0)); 12491 | } 12492 | 12493 | assert(valid()); 12494 | } 12495 | 12496 | inline T value() const exprtk_override 12497 | { 12498 | T& result = rbvec_node_ptr_->ref(); 12499 | result = branch(1)->value(); 12500 | 12501 | return result; 12502 | } 12503 | 12504 | inline bool valid() const exprtk_override 12505 | { 12506 | return rbvec_node_ptr_ && binary_node<T>::valid(); 12507 | } 12508 | 12509 | private: 12510 | 12511 | rebasevector_elem_node<T>* rbvec_node_ptr_; 12512 | }; 12513 | 12514 | template <typename T> 12515 | class assignment_rebasevec_elem_rtc_node exprtk_final : public binary_node<T> 12516 | { 12517 | public: 12518 | 12519 | typedef expression_node<T>* expression_ptr; 12520 | using expression_node<T>::branch; 12521 | 12522 | assignment_rebasevec_elem_rtc_node(const operator_type& opr, 12523 | expression_ptr branch0, 12524 | expression_ptr branch1) 12525 | : binary_node<T>(opr, branch0, branch1) 12526 | , rbvec_node_ptr_(0) 12527 | { 12528 | if (is_rebasevector_elem_rtc_node(branch(0))) 12529 | { 12530 | rbvec_node_ptr_ = static_cast<rebasevector_elem_rtc_node<T>*>(branch(0)); 12531 | } 12532 | 12533 | assert(valid()); 12534 | } 12535 | 12536 | inline T value() const exprtk_override 12537 | { 12538 | T& result = rbvec_node_ptr_->ref(); 12539 | result = branch(1)->value(); 12540 | 12541 | return result; 12542 | } 12543 | 12544 | inline bool valid() const exprtk_override 12545 | { 12546 | return rbvec_node_ptr_ && binary_node<T>::valid(); 12547 | } 12548 | 12549 | private: 12550 | 12551 | rebasevector_elem_rtc_node<T>* rbvec_node_ptr_; 12552 | }; 12553 | 12554 | template <typename T> 12555 | class assignment_rebasevec_celem_node exprtk_final : public binary_node<T> 12556 | { 12557 | public: 12558 | 12559 | typedef expression_node<T>* expression_ptr; 12560 | using binary_node<T>::branch; 12561 | 12562 | assignment_rebasevec_celem_node(const operator_type& opr, 12563 | expression_ptr branch0, 12564 | expression_ptr branch1) 12565 | : binary_node<T>(opr, branch0, branch1) 12566 | , rbvec_node_ptr_(0) 12567 | { 12568 | if (is_rebasevector_celem_node(branch(0))) 12569 | { 12570 | rbvec_node_ptr_ = static_cast<rebasevector_celem_node<T>*>(branch(0)); 12571 | } 12572 | 12573 | assert(valid()); 12574 | } 12575 | 12576 | inline T value() const exprtk_override 12577 | { 12578 | T& result = rbvec_node_ptr_->ref(); 12579 | result = branch(1)->value(); 12580 | 12581 | return result; 12582 | } 12583 | 12584 | inline bool valid() const exprtk_override 12585 | { 12586 | return rbvec_node_ptr_ && binary_node<T>::valid(); 12587 | } 12588 | 12589 | private: 12590 | 12591 | rebasevector_celem_node<T>* rbvec_node_ptr_; 12592 | }; 12593 | 12594 | template <typename T> 12595 | class assignment_vec_node exprtk_final 12596 | : public binary_node <T> 12597 | , public vector_interface<T> 12598 | { 12599 | public: 12600 | 12601 | typedef expression_node<T>* expression_ptr; 12602 | typedef vector_node<T>* vector_node_ptr; 12603 | typedef vec_data_store<T> vds_t; 12604 | 12605 | using binary_node<T>::branch; 12606 | 12607 | assignment_vec_node(const operator_type& opr, 12608 | expression_ptr branch0, 12609 | expression_ptr branch1) 12610 | : binary_node<T>(opr, branch0, branch1) 12611 | , vec_node_ptr_(0) 12612 | { 12613 | if (is_vector_node(branch(0))) 12614 | { 12615 | vec_node_ptr_ = static_cast<vector_node<T>*>(branch(0)); 12616 | vds() = vec_node_ptr_->vds(); 12617 | } 12618 | 12619 | assert(valid()); 12620 | } 12621 | 12622 | inline T value() const exprtk_override 12623 | { 12624 | const T v = branch(1)->value(); 12625 | 12626 | T* vec = vds().data(); 12627 | 12628 | loop_unroll::details lud(size()); 12629 | const T* upper_bound = vec + lud.upper_bound; 12630 | 12631 | while (vec < upper_bound) 12632 | { 12633 | #define exprtk_loop(N) \ 12634 | vec[N] = v; \ 12635 | 12636 | exprtk_loop( 0) exprtk_loop( 1) 12637 | exprtk_loop( 2) exprtk_loop( 3) 12638 | #ifndef exprtk_disable_superscalar_unroll 12639 | exprtk_loop( 4) exprtk_loop( 5) 12640 | exprtk_loop( 6) exprtk_loop( 7) 12641 | exprtk_loop( 8) exprtk_loop( 9) 12642 | exprtk_loop(10) exprtk_loop(11) 12643 | exprtk_loop(12) exprtk_loop(13) 12644 | exprtk_loop(14) exprtk_loop(15) 12645 | #endif 12646 | 12647 | vec += lud.batch_size; 12648 | } 12649 | 12650 | switch (lud.remainder) 12651 | { 12652 | #define case_stmt(N) \ 12653 | case N : *vec++ = v; \ 12654 | exprtk_fallthrough \ 12655 | 12656 | #ifndef exprtk_disable_superscalar_unroll 12657 | case_stmt(15) case_stmt(14) 12658 | case_stmt(13) case_stmt(12) 12659 | case_stmt(11) case_stmt(10) 12660 | case_stmt( 9) case_stmt( 8) 12661 | case_stmt( 7) case_stmt( 6) 12662 | case_stmt( 5) case_stmt( 4) 12663 | #endif 12664 | case_stmt( 3) case_stmt( 2) 12665 | case 1 : *vec++ = v; 12666 | } 12667 | 12668 | #undef exprtk_loop 12669 | #undef case_stmt 12670 | 12671 | return vec_node_ptr_->value(); 12672 | } 12673 | 12674 | vector_node_ptr vec() const exprtk_override 12675 | { 12676 | return vec_node_ptr_; 12677 | } 12678 | 12679 | vector_node_ptr vec() exprtk_override 12680 | { 12681 | return vec_node_ptr_; 12682 | } 12683 | 12684 | inline typename expression_node<T>::node_type type() const exprtk_override 12685 | { 12686 | return expression_node<T>::e_vecvalass; 12687 | } 12688 | 12689 | inline bool valid() const exprtk_override 12690 | { 12691 | return 12692 | vec_node_ptr_ && 12693 | (vds().size() <= vec_node_ptr_->vec_holder().base_size()) && 12694 | binary_node<T>::valid(); 12695 | } 12696 | 12697 | std::size_t size() const exprtk_override 12698 | { 12699 | return vec_node_ptr_->vec_holder().size(); 12700 | } 12701 | 12702 | std::size_t base_size() const exprtk_override 12703 | { 12704 | return vec_node_ptr_->vec_holder().base_size(); 12705 | } 12706 | 12707 | vds_t& vds() exprtk_override 12708 | { 12709 | return vds_; 12710 | } 12711 | 12712 | const vds_t& vds() const exprtk_override 12713 | { 12714 | return vds_; 12715 | } 12716 | 12717 | private: 12718 | 12719 | vector_node<T>* vec_node_ptr_; 12720 | vds_t vds_; 12721 | }; 12722 | 12723 | template <typename T> 12724 | class assignment_vecvec_node exprtk_final 12725 | : public binary_node <T> 12726 | , public vector_interface<T> 12727 | { 12728 | public: 12729 | 12730 | typedef expression_node<T>* expression_ptr; 12731 | typedef vector_node<T>* vector_node_ptr; 12732 | typedef vec_data_store<T> vds_t; 12733 | 12734 | using binary_node<T>::branch; 12735 | 12736 | assignment_vecvec_node(const operator_type& opr, 12737 | expression_ptr branch0, 12738 | expression_ptr branch1) 12739 | : binary_node<T>(opr, branch0, branch1) 12740 | , vec0_node_ptr_(0) 12741 | , vec1_node_ptr_(0) 12742 | , initialised_(false) 12743 | , src_is_ivec_(false) 12744 | { 12745 | if (is_vector_node(branch(0))) 12746 | { 12747 | vec0_node_ptr_ = static_cast<vector_node<T>*>(branch(0)); 12748 | vds() = vec0_node_ptr_->vds(); 12749 | } 12750 | 12751 | if (is_vector_node(branch(1))) 12752 | { 12753 | vec1_node_ptr_ = static_cast<vector_node<T>*>(branch(1)); 12754 | vds_t::match_sizes(vds(),vec1_node_ptr_->vds()); 12755 | } 12756 | else if (is_ivector_node(branch(1))) 12757 | { 12758 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 12759 | 12760 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1)))) 12761 | { 12762 | vec1_node_ptr_ = vi->vec(); 12763 | 12764 | if (!vi->side_effect()) 12765 | { 12766 | vi->vds() = vds(); 12767 | src_is_ivec_ = true; 12768 | } 12769 | else 12770 | vds_t::match_sizes(vds(),vi->vds()); 12771 | } 12772 | } 12773 | 12774 | initialised_ = 12775 | vec0_node_ptr_ && 12776 | vec1_node_ptr_ && 12777 | (size() <= base_size()) && 12778 | (vds_.size() <= base_size()) && 12779 | binary_node<T>::valid(); 12780 | 12781 | assert(valid()); 12782 | } 12783 | 12784 | inline T value() const exprtk_override 12785 | { 12786 | branch(1)->value(); 12787 | 12788 | if (src_is_ivec_) 12789 | return vec0_node_ptr_->value(); 12790 | 12791 | T* vec0 = vec0_node_ptr_->vds().data(); 12792 | T* vec1 = vec1_node_ptr_->vds().data(); 12793 | 12794 | loop_unroll::details lud(size()); 12795 | const T* upper_bound = vec0 + lud.upper_bound; 12796 | 12797 | while (vec0 < upper_bound) 12798 | { 12799 | #define exprtk_loop(N) \ 12800 | vec0[N] = vec1[N]; \ 12801 | 12802 | exprtk_loop( 0) exprtk_loop( 1) 12803 | exprtk_loop( 2) exprtk_loop( 3) 12804 | #ifndef exprtk_disable_superscalar_unroll 12805 | exprtk_loop( 4) exprtk_loop( 5) 12806 | exprtk_loop( 6) exprtk_loop( 7) 12807 | exprtk_loop( 8) exprtk_loop( 9) 12808 | exprtk_loop(10) exprtk_loop(11) 12809 | exprtk_loop(12) exprtk_loop(13) 12810 | exprtk_loop(14) exprtk_loop(15) 12811 | #endif 12812 | 12813 | vec0 += lud.batch_size; 12814 | vec1 += lud.batch_size; 12815 | } 12816 | 12817 | switch (lud.remainder) 12818 | { 12819 | #define case_stmt(N,fall_through) \ 12820 | case N : *vec0++ = *vec1++; \ 12821 | fall_through \ 12822 | 12823 | #ifndef exprtk_disable_superscalar_unroll 12824 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 12825 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 12826 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 12827 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 12828 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 12829 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 12830 | #endif 12831 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 12832 | case_stmt( 1, (void)0;) 12833 | } 12834 | 12835 | #undef exprtk_loop 12836 | #undef case_stmt 12837 | 12838 | return vec0_node_ptr_->value(); 12839 | } 12840 | 12841 | vector_node_ptr vec() exprtk_override 12842 | { 12843 | return vec0_node_ptr_; 12844 | } 12845 | 12846 | vector_node_ptr vec() const exprtk_override 12847 | { 12848 | return vec0_node_ptr_; 12849 | } 12850 | 12851 | inline typename expression_node<T>::node_type type() const exprtk_override 12852 | { 12853 | return expression_node<T>::e_vecvecass; 12854 | } 12855 | 12856 | inline bool valid() const exprtk_override 12857 | { 12858 | return initialised_; 12859 | } 12860 | 12861 | std::size_t size() const exprtk_override 12862 | { 12863 | return std::min( 12864 | vec0_node_ptr_->vec_holder().size(), 12865 | vec1_node_ptr_->vec_holder().size()); 12866 | } 12867 | 12868 | std::size_t base_size() const exprtk_override 12869 | { 12870 | return std::min( 12871 | vec0_node_ptr_->vec_holder().base_size(), 12872 | vec1_node_ptr_->vec_holder().base_size()); 12873 | } 12874 | 12875 | vds_t& vds() exprtk_override 12876 | { 12877 | return vds_; 12878 | } 12879 | 12880 | const vds_t& vds() const exprtk_override 12881 | { 12882 | return vds_; 12883 | } 12884 | 12885 | private: 12886 | 12887 | vector_node<T>* vec0_node_ptr_; 12888 | vector_node<T>* vec1_node_ptr_; 12889 | bool initialised_; 12890 | bool src_is_ivec_; 12891 | vds_t vds_; 12892 | }; 12893 | 12894 | template <typename T, typename Operation> 12895 | class assignment_op_node exprtk_final : public binary_node<T> 12896 | { 12897 | public: 12898 | 12899 | typedef expression_node<T>* expression_ptr; 12900 | using binary_node<T>::branch; 12901 | 12902 | assignment_op_node(const operator_type& opr, 12903 | expression_ptr branch0, 12904 | expression_ptr branch1) 12905 | : binary_node<T>(opr, branch0, branch1) 12906 | , var_node_ptr_(0) 12907 | { 12908 | if (is_variable_node(branch(0))) 12909 | { 12910 | var_node_ptr_ = static_cast<variable_node<T>*>(branch(0)); 12911 | } 12912 | 12913 | assert(valid()); 12914 | } 12915 | 12916 | inline T value() const exprtk_override 12917 | { 12918 | T& v = var_node_ptr_->ref(); 12919 | v = Operation::process(v,branch(1)->value()); 12920 | 12921 | return v; 12922 | } 12923 | 12924 | inline bool valid() const exprtk_override 12925 | { 12926 | return var_node_ptr_ && binary_node<T>::valid(); 12927 | } 12928 | 12929 | private: 12930 | 12931 | variable_node<T>* var_node_ptr_; 12932 | }; 12933 | 12934 | template <typename T, typename Operation> 12935 | class assignment_vec_elem_op_node exprtk_final : public binary_node<T> 12936 | { 12937 | public: 12938 | 12939 | typedef expression_node<T>* expression_ptr; 12940 | using binary_node<T>::branch; 12941 | 12942 | assignment_vec_elem_op_node(const operator_type& opr, 12943 | expression_ptr branch0, 12944 | expression_ptr branch1) 12945 | : binary_node<T>(opr, branch0, branch1) 12946 | , vec_node_ptr_(0) 12947 | { 12948 | if (is_vector_elem_node(branch(0))) 12949 | { 12950 | vec_node_ptr_ = static_cast<vector_elem_node<T>*>(branch(0)); 12951 | } 12952 | 12953 | assert(valid()); 12954 | } 12955 | 12956 | inline T value() const exprtk_override 12957 | { 12958 | T& v = vec_node_ptr_->ref(); 12959 | v = Operation::process(v,branch(1)->value()); 12960 | 12961 | return v; 12962 | } 12963 | 12964 | inline bool valid() const exprtk_override 12965 | { 12966 | return vec_node_ptr_ && binary_node<T>::valid(); 12967 | } 12968 | 12969 | private: 12970 | 12971 | vector_elem_node<T>* vec_node_ptr_; 12972 | }; 12973 | 12974 | template <typename T, typename Operation> 12975 | class assignment_vec_elem_op_rtc_node exprtk_final : public binary_node<T> 12976 | { 12977 | public: 12978 | 12979 | typedef expression_node<T>* expression_ptr; 12980 | using binary_node<T>::branch; 12981 | 12982 | assignment_vec_elem_op_rtc_node(const operator_type& opr, 12983 | expression_ptr branch0, 12984 | expression_ptr branch1) 12985 | : binary_node<T>(opr, branch0, branch1) 12986 | , vec_node_ptr_(0) 12987 | { 12988 | if (is_vector_elem_rtc_node(branch(0))) 12989 | { 12990 | vec_node_ptr_ = static_cast<vector_elem_rtc_node<T>*>(branch(0)); 12991 | } 12992 | 12993 | assert(valid()); 12994 | } 12995 | 12996 | inline T value() const exprtk_override 12997 | { 12998 | T& v = vec_node_ptr_->ref(); 12999 | v = Operation::process(v,branch(1)->value()); 13000 | 13001 | return v; 13002 | } 13003 | 13004 | inline bool valid() const exprtk_override 13005 | { 13006 | return vec_node_ptr_ && binary_node<T>::valid(); 13007 | } 13008 | 13009 | private: 13010 | 13011 | vector_elem_rtc_node<T>* vec_node_ptr_; 13012 | }; 13013 | 13014 | template <typename T, typename Operation> 13015 | class assignment_vec_celem_op_rtc_node exprtk_final : public binary_node<T> 13016 | { 13017 | public: 13018 | 13019 | typedef expression_node<T>* expression_ptr; 13020 | using binary_node<T>::branch; 13021 | 13022 | assignment_vec_celem_op_rtc_node(const operator_type& opr, 13023 | expression_ptr branch0, 13024 | expression_ptr branch1) 13025 | : binary_node<T>(opr, branch0, branch1) 13026 | , vec_node_ptr_(0) 13027 | { 13028 | if (is_vector_celem_rtc_node(branch(0))) 13029 | { 13030 | vec_node_ptr_ = static_cast<vector_celem_rtc_node<T>*>(branch(0)); 13031 | } 13032 | 13033 | assert(valid()); 13034 | } 13035 | 13036 | inline T value() const exprtk_override 13037 | { 13038 | T& v = vec_node_ptr_->ref(); 13039 | v = Operation::process(v,branch(1)->value()); 13040 | 13041 | return v; 13042 | } 13043 | 13044 | inline bool valid() const exprtk_override 13045 | { 13046 | return vec_node_ptr_ && binary_node<T>::valid(); 13047 | } 13048 | 13049 | private: 13050 | 13051 | vector_celem_rtc_node<T>* vec_node_ptr_; 13052 | }; 13053 | 13054 | template <typename T, typename Operation> 13055 | class assignment_rebasevec_elem_op_node exprtk_final : public binary_node<T> 13056 | { 13057 | public: 13058 | 13059 | typedef expression_node<T>* expression_ptr; 13060 | using binary_node<T>::branch; 13061 | 13062 | assignment_rebasevec_elem_op_node(const operator_type& opr, 13063 | expression_ptr branch0, 13064 | expression_ptr branch1) 13065 | : binary_node<T>(opr, branch0, branch1) 13066 | , rbvec_node_ptr_(0) 13067 | { 13068 | if (is_rebasevector_elem_node(branch(0))) 13069 | { 13070 | rbvec_node_ptr_ = static_cast<rebasevector_elem_node<T>*>(branch(0)); 13071 | } 13072 | 13073 | assert(valid()); 13074 | } 13075 | 13076 | inline T value() const exprtk_override 13077 | { 13078 | T& v = rbvec_node_ptr_->ref(); 13079 | v = Operation::process(v,branch(1)->value()); 13080 | 13081 | return v; 13082 | } 13083 | 13084 | inline bool valid() const exprtk_override 13085 | { 13086 | return rbvec_node_ptr_ && binary_node<T>::valid(); 13087 | } 13088 | 13089 | private: 13090 | 13091 | rebasevector_elem_node<T>* rbvec_node_ptr_; 13092 | }; 13093 | 13094 | template <typename T, typename Operation> 13095 | class assignment_rebasevec_celem_op_node exprtk_final : public binary_node<T> 13096 | { 13097 | public: 13098 | 13099 | typedef expression_node<T>* expression_ptr; 13100 | using binary_node<T>::branch; 13101 | 13102 | assignment_rebasevec_celem_op_node(const operator_type& opr, 13103 | expression_ptr branch0, 13104 | expression_ptr branch1) 13105 | : binary_node<T>(opr, branch0, branch1) 13106 | , rbvec_node_ptr_(0) 13107 | { 13108 | if (is_rebasevector_celem_node(branch(0))) 13109 | { 13110 | rbvec_node_ptr_ = static_cast<rebasevector_celem_node<T>*>(branch(0)); 13111 | } 13112 | 13113 | assert(valid()); 13114 | } 13115 | 13116 | inline T value() const exprtk_override 13117 | { 13118 | T& v = rbvec_node_ptr_->ref(); 13119 | v = Operation::process(v,branch(1)->value()); 13120 | 13121 | return v; 13122 | } 13123 | 13124 | inline bool valid() const exprtk_override 13125 | { 13126 | return rbvec_node_ptr_ && binary_node<T>::valid(); 13127 | } 13128 | 13129 | private: 13130 | 13131 | rebasevector_celem_node<T>* rbvec_node_ptr_; 13132 | }; 13133 | 13134 | template <typename T, typename Operation> 13135 | class assignment_rebasevec_elem_op_rtc_node exprtk_final : public binary_node<T> 13136 | { 13137 | public: 13138 | 13139 | typedef expression_node<T>* expression_ptr; 13140 | using binary_node<T>::branch; 13141 | 13142 | assignment_rebasevec_elem_op_rtc_node(const operator_type& opr, 13143 | expression_ptr branch0, 13144 | expression_ptr branch1) 13145 | : binary_node<T>(opr, branch0, branch1) 13146 | , rbvec_node_ptr_(0) 13147 | { 13148 | if (is_rebasevector_elem_rtc_node(branch(0))) 13149 | { 13150 | rbvec_node_ptr_ = static_cast<rebasevector_elem_rtc_node<T>*>(branch(0)); 13151 | } 13152 | 13153 | assert(valid()); 13154 | } 13155 | 13156 | inline T value() const exprtk_override 13157 | { 13158 | T& v = rbvec_node_ptr_->ref(); 13159 | v = Operation::process(v,branch(1)->value()); 13160 | 13161 | return v; 13162 | } 13163 | 13164 | inline bool valid() const exprtk_override 13165 | { 13166 | return rbvec_node_ptr_ && binary_node<T>::valid(); 13167 | } 13168 | 13169 | private: 13170 | 13171 | rebasevector_elem_rtc_node<T>* rbvec_node_ptr_; 13172 | }; 13173 | 13174 | template <typename T, typename Operation> 13175 | class assignment_rebasevec_celem_op_rtc_node exprtk_final : public binary_node<T> 13176 | { 13177 | public: 13178 | 13179 | typedef expression_node<T>* expression_ptr; 13180 | using binary_node<T>::branch; 13181 | 13182 | assignment_rebasevec_celem_op_rtc_node(const operator_type& opr, 13183 | expression_ptr branch0, 13184 | expression_ptr branch1) 13185 | : binary_node<T>(opr, branch0, branch1) 13186 | , rbvec_node_ptr_(0) 13187 | { 13188 | if (is_rebasevector_celem_rtc_node(branch(0))) 13189 | { 13190 | rbvec_node_ptr_ = static_cast<rebasevector_celem_rtc_node<T>*>(branch(0)); 13191 | } 13192 | 13193 | assert(valid()); 13194 | } 13195 | 13196 | inline T value() const exprtk_override 13197 | { 13198 | T& v = rbvec_node_ptr_->ref(); 13199 | v = Operation::process(v,branch(1)->value()); 13200 | 13201 | return v; 13202 | } 13203 | 13204 | inline bool valid() const exprtk_override 13205 | { 13206 | return rbvec_node_ptr_ && binary_node<T>::valid(); 13207 | } 13208 | 13209 | private: 13210 | 13211 | rebasevector_celem_rtc_node<T>* rbvec_node_ptr_; 13212 | }; 13213 | 13214 | template <typename T, typename Operation> 13215 | class assignment_vec_op_node exprtk_final 13216 | : public binary_node <T> 13217 | , public vector_interface<T> 13218 | { 13219 | public: 13220 | 13221 | typedef expression_node<T>* expression_ptr; 13222 | typedef vector_node<T>* vector_node_ptr; 13223 | typedef vec_data_store<T> vds_t; 13224 | 13225 | using binary_node<T>::branch; 13226 | 13227 | assignment_vec_op_node(const operator_type& opr, 13228 | expression_ptr branch0, 13229 | expression_ptr branch1) 13230 | : binary_node<T>(opr, branch0, branch1) 13231 | , vec_node_ptr_(0) 13232 | { 13233 | if (is_vector_node(branch(0))) 13234 | { 13235 | vec_node_ptr_ = static_cast<vector_node<T>*>(branch(0)); 13236 | vds() = vec_node_ptr_->vds(); 13237 | } 13238 | 13239 | assert(valid()); 13240 | } 13241 | 13242 | inline T value() const exprtk_override 13243 | { 13244 | const T v = branch(1)->value(); 13245 | 13246 | T* vec = vds().data(); 13247 | 13248 | loop_unroll::details lud(size()); 13249 | const T* upper_bound = vec + lud.upper_bound; 13250 | 13251 | while (vec < upper_bound) 13252 | { 13253 | #define exprtk_loop(N) \ 13254 | Operation::assign(vec[N],v); \ 13255 | 13256 | exprtk_loop( 0) exprtk_loop( 1) 13257 | exprtk_loop( 2) exprtk_loop( 3) 13258 | #ifndef exprtk_disable_superscalar_unroll 13259 | exprtk_loop( 4) exprtk_loop( 5) 13260 | exprtk_loop( 6) exprtk_loop( 7) 13261 | exprtk_loop( 8) exprtk_loop( 9) 13262 | exprtk_loop(10) exprtk_loop(11) 13263 | exprtk_loop(12) exprtk_loop(13) 13264 | exprtk_loop(14) exprtk_loop(15) 13265 | #endif 13266 | 13267 | vec += lud.batch_size; 13268 | } 13269 | 13270 | switch (lud.remainder) 13271 | { 13272 | #define case_stmt(N,fall_through) \ 13273 | case N : Operation::assign(*vec++,v); \ 13274 | fall_through \ 13275 | 13276 | #ifndef exprtk_disable_superscalar_unroll 13277 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 13278 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 13279 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 13280 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 13281 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 13282 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 13283 | #endif 13284 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 13285 | case_stmt( 1, (void)0;) 13286 | } 13287 | 13288 | #undef exprtk_loop 13289 | #undef case_stmt 13290 | 13291 | return vec_node_ptr_->value(); 13292 | } 13293 | 13294 | vector_node_ptr vec() const exprtk_override 13295 | { 13296 | return vec_node_ptr_; 13297 | } 13298 | 13299 | vector_node_ptr vec() exprtk_override 13300 | { 13301 | return vec_node_ptr_; 13302 | } 13303 | 13304 | inline typename expression_node<T>::node_type type() const exprtk_override 13305 | { 13306 | return expression_node<T>::e_vecopvalass; 13307 | } 13308 | 13309 | inline bool valid() const exprtk_override 13310 | { 13311 | return 13312 | vec_node_ptr_ && 13313 | (size() <= base_size()) && 13314 | binary_node<T>::valid() ; 13315 | } 13316 | 13317 | std::size_t size() const exprtk_override 13318 | { 13319 | return vec_node_ptr_->vec_holder().size(); 13320 | } 13321 | 13322 | std::size_t base_size() const exprtk_override 13323 | { 13324 | return vec_node_ptr_->vec_holder().base_size(); 13325 | } 13326 | 13327 | vds_t& vds() exprtk_override 13328 | { 13329 | return vds_; 13330 | } 13331 | 13332 | const vds_t& vds() const exprtk_override 13333 | { 13334 | return vds_; 13335 | } 13336 | 13337 | bool side_effect() const exprtk_override 13338 | { 13339 | return true; 13340 | } 13341 | 13342 | private: 13343 | 13344 | vector_node<T>* vec_node_ptr_; 13345 | vds_t vds_; 13346 | }; 13347 | 13348 | template <typename T, typename Operation> 13349 | class assignment_vecvec_op_node exprtk_final 13350 | : public binary_node <T> 13351 | , public vector_interface<T> 13352 | { 13353 | public: 13354 | 13355 | typedef expression_node<T>* expression_ptr; 13356 | typedef vector_node<T>* vector_node_ptr; 13357 | typedef vec_data_store<T> vds_t; 13358 | 13359 | using binary_node<T>::branch; 13360 | 13361 | assignment_vecvec_op_node(const operator_type& opr, 13362 | expression_ptr branch0, 13363 | expression_ptr branch1) 13364 | : binary_node<T>(opr, branch0, branch1) 13365 | , vec0_node_ptr_(0) 13366 | , vec1_node_ptr_(0) 13367 | , initialised_(false) 13368 | { 13369 | if (is_vector_node(branch(0))) 13370 | { 13371 | vec0_node_ptr_ = static_cast<vector_node<T>*>(branch(0)); 13372 | vds() = vec0_node_ptr_->vds(); 13373 | } 13374 | 13375 | if (is_vector_node(branch(1))) 13376 | { 13377 | vec1_node_ptr_ = static_cast<vector_node<T>*>(branch(1)); 13378 | vec1_node_ptr_->vds() = vds(); 13379 | } 13380 | else if (is_ivector_node(branch(1))) 13381 | { 13382 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 13383 | 13384 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1)))) 13385 | { 13386 | vec1_node_ptr_ = vi->vec(); 13387 | vec1_node_ptr_->vds() = vi->vds(); 13388 | } 13389 | else 13390 | vds_t::match_sizes(vds(),vec1_node_ptr_->vds()); 13391 | } 13392 | 13393 | initialised_ = 13394 | vec0_node_ptr_ && 13395 | vec1_node_ptr_ && 13396 | (size() <= base_size()) && 13397 | binary_node<T>::valid(); 13398 | 13399 | assert(valid()); 13400 | } 13401 | 13402 | inline T value() const exprtk_override 13403 | { 13404 | branch(0)->value(); 13405 | branch(1)->value(); 13406 | 13407 | T* vec0 = vec0_node_ptr_->vds().data(); 13408 | const T* vec1 = vec1_node_ptr_->vds().data(); 13409 | 13410 | loop_unroll::details lud(size()); 13411 | const T* upper_bound = vec0 + lud.upper_bound; 13412 | 13413 | while (vec0 < upper_bound) 13414 | { 13415 | #define exprtk_loop(N) \ 13416 | vec0[N] = Operation::process(vec0[N], vec1[N]); \ 13417 | 13418 | exprtk_loop( 0) exprtk_loop( 1) 13419 | exprtk_loop( 2) exprtk_loop( 3) 13420 | #ifndef exprtk_disable_superscalar_unroll 13421 | exprtk_loop( 4) exprtk_loop( 5) 13422 | exprtk_loop( 6) exprtk_loop( 7) 13423 | exprtk_loop( 8) exprtk_loop( 9) 13424 | exprtk_loop(10) exprtk_loop(11) 13425 | exprtk_loop(12) exprtk_loop(13) 13426 | exprtk_loop(14) exprtk_loop(15) 13427 | #endif 13428 | 13429 | vec0 += lud.batch_size; 13430 | vec1 += lud.batch_size; 13431 | } 13432 | 13433 | int i = 0; 13434 | 13435 | switch (lud.remainder) 13436 | { 13437 | #define case_stmt(N,fall_through) \ 13438 | case N : { vec0[i] = Operation::process(vec0[i], vec1[i]); ++i; } \ 13439 | fall_through \ 13440 | 13441 | #ifndef exprtk_disable_superscalar_unroll 13442 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 13443 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 13444 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 13445 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 13446 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 13447 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 13448 | #endif 13449 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 13450 | case_stmt( 1, (void)0;) 13451 | } 13452 | 13453 | #undef exprtk_loop 13454 | #undef case_stmt 13455 | 13456 | return vec0_node_ptr_->value(); 13457 | } 13458 | 13459 | vector_node_ptr vec() const exprtk_override 13460 | { 13461 | return vec0_node_ptr_; 13462 | } 13463 | 13464 | vector_node_ptr vec() exprtk_override 13465 | { 13466 | return vec0_node_ptr_; 13467 | } 13468 | 13469 | inline typename expression_node<T>::node_type type() const exprtk_override 13470 | { 13471 | return expression_node<T>::e_vecopvecass; 13472 | } 13473 | 13474 | inline bool valid() const exprtk_override 13475 | { 13476 | return initialised_; 13477 | } 13478 | 13479 | std::size_t size() const exprtk_override 13480 | { 13481 | return std::min( 13482 | vec0_node_ptr_->vec_holder().size(), 13483 | vec1_node_ptr_->vec_holder().size()); 13484 | } 13485 | 13486 | std::size_t base_size() const exprtk_override 13487 | { 13488 | return std::min( 13489 | vec0_node_ptr_->vec_holder().base_size(), 13490 | vec1_node_ptr_->vec_holder().base_size()); 13491 | } 13492 | 13493 | vds_t& vds() exprtk_override 13494 | { 13495 | return vds_; 13496 | } 13497 | 13498 | const vds_t& vds() const exprtk_override 13499 | { 13500 | return vds_; 13501 | } 13502 | 13503 | bool side_effect() const exprtk_override 13504 | { 13505 | return true; 13506 | } 13507 | 13508 | private: 13509 | 13510 | vector_node<T>* vec0_node_ptr_; 13511 | vector_node<T>* vec1_node_ptr_; 13512 | bool initialised_; 13513 | vds_t vds_; 13514 | }; 13515 | 13516 | template <typename T> 13517 | struct memory_context_t 13518 | { 13519 | typedef vector_node<T>* vector_node_ptr; 13520 | typedef vector_holder<T> vector_holder_t; 13521 | typedef vector_holder_t* vector_holder_ptr; 13522 | 13523 | memory_context_t() 13524 | : temp_(0) 13525 | , temp_vec_node_(0) 13526 | {} 13527 | 13528 | void clear() 13529 | { 13530 | delete temp_vec_node_; 13531 | delete temp_; 13532 | } 13533 | 13534 | vector_holder_ptr temp_; 13535 | vector_node_ptr temp_vec_node_; 13536 | }; 13537 | 13538 | template <typename T> 13539 | inline memory_context_t<T> make_memory_context(vector_holder<T>& vec_holder, 13540 | vec_data_store<T>& vds) 13541 | { 13542 | memory_context_t<T> result_ctxt; 13543 | 13544 | result_ctxt.temp_ = (vec_holder.rebaseable()) ? 13545 | new vector_holder<T>(vec_holder,vds) : 13546 | new vector_holder<T>(vds) ; 13547 | 13548 | result_ctxt.temp_vec_node_ = new vector_node<T>(vds,result_ctxt.temp_); 13549 | 13550 | return result_ctxt; 13551 | } 13552 | 13553 | template <typename T> 13554 | inline memory_context_t<T> make_memory_context(vector_holder<T>& vec_holder0, 13555 | vector_holder<T>& vec_holder1, 13556 | vec_data_store<T>& vds) 13557 | { 13558 | memory_context_t<T> result_ctxt; 13559 | 13560 | if (!vec_holder0.rebaseable() && !vec_holder1.rebaseable()) 13561 | result_ctxt.temp_ = new vector_holder<T>(vds); 13562 | else if (vec_holder0.rebaseable() && !vec_holder1.rebaseable()) 13563 | result_ctxt.temp_ = new vector_holder<T>(vec_holder0,vds); 13564 | else if (!vec_holder0.rebaseable() && vec_holder1.rebaseable()) 13565 | result_ctxt.temp_ = new vector_holder<T>(vec_holder1,vds); 13566 | else 13567 | { 13568 | result_ctxt.temp_ = (vec_holder0.base_size() >= vec_holder1.base_size()) ? 13569 | new vector_holder<T>(vec_holder0, vds) : 13570 | new vector_holder<T>(vec_holder1, vds) ; 13571 | } 13572 | 13573 | result_ctxt.temp_vec_node_ = new vector_node<T>(vds,result_ctxt.temp_); 13574 | 13575 | return result_ctxt; 13576 | } 13577 | 13578 | template <typename T, typename Operation> 13579 | class vec_binop_vecvec_node exprtk_final 13580 | : public binary_node <T> 13581 | , public vector_interface<T> 13582 | { 13583 | public: 13584 | 13585 | typedef expression_node<T>* expression_ptr; 13586 | typedef vector_node<T>* vector_node_ptr; 13587 | typedef vector_holder<T> vector_holder_t; 13588 | typedef vector_holder_t* vector_holder_ptr; 13589 | typedef vec_data_store<T> vds_t; 13590 | typedef memory_context_t<T> memory_context; 13591 | 13592 | using binary_node<T>::branch; 13593 | 13594 | vec_binop_vecvec_node(const operator_type& opr, 13595 | expression_ptr branch0, 13596 | expression_ptr branch1) 13597 | : binary_node<T>(opr, branch0, branch1) 13598 | , vec0_node_ptr_(0) 13599 | , vec1_node_ptr_(0) 13600 | , initialised_(false) 13601 | { 13602 | bool v0_is_ivec = false; 13603 | bool v1_is_ivec = false; 13604 | 13605 | if (is_vector_node(branch(0))) 13606 | { 13607 | vec0_node_ptr_ = static_cast<vector_node_ptr>(branch(0)); 13608 | } 13609 | else if (is_ivector_node(branch(0))) 13610 | { 13611 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 13612 | 13613 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(0)))) 13614 | { 13615 | vec0_node_ptr_ = vi->vec(); 13616 | v0_is_ivec = true; 13617 | } 13618 | } 13619 | 13620 | if (is_vector_node(branch(1))) 13621 | { 13622 | vec1_node_ptr_ = static_cast<vector_node_ptr>(branch(1)); 13623 | } 13624 | else if (is_ivector_node(branch(1))) 13625 | { 13626 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 13627 | 13628 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1)))) 13629 | { 13630 | vec1_node_ptr_ = vi->vec(); 13631 | v1_is_ivec = true; 13632 | } 13633 | } 13634 | 13635 | if (vec0_node_ptr_ && vec1_node_ptr_) 13636 | { 13637 | vector_holder<T>& vec0 = vec0_node_ptr_->vec_holder(); 13638 | vector_holder<T>& vec1 = vec1_node_ptr_->vec_holder(); 13639 | 13640 | if (v0_is_ivec && (vec0.base_size() <= vec1.base_size())) 13641 | { 13642 | vds_ = vds_t(vec0_node_ptr_->vds()); 13643 | } 13644 | else if (v1_is_ivec && (vec1.base_size() <= vec0.base_size())) 13645 | { 13646 | vds_ = vds_t(vec1_node_ptr_->vds()); 13647 | } 13648 | else 13649 | { 13650 | vds_ = vds_t(std::min(vec0.base_size(),vec1.base_size())); 13651 | } 13652 | 13653 | memory_context_ = make_memory_context(vec0, vec1, vds()); 13654 | 13655 | initialised_ = 13656 | (size() <= base_size()) && 13657 | binary_node<T>::valid(); 13658 | } 13659 | 13660 | assert(valid()); 13661 | } 13662 | 13663 | ~vec_binop_vecvec_node() 13664 | { 13665 | memory_context_.clear(); 13666 | } 13667 | 13668 | inline T value() const exprtk_override 13669 | { 13670 | branch(0)->value(); 13671 | branch(1)->value(); 13672 | 13673 | const T* vec0 = vec0_node_ptr_->vds().data(); 13674 | const T* vec1 = vec1_node_ptr_->vds().data(); 13675 | T* vec2 = vds().data(); 13676 | 13677 | loop_unroll::details lud(size()); 13678 | const T* upper_bound = vec2 + lud.upper_bound; 13679 | 13680 | while (vec2 < upper_bound) 13681 | { 13682 | #define exprtk_loop(N) \ 13683 | vec2[N] = Operation::process(vec0[N], vec1[N]); \ 13684 | 13685 | exprtk_loop( 0) exprtk_loop( 1) 13686 | exprtk_loop( 2) exprtk_loop( 3) 13687 | #ifndef exprtk_disable_superscalar_unroll 13688 | exprtk_loop( 4) exprtk_loop( 5) 13689 | exprtk_loop( 6) exprtk_loop( 7) 13690 | exprtk_loop( 8) exprtk_loop( 9) 13691 | exprtk_loop(10) exprtk_loop(11) 13692 | exprtk_loop(12) exprtk_loop(13) 13693 | exprtk_loop(14) exprtk_loop(15) 13694 | #endif 13695 | 13696 | vec0 += lud.batch_size; 13697 | vec1 += lud.batch_size; 13698 | vec2 += lud.batch_size; 13699 | } 13700 | 13701 | int i = 0; 13702 | 13703 | switch (lud.remainder) 13704 | { 13705 | #define case_stmt(N) \ 13706 | case N : { vec2[i] = Operation::process(vec0[i], vec1[i]); ++i; } \ 13707 | exprtk_fallthrough \ 13708 | 13709 | #ifndef exprtk_disable_superscalar_unroll 13710 | case_stmt(15) case_stmt(14) 13711 | case_stmt(13) case_stmt(12) 13712 | case_stmt(11) case_stmt(10) 13713 | case_stmt( 9) case_stmt( 8) 13714 | case_stmt( 7) case_stmt( 6) 13715 | case_stmt( 5) case_stmt( 4) 13716 | #endif 13717 | case_stmt( 3) case_stmt( 2) 13718 | case_stmt( 1) 13719 | default: break; 13720 | } 13721 | 13722 | #undef exprtk_loop 13723 | #undef case_stmt 13724 | 13725 | return (vds().data())[0]; 13726 | } 13727 | 13728 | vector_node_ptr vec() const exprtk_override 13729 | { 13730 | return memory_context_.temp_vec_node_; 13731 | } 13732 | 13733 | vector_node_ptr vec() exprtk_override 13734 | { 13735 | return memory_context_.temp_vec_node_; 13736 | } 13737 | 13738 | inline typename expression_node<T>::node_type type() const exprtk_override 13739 | { 13740 | return expression_node<T>::e_vecvecarith; 13741 | } 13742 | 13743 | inline bool valid() const exprtk_override 13744 | { 13745 | return initialised_; 13746 | } 13747 | 13748 | std::size_t size() const exprtk_override 13749 | { 13750 | return std::min( 13751 | vec0_node_ptr_->vec_holder().size(), 13752 | vec1_node_ptr_->vec_holder().size()); 13753 | } 13754 | 13755 | std::size_t base_size() const exprtk_override 13756 | { 13757 | return std::min( 13758 | vec0_node_ptr_->vec_holder().base_size(), 13759 | vec1_node_ptr_->vec_holder().base_size()); 13760 | } 13761 | 13762 | vds_t& vds() exprtk_override 13763 | { 13764 | return vds_; 13765 | } 13766 | 13767 | const vds_t& vds() const exprtk_override 13768 | { 13769 | return vds_; 13770 | } 13771 | 13772 | private: 13773 | 13774 | vector_node_ptr vec0_node_ptr_; 13775 | vector_node_ptr vec1_node_ptr_; 13776 | bool initialised_; 13777 | vds_t vds_; 13778 | memory_context memory_context_; 13779 | }; 13780 | 13781 | template <typename T, typename Operation> 13782 | class vec_binop_vecval_node exprtk_final 13783 | : public binary_node <T> 13784 | , public vector_interface<T> 13785 | { 13786 | public: 13787 | 13788 | typedef expression_node<T>* expression_ptr; 13789 | typedef vector_node<T>* vector_node_ptr; 13790 | typedef vector_holder<T> vector_holder_t; 13791 | typedef vector_holder_t* vector_holder_ptr; 13792 | typedef vec_data_store<T> vds_t; 13793 | typedef memory_context_t<T> memory_context; 13794 | 13795 | using binary_node<T>::branch; 13796 | 13797 | vec_binop_vecval_node(const operator_type& opr, 13798 | expression_ptr branch0, 13799 | expression_ptr branch1) 13800 | : binary_node<T>(opr, branch0, branch1) 13801 | , vec0_node_ptr_(0) 13802 | { 13803 | bool v0_is_ivec = false; 13804 | 13805 | if (is_vector_node(branch(0))) 13806 | { 13807 | vec0_node_ptr_ = static_cast<vector_node_ptr>(branch(0)); 13808 | } 13809 | else if (is_ivector_node(branch(0))) 13810 | { 13811 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 13812 | 13813 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(0)))) 13814 | { 13815 | vec0_node_ptr_ = vi->vec(); 13816 | v0_is_ivec = true; 13817 | } 13818 | } 13819 | 13820 | if (vec0_node_ptr_) 13821 | { 13822 | if (v0_is_ivec) 13823 | vds() = vec0_node_ptr_->vds(); 13824 | else 13825 | vds() = vds_t(vec0_node_ptr_->base_size()); 13826 | 13827 | memory_context_ = make_memory_context(vec0_node_ptr_->vec_holder(), vds()); 13828 | } 13829 | 13830 | assert(valid()); 13831 | } 13832 | 13833 | ~vec_binop_vecval_node() 13834 | { 13835 | memory_context_.clear(); 13836 | } 13837 | 13838 | inline T value() const exprtk_override 13839 | { 13840 | branch(0)->value(); 13841 | const T v = branch(1)->value(); 13842 | 13843 | const T* vec0 = vec0_node_ptr_->vds().data(); 13844 | T* vec1 = vds().data(); 13845 | 13846 | loop_unroll::details lud(size()); 13847 | const T* upper_bound = vec0 + lud.upper_bound; 13848 | 13849 | while (vec0 < upper_bound) 13850 | { 13851 | #define exprtk_loop(N) \ 13852 | vec1[N] = Operation::process(vec0[N], v); \ 13853 | 13854 | exprtk_loop( 0) exprtk_loop( 1) 13855 | exprtk_loop( 2) exprtk_loop( 3) 13856 | #ifndef exprtk_disable_superscalar_unroll 13857 | exprtk_loop( 4) exprtk_loop( 5) 13858 | exprtk_loop( 6) exprtk_loop( 7) 13859 | exprtk_loop( 8) exprtk_loop( 9) 13860 | exprtk_loop(10) exprtk_loop(11) 13861 | exprtk_loop(12) exprtk_loop(13) 13862 | exprtk_loop(14) exprtk_loop(15) 13863 | #endif 13864 | 13865 | vec0 += lud.batch_size; 13866 | vec1 += lud.batch_size; 13867 | } 13868 | 13869 | int i = 0; 13870 | 13871 | switch (lud.remainder) 13872 | { 13873 | #define case_stmt(N,fall_through) \ 13874 | case N : { vec1[i] = Operation::process(vec0[i], v); ++i; } \ 13875 | fall_through \ 13876 | 13877 | #ifndef exprtk_disable_superscalar_unroll 13878 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 13879 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 13880 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 13881 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 13882 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 13883 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 13884 | #endif 13885 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 13886 | case_stmt( 1, (void)0;) 13887 | } 13888 | 13889 | #undef exprtk_loop 13890 | #undef case_stmt 13891 | 13892 | return (vds().data())[0]; 13893 | } 13894 | 13895 | vector_node_ptr vec() const exprtk_override 13896 | { 13897 | return memory_context_.temp_vec_node_; 13898 | } 13899 | 13900 | vector_node_ptr vec() exprtk_override 13901 | { 13902 | return memory_context_.temp_vec_node_; 13903 | } 13904 | 13905 | inline typename expression_node<T>::node_type type() const exprtk_override 13906 | { 13907 | return expression_node<T>::e_vecvalarith; 13908 | } 13909 | 13910 | inline bool valid() const exprtk_override 13911 | { 13912 | return 13913 | vec0_node_ptr_ && 13914 | (size() <= base_size()) && 13915 | binary_node<T>::valid(); 13916 | } 13917 | 13918 | std::size_t size() const exprtk_override 13919 | { 13920 | return vec0_node_ptr_->size(); 13921 | } 13922 | 13923 | std::size_t base_size() const exprtk_override 13924 | { 13925 | return vec0_node_ptr_->vec_holder().base_size(); 13926 | } 13927 | 13928 | vds_t& vds() exprtk_override 13929 | { 13930 | return vds_; 13931 | } 13932 | 13933 | const vds_t& vds() const exprtk_override 13934 | { 13935 | return vds_; 13936 | } 13937 | 13938 | private: 13939 | 13940 | vector_node_ptr vec0_node_ptr_; 13941 | vds_t vds_; 13942 | memory_context memory_context_; 13943 | }; 13944 | 13945 | template <typename T, typename Operation> 13946 | class vec_binop_valvec_node exprtk_final 13947 | : public binary_node <T> 13948 | , public vector_interface<T> 13949 | { 13950 | public: 13951 | 13952 | typedef expression_node<T>* expression_ptr; 13953 | typedef vector_node<T>* vector_node_ptr; 13954 | typedef vector_holder<T> vector_holder_t; 13955 | typedef vector_holder_t* vector_holder_ptr; 13956 | typedef vec_data_store<T> vds_t; 13957 | typedef memory_context_t<T> memory_context; 13958 | 13959 | using binary_node<T>::branch; 13960 | 13961 | vec_binop_valvec_node(const operator_type& opr, 13962 | expression_ptr branch0, 13963 | expression_ptr branch1) 13964 | : binary_node<T>(opr, branch0, branch1) 13965 | , vec1_node_ptr_(0) 13966 | { 13967 | bool v1_is_ivec = false; 13968 | 13969 | if (is_vector_node(branch(1))) 13970 | { 13971 | vec1_node_ptr_ = static_cast<vector_node_ptr>(branch(1)); 13972 | } 13973 | else if (is_ivector_node(branch(1))) 13974 | { 13975 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 13976 | 13977 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1)))) 13978 | { 13979 | vec1_node_ptr_ = vi->vec(); 13980 | v1_is_ivec = true; 13981 | } 13982 | } 13983 | 13984 | if (vec1_node_ptr_) 13985 | { 13986 | if (v1_is_ivec) 13987 | vds() = vec1_node_ptr_->vds(); 13988 | else 13989 | vds() = vds_t(vec1_node_ptr_->base_size()); 13990 | 13991 | memory_context_ = make_memory_context(vec1_node_ptr_->vec_holder(), vds()); 13992 | } 13993 | 13994 | assert(valid()); 13995 | } 13996 | 13997 | ~vec_binop_valvec_node() 13998 | { 13999 | memory_context_.clear(); 14000 | } 14001 | 14002 | inline T value() const exprtk_override 14003 | { 14004 | const T v = branch(0)->value(); 14005 | branch(1)->value(); 14006 | 14007 | T* vec0 = vds().data(); 14008 | const T* vec1 = vec1_node_ptr_->vds().data(); 14009 | 14010 | loop_unroll::details lud(size()); 14011 | const T* upper_bound = vec0 + lud.upper_bound; 14012 | 14013 | while (vec0 < upper_bound) 14014 | { 14015 | #define exprtk_loop(N) \ 14016 | vec0[N] = Operation::process(v, vec1[N]); \ 14017 | 14018 | exprtk_loop( 0) exprtk_loop( 1) 14019 | exprtk_loop( 2) exprtk_loop( 3) 14020 | #ifndef exprtk_disable_superscalar_unroll 14021 | exprtk_loop( 4) exprtk_loop( 5) 14022 | exprtk_loop( 6) exprtk_loop( 7) 14023 | exprtk_loop( 8) exprtk_loop( 9) 14024 | exprtk_loop(10) exprtk_loop(11) 14025 | exprtk_loop(12) exprtk_loop(13) 14026 | exprtk_loop(14) exprtk_loop(15) 14027 | #endif 14028 | 14029 | vec0 += lud.batch_size; 14030 | vec1 += lud.batch_size; 14031 | } 14032 | 14033 | int i = 0; 14034 | 14035 | switch (lud.remainder) 14036 | { 14037 | #define case_stmt(N,fall_through) \ 14038 | case N : { vec0[i] = Operation::process(v, vec1[i]); ++i; } \ 14039 | fall_through \ 14040 | 14041 | #ifndef exprtk_disable_superscalar_unroll 14042 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 14043 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 14044 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 14045 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 14046 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 14047 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 14048 | #endif 14049 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 14050 | case_stmt( 1, (void)0;) 14051 | } 14052 | 14053 | #undef exprtk_loop 14054 | #undef case_stmt 14055 | 14056 | return (vds().data())[0]; 14057 | } 14058 | 14059 | vector_node_ptr vec() const exprtk_override 14060 | { 14061 | return memory_context_.temp_vec_node_; 14062 | } 14063 | 14064 | vector_node_ptr vec() exprtk_override 14065 | { 14066 | return memory_context_.temp_vec_node_; 14067 | } 14068 | 14069 | inline typename expression_node<T>::node_type type() const exprtk_override 14070 | { 14071 | return expression_node<T>::e_vecvalarith; 14072 | } 14073 | 14074 | inline bool valid() const exprtk_override 14075 | { 14076 | return 14077 | vec1_node_ptr_ && 14078 | (size() <= base_size()) && 14079 | (vds_.size() <= base_size()) && 14080 | binary_node<T>::valid(); 14081 | } 14082 | 14083 | std::size_t size() const exprtk_override 14084 | { 14085 | return vec1_node_ptr_->vec_holder().size(); 14086 | } 14087 | 14088 | std::size_t base_size() const exprtk_override 14089 | { 14090 | return vec1_node_ptr_->vec_holder().base_size(); 14091 | } 14092 | 14093 | vds_t& vds() exprtk_override 14094 | { 14095 | return vds_; 14096 | } 14097 | 14098 | const vds_t& vds() const exprtk_override 14099 | { 14100 | return vds_; 14101 | } 14102 | 14103 | private: 14104 | 14105 | vector_node_ptr vec1_node_ptr_; 14106 | vds_t vds_; 14107 | memory_context memory_context_; 14108 | }; 14109 | 14110 | template <typename T, typename Operation> 14111 | class unary_vector_node exprtk_final 14112 | : public unary_node <T> 14113 | , public vector_interface<T> 14114 | { 14115 | public: 14116 | 14117 | typedef expression_node<T>* expression_ptr; 14118 | typedef vector_node<T>* vector_node_ptr; 14119 | typedef vector_holder<T> vector_holder_t; 14120 | typedef vector_holder_t* vector_holder_ptr; 14121 | typedef vec_data_store<T> vds_t; 14122 | typedef memory_context_t<T> memory_context; 14123 | 14124 | using expression_node<T>::branch; 14125 | 14126 | unary_vector_node(const operator_type& opr, expression_ptr branch0) 14127 | : unary_node<T>(opr, branch0) 14128 | , vec0_node_ptr_(0) 14129 | { 14130 | bool vec0_is_ivec = false; 14131 | 14132 | if (is_vector_node(branch(0))) 14133 | { 14134 | vec0_node_ptr_ = static_cast<vector_node_ptr>(branch(0)); 14135 | } 14136 | else if (is_ivector_node(branch(0))) 14137 | { 14138 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 14139 | 14140 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(0)))) 14141 | { 14142 | vec0_node_ptr_ = vi->vec(); 14143 | vec0_is_ivec = true; 14144 | } 14145 | } 14146 | 14147 | if (vec0_node_ptr_) 14148 | { 14149 | if (vec0_is_ivec) 14150 | vds_ = vec0_node_ptr_->vds(); 14151 | else 14152 | vds_ = vds_t(vec0_node_ptr_->base_size()); 14153 | 14154 | memory_context_ = make_memory_context(vec0_node_ptr_->vec_holder(), vds()); 14155 | } 14156 | 14157 | assert(valid()); 14158 | } 14159 | 14160 | ~unary_vector_node() 14161 | { 14162 | memory_context_.clear(); 14163 | } 14164 | 14165 | inline T value() const exprtk_override 14166 | { 14167 | branch()->value(); 14168 | 14169 | const T* vec0 = vec0_node_ptr_->vds().data(); 14170 | T* vec1 = vds().data(); 14171 | 14172 | loop_unroll::details lud(size()); 14173 | const T* upper_bound = vec0 + lud.upper_bound; 14174 | 14175 | while (vec0 < upper_bound) 14176 | { 14177 | #define exprtk_loop(N) \ 14178 | vec1[N] = Operation::process(vec0[N]); \ 14179 | 14180 | exprtk_loop( 0) exprtk_loop( 1) 14181 | exprtk_loop( 2) exprtk_loop( 3) 14182 | #ifndef exprtk_disable_superscalar_unroll 14183 | exprtk_loop( 4) exprtk_loop( 5) 14184 | exprtk_loop( 6) exprtk_loop( 7) 14185 | exprtk_loop( 8) exprtk_loop( 9) 14186 | exprtk_loop(10) exprtk_loop(11) 14187 | exprtk_loop(12) exprtk_loop(13) 14188 | exprtk_loop(14) exprtk_loop(15) 14189 | #endif 14190 | 14191 | vec0 += lud.batch_size; 14192 | vec1 += lud.batch_size; 14193 | } 14194 | 14195 | int i = 0; 14196 | 14197 | switch (lud.remainder) 14198 | { 14199 | #define case_stmt(N) \ 14200 | case N : { vec1[i] = Operation::process(vec0[i]); ++i; } \ 14201 | exprtk_fallthrough \ 14202 | 14203 | #ifndef exprtk_disable_superscalar_unroll 14204 | case_stmt(15) case_stmt(14) 14205 | case_stmt(13) case_stmt(12) 14206 | case_stmt(11) case_stmt(10) 14207 | case_stmt( 9) case_stmt( 8) 14208 | case_stmt( 7) case_stmt( 6) 14209 | case_stmt( 5) case_stmt( 4) 14210 | #endif 14211 | case_stmt( 3) case_stmt( 2) 14212 | case_stmt( 1) 14213 | default: break; 14214 | } 14215 | 14216 | #undef exprtk_loop 14217 | #undef case_stmt 14218 | 14219 | return (vds().data())[0]; 14220 | } 14221 | 14222 | vector_node_ptr vec() const exprtk_override 14223 | { 14224 | return memory_context_.temp_vec_node_; 14225 | } 14226 | 14227 | vector_node_ptr vec() exprtk_override 14228 | { 14229 | return memory_context_.temp_vec_node_; 14230 | } 14231 | 14232 | inline typename expression_node<T>::node_type type() const exprtk_override 14233 | { 14234 | return expression_node<T>::e_vecunaryop; 14235 | } 14236 | 14237 | inline bool valid() const exprtk_override 14238 | { 14239 | return vec0_node_ptr_ && unary_node<T>::valid(); 14240 | } 14241 | 14242 | std::size_t size() const exprtk_override 14243 | { 14244 | return vec0_node_ptr_->vec_holder().size(); 14245 | } 14246 | 14247 | std::size_t base_size() const exprtk_override 14248 | { 14249 | return vec0_node_ptr_->vec_holder().base_size(); 14250 | } 14251 | 14252 | vds_t& vds() exprtk_override 14253 | { 14254 | return vds_; 14255 | } 14256 | 14257 | const vds_t& vds() const exprtk_override 14258 | { 14259 | return vds_; 14260 | } 14261 | 14262 | private: 14263 | 14264 | vector_node_ptr vec0_node_ptr_; 14265 | vds_t vds_; 14266 | memory_context memory_context_; 14267 | }; 14268 | 14269 | template <typename T> 14270 | class conditional_vector_node exprtk_final 14271 | : public expression_node <T> 14272 | , public vector_interface<T> 14273 | { 14274 | public: 14275 | 14276 | typedef expression_node <T>* expression_ptr; 14277 | typedef vector_interface<T>* vec_interface_ptr; 14278 | typedef vector_node <T>* vector_node_ptr; 14279 | typedef vector_holder <T> vector_holder_t; 14280 | typedef vector_holder_t* vector_holder_ptr; 14281 | typedef vec_data_store <T> vds_t; 14282 | typedef memory_context_t<T> memory_context; 14283 | typedef std::pair<expression_ptr,bool> branch_t; 14284 | 14285 | conditional_vector_node(expression_ptr condition, 14286 | expression_ptr consequent, 14287 | expression_ptr alternative) 14288 | : consequent_node_ptr_ (0) 14289 | , alternative_node_ptr_(0) 14290 | , temp_vec_node_ (0) 14291 | , temp_ (0) 14292 | , result_vec_size_ (0) 14293 | , initialised_ (false) 14294 | { 14295 | construct_branch_pair(condition_ , condition ); 14296 | construct_branch_pair(consequent_ , consequent ); 14297 | construct_branch_pair(alternative_, alternative); 14298 | 14299 | if (details::is_ivector_node(consequent_.first)) 14300 | { 14301 | vec_interface_ptr ivec_ptr = dynamic_cast<vec_interface_ptr>(consequent_.first); 14302 | 14303 | if (0 != ivec_ptr) 14304 | { 14305 | consequent_node_ptr_ = ivec_ptr->vec(); 14306 | } 14307 | } 14308 | 14309 | if (details::is_ivector_node(alternative_.first)) 14310 | { 14311 | vec_interface_ptr ivec_ptr = dynamic_cast<vec_interface_ptr>(alternative_.first); 14312 | 14313 | if (0 != ivec_ptr) 14314 | { 14315 | alternative_node_ptr_ = ivec_ptr->vec(); 14316 | } 14317 | } 14318 | 14319 | if (consequent_node_ptr_ && alternative_node_ptr_) 14320 | { 14321 | const std::size_t vec_size = 14322 | std::max(consequent_node_ptr_ ->vec_holder().base_size(), 14323 | alternative_node_ptr_->vec_holder().base_size()); 14324 | 14325 | vds_ = vds_t(vec_size); 14326 | memory_context_ = make_memory_context( 14327 | consequent_node_ptr_ ->vec_holder(), 14328 | alternative_node_ptr_->vec_holder(), 14329 | vds()); 14330 | 14331 | initialised_ = (vec_size > 0); 14332 | } 14333 | 14334 | assert(initialised_); 14335 | } 14336 | 14337 | ~conditional_vector_node() 14338 | { 14339 | memory_context_.clear(); 14340 | } 14341 | 14342 | inline T value() const exprtk_override 14343 | { 14344 | T result = T(0); 14345 | T* source_vector = 0; 14346 | T* result_vector = vds().data(); 14347 | 14348 | if (is_true(condition_)) 14349 | { 14350 | result = consequent_.first->value(); 14351 | source_vector = consequent_node_ptr_->vds().data(); 14352 | result_vec_size_ = consequent_node_ptr_->size(); 14353 | } 14354 | else 14355 | { 14356 | result = alternative_.first->value(); 14357 | source_vector = alternative_node_ptr_->vds().data(); 14358 | result_vec_size_ = alternative_node_ptr_->size(); 14359 | } 14360 | 14361 | for (std::size_t i = 0; i < result_vec_size_; ++i) 14362 | { 14363 | result_vector[i] = source_vector[i]; 14364 | } 14365 | 14366 | return result; 14367 | } 14368 | 14369 | vector_node_ptr vec() const exprtk_override 14370 | { 14371 | return memory_context_.temp_vec_node_; 14372 | } 14373 | 14374 | vector_node_ptr vec() exprtk_override 14375 | { 14376 | return memory_context_.temp_vec_node_; 14377 | } 14378 | 14379 | inline typename expression_node<T>::node_type type() const exprtk_override 14380 | { 14381 | return expression_node<T>::e_vecondition; 14382 | } 14383 | 14384 | inline bool valid() const exprtk_override 14385 | { 14386 | return 14387 | initialised_ && 14388 | condition_ .first && condition_ .first->valid() && 14389 | consequent_ .first && consequent_ .first->valid() && 14390 | alternative_.first && alternative_.first->valid() && 14391 | size() <= base_size(); 14392 | } 14393 | 14394 | std::size_t size() const exprtk_override 14395 | { 14396 | return result_vec_size_; 14397 | } 14398 | 14399 | std::size_t base_size() const exprtk_override 14400 | { 14401 | return std::min( 14402 | consequent_node_ptr_ ->vec_holder().base_size(), 14403 | alternative_node_ptr_->vec_holder().base_size()); 14404 | } 14405 | 14406 | vds_t& vds() exprtk_override 14407 | { 14408 | return vds_; 14409 | } 14410 | 14411 | const vds_t& vds() const exprtk_override 14412 | { 14413 | return vds_; 14414 | } 14415 | 14416 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 14417 | { 14418 | expression_node<T>::ndb_t::collect(condition_ , node_delete_list); 14419 | expression_node<T>::ndb_t::collect(consequent_ , node_delete_list); 14420 | expression_node<T>::ndb_t::collect(alternative_ , node_delete_list); 14421 | } 14422 | 14423 | std::size_t node_depth() const exprtk_override 14424 | { 14425 | return expression_node<T>::ndb_t::compute_node_depth 14426 | (condition_, consequent_, alternative_); 14427 | } 14428 | 14429 | private: 14430 | 14431 | branch_t condition_; 14432 | branch_t consequent_; 14433 | branch_t alternative_; 14434 | vector_node_ptr consequent_node_ptr_; 14435 | vector_node_ptr alternative_node_ptr_; 14436 | vector_node_ptr temp_vec_node_; 14437 | vector_holder_ptr temp_; 14438 | vds_t vds_; 14439 | mutable std::size_t result_vec_size_; 14440 | bool initialised_; 14441 | memory_context memory_context_; 14442 | }; 14443 | 14444 | template <typename T> 14445 | class scand_node exprtk_final : public binary_node<T> 14446 | { 14447 | public: 14448 | 14449 | typedef expression_node<T>* expression_ptr; 14450 | using binary_node<T>::branch; 14451 | 14452 | scand_node(const operator_type& opr, 14453 | expression_ptr branch0, 14454 | expression_ptr branch1) 14455 | : binary_node<T>(opr, branch0, branch1) 14456 | { 14457 | assert(binary_node<T>::valid()); 14458 | } 14459 | 14460 | inline T value() const exprtk_override 14461 | { 14462 | return ( 14463 | std::not_equal_to<T>() 14464 | (T(0),branch(0)->value()) && 14465 | std::not_equal_to<T>() 14466 | (T(0),branch(1)->value()) 14467 | ) ? T(1) : T(0); 14468 | } 14469 | }; 14470 | 14471 | template <typename T> 14472 | class scor_node exprtk_final : public binary_node<T> 14473 | { 14474 | public: 14475 | 14476 | typedef expression_node<T>* expression_ptr; 14477 | using binary_node<T>::branch; 14478 | 14479 | scor_node(const operator_type& opr, 14480 | expression_ptr branch0, 14481 | expression_ptr branch1) 14482 | : binary_node<T>(opr, branch0, branch1) 14483 | { 14484 | assert(binary_node<T>::valid()); 14485 | } 14486 | 14487 | inline T value() const exprtk_override 14488 | { 14489 | return ( 14490 | std::not_equal_to<T>() 14491 | (T(0),branch(0)->value()) || 14492 | std::not_equal_to<T>() 14493 | (T(0),branch(1)->value()) 14494 | ) ? T(1) : T(0); 14495 | } 14496 | }; 14497 | 14498 | template <typename T, typename IFunction, std::size_t N> 14499 | class function_N_node exprtk_final : public expression_node<T> 14500 | { 14501 | public: 14502 | 14503 | // Function of N parameters. 14504 | typedef expression_node<T>* expression_ptr; 14505 | typedef std::pair<expression_ptr,bool> branch_t; 14506 | typedef IFunction ifunction; 14507 | 14508 | explicit function_N_node(ifunction* func) 14509 | : function_((N == func->param_count) ? func : reinterpret_cast<ifunction*>(0)) 14510 | , parameter_count_(func->param_count) 14511 | , initialised_(false) 14512 | {} 14513 | 14514 | template <std::size_t NumBranches> 14515 | bool init_branches(expression_ptr (&b)[NumBranches]) 14516 | { 14517 | // Needed for incompetent and broken msvc compiler versions 14518 | #ifdef _MSC_VER 14519 | #pragma warning(push) 14520 | #pragma warning(disable: 4127) 14521 | #endif 14522 | 14523 | if (N != NumBranches) 14524 | { 14525 | return false; 14526 | } 14527 | 14528 | for (std::size_t i = 0; i < NumBranches; ++i) 14529 | { 14530 | if (b[i] && b[i]->valid()) 14531 | branch_[i] = std::make_pair(b[i],branch_deletable(b[i])); 14532 | else 14533 | return false; 14534 | } 14535 | 14536 | initialised_ = function_; 14537 | assert(valid()); 14538 | return initialised_; 14539 | 14540 | #ifdef _MSC_VER 14541 | #pragma warning(pop) 14542 | #endif 14543 | } 14544 | 14545 | inline bool operator <(const function_N_node<T,IFunction,N>& fn) const 14546 | { 14547 | return this < (&fn); 14548 | } 14549 | 14550 | inline T value() const exprtk_override 14551 | { 14552 | // Needed for incompetent and broken msvc compiler versions 14553 | #ifdef _MSC_VER 14554 | #pragma warning(push) 14555 | #pragma warning(disable: 4127) 14556 | #endif 14557 | 14558 | T v[N]; 14559 | evaluate_branches<T,N>::execute(v,branch_); 14560 | return invoke<T,N>::execute(*function_,v); 14561 | 14562 | #ifdef _MSC_VER 14563 | #pragma warning(pop) 14564 | #endif 14565 | } 14566 | 14567 | inline typename expression_node<T>::node_type type() const exprtk_override 14568 | { 14569 | return expression_node<T>::e_function; 14570 | } 14571 | 14572 | inline bool valid() const exprtk_override 14573 | { 14574 | return initialised_; 14575 | } 14576 | 14577 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 14578 | { 14579 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 14580 | } 14581 | 14582 | std::size_t node_depth() const exprtk_override 14583 | { 14584 | return expression_node<T>::ndb_t::template compute_node_depth<N>(branch_); 14585 | } 14586 | 14587 | template <typename T_, std::size_t BranchCount> 14588 | struct evaluate_branches 14589 | { 14590 | static inline void execute(T_ (&v)[BranchCount], const branch_t (&b)[BranchCount]) 14591 | { 14592 | for (std::size_t i = 0; i < BranchCount; ++i) 14593 | { 14594 | v[i] = b[i].first->value(); 14595 | } 14596 | } 14597 | }; 14598 | 14599 | template <typename T_> 14600 | struct evaluate_branches <T_,6> 14601 | { 14602 | static inline void execute(T_ (&v)[6], const branch_t (&b)[6]) 14603 | { 14604 | v[0] = b[0].first->value(); 14605 | v[1] = b[1].first->value(); 14606 | v[2] = b[2].first->value(); 14607 | v[3] = b[3].first->value(); 14608 | v[4] = b[4].first->value(); 14609 | v[5] = b[5].first->value(); 14610 | } 14611 | }; 14612 | 14613 | template <typename T_> 14614 | struct evaluate_branches <T_,5> 14615 | { 14616 | static inline void execute(T_ (&v)[5], const branch_t (&b)[5]) 14617 | { 14618 | v[0] = b[0].first->value(); 14619 | v[1] = b[1].first->value(); 14620 | v[2] = b[2].first->value(); 14621 | v[3] = b[3].first->value(); 14622 | v[4] = b[4].first->value(); 14623 | } 14624 | }; 14625 | 14626 | template <typename T_> 14627 | struct evaluate_branches <T_,4> 14628 | { 14629 | static inline void execute(T_ (&v)[4], const branch_t (&b)[4]) 14630 | { 14631 | v[0] = b[0].first->value(); 14632 | v[1] = b[1].first->value(); 14633 | v[2] = b[2].first->value(); 14634 | v[3] = b[3].first->value(); 14635 | } 14636 | }; 14637 | 14638 | template <typename T_> 14639 | struct evaluate_branches <T_,3> 14640 | { 14641 | static inline void execute(T_ (&v)[3], const branch_t (&b)[3]) 14642 | { 14643 | v[0] = b[0].first->value(); 14644 | v[1] = b[1].first->value(); 14645 | v[2] = b[2].first->value(); 14646 | } 14647 | }; 14648 | 14649 | template <typename T_> 14650 | struct evaluate_branches <T_,2> 14651 | { 14652 | static inline void execute(T_ (&v)[2], const branch_t (&b)[2]) 14653 | { 14654 | v[0] = b[0].first->value(); 14655 | v[1] = b[1].first->value(); 14656 | } 14657 | }; 14658 | 14659 | template <typename T_> 14660 | struct evaluate_branches <T_,1> 14661 | { 14662 | static inline void execute(T_ (&v)[1], const branch_t (&b)[1]) 14663 | { 14664 | v[0] = b[0].first->value(); 14665 | } 14666 | }; 14667 | 14668 | template <typename T_, std::size_t ParamCount> 14669 | struct invoke { static inline T execute(ifunction&, branch_t (&)[ParamCount]) { return std::numeric_limits<T_>::quiet_NaN(); } }; 14670 | 14671 | template <typename T_> 14672 | struct invoke<T_,20> 14673 | { 14674 | static inline T_ execute(ifunction& f, T_ (&v)[20]) 14675 | { 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]); } 14676 | }; 14677 | 14678 | template <typename T_> 14679 | struct invoke<T_,19> 14680 | { 14681 | static inline T_ execute(ifunction& f, T_ (&v)[19]) 14682 | { 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]); } 14683 | }; 14684 | 14685 | template <typename T_> 14686 | struct invoke<T_,18> 14687 | { 14688 | static inline T_ execute(ifunction& f, T_ (&v)[18]) 14689 | { 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]); } 14690 | }; 14691 | 14692 | template <typename T_> 14693 | struct invoke<T_,17> 14694 | { 14695 | static inline T_ execute(ifunction& f, T_ (&v)[17]) 14696 | { 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]); } 14697 | }; 14698 | 14699 | template <typename T_> 14700 | struct invoke<T_,16> 14701 | { 14702 | static inline T_ execute(ifunction& f, T_ (&v)[16]) 14703 | { 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]); } 14704 | }; 14705 | 14706 | template <typename T_> 14707 | struct invoke<T_,15> 14708 | { 14709 | static inline T_ execute(ifunction& f, T_ (&v)[15]) 14710 | { 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]); } 14711 | }; 14712 | 14713 | template <typename T_> 14714 | struct invoke<T_,14> 14715 | { 14716 | static inline T_ execute(ifunction& f, T_ (&v)[14]) 14717 | { 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]); } 14718 | }; 14719 | 14720 | template <typename T_> 14721 | struct invoke<T_,13> 14722 | { 14723 | static inline T_ execute(ifunction& f, T_ (&v)[13]) 14724 | { 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]); } 14725 | }; 14726 | 14727 | template <typename T_> 14728 | struct invoke<T_,12> 14729 | { 14730 | static inline T_ execute(ifunction& f, T_ (&v)[12]) 14731 | { 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]); } 14732 | }; 14733 | 14734 | template <typename T_> 14735 | struct invoke<T_,11> 14736 | { 14737 | static inline T_ execute(ifunction& f, T_ (&v)[11]) 14738 | { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9], v[10]); } 14739 | }; 14740 | 14741 | template <typename T_> 14742 | struct invoke<T_,10> 14743 | { 14744 | static inline T_ execute(ifunction& f, T_ (&v)[10]) 14745 | { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9]); } 14746 | }; 14747 | 14748 | template <typename T_> 14749 | struct invoke<T_,9> 14750 | { 14751 | static inline T_ execute(ifunction& f, T_ (&v)[9]) 14752 | { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8]); } 14753 | }; 14754 | 14755 | template <typename T_> 14756 | struct invoke<T_,8> 14757 | { 14758 | static inline T_ execute(ifunction& f, T_ (&v)[8]) 14759 | { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]); } 14760 | }; 14761 | 14762 | template <typename T_> 14763 | struct invoke<T_,7> 14764 | { 14765 | static inline T_ execute(ifunction& f, T_ (&v)[7]) 14766 | { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6]); } 14767 | }; 14768 | 14769 | template <typename T_> 14770 | struct invoke<T_,6> 14771 | { 14772 | static inline T_ execute(ifunction& f, T_ (&v)[6]) 14773 | { return f(v[0], v[1], v[2], v[3], v[4], v[5]); } 14774 | }; 14775 | 14776 | template <typename T_> 14777 | struct invoke<T_,5> 14778 | { 14779 | static inline T_ execute(ifunction& f, T_ (&v)[5]) 14780 | { return f(v[0], v[1], v[2], v[3], v[4]); } 14781 | }; 14782 | 14783 | template <typename T_> 14784 | struct invoke<T_,4> 14785 | { 14786 | static inline T_ execute(ifunction& f, T_ (&v)[4]) 14787 | { return f(v[0], v[1], v[2], v[3]); } 14788 | }; 14789 | 14790 | template <typename T_> 14791 | struct invoke<T_,3> 14792 | { 14793 | static inline T_ execute(ifunction& f, T_ (&v)[3]) 14794 | { return f(v[0], v[1], v[2]); } 14795 | }; 14796 | 14797 | template <typename T_> 14798 | struct invoke<T_,2> 14799 | { 14800 | static inline T_ execute(ifunction& f, T_ (&v)[2]) 14801 | { return f(v[0], v[1]); } 14802 | }; 14803 | 14804 | template <typename T_> 14805 | struct invoke<T_,1> 14806 | { 14807 | static inline T_ execute(ifunction& f, T_ (&v)[1]) 14808 | { return f(v[0]); } 14809 | }; 14810 | 14811 | private: 14812 | 14813 | ifunction* function_; 14814 | std::size_t parameter_count_; 14815 | branch_t branch_[N]; 14816 | bool initialised_; 14817 | }; 14818 | 14819 | template <typename T, typename IFunction> 14820 | class function_N_node<T,IFunction,0> exprtk_final : public expression_node<T> 14821 | { 14822 | public: 14823 | 14824 | typedef expression_node<T>* expression_ptr; 14825 | typedef IFunction ifunction; 14826 | 14827 | explicit function_N_node(ifunction* func) 14828 | : function_((0 == func->param_count) ? func : reinterpret_cast<ifunction*>(0)) 14829 | { 14830 | assert(valid()); 14831 | } 14832 | 14833 | inline bool operator <(const function_N_node<T,IFunction,0>& fn) const 14834 | { 14835 | return this < (&fn); 14836 | } 14837 | 14838 | inline T value() const exprtk_override 14839 | { 14840 | return (*function_)(); 14841 | } 14842 | 14843 | inline typename expression_node<T>::node_type type() const exprtk_override 14844 | { 14845 | return expression_node<T>::e_function; 14846 | } 14847 | 14848 | inline bool valid() const exprtk_override 14849 | { 14850 | return function_; 14851 | } 14852 | 14853 | private: 14854 | 14855 | ifunction* function_; 14856 | }; 14857 | 14858 | template <typename T, typename VarArgFunction> 14859 | class vararg_function_node exprtk_final : public expression_node<T> 14860 | { 14861 | public: 14862 | 14863 | typedef expression_node<T>* expression_ptr; 14864 | 14865 | vararg_function_node(VarArgFunction* func, 14866 | const std::vector<expression_ptr>& arg_list) 14867 | : function_(func) 14868 | , arg_list_(arg_list) 14869 | { 14870 | value_list_.resize(arg_list.size(),std::numeric_limits<T>::quiet_NaN()); 14871 | assert(valid()); 14872 | } 14873 | 14874 | inline bool operator <(const vararg_function_node<T,VarArgFunction>& fn) const 14875 | { 14876 | return this < (&fn); 14877 | } 14878 | 14879 | inline T value() const exprtk_override 14880 | { 14881 | populate_value_list(); 14882 | return (*function_)(value_list_); 14883 | } 14884 | 14885 | inline typename expression_node<T>::node_type type() const exprtk_override 14886 | { 14887 | return expression_node<T>::e_vafunction; 14888 | } 14889 | 14890 | inline bool valid() const exprtk_override 14891 | { 14892 | return function_; 14893 | } 14894 | 14895 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 14896 | { 14897 | for (std::size_t i = 0; i < arg_list_.size(); ++i) 14898 | { 14899 | if (arg_list_[i] && !details::is_variable_node(arg_list_[i])) 14900 | { 14901 | node_delete_list.push_back(&arg_list_[i]); 14902 | } 14903 | } 14904 | } 14905 | 14906 | std::size_t node_depth() const exprtk_override 14907 | { 14908 | return expression_node<T>::ndb_t::compute_node_depth(arg_list_); 14909 | } 14910 | 14911 | private: 14912 | 14913 | inline void populate_value_list() const 14914 | { 14915 | for (std::size_t i = 0; i < arg_list_.size(); ++i) 14916 | { 14917 | value_list_[i] = arg_list_[i]->value(); 14918 | } 14919 | } 14920 | 14921 | VarArgFunction* function_; 14922 | std::vector<expression_ptr> arg_list_; 14923 | mutable std::vector<T> value_list_; 14924 | }; 14925 | 14926 | template <typename T, typename GenericFunction> 14927 | class generic_function_node : public expression_node<T> 14928 | { 14929 | public: 14930 | 14931 | typedef type_store<T> type_store_t; 14932 | typedef expression_node<T>* expression_ptr; 14933 | typedef variable_node<T> variable_node_t; 14934 | typedef vector_node<T> vector_node_t; 14935 | typedef variable_node_t* variable_node_ptr_t; 14936 | typedef vector_node_t* vector_node_ptr_t; 14937 | typedef range_interface<T> range_interface_t; 14938 | typedef range_data_type<T> range_data_type_t; 14939 | typedef typename range_interface<T>::range_t range_t; 14940 | 14941 | typedef std::pair<expression_ptr,bool> branch_t; 14942 | typedef vector_holder<T>* vh_t; 14943 | typedef vector_view<T>* vecview_t; 14944 | 14945 | typedef std::vector<T> tmp_vs_t; 14946 | typedef std::vector<type_store_t> typestore_list_t; 14947 | typedef std::vector<range_data_type_t> range_list_t; 14948 | 14949 | explicit generic_function_node(const std::vector<expression_ptr>& arg_list, 14950 | GenericFunction* func = reinterpret_cast<GenericFunction*>(0)) 14951 | : function_(func) 14952 | , arg_list_(arg_list) 14953 | {} 14954 | 14955 | virtual ~generic_function_node() 14956 | { 14957 | for (std::size_t i = 0; i < vv_list_.size(); ++i) 14958 | { 14959 | vecview_t& vv = vv_list_[i]; 14960 | if (vv && typestore_list_[i].vec_data) 14961 | { 14962 | vv->remove_ref(&typestore_list_[i].vec_data); 14963 | typestore_list_[i].vec_data = 0; 14964 | } 14965 | } 14966 | } 14967 | 14968 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 14969 | { 14970 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 14971 | } 14972 | 14973 | std::size_t node_depth() const exprtk_override exprtk_final 14974 | { 14975 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 14976 | } 14977 | 14978 | virtual bool init_branches() 14979 | { 14980 | expr_as_vec1_store_.resize(arg_list_.size(), T(0) ); 14981 | typestore_list_ .resize(arg_list_.size(), type_store_t() ); 14982 | range_list_ .resize(arg_list_.size(), range_data_type_t()); 14983 | branch_ .resize(arg_list_.size(), branch_t(reinterpret_cast<expression_ptr>(0),false)); 14984 | vv_list_ .resize(arg_list_.size(), vecview_t(0)); 14985 | 14986 | for (std::size_t i = 0; i < arg_list_.size(); ++i) 14987 | { 14988 | type_store_t& ts = typestore_list_[i]; 14989 | 14990 | if (0 == arg_list_[i]) 14991 | return false; 14992 | else if (is_ivector_node(arg_list_[i])) 14993 | { 14994 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 14995 | 14996 | if (0 == (vi = dynamic_cast<vector_interface<T>*>(arg_list_[i]))) 14997 | return false; 14998 | 14999 | ts.size = vi->size(); 15000 | ts.data = vi->vds().data(); 15001 | ts.type = type_store_t::e_vector; 15002 | 15003 | if ( 15004 | vi->vec()->vec_holder().rebaseable() && 15005 | vi->vec()->vec_holder().rebaseable_instance() 15006 | ) 15007 | { 15008 | vv_list_[i] = vi->vec()->vec_holder().rebaseable_instance(); 15009 | vv_list_[i]->set_ref(&ts.vec_data); 15010 | } 15011 | } 15012 | #ifndef exprtk_disable_string_capabilities 15013 | else if (is_generally_string_node(arg_list_[i])) 15014 | { 15015 | string_base_node<T>* sbn = reinterpret_cast<string_base_node<T>*>(0); 15016 | 15017 | if (0 == (sbn = dynamic_cast<string_base_node<T>*>(arg_list_[i]))) 15018 | return false; 15019 | 15020 | ts.size = sbn->size(); 15021 | ts.data = reinterpret_cast<void*>(const_cast<char_ptr>(sbn->base())); 15022 | ts.type = type_store_t::e_string; 15023 | 15024 | range_list_[i].data = ts.data; 15025 | range_list_[i].size = ts.size; 15026 | range_list_[i].type_size = sizeof(char); 15027 | range_list_[i].str_node = sbn; 15028 | 15029 | range_interface_t* ri = reinterpret_cast<range_interface_t*>(0); 15030 | 15031 | if (0 == (ri = dynamic_cast<range_interface_t*>(arg_list_[i]))) 15032 | return false; 15033 | 15034 | const range_t& rp = ri->range_ref(); 15035 | 15036 | if ( 15037 | rp.const_range() && 15038 | is_const_string_range_node(arg_list_[i]) 15039 | ) 15040 | { 15041 | ts.size = rp.const_size(); 15042 | ts.data = static_cast<char_ptr>(ts.data) + rp.n0_c.second; 15043 | range_list_[i].range = reinterpret_cast<range_t*>(0); 15044 | } 15045 | else 15046 | { 15047 | range_list_[i].range = &(ri->range_ref()); 15048 | range_param_list_.push_back(i); 15049 | } 15050 | } 15051 | #endif 15052 | else if (is_variable_node(arg_list_[i])) 15053 | { 15054 | variable_node_ptr_t var = variable_node_ptr_t(0); 15055 | 15056 | if (0 == (var = dynamic_cast<variable_node_ptr_t>(arg_list_[i]))) 15057 | return false; 15058 | 15059 | ts.size = 1; 15060 | ts.data = &var->ref(); 15061 | ts.type = type_store_t::e_scalar; 15062 | } 15063 | else 15064 | { 15065 | ts.size = 1; 15066 | ts.data = reinterpret_cast<void*>(&expr_as_vec1_store_[i]); 15067 | ts.type = type_store_t::e_scalar; 15068 | } 15069 | 15070 | branch_[i] = std::make_pair(arg_list_[i],branch_deletable(arg_list_[i])); 15071 | } 15072 | 15073 | return true; 15074 | } 15075 | 15076 | inline bool operator <(const generic_function_node<T,GenericFunction>& fn) const 15077 | { 15078 | return this < (&fn); 15079 | } 15080 | 15081 | inline T value() const exprtk_override 15082 | { 15083 | if (populate_value_list()) 15084 | { 15085 | typedef typename GenericFunction::parameter_list_t parameter_list_t; 15086 | 15087 | return (*function_)(parameter_list_t(typestore_list_)); 15088 | } 15089 | 15090 | return std::numeric_limits<T>::quiet_NaN(); 15091 | } 15092 | 15093 | inline typename expression_node<T>::node_type type() const exprtk_override 15094 | { 15095 | return expression_node<T>::e_genfunction; 15096 | } 15097 | 15098 | inline bool valid() const exprtk_override 15099 | { 15100 | return function_; 15101 | } 15102 | 15103 | protected: 15104 | 15105 | inline virtual bool populate_value_list() const 15106 | { 15107 | for (std::size_t i = 0; i < branch_.size(); ++i) 15108 | { 15109 | expr_as_vec1_store_[i] = branch_[i].first->value(); 15110 | } 15111 | 15112 | if (!range_param_list_.empty()) 15113 | { 15114 | assert(range_param_list_.size() <= branch_.size()); 15115 | 15116 | for (std::size_t i = 0; i < range_param_list_.size(); ++i) 15117 | { 15118 | const std::size_t index = range_param_list_[i]; 15119 | range_data_type_t& rdt = range_list_[index]; 15120 | 15121 | const range_t& rp = (*rdt.range); 15122 | std::size_t r0 = 0; 15123 | std::size_t r1 = 0; 15124 | 15125 | const std::size_t data_size = 15126 | #ifndef exprtk_disable_string_capabilities 15127 | rdt.str_node ? rdt.str_node->size() : rdt.size; 15128 | #else 15129 | rdt.size; 15130 | #endif 15131 | 15132 | if (!rp(r0, r1, data_size)) 15133 | { 15134 | return false; 15135 | } 15136 | 15137 | type_store_t& ts = typestore_list_[index]; 15138 | 15139 | ts.size = rp.cache_size(); 15140 | #ifndef exprtk_disable_string_capabilities 15141 | if (ts.type == type_store_t::e_string) 15142 | ts.data = const_cast<char_ptr>(rdt.str_node->base()) + rp.cache.first; 15143 | else 15144 | #endif 15145 | ts.data = static_cast<char_ptr>(rdt.data) + (rp.cache.first * rdt.type_size); 15146 | } 15147 | } 15148 | 15149 | return true; 15150 | } 15151 | 15152 | GenericFunction* function_; 15153 | mutable typestore_list_t typestore_list_; 15154 | 15155 | private: 15156 | 15157 | std::vector<expression_ptr> arg_list_; 15158 | std::vector<branch_t> branch_; 15159 | std::vector<vecview_t> vv_list_; 15160 | mutable tmp_vs_t expr_as_vec1_store_; 15161 | mutable range_list_t range_list_; 15162 | std::vector<std::size_t> range_param_list_; 15163 | }; 15164 | 15165 | #ifndef exprtk_disable_string_capabilities 15166 | template <typename T, typename StringFunction> 15167 | class string_function_node : public generic_function_node<T,StringFunction> 15168 | , public string_base_node<T> 15169 | , public range_interface <T> 15170 | { 15171 | public: 15172 | 15173 | typedef generic_function_node<T,StringFunction> gen_function_t; 15174 | typedef typename range_interface<T>::range_t range_t; 15175 | 15176 | string_function_node(StringFunction* func, 15177 | const std::vector<typename gen_function_t::expression_ptr>& arg_list) 15178 | : gen_function_t(arg_list,func) 15179 | { 15180 | range_.n0_c = std::make_pair<bool,std::size_t>(true,0); 15181 | range_.n1_c = std::make_pair<bool,std::size_t>(true,0); 15182 | range_.cache.first = range_.n0_c.second; 15183 | range_.cache.second = range_.n1_c.second; 15184 | assert(valid()); 15185 | } 15186 | 15187 | inline bool operator <(const string_function_node<T,StringFunction>& fn) const 15188 | { 15189 | return this < (&fn); 15190 | } 15191 | 15192 | inline T value() const exprtk_override 15193 | { 15194 | if (gen_function_t::populate_value_list()) 15195 | { 15196 | typedef typename StringFunction::parameter_list_t parameter_list_t; 15197 | 15198 | const T result = 15199 | (*gen_function_t::function_) 15200 | ( 15201 | ret_string_, 15202 | parameter_list_t(gen_function_t::typestore_list_) 15203 | ); 15204 | 15205 | range_.n1_c.second = ret_string_.size(); 15206 | range_.cache.second = range_.n1_c.second; 15207 | 15208 | return result; 15209 | } 15210 | 15211 | return std::numeric_limits<T>::quiet_NaN(); 15212 | } 15213 | 15214 | inline typename expression_node<T>::node_type type() const exprtk_override 15215 | { 15216 | return expression_node<T>::e_strfunction; 15217 | } 15218 | 15219 | inline bool valid() const exprtk_override 15220 | { 15221 | return gen_function_t::function_; 15222 | } 15223 | 15224 | std::string str() const exprtk_override 15225 | { 15226 | return ret_string_; 15227 | } 15228 | 15229 | char_cptr base() const exprtk_override 15230 | { 15231 | return &ret_string_[0]; 15232 | } 15233 | 15234 | std::size_t size() const exprtk_override 15235 | { 15236 | return ret_string_.size(); 15237 | } 15238 | 15239 | range_t& range_ref() exprtk_override 15240 | { 15241 | return range_; 15242 | } 15243 | 15244 | const range_t& range_ref() const exprtk_override 15245 | { 15246 | return range_; 15247 | } 15248 | 15249 | protected: 15250 | 15251 | mutable range_t range_; 15252 | mutable std::string ret_string_; 15253 | }; 15254 | #endif 15255 | 15256 | template <typename T, typename GenericFunction> 15257 | class multimode_genfunction_node : public generic_function_node<T,GenericFunction> 15258 | { 15259 | public: 15260 | 15261 | typedef generic_function_node<T,GenericFunction> gen_function_t; 15262 | typedef typename gen_function_t::range_t range_t; 15263 | 15264 | multimode_genfunction_node(GenericFunction* func, 15265 | const std::size_t& param_seq_index, 15266 | const std::vector<typename gen_function_t::expression_ptr>& arg_list) 15267 | : gen_function_t(arg_list,func) 15268 | , param_seq_index_(param_seq_index) 15269 | {} 15270 | 15271 | inline T value() const exprtk_override 15272 | { 15273 | assert(gen_function_t::valid()); 15274 | 15275 | if (gen_function_t::populate_value_list()) 15276 | { 15277 | typedef typename GenericFunction::parameter_list_t parameter_list_t; 15278 | 15279 | return 15280 | (*gen_function_t::function_) 15281 | ( 15282 | param_seq_index_, 15283 | parameter_list_t(gen_function_t::typestore_list_) 15284 | ); 15285 | } 15286 | 15287 | return std::numeric_limits<T>::quiet_NaN(); 15288 | } 15289 | 15290 | inline typename expression_node<T>::node_type type() const exprtk_override exprtk_final 15291 | { 15292 | return expression_node<T>::e_genfunction; 15293 | } 15294 | 15295 | private: 15296 | 15297 | std::size_t param_seq_index_; 15298 | }; 15299 | 15300 | #ifndef exprtk_disable_string_capabilities 15301 | template <typename T, typename StringFunction> 15302 | class multimode_strfunction_node exprtk_final : public string_function_node<T,StringFunction> 15303 | { 15304 | public: 15305 | 15306 | typedef string_function_node<T,StringFunction> str_function_t; 15307 | typedef typename str_function_t::range_t range_t; 15308 | 15309 | multimode_strfunction_node(StringFunction* func, 15310 | const std::size_t& param_seq_index, 15311 | const std::vector<typename str_function_t::expression_ptr>& arg_list) 15312 | : str_function_t(func,arg_list) 15313 | , param_seq_index_(param_seq_index) 15314 | {} 15315 | 15316 | inline T value() const exprtk_override 15317 | { 15318 | if (str_function_t::populate_value_list()) 15319 | { 15320 | typedef typename StringFunction::parameter_list_t parameter_list_t; 15321 | 15322 | const T result = 15323 | (*str_function_t::function_) 15324 | ( 15325 | param_seq_index_, 15326 | str_function_t::ret_string_, 15327 | parameter_list_t(str_function_t::typestore_list_) 15328 | ); 15329 | 15330 | str_function_t::range_.n1_c.second = str_function_t::ret_string_.size(); 15331 | str_function_t::range_.cache.second = str_function_t::range_.n1_c.second; 15332 | 15333 | return result; 15334 | } 15335 | 15336 | return std::numeric_limits<T>::quiet_NaN(); 15337 | } 15338 | 15339 | inline typename expression_node<T>::node_type type() const exprtk_override 15340 | { 15341 | return expression_node<T>::e_strfunction; 15342 | } 15343 | 15344 | private: 15345 | 15346 | const std::size_t param_seq_index_; 15347 | }; 15348 | #endif 15349 | 15350 | class return_exception {}; 15351 | 15352 | template <typename T> 15353 | class null_igenfunc 15354 | { 15355 | public: 15356 | 15357 | virtual ~null_igenfunc() 15358 | {} 15359 | 15360 | typedef type_store<T> generic_type; 15361 | typedef typename generic_type::parameter_list parameter_list_t; 15362 | 15363 | inline virtual T operator() (parameter_list_t) 15364 | { 15365 | return std::numeric_limits<T>::quiet_NaN(); 15366 | } 15367 | }; 15368 | 15369 | #ifndef exprtk_disable_return_statement 15370 | template <typename T> 15371 | class return_node exprtk_final : public generic_function_node<T,null_igenfunc<T> > 15372 | { 15373 | public: 15374 | 15375 | typedef results_context<T> results_context_t; 15376 | typedef null_igenfunc<T> igeneric_function_t; 15377 | typedef igeneric_function_t* igeneric_function_ptr; 15378 | typedef generic_function_node<T,igeneric_function_t> gen_function_t; 15379 | 15380 | return_node(const std::vector<typename gen_function_t::expression_ptr>& arg_list, 15381 | results_context_t& rc) 15382 | : gen_function_t (arg_list) 15383 | , results_context_(&rc) 15384 | { 15385 | assert(valid()); 15386 | } 15387 | 15388 | inline T value() const exprtk_override 15389 | { 15390 | if (gen_function_t::populate_value_list()) 15391 | { 15392 | typedef typename type_store<T>::parameter_list parameter_list_t; 15393 | 15394 | results_context_-> 15395 | assign(parameter_list_t(gen_function_t::typestore_list_)); 15396 | 15397 | throw return_exception(); 15398 | } 15399 | 15400 | return std::numeric_limits<T>::quiet_NaN(); 15401 | } 15402 | 15403 | inline typename expression_node<T>::node_type type() const exprtk_override 15404 | { 15405 | return expression_node<T>::e_return; 15406 | } 15407 | 15408 | inline bool valid() const exprtk_override 15409 | { 15410 | return results_context_; 15411 | } 15412 | 15413 | private: 15414 | 15415 | results_context_t* results_context_; 15416 | }; 15417 | 15418 | template <typename T> 15419 | class return_envelope_node exprtk_final : public expression_node<T> 15420 | { 15421 | public: 15422 | 15423 | typedef expression_node<T>* expression_ptr; 15424 | typedef results_context<T> results_context_t; 15425 | typedef std::pair<expression_ptr,bool> branch_t; 15426 | 15427 | return_envelope_node(expression_ptr body, results_context_t& rc) 15428 | : results_context_(&rc ) 15429 | , return_invoked_ (false) 15430 | { 15431 | construct_branch_pair(body_, body); 15432 | assert(valid()); 15433 | } 15434 | 15435 | inline T value() const exprtk_override 15436 | { 15437 | try 15438 | { 15439 | return_invoked_ = false; 15440 | results_context_->clear(); 15441 | 15442 | return body_.first->value(); 15443 | } 15444 | catch(const return_exception&) 15445 | { 15446 | return_invoked_ = true; 15447 | 15448 | return std::numeric_limits<T>::quiet_NaN(); 15449 | } 15450 | } 15451 | 15452 | inline typename expression_node<T>::node_type type() const exprtk_override 15453 | { 15454 | return expression_node<T>::e_retenv; 15455 | } 15456 | 15457 | inline bool valid() const exprtk_override 15458 | { 15459 | return results_context_ && body_.first; 15460 | } 15461 | 15462 | inline bool* retinvk_ptr() 15463 | { 15464 | return &return_invoked_; 15465 | } 15466 | 15467 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 15468 | { 15469 | expression_node<T>::ndb_t::collect(body_, node_delete_list); 15470 | } 15471 | 15472 | std::size_t node_depth() const exprtk_override 15473 | { 15474 | return expression_node<T>::ndb_t::compute_node_depth(body_); 15475 | } 15476 | 15477 | private: 15478 | 15479 | results_context_t* results_context_; 15480 | mutable bool return_invoked_; 15481 | branch_t body_; 15482 | }; 15483 | #endif 15484 | 15485 | #define exprtk_define_unary_op(OpName) \ 15486 | template <typename T> \ 15487 | struct OpName##_op \ 15488 | { \ 15489 | typedef typename functor_t<T>::Type Type; \ 15490 | typedef typename expression_node<T>::node_type node_t; \ 15491 | \ 15492 | static inline T process(Type v) \ 15493 | { \ 15494 | return numeric:: OpName (v); \ 15495 | } \ 15496 | \ 15497 | static inline node_t type() \ 15498 | { \ 15499 | return expression_node<T>::e_##OpName; \ 15500 | } \ 15501 | \ 15502 | static inline details::operator_type operation() \ 15503 | { \ 15504 | return details::e_##OpName; \ 15505 | } \ 15506 | }; \ 15507 | 15508 | exprtk_define_unary_op(abs ) 15509 | exprtk_define_unary_op(acos ) 15510 | exprtk_define_unary_op(acosh) 15511 | exprtk_define_unary_op(asin ) 15512 | exprtk_define_unary_op(asinh) 15513 | exprtk_define_unary_op(atan ) 15514 | exprtk_define_unary_op(atanh) 15515 | exprtk_define_unary_op(ceil ) 15516 | exprtk_define_unary_op(cos ) 15517 | exprtk_define_unary_op(cosh ) 15518 | exprtk_define_unary_op(cot ) 15519 | exprtk_define_unary_op(csc ) 15520 | exprtk_define_unary_op(d2g ) 15521 | exprtk_define_unary_op(d2r ) 15522 | exprtk_define_unary_op(erf ) 15523 | exprtk_define_unary_op(erfc ) 15524 | exprtk_define_unary_op(exp ) 15525 | exprtk_define_unary_op(expm1) 15526 | exprtk_define_unary_op(floor) 15527 | exprtk_define_unary_op(frac ) 15528 | exprtk_define_unary_op(g2d ) 15529 | exprtk_define_unary_op(log ) 15530 | exprtk_define_unary_op(log10) 15531 | exprtk_define_unary_op(log2 ) 15532 | exprtk_define_unary_op(log1p) 15533 | exprtk_define_unary_op(ncdf ) 15534 | exprtk_define_unary_op(neg ) 15535 | exprtk_define_unary_op(notl ) 15536 | exprtk_define_unary_op(pos ) 15537 | exprtk_define_unary_op(r2d ) 15538 | exprtk_define_unary_op(round) 15539 | exprtk_define_unary_op(sec ) 15540 | exprtk_define_unary_op(sgn ) 15541 | exprtk_define_unary_op(sin ) 15542 | exprtk_define_unary_op(sinc ) 15543 | exprtk_define_unary_op(sinh ) 15544 | exprtk_define_unary_op(sqrt ) 15545 | exprtk_define_unary_op(tan ) 15546 | exprtk_define_unary_op(tanh ) 15547 | exprtk_define_unary_op(trunc) 15548 | #undef exprtk_define_unary_op 15549 | 15550 | template <typename T> 15551 | struct opr_base 15552 | { 15553 | typedef typename details::functor_t<T>::Type Type; 15554 | typedef typename details::functor_t<T>::RefType RefType; 15555 | typedef typename details::functor_t<T> functor_t; 15556 | typedef typename functor_t::qfunc_t quaternary_functor_t; 15557 | typedef typename functor_t::tfunc_t trinary_functor_t; 15558 | typedef typename functor_t::bfunc_t binary_functor_t; 15559 | typedef typename functor_t::ufunc_t unary_functor_t; 15560 | }; 15561 | 15562 | template <typename T> 15563 | struct add_op : public opr_base<T> 15564 | { 15565 | typedef typename opr_base<T>::Type Type; 15566 | typedef typename opr_base<T>::RefType RefType; 15567 | 15568 | static inline T process(Type t1, Type t2) { return t1 + t2; } 15569 | static inline T process(Type t1, Type t2, Type t3) { return t1 + t2 + t3; } 15570 | static inline void assign(RefType t1, Type t2) { t1 += t2; } 15571 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_add; } 15572 | static inline details::operator_type operation() { return details::e_add; } 15573 | }; 15574 | 15575 | template <typename T> 15576 | struct mul_op : public opr_base<T> 15577 | { 15578 | typedef typename opr_base<T>::Type Type; 15579 | typedef typename opr_base<T>::RefType RefType; 15580 | 15581 | static inline T process(Type t1, Type t2) { return t1 * t2; } 15582 | static inline T process(Type t1, Type t2, Type t3) { return t1 * t2 * t3; } 15583 | static inline void assign(RefType t1, Type t2) { t1 *= t2; } 15584 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_mul; } 15585 | static inline details::operator_type operation() { return details::e_mul; } 15586 | }; 15587 | 15588 | template <typename T> 15589 | struct sub_op : public opr_base<T> 15590 | { 15591 | typedef typename opr_base<T>::Type Type; 15592 | typedef typename opr_base<T>::RefType RefType; 15593 | 15594 | static inline T process(Type t1, Type t2) { return t1 - t2; } 15595 | static inline T process(Type t1, Type t2, Type t3) { return t1 - t2 - t3; } 15596 | static inline void assign(RefType t1, Type t2) { t1 -= t2; } 15597 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_sub; } 15598 | static inline details::operator_type operation() { return details::e_sub; } 15599 | }; 15600 | 15601 | template <typename T> 15602 | struct div_op : public opr_base<T> 15603 | { 15604 | typedef typename opr_base<T>::Type Type; 15605 | typedef typename opr_base<T>::RefType RefType; 15606 | 15607 | static inline T process(Type t1, Type t2) { return t1 / t2; } 15608 | static inline T process(Type t1, Type t2, Type t3) { return t1 / t2 / t3; } 15609 | static inline void assign(RefType t1, Type t2) { t1 /= t2; } 15610 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_div; } 15611 | static inline details::operator_type operation() { return details::e_div; } 15612 | }; 15613 | 15614 | template <typename T> 15615 | struct mod_op : public opr_base<T> 15616 | { 15617 | typedef typename opr_base<T>::Type Type; 15618 | typedef typename opr_base<T>::RefType RefType; 15619 | 15620 | static inline T process(Type t1, Type t2) { return numeric::modulus<T>(t1,t2); } 15621 | static inline void assign(RefType t1, Type t2) { t1 = numeric::modulus<T>(t1,t2); } 15622 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_mod; } 15623 | static inline details::operator_type operation() { return details::e_mod; } 15624 | }; 15625 | 15626 | template <typename T> 15627 | struct pow_op : public opr_base<T> 15628 | { 15629 | typedef typename opr_base<T>::Type Type; 15630 | typedef typename opr_base<T>::RefType RefType; 15631 | 15632 | static inline T process(Type t1, Type t2) { return numeric::pow<T>(t1,t2); } 15633 | static inline void assign(RefType t1, Type t2) { t1 = numeric::pow<T>(t1,t2); } 15634 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_pow; } 15635 | static inline details::operator_type operation() { return details::e_pow; } 15636 | }; 15637 | 15638 | template <typename T> 15639 | struct lt_op : public opr_base<T> 15640 | { 15641 | typedef typename opr_base<T>::Type Type; 15642 | 15643 | static inline T process(Type t1, Type t2) { return ((t1 < t2) ? T(1) : T(0)); } 15644 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 < t2) ? T(1) : T(0)); } 15645 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_lt; } 15646 | static inline details::operator_type operation() { return details::e_lt; } 15647 | }; 15648 | 15649 | template <typename T> 15650 | struct lte_op : public opr_base<T> 15651 | { 15652 | typedef typename opr_base<T>::Type Type; 15653 | 15654 | static inline T process(Type t1, Type t2) { return ((t1 <= t2) ? T(1) : T(0)); } 15655 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 <= t2) ? T(1) : T(0)); } 15656 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_lte; } 15657 | static inline details::operator_type operation() { return details::e_lte; } 15658 | }; 15659 | 15660 | template <typename T> 15661 | struct gt_op : public opr_base<T> 15662 | { 15663 | typedef typename opr_base<T>::Type Type; 15664 | 15665 | static inline T process(Type t1, Type t2) { return ((t1 > t2) ? T(1) : T(0)); } 15666 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 > t2) ? T(1) : T(0)); } 15667 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_gt; } 15668 | static inline details::operator_type operation() { return details::e_gt; } 15669 | }; 15670 | 15671 | template <typename T> 15672 | struct gte_op : public opr_base<T> 15673 | { 15674 | typedef typename opr_base<T>::Type Type; 15675 | 15676 | static inline T process(Type t1, Type t2) { return ((t1 >= t2) ? T(1) : T(0)); } 15677 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 >= t2) ? T(1) : T(0)); } 15678 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_gte; } 15679 | static inline details::operator_type operation() { return details::e_gte; } 15680 | }; 15681 | 15682 | template <typename T> 15683 | struct eq_op : public opr_base<T> 15684 | { 15685 | typedef typename opr_base<T>::Type Type; 15686 | static inline T process(Type t1, Type t2) { return (std::equal_to<T>()(t1,t2) ? T(1) : T(0)); } 15687 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 == t2) ? T(1) : T(0)); } 15688 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_eq; } 15689 | static inline details::operator_type operation() { return details::e_eq; } 15690 | }; 15691 | 15692 | template <typename T> 15693 | struct equal_op : public opr_base<T> 15694 | { 15695 | typedef typename opr_base<T>::Type Type; 15696 | 15697 | static inline T process(Type t1, Type t2) { return numeric::equal(t1,t2); } 15698 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 == t2) ? T(1) : T(0)); } 15699 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_eq; } 15700 | static inline details::operator_type operation() { return details::e_equal; } 15701 | }; 15702 | 15703 | template <typename T> 15704 | struct ne_op : public opr_base<T> 15705 | { 15706 | typedef typename opr_base<T>::Type Type; 15707 | 15708 | static inline T process(Type t1, Type t2) { return (std::not_equal_to<T>()(t1,t2) ? T(1) : T(0)); } 15709 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 != t2) ? T(1) : T(0)); } 15710 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_ne; } 15711 | static inline details::operator_type operation() { return details::e_ne; } 15712 | }; 15713 | 15714 | template <typename T> 15715 | struct and_op : public opr_base<T> 15716 | { 15717 | typedef typename opr_base<T>::Type Type; 15718 | 15719 | static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(1) : T(0); } 15720 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_and; } 15721 | static inline details::operator_type operation() { return details::e_and; } 15722 | }; 15723 | 15724 | template <typename T> 15725 | struct nand_op : public opr_base<T> 15726 | { 15727 | typedef typename opr_base<T>::Type Type; 15728 | 15729 | static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(0) : T(1); } 15730 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nand; } 15731 | static inline details::operator_type operation() { return details::e_nand; } 15732 | }; 15733 | 15734 | template <typename T> 15735 | struct or_op : public opr_base<T> 15736 | { 15737 | typedef typename opr_base<T>::Type Type; 15738 | 15739 | static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(1) : T(0); } 15740 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_or; } 15741 | static inline details::operator_type operation() { return details::e_or; } 15742 | }; 15743 | 15744 | template <typename T> 15745 | struct nor_op : public opr_base<T> 15746 | { 15747 | typedef typename opr_base<T>::Type Type; 15748 | 15749 | static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(0) : T(1); } 15750 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; } 15751 | static inline details::operator_type operation() { return details::e_nor; } 15752 | }; 15753 | 15754 | template <typename T> 15755 | struct xor_op : public opr_base<T> 15756 | { 15757 | typedef typename opr_base<T>::Type Type; 15758 | 15759 | static inline T process(Type t1, Type t2) { return numeric::xor_opr<T>(t1,t2); } 15760 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; } 15761 | static inline details::operator_type operation() { return details::e_xor; } 15762 | }; 15763 | 15764 | template <typename T> 15765 | struct xnor_op : public opr_base<T> 15766 | { 15767 | typedef typename opr_base<T>::Type Type; 15768 | 15769 | static inline T process(Type t1, Type t2) { return numeric::xnor_opr<T>(t1,t2); } 15770 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; } 15771 | static inline details::operator_type operation() { return details::e_xnor; } 15772 | }; 15773 | 15774 | template <typename T> 15775 | struct in_op : public opr_base<T> 15776 | { 15777 | typedef typename opr_base<T>::Type Type; 15778 | 15779 | static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); } 15780 | static inline T process(const std::string& t1, const std::string& t2) { return ((std::string::npos != t2.find(t1)) ? T(1) : T(0)); } 15781 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_in; } 15782 | static inline details::operator_type operation() { return details::e_in; } 15783 | }; 15784 | 15785 | template <typename T> 15786 | struct like_op : public opr_base<T> 15787 | { 15788 | typedef typename opr_base<T>::Type Type; 15789 | 15790 | static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); } 15791 | static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_match(t2,t1) ? T(1) : T(0)); } 15792 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_like; } 15793 | static inline details::operator_type operation() { return details::e_like; } 15794 | }; 15795 | 15796 | template <typename T> 15797 | struct ilike_op : public opr_base<T> 15798 | { 15799 | typedef typename opr_base<T>::Type Type; 15800 | 15801 | static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); } 15802 | static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_imatch(t2,t1) ? T(1) : T(0)); } 15803 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_ilike; } 15804 | static inline details::operator_type operation() { return details::e_ilike; } 15805 | }; 15806 | 15807 | template <typename T> 15808 | struct inrange_op : public opr_base<T> 15809 | { 15810 | typedef typename opr_base<T>::Type Type; 15811 | 15812 | static inline T process(const T& t0, const T& t1, const T& t2) { return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0); } 15813 | static inline T process(const std::string& t0, const std::string& t1, const std::string& t2) 15814 | { 15815 | return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0); 15816 | } 15817 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_inranges; } 15818 | static inline details::operator_type operation() { return details::e_inrange; } 15819 | }; 15820 | 15821 | template <typename T> 15822 | inline T value(details::expression_node<T>* n) 15823 | { 15824 | return n->value(); 15825 | } 15826 | 15827 | template <typename T> 15828 | inline T value(std::pair<details::expression_node<T>*,bool> n) 15829 | { 15830 | return n.first->value(); 15831 | } 15832 | 15833 | template <typename T> 15834 | inline T value(const T* t) 15835 | { 15836 | return (*t); 15837 | } 15838 | 15839 | template <typename T> 15840 | inline T value(const T& t) 15841 | { 15842 | return t; 15843 | } 15844 | 15845 | template <typename T> 15846 | struct vararg_add_op exprtk_final : public opr_base<T> 15847 | { 15848 | typedef typename opr_base<T>::Type Type; 15849 | 15850 | template <typename Type, 15851 | typename Allocator, 15852 | template <typename, typename> class Sequence> 15853 | static inline T process(const Sequence<Type,Allocator>& arg_list) 15854 | { 15855 | switch (arg_list.size()) 15856 | { 15857 | case 0 : return T(0); 15858 | case 1 : return process_1(arg_list); 15859 | case 2 : return process_2(arg_list); 15860 | case 3 : return process_3(arg_list); 15861 | case 4 : return process_4(arg_list); 15862 | case 5 : return process_5(arg_list); 15863 | default : 15864 | { 15865 | T result = T(0); 15866 | 15867 | for (std::size_t i = 0; i < arg_list.size(); ++i) 15868 | { 15869 | result += value(arg_list[i]); 15870 | } 15871 | 15872 | return result; 15873 | } 15874 | } 15875 | } 15876 | 15877 | template <typename Sequence> 15878 | static inline T process_1(const Sequence& arg_list) 15879 | { 15880 | return value(arg_list[0]); 15881 | } 15882 | 15883 | template <typename Sequence> 15884 | static inline T process_2(const Sequence& arg_list) 15885 | { 15886 | return value(arg_list[0]) + value(arg_list[1]); 15887 | } 15888 | 15889 | template <typename Sequence> 15890 | static inline T process_3(const Sequence& arg_list) 15891 | { 15892 | return value(arg_list[0]) + value(arg_list[1]) + 15893 | value(arg_list[2]) ; 15894 | } 15895 | 15896 | template <typename Sequence> 15897 | static inline T process_4(const Sequence& arg_list) 15898 | { 15899 | return value(arg_list[0]) + value(arg_list[1]) + 15900 | value(arg_list[2]) + value(arg_list[3]) ; 15901 | } 15902 | 15903 | template <typename Sequence> 15904 | static inline T process_5(const Sequence& arg_list) 15905 | { 15906 | return value(arg_list[0]) + value(arg_list[1]) + 15907 | value(arg_list[2]) + value(arg_list[3]) + 15908 | value(arg_list[4]) ; 15909 | } 15910 | }; 15911 | 15912 | template <typename T> 15913 | struct vararg_mul_op exprtk_final : public opr_base<T> 15914 | { 15915 | typedef typename opr_base<T>::Type Type; 15916 | 15917 | template <typename Type, 15918 | typename Allocator, 15919 | template <typename, typename> class Sequence> 15920 | static inline T process(const Sequence<Type,Allocator>& arg_list) 15921 | { 15922 | switch (arg_list.size()) 15923 | { 15924 | case 0 : return T(0); 15925 | case 1 : return process_1(arg_list); 15926 | case 2 : return process_2(arg_list); 15927 | case 3 : return process_3(arg_list); 15928 | case 4 : return process_4(arg_list); 15929 | case 5 : return process_5(arg_list); 15930 | default : 15931 | { 15932 | T result = T(value(arg_list[0])); 15933 | 15934 | for (std::size_t i = 1; i < arg_list.size(); ++i) 15935 | { 15936 | result *= value(arg_list[i]); 15937 | } 15938 | 15939 | return result; 15940 | } 15941 | } 15942 | } 15943 | 15944 | template <typename Sequence> 15945 | static inline T process_1(const Sequence& arg_list) 15946 | { 15947 | return value(arg_list[0]); 15948 | } 15949 | 15950 | template <typename Sequence> 15951 | static inline T process_2(const Sequence& arg_list) 15952 | { 15953 | return value(arg_list[0]) * value(arg_list[1]); 15954 | } 15955 | 15956 | template <typename Sequence> 15957 | static inline T process_3(const Sequence& arg_list) 15958 | { 15959 | return value(arg_list[0]) * value(arg_list[1]) * 15960 | value(arg_list[2]) ; 15961 | } 15962 | 15963 | template <typename Sequence> 15964 | static inline T process_4(const Sequence& arg_list) 15965 | { 15966 | return value(arg_list[0]) * value(arg_list[1]) * 15967 | value(arg_list[2]) * value(arg_list[3]) ; 15968 | } 15969 | 15970 | template <typename Sequence> 15971 | static inline T process_5(const Sequence& arg_list) 15972 | { 15973 | return value(arg_list[0]) * value(arg_list[1]) * 15974 | value(arg_list[2]) * value(arg_list[3]) * 15975 | value(arg_list[4]) ; 15976 | } 15977 | }; 15978 | 15979 | template <typename T> 15980 | struct vararg_avg_op exprtk_final : public opr_base<T> 15981 | { 15982 | typedef typename opr_base<T>::Type Type; 15983 | 15984 | template <typename Type, 15985 | typename Allocator, 15986 | template <typename, typename> class Sequence> 15987 | static inline T process(const Sequence<Type,Allocator>& arg_list) 15988 | { 15989 | switch (arg_list.size()) 15990 | { 15991 | case 0 : return T(0); 15992 | case 1 : return process_1(arg_list); 15993 | case 2 : return process_2(arg_list); 15994 | case 3 : return process_3(arg_list); 15995 | case 4 : return process_4(arg_list); 15996 | case 5 : return process_5(arg_list); 15997 | default : return vararg_add_op<T>::process(arg_list) / T(arg_list.size()); 15998 | } 15999 | } 16000 | 16001 | template <typename Sequence> 16002 | static inline T process_1(const Sequence& arg_list) 16003 | { 16004 | return value(arg_list[0]); 16005 | } 16006 | 16007 | template <typename Sequence> 16008 | static inline T process_2(const Sequence& arg_list) 16009 | { 16010 | return (value(arg_list[0]) + value(arg_list[1])) / T(2); 16011 | } 16012 | 16013 | template <typename Sequence> 16014 | static inline T process_3(const Sequence& arg_list) 16015 | { 16016 | return (value(arg_list[0]) + value(arg_list[1]) + value(arg_list[2])) / T(3); 16017 | } 16018 | 16019 | template <typename Sequence> 16020 | static inline T process_4(const Sequence& arg_list) 16021 | { 16022 | return (value(arg_list[0]) + value(arg_list[1]) + 16023 | value(arg_list[2]) + value(arg_list[3])) / T(4); 16024 | } 16025 | 16026 | template <typename Sequence> 16027 | static inline T process_5(const Sequence& arg_list) 16028 | { 16029 | return (value(arg_list[0]) + value(arg_list[1]) + 16030 | value(arg_list[2]) + value(arg_list[3]) + 16031 | value(arg_list[4])) / T(5); 16032 | } 16033 | }; 16034 | 16035 | template <typename T> 16036 | struct vararg_min_op exprtk_final : public opr_base<T> 16037 | { 16038 | typedef typename opr_base<T>::Type Type; 16039 | 16040 | template <typename Type, 16041 | typename Allocator, 16042 | template <typename, typename> class Sequence> 16043 | static inline T process(const Sequence<Type,Allocator>& arg_list) 16044 | { 16045 | switch (arg_list.size()) 16046 | { 16047 | case 0 : return T(0); 16048 | case 1 : return process_1(arg_list); 16049 | case 2 : return process_2(arg_list); 16050 | case 3 : return process_3(arg_list); 16051 | case 4 : return process_4(arg_list); 16052 | case 5 : return process_5(arg_list); 16053 | default : 16054 | { 16055 | T result = T(value(arg_list[0])); 16056 | 16057 | for (std::size_t i = 1; i < arg_list.size(); ++i) 16058 | { 16059 | const T v = value(arg_list[i]); 16060 | 16061 | if (v < result) 16062 | result = v; 16063 | } 16064 | 16065 | return result; 16066 | } 16067 | } 16068 | } 16069 | 16070 | template <typename Sequence> 16071 | static inline T process_1(const Sequence& arg_list) 16072 | { 16073 | return value(arg_list[0]); 16074 | } 16075 | 16076 | template <typename Sequence> 16077 | static inline T process_2(const Sequence& arg_list) 16078 | { 16079 | return std::min<T>(value(arg_list[0]),value(arg_list[1])); 16080 | } 16081 | 16082 | template <typename Sequence> 16083 | static inline T process_3(const Sequence& arg_list) 16084 | { 16085 | return std::min<T>(std::min<T>(value(arg_list[0]),value(arg_list[1])),value(arg_list[2])); 16086 | } 16087 | 16088 | template <typename Sequence> 16089 | static inline T process_4(const Sequence& arg_list) 16090 | { 16091 | return std::min<T>( 16092 | std::min<T>(value(arg_list[0]), value(arg_list[1])), 16093 | std::min<T>(value(arg_list[2]), value(arg_list[3]))); 16094 | } 16095 | 16096 | template <typename Sequence> 16097 | static inline T process_5(const Sequence& arg_list) 16098 | { 16099 | return std::min<T>( 16100 | std::min<T>(std::min<T>(value(arg_list[0]), value(arg_list[1])), 16101 | std::min<T>(value(arg_list[2]), value(arg_list[3]))), 16102 | value(arg_list[4])); 16103 | } 16104 | }; 16105 | 16106 | template <typename T> 16107 | struct vararg_max_op exprtk_final : public opr_base<T> 16108 | { 16109 | typedef typename opr_base<T>::Type Type; 16110 | 16111 | template <typename Type, 16112 | typename Allocator, 16113 | template <typename, typename> class Sequence> 16114 | static inline T process(const Sequence<Type,Allocator>& arg_list) 16115 | { 16116 | switch (arg_list.size()) 16117 | { 16118 | case 0 : return T(0); 16119 | case 1 : return process_1(arg_list); 16120 | case 2 : return process_2(arg_list); 16121 | case 3 : return process_3(arg_list); 16122 | case 4 : return process_4(arg_list); 16123 | case 5 : return process_5(arg_list); 16124 | default : 16125 | { 16126 | T result = T(value(arg_list[0])); 16127 | 16128 | for (std::size_t i = 1; i < arg_list.size(); ++i) 16129 | { 16130 | const T v = value(arg_list[i]); 16131 | 16132 | if (v > result) 16133 | result = v; 16134 | } 16135 | 16136 | return result; 16137 | } 16138 | } 16139 | } 16140 | 16141 | template <typename Sequence> 16142 | static inline T process_1(const Sequence& arg_list) 16143 | { 16144 | return value(arg_list[0]); 16145 | } 16146 | 16147 | template <typename Sequence> 16148 | static inline T process_2(const Sequence& arg_list) 16149 | { 16150 | return std::max<T>(value(arg_list[0]),value(arg_list[1])); 16151 | } 16152 | 16153 | template <typename Sequence> 16154 | static inline T process_3(const Sequence& arg_list) 16155 | { 16156 | return std::max<T>(std::max<T>(value(arg_list[0]),value(arg_list[1])),value(arg_list[2])); 16157 | } 16158 | 16159 | template <typename Sequence> 16160 | static inline T process_4(const Sequence& arg_list) 16161 | { 16162 | return std::max<T>( 16163 | std::max<T>(value(arg_list[0]), value(arg_list[1])), 16164 | std::max<T>(value(arg_list[2]), value(arg_list[3]))); 16165 | } 16166 | 16167 | template <typename Sequence> 16168 | static inline T process_5(const Sequence& arg_list) 16169 | { 16170 | return std::max<T>( 16171 | std::max<T>(std::max<T>(value(arg_list[0]), value(arg_list[1])), 16172 | std::max<T>(value(arg_list[2]), value(arg_list[3]))), 16173 | value(arg_list[4])); 16174 | } 16175 | }; 16176 | 16177 | template <typename T> 16178 | struct vararg_mand_op exprtk_final : public opr_base<T> 16179 | { 16180 | typedef typename opr_base<T>::Type Type; 16181 | 16182 | template <typename Type, 16183 | typename Allocator, 16184 | template <typename, typename> class Sequence> 16185 | static inline T process(const Sequence<Type,Allocator>& arg_list) 16186 | { 16187 | switch (arg_list.size()) 16188 | { 16189 | case 1 : return process_1(arg_list); 16190 | case 2 : return process_2(arg_list); 16191 | case 3 : return process_3(arg_list); 16192 | case 4 : return process_4(arg_list); 16193 | case 5 : return process_5(arg_list); 16194 | default : 16195 | { 16196 | for (std::size_t i = 0; i < arg_list.size(); ++i) 16197 | { 16198 | if (std::equal_to<T>()(T(0), value(arg_list[i]))) 16199 | return T(0); 16200 | } 16201 | 16202 | return T(1); 16203 | } 16204 | } 16205 | } 16206 | 16207 | template <typename Sequence> 16208 | static inline T process_1(const Sequence& arg_list) 16209 | { 16210 | return std::not_equal_to<T>() 16211 | (T(0), value(arg_list[0])) ? T(1) : T(0); 16212 | } 16213 | 16214 | template <typename Sequence> 16215 | static inline T process_2(const Sequence& arg_list) 16216 | { 16217 | return ( 16218 | std::not_equal_to<T>()(T(0), value(arg_list[0])) && 16219 | std::not_equal_to<T>()(T(0), value(arg_list[1])) 16220 | ) ? T(1) : T(0); 16221 | } 16222 | 16223 | template <typename Sequence> 16224 | static inline T process_3(const Sequence& arg_list) 16225 | { 16226 | return ( 16227 | std::not_equal_to<T>()(T(0), value(arg_list[0])) && 16228 | std::not_equal_to<T>()(T(0), value(arg_list[1])) && 16229 | std::not_equal_to<T>()(T(0), value(arg_list[2])) 16230 | ) ? T(1) : T(0); 16231 | } 16232 | 16233 | template <typename Sequence> 16234 | static inline T process_4(const Sequence& arg_list) 16235 | { 16236 | return ( 16237 | std::not_equal_to<T>()(T(0), value(arg_list[0])) && 16238 | std::not_equal_to<T>()(T(0), value(arg_list[1])) && 16239 | std::not_equal_to<T>()(T(0), value(arg_list[2])) && 16240 | std::not_equal_to<T>()(T(0), value(arg_list[3])) 16241 | ) ? T(1) : T(0); 16242 | } 16243 | 16244 | template <typename Sequence> 16245 | static inline T process_5(const Sequence& arg_list) 16246 | { 16247 | return ( 16248 | std::not_equal_to<T>()(T(0), value(arg_list[0])) && 16249 | std::not_equal_to<T>()(T(0), value(arg_list[1])) && 16250 | std::not_equal_to<T>()(T(0), value(arg_list[2])) && 16251 | std::not_equal_to<T>()(T(0), value(arg_list[3])) && 16252 | std::not_equal_to<T>()(T(0), value(arg_list[4])) 16253 | ) ? T(1) : T(0); 16254 | } 16255 | }; 16256 | 16257 | template <typename T> 16258 | struct vararg_mor_op exprtk_final : public opr_base<T> 16259 | { 16260 | typedef typename opr_base<T>::Type Type; 16261 | 16262 | template <typename Type, 16263 | typename Allocator, 16264 | template <typename, typename> class Sequence> 16265 | static inline T process(const Sequence<Type,Allocator>& arg_list) 16266 | { 16267 | switch (arg_list.size()) 16268 | { 16269 | case 1 : return process_1(arg_list); 16270 | case 2 : return process_2(arg_list); 16271 | case 3 : return process_3(arg_list); 16272 | case 4 : return process_4(arg_list); 16273 | case 5 : return process_5(arg_list); 16274 | default : 16275 | { 16276 | for (std::size_t i = 0; i < arg_list.size(); ++i) 16277 | { 16278 | if (std::not_equal_to<T>()(T(0), value(arg_list[i]))) 16279 | return T(1); 16280 | } 16281 | 16282 | return T(0); 16283 | } 16284 | } 16285 | } 16286 | 16287 | template <typename Sequence> 16288 | static inline T process_1(const Sequence& arg_list) 16289 | { 16290 | return std::not_equal_to<T>() 16291 | (T(0), value(arg_list[0])) ? T(1) : T(0); 16292 | } 16293 | 16294 | template <typename Sequence> 16295 | static inline T process_2(const Sequence& arg_list) 16296 | { 16297 | return ( 16298 | std::not_equal_to<T>()(T(0), value(arg_list[0])) || 16299 | std::not_equal_to<T>()(T(0), value(arg_list[1])) 16300 | ) ? T(1) : T(0); 16301 | } 16302 | 16303 | template <typename Sequence> 16304 | static inline T process_3(const Sequence& arg_list) 16305 | { 16306 | return ( 16307 | std::not_equal_to<T>()(T(0), value(arg_list[0])) || 16308 | std::not_equal_to<T>()(T(0), value(arg_list[1])) || 16309 | std::not_equal_to<T>()(T(0), value(arg_list[2])) 16310 | ) ? T(1) : T(0); 16311 | } 16312 | 16313 | template <typename Sequence> 16314 | static inline T process_4(const Sequence& arg_list) 16315 | { 16316 | return ( 16317 | std::not_equal_to<T>()(T(0), value(arg_list[0])) || 16318 | std::not_equal_to<T>()(T(0), value(arg_list[1])) || 16319 | std::not_equal_to<T>()(T(0), value(arg_list[2])) || 16320 | std::not_equal_to<T>()(T(0), value(arg_list[3])) 16321 | ) ? T(1) : T(0); 16322 | } 16323 | 16324 | template <typename Sequence> 16325 | static inline T process_5(const Sequence& arg_list) 16326 | { 16327 | return ( 16328 | std::not_equal_to<T>()(T(0), value(arg_list[0])) || 16329 | std::not_equal_to<T>()(T(0), value(arg_list[1])) || 16330 | std::not_equal_to<T>()(T(0), value(arg_list[2])) || 16331 | std::not_equal_to<T>()(T(0), value(arg_list[3])) || 16332 | std::not_equal_to<T>()(T(0), value(arg_list[4])) 16333 | ) ? T(1) : T(0); 16334 | } 16335 | }; 16336 | 16337 | template <typename T> 16338 | struct vararg_multi_op exprtk_final : public opr_base<T> 16339 | { 16340 | typedef typename opr_base<T>::Type Type; 16341 | 16342 | template <typename Type, 16343 | typename Allocator, 16344 | template <typename, typename> class Sequence> 16345 | static inline T process(const Sequence<Type,Allocator>& arg_list) 16346 | { 16347 | switch (arg_list.size()) 16348 | { 16349 | case 0 : return std::numeric_limits<T>::quiet_NaN(); 16350 | case 1 : return process_1(arg_list); 16351 | case 2 : return process_2(arg_list); 16352 | case 3 : return process_3(arg_list); 16353 | case 4 : return process_4(arg_list); 16354 | case 5 : return process_5(arg_list); 16355 | case 6 : return process_6(arg_list); 16356 | case 7 : return process_7(arg_list); 16357 | case 8 : return process_8(arg_list); 16358 | default : 16359 | { 16360 | for (std::size_t i = 0; i < (arg_list.size() - 1); ++i) 16361 | { 16362 | value(arg_list[i]); 16363 | } 16364 | return value(arg_list.back()); 16365 | } 16366 | } 16367 | } 16368 | 16369 | template <typename Sequence> 16370 | static inline T process_1(const Sequence& arg_list) 16371 | { 16372 | return value(arg_list[0]); 16373 | } 16374 | 16375 | template <typename Sequence> 16376 | static inline T process_2(const Sequence& arg_list) 16377 | { 16378 | value(arg_list[0]); 16379 | return value(arg_list[1]); 16380 | } 16381 | 16382 | template <typename Sequence> 16383 | static inline T process_3(const Sequence& arg_list) 16384 | { 16385 | value(arg_list[0]); 16386 | value(arg_list[1]); 16387 | return value(arg_list[2]); 16388 | } 16389 | 16390 | template <typename Sequence> 16391 | static inline T process_4(const Sequence& arg_list) 16392 | { 16393 | value(arg_list[0]); 16394 | value(arg_list[1]); 16395 | value(arg_list[2]); 16396 | return value(arg_list[3]); 16397 | } 16398 | 16399 | template <typename Sequence> 16400 | static inline T process_5(const Sequence& arg_list) 16401 | { 16402 | value(arg_list[0]); 16403 | value(arg_list[1]); 16404 | value(arg_list[2]); 16405 | value(arg_list[3]); 16406 | return value(arg_list[4]); 16407 | } 16408 | 16409 | template <typename Sequence> 16410 | static inline T process_6(const Sequence& arg_list) 16411 | { 16412 | value(arg_list[0]); 16413 | value(arg_list[1]); 16414 | value(arg_list[2]); 16415 | value(arg_list[3]); 16416 | value(arg_list[4]); 16417 | return value(arg_list[5]); 16418 | } 16419 | 16420 | template <typename Sequence> 16421 | static inline T process_7(const Sequence& arg_list) 16422 | { 16423 | value(arg_list[0]); 16424 | value(arg_list[1]); 16425 | value(arg_list[2]); 16426 | value(arg_list[3]); 16427 | value(arg_list[4]); 16428 | value(arg_list[5]); 16429 | return value(arg_list[6]); 16430 | } 16431 | 16432 | template <typename Sequence> 16433 | static inline T process_8(const Sequence& arg_list) 16434 | { 16435 | value(arg_list[0]); 16436 | value(arg_list[1]); 16437 | value(arg_list[2]); 16438 | value(arg_list[3]); 16439 | value(arg_list[4]); 16440 | value(arg_list[5]); 16441 | value(arg_list[6]); 16442 | return value(arg_list[7]); 16443 | } 16444 | }; 16445 | 16446 | template <typename T> 16447 | struct vec_add_op 16448 | { 16449 | typedef vector_interface<T>* ivector_ptr; 16450 | 16451 | static inline T process(const ivector_ptr v) 16452 | { 16453 | const T* vec = v->vec()->vds().data(); 16454 | const std::size_t vec_size = v->size(); 16455 | 16456 | loop_unroll::details lud(vec_size); 16457 | 16458 | if (vec_size <= static_cast<std::size_t>(lud.batch_size)) 16459 | { 16460 | T result = T(0); 16461 | int i = 0; 16462 | 16463 | switch (vec_size) 16464 | { 16465 | #define case_stmt(N,fall_through) \ 16466 | case N : result += vec[i++]; \ 16467 | fall_through \ 16468 | 16469 | #ifndef exprtk_disable_superscalar_unroll 16470 | case_stmt(16, exprtk_fallthrough) case_stmt(15, exprtk_fallthrough) 16471 | case_stmt(14, exprtk_fallthrough) case_stmt(13, exprtk_fallthrough) 16472 | case_stmt(12, exprtk_fallthrough) case_stmt(11, exprtk_fallthrough) 16473 | case_stmt(10, exprtk_fallthrough) case_stmt( 9, exprtk_fallthrough) 16474 | case_stmt( 8, exprtk_fallthrough) case_stmt( 7, exprtk_fallthrough) 16475 | case_stmt( 6, exprtk_fallthrough) case_stmt( 5, exprtk_fallthrough) 16476 | 16477 | #endif 16478 | case_stmt( 4, exprtk_fallthrough) case_stmt( 3, exprtk_fallthrough) 16479 | case_stmt( 2, exprtk_fallthrough) case_stmt( 1, (void)0;) 16480 | } 16481 | 16482 | #undef case_stmt 16483 | 16484 | return result; 16485 | } 16486 | 16487 | T r[] = { 16488 | T(0), T(0), T(0), T(0), T(0), T(0), T(0), T(0), 16489 | T(0), T(0), T(0), T(0), T(0), T(0), T(0), T(0) 16490 | }; 16491 | 16492 | const T* upper_bound = vec + lud.upper_bound; 16493 | 16494 | while (vec < upper_bound) 16495 | { 16496 | #define exprtk_loop(N) \ 16497 | r[N] += vec[N]; \ 16498 | 16499 | exprtk_loop( 0) exprtk_loop( 1) 16500 | exprtk_loop( 2) exprtk_loop( 3) 16501 | #ifndef exprtk_disable_superscalar_unroll 16502 | exprtk_loop( 4) exprtk_loop( 5) 16503 | exprtk_loop( 6) exprtk_loop( 7) 16504 | exprtk_loop( 8) exprtk_loop( 9) 16505 | exprtk_loop(10) exprtk_loop(11) 16506 | exprtk_loop(12) exprtk_loop(13) 16507 | exprtk_loop(14) exprtk_loop(15) 16508 | #endif 16509 | 16510 | vec += lud.batch_size; 16511 | } 16512 | 16513 | int i = 0; 16514 | 16515 | switch (lud.remainder) 16516 | { 16517 | #define case_stmt(N,fall_through) \ 16518 | case N : r[0] += vec[i++]; \ 16519 | fall_through \ 16520 | 16521 | #ifndef exprtk_disable_superscalar_unroll 16522 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 16523 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 16524 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 16525 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 16526 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 16527 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 16528 | #endif 16529 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 16530 | case_stmt( 1, (void)0;) 16531 | } 16532 | 16533 | #undef exprtk_loop 16534 | #undef case_stmt 16535 | 16536 | return (r[ 0] + r[ 1] + r[ 2] + r[ 3]) 16537 | #ifndef exprtk_disable_superscalar_unroll 16538 | + (r[ 4] + r[ 5] + r[ 6] + r[ 7]) 16539 | + (r[ 8] + r[ 9] + r[10] + r[11]) 16540 | + (r[12] + r[13] + r[14] + r[15]) 16541 | #endif 16542 | ; 16543 | } 16544 | }; 16545 | 16546 | template <typename T> 16547 | struct vec_mul_op 16548 | { 16549 | typedef vector_interface<T>* ivector_ptr; 16550 | 16551 | static inline T process(const ivector_ptr v) 16552 | { 16553 | const T* vec = v->vec()->vds().data(); 16554 | const std::size_t vec_size = v->vec()->size(); 16555 | 16556 | loop_unroll::details lud(vec_size); 16557 | 16558 | if (vec_size <= static_cast<std::size_t>(lud.batch_size)) 16559 | { 16560 | T result = T(1); 16561 | int i = 0; 16562 | 16563 | switch (vec_size) 16564 | { 16565 | #define case_stmt(N,fall_through) \ 16566 | case N : result *= vec[i++]; \ 16567 | fall_through \ 16568 | 16569 | #ifndef exprtk_disable_superscalar_unroll 16570 | case_stmt(16, exprtk_fallthrough) case_stmt(15, exprtk_fallthrough) 16571 | case_stmt(14, exprtk_fallthrough) case_stmt(13, exprtk_fallthrough) 16572 | case_stmt(12, exprtk_fallthrough) case_stmt(11, exprtk_fallthrough) 16573 | case_stmt(10, exprtk_fallthrough) case_stmt( 9, exprtk_fallthrough) 16574 | case_stmt( 8, exprtk_fallthrough) case_stmt( 7, exprtk_fallthrough) 16575 | case_stmt( 6, exprtk_fallthrough) case_stmt( 5, exprtk_fallthrough) 16576 | #endif 16577 | case_stmt( 4, exprtk_fallthrough) case_stmt( 3, exprtk_fallthrough) 16578 | case_stmt( 2, exprtk_fallthrough) case_stmt( 1, (void)0;) 16579 | } 16580 | 16581 | #undef case_stmt 16582 | 16583 | return result; 16584 | } 16585 | 16586 | T r[] = { 16587 | T(1), T(1), T(1), T(1), T(1), T(1), T(1), T(1), 16588 | T(1), T(1), T(1), T(1), T(1), T(1), T(1), T(1) 16589 | }; 16590 | 16591 | const T* upper_bound = vec + lud.upper_bound; 16592 | 16593 | while (vec < upper_bound) 16594 | { 16595 | #define exprtk_loop(N) \ 16596 | r[N] *= vec[N]; \ 16597 | 16598 | exprtk_loop( 0) exprtk_loop( 1) 16599 | exprtk_loop( 2) exprtk_loop( 3) 16600 | #ifndef exprtk_disable_superscalar_unroll 16601 | exprtk_loop( 4) exprtk_loop( 5) 16602 | exprtk_loop( 6) exprtk_loop( 7) 16603 | exprtk_loop( 8) exprtk_loop( 9) 16604 | exprtk_loop(10) exprtk_loop(11) 16605 | exprtk_loop(12) exprtk_loop(13) 16606 | exprtk_loop(14) exprtk_loop(15) 16607 | #endif 16608 | 16609 | vec += lud.batch_size; 16610 | } 16611 | 16612 | int i = 0; 16613 | 16614 | switch (lud.remainder) 16615 | { 16616 | #define case_stmt(N,fall_through) \ 16617 | case N : r[0] *= vec[i++]; \ 16618 | fall_through \ 16619 | 16620 | #ifndef exprtk_disable_superscalar_unroll 16621 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 16622 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 16623 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 16624 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 16625 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 16626 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 16627 | #endif 16628 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 16629 | case_stmt( 1, (void)0;) 16630 | } 16631 | 16632 | #undef exprtk_loop 16633 | #undef case_stmt 16634 | 16635 | return (r[ 0] * r[ 1] * r[ 2] * r[ 3]) 16636 | #ifndef exprtk_disable_superscalar_unroll 16637 | * (r[ 4] * r[ 5] * r[ 6] * r[ 7]) 16638 | * (r[ 8] * r[ 9] * r[10] * r[11]) 16639 | * (r[12] * r[13] * r[14] * r[15]) 16640 | #endif 16641 | ; 16642 | } 16643 | }; 16644 | 16645 | template <typename T> 16646 | struct vec_avg_op 16647 | { 16648 | typedef vector_interface<T>* ivector_ptr; 16649 | 16650 | static inline T process(const ivector_ptr v) 16651 | { 16652 | const T vec_size = T(v->vec()->size()); 16653 | return vec_add_op<T>::process(v) / vec_size; 16654 | } 16655 | }; 16656 | 16657 | template <typename T> 16658 | struct vec_min_op 16659 | { 16660 | typedef vector_interface<T>* ivector_ptr; 16661 | 16662 | static inline T process(const ivector_ptr v) 16663 | { 16664 | const T* vec = v->vec()->vds().data(); 16665 | const std::size_t vec_size = v->vec()->size(); 16666 | 16667 | T result = vec[0]; 16668 | 16669 | for (std::size_t i = 1; i < vec_size; ++i) 16670 | { 16671 | const T v_i = vec[i]; 16672 | 16673 | if (v_i < result) 16674 | result = v_i; 16675 | } 16676 | 16677 | return result; 16678 | } 16679 | }; 16680 | 16681 | template <typename T> 16682 | struct vec_max_op 16683 | { 16684 | typedef vector_interface<T>* ivector_ptr; 16685 | 16686 | static inline T process(const ivector_ptr v) 16687 | { 16688 | const T* vec = v->vec()->vds().data(); 16689 | const std::size_t vec_size = v->vec()->size(); 16690 | 16691 | T result = vec[0]; 16692 | 16693 | for (std::size_t i = 1; i < vec_size; ++i) 16694 | { 16695 | const T v_i = vec[i]; 16696 | 16697 | if (v_i > result) 16698 | result = v_i; 16699 | } 16700 | 16701 | return result; 16702 | } 16703 | }; 16704 | 16705 | template <typename T> 16706 | class vov_base_node : public expression_node<T> 16707 | { 16708 | public: 16709 | 16710 | virtual ~vov_base_node() 16711 | {} 16712 | 16713 | inline virtual operator_type operation() const 16714 | { 16715 | return details::e_default; 16716 | } 16717 | 16718 | virtual const T& v0() const = 0; 16719 | 16720 | virtual const T& v1() const = 0; 16721 | }; 16722 | 16723 | template <typename T> 16724 | class cov_base_node : public expression_node<T> 16725 | { 16726 | public: 16727 | 16728 | virtual ~cov_base_node() 16729 | {} 16730 | 16731 | inline virtual operator_type operation() const 16732 | { 16733 | return details::e_default; 16734 | } 16735 | 16736 | virtual const T c() const = 0; 16737 | 16738 | virtual const T& v() const = 0; 16739 | }; 16740 | 16741 | template <typename T> 16742 | class voc_base_node : public expression_node<T> 16743 | { 16744 | public: 16745 | 16746 | virtual ~voc_base_node() 16747 | {} 16748 | 16749 | inline virtual operator_type operation() const 16750 | { 16751 | return details::e_default; 16752 | } 16753 | 16754 | virtual const T c() const = 0; 16755 | 16756 | virtual const T& v() const = 0; 16757 | }; 16758 | 16759 | template <typename T> 16760 | class vob_base_node : public expression_node<T> 16761 | { 16762 | public: 16763 | 16764 | virtual ~vob_base_node() 16765 | {} 16766 | 16767 | virtual const T& v() const = 0; 16768 | }; 16769 | 16770 | template <typename T> 16771 | class bov_base_node : public expression_node<T> 16772 | { 16773 | public: 16774 | 16775 | virtual ~bov_base_node() 16776 | {} 16777 | 16778 | virtual const T& v() const = 0; 16779 | }; 16780 | 16781 | template <typename T> 16782 | class cob_base_node : public expression_node<T> 16783 | { 16784 | public: 16785 | 16786 | virtual ~cob_base_node() 16787 | {} 16788 | 16789 | inline virtual operator_type operation() const 16790 | { 16791 | return details::e_default; 16792 | } 16793 | 16794 | virtual const T c() const = 0; 16795 | 16796 | virtual void set_c(const T) = 0; 16797 | 16798 | virtual expression_node<T>* move_branch(const std::size_t& index) = 0; 16799 | }; 16800 | 16801 | template <typename T> 16802 | class boc_base_node : public expression_node<T> 16803 | { 16804 | public: 16805 | 16806 | virtual ~boc_base_node() 16807 | {} 16808 | 16809 | inline virtual operator_type operation() const 16810 | { 16811 | return details::e_default; 16812 | } 16813 | 16814 | virtual const T c() const = 0; 16815 | 16816 | virtual void set_c(const T) = 0; 16817 | 16818 | virtual expression_node<T>* move_branch(const std::size_t& index) = 0; 16819 | }; 16820 | 16821 | template <typename T> 16822 | class uv_base_node : public expression_node<T> 16823 | { 16824 | public: 16825 | 16826 | virtual ~uv_base_node() 16827 | {} 16828 | 16829 | inline virtual operator_type operation() const 16830 | { 16831 | return details::e_default; 16832 | } 16833 | 16834 | virtual const T& v() const = 0; 16835 | }; 16836 | 16837 | template <typename T> 16838 | class sos_base_node : public expression_node<T> 16839 | { 16840 | public: 16841 | 16842 | virtual ~sos_base_node() 16843 | {} 16844 | 16845 | inline virtual operator_type operation() const 16846 | { 16847 | return details::e_default; 16848 | } 16849 | }; 16850 | 16851 | template <typename T> 16852 | class sosos_base_node : public expression_node<T> 16853 | { 16854 | public: 16855 | 16856 | virtual ~sosos_base_node() 16857 | {} 16858 | 16859 | inline virtual operator_type operation() const 16860 | { 16861 | return details::e_default; 16862 | } 16863 | }; 16864 | 16865 | template <typename T> 16866 | class T0oT1oT2_base_node : public expression_node<T> 16867 | { 16868 | public: 16869 | 16870 | virtual ~T0oT1oT2_base_node() 16871 | {} 16872 | 16873 | virtual std::string type_id() const = 0; 16874 | }; 16875 | 16876 | template <typename T> 16877 | class T0oT1oT2oT3_base_node : public expression_node<T> 16878 | { 16879 | public: 16880 | 16881 | virtual ~T0oT1oT2oT3_base_node() 16882 | {} 16883 | 16884 | virtual std::string type_id() const = 0; 16885 | }; 16886 | 16887 | template <typename T, typename Operation> 16888 | class unary_variable_node exprtk_final : public uv_base_node<T> 16889 | { 16890 | public: 16891 | 16892 | typedef expression_node<T>* expression_ptr; 16893 | typedef Operation operation_t; 16894 | 16895 | explicit unary_variable_node(const T& var) 16896 | : v_(var) 16897 | {} 16898 | 16899 | inline T value() const exprtk_override 16900 | { 16901 | return Operation::process(v_); 16902 | } 16903 | 16904 | inline typename expression_node<T>::node_type type() const exprtk_override 16905 | { 16906 | return Operation::type(); 16907 | } 16908 | 16909 | inline operator_type operation() const exprtk_override 16910 | { 16911 | return Operation::operation(); 16912 | } 16913 | 16914 | inline const T& v() const exprtk_override 16915 | { 16916 | return v_; 16917 | } 16918 | 16919 | private: 16920 | 16921 | unary_variable_node(const unary_variable_node<T,Operation>&) exprtk_delete; 16922 | unary_variable_node<T,Operation>& operator=(const unary_variable_node<T,Operation>&) exprtk_delete; 16923 | 16924 | const T& v_; 16925 | }; 16926 | 16927 | template <typename T> 16928 | class uvouv_node exprtk_final : public expression_node<T> 16929 | { 16930 | public: 16931 | 16932 | // UOpr1(v0) Op UOpr2(v1) 16933 | typedef typename details::functor_t<T> functor_t; 16934 | typedef typename functor_t::bfunc_t bfunc_t; 16935 | typedef typename functor_t::ufunc_t ufunc_t; 16936 | typedef expression_node<T>* expression_ptr; 16937 | 16938 | explicit uvouv_node(const T& var0,const T& var1, 16939 | ufunc_t uf0, ufunc_t uf1, bfunc_t bf) 16940 | : v0_(var0) 16941 | , v1_(var1) 16942 | , u0_(uf0 ) 16943 | , u1_(uf1 ) 16944 | , f_ (bf ) 16945 | {} 16946 | 16947 | inline T value() const exprtk_override 16948 | { 16949 | return f_(u0_(v0_),u1_(v1_)); 16950 | } 16951 | 16952 | inline typename expression_node<T>::node_type type() const exprtk_override 16953 | { 16954 | return expression_node<T>::e_uvouv; 16955 | } 16956 | 16957 | inline const T& v0() 16958 | { 16959 | return v0_; 16960 | } 16961 | 16962 | inline const T& v1() 16963 | { 16964 | return v1_; 16965 | } 16966 | 16967 | inline ufunc_t u0() 16968 | { 16969 | return u0_; 16970 | } 16971 | 16972 | inline ufunc_t u1() 16973 | { 16974 | return u1_; 16975 | } 16976 | 16977 | inline ufunc_t f() 16978 | { 16979 | return f_; 16980 | } 16981 | 16982 | private: 16983 | 16984 | uvouv_node(const uvouv_node<T>&) exprtk_delete; 16985 | uvouv_node<T>& operator=(const uvouv_node<T>&) exprtk_delete; 16986 | 16987 | const T& v0_; 16988 | const T& v1_; 16989 | const ufunc_t u0_; 16990 | const ufunc_t u1_; 16991 | const bfunc_t f_; 16992 | }; 16993 | 16994 | template <typename T, typename Operation> 16995 | class unary_branch_node exprtk_final : public expression_node<T> 16996 | { 16997 | public: 16998 | 16999 | typedef Operation operation_t; 17000 | typedef expression_node<T>* expression_ptr; 17001 | typedef std::pair<expression_ptr,bool> branch_t; 17002 | 17003 | explicit unary_branch_node(expression_ptr branch) 17004 | { 17005 | construct_branch_pair(branch_, branch); 17006 | } 17007 | 17008 | inline T value() const exprtk_override 17009 | { 17010 | return Operation::process(branch_.first->value()); 17011 | } 17012 | 17013 | inline typename expression_node<T>::node_type type() const exprtk_override 17014 | { 17015 | return Operation::type(); 17016 | } 17017 | 17018 | inline bool valid() const exprtk_override 17019 | { 17020 | return branch_.first && branch_.first->valid(); 17021 | } 17022 | 17023 | inline operator_type operation() 17024 | { 17025 | return Operation::operation(); 17026 | } 17027 | 17028 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 17029 | { 17030 | return branch_.first; 17031 | } 17032 | 17033 | inline void release() 17034 | { 17035 | branch_.second = false; 17036 | } 17037 | 17038 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 17039 | { 17040 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 17041 | } 17042 | 17043 | std::size_t node_depth() const exprtk_override 17044 | { 17045 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 17046 | } 17047 | 17048 | private: 17049 | 17050 | unary_branch_node(const unary_branch_node<T,Operation>&) exprtk_delete; 17051 | unary_branch_node<T,Operation>& operator=(const unary_branch_node<T,Operation>&) exprtk_delete; 17052 | 17053 | branch_t branch_; 17054 | }; 17055 | 17056 | template <typename T> struct is_const { enum {result = 0}; }; 17057 | template <typename T> struct is_const <const T> { enum {result = 1}; }; 17058 | template <typename T> struct is_const_ref { enum {result = 0}; }; 17059 | template <typename T> struct is_const_ref <const T&> { enum {result = 1}; }; 17060 | template <typename T> struct is_ref { enum {result = 0}; }; 17061 | template <typename T> struct is_ref<T&> { enum {result = 1}; }; 17062 | template <typename T> struct is_ref<const T&> { enum {result = 0}; }; 17063 | 17064 | template <std::size_t State> 17065 | struct param_to_str { static std::string result() { static const std::string r("v"); return r; } }; 17066 | 17067 | template <> 17068 | struct param_to_str<0> { static std::string result() { static const std::string r("c"); return r; } }; 17069 | 17070 | #define exprtk_crtype(Type) \ 17071 | param_to_str<is_const_ref< Type >::result>::result() \ 17072 | 17073 | template <typename T> 17074 | struct T0oT1oT2process 17075 | { 17076 | typedef typename details::functor_t<T> functor_t; 17077 | typedef typename functor_t::bfunc_t bfunc_t; 17078 | 17079 | struct mode0 17080 | { 17081 | static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1) 17082 | { 17083 | // (T0 o0 T1) o1 T2 17084 | return bf1(bf0(t0,t1),t2); 17085 | } 17086 | 17087 | template <typename T0, typename T1, typename T2> 17088 | static inline std::string id() 17089 | { 17090 | static const std::string result = "(" + exprtk_crtype(T0) + "o" + 17091 | exprtk_crtype(T1) + ")o(" + 17092 | exprtk_crtype(T2) + ")" ; 17093 | return result; 17094 | } 17095 | }; 17096 | 17097 | struct mode1 17098 | { 17099 | static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1) 17100 | { 17101 | // T0 o0 (T1 o1 T2) 17102 | return bf0(t0,bf1(t1,t2)); 17103 | } 17104 | 17105 | template <typename T0, typename T1, typename T2> 17106 | static inline std::string id() 17107 | { 17108 | static const std::string result = "(" + exprtk_crtype(T0) + ")o(" + 17109 | exprtk_crtype(T1) + "o" + 17110 | exprtk_crtype(T2) + ")" ; 17111 | return result; 17112 | } 17113 | }; 17114 | }; 17115 | 17116 | template <typename T> 17117 | struct T0oT1oT20T3process 17118 | { 17119 | typedef typename details::functor_t<T> functor_t; 17120 | typedef typename functor_t::bfunc_t bfunc_t; 17121 | 17122 | struct mode0 17123 | { 17124 | static inline T process(const T& t0, const T& t1, 17125 | const T& t2, const T& t3, 17126 | const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) 17127 | { 17128 | // (T0 o0 T1) o1 (T2 o2 T3) 17129 | return bf1(bf0(t0,t1),bf2(t2,t3)); 17130 | } 17131 | 17132 | template <typename T0, typename T1, typename T2, typename T3> 17133 | static inline std::string id() 17134 | { 17135 | static const std::string result = "(" + exprtk_crtype(T0) + "o" + 17136 | exprtk_crtype(T1) + ")o" + 17137 | "(" + exprtk_crtype(T2) + "o" + 17138 | exprtk_crtype(T3) + ")" ; 17139 | return result; 17140 | } 17141 | }; 17142 | 17143 | struct mode1 17144 | { 17145 | static inline T process(const T& t0, const T& t1, 17146 | const T& t2, const T& t3, 17147 | const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) 17148 | { 17149 | // (T0 o0 (T1 o1 (T2 o2 T3)) 17150 | return bf0(t0,bf1(t1,bf2(t2,t3))); 17151 | } 17152 | template <typename T0, typename T1, typename T2, typename T3> 17153 | static inline std::string id() 17154 | { 17155 | static const std::string result = "(" + exprtk_crtype(T0) + ")o((" + 17156 | exprtk_crtype(T1) + ")o(" + 17157 | exprtk_crtype(T2) + "o" + 17158 | exprtk_crtype(T3) + "))" ; 17159 | return result; 17160 | } 17161 | }; 17162 | 17163 | struct mode2 17164 | { 17165 | static inline T process(const T& t0, const T& t1, 17166 | const T& t2, const T& t3, 17167 | const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) 17168 | { 17169 | // (T0 o0 ((T1 o1 T2) o2 T3) 17170 | return bf0(t0,bf2(bf1(t1,t2),t3)); 17171 | } 17172 | 17173 | template <typename T0, typename T1, typename T2, typename T3> 17174 | static inline std::string id() 17175 | { 17176 | static const std::string result = "(" + exprtk_crtype(T0) + ")o((" + 17177 | exprtk_crtype(T1) + "o" + 17178 | exprtk_crtype(T2) + ")o(" + 17179 | exprtk_crtype(T3) + "))" ; 17180 | return result; 17181 | } 17182 | }; 17183 | 17184 | struct mode3 17185 | { 17186 | static inline T process(const T& t0, const T& t1, 17187 | const T& t2, const T& t3, 17188 | const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) 17189 | { 17190 | // (((T0 o0 T1) o1 T2) o2 T3) 17191 | return bf2(bf1(bf0(t0,t1),t2),t3); 17192 | } 17193 | 17194 | template <typename T0, typename T1, typename T2, typename T3> 17195 | static inline std::string id() 17196 | { 17197 | static const std::string result = "((" + exprtk_crtype(T0) + "o" + 17198 | exprtk_crtype(T1) + ")o(" + 17199 | exprtk_crtype(T2) + "))o(" + 17200 | exprtk_crtype(T3) + ")" 17201 | return result; 17202 | } 17203 | }; 17204 | 17205 | struct mode4 17206 | { 17207 | static inline T process(const T& t0, const T& t1, 17208 | const T& t2, const T& t3, 17209 | const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) 17210 | { 17211 | // ((T0 o0 (T1 o1 T2)) o2 T3 17212 | return bf2(bf0(t0,bf1(t1,t2)),t3); 17213 | } 17214 | 17215 | template <typename T0, typename T1, typename T2, typename T3> 17216 | static inline std::string id() 17217 | { 17218 | static const std::string result = "((" + exprtk_crtype(T0) + ")o(" + 17219 | exprtk_crtype(T1) + "o" + 17220 | exprtk_crtype(T2) + "))o(" + 17221 | exprtk_crtype(T3) + ")" ; 17222 | return result; 17223 | } 17224 | }; 17225 | }; 17226 | 17227 | #undef exprtk_crtype 17228 | 17229 | template <typename T, typename T0, typename T1> 17230 | struct nodetype_T0oT1 { static const typename expression_node<T>::node_type result; }; 17231 | template <typename T, typename T0, typename T1> 17232 | const typename expression_node<T>::node_type nodetype_T0oT1<T,T0,T1>::result = expression_node<T>::e_none; 17233 | 17234 | #define synthesis_node_type_define(T0_, T1_, v_) \ 17235 | template <typename T, typename T0, typename T1> \ 17236 | struct nodetype_T0oT1<T,T0_,T1_> { static const typename expression_node<T>::node_type result; }; \ 17237 | template <typename T, typename T0, typename T1> \ 17238 | const typename expression_node<T>::node_type nodetype_T0oT1<T,T0_,T1_>::result = expression_node<T>:: v_; \ 17239 | 17240 | synthesis_node_type_define(const T0&, const T1&, e_vov) 17241 | synthesis_node_type_define(const T0&, const T1 , e_voc) 17242 | synthesis_node_type_define(const T0 , const T1&, e_cov) 17243 | synthesis_node_type_define( T0&, T1&, e_none) 17244 | synthesis_node_type_define(const T0 , const T1 , e_none) 17245 | synthesis_node_type_define( T0&, const T1 , e_none) 17246 | synthesis_node_type_define(const T0 , T1&, e_none) 17247 | synthesis_node_type_define(const T0&, T1&, e_none) 17248 | synthesis_node_type_define( T0&, const T1&, e_none) 17249 | #undef synthesis_node_type_define 17250 | 17251 | template <typename T, typename T0, typename T1, typename T2> 17252 | struct nodetype_T0oT1oT2 { static const typename expression_node<T>::node_type result; }; 17253 | template <typename T, typename T0, typename T1, typename T2> 17254 | const typename expression_node<T>::node_type nodetype_T0oT1oT2<T,T0,T1,T2>::result = expression_node<T>::e_none; 17255 | 17256 | #define synthesis_node_type_define(T0_, T1_, T2_, v_) \ 17257 | template <typename T, typename T0, typename T1, typename T2> \ 17258 | struct nodetype_T0oT1oT2<T,T0_,T1_,T2_> { static const typename expression_node<T>::node_type result; }; \ 17259 | template <typename T, typename T0, typename T1, typename T2> \ 17260 | const typename expression_node<T>::node_type nodetype_T0oT1oT2<T,T0_,T1_,T2_>::result = expression_node<T>:: v_; \ 17261 | 17262 | synthesis_node_type_define(const T0&, const T1&, const T2&, e_vovov) 17263 | synthesis_node_type_define(const T0&, const T1&, const T2 , e_vovoc) 17264 | synthesis_node_type_define(const T0&, const T1 , const T2&, e_vocov) 17265 | synthesis_node_type_define(const T0 , const T1&, const T2&, e_covov) 17266 | synthesis_node_type_define(const T0 , const T1&, const T2 , e_covoc) 17267 | synthesis_node_type_define(const T0 , const T1 , const T2 , e_none ) 17268 | synthesis_node_type_define(const T0 , const T1 , const T2&, e_none ) 17269 | synthesis_node_type_define(const T0&, const T1 , const T2 , e_none ) 17270 | synthesis_node_type_define( T0&, T1&, T2&, e_none ) 17271 | #undef synthesis_node_type_define 17272 | 17273 | template <typename T, typename T0, typename T1, typename T2, typename T3> 17274 | struct nodetype_T0oT1oT2oT3 { static const typename expression_node<T>::node_type result; }; 17275 | template <typename T, typename T0, typename T1, typename T2, typename T3> 17276 | const typename expression_node<T>::node_type nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result = expression_node<T>::e_none; 17277 | 17278 | #define synthesis_node_type_define(T0_, T1_, T2_, T3_, v_) \ 17279 | template <typename T, typename T0, typename T1, typename T2, typename T3> \ 17280 | struct nodetype_T0oT1oT2oT3<T,T0_,T1_,T2_,T3_> { static const typename expression_node<T>::node_type result; }; \ 17281 | template <typename T, typename T0, typename T1, typename T2, typename T3> \ 17282 | const typename expression_node<T>::node_type nodetype_T0oT1oT2oT3<T,T0_,T1_,T2_,T3_>::result = expression_node<T>:: v_; \ 17283 | 17284 | synthesis_node_type_define(const T0&, const T1&, const T2&, const T3&, e_vovovov) 17285 | synthesis_node_type_define(const T0&, const T1&, const T2&, const T3 , e_vovovoc) 17286 | synthesis_node_type_define(const T0&, const T1&, const T2 , const T3&, e_vovocov) 17287 | synthesis_node_type_define(const T0&, const T1 , const T2&, const T3&, e_vocovov) 17288 | synthesis_node_type_define(const T0 , const T1&, const T2&, const T3&, e_covovov) 17289 | synthesis_node_type_define(const T0 , const T1&, const T2 , const T3&, e_covocov) 17290 | synthesis_node_type_define(const T0&, const T1 , const T2&, const T3 , e_vocovoc) 17291 | synthesis_node_type_define(const T0 , const T1&, const T2&, const T3 , e_covovoc) 17292 | synthesis_node_type_define(const T0&, const T1 , const T2 , const T3&, e_vococov) 17293 | synthesis_node_type_define(const T0 , const T1 , const T2 , const T3 , e_none ) 17294 | synthesis_node_type_define(const T0 , const T1 , const T2 , const T3&, e_none ) 17295 | synthesis_node_type_define(const T0 , const T1 , const T2&, const T3 , e_none ) 17296 | synthesis_node_type_define(const T0 , const T1&, const T2 , const T3 , e_none ) 17297 | synthesis_node_type_define(const T0&, const T1 , const T2 , const T3 , e_none ) 17298 | synthesis_node_type_define(const T0 , const T1 , const T2&, const T3&, e_none ) 17299 | synthesis_node_type_define(const T0&, const T1&, const T2 , const T3 , e_none ) 17300 | #undef synthesis_node_type_define 17301 | 17302 | template <typename T, typename T0, typename T1> 17303 | class T0oT1 exprtk_final : public expression_node<T> 17304 | { 17305 | public: 17306 | 17307 | typedef typename details::functor_t<T> functor_t; 17308 | typedef typename functor_t::bfunc_t bfunc_t; 17309 | typedef T value_type; 17310 | typedef T0oT1<T,T0,T1> node_type; 17311 | 17312 | T0oT1(T0 p0, T1 p1, const bfunc_t p2) 17313 | : t0_(p0) 17314 | , t1_(p1) 17315 | , f_ (p2) 17316 | {} 17317 | 17318 | inline typename expression_node<T>::node_type type() const exprtk_override 17319 | { 17320 | static const typename expression_node<T>::node_type result = nodetype_T0oT1<T,T0,T1>::result; 17321 | return result; 17322 | } 17323 | 17324 | inline operator_type operation() const exprtk_override 17325 | { 17326 | return e_default; 17327 | } 17328 | 17329 | inline T value() const exprtk_override 17330 | { 17331 | return f_(t0_,t1_); 17332 | } 17333 | 17334 | inline T0 t0() const 17335 | { 17336 | return t0_; 17337 | } 17338 | 17339 | inline T1 t1() const 17340 | { 17341 | return t1_; 17342 | } 17343 | 17344 | inline bfunc_t f() const 17345 | { 17346 | return f_; 17347 | } 17348 | 17349 | template <typename Allocator> 17350 | static inline expression_node<T>* allocate(Allocator& allocator, 17351 | T0 p0, T1 p1, 17352 | bfunc_t p2) 17353 | { 17354 | return allocator 17355 | .template allocate_type<node_type, T0, T1, bfunc_t&> 17356 | (p0, p1, p2); 17357 | } 17358 | 17359 | private: 17360 | 17361 | T0oT1(const T0oT1<T,T0,T1>&) exprtk_delete; 17362 | T0oT1<T,T0,T1>& operator=(const T0oT1<T,T0,T1>&) { return (*this); } 17363 | 17364 | T0 t0_; 17365 | T1 t1_; 17366 | const bfunc_t f_; 17367 | }; 17368 | 17369 | template <typename T, typename T0, typename T1, typename T2, typename ProcessMode> 17370 | class T0oT1oT2 exprtk_final : public T0oT1oT2_base_node<T> 17371 | { 17372 | public: 17373 | 17374 | typedef typename details::functor_t<T> functor_t; 17375 | typedef typename functor_t::bfunc_t bfunc_t; 17376 | typedef T value_type; 17377 | typedef T0oT1oT2<T,T0,T1,T2,ProcessMode> node_type; 17378 | typedef ProcessMode process_mode_t; 17379 | 17380 | T0oT1oT2(T0 p0, T1 p1, T2 p2, const bfunc_t p3, const bfunc_t p4) 17381 | : t0_(p0) 17382 | , t1_(p1) 17383 | , t2_(p2) 17384 | , f0_(p3) 17385 | , f1_(p4) 17386 | {} 17387 | 17388 | inline typename expression_node<T>::node_type type() const exprtk_override 17389 | { 17390 | static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result; 17391 | return result; 17392 | } 17393 | 17394 | inline operator_type operation() 17395 | { 17396 | return e_default; 17397 | } 17398 | 17399 | inline T value() const exprtk_override 17400 | { 17401 | return ProcessMode::process(t0_, t1_, t2_, f0_, f1_); 17402 | } 17403 | 17404 | inline T0 t0() const 17405 | { 17406 | return t0_; 17407 | } 17408 | 17409 | inline T1 t1() const 17410 | { 17411 | return t1_; 17412 | } 17413 | 17414 | inline T2 t2() const 17415 | { 17416 | return t2_; 17417 | } 17418 | 17419 | bfunc_t f0() const 17420 | { 17421 | return f0_; 17422 | } 17423 | 17424 | bfunc_t f1() const 17425 | { 17426 | return f1_; 17427 | } 17428 | 17429 | std::string type_id() const exprtk_override 17430 | { 17431 | return id(); 17432 | } 17433 | 17434 | static inline std::string id() 17435 | { 17436 | return process_mode_t::template id<T0,T1,T2>(); 17437 | } 17438 | 17439 | template <typename Allocator> 17440 | static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, bfunc_t p3, bfunc_t p4) 17441 | { 17442 | return allocator 17443 | .template allocate_type<node_type, T0, T1, T2, bfunc_t, bfunc_t> 17444 | (p0, p1, p2, p3, p4); 17445 | } 17446 | 17447 | private: 17448 | 17449 | T0oT1oT2(const node_type&) exprtk_delete; 17450 | node_type& operator=(const node_type&) exprtk_delete; 17451 | 17452 | T0 t0_; 17453 | T1 t1_; 17454 | T2 t2_; 17455 | const bfunc_t f0_; 17456 | const bfunc_t f1_; 17457 | }; 17458 | 17459 | template <typename T, typename T0_, typename T1_, typename T2_, typename T3_, typename ProcessMode> 17460 | class T0oT1oT2oT3 exprtk_final : public T0oT1oT2oT3_base_node<T> 17461 | { 17462 | public: 17463 | 17464 | typedef typename details::functor_t<T> functor_t; 17465 | typedef typename functor_t::bfunc_t bfunc_t; 17466 | typedef T value_type; 17467 | typedef T0_ T0; 17468 | typedef T1_ T1; 17469 | typedef T2_ T2; 17470 | typedef T3_ T3; 17471 | typedef T0oT1oT2oT3<T,T0,T1,T2,T3,ProcessMode> node_type; 17472 | typedef ProcessMode process_mode_t; 17473 | 17474 | T0oT1oT2oT3(T0 p0, T1 p1, T2 p2, T3 p3, bfunc_t p4, bfunc_t p5, bfunc_t p6) 17475 | : t0_(p0) 17476 | , t1_(p1) 17477 | , t2_(p2) 17478 | , t3_(p3) 17479 | , f0_(p4) 17480 | , f1_(p5) 17481 | , f2_(p6) 17482 | {} 17483 | 17484 | inline T value() const exprtk_override 17485 | { 17486 | return ProcessMode::process(t0_, t1_, t2_, t3_, f0_, f1_, f2_); 17487 | } 17488 | 17489 | inline T0 t0() const 17490 | { 17491 | return t0_; 17492 | } 17493 | 17494 | inline T1 t1() const 17495 | { 17496 | return t1_; 17497 | } 17498 | 17499 | inline T2 t2() const 17500 | { 17501 | return t2_; 17502 | } 17503 | 17504 | inline T3 t3() const 17505 | { 17506 | return t3_; 17507 | } 17508 | 17509 | inline bfunc_t f0() const 17510 | { 17511 | return f0_; 17512 | } 17513 | 17514 | inline bfunc_t f1() const 17515 | { 17516 | return f1_; 17517 | } 17518 | 17519 | inline bfunc_t f2() const 17520 | { 17521 | return f2_; 17522 | } 17523 | 17524 | inline std::string type_id() const exprtk_override 17525 | { 17526 | return id(); 17527 | } 17528 | 17529 | static inline std::string id() 17530 | { 17531 | return process_mode_t::template id<T0, T1, T2, T3>(); 17532 | } 17533 | 17534 | template <typename Allocator> 17535 | static inline expression_node<T>* allocate(Allocator& allocator, 17536 | T0 p0, T1 p1, T2 p2, T3 p3, 17537 | bfunc_t p4, bfunc_t p5, bfunc_t p6) 17538 | { 17539 | return allocator 17540 | .template allocate_type<node_type, T0, T1, T2, T3, bfunc_t, bfunc_t> 17541 | (p0, p1, p2, p3, p4, p5, p6); 17542 | } 17543 | 17544 | private: 17545 | 17546 | T0oT1oT2oT3(const node_type&) exprtk_delete; 17547 | node_type& operator=(const node_type&) exprtk_delete; 17548 | 17549 | T0 t0_; 17550 | T1 t1_; 17551 | T2 t2_; 17552 | T3 t3_; 17553 | const bfunc_t f0_; 17554 | const bfunc_t f1_; 17555 | const bfunc_t f2_; 17556 | }; 17557 | 17558 | template <typename T, typename T0, typename T1, typename T2> 17559 | class T0oT1oT2_sf3 exprtk_final : public T0oT1oT2_base_node<T> 17560 | { 17561 | public: 17562 | 17563 | typedef typename details::functor_t<T> functor_t; 17564 | typedef typename functor_t::tfunc_t tfunc_t; 17565 | typedef T value_type; 17566 | typedef T0oT1oT2_sf3<T,T0,T1,T2> node_type; 17567 | 17568 | T0oT1oT2_sf3(T0 p0, T1 p1, T2 p2, const tfunc_t p3) 17569 | : t0_(p0) 17570 | , t1_(p1) 17571 | , t2_(p2) 17572 | , f_ (p3) 17573 | {} 17574 | 17575 | inline typename expression_node<T>::node_type type() const exprtk_override 17576 | { 17577 | static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result; 17578 | return result; 17579 | } 17580 | 17581 | inline operator_type operation() const exprtk_override 17582 | { 17583 | return e_default; 17584 | } 17585 | 17586 | inline T value() const exprtk_override 17587 | { 17588 | return f_(t0_, t1_, t2_); 17589 | } 17590 | 17591 | inline T0 t0() const 17592 | { 17593 | return t0_; 17594 | } 17595 | 17596 | inline T1 t1() const 17597 | { 17598 | return t1_; 17599 | } 17600 | 17601 | inline T2 t2() const 17602 | { 17603 | return t2_; 17604 | } 17605 | 17606 | tfunc_t f() const 17607 | { 17608 | return f_; 17609 | } 17610 | 17611 | std::string type_id() const 17612 | { 17613 | return id(); 17614 | } 17615 | 17616 | static inline std::string id() 17617 | { 17618 | return "sf3" 17619 | } 17620 | 17621 | template <typename Allocator> 17622 | static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, tfunc_t p3) 17623 | { 17624 | return allocator 17625 | .template allocate_type<node_type, T0, T1, T2, tfunc_t> 17626 | (p0, p1, p2, p3); 17627 | } 17628 | 17629 | private: 17630 | 17631 | T0oT1oT2_sf3(const node_type&) exprtk_delete; 17632 | node_type& operator=(const node_type&) exprtk_delete; 17633 | 17634 | T0 t0_; 17635 | T1 t1_; 17636 | T2 t2_; 17637 | const tfunc_t f_; 17638 | }; 17639 | 17640 | template <typename T, typename T0, typename T1, typename T2> 17641 | class sf3ext_type_node : public T0oT1oT2_base_node<T> 17642 | { 17643 | public: 17644 | 17645 | virtual ~sf3ext_type_node() 17646 | {} 17647 | 17648 | virtual T0 t0() const = 0; 17649 | 17650 | virtual T1 t1() const = 0; 17651 | 17652 | virtual T2 t2() const = 0; 17653 | }; 17654 | 17655 | template <typename T, typename T0, typename T1, typename T2, typename SF3Operation> 17656 | class T0oT1oT2_sf3ext exprtk_final : public sf3ext_type_node<T,T0,T1,T2> 17657 | { 17658 | public: 17659 | 17660 | typedef T value_type; 17661 | typedef T0oT1oT2_sf3ext<T, T0, T1, T2, SF3Operation> node_type; 17662 | 17663 | T0oT1oT2_sf3ext(T0 p0, T1 p1, T2 p2) 17664 | : t0_(p0) 17665 | , t1_(p1) 17666 | , t2_(p2) 17667 | {} 17668 | 17669 | inline typename expression_node<T>::node_type type() const exprtk_override 17670 | { 17671 | static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result; 17672 | return result; 17673 | } 17674 | 17675 | inline operator_type operation() 17676 | { 17677 | return e_default; 17678 | } 17679 | 17680 | inline T value() const exprtk_override 17681 | { 17682 | return SF3Operation::process(t0_, t1_, t2_); 17683 | } 17684 | 17685 | T0 t0() const exprtk_override 17686 | { 17687 | return t0_; 17688 | } 17689 | 17690 | T1 t1() const exprtk_override 17691 | { 17692 | return t1_; 17693 | } 17694 | 17695 | T2 t2() const exprtk_override 17696 | { 17697 | return t2_; 17698 | } 17699 | 17700 | std::string type_id() const exprtk_override 17701 | { 17702 | return id(); 17703 | } 17704 | 17705 | static inline std::string id() 17706 | { 17707 | return SF3Operation::id(); 17708 | } 17709 | 17710 | template <typename Allocator> 17711 | static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2) 17712 | { 17713 | return allocator 17714 | .template allocate_type<node_type, T0, T1, T2> 17715 | (p0, p1, p2); 17716 | } 17717 | 17718 | private: 17719 | 17720 | T0oT1oT2_sf3ext(const node_type&) exprtk_delete; 17721 | node_type& operator=(const node_type&) exprtk_delete; 17722 | 17723 | T0 t0_; 17724 | T1 t1_; 17725 | T2 t2_; 17726 | }; 17727 | 17728 | template <typename T> 17729 | inline bool is_sf3ext_node(const expression_node<T>* n) 17730 | { 17731 | switch (n->type()) 17732 | { 17733 | case expression_node<T>::e_vovov : return true; 17734 | case expression_node<T>::e_vovoc : return true; 17735 | case expression_node<T>::e_vocov : return true; 17736 | case expression_node<T>::e_covov : return true; 17737 | case expression_node<T>::e_covoc : return true; 17738 | default : return false; 17739 | } 17740 | } 17741 | 17742 | template <typename T, typename T0, typename T1, typename T2, typename T3> 17743 | class T0oT1oT2oT3_sf4 exprtk_final : public T0oT1oT2_base_node<T> 17744 | { 17745 | public: 17746 | 17747 | typedef typename details::functor_t<T> functor_t; 17748 | typedef typename functor_t::qfunc_t qfunc_t; 17749 | typedef T value_type; 17750 | typedef T0oT1oT2oT3_sf4<T, T0, T1, T2, T3> node_type; 17751 | 17752 | T0oT1oT2oT3_sf4(T0 p0, T1 p1, T2 p2, T3 p3, const qfunc_t p4) 17753 | : t0_(p0) 17754 | , t1_(p1) 17755 | , t2_(p2) 17756 | , t3_(p3) 17757 | , f_ (p4) 17758 | {} 17759 | 17760 | inline typename expression_node<T>::node_type type() const exprtk_override 17761 | { 17762 | static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result; 17763 | return result; 17764 | } 17765 | 17766 | inline operator_type operation() const exprtk_override 17767 | { 17768 | return e_default; 17769 | } 17770 | 17771 | inline T value() const exprtk_override 17772 | { 17773 | return f_(t0_, t1_, t2_, t3_); 17774 | } 17775 | 17776 | inline T0 t0() const 17777 | { 17778 | return t0_; 17779 | } 17780 | 17781 | inline T1 t1() const 17782 | { 17783 | return t1_; 17784 | } 17785 | 17786 | inline T2 t2() const 17787 | { 17788 | return t2_; 17789 | } 17790 | 17791 | inline T3 t3() const 17792 | { 17793 | return t3_; 17794 | } 17795 | 17796 | qfunc_t f() const 17797 | { 17798 | return f_; 17799 | } 17800 | 17801 | std::string type_id() const 17802 | { 17803 | return id(); 17804 | } 17805 | 17806 | static inline std::string id() 17807 | { 17808 | return "sf4" 17809 | } 17810 | 17811 | template <typename Allocator> 17812 | static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, T3 p3, qfunc_t p4) 17813 | { 17814 | return allocator 17815 | .template allocate_type<node_type, T0, T1, T2, T3, qfunc_t> 17816 | (p0, p1, p2, p3, p4); 17817 | } 17818 | 17819 | private: 17820 | 17821 | T0oT1oT2oT3_sf4(const node_type&) exprtk_delete; 17822 | node_type& operator=(const node_type&) exprtk_delete; 17823 | 17824 | T0 t0_; 17825 | T1 t1_; 17826 | T2 t2_; 17827 | T3 t3_; 17828 | const qfunc_t f_; 17829 | }; 17830 | 17831 | template <typename T, typename T0, typename T1, typename T2, typename T3, typename SF4Operation> 17832 | class T0oT1oT2oT3_sf4ext exprtk_final : public T0oT1oT2oT3_base_node<T> 17833 | { 17834 | public: 17835 | 17836 | typedef T value_type; 17837 | typedef T0oT1oT2oT3_sf4ext<T, T0, T1, T2, T3, SF4Operation> node_type; 17838 | 17839 | T0oT1oT2oT3_sf4ext(T0 p0, T1 p1, T2 p2, T3 p3) 17840 | : t0_(p0) 17841 | , t1_(p1) 17842 | , t2_(p2) 17843 | , t3_(p3) 17844 | {} 17845 | 17846 | inline typename expression_node<T>::node_type type() const exprtk_override 17847 | { 17848 | static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result; 17849 | return result; 17850 | } 17851 | 17852 | inline T value() const exprtk_override 17853 | { 17854 | return SF4Operation::process(t0_, t1_, t2_, t3_); 17855 | } 17856 | 17857 | inline T0 t0() const 17858 | { 17859 | return t0_; 17860 | } 17861 | 17862 | inline T1 t1() const 17863 | { 17864 | return t1_; 17865 | } 17866 | 17867 | inline T2 t2() const 17868 | { 17869 | return t2_; 17870 | } 17871 | 17872 | inline T3 t3() const 17873 | { 17874 | return t3_; 17875 | } 17876 | 17877 | std::string type_id() const exprtk_override 17878 | { 17879 | return id(); 17880 | } 17881 | 17882 | static inline std::string id() 17883 | { 17884 | return SF4Operation::id(); 17885 | } 17886 | 17887 | template <typename Allocator> 17888 | static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, T3 p3) 17889 | { 17890 | return allocator 17891 | .template allocate_type<node_type, T0, T1, T2, T3> 17892 | (p0, p1, p2, p3); 17893 | } 17894 | 17895 | private: 17896 | 17897 | T0oT1oT2oT3_sf4ext(const node_type&) exprtk_delete; 17898 | node_type& operator=(const node_type&) exprtk_delete; 17899 | 17900 | T0 t0_; 17901 | T1 t1_; 17902 | T2 t2_; 17903 | T3 t3_; 17904 | }; 17905 | 17906 | template <typename T> 17907 | inline bool is_sf4ext_node(const expression_node<T>* n) 17908 | { 17909 | switch (n->type()) 17910 | { 17911 | case expression_node<T>::e_vovovov : return true; 17912 | case expression_node<T>::e_vovovoc : return true; 17913 | case expression_node<T>::e_vovocov : return true; 17914 | case expression_node<T>::e_vocovov : return true; 17915 | case expression_node<T>::e_covovov : return true; 17916 | case expression_node<T>::e_covocov : return true; 17917 | case expression_node<T>::e_vocovoc : return true; 17918 | case expression_node<T>::e_covovoc : return true; 17919 | case expression_node<T>::e_vococov : return true; 17920 | default : return false; 17921 | } 17922 | } 17923 | 17924 | template <typename T, typename T0, typename T1> 17925 | struct T0oT1_define 17926 | { 17927 | typedef details::T0oT1<T, T0, T1> type0; 17928 | }; 17929 | 17930 | template <typename T, typename T0, typename T1, typename T2> 17931 | struct T0oT1oT2_define 17932 | { 17933 | typedef details::T0oT1oT2<T, T0, T1, T2, typename T0oT1oT2process<T>::mode0> type0; 17934 | typedef details::T0oT1oT2<T, T0, T1, T2, typename T0oT1oT2process<T>::mode1> type1; 17935 | typedef details::T0oT1oT2_sf3<T, T0, T1, T2> sf3_type; 17936 | typedef details::sf3ext_type_node<T, T0, T1, T2> sf3_type_node; 17937 | }; 17938 | 17939 | template <typename T, typename T0, typename T1, typename T2, typename T3> 17940 | struct T0oT1oT2oT3_define 17941 | { 17942 | typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode0> type0; 17943 | typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode1> type1; 17944 | typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode2> type2; 17945 | typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode3> type3; 17946 | typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode4> type4; 17947 | typedef details::T0oT1oT2oT3_sf4<T, T0, T1, T2, T3> sf4_type; 17948 | }; 17949 | 17950 | template <typename T, typename Operation> 17951 | class vov_node exprtk_final : public vov_base_node<T> 17952 | { 17953 | public: 17954 | 17955 | typedef expression_node<T>* expression_ptr; 17956 | typedef Operation operation_t; 17957 | 17958 | // variable op variable node 17959 | explicit vov_node(const T& var0, const T& var1) 17960 | : v0_(var0) 17961 | , v1_(var1) 17962 | {} 17963 | 17964 | inline T value() const exprtk_override 17965 | { 17966 | return Operation::process(v0_,v1_); 17967 | } 17968 | 17969 | inline typename expression_node<T>::node_type type() const exprtk_override 17970 | { 17971 | return Operation::type(); 17972 | } 17973 | 17974 | inline operator_type operation() const exprtk_override 17975 | { 17976 | return Operation::operation(); 17977 | } 17978 | 17979 | inline const T& v0() const exprtk_override 17980 | { 17981 | return v0_; 17982 | } 17983 | 17984 | inline const T& v1() const exprtk_override 17985 | { 17986 | return v1_; 17987 | } 17988 | 17989 | protected: 17990 | 17991 | const T& v0_; 17992 | const T& v1_; 17993 | 17994 | private: 17995 | 17996 | vov_node(const vov_node<T,Operation>&) exprtk_delete; 17997 | vov_node<T,Operation>& operator=(const vov_node<T,Operation>&) exprtk_delete; 17998 | }; 17999 | 18000 | template <typename T, typename Operation> 18001 | class cov_node exprtk_final : public cov_base_node<T> 18002 | { 18003 | public: 18004 | 18005 | typedef expression_node<T>* expression_ptr; 18006 | typedef Operation operation_t; 18007 | 18008 | // constant op variable node 18009 | explicit cov_node(const T& const_var, const T& var) 18010 | : c_(const_var) 18011 | , v_(var) 18012 | {} 18013 | 18014 | inline T value() const exprtk_override 18015 | { 18016 | return Operation::process(c_,v_); 18017 | } 18018 | 18019 | inline typename expression_node<T>::node_type type() const exprtk_override 18020 | { 18021 | return Operation::type(); 18022 | } 18023 | 18024 | inline operator_type operation() const exprtk_override 18025 | { 18026 | return Operation::operation(); 18027 | } 18028 | 18029 | inline const T c() const exprtk_override 18030 | { 18031 | return c_; 18032 | } 18033 | 18034 | inline const T& v() const exprtk_override 18035 | { 18036 | return v_; 18037 | } 18038 | 18039 | protected: 18040 | 18041 | const T c_; 18042 | const T& v_; 18043 | 18044 | private: 18045 | 18046 | cov_node(const cov_node<T,Operation>&) exprtk_delete; 18047 | cov_node<T,Operation>& operator=(const cov_node<T,Operation>&) exprtk_delete; 18048 | }; 18049 | 18050 | template <typename T, typename Operation> 18051 | class voc_node exprtk_final : public voc_base_node<T> 18052 | { 18053 | public: 18054 | 18055 | typedef expression_node<T>* expression_ptr; 18056 | typedef Operation operation_t; 18057 | 18058 | // variable op constant node 18059 | explicit voc_node(const T& var, const T& const_var) 18060 | : v_(var) 18061 | , c_(const_var) 18062 | {} 18063 | 18064 | inline T value() const exprtk_override 18065 | { 18066 | return Operation::process(v_,c_); 18067 | } 18068 | 18069 | inline operator_type operation() const exprtk_override 18070 | { 18071 | return Operation::operation(); 18072 | } 18073 | 18074 | inline const T c() const exprtk_override 18075 | { 18076 | return c_; 18077 | } 18078 | 18079 | inline const T& v() const exprtk_override 18080 | { 18081 | return v_; 18082 | } 18083 | 18084 | protected: 18085 | 18086 | const T& v_; 18087 | const T c_; 18088 | 18089 | private: 18090 | 18091 | voc_node(const voc_node<T,Operation>&) exprtk_delete; 18092 | voc_node<T,Operation>& operator=(const voc_node<T,Operation>&) exprtk_delete; 18093 | }; 18094 | 18095 | template <typename T, typename Operation> 18096 | class vob_node exprtk_final : public vob_base_node<T> 18097 | { 18098 | public: 18099 | 18100 | typedef expression_node<T>* expression_ptr; 18101 | typedef std::pair<expression_ptr,bool> branch_t; 18102 | typedef Operation operation_t; 18103 | 18104 | // variable op binary node 18105 | explicit vob_node(const T& var, const expression_ptr branch) 18106 | : v_(var) 18107 | { 18108 | construct_branch_pair(branch_, branch); 18109 | assert(valid()); 18110 | } 18111 | 18112 | inline T value() const exprtk_override 18113 | { 18114 | return Operation::process(v_,branch_.first->value()); 18115 | } 18116 | 18117 | inline const T& v() const exprtk_override 18118 | { 18119 | return v_; 18120 | } 18121 | 18122 | inline bool valid() const exprtk_override 18123 | { 18124 | return branch_.first && branch_.first->valid(); 18125 | } 18126 | 18127 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 18128 | { 18129 | return branch_.first; 18130 | } 18131 | 18132 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 18133 | { 18134 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 18135 | } 18136 | 18137 | std::size_t node_depth() const exprtk_override 18138 | { 18139 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 18140 | } 18141 | 18142 | private: 18143 | 18144 | vob_node(const vob_node<T,Operation>&) exprtk_delete; 18145 | vob_node<T,Operation>& operator=(const vob_node<T,Operation>&) exprtk_delete; 18146 | 18147 | const T& v_; 18148 | branch_t branch_; 18149 | }; 18150 | 18151 | template <typename T, typename Operation> 18152 | class bov_node exprtk_final : public bov_base_node<T> 18153 | { 18154 | public: 18155 | 18156 | typedef expression_node<T>* expression_ptr; 18157 | typedef std::pair<expression_ptr,bool> branch_t; 18158 | typedef Operation operation_t; 18159 | 18160 | // binary node op variable node 18161 | explicit bov_node(const expression_ptr branch, const T& var) 18162 | : v_(var) 18163 | { 18164 | construct_branch_pair(branch_, branch); 18165 | assert(valid()); 18166 | } 18167 | 18168 | inline T value() const exprtk_override 18169 | { 18170 | return Operation::process(branch_.first->value(),v_); 18171 | } 18172 | 18173 | inline const T& v() const exprtk_override 18174 | { 18175 | return v_; 18176 | } 18177 | 18178 | inline bool valid() const exprtk_override 18179 | { 18180 | return branch_.first && branch_.first->valid(); 18181 | } 18182 | 18183 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 18184 | { 18185 | return branch_.first; 18186 | } 18187 | 18188 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 18189 | { 18190 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 18191 | } 18192 | 18193 | std::size_t node_depth() const exprtk_override 18194 | { 18195 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 18196 | } 18197 | 18198 | private: 18199 | 18200 | bov_node(const bov_node<T,Operation>&) exprtk_delete; 18201 | bov_node<T,Operation>& operator=(const bov_node<T,Operation>&) exprtk_delete; 18202 | 18203 | const T& v_; 18204 | branch_t branch_; 18205 | }; 18206 | 18207 | template <typename T, typename Operation> 18208 | class cob_node exprtk_final : public cob_base_node<T> 18209 | { 18210 | public: 18211 | 18212 | typedef expression_node<T>* expression_ptr; 18213 | typedef std::pair<expression_ptr,bool> branch_t; 18214 | typedef Operation operation_t; 18215 | 18216 | // constant op variable node 18217 | explicit cob_node(const T const_var, const expression_ptr branch) 18218 | : c_(const_var) 18219 | { 18220 | construct_branch_pair(branch_, branch); 18221 | assert(valid()); 18222 | } 18223 | 18224 | inline T value() const exprtk_override 18225 | { 18226 | return Operation::process(c_,branch_.first->value()); 18227 | } 18228 | 18229 | inline operator_type operation() const exprtk_override 18230 | { 18231 | return Operation::operation(); 18232 | } 18233 | 18234 | inline const T c() const exprtk_override 18235 | { 18236 | return c_; 18237 | } 18238 | 18239 | inline void set_c(const T new_c) exprtk_override 18240 | { 18241 | (*const_cast<T*>(&c_)) = new_c; 18242 | } 18243 | 18244 | inline bool valid() const exprtk_override 18245 | { 18246 | return branch_.first && branch_.first->valid(); 18247 | } 18248 | 18249 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 18250 | { 18251 | return branch_.first; 18252 | } 18253 | 18254 | inline expression_node<T>* move_branch(const std::size_t&) exprtk_override 18255 | { 18256 | branch_.second = false; 18257 | return branch_.first; 18258 | } 18259 | 18260 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 18261 | { 18262 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 18263 | } 18264 | 18265 | std::size_t node_depth() const exprtk_override 18266 | { 18267 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 18268 | } 18269 | 18270 | private: 18271 | 18272 | cob_node(const cob_node<T,Operation>&) exprtk_delete; 18273 | cob_node<T,Operation>& operator=(const cob_node<T,Operation>&) exprtk_delete; 18274 | 18275 | const T c_; 18276 | branch_t branch_; 18277 | }; 18278 | 18279 | template <typename T, typename Operation> 18280 | class boc_node exprtk_final : public boc_base_node<T> 18281 | { 18282 | public: 18283 | 18284 | typedef expression_node<T>* expression_ptr; 18285 | typedef std::pair<expression_ptr,bool> branch_t; 18286 | typedef Operation operation_t; 18287 | 18288 | // binary node op constant node 18289 | explicit boc_node(const expression_ptr branch, const T const_var) 18290 | : c_(const_var) 18291 | { 18292 | construct_branch_pair(branch_, branch); 18293 | assert(valid()); 18294 | } 18295 | 18296 | inline T value() const exprtk_override 18297 | { 18298 | return Operation::process(branch_.first->value(),c_); 18299 | } 18300 | 18301 | inline operator_type operation() const exprtk_override 18302 | { 18303 | return Operation::operation(); 18304 | } 18305 | 18306 | inline const T c() const exprtk_override 18307 | { 18308 | return c_; 18309 | } 18310 | 18311 | inline void set_c(const T new_c) exprtk_override 18312 | { 18313 | (*const_cast<T*>(&c_)) = new_c; 18314 | } 18315 | 18316 | inline bool valid() const exprtk_override 18317 | { 18318 | return branch_.first && branch_.first->valid(); 18319 | } 18320 | 18321 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 18322 | { 18323 | return branch_.first; 18324 | } 18325 | 18326 | inline expression_node<T>* move_branch(const std::size_t&) exprtk_override 18327 | { 18328 | branch_.second = false; 18329 | return branch_.first; 18330 | } 18331 | 18332 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 18333 | { 18334 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 18335 | } 18336 | 18337 | std::size_t node_depth() const exprtk_override 18338 | { 18339 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 18340 | } 18341 | 18342 | private: 18343 | 18344 | boc_node(const boc_node<T,Operation>&) exprtk_delete; 18345 | boc_node<T,Operation>& operator=(const boc_node<T,Operation>&) exprtk_delete; 18346 | 18347 | const T c_; 18348 | branch_t branch_; 18349 | }; 18350 | 18351 | #ifndef exprtk_disable_string_capabilities 18352 | template <typename T, typename SType0, typename SType1, typename Operation> 18353 | class sos_node exprtk_final : public sos_base_node<T> 18354 | { 18355 | public: 18356 | 18357 | typedef expression_node<T>* expression_ptr; 18358 | typedef Operation operation_t; 18359 | 18360 | // string op string node 18361 | explicit sos_node(SType0 p0, SType1 p1) 18362 | : s0_(p0) 18363 | , s1_(p1) 18364 | {} 18365 | 18366 | inline T value() const exprtk_override 18367 | { 18368 | return Operation::process(s0_,s1_); 18369 | } 18370 | 18371 | inline typename expression_node<T>::node_type type() const exprtk_override 18372 | { 18373 | return Operation::type(); 18374 | } 18375 | 18376 | inline operator_type operation() const exprtk_override 18377 | { 18378 | return Operation::operation(); 18379 | } 18380 | 18381 | inline std::string& s0() 18382 | { 18383 | return s0_; 18384 | } 18385 | 18386 | inline std::string& s1() 18387 | { 18388 | return s1_; 18389 | } 18390 | 18391 | protected: 18392 | 18393 | SType0 s0_; 18394 | SType1 s1_; 18395 | 18396 | private: 18397 | 18398 | sos_node(const sos_node<T,SType0,SType1,Operation>&) exprtk_delete; 18399 | sos_node<T,SType0,SType1,Operation>& operator=(const sos_node<T,SType0,SType1,Operation>&) exprtk_delete; 18400 | }; 18401 | 18402 | template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation> 18403 | class str_xrox_node exprtk_final : public sos_base_node<T> 18404 | { 18405 | public: 18406 | 18407 | typedef expression_node<T>* expression_ptr; 18408 | typedef Operation operation_t; 18409 | typedef str_xrox_node<T,SType0,SType1,RangePack,Operation> node_type; 18410 | 18411 | // string-range op string node 18412 | explicit str_xrox_node(SType0 p0, SType1 p1, RangePack rp0) 18413 | : s0_ (p0 ) 18414 | , s1_ (p1 ) 18415 | , rp0_(rp0) 18416 | {} 18417 | 18418 | ~str_xrox_node() exprtk_override 18419 | { 18420 | rp0_.free(); 18421 | } 18422 | 18423 | inline T value() const exprtk_override 18424 | { 18425 | std::size_t r0 = 0; 18426 | std::size_t r1 = 0; 18427 | 18428 | if (rp0_(r0, r1, s0_.size())) 18429 | return Operation::process(s0_.substr(r0, (r1 - r0) + 1), s1_); 18430 | else 18431 | return T(0); 18432 | } 18433 | 18434 | inline typename expression_node<T>::node_type type() const exprtk_override 18435 | { 18436 | return Operation::type(); 18437 | } 18438 | 18439 | inline operator_type operation() const exprtk_override 18440 | { 18441 | return Operation::operation(); 18442 | } 18443 | 18444 | inline std::string& s0() 18445 | { 18446 | return s0_; 18447 | } 18448 | 18449 | inline std::string& s1() 18450 | { 18451 | return s1_; 18452 | } 18453 | 18454 | protected: 18455 | 18456 | SType0 s0_; 18457 | SType1 s1_; 18458 | RangePack rp0_; 18459 | 18460 | private: 18461 | 18462 | str_xrox_node(const node_type&) exprtk_delete; 18463 | node_type& operator=(const node_type&) exprtk_delete; 18464 | }; 18465 | 18466 | template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation> 18467 | class str_xoxr_node exprtk_final : public sos_base_node<T> 18468 | { 18469 | public: 18470 | 18471 | typedef expression_node<T>* expression_ptr; 18472 | typedef Operation operation_t; 18473 | typedef str_xoxr_node<T,SType0,SType1,RangePack,Operation> node_type; 18474 | 18475 | // string op string range node 18476 | explicit str_xoxr_node(SType0 p0, SType1 p1, RangePack rp1) 18477 | : s0_ (p0 ) 18478 | , s1_ (p1 ) 18479 | , rp1_(rp1) 18480 | {} 18481 | 18482 | ~str_xoxr_node() 18483 | { 18484 | rp1_.free(); 18485 | } 18486 | 18487 | inline T value() const exprtk_override 18488 | { 18489 | std::size_t r0 = 0; 18490 | std::size_t r1 = 0; 18491 | 18492 | if (rp1_(r0, r1, s1_.size())) 18493 | { 18494 | return Operation::process 18495 | ( 18496 | s0_, 18497 | s1_.substr(r0, (r1 - r0) + 1) 18498 | ); 18499 | } 18500 | else 18501 | return T(0); 18502 | } 18503 | 18504 | inline typename expression_node<T>::node_type type() const exprtk_override 18505 | { 18506 | return Operation::type(); 18507 | } 18508 | 18509 | inline operator_type operation() const exprtk_override 18510 | { 18511 | return Operation::operation(); 18512 | } 18513 | 18514 | inline std::string& s0() 18515 | { 18516 | return s0_; 18517 | } 18518 | 18519 | inline std::string& s1() 18520 | { 18521 | return s1_; 18522 | } 18523 | 18524 | protected: 18525 | 18526 | SType0 s0_; 18527 | SType1 s1_; 18528 | RangePack rp1_; 18529 | 18530 | private: 18531 | 18532 | str_xoxr_node(const node_type&) exprtk_delete; 18533 | node_type& operator=(const node_type&) exprtk_delete; 18534 | }; 18535 | 18536 | template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation> 18537 | class str_xroxr_node exprtk_final : public sos_base_node<T> 18538 | { 18539 | public: 18540 | 18541 | typedef expression_node<T>* expression_ptr; 18542 | typedef Operation operation_t; 18543 | typedef str_xroxr_node<T,SType0,SType1,RangePack,Operation> node_type; 18544 | 18545 | // string-range op string-range node 18546 | explicit str_xroxr_node(SType0 p0, SType1 p1, RangePack rp0, RangePack rp1) 18547 | : s0_ (p0 ) 18548 | , s1_ (p1 ) 18549 | , rp0_(rp0) 18550 | , rp1_(rp1) 18551 | {} 18552 | 18553 | ~str_xroxr_node() exprtk_override 18554 | { 18555 | rp0_.free(); 18556 | rp1_.free(); 18557 | } 18558 | 18559 | inline T value() const exprtk_override 18560 | { 18561 | std::size_t r0_0 = 0; 18562 | std::size_t r0_1 = 0; 18563 | std::size_t r1_0 = 0; 18564 | std::size_t r1_1 = 0; 18565 | 18566 | if ( 18567 | rp0_(r0_0, r1_0, s0_.size()) && 18568 | rp1_(r0_1, r1_1, s1_.size()) 18569 | ) 18570 | { 18571 | return Operation::process 18572 | ( 18573 | s0_.substr(r0_0, (r1_0 - r0_0) + 1), 18574 | s1_.substr(r0_1, (r1_1 - r0_1) + 1) 18575 | ); 18576 | } 18577 | else 18578 | return T(0); 18579 | } 18580 | 18581 | inline typename expression_node<T>::node_type type() const exprtk_override 18582 | { 18583 | return Operation::type(); 18584 | } 18585 | 18586 | inline operator_type operation() const exprtk_override 18587 | { 18588 | return Operation::operation(); 18589 | } 18590 | 18591 | inline std::string& s0() 18592 | { 18593 | return s0_; 18594 | } 18595 | 18596 | inline std::string& s1() 18597 | { 18598 | return s1_; 18599 | } 18600 | 18601 | protected: 18602 | 18603 | SType0 s0_; 18604 | SType1 s1_; 18605 | RangePack rp0_; 18606 | RangePack rp1_; 18607 | 18608 | private: 18609 | 18610 | str_xroxr_node(const node_type&) exprtk_delete; 18611 | node_type& operator=(const node_type&) exprtk_delete; 18612 | }; 18613 | 18614 | template <typename T, typename Operation> 18615 | class str_sogens_node exprtk_final : public binary_node<T> 18616 | { 18617 | public: 18618 | 18619 | typedef expression_node <T>* expression_ptr; 18620 | typedef string_base_node<T>* str_base_ptr; 18621 | typedef range_pack <T> range_t; 18622 | typedef range_t* range_ptr; 18623 | typedef range_interface <T> irange_t; 18624 | typedef irange_t* irange_ptr; 18625 | 18626 | using binary_node<T>::branch; 18627 | 18628 | str_sogens_node(const operator_type& opr, 18629 | expression_ptr branch0, 18630 | expression_ptr branch1) 18631 | : binary_node<T>(opr, branch0, branch1) 18632 | , str0_base_ptr_ (0) 18633 | , str1_base_ptr_ (0) 18634 | , str0_range_ptr_(0) 18635 | , str1_range_ptr_(0) 18636 | , initialised_ (false) 18637 | { 18638 | if (is_generally_string_node(branch(0))) 18639 | { 18640 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0)); 18641 | 18642 | if (0 == str0_base_ptr_) 18643 | return; 18644 | 18645 | irange_ptr range = dynamic_cast<irange_ptr>(branch(0)); 18646 | 18647 | if (0 == range) 18648 | return; 18649 | 18650 | str0_range_ptr_ = &(range->range_ref()); 18651 | } 18652 | 18653 | if (is_generally_string_node(branch(1))) 18654 | { 18655 | str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1)); 18656 | 18657 | if (0 == str1_base_ptr_) 18658 | return; 18659 | 18660 | irange_ptr range = dynamic_cast<irange_ptr>(branch(1)); 18661 | 18662 | if (0 == range) 18663 | return; 18664 | 18665 | str1_range_ptr_ = &(range->range_ref()); 18666 | } 18667 | 18668 | initialised_ = 18669 | str0_base_ptr_ && 18670 | str1_base_ptr_ && 18671 | str0_range_ptr_ && 18672 | str1_range_ptr_; 18673 | 18674 | assert(valid()); 18675 | } 18676 | 18677 | inline T value() const exprtk_override 18678 | { 18679 | branch(0)->value(); 18680 | branch(1)->value(); 18681 | 18682 | std::size_t str0_r0 = 0; 18683 | std::size_t str0_r1 = 0; 18684 | 18685 | std::size_t str1_r0 = 0; 18686 | std::size_t str1_r1 = 0; 18687 | 18688 | const range_t& range0 = (*str0_range_ptr_); 18689 | const range_t& range1 = (*str1_range_ptr_); 18690 | 18691 | if ( 18692 | range0(str0_r0, str0_r1, str0_base_ptr_->size()) && 18693 | range1(str1_r0, str1_r1, str1_base_ptr_->size()) 18694 | ) 18695 | { 18696 | return Operation::process 18697 | ( 18698 | str0_base_ptr_->str().substr(str0_r0,(str0_r1 - str0_r0)), 18699 | str1_base_ptr_->str().substr(str1_r0,(str1_r1 - str1_r0)) 18700 | ); 18701 | } 18702 | 18703 | return std::numeric_limits<T>::quiet_NaN(); 18704 | } 18705 | 18706 | inline typename expression_node<T>::node_type type() const exprtk_override 18707 | { 18708 | return Operation::type(); 18709 | } 18710 | 18711 | inline bool valid() const exprtk_override 18712 | { 18713 | return initialised_; 18714 | } 18715 | 18716 | private: 18717 | 18718 | str_sogens_node(const str_sogens_node<T,Operation>&) exprtk_delete; 18719 | str_sogens_node<T,Operation>& operator=(const str_sogens_node<T,Operation>&) exprtk_delete; 18720 | 18721 | str_base_ptr str0_base_ptr_; 18722 | str_base_ptr str1_base_ptr_; 18723 | range_ptr str0_range_ptr_; 18724 | range_ptr str1_range_ptr_; 18725 | bool initialised_; 18726 | }; 18727 | 18728 | template <typename T, typename SType0, typename SType1, typename SType2, typename Operation> 18729 | class sosos_node exprtk_final : public sosos_base_node<T> 18730 | { 18731 | public: 18732 | 18733 | typedef expression_node<T>* expression_ptr; 18734 | typedef Operation operation_t; 18735 | typedef sosos_node<T, SType0, SType1, SType2, Operation> node_type; 18736 | 18737 | // string op string op string node 18738 | explicit sosos_node(SType0 p0, SType1 p1, SType2 p2) 18739 | : s0_(p0) 18740 | , s1_(p1) 18741 | , s2_(p2) 18742 | {} 18743 | 18744 | inline T value() const exprtk_override 18745 | { 18746 | return Operation::process(s0_, s1_, s2_); 18747 | } 18748 | 18749 | inline typename expression_node<T>::node_type type() const exprtk_override 18750 | { 18751 | return Operation::type(); 18752 | } 18753 | 18754 | inline operator_type operation() const exprtk_override 18755 | { 18756 | return Operation::operation(); 18757 | } 18758 | 18759 | inline std::string& s0() 18760 | { 18761 | return s0_; 18762 | } 18763 | 18764 | inline std::string& s1() 18765 | { 18766 | return s1_; 18767 | } 18768 | 18769 | inline std::string& s2() 18770 | { 18771 | return s2_; 18772 | } 18773 | 18774 | protected: 18775 | 18776 | SType0 s0_; 18777 | SType1 s1_; 18778 | SType2 s2_; 18779 | 18780 | private: 18781 | 18782 | sosos_node(const node_type&) exprtk_delete; 18783 | node_type& operator=(const node_type&) exprtk_delete; 18784 | }; 18785 | #endif 18786 | 18787 | template <typename T, typename PowOp> 18788 | class ipow_node exprtk_final: public expression_node<T> 18789 | { 18790 | public: 18791 | 18792 | typedef expression_node<T>* expression_ptr; 18793 | typedef PowOp operation_t; 18794 | 18795 | explicit ipow_node(const T& v) 18796 | : v_(v) 18797 | {} 18798 | 18799 | inline T value() const exprtk_override 18800 | { 18801 | return PowOp::result(v_); 18802 | } 18803 | 18804 | inline typename expression_node<T>::node_type type() const exprtk_override 18805 | { 18806 | return expression_node<T>::e_ipow; 18807 | } 18808 | 18809 | private: 18810 | 18811 | ipow_node(const ipow_node<T,PowOp>&) exprtk_delete; 18812 | ipow_node<T,PowOp>& operator=(const ipow_node<T,PowOp>&) exprtk_delete; 18813 | 18814 | const T& v_; 18815 | }; 18816 | 18817 | template <typename T, typename PowOp> 18818 | class bipow_node exprtk_final : public expression_node<T> 18819 | { 18820 | public: 18821 | 18822 | typedef expression_node<T>* expression_ptr; 18823 | typedef std::pair<expression_ptr, bool> branch_t; 18824 | typedef PowOp operation_t; 18825 | 18826 | explicit bipow_node(expression_ptr branch) 18827 | { 18828 | construct_branch_pair(branch_, branch); 18829 | assert(valid()); 18830 | } 18831 | 18832 | inline T value() const exprtk_override 18833 | { 18834 | return PowOp::result(branch_.first->value()); 18835 | } 18836 | 18837 | inline typename expression_node<T>::node_type type() const exprtk_override 18838 | { 18839 | return expression_node<T>::e_ipow; 18840 | } 18841 | 18842 | inline bool valid() const exprtk_override 18843 | { 18844 | return branch_.first && branch_.first->valid(); 18845 | } 18846 | 18847 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 18848 | { 18849 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 18850 | } 18851 | 18852 | std::size_t node_depth() const exprtk_override 18853 | { 18854 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 18855 | } 18856 | 18857 | private: 18858 | 18859 | bipow_node(const bipow_node<T,PowOp>&) exprtk_delete; 18860 | bipow_node<T,PowOp>& operator=(const bipow_node<T,PowOp>&) exprtk_delete; 18861 | 18862 | branch_t branch_; 18863 | }; 18864 | 18865 | template <typename T, typename PowOp> 18866 | class ipowinv_node exprtk_final : public expression_node<T> 18867 | { 18868 | public: 18869 | 18870 | typedef expression_node<T>* expression_ptr; 18871 | typedef PowOp operation_t; 18872 | 18873 | explicit ipowinv_node(const T& v) 18874 | : v_(v) 18875 | {} 18876 | 18877 | inline T value() const exprtk_override 18878 | { 18879 | return (T(1) / PowOp::result(v_)); 18880 | } 18881 | 18882 | inline typename expression_node<T>::node_type type() const exprtk_override 18883 | { 18884 | return expression_node<T>::e_ipowinv; 18885 | } 18886 | 18887 | private: 18888 | 18889 | ipowinv_node(const ipowinv_node<T,PowOp>&) exprtk_delete; 18890 | ipowinv_node<T,PowOp>& operator=(const ipowinv_node<T,PowOp>&) exprtk_delete; 18891 | 18892 | const T& v_; 18893 | }; 18894 | 18895 | template <typename T, typename PowOp> 18896 | class bipowinv_node exprtk_final : public expression_node<T> 18897 | { 18898 | public: 18899 | 18900 | typedef expression_node<T>* expression_ptr; 18901 | typedef std::pair<expression_ptr, bool> branch_t; 18902 | typedef PowOp operation_t; 18903 | 18904 | explicit bipowinv_node(expression_ptr branch) 18905 | { 18906 | construct_branch_pair(branch_, branch); 18907 | assert(valid()); 18908 | } 18909 | 18910 | inline T value() const exprtk_override 18911 | { 18912 | return (T(1) / PowOp::result(branch_.first->value())); 18913 | } 18914 | 18915 | inline typename expression_node<T>::node_type type() const exprtk_override 18916 | { 18917 | return expression_node<T>::e_ipowinv; 18918 | } 18919 | 18920 | inline bool valid() const exprtk_override 18921 | { 18922 | return branch_.first && branch_.first->valid(); 18923 | } 18924 | 18925 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 18926 | { 18927 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 18928 | } 18929 | 18930 | std::size_t node_depth() const exprtk_override 18931 | { 18932 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 18933 | } 18934 | 18935 | private: 18936 | 18937 | bipowinv_node(const bipowinv_node<T,PowOp>&) exprtk_delete; 18938 | bipowinv_node<T,PowOp>& operator=(const bipowinv_node<T,PowOp>&) exprtk_delete; 18939 | 18940 | branch_t branch_; 18941 | }; 18942 | 18943 | template <typename T> 18944 | inline bool is_vov_node(const expression_node<T>* node) 18945 | { 18946 | return (0 != dynamic_cast<const vov_base_node<T>*>(node)); 18947 | } 18948 | 18949 | template <typename T> 18950 | inline bool is_cov_node(const expression_node<T>* node) 18951 | { 18952 | return (0 != dynamic_cast<const cov_base_node<T>*>(node)); 18953 | } 18954 | 18955 | template <typename T> 18956 | inline bool is_voc_node(const expression_node<T>* node) 18957 | { 18958 | return (0 != dynamic_cast<const voc_base_node<T>*>(node)); 18959 | } 18960 | 18961 | template <typename T> 18962 | inline bool is_cob_node(const expression_node<T>* node) 18963 | { 18964 | return (0 != dynamic_cast<const cob_base_node<T>*>(node)); 18965 | } 18966 | 18967 | template <typename T> 18968 | inline bool is_boc_node(const expression_node<T>* node) 18969 | { 18970 | return (0 != dynamic_cast<const boc_base_node<T>*>(node)); 18971 | } 18972 | 18973 | template <typename T> 18974 | inline bool is_t0ot1ot2_node(const expression_node<T>* node) 18975 | { 18976 | return (0 != dynamic_cast<const T0oT1oT2_base_node<T>*>(node)); 18977 | } 18978 | 18979 | template <typename T> 18980 | inline bool is_t0ot1ot2ot3_node(const expression_node<T>* node) 18981 | { 18982 | return (0 != dynamic_cast<const T0oT1oT2oT3_base_node<T>*>(node)); 18983 | } 18984 | 18985 | template <typename T> 18986 | inline bool is_uv_node(const expression_node<T>* node) 18987 | { 18988 | return (0 != dynamic_cast<const uv_base_node<T>*>(node)); 18989 | } 18990 | 18991 | template <typename T> 18992 | inline bool is_string_node(const expression_node<T>* node) 18993 | { 18994 | return node && (expression_node<T>::e_stringvar == node->type()); 18995 | } 18996 | 18997 | template <typename T> 18998 | inline bool is_string_range_node(const expression_node<T>* node) 18999 | { 19000 | return node && (expression_node<T>::e_stringvarrng == node->type()); 19001 | } 19002 | 19003 | template <typename T> 19004 | inline bool is_const_string_node(const expression_node<T>* node) 19005 | { 19006 | return node && (expression_node<T>::e_stringconst == node->type()); 19007 | } 19008 | 19009 | template <typename T> 19010 | inline bool is_const_string_range_node(const expression_node<T>* node) 19011 | { 19012 | return node && (expression_node<T>::e_cstringvarrng == node->type()); 19013 | } 19014 | 19015 | template <typename T> 19016 | inline bool is_string_assignment_node(const expression_node<T>* node) 19017 | { 19018 | return node && (expression_node<T>::e_strass == node->type()); 19019 | } 19020 | 19021 | template <typename T> 19022 | inline bool is_string_concat_node(const expression_node<T>* node) 19023 | { 19024 | return node && (expression_node<T>::e_strconcat == node->type()); 19025 | } 19026 | 19027 | template <typename T> 19028 | inline bool is_string_function_node(const expression_node<T>* node) 19029 | { 19030 | return node && (expression_node<T>::e_strfunction == node->type()); 19031 | } 19032 | 19033 | template <typename T> 19034 | inline bool is_string_condition_node(const expression_node<T>* node) 19035 | { 19036 | return node && (expression_node<T>::e_strcondition == node->type()); 19037 | } 19038 | 19039 | template <typename T> 19040 | inline bool is_string_ccondition_node(const expression_node<T>* node) 19041 | { 19042 | return node && (expression_node<T>::e_strccondition == node->type()); 19043 | } 19044 | 19045 | template <typename T> 19046 | inline bool is_string_vararg_node(const expression_node<T>* node) 19047 | { 19048 | return node && (expression_node<T>::e_stringvararg == node->type()); 19049 | } 19050 | 19051 | template <typename T> 19052 | inline bool is_genricstring_range_node(const expression_node<T>* node) 19053 | { 19054 | return node && (expression_node<T>::e_strgenrange == node->type()); 19055 | } 19056 | 19057 | template <typename T> 19058 | inline bool is_generally_string_node(const expression_node<T>* node) 19059 | { 19060 | if (node) 19061 | { 19062 | switch (node->type()) 19063 | { 19064 | case expression_node<T>::e_stringvar : 19065 | case expression_node<T>::e_stringconst : 19066 | case expression_node<T>::e_stringvarrng : 19067 | case expression_node<T>::e_cstringvarrng : 19068 | case expression_node<T>::e_strgenrange : 19069 | case expression_node<T>::e_strass : 19070 | case expression_node<T>::e_strconcat : 19071 | case expression_node<T>::e_strfunction : 19072 | case expression_node<T>::e_strcondition : 19073 | case expression_node<T>::e_strccondition : 19074 | case expression_node<T>::e_stringvararg : return true; 19075 | default : return false; 19076 | } 19077 | } 19078 | 19079 | return false; 19080 | } 19081 | 19082 | template <typename T> 19083 | inline bool is_loop_node(const expression_node<T>* node) 19084 | { 19085 | if (node) 19086 | { 19087 | switch (node->type()) 19088 | { 19089 | case expression_node<T>::e_for : 19090 | case expression_node<T>::e_repeat : 19091 | case expression_node<T>::e_while : return true; 19092 | default : return false; 19093 | } 19094 | } 19095 | 19096 | return false; 19097 | } 19098 | 19099 | template <typename T> 19100 | inline bool is_block_node(const expression_node<T>* node) 19101 | { 19102 | if (node) 19103 | { 19104 | if (is_loop_node(node)) 19105 | { 19106 | return true; 19107 | } 19108 | 19109 | switch (node->type()) 19110 | { 19111 | case expression_node<T>::e_conditional : 19112 | case expression_node<T>::e_mswitch : 19113 | case expression_node<T>::e_switch : 19114 | case expression_node<T>::e_vararg : return true; 19115 | default : return false; 19116 | } 19117 | } 19118 | 19119 | return false; 19120 | } 19121 | 19122 | class node_allocator 19123 | { 19124 | public: 19125 | 19126 | template <typename ResultNode, typename OpType, typename ExprNode> 19127 | inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[1]) 19128 | { 19129 | expression_node<typename ResultNode::value_type>* result = 19130 | allocate<ResultNode>(operation, branch[0]); 19131 | result->node_depth(); 19132 | return result; 19133 | } 19134 | 19135 | template <typename ResultNode, typename OpType, typename ExprNode> 19136 | inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[2]) 19137 | { 19138 | expression_node<typename ResultNode::value_type>* result = 19139 | allocate<ResultNode>(operation, branch[0], branch[1]); 19140 | result->node_depth(); 19141 | return result; 19142 | } 19143 | 19144 | template <typename ResultNode, typename OpType, typename ExprNode> 19145 | inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[3]) 19146 | { 19147 | expression_node<typename ResultNode::value_type>* result = 19148 | allocate<ResultNode>(operation, branch[0], branch[1], branch[2]); 19149 | result->node_depth(); 19150 | return result; 19151 | } 19152 | 19153 | template <typename ResultNode, typename OpType, typename ExprNode> 19154 | inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[4]) 19155 | { 19156 | expression_node<typename ResultNode::value_type>* result = 19157 | allocate<ResultNode>(operation, branch[0], branch[1], branch[2], branch[3]); 19158 | result->node_depth(); 19159 | return result; 19160 | } 19161 | 19162 | template <typename ResultNode, typename OpType, typename ExprNode> 19163 | inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[5]) 19164 | { 19165 | expression_node<typename ResultNode::value_type>* result = 19166 | allocate<ResultNode>(operation, branch[0],branch[1], branch[2], branch[3], branch[4]); 19167 | result->node_depth(); 19168 | return result; 19169 | } 19170 | 19171 | template <typename ResultNode, typename OpType, typename ExprNode> 19172 | inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[6]) 19173 | { 19174 | expression_node<typename ResultNode::value_type>* result = 19175 | allocate<ResultNode>(operation, branch[0], branch[1], branch[2], branch[3], branch[4], branch[5]); 19176 | result->node_depth(); 19177 | return result; 19178 | } 19179 | 19180 | template <typename node_type> 19181 | inline expression_node<typename node_type::value_type>* allocate() const 19182 | { 19183 | return (new node_type()); 19184 | } 19185 | 19186 | template <typename node_type, 19187 | typename Type, 19188 | typename Allocator, 19189 | template <typename, typename> class Sequence> 19190 | inline expression_node<typename node_type::value_type>* allocate(const Sequence<Type,Allocator>& seq) const 19191 | { 19192 | expression_node<typename node_type::value_type>* 19193 | result = (new node_type(seq)); 19194 | result->node_depth(); 19195 | return result; 19196 | } 19197 | 19198 | template <typename node_type, typename T1> 19199 | inline expression_node<typename node_type::value_type>* allocate(T1& t1) const 19200 | { 19201 | expression_node<typename node_type::value_type>* 19202 | result = (new node_type(t1)); 19203 | result->node_depth(); 19204 | return result; 19205 | } 19206 | 19207 | template <typename node_type, typename T1> 19208 | inline expression_node<typename node_type::value_type>* allocate_c(const T1& t1) const 19209 | { 19210 | expression_node<typename node_type::value_type>* 19211 | result = (new node_type(t1)); 19212 | result->node_depth(); 19213 | return result; 19214 | } 19215 | 19216 | template <typename node_type, 19217 | typename T1, typename T2> 19218 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2) const 19219 | { 19220 | expression_node<typename node_type::value_type>* 19221 | result = (new node_type(t1, t2)); 19222 | result->node_depth(); 19223 | return result; 19224 | } 19225 | 19226 | template <typename node_type, 19227 | typename T1, typename T2> 19228 | inline expression_node<typename node_type::value_type>* allocate_cr(const T1& t1, T2& t2) const 19229 | { 19230 | expression_node<typename node_type::value_type>* 19231 | result = (new node_type(t1, t2)); 19232 | result->node_depth(); 19233 | return result; 19234 | } 19235 | 19236 | template <typename node_type, 19237 | typename T1, typename T2> 19238 | inline expression_node<typename node_type::value_type>* allocate_rc(T1& t1, const T2& t2) const 19239 | { 19240 | expression_node<typename node_type::value_type>* 19241 | result = (new node_type(t1, t2)); 19242 | result->node_depth(); 19243 | return result; 19244 | } 19245 | 19246 | template <typename node_type, 19247 | typename T1, typename T2> 19248 | inline expression_node<typename node_type::value_type>* allocate_rr(T1& t1, T2& t2) const 19249 | { 19250 | expression_node<typename node_type::value_type>* 19251 | result = (new node_type(t1, t2)); 19252 | result->node_depth(); 19253 | return result; 19254 | } 19255 | 19256 | template <typename node_type, 19257 | typename T1, typename T2> 19258 | inline expression_node<typename node_type::value_type>* allocate_tt(T1 t1, T2 t2) const 19259 | { 19260 | expression_node<typename node_type::value_type>* 19261 | result = (new node_type(t1, t2)); 19262 | result->node_depth(); 19263 | return result; 19264 | } 19265 | 19266 | template <typename node_type, 19267 | typename T1, typename T2, typename T3> 19268 | inline expression_node<typename node_type::value_type>* allocate_ttt(T1 t1, T2 t2, T3 t3) const 19269 | { 19270 | expression_node<typename node_type::value_type>* 19271 | result = (new node_type(t1, t2, t3)); 19272 | result->node_depth(); 19273 | return result; 19274 | } 19275 | 19276 | template <typename node_type, 19277 | typename T1, typename T2, typename T3, typename T4> 19278 | inline expression_node<typename node_type::value_type>* allocate_tttt(T1 t1, T2 t2, T3 t3, T4 t4) const 19279 | { 19280 | expression_node<typename node_type::value_type>* 19281 | result = (new node_type(t1, t2, t3, t4)); 19282 | result->node_depth(); 19283 | return result; 19284 | } 19285 | 19286 | template <typename node_type, 19287 | typename T1, typename T2, typename T3> 19288 | inline expression_node<typename node_type::value_type>* allocate_rrr(T1& t1, T2& t2, T3& t3) const 19289 | { 19290 | expression_node<typename node_type::value_type>* 19291 | result = (new node_type(t1, t2, t3)); 19292 | result->node_depth(); 19293 | return result; 19294 | } 19295 | 19296 | template <typename node_type, 19297 | typename T1, typename T2, typename T3, typename T4> 19298 | inline expression_node<typename node_type::value_type>* allocate_rrrr(T1& t1, T2& t2, T3& t3, T4& t4) const 19299 | { 19300 | expression_node<typename node_type::value_type>* 19301 | result = (new node_type(t1, t2, t3, t4)); 19302 | result->node_depth(); 19303 | return result; 19304 | } 19305 | 19306 | template <typename node_type, 19307 | typename T1, typename T2, typename T3, typename T4, typename T5> 19308 | inline expression_node<typename node_type::value_type>* allocate_rrrrr(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5) const 19309 | { 19310 | expression_node<typename node_type::value_type>* 19311 | result = (new node_type(t1, t2, t3, t4, t5)); 19312 | result->node_depth(); 19313 | return result; 19314 | } 19315 | 19316 | template <typename node_type, 19317 | typename T1, typename T2, typename T3> 19318 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19319 | const T3& t3) const 19320 | { 19321 | expression_node<typename node_type::value_type>* 19322 | result = (new node_type(t1, t2, t3)); 19323 | result->node_depth(); 19324 | return result; 19325 | } 19326 | 19327 | template <typename node_type, 19328 | typename T1, typename T2, 19329 | typename T3, typename T4> 19330 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19331 | const T3& t3, const T4& t4) const 19332 | { 19333 | expression_node<typename node_type::value_type>* 19334 | result = (new node_type(t1, t2, t3, t4)); 19335 | result->node_depth(); 19336 | return result; 19337 | } 19338 | 19339 | template <typename node_type, 19340 | typename T1, typename T2, 19341 | typename T3, typename T4, typename T5> 19342 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19343 | const T3& t3, const T4& t4, 19344 | const T5& t5) const 19345 | { 19346 | expression_node<typename node_type::value_type>* 19347 | result = (new node_type(t1, t2, t3, t4, t5)); 19348 | result->node_depth(); 19349 | return result; 19350 | } 19351 | 19352 | template <typename node_type, 19353 | typename T1, typename T2, 19354 | typename T3, typename T4, typename T5, typename T6> 19355 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19356 | const T3& t3, const T4& t4, 19357 | const T5& t5, const T6& t6) const 19358 | { 19359 | expression_node<typename node_type::value_type>* 19360 | result = (new node_type(t1, t2, t3, t4, t5, t6)); 19361 | result->node_depth(); 19362 | return result; 19363 | } 19364 | 19365 | template <typename node_type, 19366 | typename T1, typename T2, 19367 | typename T3, typename T4, 19368 | typename T5, typename T6, typename T7> 19369 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19370 | const T3& t3, const T4& t4, 19371 | const T5& t5, const T6& t6, 19372 | const T7& t7) const 19373 | { 19374 | expression_node<typename node_type::value_type>* 19375 | result = (new node_type(t1, t2, t3, t4, t5, t6, t7)); 19376 | result->node_depth(); 19377 | return result; 19378 | } 19379 | 19380 | template <typename node_type, 19381 | typename T1, typename T2, 19382 | typename T3, typename T4, 19383 | typename T5, typename T6, 19384 | typename T7, typename T8> 19385 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19386 | const T3& t3, const T4& t4, 19387 | const T5& t5, const T6& t6, 19388 | const T7& t7, const T8& t8) const 19389 | { 19390 | expression_node<typename node_type::value_type>* 19391 | result = (new node_type(t1, t2, t3, t4, t5, t6, t7, t8)); 19392 | result->node_depth(); 19393 | return result; 19394 | } 19395 | 19396 | template <typename node_type, 19397 | typename T1, typename T2, 19398 | typename T3, typename T4, 19399 | typename T5, typename T6, 19400 | typename T7, typename T8, typename T9> 19401 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19402 | const T3& t3, const T4& t4, 19403 | const T5& t5, const T6& t6, 19404 | const T7& t7, const T8& t8, 19405 | const T9& t9) const 19406 | { 19407 | expression_node<typename node_type::value_type>* 19408 | result = (new node_type(t1, t2, t3, t4, t5, t6, t7, t8, t9)); 19409 | result->node_depth(); 19410 | return result; 19411 | } 19412 | 19413 | template <typename node_type, 19414 | typename T1, typename T2, 19415 | typename T3, typename T4, 19416 | typename T5, typename T6, 19417 | typename T7, typename T8, 19418 | typename T9, typename T10> 19419 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19420 | const T3& t3, const T4& t4, 19421 | const T5& t5, const T6& t6, 19422 | const T7& t7, const T8& t8, 19423 | const T9& t9, const T10& t10) const 19424 | { 19425 | expression_node<typename node_type::value_type>* 19426 | result = (new node_type(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10)); 19427 | result->node_depth(); 19428 | return result; 19429 | } 19430 | 19431 | template <typename node_type, 19432 | typename T1, typename T2, typename T3> 19433 | inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, T3 t3) const 19434 | { 19435 | expression_node<typename node_type::value_type>* 19436 | result = (new node_type(t1, t2, t3)); 19437 | result->node_depth(); 19438 | return result; 19439 | } 19440 | 19441 | template <typename node_type, 19442 | typename T1, typename T2, 19443 | typename T3, typename T4> 19444 | inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, 19445 | T3 t3, T4 t4) const 19446 | { 19447 | expression_node<typename node_type::value_type>* 19448 | result = (new node_type(t1, t2, t3, t4)); 19449 | result->node_depth(); 19450 | return result; 19451 | } 19452 | 19453 | template <typename node_type, 19454 | typename T1, typename T2, 19455 | typename T3, typename T4, 19456 | typename T5> 19457 | inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, 19458 | T3 t3, T4 t4, 19459 | T5 t5) const 19460 | { 19461 | expression_node<typename node_type::value_type>* 19462 | result = (new node_type(t1, t2, t3, t4, t5)); 19463 | result->node_depth(); 19464 | return result; 19465 | } 19466 | 19467 | template <typename node_type, 19468 | typename T1, typename T2, 19469 | typename T3, typename T4, 19470 | typename T5, typename T6> 19471 | inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, 19472 | T3 t3, T4 t4, 19473 | T5 t5, T6 t6) const 19474 | { 19475 | expression_node<typename node_type::value_type>* 19476 | result = (new node_type(t1, t2, t3, t4, t5, t6)); 19477 | result->node_depth(); 19478 | return result; 19479 | } 19480 | 19481 | template <typename node_type, 19482 | typename T1, typename T2, 19483 | typename T3, typename T4, 19484 | typename T5, typename T6, typename T7> 19485 | inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, 19486 | T3 t3, T4 t4, 19487 | T5 t5, T6 t6, 19488 | T7 t7) const 19489 | { 19490 | expression_node<typename node_type::value_type>* 19491 | result = (new node_type(t1, t2, t3, t4, t5, t6, t7)); 19492 | result->node_depth(); 19493 | return result; 19494 | } 19495 | 19496 | template <typename T> 19497 | void inline free(expression_node<T>*& e) const 19498 | { 19499 | exprtk_debug(("node_allocator::free() - deleting expression_node " 19500 | "type: %03d addr: %p\n", 19501 | static_cast<int>(e->type()), 19502 | reinterpret_cast<void*>(e))); 19503 | delete e; 19504 | e = 0; 19505 | } 19506 | }; 19507 | 19508 | inline void load_operations_map(std::multimap<std::string,details::base_operation_t,details::ilesscompare>& m) 19509 | { 19510 | #define register_op(Symbol, Type, Args) \ 19511 | m.insert(std::make_pair(std::string(Symbol),details::base_operation_t(Type,Args))); \ 19512 | 19513 | register_op("abs" , e_abs , 1) 19514 | register_op("acos" , e_acos , 1) 19515 | register_op("acosh" , e_acosh , 1) 19516 | register_op("asin" , e_asin , 1) 19517 | register_op("asinh" , e_asinh , 1) 19518 | register_op("atan" , e_atan , 1) 19519 | register_op("atanh" , e_atanh , 1) 19520 | register_op("ceil" , e_ceil , 1) 19521 | register_op("cos" , e_cos , 1) 19522 | register_op("cosh" , e_cosh , 1) 19523 | register_op("exp" , e_exp , 1) 19524 | register_op("expm1" , e_expm1 , 1) 19525 | register_op("floor" , e_floor , 1) 19526 | register_op("log" , e_log , 1) 19527 | register_op("log10" , e_log10 , 1) 19528 | register_op("log2" , e_log2 , 1) 19529 | register_op("log1p" , e_log1p , 1) 19530 | register_op("round" , e_round , 1) 19531 | register_op("sin" , e_sin , 1) 19532 | register_op("sinc" , e_sinc , 1) 19533 | register_op("sinh" , e_sinh , 1) 19534 | register_op("sec" , e_sec , 1) 19535 | register_op("csc" , e_csc , 1) 19536 | register_op("sqrt" , e_sqrt , 1) 19537 | register_op("tan" , e_tan , 1) 19538 | register_op("tanh" , e_tanh , 1) 19539 | register_op("cot" , e_cot , 1) 19540 | register_op("rad2deg" , e_r2d , 1) 19541 | register_op("deg2rad" , e_d2r , 1) 19542 | register_op("deg2grad" , e_d2g , 1) 19543 | register_op("grad2deg" , e_g2d , 1) 19544 | register_op("sgn" , e_sgn , 1) 19545 | register_op("not" , e_notl , 1) 19546 | register_op("erf" , e_erf , 1) 19547 | register_op("erfc" , e_erfc , 1) 19548 | register_op("ncdf" , e_ncdf , 1) 19549 | register_op("frac" , e_frac , 1) 19550 | register_op("trunc" , e_trunc , 1) 19551 | register_op("atan2" , e_atan2 , 2) 19552 | register_op("mod" , e_mod , 2) 19553 | register_op("logn" , e_logn , 2) 19554 | register_op("pow" , e_pow , 2) 19555 | register_op("root" , e_root , 2) 19556 | register_op("roundn" , e_roundn , 2) 19557 | register_op("equal" , e_equal , 2) 19558 | register_op("not_equal" , e_nequal , 2) 19559 | register_op("hypot" , e_hypot , 2) 19560 | register_op("shr" , e_shr , 2) 19561 | register_op("shl" , e_shl , 2) 19562 | register_op("clamp" , e_clamp , 3) 19563 | register_op("iclamp" , e_iclamp , 3) 19564 | register_op("inrange" , e_inrange , 3) 19565 | #undef register_op 19566 | } 19567 | 19568 | } // namespace details 19569 | 19570 | class function_traits 19571 | { 19572 | public: 19573 | 19574 | function_traits() 19575 | : allow_zero_parameters_(false) 19576 | , has_side_effects_(true) 19577 | , min_num_args_(0) 19578 | , max_num_args_(std::numeric_limits<std::size_t>::max()) 19579 | {} 19580 | 19581 | inline bool& allow_zero_parameters() 19582 | { 19583 | return allow_zero_parameters_; 19584 | } 19585 | 19586 | inline bool& has_side_effects() 19587 | { 19588 | return has_side_effects_; 19589 | } 19590 | 19591 | std::size_t& min_num_args() 19592 | { 19593 | return min_num_args_; 19594 | } 19595 | 19596 | std::size_t& max_num_args() 19597 | { 19598 | return max_num_args_; 19599 | } 19600 | 19601 | private: 19602 | 19603 | bool allow_zero_parameters_; 19604 | bool has_side_effects_; 19605 | std::size_t min_num_args_; 19606 | std::size_t max_num_args_; 19607 | }; 19608 | 19609 | template <typename FunctionType> 19610 | void enable_zero_parameters(FunctionType& func) 19611 | { 19612 | func.allow_zero_parameters() = true; 19613 | 19614 | if (0 != func.min_num_args()) 19615 | { 19616 | func.min_num_args() = 0; 19617 | } 19618 | } 19619 | 19620 | template <typename FunctionType> 19621 | void disable_zero_parameters(FunctionType& func) 19622 | { 19623 | func.allow_zero_parameters() = false; 19624 | } 19625 | 19626 | template <typename FunctionType> 19627 | void enable_has_side_effects(FunctionType& func) 19628 | { 19629 | func.has_side_effects() = true; 19630 | } 19631 | 19632 | template <typename FunctionType> 19633 | void disable_has_side_effects(FunctionType& func) 19634 | { 19635 | func.has_side_effects() = false; 19636 | } 19637 | 19638 | template <typename FunctionType> 19639 | void set_min_num_args(FunctionType& func, const std::size_t& num_args) 19640 | { 19641 | func.min_num_args() = num_args; 19642 | 19643 | if ((0 != func.min_num_args()) && func.allow_zero_parameters()) 19644 | func.allow_zero_parameters() = false; 19645 | } 19646 | 19647 | template <typename FunctionType> 19648 | void set_max_num_args(FunctionType& func, const std::size_t& num_args) 19649 | { 19650 | func.max_num_args() = num_args; 19651 | } 19652 | 19653 | template <typename T> 19654 | class ifunction : public function_traits 19655 | { 19656 | public: 19657 | 19658 | explicit ifunction(const std::size_t& pc) 19659 | : param_count(pc) 19660 | {} 19661 | 19662 | virtual ~ifunction() 19663 | {} 19664 | 19665 | #define empty_method_body(N) \ 19666 | { \ 19667 | exprtk_debug(("ifunction::operator() - Operator(" #N ") has not been overridden\n")); \ 19668 | return std::numeric_limits<T>::quiet_NaN(); \ 19669 | } \ 19670 | 19671 | inline virtual T operator() () 19672 | empty_method_body(0) 19673 | 19674 | inline virtual T operator() (const T&) 19675 | empty_method_body(1) 19676 | 19677 | inline virtual T operator() (const T&,const T&) 19678 | empty_method_body(2) 19679 | 19680 | inline virtual T operator() (const T&, const T&, const T&) 19681 | empty_method_body(3) 19682 | 19683 | inline virtual T operator() (const T&, const T&, const T&, const T&) 19684 | empty_method_body(4) 19685 | 19686 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&) 19687 | empty_method_body(5) 19688 | 19689 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&) 19690 | empty_method_body(6) 19691 | 19692 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19693 | empty_method_body(7) 19694 | 19695 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19696 | empty_method_body(8) 19697 | 19698 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19699 | empty_method_body(9) 19700 | 19701 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19702 | empty_method_body(10) 19703 | 19704 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19705 | const T&) 19706 | empty_method_body(11) 19707 | 19708 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19709 | const T&, const T&) 19710 | empty_method_body(12) 19711 | 19712 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19713 | const T&, const T&, const T&) 19714 | empty_method_body(13) 19715 | 19716 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19717 | const T&, const T&, const T&, const T&) 19718 | empty_method_body(14) 19719 | 19720 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19721 | const T&, const T&, const T&, const T&, const T&) 19722 | empty_method_body(15) 19723 | 19724 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19725 | const T&, const T&, const T&, const T&, const T&, const T&) 19726 | empty_method_body(16) 19727 | 19728 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19729 | const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19730 | empty_method_body(17) 19731 | 19732 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19733 | const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19734 | empty_method_body(18) 19735 | 19736 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19737 | const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19738 | empty_method_body(19) 19739 | 19740 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19741 | const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19742 | empty_method_body(20) 19743 | 19744 | #undef empty_method_body 19745 | 19746 | std::size_t param_count; 19747 | }; 19748 | 19749 | template <typename T> 19750 | class ivararg_function : public function_traits 19751 | { 19752 | public: 19753 | 19754 | virtual ~ivararg_function() 19755 | {} 19756 | 19757 | inline virtual T operator() (const std::vector<T>&) 19758 | { 19759 | exprtk_debug(("ivararg_function::operator() - Operator has not been overridden\n")); 19760 | return std::numeric_limits<T>::quiet_NaN(); 19761 | } 19762 | }; 19763 | 19764 | template <typename T> 19765 | class igeneric_function : public function_traits 19766 | { 19767 | public: 19768 | 19769 | enum return_type 19770 | { 19771 | e_rtrn_scalar = 0, 19772 | e_rtrn_string = 1, 19773 | e_rtrn_overload = 2 19774 | }; 19775 | 19776 | typedef T type; 19777 | typedef type_store<T> generic_type; 19778 | typedef typename generic_type::parameter_list parameter_list_t; 19779 | 19780 | explicit igeneric_function(const std::string& param_seq = "", const return_type rtr_type = e_rtrn_scalar) 19781 | : parameter_sequence(param_seq) 19782 | , rtrn_type(rtr_type) 19783 | {} 19784 | 19785 | virtual ~igeneric_function() 19786 | {} 19787 | 19788 | #define igeneric_function_empty_body(N) \ 19789 | { \ 19790 | exprtk_debug(("igeneric_function::operator() - Operator(" #N ") has not been overridden\n")); \ 19791 | return std::numeric_limits<T>::quiet_NaN(); \ 19792 | } \ 19793 | 19794 | // f(i_0,i_1,....,i_N) --> Scalar 19795 | inline virtual T operator() (parameter_list_t) 19796 | igeneric_function_empty_body(1) 19797 | 19798 | // f(i_0,i_1,....,i_N) --> String 19799 | inline virtual T operator() (std::string&, parameter_list_t) 19800 | igeneric_function_empty_body(2) 19801 | 19802 | // f(psi,i_0,i_1,....,i_N) --> Scalar 19803 | inline virtual T operator() (const std::size_t&, parameter_list_t) 19804 | igeneric_function_empty_body(3) 19805 | 19806 | // f(psi,i_0,i_1,....,i_N) --> String 19807 | inline virtual T operator() (const std::size_t&, std::string&, parameter_list_t) 19808 | igeneric_function_empty_body(4) 19809 | 19810 | #undef igeneric_function_empty_body 19811 | 19812 | std::string parameter_sequence; 19813 | return_type rtrn_type; 19814 | }; 19815 | 19816 | #ifndef exprtk_disable_string_capabilities 19817 | template <typename T> 19818 | class stringvar_base 19819 | { 19820 | public: 19821 | 19822 | typedef typename details::stringvar_node<T> stringvar_node_t; 19823 | 19824 | stringvar_base(const std::string& name, stringvar_node_t* svn) 19825 | : name_(name) 19826 | , string_varnode_(svn) 19827 | {} 19828 | 19829 | bool valid() const 19830 | { 19831 | return !name_.empty() && (0 != string_varnode_); 19832 | } 19833 | 19834 | std::string name() const 19835 | { 19836 | assert(string_varnode_); 19837 | return name_; 19838 | } 19839 | 19840 | void rebase(std::string& s) 19841 | { 19842 | assert(string_varnode_); 19843 | string_varnode_->rebase(s); 19844 | } 19845 | 19846 | private: 19847 | 19848 | std::string name_; 19849 | stringvar_node_t* string_varnode_; 19850 | }; 19851 | #endif 19852 | 19853 | template <typename T> class parser; 19854 | template <typename T> class expression_helper; 19855 | 19856 | template <typename T> 19857 | class symbol_table 19858 | { 19859 | public: 19860 | 19861 | enum symtab_mutability_type 19862 | { 19863 | e_unknown = 0, 19864 | e_mutable = 1, 19865 | e_immutable = 2 19866 | }; 19867 | 19868 | typedef T (*ff00_functor)(); 19869 | typedef T (*ff01_functor)(T); 19870 | typedef T (*ff02_functor)(T, T); 19871 | typedef T (*ff03_functor)(T, T, T); 19872 | typedef T (*ff04_functor)(T, T, T, T); 19873 | typedef T (*ff05_functor)(T, T, T, T, T); 19874 | typedef T (*ff06_functor)(T, T, T, T, T, T); 19875 | typedef T (*ff07_functor)(T, T, T, T, T, T, T); 19876 | typedef T (*ff08_functor)(T, T, T, T, T, T, T, T); 19877 | typedef T (*ff09_functor)(T, T, T, T, T, T, T, T, T); 19878 | typedef T (*ff10_functor)(T, T, T, T, T, T, T, T, T, T); 19879 | typedef T (*ff11_functor)(T, T, T, T, T, T, T, T, T, T, T); 19880 | typedef T (*ff12_functor)(T, T, T, T, T, T, T, T, T, T, T, T); 19881 | typedef T (*ff13_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T); 19882 | typedef T (*ff14_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T); 19883 | typedef T (*ff15_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T, T); 19884 | 19885 | protected: 19886 | 19887 | struct freefunc00 exprtk_final : public exprtk::ifunction<T> 19888 | { 19889 | using exprtk::ifunction<T>::operator(); 19890 | 19891 | explicit freefunc00(ff00_functor ff) : exprtk::ifunction<T>(0), f(ff) {} 19892 | inline T operator() () exprtk_override 19893 | { return f(); } 19894 | ff00_functor f; 19895 | }; 19896 | 19897 | struct freefunc01 exprtk_final : public exprtk::ifunction<T> 19898 | { 19899 | using exprtk::ifunction<T>::operator(); 19900 | 19901 | explicit freefunc01(ff01_functor ff) : exprtk::ifunction<T>(1), f(ff) {} 19902 | inline T operator() (const T& v0) exprtk_override 19903 | { return f(v0); } 19904 | ff01_functor f; 19905 | }; 19906 | 19907 | struct freefunc02 exprtk_final : public exprtk::ifunction<T> 19908 | { 19909 | using exprtk::ifunction<T>::operator(); 19910 | 19911 | explicit freefunc02(ff02_functor ff) : exprtk::ifunction<T>(2), f(ff) {} 19912 | inline T operator() (const T& v0, const T& v1) exprtk_override 19913 | { return f(v0, v1); } 19914 | ff02_functor f; 19915 | }; 19916 | 19917 | struct freefunc03 exprtk_final : public exprtk::ifunction<T> 19918 | { 19919 | using exprtk::ifunction<T>::operator(); 19920 | 19921 | explicit freefunc03(ff03_functor ff) : exprtk::ifunction<T>(3), f(ff) {} 19922 | inline T operator() (const T& v0, const T& v1, const T& v2) exprtk_override 19923 | { return f(v0, v1, v2); } 19924 | ff03_functor f; 19925 | }; 19926 | 19927 | struct freefunc04 exprtk_final : public exprtk::ifunction<T> 19928 | { 19929 | using exprtk::ifunction<T>::operator(); 19930 | 19931 | explicit freefunc04(ff04_functor ff) : exprtk::ifunction<T>(4), f(ff) {} 19932 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3) exprtk_override 19933 | { return f(v0, v1, v2, v3); } 19934 | ff04_functor f; 19935 | }; 19936 | 19937 | struct freefunc05 : public exprtk::ifunction<T> 19938 | { 19939 | using exprtk::ifunction<T>::operator(); 19940 | 19941 | explicit freefunc05(ff05_functor ff) : exprtk::ifunction<T>(5), f(ff) {} 19942 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4) exprtk_override 19943 | { return f(v0, v1, v2, v3, v4); } 19944 | ff05_functor f; 19945 | }; 19946 | 19947 | struct freefunc06 exprtk_final : public exprtk::ifunction<T> 19948 | { 19949 | using exprtk::ifunction<T>::operator(); 19950 | 19951 | explicit freefunc06(ff06_functor ff) : exprtk::ifunction<T>(6), f(ff) {} 19952 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5) exprtk_override 19953 | { return f(v0, v1, v2, v3, v4, v5); } 19954 | ff06_functor f; 19955 | }; 19956 | 19957 | struct freefunc07 exprtk_final : public exprtk::ifunction<T> 19958 | { 19959 | using exprtk::ifunction<T>::operator(); 19960 | 19961 | explicit freefunc07(ff07_functor ff) : exprtk::ifunction<T>(7), f(ff) {} 19962 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, 19963 | const T& v5, const T& v6) exprtk_override 19964 | { return f(v0, v1, v2, v3, v4, v5, v6); } 19965 | ff07_functor f; 19966 | }; 19967 | 19968 | struct freefunc08 exprtk_final : public exprtk::ifunction<T> 19969 | { 19970 | using exprtk::ifunction<T>::operator(); 19971 | 19972 | explicit freefunc08(ff08_functor ff) : exprtk::ifunction<T>(8), f(ff) {} 19973 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, 19974 | const T& v5, const T& v6, const T& v7) exprtk_override 19975 | { return f(v0, v1, v2, v3, v4, v5, v6, v7); } 19976 | ff08_functor f; 19977 | }; 19978 | 19979 | struct freefunc09 exprtk_final : public exprtk::ifunction<T> 19980 | { 19981 | using exprtk::ifunction<T>::operator(); 19982 | 19983 | explicit freefunc09(ff09_functor ff) : exprtk::ifunction<T>(9), f(ff) {} 19984 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, 19985 | const T& v5, const T& v6, const T& v7, const T& v8) exprtk_override 19986 | { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8); } 19987 | ff09_functor f; 19988 | }; 19989 | 19990 | struct freefunc10 exprtk_final : public exprtk::ifunction<T> 19991 | { 19992 | using exprtk::ifunction<T>::operator(); 19993 | 19994 | explicit freefunc10(ff10_functor ff) : exprtk::ifunction<T>(10), f(ff) {} 19995 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, 19996 | const T& v5, const T& v6, const T& v7, const T& v8, const T& v9) exprtk_override 19997 | { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9); } 19998 | ff10_functor f; 19999 | }; 20000 | 20001 | struct freefunc11 exprtk_final : public exprtk::ifunction<T> 20002 | { 20003 | using exprtk::ifunction<T>::operator(); 20004 | 20005 | explicit freefunc11(ff11_functor ff) : exprtk::ifunction<T>(11), f(ff) {} 20006 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, 20007 | const T& v5, const T& v6, const T& v7, const T& v8, const T& v9, const T& v10) exprtk_override 20008 | { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10); } 20009 | ff11_functor f; 20010 | }; 20011 | 20012 | struct freefunc12 exprtk_final : public exprtk::ifunction<T> 20013 | { 20014 | using exprtk::ifunction<T>::operator(); 20015 | 20016 | explicit freefunc12(ff12_functor ff) : exprtk::ifunction<T>(12), f(ff) {} 20017 | inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04, 20018 | const T& v05, const T& v06, const T& v07, const T& v08, const T& v09, 20019 | const T& v10, const T& v11) exprtk_override 20020 | { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11); } 20021 | ff12_functor f; 20022 | }; 20023 | 20024 | struct freefunc13 exprtk_final : public exprtk::ifunction<T> 20025 | { 20026 | using exprtk::ifunction<T>::operator(); 20027 | 20028 | explicit freefunc13(ff13_functor ff) : exprtk::ifunction<T>(13), f(ff) {} 20029 | inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04, 20030 | const T& v05, const T& v06, const T& v07, const T& v08, const T& v09, 20031 | const T& v10, const T& v11, const T& v12) exprtk_override 20032 | { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12); } 20033 | ff13_functor f; 20034 | }; 20035 | 20036 | struct freefunc14 exprtk_final : public exprtk::ifunction<T> 20037 | { 20038 | using exprtk::ifunction<T>::operator(); 20039 | 20040 | explicit freefunc14(ff14_functor ff) : exprtk::ifunction<T>(14), f(ff) {} 20041 | inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04, 20042 | const T& v05, const T& v06, const T& v07, const T& v08, const T& v09, 20043 | const T& v10, const T& v11, const T& v12, const T& v13) exprtk_override 20044 | { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12, v13); } 20045 | ff14_functor f; 20046 | }; 20047 | 20048 | struct freefunc15 exprtk_final : public exprtk::ifunction<T> 20049 | { 20050 | using exprtk::ifunction<T>::operator(); 20051 | 20052 | explicit freefunc15(ff15_functor ff) : exprtk::ifunction<T>(15), f(ff) {} 20053 | inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04, 20054 | const T& v05, const T& v06, const T& v07, const T& v08, const T& v09, 20055 | const T& v10, const T& v11, const T& v12, const T& v13, const T& v14) exprtk_override 20056 | { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12, v13, v14); } 20057 | ff15_functor f; 20058 | }; 20059 | 20060 | template <typename Type, typename RawType> 20061 | struct type_store 20062 | { 20063 | typedef details::expression_node<T>* expression_ptr; 20064 | typedef typename details::variable_node<T> variable_node_t; 20065 | typedef ifunction<T> ifunction_t; 20066 | typedef ivararg_function<T> ivararg_function_t; 20067 | typedef igeneric_function<T> igeneric_function_t; 20068 | typedef details::vector_holder<T> vector_t; 20069 | #ifndef exprtk_disable_string_capabilities 20070 | typedef typename details::stringvar_node<T> stringvar_node_t; 20071 | #endif 20072 | 20073 | typedef Type type_t; 20074 | typedef type_t* type_ptr; 20075 | typedef std::pair<bool,type_ptr> type_pair_t; 20076 | typedef std::map<std::string,type_pair_t,details::ilesscompare> type_map_t; 20077 | typedef typename type_map_t::iterator tm_itr_t; 20078 | typedef typename type_map_t::const_iterator tm_const_itr_t; 20079 | 20080 | enum { lut_size = 256 }; 20081 | 20082 | type_map_t map; 20083 | std::size_t size; 20084 | 20085 | type_store() 20086 | : size(0) 20087 | {} 20088 | 20089 | struct deleter 20090 | { 20091 | #define exprtk_define_process(Type) \ 20092 | static inline void process(std::pair<bool,Type*>& n) \ 20093 | { \ 20094 | delete n.second; \ 20095 | } \ 20096 | 20097 | exprtk_define_process(variable_node_t ) 20098 | exprtk_define_process(vector_t ) 20099 | #ifndef exprtk_disable_string_capabilities 20100 | exprtk_define_process(stringvar_node_t) 20101 | #endif 20102 | 20103 | #undef exprtk_define_process 20104 | 20105 | template <typename DeleteType> 20106 | static inline void process(std::pair<bool,DeleteType*>&) 20107 | {} 20108 | }; 20109 | 20110 | inline bool symbol_exists(const std::string& symbol_name) const 20111 | { 20112 | if (symbol_name.empty()) 20113 | return false; 20114 | else if (map.end() != map.find(symbol_name)) 20115 | return true; 20116 | else 20117 | return false; 20118 | } 20119 | 20120 | template <typename PtrType> 20121 | inline std::string entity_name(const PtrType& ptr) const 20122 | { 20123 | if (map.empty()) 20124 | return std::string(); 20125 | 20126 | tm_const_itr_t itr = map.begin(); 20127 | 20128 | while (map.end() != itr) 20129 | { 20130 | if (itr->second.second == ptr) 20131 | { 20132 | return itr->first; 20133 | } 20134 | else 20135 | ++itr; 20136 | } 20137 | 20138 | return std::string(); 20139 | } 20140 | 20141 | inline bool is_constant(const std::string& symbol_name) const 20142 | { 20143 | if (symbol_name.empty()) 20144 | return false; 20145 | else 20146 | { 20147 | const tm_const_itr_t itr = map.find(symbol_name); 20148 | 20149 | if (map.end() == itr) 20150 | return false; 20151 | else 20152 | return (*itr).second.first; 20153 | } 20154 | } 20155 | 20156 | template <typename Tie, typename RType> 20157 | inline bool add_impl(const std::string& symbol_name, RType t, const bool is_const) 20158 | { 20159 | if (symbol_name.size() > 1) 20160 | { 20161 | for (std::size_t i = 0; i < details::reserved_symbols_size; ++i) 20162 | { 20163 | if (details::imatch(symbol_name, details::reserved_symbols[i])) 20164 | { 20165 | return false; 20166 | } 20167 | } 20168 | } 20169 | 20170 | const tm_itr_t itr = map.find(symbol_name); 20171 | 20172 | if (map.end() == itr) 20173 | { 20174 | map[symbol_name] = Tie::make(t,is_const); 20175 | ++size; 20176 | } 20177 | 20178 | return true; 20179 | } 20180 | 20181 | struct tie_array 20182 | { 20183 | static inline std::pair<bool,vector_t*> make(std::pair<T*,std::size_t> v, const bool is_const = false) 20184 | { 20185 | return std::make_pair(is_const, new vector_t(v.first, v.second)); 20186 | } 20187 | }; 20188 | 20189 | struct tie_stdvec 20190 | { 20191 | template <typename Allocator> 20192 | static inline std::pair<bool,vector_t*> make(std::vector<T,Allocator>& v, const bool is_const = false) 20193 | { 20194 | return std::make_pair(is_const, new vector_t(v)); 20195 | } 20196 | }; 20197 | 20198 | struct tie_vecview 20199 | { 20200 | static inline std::pair<bool,vector_t*> make(exprtk::vector_view<T>& v, const bool is_const = false) 20201 | { 20202 | return std::make_pair(is_const, new vector_t(v)); 20203 | } 20204 | }; 20205 | 20206 | struct tie_stddeq 20207 | { 20208 | template <typename Allocator> 20209 | static inline std::pair<bool,vector_t*> make(std::deque<T,Allocator>& v, const bool is_const = false) 20210 | { 20211 | return std::make_pair(is_const, new vector_t(v)); 20212 | } 20213 | }; 20214 | 20215 | template <std::size_t v_size> 20216 | inline bool add(const std::string& symbol_name, T (&v)[v_size], const bool is_const = false) 20217 | { 20218 | return add_impl<tie_array,std::pair<T*,std::size_t> > 20219 | (symbol_name, std::make_pair(v,v_size), is_const); 20220 | } 20221 | 20222 | inline bool add(const std::string& symbol_name, T* v, const std::size_t v_size, const bool is_const = false) 20223 | { 20224 | return add_impl<tie_array,std::pair<T*,std::size_t> > 20225 | (symbol_name, std::make_pair(v,v_size), is_const); 20226 | } 20227 | 20228 | template <typename Allocator> 20229 | inline bool add(const std::string& symbol_name, std::vector<T,Allocator>& v, const bool is_const = false) 20230 | { 20231 | return add_impl<tie_stdvec,std::vector<T,Allocator>&> 20232 | (symbol_name, v, is_const); 20233 | } 20234 | 20235 | inline bool add(const std::string& symbol_name, exprtk::vector_view<T>& v, const bool is_const = false) 20236 | { 20237 | return add_impl<tie_vecview,exprtk::vector_view<T>&> 20238 | (symbol_name, v, is_const); 20239 | } 20240 | 20241 | template <typename Allocator> 20242 | inline bool add(const std::string& symbol_name, std::deque<T,Allocator>& v, const bool is_const = false) 20243 | { 20244 | return add_impl<tie_stddeq,std::deque<T,Allocator>&> 20245 | (symbol_name, v, is_const); 20246 | } 20247 | 20248 | inline bool add(const std::string& symbol_name, RawType& t_, const bool is_const = false) 20249 | { 20250 | struct tie 20251 | { 20252 | static inline std::pair<bool,variable_node_t*> make(T& t, const bool is_constant = false) 20253 | { 20254 | return std::make_pair(is_constant, new variable_node_t(t)); 20255 | } 20256 | 20257 | #ifndef exprtk_disable_string_capabilities 20258 | static inline std::pair<bool,stringvar_node_t*> make(std::string& t, const bool is_constant = false) 20259 | { 20260 | return std::make_pair(is_constant, new stringvar_node_t(t)); 20261 | } 20262 | #endif 20263 | 20264 | static inline std::pair<bool,function_t*> make(function_t& t, const bool is_constant = false) 20265 | { 20266 | return std::make_pair(is_constant,&t); 20267 | } 20268 | 20269 | static inline std::pair<bool,vararg_function_t*> make(vararg_function_t& t, const bool is_constant = false) 20270 | { 20271 | return std::make_pair(is_constant,&t); 20272 | } 20273 | 20274 | static inline std::pair<bool,generic_function_t*> make(generic_function_t& t, const bool is_constant = false) 20275 | { 20276 | return std::make_pair(is_constant,&t); 20277 | } 20278 | }; 20279 | 20280 | const tm_itr_t itr = map.find(symbol_name); 20281 | 20282 | if (map.end() == itr) 20283 | { 20284 | map[symbol_name] = tie::make(t_,is_const); 20285 | ++size; 20286 | } 20287 | 20288 | return true; 20289 | } 20290 | 20291 | inline type_ptr get(const std::string& symbol_name) const 20292 | { 20293 | const tm_const_itr_t itr = map.find(symbol_name); 20294 | 20295 | if (map.end() == itr) 20296 | return reinterpret_cast<type_ptr>(0); 20297 | else 20298 | return itr->second.second; 20299 | } 20300 | 20301 | template <typename TType, typename TRawType, typename PtrType> 20302 | struct ptr_match 20303 | { 20304 | static inline bool test(const PtrType, const void*) 20305 | { 20306 | return false; 20307 | } 20308 | }; 20309 | 20310 | template <typename TType, typename TRawType> 20311 | struct ptr_match<TType,TRawType,variable_node_t*> 20312 | { 20313 | static inline bool test(const variable_node_t* p, const void* ptr) 20314 | { 20315 | exprtk_debug(("ptr_match::test() - %p <--> %p\n", reinterpret_cast<const void*>(&(p->ref())), ptr)); 20316 | return (&(p->ref()) == ptr); 20317 | } 20318 | }; 20319 | 20320 | inline type_ptr get_from_varptr(const void* ptr) const 20321 | { 20322 | tm_const_itr_t itr = map.begin(); 20323 | 20324 | while (map.end() != itr) 20325 | { 20326 | type_ptr ret_ptr = itr->second.second; 20327 | 20328 | if (ptr_match<Type,RawType,type_ptr>::test(ret_ptr,ptr)) 20329 | { 20330 | return ret_ptr; 20331 | } 20332 | 20333 | ++itr; 20334 | } 20335 | 20336 | return type_ptr(0); 20337 | } 20338 | 20339 | inline bool remove(const std::string& symbol_name, const bool delete_node = true) 20340 | { 20341 | const tm_itr_t itr = map.find(symbol_name); 20342 | 20343 | if (map.end() != itr) 20344 | { 20345 | if (delete_node) 20346 | { 20347 | deleter::process((*itr).second); 20348 | } 20349 | 20350 | map.erase(itr); 20351 | --size; 20352 | 20353 | return true; 20354 | } 20355 | else 20356 | return false; 20357 | } 20358 | 20359 | inline RawType& type_ref(const std::string& symbol_name) 20360 | { 20361 | struct init_type 20362 | { 20363 | static inline double set(double) { return (0.0); } 20364 | static inline double set(long double) { return (0.0); } 20365 | static inline float set(float) { return (0.0f); } 20366 | static inline std::string set(std::string) { return std::string(""); } 20367 | }; 20368 | 20369 | static RawType null_type = init_type::set(RawType()); 20370 | 20371 | const tm_const_itr_t itr = map.find(symbol_name); 20372 | 20373 | if (map.end() == itr) 20374 | return null_type; 20375 | else 20376 | return itr->second.second->ref(); 20377 | } 20378 | 20379 | inline void clear(const bool delete_node = true) 20380 | { 20381 | if (!map.empty()) 20382 | { 20383 | if (delete_node) 20384 | { 20385 | tm_itr_t itr = map.begin(); 20386 | tm_itr_t end = map.end (); 20387 | 20388 | while (end != itr) 20389 | { 20390 | deleter::process((*itr).second); 20391 | ++itr; 20392 | } 20393 | } 20394 | 20395 | map.clear(); 20396 | } 20397 | 20398 | size = 0; 20399 | } 20400 | 20401 | template <typename Allocator, 20402 | template <typename, typename> class Sequence> 20403 | inline std::size_t get_list(Sequence<std::pair<std::string,RawType>,Allocator>& list) const 20404 | { 20405 | std::size_t count = 0; 20406 | 20407 | if (!map.empty()) 20408 | { 20409 | tm_const_itr_t itr = map.begin(); 20410 | tm_const_itr_t end = map.end (); 20411 | 20412 | while (end != itr) 20413 | { 20414 | list.push_back(std::make_pair((*itr).first,itr->second.second->ref())); 20415 | ++itr; 20416 | ++count; 20417 | } 20418 | } 20419 | 20420 | return count; 20421 | } 20422 | 20423 | template <typename Allocator, 20424 | template <typename, typename> class Sequence> 20425 | inline std::size_t get_list(Sequence<std::string,Allocator>& vlist) const 20426 | { 20427 | std::size_t count = 0; 20428 | 20429 | if (!map.empty()) 20430 | { 20431 | tm_const_itr_t itr = map.begin(); 20432 | tm_const_itr_t end = map.end (); 20433 | 20434 | while (end != itr) 20435 | { 20436 | vlist.push_back((*itr).first); 20437 | ++itr; 20438 | ++count; 20439 | } 20440 | } 20441 | 20442 | return count; 20443 | } 20444 | }; 20445 | 20446 | typedef details::expression_node<T>* expression_ptr; 20447 | typedef typename details::variable_node<T> variable_t; 20448 | typedef typename details::vector_holder<T> vector_holder_t; 20449 | typedef variable_t* variable_ptr; 20450 | #ifndef exprtk_disable_string_capabilities 20451 | typedef typename details::stringvar_node<T> stringvar_t; 20452 | typedef stringvar_t* stringvar_ptr; 20453 | #endif 20454 | typedef ifunction <T> function_t; 20455 | typedef ivararg_function <T> vararg_function_t; 20456 | typedef igeneric_function<T> generic_function_t; 20457 | typedef function_t* function_ptr; 20458 | typedef vararg_function_t* vararg_function_ptr; 20459 | typedef generic_function_t* generic_function_ptr; 20460 | 20461 | static const std::size_t lut_size = 256; 20462 | 20463 | // Symbol Table Holder 20464 | struct control_block 20465 | { 20466 | struct st_data 20467 | { 20468 | type_store<variable_t , T > variable_store; 20469 | type_store<function_t , function_t > function_store; 20470 | type_store<vararg_function_t , vararg_function_t > vararg_function_store; 20471 | type_store<generic_function_t, generic_function_t> generic_function_store; 20472 | type_store<generic_function_t, generic_function_t> string_function_store; 20473 | type_store<generic_function_t, generic_function_t> overload_function_store; 20474 | type_store<vector_holder_t , vector_holder_t > vector_store; 20475 | #ifndef exprtk_disable_string_capabilities 20476 | type_store<stringvar_t , std::string > stringvar_store; 20477 | #endif 20478 | 20479 | st_data() 20480 | { 20481 | for (std::size_t i = 0; i < details::reserved_words_size; ++i) 20482 | { 20483 | reserved_symbol_table_.insert(details::reserved_words[i]); 20484 | } 20485 | 20486 | for (std::size_t i = 0; i < details::reserved_symbols_size; ++i) 20487 | { 20488 | reserved_symbol_table_.insert(details::reserved_symbols[i]); 20489 | } 20490 | } 20491 | 20492 | ~st_data() 20493 | { 20494 | for (std::size_t i = 0; i < free_function_list_.size(); ++i) 20495 | { 20496 | delete free_function_list_[i]; 20497 | } 20498 | } 20499 | 20500 | inline bool is_reserved_symbol(const std::string& symbol) const 20501 | { 20502 | return (reserved_symbol_table_.end() != reserved_symbol_table_.find(symbol)); 20503 | } 20504 | 20505 | static inline st_data* create() 20506 | { 20507 | return (new st_data); 20508 | } 20509 | 20510 | static inline void destroy(st_data*& sd) 20511 | { 20512 | delete sd; 20513 | sd = reinterpret_cast<st_data*>(0); 20514 | } 20515 | 20516 | std::list<T> local_symbol_list_; 20517 | std::list<std::string> local_stringvar_list_; 20518 | std::set<std::string> reserved_symbol_table_; 20519 | std::vector<ifunction<T>*> free_function_list_; 20520 | }; 20521 | 20522 | control_block() 20523 | : ref_count(1) 20524 | , data_(st_data::create()) 20525 | , mutability_(e_mutable) 20526 | {} 20527 | 20528 | explicit control_block(st_data* data) 20529 | : ref_count(1) 20530 | , data_(data) 20531 | , mutability_(e_mutable) 20532 | {} 20533 | 20534 | ~control_block() 20535 | { 20536 | if (data_ && (0 == ref_count)) 20537 | { 20538 | st_data::destroy(data_); 20539 | } 20540 | } 20541 | 20542 | static inline control_block* create() 20543 | { 20544 | return (new control_block); 20545 | } 20546 | 20547 | template <typename SymTab> 20548 | static inline void destroy(control_block*& cntrl_blck, SymTab* sym_tab) 20549 | { 20550 | if (cntrl_blck) 20551 | { 20552 | if ( 20553 | (0 != cntrl_blck->ref_count) && 20554 | (0 == --cntrl_blck->ref_count) 20555 | ) 20556 | { 20557 | if (sym_tab) 20558 | sym_tab->clear(); 20559 | 20560 | delete cntrl_blck; 20561 | } 20562 | 20563 | cntrl_blck = 0; 20564 | } 20565 | } 20566 | 20567 | void set_mutability(const symtab_mutability_type mutability) 20568 | { 20569 | mutability_ = mutability; 20570 | } 20571 | 20572 | std::size_t ref_count; 20573 | st_data* data_; 20574 | symtab_mutability_type mutability_; 20575 | }; 20576 | 20577 | public: 20578 | 20579 | explicit symbol_table(const symtab_mutability_type mutability = e_mutable) 20580 | : control_block_(control_block::create()) 20581 | { 20582 | control_block_->set_mutability(mutability); 20583 | clear(); 20584 | } 20585 | 20586 | ~symbol_table() 20587 | { 20588 | exprtk::details::dump_ptr("~symbol_table", this); 20589 | control_block::destroy(control_block_, this); 20590 | } 20591 | 20592 | symbol_table(const symbol_table<T>& st) 20593 | { 20594 | control_block_ = st.control_block_; 20595 | control_block_->ref_count++; 20596 | } 20597 | 20598 | inline symbol_table<T>& operator=(const symbol_table<T>& st) 20599 | { 20600 | if (this != &st) 20601 | { 20602 | control_block::destroy(control_block_,reinterpret_cast<symbol_table<T>*>(0)); 20603 | 20604 | control_block_ = st.control_block_; 20605 | control_block_->ref_count++; 20606 | } 20607 | 20608 | return (*this); 20609 | } 20610 | 20611 | inline bool operator==(const symbol_table<T>& st) const 20612 | { 20613 | return (this == &st) || (control_block_ == st.control_block_); 20614 | } 20615 | 20616 | inline symtab_mutability_type mutability() const 20617 | { 20618 | return valid() ? control_block_->mutability_ : e_unknown; 20619 | } 20620 | 20621 | inline void clear_variables(const bool delete_node = true) 20622 | { 20623 | local_data().variable_store.clear(delete_node); 20624 | } 20625 | 20626 | inline void clear_functions() 20627 | { 20628 | local_data().function_store.clear(); 20629 | } 20630 | 20631 | inline void clear_strings() 20632 | { 20633 | #ifndef exprtk_disable_string_capabilities 20634 | local_data().stringvar_store.clear(); 20635 | #endif 20636 | } 20637 | 20638 | inline void clear_vectors() 20639 | { 20640 | local_data().vector_store.clear(); 20641 | } 20642 | 20643 | inline void clear_local_constants() 20644 | { 20645 | local_data().local_symbol_list_.clear(); 20646 | } 20647 | 20648 | inline void clear() 20649 | { 20650 | if (!valid()) return; 20651 | clear_variables (); 20652 | clear_functions (); 20653 | clear_strings (); 20654 | clear_vectors (); 20655 | clear_local_constants(); 20656 | } 20657 | 20658 | inline std::size_t variable_count() const 20659 | { 20660 | if (valid()) 20661 | return local_data().variable_store.size; 20662 | else 20663 | return 0; 20664 | } 20665 | 20666 | #ifndef exprtk_disable_string_capabilities 20667 | inline std::size_t stringvar_count() const 20668 | { 20669 | if (valid()) 20670 | return local_data().stringvar_store.size; 20671 | else 20672 | return 0; 20673 | } 20674 | #endif 20675 | 20676 | inline std::size_t function_count() const 20677 | { 20678 | if (valid()) 20679 | return local_data().function_store.size; 20680 | else 20681 | return 0; 20682 | } 20683 | 20684 | inline std::size_t vector_count() const 20685 | { 20686 | if (valid()) 20687 | return local_data().vector_store.size; 20688 | else 20689 | return 0; 20690 | } 20691 | 20692 | inline variable_ptr get_variable(const std::string& variable_name) const 20693 | { 20694 | if (!valid()) 20695 | return reinterpret_cast<variable_ptr>(0); 20696 | else if (!valid_symbol(variable_name)) 20697 | return reinterpret_cast<variable_ptr>(0); 20698 | else 20699 | return local_data().variable_store.get(variable_name); 20700 | } 20701 | 20702 | inline variable_ptr get_variable(const T& var_ref) const 20703 | { 20704 | if (!valid()) 20705 | return reinterpret_cast<variable_ptr>(0); 20706 | else 20707 | return local_data().variable_store.get_from_varptr( 20708 | reinterpret_cast<const void*>(&var_ref)); 20709 | } 20710 | 20711 | #ifndef exprtk_disable_string_capabilities 20712 | inline stringvar_ptr get_stringvar(const std::string& string_name) const 20713 | { 20714 | if (!valid()) 20715 | return reinterpret_cast<stringvar_ptr>(0); 20716 | else if (!valid_symbol(string_name)) 20717 | return reinterpret_cast<stringvar_ptr>(0); 20718 | else 20719 | return local_data().stringvar_store.get(string_name); 20720 | } 20721 | 20722 | inline stringvar_base<T> get_stringvar_base(const std::string& string_name) const 20723 | { 20724 | static stringvar_base<T> null_stringvar_base("",reinterpret_cast<stringvar_ptr>(0)); 20725 | if (!valid()) 20726 | return null_stringvar_base; 20727 | else if (!valid_symbol(string_name)) 20728 | return null_stringvar_base; 20729 | 20730 | stringvar_ptr stringvar = local_data().stringvar_store.get(string_name); 20731 | 20732 | if (0 == stringvar) 20733 | { 20734 | return null_stringvar_base; 20735 | } 20736 | 20737 | return stringvar_base<T>(string_name,stringvar); 20738 | } 20739 | #endif 20740 | 20741 | inline function_ptr get_function(const std::string& function_name) const 20742 | { 20743 | if (!valid()) 20744 | return reinterpret_cast<function_ptr>(0); 20745 | else if (!valid_symbol(function_name)) 20746 | return reinterpret_cast<function_ptr>(0); 20747 | else 20748 | return local_data().function_store.get(function_name); 20749 | } 20750 | 20751 | inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name) const 20752 | { 20753 | if (!valid()) 20754 | return reinterpret_cast<vararg_function_ptr>(0); 20755 | else if (!valid_symbol(vararg_function_name)) 20756 | return reinterpret_cast<vararg_function_ptr>(0); 20757 | else 20758 | return local_data().vararg_function_store.get(vararg_function_name); 20759 | } 20760 | 20761 | inline generic_function_ptr get_generic_function(const std::string& function_name) const 20762 | { 20763 | if (!valid()) 20764 | return reinterpret_cast<generic_function_ptr>(0); 20765 | else if (!valid_symbol(function_name)) 20766 | return reinterpret_cast<generic_function_ptr>(0); 20767 | else 20768 | return local_data().generic_function_store.get(function_name); 20769 | } 20770 | 20771 | inline generic_function_ptr get_string_function(const std::string& function_name) const 20772 | { 20773 | if (!valid()) 20774 | return reinterpret_cast<generic_function_ptr>(0); 20775 | else if (!valid_symbol(function_name)) 20776 | return reinterpret_cast<generic_function_ptr>(0); 20777 | else 20778 | return local_data().string_function_store.get(function_name); 20779 | } 20780 | 20781 | inline generic_function_ptr get_overload_function(const std::string& function_name) const 20782 | { 20783 | if (!valid()) 20784 | return reinterpret_cast<generic_function_ptr>(0); 20785 | else if (!valid_symbol(function_name)) 20786 | return reinterpret_cast<generic_function_ptr>(0); 20787 | else 20788 | return local_data().overload_function_store.get(function_name); 20789 | } 20790 | 20791 | typedef vector_holder_t* vector_holder_ptr; 20792 | 20793 | inline vector_holder_ptr get_vector(const std::string& vector_name) const 20794 | { 20795 | if (!valid()) 20796 | return reinterpret_cast<vector_holder_ptr>(0); 20797 | else if (!valid_symbol(vector_name)) 20798 | return reinterpret_cast<vector_holder_ptr>(0); 20799 | else 20800 | return local_data().vector_store.get(vector_name); 20801 | } 20802 | 20803 | inline T& variable_ref(const std::string& symbol_name) 20804 | { 20805 | static T null_var = T(0); 20806 | if (!valid()) 20807 | return null_var; 20808 | else if (!valid_symbol(symbol_name)) 20809 | return null_var; 20810 | else 20811 | return local_data().variable_store.type_ref(symbol_name); 20812 | } 20813 | 20814 | #ifndef exprtk_disable_string_capabilities 20815 | inline std::string& stringvar_ref(const std::string& symbol_name) 20816 | { 20817 | static std::string null_stringvar; 20818 | if (!valid()) 20819 | return null_stringvar; 20820 | else if (!valid_symbol(symbol_name)) 20821 | return null_stringvar; 20822 | else 20823 | return local_data().stringvar_store.type_ref(symbol_name); 20824 | } 20825 | #endif 20826 | 20827 | inline bool is_constant_node(const std::string& symbol_name) const 20828 | { 20829 | if (!valid()) 20830 | return false; 20831 | else if (!valid_symbol(symbol_name)) 20832 | return false; 20833 | else 20834 | return local_data().variable_store.is_constant(symbol_name); 20835 | } 20836 | 20837 | #ifndef exprtk_disable_string_capabilities 20838 | inline bool is_constant_string(const std::string& symbol_name) const 20839 | { 20840 | if (!valid()) 20841 | return false; 20842 | else if (!valid_symbol(symbol_name)) 20843 | return false; 20844 | else if (!local_data().stringvar_store.symbol_exists(symbol_name)) 20845 | return false; 20846 | else 20847 | return local_data().stringvar_store.is_constant(symbol_name); 20848 | } 20849 | #endif 20850 | 20851 | inline bool create_variable(const std::string& variable_name, const T& value = T(0)) 20852 | { 20853 | if (!valid()) 20854 | return false; 20855 | else if (!valid_symbol(variable_name)) 20856 | return false; 20857 | else if (symbol_exists(variable_name)) 20858 | return false; 20859 | 20860 | local_data().local_symbol_list_.push_back(value); 20861 | T& t = local_data().local_symbol_list_.back(); 20862 | 20863 | return add_variable(variable_name,t); 20864 | } 20865 | 20866 | #ifndef exprtk_disable_string_capabilities 20867 | inline bool create_stringvar(const std::string& stringvar_name, const std::string& value = std::string("")) 20868 | { 20869 | if (!valid()) 20870 | return false; 20871 | else if (!valid_symbol(stringvar_name)) 20872 | return false; 20873 | else if (symbol_exists(stringvar_name)) 20874 | return false; 20875 | 20876 | local_data().local_stringvar_list_.push_back(value); 20877 | std::string& s = local_data().local_stringvar_list_.back(); 20878 | 20879 | return add_stringvar(stringvar_name,s); 20880 | } 20881 | #endif 20882 | 20883 | inline bool add_variable(const std::string& variable_name, T& t, const bool is_constant = false) 20884 | { 20885 | if (!valid()) 20886 | return false; 20887 | else if (!valid_symbol(variable_name)) 20888 | return false; 20889 | else if (symbol_exists(variable_name)) 20890 | return false; 20891 | else 20892 | return local_data().variable_store.add(variable_name, t, is_constant); 20893 | } 20894 | 20895 | inline bool add_constant(const std::string& constant_name, const T& value) 20896 | { 20897 | if (!valid()) 20898 | return false; 20899 | else if (!valid_symbol(constant_name)) 20900 | return false; 20901 | else if (symbol_exists(constant_name)) 20902 | return false; 20903 | 20904 | local_data().local_symbol_list_.push_back(value); 20905 | T& t = local_data().local_symbol_list_.back(); 20906 | 20907 | return add_variable(constant_name, t, true); 20908 | } 20909 | 20910 | #ifndef exprtk_disable_string_capabilities 20911 | inline bool add_stringvar(const std::string& stringvar_name, std::string& s, const bool is_constant = false) 20912 | { 20913 | if (!valid()) 20914 | return false; 20915 | else if (!valid_symbol(stringvar_name)) 20916 | return false; 20917 | else if (symbol_exists(stringvar_name)) 20918 | return false; 20919 | else 20920 | return local_data().stringvar_store.add(stringvar_name, s, is_constant); 20921 | } 20922 | #endif 20923 | 20924 | inline bool add_function(const std::string& function_name, function_t& function) 20925 | { 20926 | if (!valid()) 20927 | return false; 20928 | else if (!valid_symbol(function_name)) 20929 | return false; 20930 | else if (symbol_exists(function_name)) 20931 | return false; 20932 | else 20933 | return local_data().function_store.add(function_name,function); 20934 | } 20935 | 20936 | inline bool add_function(const std::string& vararg_function_name, vararg_function_t& vararg_function) 20937 | { 20938 | if (!valid()) 20939 | return false; 20940 | else if (!valid_symbol(vararg_function_name)) 20941 | return false; 20942 | else if (symbol_exists(vararg_function_name)) 20943 | return false; 20944 | else 20945 | return local_data().vararg_function_store.add(vararg_function_name,vararg_function); 20946 | } 20947 | 20948 | inline bool add_function(const std::string& function_name, generic_function_t& function) 20949 | { 20950 | if (!valid()) 20951 | return false; 20952 | else if (!valid_symbol(function_name)) 20953 | return false; 20954 | else if (symbol_exists(function_name)) 20955 | return false; 20956 | else 20957 | { 20958 | switch (function.rtrn_type) 20959 | { 20960 | case generic_function_t::e_rtrn_scalar : 20961 | return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ? 20962 | local_data().generic_function_store.add(function_name,function) : false; 20963 | 20964 | case generic_function_t::e_rtrn_string : 20965 | return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ? 20966 | local_data().string_function_store.add(function_name,function) : false; 20967 | 20968 | case generic_function_t::e_rtrn_overload : 20969 | return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|:")) ? 20970 | local_data().overload_function_store.add(function_name,function) : false; 20971 | } 20972 | } 20973 | 20974 | return false; 20975 | } 20976 | 20977 | #define exprtk_define_freefunction(NN) \ 20978 | inline bool add_function(const std::string& function_name, ff##NN##_functor function) \ 20979 | { \ 20980 | if (!valid()) \ 20981 | { return false; } \ 20982 | if (!valid_symbol(function_name)) \ 20983 | { return false; } \ 20984 | if (symbol_exists(function_name)) \ 20985 | { return false; } \ 20986 | \ 20987 | exprtk::ifunction<T>* ifunc = new freefunc##NN(function); \ 20988 | \ 20989 | local_data().free_function_list_.push_back(ifunc); \ 20990 | \ 20991 | return add_function(function_name,(*local_data().free_function_list_.back())); \ 20992 | } \ 20993 | 20994 | exprtk_define_freefunction(00) exprtk_define_freefunction(01) 20995 | exprtk_define_freefunction(02) exprtk_define_freefunction(03) 20996 | exprtk_define_freefunction(04) exprtk_define_freefunction(05) 20997 | exprtk_define_freefunction(06) exprtk_define_freefunction(07) 20998 | exprtk_define_freefunction(08) exprtk_define_freefunction(09) 20999 | exprtk_define_freefunction(10) exprtk_define_freefunction(11) 21000 | exprtk_define_freefunction(12) exprtk_define_freefunction(13) 21001 | exprtk_define_freefunction(14) exprtk_define_freefunction(15) 21002 | 21003 | #undef exprtk_define_freefunction 21004 | 21005 | inline bool add_reserved_function(const std::string& function_name, function_t& function) 21006 | { 21007 | if (!valid()) 21008 | return false; 21009 | else if (!valid_symbol(function_name,false)) 21010 | return false; 21011 | else if (symbol_exists(function_name,false)) 21012 | return false; 21013 | else 21014 | return local_data().function_store.add(function_name,function); 21015 | } 21016 | 21017 | inline bool add_reserved_function(const std::string& vararg_function_name, vararg_function_t& vararg_function) 21018 | { 21019 | if (!valid()) 21020 | return false; 21021 | else if (!valid_symbol(vararg_function_name,false)) 21022 | return false; 21023 | else if (symbol_exists(vararg_function_name,false)) 21024 | return false; 21025 | else 21026 | return local_data().vararg_function_store.add(vararg_function_name,vararg_function); 21027 | } 21028 | 21029 | inline bool add_reserved_function(const std::string& function_name, generic_function_t& function) 21030 | { 21031 | if (!valid()) 21032 | return false; 21033 | else if (!valid_symbol(function_name,false)) 21034 | return false; 21035 | else if (symbol_exists(function_name,false)) 21036 | return false; 21037 | else 21038 | { 21039 | switch (function.rtrn_type) 21040 | { 21041 | case generic_function_t::e_rtrn_scalar : 21042 | return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ? 21043 | local_data().generic_function_store.add(function_name,function) : false; 21044 | 21045 | case generic_function_t::e_rtrn_string : 21046 | return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ? 21047 | local_data().string_function_store.add(function_name,function) : false; 21048 | 21049 | case generic_function_t::e_rtrn_overload : 21050 | return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|:")) ? 21051 | local_data().overload_function_store.add(function_name,function) : false; 21052 | } 21053 | } 21054 | 21055 | return false; 21056 | } 21057 | 21058 | #define exprtk_define_reserved_function(NN) \ 21059 | inline bool add_reserved_function(const std::string& function_name, ff##NN##_functor function) \ 21060 | { \ 21061 | if (!valid()) \ 21062 | { return false; } \ 21063 | if (!valid_symbol(function_name,false)) \ 21064 | { return false; } \ 21065 | if (symbol_exists(function_name,false)) \ 21066 | { return false; } \ 21067 | \ 21068 | exprtk::ifunction<T>* ifunc = new freefunc##NN(function); \ 21069 | \ 21070 | local_data().free_function_list_.push_back(ifunc); \ 21071 | \ 21072 | return add_reserved_function(function_name,(*local_data().free_function_list_.back())); \ 21073 | } \ 21074 | 21075 | exprtk_define_reserved_function(00) exprtk_define_reserved_function(01) 21076 | exprtk_define_reserved_function(02) exprtk_define_reserved_function(03) 21077 | exprtk_define_reserved_function(04) exprtk_define_reserved_function(05) 21078 | exprtk_define_reserved_function(06) exprtk_define_reserved_function(07) 21079 | exprtk_define_reserved_function(08) exprtk_define_reserved_function(09) 21080 | exprtk_define_reserved_function(10) exprtk_define_reserved_function(11) 21081 | exprtk_define_reserved_function(12) exprtk_define_reserved_function(13) 21082 | exprtk_define_reserved_function(14) exprtk_define_reserved_function(15) 21083 | 21084 | #undef exprtk_define_reserved_function 21085 | 21086 | template <std::size_t N> 21087 | inline bool add_vector(const std::string& vector_name, T (&v)[N]) 21088 | { 21089 | if (!valid()) 21090 | return false; 21091 | else if (!valid_symbol(vector_name)) 21092 | return false; 21093 | else if (symbol_exists(vector_name)) 21094 | return false; 21095 | else 21096 | return local_data().vector_store.add(vector_name,v); 21097 | } 21098 | 21099 | inline bool add_vector(const std::string& vector_name, T* v, const std::size_t& v_size) 21100 | { 21101 | if (!valid()) 21102 | return false; 21103 | else if (!valid_symbol(vector_name)) 21104 | return false; 21105 | else if (symbol_exists(vector_name)) 21106 | return false; 21107 | else if (0 == v_size) 21108 | return false; 21109 | else 21110 | return local_data().vector_store.add(vector_name, v, v_size); 21111 | } 21112 | 21113 | template <typename Allocator> 21114 | inline bool add_vector(const std::string& vector_name, std::vector<T,Allocator>& v) 21115 | { 21116 | if (!valid()) 21117 | return false; 21118 | else if (!valid_symbol(vector_name)) 21119 | return false; 21120 | else if (symbol_exists(vector_name)) 21121 | return false; 21122 | else if (0 == v.size()) 21123 | return false; 21124 | else 21125 | return local_data().vector_store.add(vector_name,v); 21126 | } 21127 | 21128 | inline bool add_vector(const std::string& vector_name, exprtk::vector_view<T>& v) 21129 | { 21130 | if (!valid()) 21131 | return false; 21132 | else if (!valid_symbol(vector_name)) 21133 | return false; 21134 | else if (symbol_exists(vector_name)) 21135 | return false; 21136 | else if (0 == v.size()) 21137 | return false; 21138 | else 21139 | return local_data().vector_store.add(vector_name,v); 21140 | } 21141 | 21142 | inline bool remove_variable(const std::string& variable_name, const bool delete_node = true) 21143 | { 21144 | if (!valid()) 21145 | return false; 21146 | else 21147 | return local_data().variable_store.remove(variable_name, delete_node); 21148 | } 21149 | 21150 | #ifndef exprtk_disable_string_capabilities 21151 | inline bool remove_stringvar(const std::string& string_name) 21152 | { 21153 | if (!valid()) 21154 | return false; 21155 | else 21156 | return local_data().stringvar_store.remove(string_name); 21157 | } 21158 | #endif 21159 | 21160 | inline bool remove_function(const std::string& function_name) 21161 | { 21162 | if (!valid()) 21163 | return false; 21164 | else 21165 | return local_data().function_store.remove(function_name); 21166 | } 21167 | 21168 | inline bool remove_vararg_function(const std::string& vararg_function_name) 21169 | { 21170 | if (!valid()) 21171 | return false; 21172 | else 21173 | return local_data().vararg_function_store.remove(vararg_function_name); 21174 | } 21175 | 21176 | inline bool remove_vector(const std::string& vector_name) 21177 | { 21178 | if (!valid()) 21179 | return false; 21180 | else 21181 | return local_data().vector_store.remove(vector_name); 21182 | } 21183 | 21184 | inline bool add_constants() 21185 | { 21186 | return add_pi () && 21187 | add_epsilon () && 21188 | add_infinity() ; 21189 | } 21190 | 21191 | inline bool add_pi() 21192 | { 21193 | const typename details::numeric::details::number_type<T>::type num_type; 21194 | static const T local_pi = details::numeric::details::const_pi_impl<T>(num_type); 21195 | return add_constant("pi",local_pi); 21196 | } 21197 | 21198 | inline bool add_epsilon() 21199 | { 21200 | static const T local_epsilon = details::numeric::details::epsilon_type<T>::value(); 21201 | return add_constant("epsilon",local_epsilon); 21202 | } 21203 | 21204 | inline bool add_infinity() 21205 | { 21206 | static const T local_infinity = std::numeric_limits<T>::infinity(); 21207 | return add_constant("inf",local_infinity); 21208 | } 21209 | 21210 | template <typename Package> 21211 | inline bool add_package(Package& package) 21212 | { 21213 | return package.register_package(*this); 21214 | } 21215 | 21216 | template <typename Allocator, 21217 | template <typename, typename> class Sequence> 21218 | inline std::size_t get_variable_list(Sequence<std::pair<std::string,T>,Allocator>& vlist) const 21219 | { 21220 | if (!valid()) 21221 | return 0; 21222 | else 21223 | return local_data().variable_store.get_list(vlist); 21224 | } 21225 | 21226 | template <typename Allocator, 21227 | template <typename, typename> class Sequence> 21228 | inline std::size_t get_variable_list(Sequence<std::string,Allocator>& vlist) const 21229 | { 21230 | if (!valid()) 21231 | return 0; 21232 | else 21233 | return local_data().variable_store.get_list(vlist); 21234 | } 21235 | 21236 | #ifndef exprtk_disable_string_capabilities 21237 | template <typename Allocator, 21238 | template <typename, typename> class Sequence> 21239 | inline std::size_t get_stringvar_list(Sequence<std::pair<std::string,std::string>,Allocator>& svlist) const 21240 | { 21241 | if (!valid()) 21242 | return 0; 21243 | else 21244 | return local_data().stringvar_store.get_list(svlist); 21245 | } 21246 | 21247 | template <typename Allocator, 21248 | template <typename, typename> class Sequence> 21249 | inline std::size_t get_stringvar_list(Sequence<std::string,Allocator>& svlist) const 21250 | { 21251 | if (!valid()) 21252 | return 0; 21253 | else 21254 | return local_data().stringvar_store.get_list(svlist); 21255 | } 21256 | #endif 21257 | 21258 | template <typename Allocator, 21259 | template <typename, typename> class Sequence> 21260 | inline std::size_t get_vector_list(Sequence<std::string,Allocator>& vec_list) const 21261 | { 21262 | if (!valid()) 21263 | return 0; 21264 | else 21265 | return local_data().vector_store.get_list(vec_list); 21266 | } 21267 | 21268 | template <typename Allocator, 21269 | template <typename, typename> class Sequence> 21270 | inline std::size_t get_function_list(Sequence<std::string,Allocator>& function_list) const 21271 | { 21272 | if (!valid()) 21273 | return 0; 21274 | 21275 | std::vector<std::string> function_names; 21276 | std::size_t count = 0; 21277 | 21278 | count += local_data().function_store .get_list(function_names); 21279 | count += local_data().vararg_function_store .get_list(function_names); 21280 | count += local_data().generic_function_store .get_list(function_names); 21281 | count += local_data().string_function_store .get_list(function_names); 21282 | count += local_data().overload_function_store.get_list(function_names); 21283 | 21284 | std::set<std::string> function_set; 21285 | 21286 | for (std::size_t i = 0; i < function_names.size(); ++i) 21287 | { 21288 | function_set.insert(function_names[i]); 21289 | } 21290 | 21291 | std::copy(function_set.begin(), function_set.end(), 21292 | std::back_inserter(function_list)); 21293 | 21294 | return count; 21295 | } 21296 | 21297 | inline std::vector<std::string> get_function_list() const 21298 | { 21299 | std::vector<std::string> result; 21300 | get_function_list(result); 21301 | return result; 21302 | } 21303 | 21304 | inline bool symbol_exists(const std::string& symbol_name, const bool check_reserved_symb = true) const 21305 | { 21306 | /* 21307 | Function will return true if symbol_name exists as either a 21308 | reserved symbol, variable, stringvar, vector or function name 21309 | in any of the type stores. 21310 | */ 21311 | if (!valid()) 21312 | return false; 21313 | else if (local_data().variable_store.symbol_exists(symbol_name)) 21314 | return true; 21315 | #ifndef exprtk_disable_string_capabilities 21316 | else if (local_data().stringvar_store.symbol_exists(symbol_name)) 21317 | return true; 21318 | #endif 21319 | else if (local_data().vector_store.symbol_exists(symbol_name)) 21320 | return true; 21321 | else if (local_data().function_store.symbol_exists(symbol_name)) 21322 | return true; 21323 | else if (check_reserved_symb && local_data().is_reserved_symbol(symbol_name)) 21324 | return true; 21325 | else 21326 | return false; 21327 | } 21328 | 21329 | inline bool is_variable(const std::string& variable_name) const 21330 | { 21331 | if (!valid()) 21332 | return false; 21333 | else 21334 | return local_data().variable_store.symbol_exists(variable_name); 21335 | } 21336 | 21337 | #ifndef exprtk_disable_string_capabilities 21338 | inline bool is_stringvar(const std::string& stringvar_name) const 21339 | { 21340 | if (!valid()) 21341 | return false; 21342 | else 21343 | return local_data().stringvar_store.symbol_exists(stringvar_name); 21344 | } 21345 | 21346 | inline bool is_conststr_stringvar(const std::string& symbol_name) const 21347 | { 21348 | if (!valid()) 21349 | return false; 21350 | else if (!valid_symbol(symbol_name)) 21351 | return false; 21352 | else if (!local_data().stringvar_store.symbol_exists(symbol_name)) 21353 | return false; 21354 | 21355 | return ( 21356 | local_data().stringvar_store.symbol_exists(symbol_name) || 21357 | local_data().stringvar_store.is_constant (symbol_name) 21358 | ); 21359 | } 21360 | #endif 21361 | 21362 | inline bool is_function(const std::string& function_name) const 21363 | { 21364 | if (!valid()) 21365 | return false; 21366 | else 21367 | return local_data().function_store.symbol_exists(function_name); 21368 | } 21369 | 21370 | inline bool is_vararg_function(const std::string& vararg_function_name) const 21371 | { 21372 | if (!valid()) 21373 | return false; 21374 | else 21375 | return local_data().vararg_function_store.symbol_exists(vararg_function_name); 21376 | } 21377 | 21378 | inline bool is_vector(const std::string& vector_name) const 21379 | { 21380 | if (!valid()) 21381 | return false; 21382 | else 21383 | return local_data().vector_store.symbol_exists(vector_name); 21384 | } 21385 | 21386 | inline std::string get_variable_name(const expression_ptr& ptr) const 21387 | { 21388 | return local_data().variable_store.entity_name(ptr); 21389 | } 21390 | 21391 | inline std::string get_vector_name(const vector_holder_ptr& ptr) const 21392 | { 21393 | return local_data().vector_store.entity_name(ptr); 21394 | } 21395 | 21396 | #ifndef exprtk_disable_string_capabilities 21397 | inline std::string get_stringvar_name(const expression_ptr& ptr) const 21398 | { 21399 | return local_data().stringvar_store.entity_name(ptr); 21400 | } 21401 | 21402 | inline std::string get_conststr_stringvar_name(const expression_ptr& ptr) const 21403 | { 21404 | return local_data().stringvar_store.entity_name(ptr); 21405 | } 21406 | #endif 21407 | 21408 | inline bool valid() const 21409 | { 21410 | // Symbol table sanity check. 21411 | return control_block_ && control_block_->data_; 21412 | } 21413 | 21414 | inline void load_from(const symbol_table<T>& st) 21415 | { 21416 | { 21417 | std::vector<std::string> name_list; 21418 | 21419 | st.local_data().function_store.get_list(name_list); 21420 | 21421 | if (!name_list.empty()) 21422 | { 21423 | for (std::size_t i = 0; i < name_list.size(); ++i) 21424 | { 21425 | exprtk::ifunction<T>& ifunc = *st.get_function(name_list[i]); 21426 | add_function(name_list[i],ifunc); 21427 | } 21428 | } 21429 | } 21430 | 21431 | { 21432 | std::vector<std::string> name_list; 21433 | 21434 | st.local_data().vararg_function_store.get_list(name_list); 21435 | 21436 | if (!name_list.empty()) 21437 | { 21438 | for (std::size_t i = 0; i < name_list.size(); ++i) 21439 | { 21440 | exprtk::ivararg_function<T>& ivafunc = *st.get_vararg_function(name_list[i]); 21441 | add_function(name_list[i],ivafunc); 21442 | } 21443 | } 21444 | } 21445 | 21446 | { 21447 | std::vector<std::string> name_list; 21448 | 21449 | st.local_data().generic_function_store.get_list(name_list); 21450 | 21451 | if (!name_list.empty()) 21452 | { 21453 | for (std::size_t i = 0; i < name_list.size(); ++i) 21454 | { 21455 | exprtk::igeneric_function<T>& ifunc = *st.get_generic_function(name_list[i]); 21456 | add_function(name_list[i],ifunc); 21457 | } 21458 | } 21459 | } 21460 | 21461 | { 21462 | std::vector<std::string> name_list; 21463 | 21464 | st.local_data().string_function_store.get_list(name_list); 21465 | 21466 | if (!name_list.empty()) 21467 | { 21468 | for (std::size_t i = 0; i < name_list.size(); ++i) 21469 | { 21470 | exprtk::igeneric_function<T>& ifunc = *st.get_string_function(name_list[i]); 21471 | add_function(name_list[i],ifunc); 21472 | } 21473 | } 21474 | } 21475 | 21476 | { 21477 | std::vector<std::string> name_list; 21478 | 21479 | st.local_data().overload_function_store.get_list(name_list); 21480 | 21481 | if (!name_list.empty()) 21482 | { 21483 | for (std::size_t i = 0; i < name_list.size(); ++i) 21484 | { 21485 | exprtk::igeneric_function<T>& ifunc = *st.get_overload_function(name_list[i]); 21486 | add_function(name_list[i],ifunc); 21487 | } 21488 | } 21489 | } 21490 | } 21491 | 21492 | inline void load_variables_from(const symbol_table<T>& st) 21493 | { 21494 | std::vector<std::string> name_list; 21495 | 21496 | st.local_data().variable_store.get_list(name_list); 21497 | 21498 | if (!name_list.empty()) 21499 | { 21500 | for (std::size_t i = 0; i < name_list.size(); ++i) 21501 | { 21502 | T& variable = st.get_variable(name_list[i])->ref(); 21503 | add_variable(name_list[i], variable); 21504 | } 21505 | } 21506 | } 21507 | 21508 | inline void load_vectors_from(const symbol_table<T>& st) 21509 | { 21510 | std::vector<std::string> name_list; 21511 | 21512 | st.local_data().vector_store.get_list(name_list); 21513 | 21514 | if (!name_list.empty()) 21515 | { 21516 | for (std::size_t i = 0; i < name_list.size(); ++i) 21517 | { 21518 | vector_holder_t& vecholder = *st.get_vector(name_list[i]); 21519 | add_vector(name_list[i], vecholder.data(), vecholder.size()); 21520 | } 21521 | } 21522 | } 21523 | 21524 | private: 21525 | 21526 | inline bool valid_symbol(const std::string& symbol, const bool check_reserved_symb = true) const 21527 | { 21528 | if (symbol.empty()) 21529 | return false; 21530 | else if (!details::is_letter(symbol[0])) 21531 | return false; 21532 | else if (symbol.size() > 1) 21533 | { 21534 | for (std::size_t i = 1; i < symbol.size(); ++i) 21535 | { 21536 | if ( 21537 | !details::is_letter_or_digit(symbol[i]) && 21538 | ('_' != symbol[i]) 21539 | ) 21540 | { 21541 | if ((i < (symbol.size() - 1)) && ('.' == symbol[i])) 21542 | continue; 21543 | else 21544 | return false; 21545 | } 21546 | } 21547 | } 21548 | 21549 | return (check_reserved_symb) ? (!local_data().is_reserved_symbol(symbol)) : true; 21550 | } 21551 | 21552 | inline bool valid_function(const std::string& symbol) const 21553 | { 21554 | if (symbol.empty()) 21555 | return false; 21556 | else if (!details::is_letter(symbol[0])) 21557 | return false; 21558 | else if (symbol.size() > 1) 21559 | { 21560 | for (std::size_t i = 1; i < symbol.size(); ++i) 21561 | { 21562 | if ( 21563 | !details::is_letter_or_digit(symbol[i]) && 21564 | ('_' != symbol[i]) 21565 | ) 21566 | { 21567 | if ((i < (symbol.size() - 1)) && ('.' == symbol[i])) 21568 | continue; 21569 | else 21570 | return false; 21571 | } 21572 | } 21573 | } 21574 | 21575 | return true; 21576 | } 21577 | 21578 | typedef typename control_block::st_data local_data_t; 21579 | 21580 | inline local_data_t& local_data() 21581 | { 21582 | return *(control_block_->data_); 21583 | } 21584 | 21585 | inline const local_data_t& local_data() const 21586 | { 21587 | return *(control_block_->data_); 21588 | } 21589 | 21590 | control_block* control_block_; 21591 | 21592 | friend class parser<T>; 21593 | }; // class symbol_table 21594 | 21595 | template <typename T> 21596 | class function_compositor; 21597 | 21598 | template <typename T> 21599 | class expression 21600 | { 21601 | private: 21602 | 21603 | typedef details::expression_node<T>* expression_ptr; 21604 | typedef details::vector_holder<T>* vector_holder_ptr; 21605 | typedef std::vector<symbol_table<T> > symtab_list_t; 21606 | 21607 | struct control_block 21608 | { 21609 | enum data_type 21610 | { 21611 | e_unknown , 21612 | e_expr , 21613 | e_vecholder, 21614 | e_data , 21615 | e_vecdata , 21616 | e_string 21617 | }; 21618 | 21619 | static std::string to_str(data_type dt) 21620 | { 21621 | switch (dt) 21622 | { 21623 | case e_unknown : return "e_unknown " 21624 | case e_expr : return "e_expr" ; 21625 | case e_vecholder : return "e_vecholder" 21626 | case e_data : return "e_data" ; 21627 | case e_vecdata : return "e_vecdata" ; 21628 | case e_string : return "e_string" ; 21629 | } 21630 | 21631 | return "" 21632 | } 21633 | 21634 | struct data_pack 21635 | { 21636 | data_pack() 21637 | : pointer(0) 21638 | , type(e_unknown) 21639 | , size(0) 21640 | {} 21641 | 21642 | data_pack(void* ptr, const data_type dt, const std::size_t sz = 0) 21643 | : pointer(ptr) 21644 | , type(dt) 21645 | , size(sz) 21646 | {} 21647 | 21648 | void* pointer; 21649 | data_type type; 21650 | std::size_t size; 21651 | }; 21652 | 21653 | typedef std::vector<data_pack> local_data_list_t; 21654 | typedef results_context<T> results_context_t; 21655 | typedef control_block* cntrl_blck_ptr_t; 21656 | 21657 | control_block() 21658 | : ref_count(0) 21659 | , expr (0) 21660 | , results (0) 21661 | , retinv_null(false) 21662 | , return_invoked(&retinv_null) 21663 | {} 21664 | 21665 | explicit control_block(expression_ptr e) 21666 | : ref_count(1) 21667 | , expr (e) 21668 | , results (0) 21669 | , retinv_null(false) 21670 | , return_invoked(&retinv_null) 21671 | {} 21672 | 21673 | ~control_block() 21674 | { 21675 | if (expr && details::branch_deletable(expr)) 21676 | { 21677 | destroy_node(expr); 21678 | } 21679 | 21680 | if (!local_data_list.empty()) 21681 | { 21682 | for (std::size_t i = 0; i < local_data_list.size(); ++i) 21683 | { 21684 | switch (local_data_list[i].type) 21685 | { 21686 | case e_expr : delete reinterpret_cast<expression_ptr>(local_data_list[i].pointer); 21687 | break; 21688 | 21689 | case e_vecholder : delete reinterpret_cast<vector_holder_ptr>(local_data_list[i].pointer); 21690 | break; 21691 | 21692 | case e_data : delete reinterpret_cast<T*>(local_data_list[i].pointer); 21693 | break; 21694 | 21695 | case e_vecdata : delete [] reinterpret_cast<T*>(local_data_list[i].pointer); 21696 | break; 21697 | 21698 | case e_string : delete reinterpret_cast<std::string*>(local_data_list[i].pointer); 21699 | break; 21700 | 21701 | default : break; 21702 | } 21703 | } 21704 | } 21705 | 21706 | if (results) 21707 | { 21708 | delete results; 21709 | } 21710 | } 21711 | 21712 | static inline cntrl_blck_ptr_t create(expression_ptr e) 21713 | { 21714 | return new control_block(e); 21715 | } 21716 | 21717 | static inline void destroy(cntrl_blck_ptr_t& cntrl_blck) 21718 | { 21719 | if (cntrl_blck) 21720 | { 21721 | if ( 21722 | (0 != cntrl_blck->ref_count) && 21723 | (0 == --cntrl_blck->ref_count) 21724 | ) 21725 | { 21726 | delete cntrl_blck; 21727 | } 21728 | 21729 | cntrl_blck = 0; 21730 | } 21731 | } 21732 | 21733 | std::size_t ref_count; 21734 | expression_ptr expr; 21735 | local_data_list_t local_data_list; 21736 | results_context_t* results; 21737 | bool retinv_null; 21738 | bool* return_invoked; 21739 | 21740 | friend class function_compositor<T>; 21741 | }; 21742 | 21743 | public: 21744 | 21745 | expression() 21746 | : control_block_(0) 21747 | { 21748 | set_expression(new details::null_node<T>()); 21749 | } 21750 | 21751 | expression(const expression<T>& e) 21752 | : control_block_ (e.control_block_ ) 21753 | , symbol_table_list_(e.symbol_table_list_) 21754 | { 21755 | control_block_->ref_count++; 21756 | } 21757 | 21758 | explicit expression(const symbol_table<T>& symbol_table) 21759 | : control_block_(0) 21760 | { 21761 | set_expression(new details::null_node<T>()); 21762 | symbol_table_list_.push_back(symbol_table); 21763 | } 21764 | 21765 | inline expression<T>& operator=(const expression<T>& e) 21766 | { 21767 | if (this != &e) 21768 | { 21769 | if (control_block_) 21770 | { 21771 | if ( 21772 | (0 != control_block_->ref_count) && 21773 | (0 == --control_block_->ref_count) 21774 | ) 21775 | { 21776 | delete control_block_; 21777 | } 21778 | 21779 | control_block_ = 0; 21780 | } 21781 | 21782 | control_block_ = e.control_block_; 21783 | control_block_->ref_count++; 21784 | symbol_table_list_ = e.symbol_table_list_; 21785 | } 21786 | 21787 | return *this; 21788 | } 21789 | 21790 | inline bool operator==(const expression<T>& e) const 21791 | { 21792 | return (this == &e); 21793 | } 21794 | 21795 | inline bool operator!() const 21796 | { 21797 | return ( 21798 | (0 == control_block_ ) || 21799 | (0 == control_block_->expr) 21800 | ); 21801 | } 21802 | 21803 | inline expression<T>& release() 21804 | { 21805 | exprtk::details::dump_ptr("expression::release", this); 21806 | control_block::destroy(control_block_); 21807 | 21808 | return (*this); 21809 | } 21810 | 21811 | ~expression() 21812 | { 21813 | control_block::destroy(control_block_); 21814 | } 21815 | 21816 | inline T value() const 21817 | { 21818 | assert(control_block_ ); 21819 | assert(control_block_->expr); 21820 | 21821 | return control_block_->expr->value(); 21822 | } 21823 | 21824 | inline T operator() () const 21825 | { 21826 | return value(); 21827 | } 21828 | 21829 | inline operator T() const 21830 | { 21831 | return value(); 21832 | } 21833 | 21834 | inline operator bool() const 21835 | { 21836 | return details::is_true(value()); 21837 | } 21838 | 21839 | inline bool register_symbol_table(symbol_table<T>& st) 21840 | { 21841 | for (std::size_t i = 0; i < symbol_table_list_.size(); ++i) 21842 | { 21843 | if (st == symbol_table_list_[i]) 21844 | { 21845 | return false; 21846 | } 21847 | } 21848 | 21849 | symbol_table_list_.push_back(st); 21850 | return true; 21851 | } 21852 | 21853 | inline const symbol_table<T>& get_symbol_table(const std::size_t& index = 0) const 21854 | { 21855 | return symbol_table_list_[index]; 21856 | } 21857 | 21858 | inline symbol_table<T>& get_symbol_table(const std::size_t& index = 0) 21859 | { 21860 | return symbol_table_list_[index]; 21861 | } 21862 | 21863 | std::size_t num_symbol_tables() const 21864 | { 21865 | return symbol_table_list_.size(); 21866 | } 21867 | 21868 | typedef results_context<T> results_context_t; 21869 | 21870 | inline const results_context_t& results() const 21871 | { 21872 | if (control_block_->results) 21873 | return (*control_block_->results); 21874 | else 21875 | { 21876 | static const results_context_t null_results; 21877 | return null_results; 21878 | } 21879 | } 21880 | 21881 | inline bool return_invoked() const 21882 | { 21883 | return (*control_block_->return_invoked); 21884 | } 21885 | 21886 | private: 21887 | 21888 | inline symtab_list_t get_symbol_table_list() const 21889 | { 21890 | return symbol_table_list_; 21891 | } 21892 | 21893 | inline void set_expression(const expression_ptr expr) 21894 | { 21895 | if (expr) 21896 | { 21897 | if (control_block_) 21898 | { 21899 | if (0 == --control_block_->ref_count) 21900 | { 21901 | delete control_block_; 21902 | } 21903 | } 21904 | 21905 | control_block_ = control_block::create(expr); 21906 | } 21907 | } 21908 | 21909 | inline void register_local_var(expression_ptr expr) 21910 | { 21911 | if (expr) 21912 | { 21913 | if (control_block_) 21914 | { 21915 | control_block_-> 21916 | local_data_list.push_back( 21917 | typename expression<T>::control_block:: 21918 | data_pack(reinterpret_cast<void*>(expr), 21919 | control_block::e_expr)); 21920 | } 21921 | } 21922 | } 21923 | 21924 | inline void register_local_var(vector_holder_ptr vec_holder) 21925 | { 21926 | if (vec_holder) 21927 | { 21928 | if (control_block_) 21929 | { 21930 | control_block_-> 21931 | local_data_list.push_back( 21932 | typename expression<T>::control_block:: 21933 | data_pack(reinterpret_cast<void*>(vec_holder), 21934 | control_block::e_vecholder)); 21935 | } 21936 | } 21937 | } 21938 | 21939 | inline void register_local_data(void* data, const std::size_t& size = 0, const std::size_t data_mode = 0) 21940 | { 21941 | if (data) 21942 | { 21943 | if (control_block_) 21944 | { 21945 | typename control_block::data_type dt = control_block::e_data; 21946 | 21947 | switch (data_mode) 21948 | { 21949 | case 0 : dt = control_block::e_data; break; 21950 | case 1 : dt = control_block::e_vecdata; break; 21951 | case 2 : dt = control_block::e_string; break; 21952 | } 21953 | 21954 | control_block_-> 21955 | local_data_list.push_back( 21956 | typename expression<T>::control_block:: 21957 | data_pack(reinterpret_cast<void*>(data), dt, size)); 21958 | } 21959 | } 21960 | } 21961 | 21962 | inline const typename control_block::local_data_list_t& local_data_list() 21963 | { 21964 | if (control_block_) 21965 | { 21966 | return control_block_->local_data_list; 21967 | } 21968 | else 21969 | { 21970 | static typename control_block::local_data_list_t null_local_data_list; 21971 | return null_local_data_list; 21972 | } 21973 | } 21974 | 21975 | inline void register_return_results(results_context_t* rc) 21976 | { 21977 | if (control_block_ && rc) 21978 | { 21979 | control_block_->results = rc; 21980 | } 21981 | } 21982 | 21983 | inline void set_retinvk(bool* retinvk_ptr) 21984 | { 21985 | if (control_block_) 21986 | { 21987 | control_block_->return_invoked = retinvk_ptr; 21988 | } 21989 | } 21990 | 21991 | control_block* control_block_; 21992 | symtab_list_t symbol_table_list_; 21993 | 21994 | friend class parser<T>; 21995 | friend class expression_helper<T>; 21996 | friend class function_compositor<T>; 21997 | template <typename TT> 21998 | friend bool is_valid(const expression<TT>& expr); 21999 | }; // class expression 22000 | 22001 | template <typename T> 22002 | class expression_helper 22003 | { 22004 | public: 22005 | 22006 | enum node_types 22007 | { 22008 | e_literal, 22009 | e_variable, 22010 | e_string, 22011 | e_unary, 22012 | e_binary, 22013 | e_function, 22014 | e_vararg, 22015 | e_null, 22016 | e_assert, 22017 | e_sf3ext, 22018 | e_sf4ext 22019 | }; 22020 | 22021 | static inline bool is_literal(const expression<T>& expr) 22022 | { 22023 | return expr.control_block_ && details::is_literal_node(expr.control_block_->expr); 22024 | } 22025 | 22026 | static inline bool is_variable(const expression<T>& expr) 22027 | { 22028 | return expr.control_block_ && details::is_variable_node(expr.control_block_->expr); 22029 | } 22030 | 22031 | static inline bool is_string(const expression<T>& expr) 22032 | { 22033 | return expr.control_block_ && details::is_generally_string_node(expr.control_block_->expr); 22034 | } 22035 | 22036 | static inline bool is_unary(const expression<T>& expr) 22037 | { 22038 | return expr.control_block_ && details::is_unary_node(expr.control_block_->expr); 22039 | } 22040 | 22041 | static inline bool is_binary(const expression<T>& expr) 22042 | { 22043 | return expr.control_block_ && details::is_binary_node(expr.control_block_->expr); 22044 | } 22045 | 22046 | static inline bool is_function(const expression<T>& expr) 22047 | { 22048 | return expr.control_block_ && details::is_function(expr.control_block_->expr); 22049 | } 22050 | 22051 | static inline bool is_vararg(const expression<T>& expr) 22052 | { 22053 | return expr.control_block_ && details::is_vararg_node(expr.control_block_->expr); 22054 | } 22055 | 22056 | static inline bool is_null(const expression<T>& expr) 22057 | { 22058 | return expr.control_block_ && details::is_null_node(expr.control_block_->expr); 22059 | } 22060 | 22061 | static inline bool is_assert(const expression<T>& expr) 22062 | { 22063 | return expr.control_block_ && details::is_assert_node(expr.control_block_->expr); 22064 | } 22065 | 22066 | static inline bool is_sf3ext(const expression<T>& expr) 22067 | { 22068 | return expr.control_block_ && details::is_sf3ext_node(expr.control_block_->expr); 22069 | } 22070 | 22071 | static inline bool is_sf4ext(const expression<T>& expr) 22072 | { 22073 | return expr.control_block_ && details::is_sf4ext_node(expr.control_block_->expr); 22074 | } 22075 | 22076 | static inline bool is_type(const expression<T>& expr, const node_types node_type) 22077 | { 22078 | if (0 == expr.control_block_) 22079 | { 22080 | return false; 22081 | } 22082 | 22083 | switch (node_type) 22084 | { 22085 | case e_literal : return is_literal_node(expr); 22086 | case e_variable : return is_variable (expr); 22087 | case e_string : return is_string (expr); 22088 | case e_unary : return is_unary (expr); 22089 | case e_binary : return is_binary (expr); 22090 | case e_function : return is_function (expr); 22091 | case e_null : return is_null (expr); 22092 | case e_assert : return is_assert (expr); 22093 | case e_sf3ext : return is_sf3ext (expr); 22094 | case e_sf4ext : return is_sf4ext (expr); 22095 | }; 22096 | 22097 | return false; 22098 | } 22099 | 22100 | static inline bool match_type_sequence(const expression<T>& expr, const std::vector<node_types>& type_seq) 22101 | { 22102 | if ((0 == expr.control_block_) || !is_vararg(expr)) 22103 | { 22104 | return false; 22105 | } 22106 | 22107 | typedef details::vararg_node<T, exprtk::details::vararg_multi_op<T> > mo_vararg_t; 22108 | 22109 | mo_vararg_t* vnode = dynamic_cast<mo_vararg_t*>(expr.control_block_->expr); 22110 | 22111 | if ( 22112 | (0 == vnode) || 22113 | type_seq.empty() || 22114 | (vnode->size() < type_seq.size()) 22115 | ) 22116 | { 22117 | return false; 22118 | } 22119 | 22120 | for (std::size_t i = 0; i < type_seq.size(); ++i) 22121 | { 22122 | assert((*vnode)[i]); 22123 | 22124 | switch (type_seq[i]) 22125 | { 22126 | case e_literal : { if (details::is_literal_node ((*vnode)[i])) continue; } break; 22127 | case e_variable : { if (details::is_variable_node ((*vnode)[i])) continue; } break; 22128 | case e_string : { if (details::is_generally_string_node((*vnode)[i])) continue; } break; 22129 | case e_unary : { if (details::is_unary_node ((*vnode)[i])) continue; } break; 22130 | case e_binary : { if (details::is_binary_node ((*vnode)[i])) continue; } break; 22131 | case e_function : { if (details::is_function ((*vnode)[i])) continue; } break; 22132 | case e_null : { if (details::is_null_node ((*vnode)[i])) continue; } break; 22133 | case e_assert : { if (details::is_assert_node ((*vnode)[i])) continue; } break; 22134 | case e_sf3ext : { if (details::is_sf3ext_node ((*vnode)[i])) continue; } break; 22135 | case e_sf4ext : { if (details::is_sf4ext_node ((*vnode)[i])) continue; } break; 22136 | case e_vararg : break; 22137 | } 22138 | 22139 | return false; 22140 | } 22141 | 22142 | return true; 22143 | } 22144 | }; 22145 | 22146 | template <typename T> 22147 | inline bool is_valid(const expression<T>& expr) 22148 | { 22149 | return expr.control_block_ && !expression_helper<T>::is_null(expr); 22150 | } 22151 | 22152 | namespace parser_error 22153 | { 22154 | enum error_mode 22155 | { 22156 | e_unknown = 0, 22157 | e_syntax = 1, 22158 | e_token = 2, 22159 | e_numeric = 4, 22160 | e_symtab = 5, 22161 | e_lexer = 6, 22162 | e_synthesis = 7, 22163 | e_helper = 8, 22164 | e_parser = 9 22165 | }; 22166 | 22167 | struct type 22168 | { 22169 | type() 22170 | : mode(parser_error::e_unknown) 22171 | , line_no (0) 22172 | , column_no(0) 22173 | {} 22174 | 22175 | lexer::token token; 22176 | error_mode mode; 22177 | std::string diagnostic; 22178 | std::string src_location; 22179 | std::string error_line; 22180 | std::size_t line_no; 22181 | std::size_t column_no; 22182 | }; 22183 | 22184 | inline type make_error(const error_mode mode, 22185 | const std::string& diagnostic = "", 22186 | const std::string& src_location = "") 22187 | { 22188 | type t; 22189 | t.mode = mode; 22190 | t.token.type = lexer::token::e_error; 22191 | t.diagnostic = diagnostic; 22192 | t.src_location = src_location; 22193 | exprtk_debug(("%s\n", diagnostic .c_str())); 22194 | return t; 22195 | } 22196 | 22197 | inline type make_error(const error_mode mode, 22198 | const lexer::token& tk, 22199 | const std::string& diagnostic = "", 22200 | const std::string& src_location = "") 22201 | { 22202 | type t; 22203 | t.mode = mode; 22204 | t.token = tk; 22205 | t.diagnostic = diagnostic; 22206 | t.src_location = src_location; 22207 | exprtk_debug(("%s\n", diagnostic .c_str())); 22208 | return t; 22209 | } 22210 | 22211 | inline std::string to_str(error_mode mode) 22212 | { 22213 | switch (mode) 22214 | { 22215 | case e_unknown : return std::string("Unknown Error"); 22216 | case e_syntax : return std::string("Syntax Error" ); 22217 | case e_token : return std::string("Token Error" ); 22218 | case e_numeric : return std::string("Numeric Error"); 22219 | case e_symtab : return std::string("Symbol Error" ); 22220 | case e_lexer : return std::string("Lexer Error" ); 22221 | case e_helper : return std::string("Helper Error" ); 22222 | case e_parser : return std::string("Parser Error" ); 22223 | default : return std::string("Unknown Error"); 22224 | } 22225 | } 22226 | 22227 | inline bool update_error(type& error, const std::string& expression) 22228 | { 22229 | if ( 22230 | expression.empty() || 22231 | (error.token.position > expression.size()) || 22232 | (std::numeric_limits<std::size_t>::max() == error.token.position) 22233 | ) 22234 | { 22235 | return false; 22236 | } 22237 | 22238 | std::size_t error_line_start = 0; 22239 | 22240 | for (std::size_t i = error.token.position; i > 0; --i) 22241 | { 22242 | const details::char_t c = expression[i]; 22243 | 22244 | if (('\n' == c) || ('\r' == c)) 22245 | { 22246 | error_line_start = i + 1; 22247 | break; 22248 | } 22249 | } 22250 | 22251 | std::size_t next_nl_position = std::min(expression.size(), 22252 | expression.find_first_of('\n',error.token.position + 1)); 22253 | 22254 | error.column_no = error.token.position - error_line_start; 22255 | error.error_line = expression.substr(error_line_start, 22256 | next_nl_position - error_line_start); 22257 | 22258 | error.line_no = 0; 22259 | 22260 | for (std::size_t i = 0; i < next_nl_position; ++i) 22261 | { 22262 | if ('\n' == expression[i]) 22263 | ++error.line_no; 22264 | } 22265 | 22266 | return true; 22267 | } 22268 | 22269 | inline void dump_error(const type& error) 22270 | { 22271 | printf("Position: %02d Type: [%s] Msg: %s\n", 22272 | static_cast<int>(error.token.position), 22273 | exprtk::parser_error::to_str(error.mode).c_str(), 22274 | error.diagnostic.c_str()); 22275 | } 22276 | } 22277 | 22278 | namespace details 22279 | { 22280 | template <typename Parser> 22281 | inline void disable_type_checking(Parser& p) 22282 | { 22283 | p.state_.type_check_enabled = false; 22284 | } 22285 | } 22286 | 22287 | template <typename T> 22288 | class parser : public lexer::parser_helper 22289 | { 22290 | private: 22291 | 22292 | enum precedence_level 22293 | { 22294 | e_level00, e_level01, e_level02, e_level03, e_level04, 22295 | e_level05, e_level06, e_level07, e_level08, e_level09, 22296 | e_level10, e_level11, e_level12, e_level13, e_level14 22297 | }; 22298 | 22299 | typedef const T& cref_t; 22300 | typedef const T const_t; 22301 | typedef ifunction<T> F; 22302 | typedef ivararg_function<T> VAF; 22303 | typedef igeneric_function<T> GF; 22304 | typedef ifunction<T> ifunction_t; 22305 | typedef ivararg_function<T> ivararg_function_t; 22306 | typedef igeneric_function<T> igeneric_function_t; 22307 | typedef details::expression_node<T> expression_node_t; 22308 | typedef details::literal_node<T> literal_node_t; 22309 | typedef details::unary_node<T> unary_node_t; 22310 | typedef details::binary_node<T> binary_node_t; 22311 | typedef details::trinary_node<T> trinary_node_t; 22312 | typedef details::quaternary_node<T> quaternary_node_t; 22313 | typedef details::conditional_node<T> conditional_node_t; 22314 | typedef details::cons_conditional_node<T> cons_conditional_node_t; 22315 | typedef details::while_loop_node<T> while_loop_node_t; 22316 | typedef details::repeat_until_loop_node<T> repeat_until_loop_node_t; 22317 | typedef details::for_loop_node<T> for_loop_node_t; 22318 | typedef details::while_loop_rtc_node<T> while_loop_rtc_node_t; 22319 | typedef details::repeat_until_loop_rtc_node<T> repeat_until_loop_rtc_node_t; 22320 | typedef details::for_loop_rtc_node<T> for_loop_rtc_node_t; 22321 | #ifndef exprtk_disable_break_continue 22322 | typedef details::while_loop_bc_node<T> while_loop_bc_node_t; 22323 | typedef details::repeat_until_loop_bc_node<T> repeat_until_loop_bc_node_t; 22324 | typedef details::for_loop_bc_node<T> for_loop_bc_node_t; 22325 | typedef details::while_loop_bc_rtc_node<T> while_loop_bc_rtc_node_t; 22326 | typedef details::repeat_until_loop_bc_rtc_node<T> repeat_until_loop_bc_rtc_node_t; 22327 | typedef details::for_loop_bc_rtc_node<T> for_loop_bc_rtc_node_t; 22328 | #endif 22329 | typedef details::switch_node<T> switch_node_t; 22330 | typedef details::variable_node<T> variable_node_t; 22331 | typedef details::vector_elem_node<T> vector_elem_node_t; 22332 | typedef details::vector_celem_node<T> vector_celem_node_t; 22333 | typedef details::vector_elem_rtc_node<T> vector_elem_rtc_node_t; 22334 | typedef details::vector_celem_rtc_node<T> vector_celem_rtc_node_t; 22335 | typedef details::rebasevector_elem_node<T> rebasevector_elem_node_t; 22336 | typedef details::rebasevector_celem_node<T> rebasevector_celem_node_t; 22337 | typedef details::rebasevector_elem_rtc_node<T> rebasevector_elem_rtc_node_t; 22338 | typedef details::rebasevector_celem_rtc_node<T> rebasevector_celem_rtc_node_t; 22339 | typedef details::vector_node<T> vector_node_t; 22340 | typedef details::vector_size_node<T> vector_size_node_t; 22341 | typedef details::range_pack<T> range_t; 22342 | #ifndef exprtk_disable_string_capabilities 22343 | typedef details::stringvar_node<T> stringvar_node_t; 22344 | typedef details::string_literal_node<T> string_literal_node_t; 22345 | typedef details::string_range_node<T> string_range_node_t; 22346 | typedef details::const_string_range_node<T> const_string_range_node_t; 22347 | typedef details::generic_string_range_node<T> generic_string_range_node_t; 22348 | typedef details::string_concat_node<T> string_concat_node_t; 22349 | typedef details::assignment_string_node<T> assignment_string_node_t; 22350 | typedef details::assignment_string_range_node<T> assignment_string_range_node_t; 22351 | typedef details::conditional_string_node<T> conditional_string_node_t; 22352 | typedef details::cons_conditional_str_node<T> cons_conditional_str_node_t; 22353 | #endif 22354 | typedef details::assignment_node<T> assignment_node_t; 22355 | typedef details::assignment_vec_elem_node<T> assignment_vec_elem_node_t; 22356 | typedef details::assignment_vec_elem_rtc_node<T> assignment_vec_elem_rtc_node_t; 22357 | typedef details::assignment_rebasevec_elem_node<T> assignment_rebasevec_elem_node_t; 22358 | typedef details::assignment_rebasevec_elem_rtc_node<T> assignment_rebasevec_elem_rtc_node_t; 22359 | typedef details::assignment_rebasevec_celem_node<T> assignment_rebasevec_celem_node_t; 22360 | typedef details::assignment_vec_node<T> assignment_vec_node_t; 22361 | typedef details::assignment_vecvec_node<T> assignment_vecvec_node_t; 22362 | typedef details::conditional_vector_node<T> conditional_vector_node_t; 22363 | typedef details::scand_node<T> scand_node_t; 22364 | typedef details::scor_node<T> scor_node_t; 22365 | typedef lexer::token token_t; 22366 | typedef expression_node_t* expression_node_ptr; 22367 | typedef expression<T> expression_t; 22368 | typedef symbol_table<T> symbol_table_t; 22369 | typedef typename expression<T>::symtab_list_t symbol_table_list_t; 22370 | typedef details::vector_holder<T> vector_holder_t; 22371 | typedef vector_holder_t* vector_holder_ptr; 22372 | 22373 | typedef typename details::functor_t<T> functor_t; 22374 | typedef typename functor_t::qfunc_t quaternary_functor_t; 22375 | typedef typename functor_t::tfunc_t trinary_functor_t; 22376 | typedef typename functor_t::bfunc_t binary_functor_t; 22377 | typedef typename functor_t::ufunc_t unary_functor_t; 22378 | 22379 | typedef details::operator_type operator_t; 22380 | 22381 | typedef std::map<operator_t, unary_functor_t > unary_op_map_t; 22382 | typedef std::map<operator_t, binary_functor_t > binary_op_map_t; 22383 | typedef std::map<operator_t, trinary_functor_t> trinary_op_map_t; 22384 | 22385 | typedef std::map<std::string,std::pair<trinary_functor_t ,operator_t> > sf3_map_t; 22386 | typedef std::map<std::string,std::pair<quaternary_functor_t,operator_t> > sf4_map_t; 22387 | 22388 | typedef std::map<binary_functor_t,operator_t> inv_binary_op_map_t; 22389 | typedef std::multimap<std::string,details::base_operation_t,details::ilesscompare> base_ops_map_t; 22390 | typedef std::set<std::string,details::ilesscompare> disabled_func_set_t; 22391 | 22392 | typedef details::T0oT1_define<T, cref_t , cref_t > vov_t; 22393 | typedef details::T0oT1_define<T, const_t, cref_t > cov_t; 22394 | typedef details::T0oT1_define<T, cref_t , const_t> voc_t; 22395 | 22396 | typedef details::T0oT1oT2_define<T, cref_t , cref_t , cref_t > vovov_t; 22397 | typedef details::T0oT1oT2_define<T, cref_t , cref_t , const_t> vovoc_t; 22398 | typedef details::T0oT1oT2_define<T, cref_t , const_t, cref_t > vocov_t; 22399 | typedef details::T0oT1oT2_define<T, const_t, cref_t , cref_t > covov_t; 22400 | typedef details::T0oT1oT2_define<T, const_t, cref_t , const_t> covoc_t; 22401 | typedef details::T0oT1oT2_define<T, const_t, const_t, cref_t > cocov_t; 22402 | typedef details::T0oT1oT2_define<T, cref_t , const_t, const_t> vococ_t; 22403 | 22404 | typedef details::T0oT1oT2oT3_define<T, cref_t , cref_t , cref_t , cref_t > vovovov_t; 22405 | typedef details::T0oT1oT2oT3_define<T, cref_t , cref_t , cref_t , const_t> vovovoc_t; 22406 | typedef details::T0oT1oT2oT3_define<T, cref_t , cref_t , const_t, cref_t > vovocov_t; 22407 | typedef details::T0oT1oT2oT3_define<T, cref_t , const_t, cref_t , cref_t > vocovov_t; 22408 | typedef details::T0oT1oT2oT3_define<T, const_t, cref_t , cref_t , cref_t > covovov_t; 22409 | 22410 | typedef details::T0oT1oT2oT3_define<T, const_t, cref_t , const_t, cref_t > covocov_t; 22411 | typedef details::T0oT1oT2oT3_define<T, cref_t , const_t, cref_t , const_t> vocovoc_t; 22412 | typedef details::T0oT1oT2oT3_define<T, const_t, cref_t , cref_t , const_t> covovoc_t; 22413 | typedef details::T0oT1oT2oT3_define<T, cref_t , const_t, const_t, cref_t > vococov_t; 22414 | 22415 | typedef results_context<T> results_context_t; 22416 | 22417 | typedef parser_helper prsrhlpr_t; 22418 | 22419 | struct scope_element 22420 | { 22421 | enum element_type 22422 | { 22423 | e_none , 22424 | e_literal , 22425 | e_variable, 22426 | e_vector , 22427 | e_vecelem , 22428 | e_string 22429 | }; 22430 | 22431 | typedef details::vector_holder<T> vector_holder_t; 22432 | typedef literal_node_t* literal_node_ptr; 22433 | typedef variable_node_t* variable_node_ptr; 22434 | typedef vector_holder_t* vector_holder_ptr; 22435 | typedef expression_node_t* expression_node_ptr; 22436 | #ifndef exprtk_disable_string_capabilities 22437 | typedef stringvar_node_t* stringvar_node_ptr; 22438 | #endif 22439 | 22440 | scope_element() 22441 | : name("???") 22442 | , size (std::numeric_limits<std::size_t>::max()) 22443 | , index(std::numeric_limits<std::size_t>::max()) 22444 | , depth(std::numeric_limits<std::size_t>::max()) 22445 | , ref_count(0) 22446 | , ip_index (0) 22447 | , type (e_none) 22448 | , active (false) 22449 | , data (0) 22450 | , var_node (0) 22451 | , vec_node (0) 22452 | #ifndef exprtk_disable_string_capabilities 22453 | , str_node(0) 22454 | #endif 22455 | {} 22456 | 22457 | bool operator < (const scope_element& se) const 22458 | { 22459 | if (ip_index < se.ip_index) 22460 | return true; 22461 | else if (ip_index > se.ip_index) 22462 | return false; 22463 | else if (depth < se.depth) 22464 | return true; 22465 | else if (depth > se.depth) 22466 | return false; 22467 | else if (index < se.index) 22468 | return true; 22469 | else if (index > se.index) 22470 | return false; 22471 | else 22472 | return (name < se.name); 22473 | } 22474 | 22475 | void clear() 22476 | { 22477 | name = "???" 22478 | size = std::numeric_limits<std::size_t>::max(); 22479 | index = std::numeric_limits<std::size_t>::max(); 22480 | depth = std::numeric_limits<std::size_t>::max(); 22481 | type = e_none; 22482 | active = false; 22483 | ref_count = 0; 22484 | ip_index = 0; 22485 | data = 0; 22486 | var_node = 0; 22487 | vec_node = 0; 22488 | #ifndef exprtk_disable_string_capabilities 22489 | str_node = 0; 22490 | #endif 22491 | } 22492 | 22493 | std::string name; 22494 | std::size_t size; 22495 | std::size_t index; 22496 | std::size_t depth; 22497 | std::size_t ref_count; 22498 | std::size_t ip_index; 22499 | element_type type; 22500 | bool active; 22501 | void* data; 22502 | expression_node_ptr var_node; 22503 | vector_holder_ptr vec_node; 22504 | #ifndef exprtk_disable_string_capabilities 22505 | stringvar_node_ptr str_node; 22506 | #endif 22507 | }; 22508 | 22509 | class scope_element_manager 22510 | { 22511 | public: 22512 | 22513 | typedef expression_node_t* expression_node_ptr; 22514 | typedef variable_node_t* variable_node_ptr; 22515 | typedef parser<T> parser_t; 22516 | 22517 | explicit scope_element_manager(parser<T>& p) 22518 | : parser_(p) 22519 | , input_param_cnt_(0) 22520 | , total_local_symb_size_bytes_(0) 22521 | {} 22522 | 22523 | inline std::size_t size() const 22524 | { 22525 | return element_.size(); 22526 | } 22527 | 22528 | inline bool empty() const 22529 | { 22530 | return element_.empty(); 22531 | } 22532 | 22533 | inline scope_element& get_element(const std::size_t& index) 22534 | { 22535 | if (index < element_.size()) 22536 | return element_[index]; 22537 | else 22538 | return null_element_; 22539 | } 22540 | 22541 | inline scope_element& get_element(const std::string& var_name, 22542 | const std::size_t index = std::numeric_limits<std::size_t>::max()) 22543 | { 22544 | const std::size_t current_depth = parser_.state_.scope_depth; 22545 | 22546 | for (std::size_t i = 0; i < element_.size(); ++i) 22547 | { 22548 | scope_element& se = element_[i]; 22549 | 22550 | if (se.depth > current_depth) 22551 | continue; 22552 | else if ( 22553 | details::imatch(se.name, var_name) && 22554 | (se.index == index) 22555 | ) 22556 | return se; 22557 | } 22558 | 22559 | return null_element_; 22560 | } 22561 | 22562 | inline scope_element& get_active_element(const std::string& var_name, 22563 | const std::size_t index = std::numeric_limits<std::size_t>::max()) 22564 | { 22565 | const std::size_t current_depth = parser_.state_.scope_depth; 22566 | 22567 | for (std::size_t i = 0; i < element_.size(); ++i) 22568 | { 22569 | scope_element& se = element_[i]; 22570 | 22571 | if (se.depth > current_depth) 22572 | continue; 22573 | else if ( 22574 | details::imatch(se.name, var_name) && 22575 | (se.index == index) && 22576 | (se.active) 22577 | ) 22578 | return se; 22579 | } 22580 | 22581 | return null_element_; 22582 | } 22583 | 22584 | inline bool add_element(const scope_element& se) 22585 | { 22586 | for (std::size_t i = 0; i < element_.size(); ++i) 22587 | { 22588 | scope_element& cse = element_[i]; 22589 | 22590 | if ( 22591 | details::imatch(cse.name, se.name) && 22592 | (cse.depth <= se.depth) && 22593 | (cse.index == se.index) && 22594 | (cse.size == se.size ) && 22595 | (cse.type == se.type ) && 22596 | (cse.active) 22597 | ) 22598 | return false; 22599 | } 22600 | 22601 | switch (se.type) 22602 | { 22603 | case scope_element::e_variable : total_local_symb_size_bytes_ += sizeof(T); 22604 | break; 22605 | 22606 | case scope_element::e_literal : total_local_symb_size_bytes_ += sizeof(T); 22607 | break; 22608 | 22609 | case scope_element::e_vector : total_local_symb_size_bytes_ += sizeof(T) * se.size; 22610 | break; 22611 | 22612 | default : break; 22613 | } 22614 | 22615 | element_.push_back(se); 22616 | std::sort(element_.begin(),element_.end()); 22617 | 22618 | return true; 22619 | } 22620 | 22621 | inline void deactivate(const std::size_t& scope_depth) 22622 | { 22623 | exprtk_debug(("deactivate() - Scope depth: %d\n", 22624 | static_cast<int>(parser_.state_.scope_depth))); 22625 | 22626 | for (std::size_t i = 0; i < element_.size(); ++i) 22627 | { 22628 | scope_element& se = element_[i]; 22629 | 22630 | if (se.active && (se.depth >= scope_depth)) 22631 | { 22632 | exprtk_debug(("deactivate() - element[%02d] '%s'\n", 22633 | static_cast<int>(i), 22634 | se.name.c_str())); 22635 | 22636 | se.active = false; 22637 | } 22638 | } 22639 | } 22640 | 22641 | inline void free_element(scope_element& se) 22642 | { 22643 | exprtk_debug(("free_element() - se[%s]\n", se.name.c_str())); 22644 | 22645 | switch (se.type) 22646 | { 22647 | case scope_element::e_literal : delete reinterpret_cast<T*>(se.data); 22648 | delete se.var_node; 22649 | break; 22650 | 22651 | case scope_element::e_variable : delete reinterpret_cast<T*>(se.data); 22652 | delete se.var_node; 22653 | break; 22654 | 22655 | case scope_element::e_vector : delete[] reinterpret_cast<T*>(se.data); 22656 | delete se.vec_node; 22657 | break; 22658 | 22659 | case scope_element::e_vecelem : delete se.var_node; 22660 | break; 22661 | 22662 | #ifndef exprtk_disable_string_capabilities 22663 | case scope_element::e_string : delete reinterpret_cast<std::string*>(se.data); 22664 | delete se.str_node; 22665 | break; 22666 | #endif 22667 | 22668 | default : return; 22669 | } 22670 | 22671 | se.clear(); 22672 | } 22673 | 22674 | inline void cleanup() 22675 | { 22676 | for (std::size_t i = 0; i < element_.size(); ++i) 22677 | { 22678 | free_element(element_[i]); 22679 | } 22680 | 22681 | element_.clear(); 22682 | 22683 | input_param_cnt_ = 0; 22684 | total_local_symb_size_bytes_ = 0; 22685 | } 22686 | 22687 | inline std::size_t total_local_symb_size_bytes() const 22688 | { 22689 | return total_local_symb_size_bytes_; 22690 | } 22691 | 22692 | inline std::size_t next_ip_index() 22693 | { 22694 | return ++input_param_cnt_; 22695 | } 22696 | 22697 | inline expression_node_ptr get_variable(const T& v) 22698 | { 22699 | for (std::size_t i = 0; i < element_.size(); ++i) 22700 | { 22701 | scope_element& se = element_[i]; 22702 | 22703 | if ( 22704 | se.active && 22705 | se.var_node && 22706 | details::is_variable_node(se.var_node) 22707 | ) 22708 | { 22709 | variable_node_ptr vn = reinterpret_cast<variable_node_ptr>(se.var_node); 22710 | 22711 | if (&(vn->ref()) == (&v)) 22712 | { 22713 | return se.var_node; 22714 | } 22715 | } 22716 | } 22717 | 22718 | return expression_node_ptr(0); 22719 | } 22720 | 22721 | inline std::string get_vector_name(const T* data) 22722 | { 22723 | for (std::size_t i = 0; i < element_.size(); ++i) 22724 | { 22725 | scope_element& se = element_[i]; 22726 | 22727 | if ( 22728 | se.active && 22729 | se.vec_node && 22730 | (se.vec_node->data() == data) 22731 | ) 22732 | { 22733 | return se.name; 22734 | } 22735 | } 22736 | 22737 | return "neo-vector" 22738 | } 22739 | 22740 | private: 22741 | 22742 | scope_element_manager(const scope_element_manager&) exprtk_delete; 22743 | scope_element_manager& operator=(const scope_element_manager&) exprtk_delete; 22744 | 22745 | parser_t& parser_; 22746 | std::vector<scope_element> element_; 22747 | scope_element null_element_; 22748 | std::size_t input_param_cnt_; 22749 | std::size_t total_local_symb_size_bytes_; 22750 | }; 22751 | 22752 | class scope_handler 22753 | { 22754 | public: 22755 | 22756 | typedef parser<T> parser_t; 22757 | 22758 | explicit scope_handler(parser<T>& p) 22759 | : parser_(p) 22760 | { 22761 | parser_.state_.scope_depth++; 22762 | #ifdef exprtk_enable_debugging 22763 | const std::string depth(2 * parser_.state_.scope_depth,'-'); 22764 | exprtk_debug(("%s> Scope Depth: %02d\n", 22765 | depth.c_str(), 22766 | static_cast<int>(parser_.state_.scope_depth))); 22767 | #endif 22768 | } 22769 | 22770 | ~scope_handler() 22771 | { 22772 | parser_.sem_.deactivate(parser_.state_.scope_depth); 22773 | parser_.state_.scope_depth--; 22774 | #ifdef exprtk_enable_debugging 22775 | const std::string depth(2 * parser_.state_.scope_depth,'-'); 22776 | exprtk_debug(("<%s Scope Depth: %02d\n", 22777 | depth.c_str(), 22778 | static_cast<int>(parser_.state_.scope_depth))); 22779 | #endif 22780 | } 22781 | 22782 | private: 22783 | 22784 | scope_handler(const scope_handler&) exprtk_delete; 22785 | scope_handler& operator=(const scope_handler&) exprtk_delete; 22786 | 22787 | parser_t& parser_; 22788 | }; 22789 | 22790 | template <typename T_> 22791 | struct halfopen_range_policy 22792 | { 22793 | static inline bool is_within(const T_& v, const T_& begin, const T_& end) 22794 | { 22795 | assert(begin <= end); 22796 | return (begin <= v) && (v < end); 22797 | } 22798 | 22799 | static inline bool is_less(const T_& v, const T_& begin) 22800 | { 22801 | return (v < begin); 22802 | } 22803 | 22804 | static inline bool is_greater(const T_& v, const T_& end) 22805 | { 22806 | return (end <= v); 22807 | } 22808 | 22809 | static inline bool end_inclusive() 22810 | { 22811 | return false; 22812 | } 22813 | }; 22814 | 22815 | template <typename T_> 22816 | struct closed_range_policy 22817 | { 22818 | static inline bool is_within(const T_& v, const T_& begin, const T_& end) 22819 | { 22820 | assert(begin <= end); 22821 | return (begin <= v) && (v <= end); 22822 | } 22823 | 22824 | static inline bool is_less(const T_& v, const T_& begin) 22825 | { 22826 | return (v < begin); 22827 | } 22828 | 22829 | static inline bool is_greater(const T_& v, const T_& end) 22830 | { 22831 | return (end < v); 22832 | } 22833 | 22834 | static inline bool end_inclusive() 22835 | { 22836 | return true; 22837 | } 22838 | }; 22839 | 22840 | template <typename IntervalPointType, 22841 | typename RangePolicy = halfopen_range_policy<IntervalPointType> > 22842 | class interval_container_t 22843 | { 22844 | public: 22845 | 22846 | typedef IntervalPointType interval_point_t; 22847 | typedef std::pair<interval_point_t, interval_point_t> interval_t; 22848 | typedef std::map<interval_point_t, interval_t> interval_map_t; 22849 | typedef typename interval_map_t::const_iterator interval_map_citr_t; 22850 | 22851 | std::size_t size() const 22852 | { 22853 | return interval_map_.size(); 22854 | } 22855 | 22856 | void reset() 22857 | { 22858 | interval_map_.clear(); 22859 | } 22860 | 22861 | bool in_interval(const interval_point_t point, interval_t& interval) const 22862 | { 22863 | interval_map_citr_t itr = RangePolicy::end_inclusive() ? 22864 | interval_map_.lower_bound(point): 22865 | interval_map_.upper_bound(point); 22866 | 22867 | for (; itr != interval_map_.end(); ++itr) 22868 | { 22869 | const interval_point_t& begin = itr->second.first; 22870 | const interval_point_t& end = itr->second.second; 22871 | 22872 | if (RangePolicy::is_within(point, begin, end)) 22873 | { 22874 | interval = interval_t(begin,end); 22875 | return true; 22876 | } 22877 | else if (RangePolicy::is_greater(point, end)) 22878 | { 22879 | break; 22880 | } 22881 | } 22882 | 22883 | return false; 22884 | } 22885 | 22886 | bool in_interval(const interval_point_t point) const 22887 | { 22888 | interval_t interval; 22889 | return in_interval(point,interval); 22890 | } 22891 | 22892 | bool add_interval(const interval_point_t begin, const interval_point_t end) 22893 | { 22894 | if ((end <= begin) || in_interval(begin) || in_interval(end)) 22895 | { 22896 | return false; 22897 | } 22898 | 22899 | interval_map_[end] = std::make_pair(begin, end); 22900 | 22901 | return true; 22902 | } 22903 | 22904 | bool add_interval(const interval_t interval) 22905 | { 22906 | return add_interval(interval.first, interval.second); 22907 | } 22908 | 22909 | private: 22910 | 22911 | interval_map_t interval_map_; 22912 | }; 22913 | 22914 | class stack_limit_handler 22915 | { 22916 | public: 22917 | 22918 | typedef parser<T> parser_t; 22919 | 22920 | explicit stack_limit_handler(parser<T>& p) 22921 | : parser_(p) 22922 | , limit_exceeded_(false) 22923 | { 22924 | if (++parser_.state_.stack_depth > parser_.settings_.max_stack_depth_) 22925 | { 22926 | limit_exceeded_ = true; 22927 | parser_.set_error(make_error( 22928 | parser_error::e_parser, 22929 | "ERR000 - Current stack depth " + details::to_str(parser_.state_.stack_depth) + 22930 | " exceeds maximum allowed stack depth of " + details::to_str(parser_.settings_.max_stack_depth_), 22931 | exprtk_error_location)); 22932 | } 22933 | } 22934 | 22935 | ~stack_limit_handler() 22936 | { 22937 | assert(parser_.state_.stack_depth > 0); 22938 | parser_.state_.stack_depth--; 22939 | } 22940 | 22941 | bool operator!() 22942 | { 22943 | return limit_exceeded_; 22944 | } 22945 | 22946 | private: 22947 | 22948 | stack_limit_handler(const stack_limit_handler&) exprtk_delete; 22949 | stack_limit_handler& operator=(const stack_limit_handler&) exprtk_delete; 22950 | 22951 | parser_t& parser_; 22952 | bool limit_exceeded_; 22953 | }; 22954 | 22955 | struct symtab_store 22956 | { 22957 | symbol_table_list_t symtab_list_; 22958 | 22959 | typedef typename symbol_table_t::local_data_t local_data_t; 22960 | typedef typename symbol_table_t::variable_ptr variable_ptr; 22961 | typedef typename symbol_table_t::function_ptr function_ptr; 22962 | #ifndef exprtk_disable_string_capabilities 22963 | typedef typename symbol_table_t::stringvar_ptr stringvar_ptr; 22964 | #endif 22965 | typedef typename symbol_table_t::vector_holder_ptr vector_holder_ptr; 22966 | typedef typename symbol_table_t::vararg_function_ptr vararg_function_ptr; 22967 | typedef typename symbol_table_t::generic_function_ptr generic_function_ptr; 22968 | 22969 | struct variable_context 22970 | { 22971 | variable_context() 22972 | : symbol_table(0) 22973 | , variable(0) 22974 | {} 22975 | 22976 | const symbol_table_t* symbol_table; 22977 | variable_ptr variable; 22978 | }; 22979 | 22980 | struct vector_context 22981 | { 22982 | vector_context() 22983 | : symbol_table(0) 22984 | , vector_holder(0) 22985 | {} 22986 | 22987 | const symbol_table_t* symbol_table; 22988 | vector_holder_ptr vector_holder; 22989 | }; 22990 | 22991 | #ifndef exprtk_disable_string_capabilities 22992 | struct string_context 22993 | { 22994 | string_context() 22995 | : symbol_table(0) 22996 | , str_var(0) 22997 | {} 22998 | 22999 | const symbol_table_t* symbol_table; 23000 | stringvar_ptr str_var; 23001 | }; 23002 | #endif 23003 | 23004 | inline bool empty() const 23005 | { 23006 | return symtab_list_.empty(); 23007 | } 23008 | 23009 | inline void clear() 23010 | { 23011 | symtab_list_.clear(); 23012 | } 23013 | 23014 | inline bool valid() const 23015 | { 23016 | if (!empty()) 23017 | { 23018 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23019 | { 23020 | if (symtab_list_[i].valid()) 23021 | return true; 23022 | } 23023 | } 23024 | 23025 | return false; 23026 | } 23027 | 23028 | inline bool valid_symbol(const std::string& symbol) const 23029 | { 23030 | if (!symtab_list_.empty()) 23031 | return symtab_list_[0].valid_symbol(symbol); 23032 | else 23033 | return false; 23034 | } 23035 | 23036 | inline bool valid_function_name(const std::string& symbol) const 23037 | { 23038 | if (!symtab_list_.empty()) 23039 | return symtab_list_[0].valid_function(symbol); 23040 | else 23041 | return false; 23042 | } 23043 | 23044 | inline variable_context get_variable_context(const std::string& variable_name) const 23045 | { 23046 | variable_context result; 23047 | 23048 | if (valid_symbol(variable_name)) 23049 | { 23050 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23051 | { 23052 | if (!symtab_list_[i].valid()) 23053 | { 23054 | continue; 23055 | } 23056 | 23057 | result.variable = local_data(i) 23058 | .variable_store.get(variable_name); 23059 | if (result.variable) 23060 | { 23061 | result.symbol_table = &symtab_list_[i]; 23062 | break; 23063 | } 23064 | } 23065 | } 23066 | 23067 | return result; 23068 | } 23069 | 23070 | inline variable_ptr get_variable(const std::string& variable_name) const 23071 | { 23072 | if (!valid_symbol(variable_name)) 23073 | return reinterpret_cast<variable_ptr>(0); 23074 | 23075 | variable_ptr result = reinterpret_cast<variable_ptr>(0); 23076 | 23077 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23078 | { 23079 | if (!symtab_list_[i].valid()) 23080 | continue; 23081 | else 23082 | result = local_data(i) 23083 | .variable_store.get(variable_name); 23084 | 23085 | if (result) break; 23086 | } 23087 | 23088 | return result; 23089 | } 23090 | 23091 | inline variable_ptr get_variable(const T& var_ref) const 23092 | { 23093 | variable_ptr result = reinterpret_cast<variable_ptr>(0); 23094 | 23095 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23096 | { 23097 | if (!symtab_list_[i].valid()) 23098 | continue; 23099 | else 23100 | result = local_data(i).variable_store 23101 | .get_from_varptr(reinterpret_cast<const void*>(&var_ref)); 23102 | 23103 | if (result) break; 23104 | } 23105 | 23106 | return result; 23107 | } 23108 | 23109 | #ifndef exprtk_disable_string_capabilities 23110 | inline string_context get_string_context(const std::string& string_name) const 23111 | { 23112 | string_context result; 23113 | 23114 | if (!valid_symbol(string_name)) 23115 | return result; 23116 | 23117 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23118 | { 23119 | if (!symtab_list_[i].valid()) 23120 | { 23121 | continue; 23122 | } 23123 | 23124 | result.str_var = local_data(i).stringvar_store.get(string_name); 23125 | 23126 | if (result.str_var) 23127 | { 23128 | result.symbol_table = &symtab_list_[i]; 23129 | break; 23130 | } 23131 | } 23132 | 23133 | return result; 23134 | } 23135 | 23136 | inline stringvar_ptr get_stringvar(const std::string& string_name) const 23137 | { 23138 | if (!valid_symbol(string_name)) 23139 | return reinterpret_cast<stringvar_ptr>(0); 23140 | 23141 | stringvar_ptr result = reinterpret_cast<stringvar_ptr>(0); 23142 | 23143 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23144 | { 23145 | if (!symtab_list_[i].valid()) 23146 | continue; 23147 | else 23148 | result = local_data(i) 23149 | .stringvar_store.get(string_name); 23150 | 23151 | if (result) break; 23152 | } 23153 | 23154 | return result; 23155 | } 23156 | #endif 23157 | 23158 | inline function_ptr get_function(const std::string& function_name) const 23159 | { 23160 | if (!valid_function_name(function_name)) 23161 | return reinterpret_cast<function_ptr>(0); 23162 | 23163 | function_ptr result = reinterpret_cast<function_ptr>(0); 23164 | 23165 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23166 | { 23167 | if (!symtab_list_[i].valid()) 23168 | continue; 23169 | else 23170 | result = local_data(i) 23171 | .function_store.get(function_name); 23172 | 23173 | if (result) break; 23174 | } 23175 | 23176 | return result; 23177 | } 23178 | 23179 | inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name) const 23180 | { 23181 | if (!valid_function_name(vararg_function_name)) 23182 | return reinterpret_cast<vararg_function_ptr>(0); 23183 | 23184 | vararg_function_ptr result = reinterpret_cast<vararg_function_ptr>(0); 23185 | 23186 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23187 | { 23188 | if (!symtab_list_[i].valid()) 23189 | continue; 23190 | else 23191 | result = local_data(i) 23192 | .vararg_function_store.get(vararg_function_name); 23193 | 23194 | if (result) break; 23195 | } 23196 | 23197 | return result; 23198 | } 23199 | 23200 | inline generic_function_ptr get_generic_function(const std::string& function_name) const 23201 | { 23202 | if (!valid_function_name(function_name)) 23203 | return reinterpret_cast<generic_function_ptr>(0); 23204 | 23205 | generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0); 23206 | 23207 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23208 | { 23209 | if (!symtab_list_[i].valid()) 23210 | continue; 23211 | else 23212 | result = local_data(i) 23213 | .generic_function_store.get(function_name); 23214 | 23215 | if (result) break; 23216 | } 23217 | 23218 | return result; 23219 | } 23220 | 23221 | inline generic_function_ptr get_string_function(const std::string& function_name) const 23222 | { 23223 | if (!valid_function_name(function_name)) 23224 | return reinterpret_cast<generic_function_ptr>(0); 23225 | 23226 | generic_function_ptr result = reinterpret_cast<generic_function_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 = 23234 | local_data(i).string_function_store.get(function_name); 23235 | 23236 | if (result) break; 23237 | } 23238 | 23239 | return result; 23240 | } 23241 | 23242 | inline generic_function_ptr get_overload_function(const std::string& function_name) const 23243 | { 23244 | if (!valid_function_name(function_name)) 23245 | return reinterpret_cast<generic_function_ptr>(0); 23246 | 23247 | generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0); 23248 | 23249 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23250 | { 23251 | if (!symtab_list_[i].valid()) 23252 | continue; 23253 | else 23254 | result = 23255 | local_data(i).overload_function_store.get(function_name); 23256 | 23257 | if (result) break; 23258 | } 23259 | 23260 | return result; 23261 | } 23262 | 23263 | inline vector_context get_vector_context(const std::string& vector_name) const 23264 | { 23265 | vector_context result; 23266 | if (!valid_symbol(vector_name)) 23267 | return result; 23268 | 23269 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23270 | { 23271 | if (!symtab_list_[i].valid()) 23272 | { 23273 | continue; 23274 | } 23275 | 23276 | result.vector_holder = local_data(i).vector_store.get(vector_name); 23277 | 23278 | if (result.vector_holder) 23279 | { 23280 | result.symbol_table = &symtab_list_[i]; 23281 | break; 23282 | } 23283 | } 23284 | 23285 | return result; 23286 | } 23287 | 23288 | inline vector_holder_ptr get_vector(const std::string& vector_name) const 23289 | { 23290 | if (!valid_symbol(vector_name)) 23291 | return reinterpret_cast<vector_holder_ptr>(0); 23292 | 23293 | vector_holder_ptr result = reinterpret_cast<vector_holder_ptr>(0); 23294 | 23295 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23296 | { 23297 | if (!symtab_list_[i].valid()) 23298 | { 23299 | continue; 23300 | } 23301 | 23302 | result = local_data(i).vector_store.get(vector_name); 23303 | 23304 | if (result) 23305 | { 23306 | break; 23307 | } 23308 | } 23309 | 23310 | return result; 23311 | } 23312 | 23313 | inline bool is_constant_node(const std::string& symbol_name) const 23314 | { 23315 | if (!valid_symbol(symbol_name)) 23316 | return false; 23317 | 23318 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23319 | { 23320 | if (!symtab_list_[i].valid()) 23321 | { 23322 | continue; 23323 | } 23324 | 23325 | if (local_data(i).variable_store.is_constant(symbol_name)) 23326 | { 23327 | return true; 23328 | } 23329 | } 23330 | 23331 | return false; 23332 | } 23333 | 23334 | #ifndef exprtk_disable_string_capabilities 23335 | inline bool is_constant_string(const std::string& symbol_name) const 23336 | { 23337 | if (!valid_symbol(symbol_name)) 23338 | return false; 23339 | 23340 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23341 | { 23342 | if (!symtab_list_[i].valid()) 23343 | continue; 23344 | else if (!local_data(i).stringvar_store.symbol_exists(symbol_name)) 23345 | continue; 23346 | else if (local_data(i).stringvar_store.is_constant(symbol_name)) 23347 | return true; 23348 | } 23349 | 23350 | return false; 23351 | } 23352 | #endif 23353 | 23354 | inline bool symbol_exists(const std::string& symbol) const 23355 | { 23356 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23357 | { 23358 | if (!symtab_list_[i].valid()) 23359 | { 23360 | continue; 23361 | } 23362 | 23363 | if (symtab_list_[i].symbol_exists(symbol)) 23364 | { 23365 | return true; 23366 | } 23367 | } 23368 | 23369 | return false; 23370 | } 23371 | 23372 | inline bool is_variable(const std::string& variable_name) const 23373 | { 23374 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23375 | { 23376 | if (!symtab_list_[i].valid()) 23377 | continue; 23378 | else if ( 23379 | symtab_list_[i].local_data().variable_store 23380 | .symbol_exists(variable_name) 23381 | ) 23382 | return true; 23383 | } 23384 | 23385 | return false; 23386 | } 23387 | 23388 | #ifndef exprtk_disable_string_capabilities 23389 | inline bool is_stringvar(const std::string& stringvar_name) const 23390 | { 23391 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23392 | { 23393 | if (!symtab_list_[i].valid()) 23394 | continue; 23395 | else if ( 23396 | symtab_list_[i].local_data().stringvar_store 23397 | .symbol_exists(stringvar_name) 23398 | ) 23399 | return true; 23400 | } 23401 | 23402 | return false; 23403 | } 23404 | 23405 | inline bool is_conststr_stringvar(const std::string& symbol_name) const 23406 | { 23407 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23408 | { 23409 | if (!symtab_list_[i].valid()) 23410 | continue; 23411 | else if ( 23412 | symtab_list_[i].local_data().stringvar_store 23413 | .symbol_exists(symbol_name) 23414 | ) 23415 | { 23416 | return ( 23417 | local_data(i).stringvar_store.symbol_exists(symbol_name) || 23418 | local_data(i).stringvar_store.is_constant (symbol_name) 23419 | ); 23420 | 23421 | } 23422 | } 23423 | 23424 | return false; 23425 | } 23426 | #endif 23427 | 23428 | inline bool is_function(const std::string& function_name) const 23429 | { 23430 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23431 | { 23432 | if (!symtab_list_[i].valid()) 23433 | continue; 23434 | else if ( 23435 | local_data(i).vararg_function_store 23436 | .symbol_exists(function_name) 23437 | ) 23438 | return true; 23439 | } 23440 | 23441 | return false; 23442 | } 23443 | 23444 | inline bool is_vararg_function(const std::string& vararg_function_name) const 23445 | { 23446 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23447 | { 23448 | if (!symtab_list_[i].valid()) 23449 | continue; 23450 | else if ( 23451 | local_data(i).vararg_function_store 23452 | .symbol_exists(vararg_function_name) 23453 | ) 23454 | return true; 23455 | } 23456 | 23457 | return false; 23458 | } 23459 | 23460 | inline bool is_vector(const std::string& vector_name) const 23461 | { 23462 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23463 | { 23464 | if (!symtab_list_[i].valid()) 23465 | continue; 23466 | else if ( 23467 | local_data(i).vector_store 23468 | .symbol_exists(vector_name) 23469 | ) 23470 | return true; 23471 | } 23472 | 23473 | return false; 23474 | } 23475 | 23476 | inline std::string get_variable_name(const expression_node_ptr& ptr) const 23477 | { 23478 | return local_data().variable_store.entity_name(ptr); 23479 | } 23480 | 23481 | inline std::string get_vector_name(const vector_holder_ptr& ptr) const 23482 | { 23483 | return local_data().vector_store.entity_name(ptr); 23484 | } 23485 | 23486 | #ifndef exprtk_disable_string_capabilities 23487 | inline std::string get_stringvar_name(const expression_node_ptr& ptr) const 23488 | { 23489 | return local_data().stringvar_store.entity_name(ptr); 23490 | } 23491 | 23492 | inline std::string get_conststr_stringvar_name(const expression_node_ptr& ptr) const 23493 | { 23494 | return local_data().stringvar_store.entity_name(ptr); 23495 | } 23496 | #endif 23497 | 23498 | inline local_data_t& local_data(const std::size_t& index = 0) 23499 | { 23500 | return symtab_list_[index].local_data(); 23501 | } 23502 | 23503 | inline const local_data_t& local_data(const std::size_t& index = 0) const 23504 | { 23505 | return symtab_list_[index].local_data(); 23506 | } 23507 | 23508 | inline symbol_table_t& get_symbol_table(const std::size_t& index = 0) 23509 | { 23510 | return symtab_list_[index]; 23511 | } 23512 | }; 23513 | 23514 | struct parser_state 23515 | { 23516 | parser_state() 23517 | : type_check_enabled(true) 23518 | { 23519 | reset(); 23520 | } 23521 | 23522 | void reset() 23523 | { 23524 | parsing_return_stmt = false; 23525 | parsing_break_stmt = false; 23526 | parsing_assert_stmt = false; 23527 | return_stmt_present = false; 23528 | side_effect_present = false; 23529 | scope_depth = 0; 23530 | stack_depth = 0; 23531 | parsing_loop_stmt_count = 0; 23532 | } 23533 | 23534 | #ifndef exprtk_enable_debugging 23535 | void activate_side_effect(const std::string&) 23536 | #else 23537 | void activate_side_effect(const std::string& source) 23538 | #endif 23539 | { 23540 | if (!side_effect_present) 23541 | { 23542 | side_effect_present = true; 23543 | 23544 | exprtk_debug(("activate_side_effect() - caller: %s\n", source.c_str())); 23545 | } 23546 | } 23547 | 23548 | bool parsing_return_stmt; 23549 | bool parsing_break_stmt; 23550 | bool parsing_assert_stmt; 23551 | bool return_stmt_present; 23552 | bool side_effect_present; 23553 | bool type_check_enabled; 23554 | std::size_t scope_depth; 23555 | std::size_t stack_depth; 23556 | std::size_t parsing_loop_stmt_count; 23557 | }; 23558 | 23559 | public: 23560 | 23561 | struct unknown_symbol_resolver 23562 | { 23563 | 23564 | enum usr_symbol_type 23565 | { 23566 | e_usr_unknown_type = 0, 23567 | e_usr_variable_type = 1, 23568 | e_usr_constant_type = 2 23569 | }; 23570 | 23571 | enum usr_mode 23572 | { 23573 | e_usrmode_default = 0, 23574 | e_usrmode_extended = 1 23575 | }; 23576 | 23577 | usr_mode mode; 23578 | 23579 | explicit unknown_symbol_resolver(const usr_mode m = e_usrmode_default) 23580 | : mode(m) 23581 | {} 23582 | 23583 | virtual ~unknown_symbol_resolver() 23584 | {} 23585 | 23586 | virtual bool process(const std::string& /*unknown_symbol*/, 23587 | usr_symbol_type& st, 23588 | T& default_value, 23589 | std::string& error_message) 23590 | { 23591 | if (e_usrmode_default != mode) 23592 | return false; 23593 | 23594 | st = e_usr_variable_type; 23595 | default_value = T(0); 23596 | error_message.clear(); 23597 | 23598 | return true; 23599 | } 23600 | 23601 | virtual bool process(const std::string& /* unknown_symbol */, 23602 | symbol_table_t& /* symbol_table */, 23603 | std::string& /* error_message */) 23604 | { 23605 | return false; 23606 | } 23607 | }; 23608 | 23609 | enum collect_type 23610 | { 23611 | e_ct_none = 0, 23612 | e_ct_variables = 1, 23613 | e_ct_functions = 2, 23614 | e_ct_assignments = 4 23615 | }; 23616 | 23617 | enum symbol_type 23618 | { 23619 | e_st_unknown = 0, 23620 | e_st_variable = 1, 23621 | e_st_vector = 2, 23622 | e_st_vecelem = 3, 23623 | e_st_string = 4, 23624 | e_st_function = 5, 23625 | e_st_local_variable = 6, 23626 | e_st_local_vector = 7, 23627 | e_st_local_string = 8 23628 | }; 23629 | 23630 | class dependent_entity_collector 23631 | { 23632 | public: 23633 | 23634 | typedef std::pair<std::string,symbol_type> symbol_t; 23635 | typedef std::vector<symbol_t> symbol_list_t; 23636 | 23637 | explicit dependent_entity_collector(const std::size_t options = e_ct_none) 23638 | : options_(options) 23639 | , collect_variables_ ((options_ & e_ct_variables ) == e_ct_variables ) 23640 | , collect_functions_ ((options_ & e_ct_functions ) == e_ct_functions ) 23641 | , collect_assignments_((options_ & e_ct_assignments) == e_ct_assignments) 23642 | , return_present_ (false) 23643 | , final_stmt_return_(false) 23644 | {} 23645 | 23646 | template <typename Allocator, 23647 | template <typename, typename> class Sequence> 23648 | inline std::size_t symbols(Sequence<symbol_t,Allocator>& symbols_list) 23649 | { 23650 | if (!collect_variables_ && !collect_functions_) 23651 | return 0; 23652 | else if (symbol_name_list_.empty()) 23653 | return 0; 23654 | 23655 | for (std::size_t i = 0; i < symbol_name_list_.size(); ++i) 23656 | { 23657 | details::case_normalise(symbol_name_list_[i].first); 23658 | } 23659 | 23660 | std::sort(symbol_name_list_.begin(), symbol_name_list_.end()); 23661 | 23662 | std::unique_copy 23663 | ( 23664 | symbol_name_list_.begin(), 23665 | symbol_name_list_.end (), 23666 | std::back_inserter(symbols_list) 23667 | ); 23668 | 23669 | return symbols_list.size(); 23670 | } 23671 | 23672 | template <typename Allocator, 23673 | template <typename, typename> class Sequence> 23674 | inline std::size_t assignment_symbols(Sequence<symbol_t,Allocator>& assignment_list) 23675 | { 23676 | if (!collect_assignments_) 23677 | return 0; 23678 | else if (assignment_name_list_.empty()) 23679 | return 0; 23680 | 23681 | for (std::size_t i = 0; i < assignment_name_list_.size(); ++i) 23682 | { 23683 | details::case_normalise(assignment_name_list_[i].first); 23684 | } 23685 | 23686 | std::sort(assignment_name_list_.begin(),assignment_name_list_.end()); 23687 | 23688 | std::unique_copy 23689 | ( 23690 | assignment_name_list_.begin(), 23691 | assignment_name_list_.end (), 23692 | std::back_inserter(assignment_list) 23693 | ); 23694 | 23695 | return assignment_list.size(); 23696 | } 23697 | 23698 | void clear() 23699 | { 23700 | symbol_name_list_ .clear(); 23701 | assignment_name_list_.clear(); 23702 | retparam_list_ .clear(); 23703 | return_present_ = false; 23704 | final_stmt_return_ = false; 23705 | } 23706 | 23707 | bool& collect_variables() 23708 | { 23709 | return collect_variables_; 23710 | } 23711 | 23712 | bool& collect_functions() 23713 | { 23714 | return collect_functions_; 23715 | } 23716 | 23717 | bool& collect_assignments() 23718 | { 23719 | return collect_assignments_; 23720 | } 23721 | 23722 | bool return_present() const 23723 | { 23724 | return return_present_; 23725 | } 23726 | 23727 | bool final_stmt_return() const 23728 | { 23729 | return final_stmt_return_; 23730 | } 23731 | 23732 | typedef std::vector<std::string> retparam_list_t; 23733 | 23734 | retparam_list_t return_param_type_list() const 23735 | { 23736 | return retparam_list_; 23737 | } 23738 | 23739 | private: 23740 | 23741 | inline void add_symbol(const std::string& symbol, const symbol_type st) 23742 | { 23743 | switch (st) 23744 | { 23745 | case e_st_variable : 23746 | case e_st_vector : 23747 | case e_st_string : 23748 | case e_st_local_variable : 23749 | case e_st_local_vector : 23750 | case e_st_local_string : if (collect_variables_) 23751 | symbol_name_list_ 23752 | .push_back(std::make_pair(symbol, st)); 23753 | break; 23754 | 23755 | case e_st_function : if (collect_functions_) 23756 | symbol_name_list_ 23757 | .push_back(std::make_pair(symbol, st)); 23758 | break; 23759 | 23760 | default : return; 23761 | } 23762 | } 23763 | 23764 | inline void add_assignment(const std::string& symbol, const symbol_type st) 23765 | { 23766 | switch (st) 23767 | { 23768 | case e_st_variable : 23769 | case e_st_vector : 23770 | case e_st_string : if (collect_assignments_) 23771 | assignment_name_list_ 23772 | .push_back(std::make_pair(symbol, st)); 23773 | break; 23774 | 23775 | default : return; 23776 | } 23777 | } 23778 | 23779 | std::size_t options_; 23780 | bool collect_variables_; 23781 | bool collect_functions_; 23782 | bool collect_assignments_; 23783 | bool return_present_; 23784 | bool final_stmt_return_; 23785 | symbol_list_t symbol_name_list_; 23786 | symbol_list_t assignment_name_list_; 23787 | retparam_list_t retparam_list_; 23788 | 23789 | friend class parser<T>; 23790 | }; 23791 | 23792 | class settings_store 23793 | { 23794 | private: 23795 | 23796 | typedef std::set<std::string,details::ilesscompare> disabled_entity_set_t; 23797 | typedef disabled_entity_set_t::iterator des_itr_t; 23798 | 23799 | public: 23800 | 23801 | enum settings_compilation_options 23802 | { 23803 | e_unknown = 0, 23804 | e_replacer = 1, 23805 | e_joiner = 2, 23806 | e_numeric_check = 4, 23807 | e_bracket_check = 8, 23808 | e_sequence_check = 16, 23809 | e_commutative_check = 32, 23810 | e_strength_reduction = 64, 23811 | e_disable_vardef = 128, 23812 | e_collect_vars = 256, 23813 | e_collect_funcs = 512, 23814 | e_collect_assings = 1024, 23815 | e_disable_usr_on_rsrvd = 2048, 23816 | e_disable_zero_return = 4096 23817 | }; 23818 | 23819 | enum settings_base_funcs 23820 | { 23821 | e_bf_unknown = 0, 23822 | e_bf_abs , e_bf_acos , e_bf_acosh , e_bf_asin , 23823 | e_bf_asinh , e_bf_atan , e_bf_atan2 , e_bf_atanh , 23824 | e_bf_avg , e_bf_ceil , e_bf_clamp , e_bf_cos , 23825 | e_bf_cosh , e_bf_cot , e_bf_csc , e_bf_equal , 23826 | e_bf_erf , e_bf_erfc , e_bf_exp , e_bf_expm1 , 23827 | e_bf_floor , e_bf_frac , e_bf_hypot , e_bf_iclamp , 23828 | e_bf_like , e_bf_log , e_bf_log10 , e_bf_log1p , 23829 | e_bf_log2 , e_bf_logn , e_bf_mand , e_bf_max , 23830 | e_bf_min , e_bf_mod , e_bf_mor , e_bf_mul , 23831 | e_bf_ncdf , e_bf_pow , e_bf_root , e_bf_round , 23832 | e_bf_roundn , e_bf_sec , e_bf_sgn , e_bf_sin , 23833 | e_bf_sinc , e_bf_sinh , e_bf_sqrt , e_bf_sum , 23834 | e_bf_swap , e_bf_tan , e_bf_tanh , e_bf_trunc , 23835 | e_bf_not_equal , e_bf_inrange , e_bf_deg2grad , e_bf_deg2rad , 23836 | e_bf_rad2deg , e_bf_grad2deg 23837 | }; 23838 | 23839 | enum settings_control_structs 23840 | { 23841 | e_ctrl_unknown = 0, 23842 | e_ctrl_ifelse, 23843 | e_ctrl_switch, 23844 | e_ctrl_for_loop, 23845 | e_ctrl_while_loop, 23846 | e_ctrl_repeat_loop, 23847 | e_ctrl_return 23848 | }; 23849 | 23850 | enum settings_logic_opr 23851 | { 23852 | e_logic_unknown = 0, 23853 | e_logic_and, e_logic_nand , e_logic_nor , 23854 | e_logic_not, e_logic_or , e_logic_xnor, 23855 | e_logic_xor, e_logic_scand, e_logic_scor 23856 | }; 23857 | 23858 | enum settings_arithmetic_opr 23859 | { 23860 | e_arith_unknown = 0, 23861 | e_arith_add, e_arith_sub, e_arith_mul, 23862 | e_arith_div, e_arith_mod, e_arith_pow 23863 | }; 23864 | 23865 | enum settings_assignment_opr 23866 | { 23867 | e_assign_unknown = 0, 23868 | e_assign_assign, e_assign_addass, e_assign_subass, 23869 | e_assign_mulass, e_assign_divass, e_assign_modass 23870 | }; 23871 | 23872 | enum settings_inequality_opr 23873 | { 23874 | e_ineq_unknown = 0, 23875 | e_ineq_lt , e_ineq_lte, e_ineq_eq , 23876 | e_ineq_equal, e_ineq_ne , e_ineq_nequal, 23877 | e_ineq_gte , e_ineq_gt 23878 | }; 23879 | 23880 | static const std::size_t default_compile_all_opts = 23881 | e_replacer + 23882 | e_joiner + 23883 | e_numeric_check + 23884 | e_bracket_check + 23885 | e_sequence_check + 23886 | e_commutative_check + 23887 | e_strength_reduction; 23888 | 23889 | settings_store(const std::size_t compile_options = default_compile_all_opts) 23890 | : max_stack_depth_(400) 23891 | , max_node_depth_(10000) 23892 | , max_total_local_symbol_size_bytes_(2000000000) 23893 | , max_local_vector_size_(max_total_local_symbol_size_bytes_ / sizeof(T)) 23894 | { 23895 | load_compile_options(compile_options); 23896 | } 23897 | 23898 | settings_store& enable_all_base_functions() 23899 | { 23900 | disabled_func_set_.clear(); 23901 | return (*this); 23902 | } 23903 | 23904 | settings_store& enable_all_control_structures() 23905 | { 23906 | disabled_ctrl_set_.clear(); 23907 | return (*this); 23908 | } 23909 | 23910 | settings_store& enable_all_logic_ops() 23911 | { 23912 | disabled_logic_set_.clear(); 23913 | return (*this); 23914 | } 23915 | 23916 | settings_store& enable_all_arithmetic_ops() 23917 | { 23918 | disabled_arithmetic_set_.clear(); 23919 | return (*this); 23920 | } 23921 | 23922 | settings_store& enable_all_assignment_ops() 23923 | { 23924 | disabled_assignment_set_.clear(); 23925 | return (*this); 23926 | } 23927 | 23928 | settings_store& enable_all_inequality_ops() 23929 | { 23930 | disabled_inequality_set_.clear(); 23931 | return (*this); 23932 | } 23933 | 23934 | settings_store& enable_local_vardef() 23935 | { 23936 | disable_vardef_ = false; 23937 | return (*this); 23938 | } 23939 | 23940 | settings_store& enable_commutative_check() 23941 | { 23942 | enable_commutative_check_ = true; 23943 | return (*this); 23944 | } 23945 | 23946 | settings_store& enable_strength_reduction() 23947 | { 23948 | enable_strength_reduction_ = true; 23949 | return (*this); 23950 | } 23951 | 23952 | settings_store& disable_all_base_functions() 23953 | { 23954 | std::copy(details::base_function_list, 23955 | details::base_function_list + details::base_function_list_size, 23956 | std::insert_iterator<disabled_entity_set_t> 23957 | (disabled_func_set_, disabled_func_set_.begin())); 23958 | return (*this); 23959 | } 23960 | 23961 | settings_store& disable_all_control_structures() 23962 | { 23963 | std::copy(details::cntrl_struct_list, 23964 | details::cntrl_struct_list + details::cntrl_struct_list_size, 23965 | std::insert_iterator<disabled_entity_set_t> 23966 | (disabled_ctrl_set_, disabled_ctrl_set_.begin())); 23967 | return (*this); 23968 | } 23969 | 23970 | settings_store& disable_all_logic_ops() 23971 | { 23972 | std::copy(details::logic_ops_list, 23973 | details::logic_ops_list + details::logic_ops_list_size, 23974 | std::insert_iterator<disabled_entity_set_t> 23975 | (disabled_logic_set_, disabled_logic_set_.begin())); 23976 | return (*this); 23977 | } 23978 | 23979 | settings_store& disable_all_arithmetic_ops() 23980 | { 23981 | std::copy(details::arithmetic_ops_list, 23982 | details::arithmetic_ops_list + details::arithmetic_ops_list_size, 23983 | std::insert_iterator<disabled_entity_set_t> 23984 | (disabled_arithmetic_set_, disabled_arithmetic_set_.begin())); 23985 | return (*this); 23986 | } 23987 | 23988 | settings_store& disable_all_assignment_ops() 23989 | { 23990 | std::copy(details::assignment_ops_list, 23991 | details::assignment_ops_list + details::assignment_ops_list_size, 23992 | std::insert_iterator<disabled_entity_set_t> 23993 | (disabled_assignment_set_, disabled_assignment_set_.begin())); 23994 | return (*this); 23995 | } 23996 | 23997 | settings_store& disable_all_inequality_ops() 23998 | { 23999 | std::copy(details::inequality_ops_list, 24000 | details::inequality_ops_list + details::inequality_ops_list_size, 24001 | std::insert_iterator<disabled_entity_set_t> 24002 | (disabled_inequality_set_, disabled_inequality_set_.begin())); 24003 | return (*this); 24004 | } 24005 | 24006 | settings_store& disable_local_vardef() 24007 | { 24008 | disable_vardef_ = true; 24009 | return (*this); 24010 | } 24011 | 24012 | settings_store& disable_commutative_check() 24013 | { 24014 | enable_commutative_check_ = false; 24015 | return (*this); 24016 | } 24017 | 24018 | settings_store& disable_strength_reduction() 24019 | { 24020 | enable_strength_reduction_ = false; 24021 | return (*this); 24022 | } 24023 | 24024 | bool replacer_enabled () const { return enable_replacer_; } 24025 | bool commutative_check_enabled () const { return enable_commutative_check_; } 24026 | bool joiner_enabled () const { return enable_joiner_; } 24027 | bool numeric_check_enabled () const { return enable_numeric_check_; } 24028 | bool bracket_check_enabled () const { return enable_bracket_check_; } 24029 | bool sequence_check_enabled () const { return enable_sequence_check_; } 24030 | bool strength_reduction_enabled () const { return enable_strength_reduction_; } 24031 | bool collect_variables_enabled () const { return enable_collect_vars_; } 24032 | bool collect_functions_enabled () const { return enable_collect_funcs_; } 24033 | bool collect_assignments_enabled() const { return enable_collect_assings_; } 24034 | bool vardef_disabled () const { return disable_vardef_; } 24035 | bool rsrvd_sym_usr_disabled () const { return disable_rsrvd_sym_usr_; } 24036 | bool zero_return_disabled () const { return disable_zero_return_; } 24037 | 24038 | bool function_enabled(const std::string& function_name) const 24039 | { 24040 | if (disabled_func_set_.empty()) 24041 | return true; 24042 | else 24043 | return (disabled_func_set_.end() == disabled_func_set_.find(function_name)); 24044 | } 24045 | 24046 | bool control_struct_enabled(const std::string& control_struct) const 24047 | { 24048 | if (disabled_ctrl_set_.empty()) 24049 | return true; 24050 | else 24051 | return (disabled_ctrl_set_.end() == disabled_ctrl_set_.find(control_struct)); 24052 | } 24053 | 24054 | bool logic_enabled(const std::string& logic_operation) const 24055 | { 24056 | if (disabled_logic_set_.empty()) 24057 | return true; 24058 | else 24059 | return (disabled_logic_set_.end() == disabled_logic_set_.find(logic_operation)); 24060 | } 24061 | 24062 | bool arithmetic_enabled(const details::operator_type& arithmetic_operation) const 24063 | { 24064 | if (disabled_logic_set_.empty()) 24065 | return true; 24066 | else 24067 | return disabled_arithmetic_set_.end() == disabled_arithmetic_set_ 24068 | .find(arith_opr_to_string(arithmetic_operation)); 24069 | } 24070 | 24071 | bool assignment_enabled(const details::operator_type& assignment) const 24072 | { 24073 | if (disabled_assignment_set_.empty()) 24074 | return true; 24075 | else 24076 | return disabled_assignment_set_.end() == disabled_assignment_set_ 24077 | .find(assign_opr_to_string(assignment)); 24078 | } 24079 | 24080 | bool inequality_enabled(const details::operator_type& inequality) const 24081 | { 24082 | if (disabled_inequality_set_.empty()) 24083 | return true; 24084 | else 24085 | return disabled_inequality_set_.end() == disabled_inequality_set_ 24086 | .find(inequality_opr_to_string(inequality)); 24087 | } 24088 | 24089 | bool function_disabled(const std::string& function_name) const 24090 | { 24091 | if (disabled_func_set_.empty()) 24092 | return false; 24093 | else 24094 | return (disabled_func_set_.end() != disabled_func_set_.find(function_name)); 24095 | } 24096 | 24097 | bool control_struct_disabled(const std::string& control_struct) const 24098 | { 24099 | if (disabled_ctrl_set_.empty()) 24100 | return false; 24101 | else 24102 | return (disabled_ctrl_set_.end() != disabled_ctrl_set_.find(control_struct)); 24103 | } 24104 | 24105 | bool logic_disabled(const std::string& logic_operation) const 24106 | { 24107 | if (disabled_logic_set_.empty()) 24108 | return false; 24109 | else 24110 | return (disabled_logic_set_.end() != disabled_logic_set_.find(logic_operation)); 24111 | } 24112 | 24113 | bool assignment_disabled(const details::operator_type assignment_operation) const 24114 | { 24115 | if (disabled_assignment_set_.empty()) 24116 | return false; 24117 | else 24118 | return disabled_assignment_set_.end() != disabled_assignment_set_ 24119 | .find(assign_opr_to_string(assignment_operation)); 24120 | } 24121 | 24122 | bool logic_disabled(const details::operator_type logic_operation) const 24123 | { 24124 | if (disabled_logic_set_.empty()) 24125 | return false; 24126 | else 24127 | return disabled_logic_set_.end() != disabled_logic_set_ 24128 | .find(logic_opr_to_string(logic_operation)); 24129 | } 24130 | 24131 | bool arithmetic_disabled(const details::operator_type arithmetic_operation) const 24132 | { 24133 | if (disabled_arithmetic_set_.empty()) 24134 | return false; 24135 | else 24136 | return disabled_arithmetic_set_.end() != disabled_arithmetic_set_ 24137 | .find(arith_opr_to_string(arithmetic_operation)); 24138 | } 24139 | 24140 | bool inequality_disabled(const details::operator_type& inequality) const 24141 | { 24142 | if (disabled_inequality_set_.empty()) 24143 | return false; 24144 | else 24145 | return disabled_inequality_set_.end() != disabled_inequality_set_ 24146 | .find(inequality_opr_to_string(inequality)); 24147 | } 24148 | 24149 | settings_store& disable_base_function(const settings_base_funcs bf) 24150 | { 24151 | if ( 24152 | (e_bf_unknown != bf) && 24153 | (static_cast<std::size_t>(bf) < (details::base_function_list_size + 1)) 24154 | ) 24155 | { 24156 | disabled_func_set_.insert(details::base_function_list[bf - 1]); 24157 | } 24158 | 24159 | return (*this); 24160 | } 24161 | 24162 | settings_store& disable_control_structure(const settings_control_structs ctrl_struct) 24163 | { 24164 | if ( 24165 | (e_ctrl_unknown != ctrl_struct) && 24166 | (static_cast<std::size_t>(ctrl_struct) < (details::cntrl_struct_list_size + 1)) 24167 | ) 24168 | { 24169 | disabled_ctrl_set_.insert(details::cntrl_struct_list[ctrl_struct - 1]); 24170 | } 24171 | 24172 | return (*this); 24173 | } 24174 | 24175 | settings_store& disable_logic_operation(const settings_logic_opr logic) 24176 | { 24177 | if ( 24178 | (e_logic_unknown != logic) && 24179 | (static_cast<std::size_t>(logic) < (details::logic_ops_list_size + 1)) 24180 | ) 24181 | { 24182 | disabled_logic_set_.insert(details::logic_ops_list[logic - 1]); 24183 | } 24184 | 24185 | return (*this); 24186 | } 24187 | 24188 | settings_store& disable_arithmetic_operation(const settings_arithmetic_opr arithmetic) 24189 | { 24190 | if ( 24191 | (e_arith_unknown != arithmetic) && 24192 | (static_cast<std::size_t>(arithmetic) < (details::arithmetic_ops_list_size + 1)) 24193 | ) 24194 | { 24195 | disabled_arithmetic_set_.insert(details::arithmetic_ops_list[arithmetic - 1]); 24196 | } 24197 | 24198 | return (*this); 24199 | } 24200 | 24201 | settings_store& disable_assignment_operation(const settings_assignment_opr assignment) 24202 | { 24203 | if ( 24204 | (e_assign_unknown != assignment) && 24205 | (static_cast<std::size_t>(assignment) < (details::assignment_ops_list_size + 1)) 24206 | ) 24207 | { 24208 | disabled_assignment_set_.insert(details::assignment_ops_list[assignment - 1]); 24209 | } 24210 | 24211 | return (*this); 24212 | } 24213 | 24214 | settings_store& disable_inequality_operation(const settings_inequality_opr inequality) 24215 | { 24216 | if ( 24217 | (e_ineq_unknown != inequality) && 24218 | (static_cast<std::size_t>(inequality) < (details::inequality_ops_list_size + 1)) 24219 | ) 24220 | { 24221 | disabled_inequality_set_.insert(details::inequality_ops_list[inequality - 1]); 24222 | } 24223 | 24224 | return (*this); 24225 | } 24226 | 24227 | settings_store& enable_base_function(const settings_base_funcs bf) 24228 | { 24229 | if ( 24230 | (e_bf_unknown != bf) && 24231 | (static_cast<std::size_t>(bf) < (details::base_function_list_size + 1)) 24232 | ) 24233 | { 24234 | const des_itr_t itr = disabled_func_set_.find(details::base_function_list[bf - 1]); 24235 | 24236 | if (disabled_func_set_.end() != itr) 24237 | { 24238 | disabled_func_set_.erase(itr); 24239 | } 24240 | } 24241 | 24242 | return (*this); 24243 | } 24244 | 24245 | settings_store& enable_control_structure(const settings_control_structs ctrl_struct) 24246 | { 24247 | if ( 24248 | (e_ctrl_unknown != ctrl_struct) && 24249 | (static_cast<std::size_t>(ctrl_struct) < (details::cntrl_struct_list_size + 1)) 24250 | ) 24251 | { 24252 | const des_itr_t itr = disabled_ctrl_set_.find(details::cntrl_struct_list[ctrl_struct - 1]); 24253 | 24254 | if (disabled_ctrl_set_.end() != itr) 24255 | { 24256 | disabled_ctrl_set_.erase(itr); 24257 | } 24258 | } 24259 | 24260 | return (*this); 24261 | } 24262 | 24263 | settings_store& enable_logic_operation(const settings_logic_opr logic) 24264 | { 24265 | if ( 24266 | (e_logic_unknown != logic) && 24267 | (static_cast<std::size_t>(logic) < (details::logic_ops_list_size + 1)) 24268 | ) 24269 | { 24270 | const des_itr_t itr = disabled_logic_set_.find(details::logic_ops_list[logic - 1]); 24271 | 24272 | if (disabled_logic_set_.end() != itr) 24273 | { 24274 | disabled_logic_set_.erase(itr); 24275 | } 24276 | } 24277 | 24278 | return (*this); 24279 | } 24280 | 24281 | settings_store& enable_arithmetic_operation(const settings_arithmetic_opr arithmetic) 24282 | { 24283 | if ( 24284 | (e_arith_unknown != arithmetic) && 24285 | (static_cast<std::size_t>(arithmetic) < (details::arithmetic_ops_list_size + 1)) 24286 | ) 24287 | { 24288 | const des_itr_t itr = disabled_arithmetic_set_.find(details::arithmetic_ops_list[arithmetic - 1]); 24289 | 24290 | if (disabled_arithmetic_set_.end() != itr) 24291 | { 24292 | disabled_arithmetic_set_.erase(itr); 24293 | } 24294 | } 24295 | 24296 | return (*this); 24297 | } 24298 | 24299 | settings_store& enable_assignment_operation(const settings_assignment_opr assignment) 24300 | { 24301 | if ( 24302 | (e_assign_unknown != assignment) && 24303 | (static_cast<std::size_t>(assignment) < (details::assignment_ops_list_size + 1)) 24304 | ) 24305 | { 24306 | const des_itr_t itr = disabled_assignment_set_.find(details::assignment_ops_list[assignment - 1]); 24307 | 24308 | if (disabled_assignment_set_.end() != itr) 24309 | { 24310 | disabled_assignment_set_.erase(itr); 24311 | } 24312 | } 24313 | 24314 | return (*this); 24315 | } 24316 | 24317 | settings_store& enable_inequality_operation(const settings_inequality_opr inequality) 24318 | { 24319 | if ( 24320 | (e_ineq_unknown != inequality) && 24321 | (static_cast<std::size_t>(inequality) < (details::inequality_ops_list_size + 1)) 24322 | ) 24323 | { 24324 | const des_itr_t itr = disabled_inequality_set_.find(details::inequality_ops_list[inequality - 1]); 24325 | 24326 | if (disabled_inequality_set_.end() != itr) 24327 | { 24328 | disabled_inequality_set_.erase(itr); 24329 | } 24330 | } 24331 | 24332 | return (*this); 24333 | } 24334 | 24335 | void set_max_stack_depth(const std::size_t max_stack_depth) 24336 | { 24337 | max_stack_depth_ = max_stack_depth; 24338 | } 24339 | 24340 | void set_max_node_depth(const std::size_t max_node_depth) 24341 | { 24342 | max_node_depth_ = max_node_depth; 24343 | } 24344 | 24345 | void set_max_local_vector_size(const std::size_t max_local_vector_size) 24346 | { 24347 | max_local_vector_size_ = max_local_vector_size; 24348 | } 24349 | 24350 | void set_max_total_local_symbol_size_bytes(const std::size_t max_total_lcl_symb_size) 24351 | { 24352 | max_total_local_symbol_size_bytes_ = max_total_lcl_symb_size; 24353 | } 24354 | 24355 | std::size_t max_stack_depth() const 24356 | { 24357 | return max_stack_depth_; 24358 | } 24359 | 24360 | std::size_t max_node_depth() const 24361 | { 24362 | return max_node_depth_; 24363 | } 24364 | 24365 | std::size_t max_local_vector_size() const 24366 | { 24367 | return max_local_vector_size_; 24368 | } 24369 | 24370 | std::size_t max_total_local_symbol_size_bytes() const 24371 | { 24372 | return max_total_local_symbol_size_bytes_; 24373 | } 24374 | 24375 | private: 24376 | 24377 | void load_compile_options(const std::size_t compile_options) 24378 | { 24379 | enable_replacer_ = (compile_options & e_replacer ) == e_replacer; 24380 | enable_joiner_ = (compile_options & e_joiner ) == e_joiner; 24381 | enable_numeric_check_ = (compile_options & e_numeric_check ) == e_numeric_check; 24382 | enable_bracket_check_ = (compile_options & e_bracket_check ) == e_bracket_check; 24383 | enable_sequence_check_ = (compile_options & e_sequence_check ) == e_sequence_check; 24384 | enable_commutative_check_ = (compile_options & e_commutative_check ) == e_commutative_check; 24385 | enable_strength_reduction_ = (compile_options & e_strength_reduction ) == e_strength_reduction; 24386 | enable_collect_vars_ = (compile_options & e_collect_vars ) == e_collect_vars; 24387 | enable_collect_funcs_ = (compile_options & e_collect_funcs ) == e_collect_funcs; 24388 | enable_collect_assings_ = (compile_options & e_collect_assings ) == e_collect_assings; 24389 | disable_vardef_ = (compile_options & e_disable_vardef ) == e_disable_vardef; 24390 | disable_rsrvd_sym_usr_ = (compile_options & e_disable_usr_on_rsrvd) == e_disable_usr_on_rsrvd; 24391 | disable_zero_return_ = (compile_options & e_disable_zero_return ) == e_disable_zero_return; 24392 | } 24393 | 24394 | std::string assign_opr_to_string(details::operator_type opr) const 24395 | { 24396 | switch (opr) 24397 | { 24398 | case details::e_assign : return ":=" 24399 | case details::e_addass : return "+=" 24400 | case details::e_subass : return "-=" 24401 | case details::e_mulass : return "*=" 24402 | case details::e_divass : return "/=" 24403 | case details::e_modass : return "%=" 24404 | default : return "" ; 24405 | } 24406 | } 24407 | 24408 | std::string arith_opr_to_string(details::operator_type opr) const 24409 | { 24410 | switch (opr) 24411 | { 24412 | case details::e_add : return "+" 24413 | case details::e_sub : return "-" 24414 | case details::e_mul : return "*" 24415 | case details::e_div : return "/" 24416 | case details::e_mod : return "%" 24417 | case details::e_pow : return "^" 24418 | default : return "" ; 24419 | } 24420 | } 24421 | 24422 | std::string inequality_opr_to_string(details::operator_type opr) const 24423 | { 24424 | switch (opr) 24425 | { 24426 | case details::e_lt : return "<" ; 24427 | case details::e_lte : return "<=" 24428 | case details::e_eq : return "==" 24429 | case details::e_equal : return "=" ; 24430 | case details::e_ne : return "!=" 24431 | case details::e_nequal: return "<>" 24432 | case details::e_gte : return ">=" 24433 | case details::e_gt : return ">" ; 24434 | default : return "" ; 24435 | } 24436 | } 24437 | 24438 | std::string logic_opr_to_string(details::operator_type opr) const 24439 | { 24440 | switch (opr) 24441 | { 24442 | case details::e_and : return "and" ; 24443 | case details::e_or : return "or" ; 24444 | case details::e_xor : return "xor" ; 24445 | case details::e_nand : return "nand" 24446 | case details::e_nor : return "nor" ; 24447 | case details::e_xnor : return "xnor" 24448 | case details::e_notl : return "not" ; 24449 | default : return "" ; 24450 | } 24451 | } 24452 | 24453 | bool enable_replacer_; 24454 | bool enable_joiner_; 24455 | bool enable_numeric_check_; 24456 | bool enable_bracket_check_; 24457 | bool enable_sequence_check_; 24458 | bool enable_commutative_check_; 24459 | bool enable_strength_reduction_; 24460 | bool enable_collect_vars_; 24461 | bool enable_collect_funcs_; 24462 | bool enable_collect_assings_; 24463 | bool disable_vardef_; 24464 | bool disable_rsrvd_sym_usr_; 24465 | bool disable_zero_return_; 24466 | 24467 | disabled_entity_set_t disabled_func_set_ ; 24468 | disabled_entity_set_t disabled_ctrl_set_ ; 24469 | disabled_entity_set_t disabled_logic_set_; 24470 | disabled_entity_set_t disabled_arithmetic_set_; 24471 | disabled_entity_set_t disabled_assignment_set_; 24472 | disabled_entity_set_t disabled_inequality_set_; 24473 | 24474 | std::size_t max_stack_depth_; 24475 | std::size_t max_node_depth_; 24476 | std::size_t max_total_local_symbol_size_bytes_; 24477 | std::size_t max_local_vector_size_; 24478 | 24479 | friend class parser<T>; 24480 | }; 24481 | 24482 | typedef settings_store settings_t; 24483 | 24484 | explicit parser(const settings_t& settings = settings_t()) 24485 | : settings_(settings) 24486 | , resolve_unknown_symbol_(false) 24487 | , results_context_(0) 24488 | , unknown_symbol_resolver_(reinterpret_cast<unknown_symbol_resolver*>(0)) 24489 | #ifdef _MSC_VER 24490 | #pragma warning(push) 24491 | #pragma warning (disable:4355) 24492 | #endif 24493 | , sem_(*this) 24494 | #ifdef _MSC_VER 24495 | #pragma warning(pop) 24496 | #endif 24497 | , operator_joiner_2_(2) 24498 | , operator_joiner_3_(3) 24499 | , loop_runtime_check_(0) 24500 | , vector_access_runtime_check_(0) 24501 | , compilation_check_ptr_(0) 24502 | , assert_check_(0) 24503 | { 24504 | init_precompilation(); 24505 | 24506 | load_operations_map (base_ops_map_ ); 24507 | load_unary_operations_map (unary_op_map_ ); 24508 | load_binary_operations_map (binary_op_map_ ); 24509 | load_inv_binary_operations_map(inv_binary_op_map_); 24510 | load_sf3_map (sf3_map_ ); 24511 | load_sf4_map (sf4_map_ ); 24512 | 24513 | expression_generator_.init_synthesize_map(); 24514 | expression_generator_.set_parser(*this); 24515 | expression_generator_.set_uom (unary_op_map_ ); 24516 | expression_generator_.set_bom (binary_op_map_ ); 24517 | expression_generator_.set_ibom(inv_binary_op_map_); 24518 | expression_generator_.set_sf3m(sf3_map_ ); 24519 | expression_generator_.set_sf4m(sf4_map_ ); 24520 | expression_generator_.set_strength_reduction_state(settings_.strength_reduction_enabled()); 24521 | } 24522 | 24523 | ~parser() 24524 | {} 24525 | 24526 | inline void init_precompilation() 24527 | { 24528 | dec_.collect_variables() = 24529 | settings_.collect_variables_enabled(); 24530 | 24531 | dec_.collect_functions() = 24532 | settings_.collect_functions_enabled(); 24533 | 24534 | dec_.collect_assignments() = 24535 | settings_.collect_assignments_enabled(); 24536 | 24537 | if (settings_.replacer_enabled()) 24538 | { 24539 | symbol_replacer_.clear(); 24540 | symbol_replacer_.add_replace("true" , "1", lexer::token::e_number); 24541 | symbol_replacer_.add_replace("false", "0", lexer::token::e_number); 24542 | helper_assembly_.token_modifier_list.clear(); 24543 | helper_assembly_.register_modifier(&symbol_replacer_); 24544 | } 24545 | 24546 | if (settings_.commutative_check_enabled()) 24547 | { 24548 | for (std::size_t i = 0; i < details::reserved_words_size; ++i) 24549 | { 24550 | commutative_inserter_.ignore_symbol(details::reserved_words[i]); 24551 | } 24552 | 24553 | helper_assembly_.token_inserter_list.clear(); 24554 | helper_assembly_.register_inserter(&commutative_inserter_); 24555 | } 24556 | 24557 | if (settings_.joiner_enabled()) 24558 | { 24559 | helper_assembly_.token_joiner_list.clear(); 24560 | helper_assembly_.register_joiner(&operator_joiner_2_); 24561 | helper_assembly_.register_joiner(&operator_joiner_3_); 24562 | } 24563 | 24564 | if ( 24565 | settings_.numeric_check_enabled () || 24566 | settings_.bracket_check_enabled () || 24567 | settings_.sequence_check_enabled() 24568 | ) 24569 | { 24570 | helper_assembly_.token_scanner_list.clear(); 24571 | 24572 | if (settings_.numeric_check_enabled()) 24573 | { 24574 | helper_assembly_.register_scanner(&numeric_checker_); 24575 | } 24576 | 24577 | if (settings_.bracket_check_enabled()) 24578 | { 24579 | helper_assembly_.register_scanner(&bracket_checker_); 24580 | } 24581 | 24582 | if (settings_.sequence_check_enabled()) 24583 | { 24584 | helper_assembly_.register_scanner(&sequence_validator_ ); 24585 | helper_assembly_.register_scanner(&sequence_validator_3tkns_); 24586 | } 24587 | } 24588 | } 24589 | 24590 | inline bool compile(const std::string& expression_string, expression<T>& expr) 24591 | { 24592 | state_ .reset(); 24593 | error_list_ .clear(); 24594 | brkcnt_list_ .clear(); 24595 | synthesis_error_ .clear(); 24596 | immutable_memory_map_.reset(); 24597 | immutable_symtok_map_.clear(); 24598 | current_state_stack_ .clear(); 24599 | assert_ids_ .clear(); 24600 | sem_ .cleanup(); 24601 | 24602 | return_cleanup(); 24603 | 24604 | if (!valid_settings()) 24605 | { 24606 | return false; 24607 | } 24608 | 24609 | expression_generator_.set_allocator(node_allocator_); 24610 | 24611 | if (expression_string.empty()) 24612 | { 24613 | set_error(make_error( 24614 | parser_error::e_syntax, 24615 | "ERR001 - Empty expression!", 24616 | exprtk_error_location)); 24617 | 24618 | return false; 24619 | } 24620 | 24621 | if (!init(expression_string)) 24622 | { 24623 | process_lexer_errors(); 24624 | return false; 24625 | } 24626 | 24627 | if (lexer().empty()) 24628 | { 24629 | set_error(make_error( 24630 | parser_error::e_syntax, 24631 | "ERR002 - Empty expression!", 24632 | exprtk_error_location)); 24633 | 24634 | return false; 24635 | } 24636 | 24637 | if (halt_compilation_check()) 24638 | { 24639 | exprtk_debug(("halt_compilation_check() - compile checkpoint 0\n")); 24640 | sem_.cleanup(); 24641 | return false; 24642 | } 24643 | 24644 | if (!run_assemblies()) 24645 | { 24646 | sem_.cleanup(); 24647 | return false; 24648 | } 24649 | 24650 | if (halt_compilation_check()) 24651 | { 24652 | exprtk_debug(("halt_compilation_check() - compile checkpoint 1\n")); 24653 | sem_.cleanup(); 24654 | return false; 24655 | } 24656 | 24657 | symtab_store_.symtab_list_ = expr.get_symbol_table_list(); 24658 | dec_.clear(); 24659 | 24660 | lexer().begin(); 24661 | 24662 | next_token(); 24663 | 24664 | expression_node_ptr e = parse_corpus(); 24665 | 24666 | if ((0 != e) && (token_t::e_eof == current_token().type)) 24667 | { 24668 | bool* retinvk_ptr = 0; 24669 | 24670 | if (state_.return_stmt_present) 24671 | { 24672 | dec_.return_present_ = true; 24673 | 24674 | e = expression_generator_ 24675 | .return_envelope(e, results_context_, retinvk_ptr); 24676 | } 24677 | 24678 | expr.set_expression(e); 24679 | expr.set_retinvk(retinvk_ptr); 24680 | 24681 | register_local_vars(expr); 24682 | register_return_results(expr); 24683 | 24684 | return !(!expr); 24685 | } 24686 | else 24687 | { 24688 | if (error_list_.empty()) 24689 | { 24690 | set_error(make_error( 24691 | parser_error::e_syntax, 24692 | current_token(), 24693 | "ERR003 - Invalid expression encountered", 24694 | exprtk_error_location)); 24695 | } 24696 | 24697 | if ((0 != e) && branch_deletable(e)) 24698 | { 24699 | destroy_node(e); 24700 | } 24701 | 24702 | dec_.clear (); 24703 | sem_.cleanup (); 24704 | return_cleanup(); 24705 | 24706 | return false; 24707 | } 24708 | } 24709 | 24710 | inline expression_t compile(const std::string& expression_string, symbol_table_t& symtab) 24711 | { 24712 | expression_t expression; 24713 | expression.register_symbol_table(symtab); 24714 | compile(expression_string,expression); 24715 | return expression; 24716 | } 24717 | 24718 | void process_lexer_errors() 24719 | { 24720 | for (std::size_t i = 0; i < lexer().size(); ++i) 24721 | { 24722 | if (lexer()[i].is_error()) 24723 | { 24724 | std::string diagnostic = "ERR004 - " 24725 | 24726 | switch (lexer()[i].type) 24727 | { 24728 | case lexer::token::e_error : diagnostic += "General token error" 24729 | break; 24730 | 24731 | case lexer::token::e_err_symbol : diagnostic += "Symbol error" 24732 | break; 24733 | 24734 | case lexer::token::e_err_number : diagnostic += "Invalid numeric token" 24735 | break; 24736 | 24737 | case lexer::token::e_err_string : diagnostic += "Invalid string token" 24738 | break; 24739 | 24740 | case lexer::token::e_err_sfunc : diagnostic += "Invalid special function token" 24741 | break; 24742 | 24743 | default : diagnostic += "Unknown compiler error" 24744 | } 24745 | 24746 | set_error(make_error( 24747 | parser_error::e_lexer, 24748 | lexer()[i], 24749 | diagnostic + ": " + lexer()[i].value, 24750 | exprtk_error_location)); 24751 | } 24752 | } 24753 | } 24754 | 24755 | inline bool run_assemblies() 24756 | { 24757 | if (settings_.commutative_check_enabled()) 24758 | { 24759 | helper_assembly_.run_inserters(lexer()); 24760 | } 24761 | 24762 | if (settings_.joiner_enabled()) 24763 | { 24764 | helper_assembly_.run_joiners(lexer()); 24765 | } 24766 | 24767 | if (settings_.replacer_enabled()) 24768 | { 24769 | helper_assembly_.run_modifiers(lexer()); 24770 | } 24771 | 24772 | if ( 24773 | settings_.numeric_check_enabled () || 24774 | settings_.bracket_check_enabled () || 24775 | settings_.sequence_check_enabled() 24776 | ) 24777 | { 24778 | if (!helper_assembly_.run_scanners(lexer())) 24779 | { 24780 | if (helper_assembly_.error_token_scanner) 24781 | { 24782 | lexer::helper::bracket_checker* bracket_checker_ptr = 0; 24783 | lexer::helper::numeric_checker<T>* numeric_checker_ptr = 0; 24784 | lexer::helper::sequence_validator* sequence_validator_ptr = 0; 24785 | lexer::helper::sequence_validator_3tokens* sequence_validator3_ptr = 0; 24786 | 24787 | if (0 != (bracket_checker_ptr = dynamic_cast<lexer::helper::bracket_checker*>(helper_assembly_.error_token_scanner))) 24788 | { 24789 | set_error(make_error( 24790 | parser_error::e_token, 24791 | bracket_checker_ptr->error_token(), 24792 | "ERR005 - Mismatched brackets: '" + bracket_checker_ptr->error_token().value + "'", 24793 | exprtk_error_location)); 24794 | } 24795 | else if (0 != (numeric_checker_ptr = dynamic_cast<lexer::helper::numeric_checker<T>*>(helper_assembly_.error_token_scanner))) 24796 | { 24797 | for (std::size_t i = 0; i < numeric_checker_ptr->error_count(); ++i) 24798 | { 24799 | lexer::token error_token = lexer()[numeric_checker_ptr->error_index(i)]; 24800 | 24801 | set_error(make_error( 24802 | parser_error::e_token, 24803 | error_token, 24804 | "ERR006 - Invalid numeric token: '" + error_token.value + "'", 24805 | exprtk_error_location)); 24806 | } 24807 | 24808 | if (numeric_checker_ptr->error_count()) 24809 | { 24810 | numeric_checker_ptr->clear_errors(); 24811 | } 24812 | } 24813 | else if (0 != (sequence_validator_ptr = dynamic_cast<lexer::helper::sequence_validator*>(helper_assembly_.error_token_scanner))) 24814 | { 24815 | for (std::size_t i = 0; i < sequence_validator_ptr->error_count(); ++i) 24816 | { 24817 | std::pair<lexer::token,lexer::token> error_token = sequence_validator_ptr->error(i); 24818 | 24819 | set_error(make_error( 24820 | parser_error::e_token, 24821 | error_token.first, 24822 | "ERR007 - Invalid token sequence: '" + 24823 | error_token.first.value + "' and '" + 24824 | error_token.second.value + "'", 24825 | exprtk_error_location)); 24826 | } 24827 | 24828 | if (sequence_validator_ptr->error_count()) 24829 | { 24830 | sequence_validator_ptr->clear_errors(); 24831 | } 24832 | } 24833 | else if (0 != (sequence_validator3_ptr = dynamic_cast<lexer::helper::sequence_validator_3tokens*>(helper_assembly_.error_token_scanner))) 24834 | { 24835 | for (std::size_t i = 0; i < sequence_validator3_ptr->error_count(); ++i) 24836 | { 24837 | std::pair<lexer::token,lexer::token> error_token = sequence_validator3_ptr->error(i); 24838 | 24839 | set_error(make_error( 24840 | parser_error::e_token, 24841 | error_token.first, 24842 | "ERR008 - Invalid token sequence: '" + 24843 | error_token.first.value + "' and '" + 24844 | error_token.second.value + "'", 24845 | exprtk_error_location)); 24846 | } 24847 | 24848 | if (sequence_validator3_ptr->error_count()) 24849 | { 24850 | sequence_validator3_ptr->clear_errors(); 24851 | } 24852 | } 24853 | } 24854 | 24855 | return false; 24856 | } 24857 | } 24858 | 24859 | return true; 24860 | } 24861 | 24862 | inline settings_store& settings() 24863 | { 24864 | return settings_; 24865 | } 24866 | 24867 | inline parser_error::type get_error(const std::size_t& index) const 24868 | { 24869 | if (index < error_list_.size()) 24870 | { 24871 | return error_list_[index]; 24872 | } 24873 | 24874 | throw std::invalid_argument("parser::get_error() - Invalid error index specified"); 24875 | } 24876 | 24877 | inline std::string error() const 24878 | { 24879 | if (!error_list_.empty()) 24880 | { 24881 | return error_list_[0].diagnostic; 24882 | } 24883 | else 24884 | return std::string("No Error"); 24885 | } 24886 | 24887 | inline std::size_t error_count() const 24888 | { 24889 | return error_list_.size(); 24890 | } 24891 | 24892 | inline dependent_entity_collector& dec() 24893 | { 24894 | return dec_; 24895 | } 24896 | 24897 | inline std::size_t total_local_symbol_size_bytes() const 24898 | { 24899 | return sem_.total_local_symb_size_bytes(); 24900 | } 24901 | 24902 | inline bool replace_symbol(const std::string& old_symbol, const std::string& new_symbol) 24903 | { 24904 | if (!settings_.replacer_enabled()) 24905 | return false; 24906 | else if (details::is_reserved_word(old_symbol)) 24907 | return false; 24908 | else 24909 | return symbol_replacer_.add_replace(old_symbol,new_symbol,lexer::token::e_symbol); 24910 | } 24911 | 24912 | inline bool remove_replace_symbol(const std::string& symbol) 24913 | { 24914 | if (!settings_.replacer_enabled()) 24915 | return false; 24916 | else if (details::is_reserved_word(symbol)) 24917 | return false; 24918 | else 24919 | return symbol_replacer_.remove(symbol); 24920 | } 24921 | 24922 | inline void enable_unknown_symbol_resolver(unknown_symbol_resolver* usr = reinterpret_cast<unknown_symbol_resolver*>(0)) 24923 | { 24924 | resolve_unknown_symbol_ = true; 24925 | 24926 | if (usr) 24927 | unknown_symbol_resolver_ = usr; 24928 | else 24929 | unknown_symbol_resolver_ = &default_usr_; 24930 | } 24931 | 24932 | inline void enable_unknown_symbol_resolver(unknown_symbol_resolver& usr) 24933 | { 24934 | enable_unknown_symbol_resolver(&usr); 24935 | } 24936 | 24937 | inline void disable_unknown_symbol_resolver() 24938 | { 24939 | resolve_unknown_symbol_ = false; 24940 | unknown_symbol_resolver_ = &default_usr_; 24941 | } 24942 | 24943 | inline void register_loop_runtime_check(loop_runtime_check& lrtchk) 24944 | { 24945 | loop_runtime_check_ = &lrtchk; 24946 | } 24947 | 24948 | inline void register_vector_access_runtime_check(vector_access_runtime_check& vartchk) 24949 | { 24950 | vector_access_runtime_check_ = &vartchk; 24951 | } 24952 | 24953 | inline void register_compilation_timeout_check(compilation_check& compchk) 24954 | { 24955 | compilation_check_ptr_ = &compchk; 24956 | } 24957 | 24958 | inline void register_assert_check(assert_check& assrt_chck) 24959 | { 24960 | assert_check_ = &assrt_chck; 24961 | } 24962 | 24963 | inline void clear_loop_runtime_check() 24964 | { 24965 | loop_runtime_check_ = loop_runtime_check_ptr(0); 24966 | } 24967 | 24968 | inline void clear_vector_access_runtime_check() 24969 | { 24970 | vector_access_runtime_check_ = vector_access_runtime_check_ptr(0); 24971 | } 24972 | 24973 | inline void clear_compilation_timeout_check() 24974 | { 24975 | compilation_check_ptr_ = compilation_check_ptr(0); 24976 | } 24977 | 24978 | inline void clear_assert_check() 24979 | { 24980 | assert_check_ = assert_check_ptr(0); 24981 | } 24982 | 24983 | private: 24984 | 24985 | inline bool valid_base_operation(const std::string& symbol) const 24986 | { 24987 | const std::size_t length = symbol.size(); 24988 | 24989 | if ( 24990 | (length < 3) || // Shortest base op symbol length 24991 | (length > 9) // Longest base op symbol length 24992 | ) 24993 | return false; 24994 | else 24995 | return settings_.function_enabled(symbol) && 24996 | (base_ops_map_.end() != base_ops_map_.find(symbol)); 24997 | } 24998 | 24999 | inline bool valid_vararg_operation(const std::string& symbol) const 25000 | { 25001 | static const std::string s_sum = "sum" ; 25002 | static const std::string s_mul = "mul" ; 25003 | static const std::string s_avg = "avg" ; 25004 | static const std::string s_min = "min" ; 25005 | static const std::string s_max = "max" ; 25006 | static const std::string s_mand = "mand" 25007 | static const std::string s_mor = "mor" ; 25008 | static const std::string s_multi = "~" ; 25009 | static const std::string s_mswitch = "[*]" ; 25010 | 25011 | return 25012 | ( 25013 | details::imatch(symbol,s_sum ) || 25014 | details::imatch(symbol,s_mul ) || 25015 | details::imatch(symbol,s_avg ) || 25016 | details::imatch(symbol,s_min ) || 25017 | details::imatch(symbol,s_max ) || 25018 | details::imatch(symbol,s_mand ) || 25019 | details::imatch(symbol,s_mor ) || 25020 | details::imatch(symbol,s_multi ) || 25021 | details::imatch(symbol,s_mswitch) 25022 | ) && 25023 | settings_.function_enabled(symbol); 25024 | } 25025 | 25026 | bool is_invalid_logic_operation(const details::operator_type operation) const 25027 | { 25028 | return settings_.logic_disabled(operation); 25029 | } 25030 | 25031 | bool is_invalid_arithmetic_operation(const details::operator_type operation) const 25032 | { 25033 | return settings_.arithmetic_disabled(operation); 25034 | } 25035 | 25036 | bool is_invalid_assignment_operation(const details::operator_type operation) const 25037 | { 25038 | return settings_.assignment_disabled(operation); 25039 | } 25040 | 25041 | bool is_invalid_inequality_operation(const details::operator_type operation) const 25042 | { 25043 | return settings_.inequality_disabled(operation); 25044 | } 25045 | 25046 | #ifdef exprtk_enable_debugging 25047 | inline void next_token() 25048 | { 25049 | const std::string ct_str = current_token().value; 25050 | const std::size_t ct_pos = current_token().position; 25051 | parser_helper::next_token(); 25052 | const std::string depth(2 * state_.scope_depth,' '); 25053 | exprtk_debug(("%s" 25054 | "prev[%s | %04d] --> curr[%s | %04d] stack_level: %3d\n", 25055 | depth.c_str(), 25056 | ct_str.c_str(), 25057 | static_cast<unsigned int>(ct_pos), 25058 | current_token().value.c_str(), 25059 | static_cast<unsigned int>(current_token().position), 25060 | static_cast<unsigned int>(state_.stack_depth))); 25061 | } 25062 | #endif 25063 | 25064 | inline expression_node_ptr parse_corpus() 25065 | { 25066 | std::vector<expression_node_ptr> arg_list; 25067 | std::vector<bool> side_effect_list; 25068 | 25069 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 25070 | 25071 | lexer::token begin_token; 25072 | lexer::token end_token; 25073 | 25074 | for ( ; ; ) 25075 | { 25076 | state_.side_effect_present = false; 25077 | 25078 | begin_token = current_token(); 25079 | 25080 | expression_node_ptr arg = parse_expression(); 25081 | 25082 | if (0 == arg) 25083 | { 25084 | if (error_list_.empty()) 25085 | { 25086 | set_error(make_error( 25087 | parser_error::e_syntax, 25088 | current_token(), 25089 | "ERR009 - Invalid expression encountered", 25090 | exprtk_error_location)); 25091 | } 25092 | 25093 | return error_node(); 25094 | } 25095 | else 25096 | { 25097 | arg_list.push_back(arg); 25098 | 25099 | side_effect_list.push_back(state_.side_effect_present); 25100 | 25101 | end_token = current_token(); 25102 | 25103 | const std::string sub_expr = construct_subexpr(begin_token, end_token); 25104 | 25105 | exprtk_debug(("parse_corpus(%02d) Subexpr: %s\n", 25106 | static_cast<int>(arg_list.size() - 1), 25107 | sub_expr.c_str())); 25108 | 25109 | exprtk_debug(("parse_corpus(%02d) - Side effect present: %s\n", 25110 | static_cast<int>(arg_list.size() - 1), 25111 | state_.side_effect_present ? "true" : "false")); 25112 | 25113 | exprtk_debug(("-------------------------------------------------\n")); 25114 | } 25115 | 25116 | if (token_is(token_t::e_eof,prsrhlpr_t::e_hold)) 25117 | { 25118 | if (lexer().finished()) 25119 | break; 25120 | else 25121 | next_token(); 25122 | } 25123 | else if ( 25124 | !settings_.commutative_check_enabled() && 25125 | ( 25126 | current_token().type == token_t::e_symbol || 25127 | current_token().type == token_t::e_number || 25128 | current_token().type == token_t::e_string || 25129 | token_is_bracket(prsrhlpr_t::e_hold) 25130 | ) 25131 | ) 25132 | { 25133 | set_error(make_error( 25134 | parser_error::e_syntax, 25135 | current_token(), 25136 | "ERR010 - Invalid syntax '" + current_token().value + "' possible missing operator or context", 25137 | exprtk_error_location)); 25138 | 25139 | return error_node(); 25140 | } 25141 | } 25142 | 25143 | if ( 25144 | !arg_list.empty() && 25145 | is_return_node(arg_list.back()) 25146 | ) 25147 | { 25148 | dec_.final_stmt_return_ = true; 25149 | } 25150 | 25151 | const expression_node_ptr result = simplify(arg_list,side_effect_list); 25152 | 25153 | svd.delete_ptr = (0 == result); 25154 | 25155 | return result; 25156 | } 25157 | 25158 | std::string construct_subexpr(lexer::token& begin_token, 25159 | lexer::token& end_token, 25160 | const bool cleanup_whitespace = true) 25161 | { 25162 | std::string result = lexer().substr(begin_token.position,end_token.position); 25163 | if (cleanup_whitespace) 25164 | { 25165 | for (std::size_t i = 0; i < result.size(); ++i) 25166 | { 25167 | if (details::is_whitespace(result[i])) result[i] = ' '; 25168 | } 25169 | } 25170 | 25171 | return result; 25172 | } 25173 | 25174 | static const precedence_level default_precedence = e_level00; 25175 | 25176 | struct state_t 25177 | { 25178 | inline void set(const precedence_level& l, 25179 | const precedence_level& r, 25180 | const details::operator_type& o, 25181 | const token_t tkn = token_t()) 25182 | { 25183 | left = l; 25184 | right = r; 25185 | operation = o; 25186 | token = tkn; 25187 | } 25188 | 25189 | inline void reset() 25190 | { 25191 | left = e_level00; 25192 | right = e_level00; 25193 | operation = details::e_default; 25194 | } 25195 | 25196 | precedence_level left; 25197 | precedence_level right; 25198 | details::operator_type operation; 25199 | token_t token; 25200 | }; 25201 | 25202 | inline void push_current_state(const state_t current_state) 25203 | { 25204 | current_state_stack_.push_back(current_state); 25205 | } 25206 | 25207 | inline void pop_current_state() 25208 | { 25209 | if (!current_state_stack_.empty()) 25210 | { 25211 | current_state_stack_.pop_back(); 25212 | } 25213 | } 25214 | 25215 | inline state_t current_state() const 25216 | { 25217 | return (!current_state_stack_.empty()) ? 25218 | current_state_stack_.back() : 25219 | state_t(); 25220 | } 25221 | 25222 | inline bool halt_compilation_check() 25223 | { 25224 | compilation_check::compilation_context context; 25225 | 25226 | if (compilation_check_ptr_ && !compilation_check_ptr_->continue_compilation(context)) 25227 | { 25228 | const std::string error_message = 25229 | !context.error_message.empty() ? " Details: " + context.error_message : "" 25230 | 25231 | set_error(make_error( 25232 | parser_error::e_parser, 25233 | token_t(), 25234 | "ERR011 - Internal compilation check failed." + error_message, 25235 | exprtk_error_location)); 25236 | 25237 | return true; 25238 | } 25239 | 25240 | return false; 25241 | } 25242 | 25243 | inline expression_node_ptr parse_expression(precedence_level precedence = e_level00) 25244 | { 25245 | if (halt_compilation_check()) 25246 | { 25247 | exprtk_debug(("halt_compilation_check() - parse_expression checkpoint 2\n")); 25248 | return error_node(); 25249 | } 25250 | 25251 | stack_limit_handler slh(*this); 25252 | 25253 | if (!slh) 25254 | { 25255 | return error_node(); 25256 | } 25257 | 25258 | expression_node_ptr expression = parse_branch(precedence); 25259 | 25260 | if (0 == expression) 25261 | { 25262 | return error_node(); 25263 | } 25264 | 25265 | if (token_is(token_t::e_eof,prsrhlpr_t::e_hold)) 25266 | { 25267 | return expression; 25268 | } 25269 | 25270 | bool break_loop = false; 25271 | 25272 | state_t current_state; 25273 | 25274 | for ( ; ; ) 25275 | { 25276 | current_state.reset(); 25277 | 25278 | switch (current_token().type) 25279 | { 25280 | case token_t::e_assign : current_state.set(e_level00, e_level00, details::e_assign, current_token()); break; 25281 | case token_t::e_addass : current_state.set(e_level00, e_level00, details::e_addass, current_token()); break; 25282 | case token_t::e_subass : current_state.set(e_level00, e_level00, details::e_subass, current_token()); break; 25283 | case token_t::e_mulass : current_state.set(e_level00, e_level00, details::e_mulass, current_token()); break; 25284 | case token_t::e_divass : current_state.set(e_level00, e_level00, details::e_divass, current_token()); break; 25285 | case token_t::e_modass : current_state.set(e_level00, e_level00, details::e_modass, current_token()); break; 25286 | case token_t::e_swap : current_state.set(e_level00, e_level00, details::e_swap , current_token()); break; 25287 | case token_t::e_lt : current_state.set(e_level05, e_level06, details::e_lt , current_token()); break; 25288 | case token_t::e_lte : current_state.set(e_level05, e_level06, details::e_lte , current_token()); break; 25289 | case token_t::e_eq : current_state.set(e_level05, e_level06, details::e_eq , current_token()); break; 25290 | case token_t::e_ne : current_state.set(e_level05, e_level06, details::e_ne , current_token()); break; 25291 | case token_t::e_gte : current_state.set(e_level05, e_level06, details::e_gte , current_token()); break; 25292 | case token_t::e_gt : current_state.set(e_level05, e_level06, details::e_gt , current_token()); break; 25293 | case token_t::e_add : current_state.set(e_level07, e_level08, details::e_add , current_token()); break; 25294 | case token_t::e_sub : current_state.set(e_level07, e_level08, details::e_sub , current_token()); break; 25295 | case token_t::e_div : current_state.set(e_level10, e_level11, details::e_div , current_token()); break; 25296 | case token_t::e_mul : current_state.set(e_level10, e_level11, details::e_mul , current_token()); break; 25297 | case token_t::e_mod : current_state.set(e_level10, e_level11, details::e_mod , current_token()); break; 25298 | case token_t::e_pow : current_state.set(e_level12, e_level12, details::e_pow , current_token()); break; 25299 | default : 25300 | if (token_t::e_symbol == current_token().type) 25301 | { 25302 | static const std::string s_and = "and" ; 25303 | static const std::string s_nand = "nand" ; 25304 | static const std::string s_or = "or" ; 25305 | static const std::string s_nor = "nor" ; 25306 | static const std::string s_xor = "xor" ; 25307 | static const std::string s_xnor = "xnor" ; 25308 | static const std::string s_in = "in" ; 25309 | static const std::string s_like = "like" ; 25310 | static const std::string s_ilike = "ilike" 25311 | static const std::string s_and1 = "&" ; 25312 | static const std::string s_or1 = "|" ; 25313 | static const std::string s_not = "not" ; 25314 | 25315 | if (details::imatch(current_token().value,s_and)) 25316 | { 25317 | current_state.set(e_level03, e_level04, details::e_and, current_token()); 25318 | break; 25319 | } 25320 | else if (details::imatch(current_token().value,s_and1)) 25321 | { 25322 | #ifndef exprtk_disable_sc_andor 25323 | current_state.set(e_level03, e_level04, details::e_scand, current_token()); 25324 | #else 25325 | current_state.set(e_level03, e_level04, details::e_and, current_token()); 25326 | #endif 25327 | break; 25328 | } 25329 | else if (details::imatch(current_token().value,s_nand)) 25330 | { 25331 | current_state.set(e_level03, e_level04, details::e_nand, current_token()); 25332 | break; 25333 | } 25334 | else if (details::imatch(current_token().value,s_or)) 25335 | { 25336 | current_state.set(e_level01, e_level02, details::e_or, current_token()); 25337 | break; 25338 | } 25339 | else if (details::imatch(current_token().value,s_or1)) 25340 | { 25341 | #ifndef exprtk_disable_sc_andor 25342 | current_state.set(e_level01, e_level02, details::e_scor, current_token()); 25343 | #else 25344 | current_state.set(e_level01, e_level02, details::e_or, current_token()); 25345 | #endif 25346 | break; 25347 | } 25348 | else if (details::imatch(current_token().value,s_nor)) 25349 | { 25350 | current_state.set(e_level01, e_level02, details::e_nor, current_token()); 25351 | break; 25352 | } 25353 | else if (details::imatch(current_token().value,s_xor)) 25354 | { 25355 | current_state.set(e_level01, e_level02, details::e_xor, current_token()); 25356 | break; 25357 | } 25358 | else if (details::imatch(current_token().value,s_xnor)) 25359 | { 25360 | current_state.set(e_level01, e_level02, details::e_xnor, current_token()); 25361 | break; 25362 | } 25363 | else if (details::imatch(current_token().value,s_in)) 25364 | { 25365 | current_state.set(e_level04, e_level04, details::e_in, current_token()); 25366 | break; 25367 | } 25368 | else if (details::imatch(current_token().value,s_like)) 25369 | { 25370 | current_state.set(e_level04, e_level04, details::e_like, current_token()); 25371 | break; 25372 | } 25373 | else if (details::imatch(current_token().value,s_ilike)) 25374 | { 25375 | current_state.set(e_level04, e_level04, details::e_ilike, current_token()); 25376 | break; 25377 | } 25378 | else if (details::imatch(current_token().value,s_not)) 25379 | { 25380 | break; 25381 | } 25382 | } 25383 | 25384 | break_loop = true; 25385 | } 25386 | 25387 | if (break_loop) 25388 | { 25389 | parse_pending_string_rangesize(expression); 25390 | break; 25391 | } 25392 | else if (current_state.left < precedence) 25393 | break; 25394 | 25395 | const lexer::token prev_token = current_token(); 25396 | 25397 | next_token(); 25398 | 25399 | expression_node_ptr right_branch = error_node(); 25400 | expression_node_ptr new_expression = error_node(); 25401 | 25402 | if (is_invalid_logic_operation(current_state.operation)) 25403 | { 25404 | free_node(node_allocator_, expression); 25405 | 25406 | set_error(make_error( 25407 | parser_error::e_syntax, 25408 | prev_token, 25409 | "ERR012 - Invalid or disabled logic operation '" + details::to_str(current_state.operation) + "'", 25410 | exprtk_error_location)); 25411 | 25412 | return error_node(); 25413 | } 25414 | else if (is_invalid_arithmetic_operation(current_state.operation)) 25415 | { 25416 | free_node(node_allocator_, expression); 25417 | 25418 | set_error(make_error( 25419 | parser_error::e_syntax, 25420 | prev_token, 25421 | "ERR013 - Invalid or disabled arithmetic operation '" + details::to_str(current_state.operation) + "'", 25422 | exprtk_error_location)); 25423 | 25424 | return error_node(); 25425 | } 25426 | else if (is_invalid_inequality_operation(current_state.operation)) 25427 | { 25428 | free_node(node_allocator_, expression); 25429 | 25430 | set_error(make_error( 25431 | parser_error::e_syntax, 25432 | prev_token, 25433 | "ERR014 - Invalid inequality operation '" + details::to_str(current_state.operation) + "'", 25434 | exprtk_error_location)); 25435 | 25436 | return error_node(); 25437 | } 25438 | else if (is_invalid_assignment_operation(current_state.operation)) 25439 | { 25440 | free_node(node_allocator_, expression); 25441 | 25442 | set_error(make_error( 25443 | parser_error::e_syntax, 25444 | prev_token, 25445 | "ERR015 - Invalid or disabled assignment operation '" + details::to_str(current_state.operation) + "'", 25446 | exprtk_error_location)); 25447 | 25448 | return error_node(); 25449 | } 25450 | 25451 | if (0 != (right_branch = parse_expression(current_state.right))) 25452 | { 25453 | if ( 25454 | details::is_return_node(expression ) || 25455 | details::is_return_node(right_branch) 25456 | ) 25457 | { 25458 | free_node(node_allocator_, expression ); 25459 | free_node(node_allocator_, right_branch); 25460 | 25461 | set_error(make_error( 25462 | parser_error::e_syntax, 25463 | prev_token, 25464 | "ERR016 - Return statements cannot be part of sub-expressions", 25465 | exprtk_error_location)); 25466 | 25467 | return error_node(); 25468 | } 25469 | 25470 | push_current_state(current_state); 25471 | 25472 | new_expression = expression_generator_ 25473 | ( 25474 | current_state.operation, 25475 | expression, 25476 | right_branch 25477 | ); 25478 | 25479 | pop_current_state(); 25480 | } 25481 | 25482 | if (0 == new_expression) 25483 | { 25484 | if (error_list_.empty()) 25485 | { 25486 | set_error(make_error( 25487 | parser_error::e_syntax, 25488 | prev_token, 25489 | !synthesis_error_.empty() ? 25490 | synthesis_error_ : 25491 | "ERR017 - General parsing error at token: '" + prev_token.value + "'", 25492 | exprtk_error_location)); 25493 | } 25494 | 25495 | free_node(node_allocator_, expression ); 25496 | free_node(node_allocator_, right_branch); 25497 | 25498 | return error_node(); 25499 | } 25500 | else 25501 | { 25502 | if ( 25503 | token_is(token_t::e_ternary,prsrhlpr_t::e_hold) && 25504 | (e_level00 == precedence) 25505 | ) 25506 | { 25507 | expression = parse_ternary_conditional_statement(new_expression); 25508 | } 25509 | else 25510 | expression = new_expression; 25511 | 25512 | parse_pending_string_rangesize(expression); 25513 | } 25514 | } 25515 | 25516 | if ((0 != expression) && (expression->node_depth() > settings_.max_node_depth_)) 25517 | { 25518 | set_error(make_error( 25519 | parser_error::e_syntax, 25520 | current_token(), 25521 | "ERR018 - Expression depth of " + details::to_str(static_cast<int>(expression->node_depth())) + 25522 | " exceeds maximum allowed expression depth of " + details::to_str(static_cast<int>(settings_.max_node_depth_)), 25523 | exprtk_error_location)); 25524 | 25525 | free_node(node_allocator_, expression); 25526 | 25527 | return error_node(); 25528 | } 25529 | else if ( 25530 | !settings_.commutative_check_enabled() && 25531 | !details::is_logic_opr(current_token().value) && 25532 | (current_state.operation == details::e_default) && 25533 | ( 25534 | current_token().type == token_t::e_symbol || 25535 | current_token().type == token_t::e_number || 25536 | current_token().type == token_t::e_string 25537 | ) 25538 | ) 25539 | { 25540 | set_error(make_error( 25541 | parser_error::e_syntax, 25542 | current_token(), 25543 | "ERR019 - Invalid syntax '" + current_token().value + "' possible missing operator or context", 25544 | exprtk_error_location)); 25545 | 25546 | free_node(node_allocator_, expression); 25547 | 25548 | return error_node(); 25549 | } 25550 | 25551 | return expression; 25552 | } 25553 | 25554 | bool simplify_unary_negation_branch(expression_node_ptr& node) 25555 | { 25556 | { 25557 | typedef details::unary_branch_node<T,details::neg_op<T> > ubn_t; 25558 | ubn_t* n = dynamic_cast<ubn_t*>(node); 25559 | 25560 | if (n) 25561 | { 25562 | expression_node_ptr un_r = n->branch(0); 25563 | n->release(); 25564 | free_node(node_allocator_, node); 25565 | node = un_r; 25566 | 25567 | return true; 25568 | } 25569 | } 25570 | 25571 | { 25572 | typedef details::unary_variable_node<T,details::neg_op<T> > uvn_t; 25573 | 25574 | uvn_t* n = dynamic_cast<uvn_t*>(node); 25575 | 25576 | if (n) 25577 | { 25578 | const T& v = n->v(); 25579 | expression_node_ptr return_node = error_node(); 25580 | 25581 | if ( 25582 | (0 != (return_node = symtab_store_.get_variable(v))) || 25583 | (0 != (return_node = sem_ .get_variable(v))) 25584 | ) 25585 | { 25586 | free_node(node_allocator_, node); 25587 | node = return_node; 25588 | 25589 | return true; 25590 | } 25591 | else 25592 | { 25593 | set_error(make_error( 25594 | parser_error::e_syntax, 25595 | current_token(), 25596 | "ERR020 - Failed to find variable node in symbol table", 25597 | exprtk_error_location)); 25598 | 25599 | free_node(node_allocator_, node); 25600 | 25601 | return false; 25602 | } 25603 | } 25604 | } 25605 | 25606 | return false; 25607 | } 25608 | 25609 | static inline expression_node_ptr error_node() 25610 | { 25611 | return reinterpret_cast<expression_node_ptr>(0); 25612 | } 25613 | 25614 | struct scoped_expression_delete 25615 | { 25616 | scoped_expression_delete(parser<T>& pr, expression_node_ptr& expression) 25617 | : delete_ptr(true) 25618 | , parser_(pr) 25619 | , expression_(expression) 25620 | {} 25621 | 25622 | ~scoped_expression_delete() 25623 | { 25624 | if (delete_ptr) 25625 | { 25626 | free_node(parser_.node_allocator_, expression_); 25627 | } 25628 | } 25629 | 25630 | bool delete_ptr; 25631 | parser<T>& parser_; 25632 | expression_node_ptr& expression_; 25633 | 25634 | private: 25635 | 25636 | scoped_expression_delete(const scoped_expression_delete&) exprtk_delete; 25637 | scoped_expression_delete& operator=(const scoped_expression_delete&) exprtk_delete; 25638 | }; 25639 | 25640 | template <typename Type, std::size_t N> 25641 | struct scoped_delete 25642 | { 25643 | typedef Type* ptr_t; 25644 | 25645 | scoped_delete(parser<T>& pr, ptr_t& p) 25646 | : delete_ptr(true) 25647 | , parser_(pr) 25648 | , p_(&p) 25649 | {} 25650 | 25651 | scoped_delete(parser<T>& pr, ptr_t (&p)[N]) 25652 | : delete_ptr(true) 25653 | , parser_(pr) 25654 | , p_(&p[0]) 25655 | {} 25656 | 25657 | ~scoped_delete() 25658 | { 25659 | if (delete_ptr) 25660 | { 25661 | for (std::size_t i = 0; i < N; ++i) 25662 | { 25663 | free_node(parser_.node_allocator_, p_[i]); 25664 | } 25665 | } 25666 | } 25667 | 25668 | bool delete_ptr; 25669 | parser<T>& parser_; 25670 | ptr_t* p_; 25671 | 25672 | private: 25673 | 25674 | scoped_delete(const scoped_delete<Type,N>&) exprtk_delete; 25675 | scoped_delete<Type,N>& operator=(const scoped_delete<Type,N>&) exprtk_delete; 25676 | }; 25677 | 25678 | template <typename Type> 25679 | struct scoped_deq_delete 25680 | { 25681 | typedef Type* ptr_t; 25682 | 25683 | scoped_deq_delete(parser<T>& pr, std::deque<ptr_t>& deq) 25684 | : delete_ptr(true) 25685 | , parser_(pr) 25686 | , deq_(deq) 25687 | {} 25688 | 25689 | ~scoped_deq_delete() 25690 | { 25691 | if (delete_ptr && !deq_.empty()) 25692 | { 25693 | for (std::size_t i = 0; i < deq_.size(); ++i) 25694 | { 25695 | exprtk_debug(("~scoped_deq_delete() - deleting node: %p\n", reinterpret_cast<void*>(deq_[i]))); 25696 | free_node(parser_.node_allocator_,deq_[i]); 25697 | } 25698 | 25699 | deq_.clear(); 25700 | } 25701 | } 25702 | 25703 | bool delete_ptr; 25704 | parser<T>& parser_; 25705 | std::deque<ptr_t>& deq_; 25706 | 25707 | private: 25708 | 25709 | scoped_deq_delete(const scoped_deq_delete<Type>&) exprtk_delete; 25710 | scoped_deq_delete<Type>& operator=(const scoped_deq_delete<Type>&) exprtk_delete; 25711 | }; 25712 | 25713 | template <typename Type> 25714 | struct scoped_vec_delete 25715 | { 25716 | typedef Type* ptr_t; 25717 | 25718 | scoped_vec_delete(parser<T>& pr, std::vector<ptr_t>& vec) 25719 | : delete_ptr(true) 25720 | , parser_(pr) 25721 | , vec_(vec) 25722 | {} 25723 | 25724 | ~scoped_vec_delete() 25725 | { 25726 | if (delete_ptr && !vec_.empty()) 25727 | { 25728 | for (std::size_t i = 0; i < vec_.size(); ++i) 25729 | { 25730 | exprtk_debug(("~scoped_vec_delete() - deleting node: %p\n", reinterpret_cast<void*>(vec_[i]))); 25731 | free_node(parser_.node_allocator_,vec_[i]); 25732 | } 25733 | 25734 | vec_.clear(); 25735 | } 25736 | } 25737 | 25738 | ptr_t operator[](const std::size_t index) 25739 | { 25740 | return vec_[index]; 25741 | } 25742 | 25743 | bool delete_ptr; 25744 | parser<T>& parser_; 25745 | std::vector<ptr_t>& vec_; 25746 | 25747 | private: 25748 | 25749 | scoped_vec_delete(const scoped_vec_delete<Type>&) exprtk_delete; 25750 | scoped_vec_delete<Type>& operator=(const scoped_vec_delete<Type>&) exprtk_delete; 25751 | }; 25752 | 25753 | struct scoped_bool_negator 25754 | { 25755 | explicit scoped_bool_negator(bool& bb) 25756 | : b(bb) 25757 | { b = !b; } 25758 | 25759 | ~scoped_bool_negator() 25760 | { b = !b; } 25761 | 25762 | bool& b; 25763 | }; 25764 | 25765 | struct scoped_bool_or_restorer 25766 | { 25767 | explicit scoped_bool_or_restorer(bool& bb) 25768 | : b(bb) 25769 | , original_value_(bb) 25770 | {} 25771 | 25772 | ~scoped_bool_or_restorer() 25773 | { 25774 | b = b || original_value_; 25775 | } 25776 | 25777 | bool& b; 25778 | bool original_value_; 25779 | }; 25780 | 25781 | struct scoped_inc_dec 25782 | { 25783 | explicit scoped_inc_dec(std::size_t& v) 25784 | : v_(v) 25785 | { ++v_; } 25786 | 25787 | ~scoped_inc_dec() 25788 | { 25789 | assert(v_ > 0); 25790 | --v_; 25791 | } 25792 | 25793 | std::size_t& v_; 25794 | }; 25795 | 25796 | inline expression_node_ptr parse_function_invocation(ifunction<T>* function, const std::string& function_name) 25797 | { 25798 | expression_node_ptr func_node = reinterpret_cast<expression_node_ptr>(0); 25799 | 25800 | switch (function->param_count) 25801 | { 25802 | case 0 : func_node = parse_function_call_0 (function,function_name); break; 25803 | case 1 : func_node = parse_function_call< 1>(function,function_name); break; 25804 | case 2 : func_node = parse_function_call< 2>(function,function_name); break; 25805 | case 3 : func_node = parse_function_call< 3>(function,function_name); break; 25806 | case 4 : func_node = parse_function_call< 4>(function,function_name); break; 25807 | case 5 : func_node = parse_function_call< 5>(function,function_name); break; 25808 | case 6 : func_node = parse_function_call< 6>(function,function_name); break; 25809 | case 7 : func_node = parse_function_call< 7>(function,function_name); break; 25810 | case 8 : func_node = parse_function_call< 8>(function,function_name); break; 25811 | case 9 : func_node = parse_function_call< 9>(function,function_name); break; 25812 | case 10 : func_node = parse_function_call<10>(function,function_name); break; 25813 | case 11 : func_node = parse_function_call<11>(function,function_name); break; 25814 | case 12 : func_node = parse_function_call<12>(function,function_name); break; 25815 | case 13 : func_node = parse_function_call<13>(function,function_name); break; 25816 | case 14 : func_node = parse_function_call<14>(function,function_name); break; 25817 | case 15 : func_node = parse_function_call<15>(function,function_name); break; 25818 | case 16 : func_node = parse_function_call<16>(function,function_name); break; 25819 | case 17 : func_node = parse_function_call<17>(function,function_name); break; 25820 | case 18 : func_node = parse_function_call<18>(function,function_name); break; 25821 | case 19 : func_node = parse_function_call<19>(function,function_name); break; 25822 | case 20 : func_node = parse_function_call<20>(function,function_name); break; 25823 | default : { 25824 | set_error(make_error( 25825 | parser_error::e_syntax, 25826 | current_token(), 25827 | "ERR021 - Invalid number of parameters for function: '" + function_name + "'", 25828 | exprtk_error_location)); 25829 | 25830 | return error_node(); 25831 | } 25832 | } 25833 | 25834 | if (func_node) 25835 | return func_node; 25836 | else 25837 | { 25838 | set_error(make_error( 25839 | parser_error::e_syntax, 25840 | current_token(), 25841 | "ERR022 - Failed to generate call to function: '" + function_name + "'", 25842 | exprtk_error_location)); 25843 | 25844 | return error_node(); 25845 | } 25846 | } 25847 | 25848 | template <std::size_t NumberofParameters> 25849 | inline expression_node_ptr parse_function_call(ifunction<T>* function, const std::string& function_name) 25850 | { 25851 | #ifdef _MSC_VER 25852 | #pragma warning(push) 25853 | #pragma warning(disable: 4127) 25854 | #endif 25855 | if (0 == NumberofParameters) 25856 | { 25857 | set_error(make_error( 25858 | parser_error::e_syntax, 25859 | current_token(), 25860 | "ERR023 - Expecting ifunction '" + function_name + "' to have non-zero parameter count", 25861 | exprtk_error_location)); 25862 | 25863 | return error_node(); 25864 | } 25865 | #ifdef _MSC_VER 25866 | #pragma warning(pop) 25867 | #endif 25868 | 25869 | expression_node_ptr branch[NumberofParameters]; 25870 | expression_node_ptr result = error_node(); 25871 | 25872 | std::fill_n(branch, NumberofParameters, reinterpret_cast<expression_node_ptr>(0)); 25873 | 25874 | scoped_delete<expression_node_t,NumberofParameters> sd((*this),branch); 25875 | 25876 | next_token(); 25877 | 25878 | if (!token_is(token_t::e_lbracket)) 25879 | { 25880 | set_error(make_error( 25881 | parser_error::e_syntax, 25882 | current_token(), 25883 | "ERR024 - Expecting argument list for function: '" + function_name + "'", 25884 | exprtk_error_location)); 25885 | 25886 | return error_node(); 25887 | } 25888 | 25889 | for (int i = 0; i < static_cast<int>(NumberofParameters); ++i) 25890 | { 25891 | branch[i] = parse_expression(); 25892 | 25893 | if (0 == branch[i]) 25894 | { 25895 | set_error(make_error( 25896 | parser_error::e_syntax, 25897 | current_token(), 25898 | "ERR025 - Failed to parse argument " + details::to_str(i) + " for function: '" + function_name + "'", 25899 | exprtk_error_location)); 25900 | 25901 | return error_node(); 25902 | } 25903 | else if (i < static_cast<int>(NumberofParameters - 1)) 25904 | { 25905 | if (!token_is(token_t::e_comma)) 25906 | { 25907 | set_error(make_error( 25908 | parser_error::e_syntax, 25909 | current_token(), 25910 | "ERR026 - Invalid number of arguments for function: '" + function_name + "'", 25911 | exprtk_error_location)); 25912 | 25913 | return error_node(); 25914 | } 25915 | } 25916 | } 25917 | 25918 | if (!token_is(token_t::e_rbracket)) 25919 | { 25920 | set_error(make_error( 25921 | parser_error::e_syntax, 25922 | current_token(), 25923 | "ERR027 - Invalid number of arguments for function: '" + function_name + "'", 25924 | exprtk_error_location)); 25925 | 25926 | return error_node(); 25927 | } 25928 | else 25929 | result = expression_generator_.function(function,branch); 25930 | 25931 | sd.delete_ptr = (0 == result); 25932 | 25933 | return result; 25934 | } 25935 | 25936 | inline expression_node_ptr parse_function_call_0(ifunction<T>* function, const std::string& function_name) 25937 | { 25938 | expression_node_ptr result = expression_generator_.function(function); 25939 | 25940 | state_.side_effect_present = function->has_side_effects(); 25941 | 25942 | next_token(); 25943 | 25944 | if ( 25945 | token_is(token_t::e_lbracket) && 25946 | !token_is(token_t::e_rbracket) 25947 | ) 25948 | { 25949 | set_error(make_error( 25950 | parser_error::e_syntax, 25951 | current_token(), 25952 | "ERR028 - Expecting '()' to proceed call to function: '" + function_name + "'", 25953 | exprtk_error_location)); 25954 | 25955 | free_node(node_allocator_, result); 25956 | 25957 | return error_node(); 25958 | } 25959 | else 25960 | return result; 25961 | } 25962 | 25963 | template <std::size_t MaxNumberofParameters> 25964 | inline std::size_t parse_base_function_call(expression_node_ptr (¶m_list)[MaxNumberofParameters], const std::string& function_name = "") 25965 | { 25966 | std::fill_n(param_list, MaxNumberofParameters, reinterpret_cast<expression_node_ptr>(0)); 25967 | 25968 | scoped_delete<expression_node_t,MaxNumberofParameters> sd((*this),param_list); 25969 | 25970 | next_token(); 25971 | 25972 | if (!token_is(token_t::e_lbracket)) 25973 | { 25974 | set_error(make_error( 25975 | parser_error::e_syntax, 25976 | current_token(), 25977 | "ERR029 - Expected a '(' at start of function call to '" + function_name + 25978 | "', instead got: '" + current_token().value + "'", 25979 | exprtk_error_location)); 25980 | 25981 | return 0; 25982 | } 25983 | 25984 | if (token_is(token_t::e_rbracket, e_hold)) 25985 | { 25986 | set_error(make_error( 25987 | parser_error::e_syntax, 25988 | current_token(), 25989 | "ERR030 - Expected at least one input parameter for function call '" + function_name + "'", 25990 | exprtk_error_location)); 25991 | 25992 | return 0; 25993 | } 25994 | 25995 | std::size_t param_index = 0; 25996 | 25997 | for (; param_index < MaxNumberofParameters; ++param_index) 25998 | { 25999 | param_list[param_index] = parse_expression(); 26000 | 26001 | if (0 == param_list[param_index]) 26002 | return 0; 26003 | else if (token_is(token_t::e_rbracket)) 26004 | { 26005 | sd.delete_ptr = false; 26006 | break; 26007 | } 26008 | else if (token_is(token_t::e_comma)) 26009 | continue; 26010 | else 26011 | { 26012 | set_error(make_error( 26013 | parser_error::e_syntax, 26014 | current_token(), 26015 | "ERR031 - Expected a ',' between function input parameters, instead got: '" + current_token().value + "'", 26016 | exprtk_error_location)); 26017 | 26018 | return 0; 26019 | } 26020 | } 26021 | 26022 | if (sd.delete_ptr) 26023 | { 26024 | set_error(make_error( 26025 | parser_error::e_syntax, 26026 | current_token(), 26027 | "ERR032 - Invalid number of input parameters passed to function '" + function_name + "'", 26028 | exprtk_error_location)); 26029 | 26030 | return 0; 26031 | } 26032 | 26033 | return (param_index + 1); 26034 | } 26035 | 26036 | inline expression_node_ptr parse_base_operation() 26037 | { 26038 | typedef std::pair<base_ops_map_t::iterator,base_ops_map_t::iterator> map_range_t; 26039 | 26040 | const std::string operation_name = current_token().value; 26041 | const token_t diagnostic_token = current_token(); 26042 | 26043 | map_range_t itr_range = base_ops_map_.equal_range(operation_name); 26044 | 26045 | if (0 == std::distance(itr_range.first,itr_range.second)) 26046 | { 26047 | set_error(make_error( 26048 | parser_error::e_syntax, 26049 | diagnostic_token, 26050 | "ERR033 - No entry found for base operation: " + operation_name, 26051 | exprtk_error_location)); 26052 | 26053 | return error_node(); 26054 | } 26055 | 26056 | static const std::size_t MaxNumberofParameters = 4; 26057 | expression_node_ptr param_list[MaxNumberofParameters] = {0}; 26058 | 26059 | const std::size_t parameter_count = parse_base_function_call(param_list, operation_name); 26060 | 26061 | if ((parameter_count > 0) && (parameter_count <= MaxNumberofParameters)) 26062 | { 26063 | for (base_ops_map_t::iterator itr = itr_range.first; itr != itr_range.second; ++itr) 26064 | { 26065 | const details::base_operation_t& operation = itr->second; 26066 | 26067 | if (operation.num_params == parameter_count) 26068 | { 26069 | switch (parameter_count) 26070 | { 26071 | #define base_opr_case(N) \ 26072 | case N : { \ 26073 | expression_node_ptr pl##N[N] = {0}; \ 26074 | std::copy(param_list, param_list + N, pl##N); \ 26075 | lodge_symbol(operation_name, e_st_function); \ 26076 | return expression_generator_(operation.type, pl##N); \ 26077 | } \ 26078 | 26079 | base_opr_case(1) 26080 | base_opr_case(2) 26081 | base_opr_case(3) 26082 | base_opr_case(4) 26083 | #undef base_opr_case 26084 | } 26085 | } 26086 | } 26087 | } 26088 | 26089 | for (std::size_t i = 0; i < MaxNumberofParameters; ++i) 26090 | { 26091 | free_node(node_allocator_, param_list[i]); 26092 | } 26093 | 26094 | set_error(make_error( 26095 | parser_error::e_syntax, 26096 | diagnostic_token, 26097 | "ERR034 - Invalid number of input parameters for call to function: '" + operation_name + "'", 26098 | exprtk_error_location)); 26099 | 26100 | return error_node(); 26101 | } 26102 | 26103 | inline expression_node_ptr parse_conditional_statement_01(expression_node_ptr condition) 26104 | { 26105 | // Parse: [if][(][condition][,][consequent][,][alternative][)] 26106 | 26107 | expression_node_ptr consequent = error_node(); 26108 | expression_node_ptr alternative = error_node(); 26109 | 26110 | bool result = true; 26111 | 26112 | if (!token_is(token_t::e_comma)) 26113 | { 26114 | set_error(make_error( 26115 | parser_error::e_syntax, 26116 | current_token(), 26117 | "ERR035 - Expected ',' between if-statement condition and consequent", 26118 | exprtk_error_location)); 26119 | 26120 | result = false; 26121 | } 26122 | else if (0 == (consequent = parse_expression())) 26123 | { 26124 | set_error(make_error( 26125 | parser_error::e_syntax, 26126 | current_token(), 26127 | "ERR036 - Failed to parse consequent for if-statement", 26128 | exprtk_error_location)); 26129 | 26130 | result = false; 26131 | } 26132 | else if (!token_is(token_t::e_comma)) 26133 | { 26134 | set_error(make_error( 26135 | parser_error::e_syntax, 26136 | current_token(), 26137 | "ERR037 - Expected ',' between if-statement consequent and alternative", 26138 | exprtk_error_location)); 26139 | 26140 | result = false; 26141 | } 26142 | else if (0 == (alternative = parse_expression())) 26143 | { 26144 | set_error(make_error( 26145 | parser_error::e_syntax, 26146 | current_token(), 26147 | "ERR038 - Failed to parse alternative for if-statement", 26148 | exprtk_error_location)); 26149 | 26150 | result = false; 26151 | } 26152 | else if (!token_is(token_t::e_rbracket)) 26153 | { 26154 | set_error(make_error( 26155 | parser_error::e_syntax, 26156 | current_token(), 26157 | "ERR039 - Expected ')' at the end of if-statement", 26158 | exprtk_error_location)); 26159 | 26160 | result = false; 26161 | } 26162 | 26163 | #ifndef exprtk_disable_string_capabilities 26164 | if (result) 26165 | { 26166 | const bool consq_is_str = is_generally_string_node(consequent ); 26167 | const bool alter_is_str = is_generally_string_node(alternative); 26168 | 26169 | if (consq_is_str || alter_is_str) 26170 | { 26171 | if (consq_is_str && alter_is_str) 26172 | { 26173 | expression_node_ptr result_node = 26174 | expression_generator_ 26175 | .conditional_string(condition, consequent, alternative); 26176 | 26177 | if (result_node && result_node->valid()) 26178 | { 26179 | return result_node; 26180 | } 26181 | 26182 | set_error(make_error( 26183 | parser_error::e_synthesis, 26184 | current_token(), 26185 | "ERR040 - Failed to synthesize node: conditional_string", 26186 | exprtk_error_location)); 26187 | 26188 | free_node(node_allocator_, result_node); 26189 | return error_node(); 26190 | } 26191 | 26192 | set_error(make_error( 26193 | parser_error::e_syntax, 26194 | current_token(), 26195 | "ERR041 - Return types of if-statement differ: string/non-string", 26196 | exprtk_error_location)); 26197 | 26198 | result = false; 26199 | } 26200 | } 26201 | #endif 26202 | 26203 | if (result) 26204 | { 26205 | const bool consq_is_vec = is_ivector_node(consequent ); 26206 | const bool alter_is_vec = is_ivector_node(alternative); 26207 | 26208 | if (consq_is_vec || alter_is_vec) 26209 | { 26210 | if (consq_is_vec && alter_is_vec) 26211 | { 26212 | return expression_generator_ 26213 | .conditional_vector(condition, consequent, alternative); 26214 | } 26215 | 26216 | set_error(make_error( 26217 | parser_error::e_syntax, 26218 | current_token(), 26219 | "ERR042 - Return types of if-statement differ: vector/non-vector", 26220 | exprtk_error_location)); 26221 | 26222 | result = false; 26223 | } 26224 | } 26225 | 26226 | if (!result) 26227 | { 26228 | free_node(node_allocator_, condition ); 26229 | free_node(node_allocator_, consequent ); 26230 | free_node(node_allocator_, alternative); 26231 | 26232 | return error_node(); 26233 | } 26234 | else 26235 | return expression_generator_ 26236 | .conditional(condition, consequent, alternative); 26237 | } 26238 | 26239 | inline expression_node_ptr parse_conditional_statement_02(expression_node_ptr condition) 26240 | { 26241 | expression_node_ptr consequent = error_node(); 26242 | expression_node_ptr alternative = error_node(); 26243 | 26244 | bool result = true; 26245 | 26246 | if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) 26247 | { 26248 | if (0 == (consequent = parse_multi_sequence("if-statement-01"))) 26249 | { 26250 | set_error(make_error( 26251 | parser_error::e_syntax, 26252 | current_token(), 26253 | "ERR043 - Failed to parse body of consequent for if-statement", 26254 | exprtk_error_location)); 26255 | 26256 | result = false; 26257 | } 26258 | else if 26259 | ( 26260 | !settings_.commutative_check_enabled() && 26261 | !token_is("else",prsrhlpr_t::e_hold) && 26262 | !token_is_loop(prsrhlpr_t::e_hold) && 26263 | !token_is_arithmetic_opr(prsrhlpr_t::e_hold) && 26264 | !token_is_right_bracket (prsrhlpr_t::e_hold) && 26265 | !token_is_ineq_opr (prsrhlpr_t::e_hold) && 26266 | !token_is(token_t::e_ternary,prsrhlpr_t::e_hold) && 26267 | !token_is(token_t::e_eof ,prsrhlpr_t::e_hold) 26268 | ) 26269 | { 26270 | set_error(make_error( 26271 | parser_error::e_syntax, 26272 | current_token(), 26273 | "ERR044 - Expected ';' at the end of the consequent for if-statement (1)", 26274 | exprtk_error_location)); 26275 | 26276 | result = false; 26277 | } 26278 | } 26279 | else 26280 | { 26281 | if ( 26282 | settings_.commutative_check_enabled() && 26283 | token_is(token_t::e_mul,prsrhlpr_t::e_hold) 26284 | ) 26285 | { 26286 | next_token(); 26287 | } 26288 | 26289 | if (0 != (consequent = parse_expression())) 26290 | { 26291 | if (!token_is(token_t::e_eof, prsrhlpr_t::e_hold)) 26292 | { 26293 | set_error(make_error( 26294 | parser_error::e_syntax, 26295 | current_token(), 26296 | "ERR045 - Expected ';' at the end of the consequent for if-statement (2)", 26297 | exprtk_error_location)); 26298 | 26299 | result = false; 26300 | } 26301 | } 26302 | else 26303 | { 26304 | set_error(make_error( 26305 | parser_error::e_syntax, 26306 | current_token(), 26307 | "ERR046 - Failed to parse body of consequent for if-statement", 26308 | exprtk_error_location)); 26309 | 26310 | result = false; 26311 | } 26312 | } 26313 | 26314 | if (result) 26315 | { 26316 | if ( 26317 | details::imatch(current_token().value,"else") || 26318 | (token_is(token_t::e_eof, prsrhlpr_t::e_hold) && peek_token_is("else")) 26319 | ) 26320 | { 26321 | next_token(); 26322 | 26323 | if (details::imatch(current_token().value,"else")) 26324 | { 26325 | next_token(); 26326 | } 26327 | 26328 | if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) 26329 | { 26330 | if (0 == (alternative = parse_multi_sequence("else-statement-01"))) 26331 | { 26332 | set_error(make_error( 26333 | parser_error::e_syntax, 26334 | current_token(), 26335 | "ERR047 - Failed to parse body of the 'else' for if-statement", 26336 | exprtk_error_location)); 26337 | 26338 | result = false; 26339 | } 26340 | } 26341 | else if (details::imatch(current_token().value,"if")) 26342 | { 26343 | if (0 == (alternative = parse_conditional_statement())) 26344 | { 26345 | set_error(make_error( 26346 | parser_error::e_syntax, 26347 | current_token(), 26348 | "ERR048 - Failed to parse body of if-else statement", 26349 | exprtk_error_location)); 26350 | 26351 | result = false; 26352 | } 26353 | } 26354 | else if (0 != (alternative = parse_expression())) 26355 | { 26356 | if ( 26357 | !token_is(token_t::e_ternary , prsrhlpr_t::e_hold) && 26358 | !token_is(token_t::e_rcrlbracket, prsrhlpr_t::e_hold) && 26359 | !token_is(token_t::e_eof) 26360 | ) 26361 | { 26362 | set_error(make_error( 26363 | parser_error::e_syntax, 26364 | current_token(), 26365 | "ERR049 - Expected ';' at the end of the 'else-if' for the if-statement", 26366 | exprtk_error_location)); 26367 | 26368 | result = false; 26369 | } 26370 | } 26371 | else 26372 | { 26373 | set_error(make_error( 26374 | parser_error::e_syntax, 26375 | current_token(), 26376 | "ERR050 - Failed to parse body of the 'else' for if-statement", 26377 | exprtk_error_location)); 26378 | 26379 | result = false; 26380 | } 26381 | } 26382 | } 26383 | 26384 | #ifndef exprtk_disable_string_capabilities 26385 | if (result) 26386 | { 26387 | const bool consq_is_str = is_generally_string_node(consequent ); 26388 | const bool alter_is_str = is_generally_string_node(alternative); 26389 | 26390 | if (consq_is_str || alter_is_str) 26391 | { 26392 | if (consq_is_str && alter_is_str) 26393 | { 26394 | return expression_generator_ 26395 | .conditional_string(condition, consequent, alternative); 26396 | } 26397 | 26398 | set_error(make_error( 26399 | parser_error::e_syntax, 26400 | current_token(), 26401 | "ERR051 - Return types of if-statement differ: string/non-string", 26402 | exprtk_error_location)); 26403 | 26404 | result = false; 26405 | } 26406 | } 26407 | #endif 26408 | 26409 | if (result) 26410 | { 26411 | const bool consq_is_vec = is_ivector_node(consequent ); 26412 | const bool alter_is_vec = is_ivector_node(alternative); 26413 | 26414 | if (consq_is_vec || alter_is_vec) 26415 | { 26416 | if (consq_is_vec && alter_is_vec) 26417 | { 26418 | return expression_generator_ 26419 | .conditional_vector(condition, consequent, alternative); 26420 | } 26421 | 26422 | set_error(make_error( 26423 | parser_error::e_syntax, 26424 | current_token(), 26425 | "ERR052 - Return types of if-statement differ: vector/non-vector", 26426 | exprtk_error_location)); 26427 | 26428 | result = false; 26429 | } 26430 | } 26431 | 26432 | if (!result) 26433 | { 26434 | free_node(node_allocator_, condition ); 26435 | free_node(node_allocator_, consequent ); 26436 | free_node(node_allocator_, alternative); 26437 | 26438 | return error_node(); 26439 | } 26440 | else 26441 | return expression_generator_ 26442 | .conditional(condition, consequent, alternative); 26443 | } 26444 | 26445 | inline expression_node_ptr parse_conditional_statement() 26446 | { 26447 | expression_node_ptr condition = error_node(); 26448 | 26449 | next_token(); 26450 | 26451 | if (!token_is(token_t::e_lbracket)) 26452 | { 26453 | set_error(make_error( 26454 | parser_error::e_syntax, 26455 | current_token(), 26456 | "ERR053 - Expected '(' at start of if-statement, instead got: '" + current_token().value + "'", 26457 | exprtk_error_location)); 26458 | 26459 | return error_node(); 26460 | } 26461 | else if (0 == (condition = parse_expression())) 26462 | { 26463 | set_error(make_error( 26464 | parser_error::e_syntax, 26465 | current_token(), 26466 | "ERR054 - Failed to parse condition for if-statement", 26467 | exprtk_error_location)); 26468 | 26469 | return error_node(); 26470 | } 26471 | else if (token_is(token_t::e_comma,prsrhlpr_t::e_hold)) 26472 | { 26473 | // if (x,y,z) 26474 | return parse_conditional_statement_01(condition); 26475 | } 26476 | else if (token_is(token_t::e_rbracket)) 26477 | { 26478 | /* 26479 | 00. if (x) y; 26480 | 01. if (x) y; else z; 26481 | 02. if (x) y; else {z0; ... zn;} 26482 | 03. if (x) y; else if (z) w; 26483 | 04. if (x) y; else if (z) w; else u; 26484 | 05. if (x) y; else if (z) w; else {u0; ... un;} 26485 | 06. if (x) y; else if (z) {w0; ... wn;} 26486 | 07. if (x) {y0; ... yn;} 26487 | 08. if (x) {y0; ... yn;} else z; 26488 | 09. if (x) {y0; ... yn;} else {z0; ... zn;}; 26489 | 10. if (x) {y0; ... yn;} else if (z) w; 26490 | 11. if (x) {y0; ... yn;} else if (z) w; else u; 26491 | 12. if (x) {y0; ... nex;} else if (z) w; else {u0 ... un;} 26492 | 13. if (x) {y0; ... yn;} else if (z) {w0; ... wn;} 26493 | */ 26494 | return parse_conditional_statement_02(condition); 26495 | } 26496 | 26497 | set_error(make_error( 26498 | parser_error::e_syntax, 26499 | current_token(), 26500 | "ERR055 - Invalid if-statement", 26501 | exprtk_error_location)); 26502 | 26503 | free_node(node_allocator_, condition); 26504 | 26505 | return error_node(); 26506 | } 26507 | 26508 | inline expression_node_ptr parse_ternary_conditional_statement(expression_node_ptr condition) 26509 | { 26510 | // Parse: [condition][?][consequent][:][alternative] 26511 | expression_node_ptr consequent = error_node(); 26512 | expression_node_ptr alternative = error_node(); 26513 | 26514 | bool result = true; 26515 | 26516 | if (0 == condition) 26517 | { 26518 | set_error(make_error( 26519 | parser_error::e_syntax, 26520 | current_token(), 26521 | "ERR056 - Encountered invalid condition branch for ternary if-statement", 26522 | exprtk_error_location)); 26523 | 26524 | return error_node(); 26525 | } 26526 | else if (!token_is(token_t::e_ternary)) 26527 | { 26528 | set_error(make_error( 26529 | parser_error::e_syntax, 26530 | current_token(), 26531 | "ERR057 - Expected '?' after condition of ternary if-statement", 26532 | exprtk_error_location)); 26533 | 26534 | result = false; 26535 | } 26536 | else if (0 == (consequent = parse_expression())) 26537 | { 26538 | set_error(make_error( 26539 | parser_error::e_syntax, 26540 | current_token(), 26541 | "ERR058 - Failed to parse consequent for ternary if-statement", 26542 | exprtk_error_location)); 26543 | 26544 | result = false; 26545 | } 26546 | else if (!token_is(token_t::e_colon)) 26547 | { 26548 | set_error(make_error( 26549 | parser_error::e_syntax, 26550 | current_token(), 26551 | "ERR059 - Expected ':' between ternary if-statement consequent and alternative", 26552 | exprtk_error_location)); 26553 | 26554 | result = false; 26555 | } 26556 | else if (0 == (alternative = parse_expression())) 26557 | { 26558 | set_error(make_error( 26559 | parser_error::e_syntax, 26560 | current_token(), 26561 | "ERR060 - Failed to parse alternative for ternary if-statement", 26562 | exprtk_error_location)); 26563 | 26564 | result = false; 26565 | } 26566 | 26567 | #ifndef exprtk_disable_string_capabilities 26568 | if (result) 26569 | { 26570 | const bool consq_is_str = is_generally_string_node(consequent ); 26571 | const bool alter_is_str = is_generally_string_node(alternative); 26572 | 26573 | if (consq_is_str || alter_is_str) 26574 | { 26575 | if (consq_is_str && alter_is_str) 26576 | { 26577 | return expression_generator_ 26578 | .conditional_string(condition, consequent, alternative); 26579 | } 26580 | 26581 | set_error(make_error( 26582 | parser_error::e_syntax, 26583 | current_token(), 26584 | "ERR061 - Return types of ternary differ: string/non-string", 26585 | exprtk_error_location)); 26586 | 26587 | result = false; 26588 | } 26589 | } 26590 | #endif 26591 | 26592 | if (result) 26593 | { 26594 | const bool consq_is_vec = is_ivector_node(consequent ); 26595 | const bool alter_is_vec = is_ivector_node(alternative); 26596 | 26597 | if (consq_is_vec || alter_is_vec) 26598 | { 26599 | if (consq_is_vec && alter_is_vec) 26600 | { 26601 | return expression_generator_ 26602 | .conditional_vector(condition, consequent, alternative); 26603 | } 26604 | 26605 | set_error(make_error( 26606 | parser_error::e_syntax, 26607 | current_token(), 26608 | "ERR062 - Return types of ternary differ: vector/non-vector", 26609 | exprtk_error_location)); 26610 | 26611 | result = false; 26612 | } 26613 | } 26614 | 26615 | if (!result) 26616 | { 26617 | free_node(node_allocator_, condition ); 26618 | free_node(node_allocator_, consequent ); 26619 | free_node(node_allocator_, alternative); 26620 | 26621 | return error_node(); 26622 | } 26623 | else 26624 | return expression_generator_ 26625 | .conditional(condition, consequent, alternative); 26626 | } 26627 | 26628 | inline expression_node_ptr parse_not_statement() 26629 | { 26630 | if (settings_.logic_disabled("not")) 26631 | { 26632 | set_error(make_error( 26633 | parser_error::e_syntax, 26634 | current_token(), 26635 | "ERR063 - Invalid or disabled logic operation 'not'", 26636 | exprtk_error_location)); 26637 | 26638 | return error_node(); 26639 | } 26640 | 26641 | return parse_base_operation(); 26642 | } 26643 | 26644 | void handle_brkcnt_scope_exit() 26645 | { 26646 | assert(!brkcnt_list_.empty()); 26647 | brkcnt_list_.pop_front(); 26648 | } 26649 | 26650 | inline expression_node_ptr parse_while_loop() 26651 | { 26652 | // Parse: [while][(][test expr][)][{][expression][}] 26653 | expression_node_ptr condition = error_node(); 26654 | expression_node_ptr branch = error_node(); 26655 | expression_node_ptr result_node = error_node(); 26656 | 26657 | bool result = true; 26658 | 26659 | next_token(); 26660 | 26661 | if (!token_is(token_t::e_lbracket)) 26662 | { 26663 | set_error(make_error( 26664 | parser_error::e_syntax, 26665 | current_token(), 26666 | "ERR064 - Expected '(' at start of while-loop condition statement", 26667 | exprtk_error_location)); 26668 | 26669 | return error_node(); 26670 | } 26671 | else if (0 == (condition = parse_expression())) 26672 | { 26673 | set_error(make_error( 26674 | parser_error::e_syntax, 26675 | current_token(), 26676 | "ERR065 - Failed to parse condition for while-loop", 26677 | exprtk_error_location)); 26678 | 26679 | return error_node(); 26680 | } 26681 | else if (!token_is(token_t::e_rbracket)) 26682 | { 26683 | set_error(make_error( 26684 | parser_error::e_syntax, 26685 | current_token(), 26686 | "ERR066 - Expected ')' at end of while-loop condition statement", 26687 | exprtk_error_location)); 26688 | 26689 | result = false; 26690 | } 26691 | 26692 | brkcnt_list_.push_front(false); 26693 | 26694 | if (result) 26695 | { 26696 | scoped_inc_dec sid(state_.parsing_loop_stmt_count); 26697 | 26698 | if (0 == (branch = parse_multi_sequence("while-loop", true))) 26699 | { 26700 | set_error(make_error( 26701 | parser_error::e_syntax, 26702 | current_token(), 26703 | "ERR067 - Failed to parse body of while-loop")); 26704 | result = false; 26705 | } 26706 | else if (0 == (result_node = expression_generator_.while_loop(condition, 26707 | branch, 26708 | brkcnt_list_.front()))) 26709 | { 26710 | set_error(make_error( 26711 | parser_error::e_syntax, 26712 | current_token(), 26713 | "ERR068 - Failed to synthesize while-loop", 26714 | exprtk_error_location)); 26715 | 26716 | result = false; 26717 | } 26718 | } 26719 | 26720 | handle_brkcnt_scope_exit(); 26721 | 26722 | if (!result) 26723 | { 26724 | free_node(node_allocator_, branch ); 26725 | free_node(node_allocator_, condition ); 26726 | free_node(node_allocator_, result_node); 26727 | 26728 | return error_node(); 26729 | } 26730 | 26731 | if (result_node && result_node->valid()) 26732 | { 26733 | return result_node; 26734 | } 26735 | 26736 | set_error(make_error( 26737 | parser_error::e_synthesis, 26738 | current_token(), 26739 | "ERR069 - Failed to synthesize 'valid' while-loop", 26740 | exprtk_error_location)); 26741 | 26742 | free_node(node_allocator_, result_node); 26743 | 26744 | return error_node(); 26745 | } 26746 | 26747 | inline expression_node_ptr parse_repeat_until_loop() 26748 | { 26749 | // Parse: [repeat][{][expression][}][until][(][test expr][)] 26750 | expression_node_ptr condition = error_node(); 26751 | expression_node_ptr branch = error_node(); 26752 | next_token(); 26753 | 26754 | std::vector<expression_node_ptr> arg_list; 26755 | std::vector<bool> side_effect_list; 26756 | 26757 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 26758 | 26759 | brkcnt_list_.push_front(false); 26760 | 26761 | if (details::imatch(current_token().value,"until")) 26762 | { 26763 | next_token(); 26764 | branch = node_allocator_.allocate<details::null_node<T> >(); 26765 | } 26766 | else 26767 | { 26768 | const token_t::token_type separator = token_t::e_eof; 26769 | 26770 | scope_handler sh(*this); 26771 | 26772 | scoped_bool_or_restorer sbr(state_.side_effect_present); 26773 | 26774 | scoped_inc_dec sid(state_.parsing_loop_stmt_count); 26775 | 26776 | for ( ; ; ) 26777 | { 26778 | state_.side_effect_present = false; 26779 | 26780 | expression_node_ptr arg = parse_expression(); 26781 | 26782 | if (0 == arg) 26783 | return error_node(); 26784 | else 26785 | { 26786 | arg_list.push_back(arg); 26787 | side_effect_list.push_back(state_.side_effect_present); 26788 | } 26789 | 26790 | if (details::imatch(current_token().value,"until")) 26791 | { 26792 | next_token(); 26793 | break; 26794 | } 26795 | 26796 | const bool is_next_until = peek_token_is(token_t::e_symbol) && 26797 | peek_token_is("until"); 26798 | 26799 | if (!token_is(separator) && is_next_until) 26800 | { 26801 | set_error(make_error( 26802 | parser_error::e_syntax, 26803 | current_token(), 26804 | "ERR070 - Expected '" + token_t::to_str(separator) + "' in body of repeat until loop", 26805 | exprtk_error_location)); 26806 | 26807 | return error_node(); 26808 | } 26809 | 26810 | if (details::imatch(current_token().value,"until")) 26811 | { 26812 | next_token(); 26813 | break; 26814 | } 26815 | } 26816 | 26817 | branch = simplify(arg_list,side_effect_list); 26818 | 26819 | svd.delete_ptr = (0 == branch); 26820 | 26821 | if (svd.delete_ptr) 26822 | { 26823 | set_error(make_error( 26824 | parser_error::e_syntax, 26825 | current_token(), 26826 | "ERR071 - Failed to parse body of repeat until loop", 26827 | exprtk_error_location)); 26828 | 26829 | return error_node(); 26830 | } 26831 | } 26832 | 26833 | if (!token_is(token_t::e_lbracket)) 26834 | { 26835 | set_error(make_error( 26836 | parser_error::e_syntax, 26837 | current_token(), 26838 | "ERR072 - Expected '(' before condition statement of repeat until loop", 26839 | exprtk_error_location)); 26840 | 26841 | free_node(node_allocator_, branch); 26842 | return error_node(); 26843 | } 26844 | else if (0 == (condition = parse_expression())) 26845 | { 26846 | set_error(make_error( 26847 | parser_error::e_syntax, 26848 | current_token(), 26849 | "ERR073 - Failed to parse condition for repeat until loop", 26850 | exprtk_error_location)); 26851 | 26852 | free_node(node_allocator_, branch); 26853 | return error_node(); 26854 | } 26855 | else if (!token_is(token_t::e_rbracket)) 26856 | { 26857 | set_error(make_error( 26858 | parser_error::e_syntax, 26859 | current_token(), 26860 | "ERR074 - Expected ')' after condition of repeat until loop", 26861 | exprtk_error_location)); 26862 | 26863 | free_node(node_allocator_, branch ); 26864 | free_node(node_allocator_, condition); 26865 | 26866 | return error_node(); 26867 | } 26868 | 26869 | expression_node_ptr result_node = 26870 | expression_generator_ 26871 | .repeat_until_loop( 26872 | condition, 26873 | branch, 26874 | brkcnt_list_.front()); 26875 | 26876 | if (0 == result_node) 26877 | { 26878 | set_error(make_error( 26879 | parser_error::e_syntax, 26880 | current_token(), 26881 | "ERR075 - Failed to synthesize repeat until loop", 26882 | exprtk_error_location)); 26883 | 26884 | free_node(node_allocator_, condition); 26885 | 26886 | return error_node(); 26887 | } 26888 | 26889 | handle_brkcnt_scope_exit(); 26890 | 26891 | if (result_node && result_node->valid()) 26892 | { 26893 | return result_node; 26894 | } 26895 | 26896 | set_error(make_error( 26897 | parser_error::e_synthesis, 26898 | current_token(), 26899 | "ERR076 - Failed to synthesize 'valid' repeat until loop", 26900 | exprtk_error_location)); 26901 | 26902 | free_node(node_allocator_, result_node); 26903 | 26904 | return error_node(); 26905 | } 26906 | 26907 | inline expression_node_ptr parse_for_loop() 26908 | { 26909 | expression_node_ptr initialiser = error_node(); 26910 | expression_node_ptr condition = error_node(); 26911 | expression_node_ptr incrementor = error_node(); 26912 | expression_node_ptr loop_body = error_node(); 26913 | 26914 | scope_element* se = 0; 26915 | bool result = true; 26916 | 26917 | next_token(); 26918 | 26919 | scope_handler sh(*this); 26920 | 26921 | if (!token_is(token_t::e_lbracket)) 26922 | { 26923 | set_error(make_error( 26924 | parser_error::e_syntax, 26925 | current_token(), 26926 | "ERR077 - Expected '(' at start of for-loop", 26927 | exprtk_error_location)); 26928 | 26929 | return error_node(); 26930 | } 26931 | 26932 | if (!token_is(token_t::e_eof)) 26933 | { 26934 | if ( 26935 | !token_is(token_t::e_symbol,prsrhlpr_t::e_hold) && 26936 | details::imatch(current_token().value,"var") 26937 | ) 26938 | { 26939 | next_token(); 26940 | 26941 | if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold)) 26942 | { 26943 | set_error(make_error( 26944 | parser_error::e_syntax, 26945 | current_token(), 26946 | "ERR078 - Expected a variable at the start of initialiser section of for-loop", 26947 | exprtk_error_location)); 26948 | 26949 | return error_node(); 26950 | } 26951 | else if (!peek_token_is(token_t::e_assign)) 26952 | { 26953 | set_error(make_error( 26954 | parser_error::e_syntax, 26955 | current_token(), 26956 | "ERR079 - Expected variable assignment of initialiser section of for-loop", 26957 | exprtk_error_location)); 26958 | 26959 | return error_node(); 26960 | } 26961 | 26962 | const std::string loop_counter_symbol = current_token().value; 26963 | 26964 | se = &sem_.get_element(loop_counter_symbol); 26965 | 26966 | if ((se->name == loop_counter_symbol) && se->active) 26967 | { 26968 | set_error(make_error( 26969 | parser_error::e_syntax, 26970 | current_token(), 26971 | "ERR080 - For-loop variable '" + loop_counter_symbol+ "' is being shadowed by a previous declaration", 26972 | exprtk_error_location)); 26973 | 26974 | return error_node(); 26975 | } 26976 | else if (!symtab_store_.is_variable(loop_counter_symbol)) 26977 | { 26978 | if ( 26979 | !se->active && 26980 | (se->name == loop_counter_symbol) && 26981 | (se->type == scope_element::e_variable) 26982 | ) 26983 | { 26984 | se->active = true; 26985 | se->ref_count++; 26986 | } 26987 | else 26988 | { 26989 | scope_element nse; 26990 | nse.name = loop_counter_symbol; 26991 | nse.active = true; 26992 | nse.ref_count = 1; 26993 | nse.type = scope_element::e_variable; 26994 | nse.depth = state_.scope_depth; 26995 | nse.data = new T(T(0)); 26996 | nse.var_node = node_allocator_.allocate<variable_node_t>(*reinterpret_cast<T*>(nse.data)); 26997 | 26998 | if (!sem_.add_element(nse)) 26999 | { 27000 | set_error(make_error( 27001 | parser_error::e_syntax, 27002 | current_token(), 27003 | "ERR081 - Failed to add new local variable '" + loop_counter_symbol + "' to SEM", 27004 | exprtk_error_location)); 27005 | 27006 | sem_.free_element(nse); 27007 | 27008 | result = false; 27009 | } 27010 | else 27011 | { 27012 | exprtk_debug(("parse_for_loop() - INFO - Added new local variable: %s\n", nse.name.c_str())); 27013 | 27014 | state_.activate_side_effect("parse_for_loop()"); 27015 | } 27016 | } 27017 | } 27018 | } 27019 | 27020 | if (0 == (initialiser = parse_expression())) 27021 | { 27022 | set_error(make_error( 27023 | parser_error::e_syntax, 27024 | current_token(), 27025 | "ERR082 - Failed to parse initialiser of for-loop", 27026 | exprtk_error_location)); 27027 | 27028 | result = false; 27029 | } 27030 | else if (!token_is(token_t::e_eof)) 27031 | { 27032 | set_error(make_error( 27033 | parser_error::e_syntax, 27034 | current_token(), 27035 | "ERR083 - Expected ';' after initialiser of for-loop", 27036 | exprtk_error_location)); 27037 | 27038 | result = false; 27039 | } 27040 | } 27041 | 27042 | if (!token_is(token_t::e_eof)) 27043 | { 27044 | if (0 == (condition = parse_expression())) 27045 | { 27046 | set_error(make_error( 27047 | parser_error::e_syntax, 27048 | current_token(), 27049 | "ERR084 - Failed to parse condition of for-loop", 27050 | exprtk_error_location)); 27051 | 27052 | result = false; 27053 | } 27054 | else if (!token_is(token_t::e_eof)) 27055 | { 27056 | set_error(make_error( 27057 | parser_error::e_syntax, 27058 | current_token(), 27059 | "ERR085 - Expected ';' after condition section of for-loop", 27060 | exprtk_error_location)); 27061 | 27062 | result = false; 27063 | } 27064 | } 27065 | 27066 | if (!token_is(token_t::e_rbracket)) 27067 | { 27068 | if (0 == (incrementor = parse_expression())) 27069 | { 27070 | set_error(make_error( 27071 | parser_error::e_syntax, 27072 | current_token(), 27073 | "ERR086 - Failed to parse incrementor of for-loop", 27074 | exprtk_error_location)); 27075 | 27076 | result = false; 27077 | } 27078 | else if (!token_is(token_t::e_rbracket)) 27079 | { 27080 | set_error(make_error( 27081 | parser_error::e_syntax, 27082 | current_token(), 27083 | "ERR087 - Expected ')' after incrementor section of for-loop", 27084 | exprtk_error_location)); 27085 | 27086 | result = false; 27087 | } 27088 | } 27089 | 27090 | if (result) 27091 | { 27092 | brkcnt_list_.push_front(false); 27093 | 27094 | scoped_inc_dec sid(state_.parsing_loop_stmt_count); 27095 | 27096 | if (0 == (loop_body = parse_multi_sequence("for-loop", true))) 27097 | { 27098 | set_error(make_error( 27099 | parser_error::e_syntax, 27100 | current_token(), 27101 | "ERR088 - Failed to parse body of for-loop", 27102 | exprtk_error_location)); 27103 | 27104 | result = false; 27105 | } 27106 | } 27107 | 27108 | if (!result) 27109 | { 27110 | if (se) 27111 | { 27112 | se->ref_count--; 27113 | } 27114 | 27115 | free_node(node_allocator_, initialiser); 27116 | free_node(node_allocator_, condition ); 27117 | free_node(node_allocator_, incrementor); 27118 | free_node(node_allocator_, loop_body ); 27119 | return error_node(); 27120 | } 27121 | 27122 | expression_node_ptr result_node = 27123 | expression_generator_.for_loop(initialiser, 27124 | condition, 27125 | incrementor, 27126 | loop_body, 27127 | brkcnt_list_.front()); 27128 | handle_brkcnt_scope_exit(); 27129 | 27130 | if (result_node && result_node->valid()) 27131 | { 27132 | return result_node; 27133 | } 27134 | 27135 | set_error(make_error( 27136 | parser_error::e_synthesis, 27137 | current_token(), 27138 | "ERR089 - Failed to synthesize 'valid' for-loop", 27139 | exprtk_error_location)); 27140 | 27141 | free_node(node_allocator_, result_node); 27142 | 27143 | return error_node(); 27144 | } 27145 | 27146 | inline expression_node_ptr parse_switch_statement() 27147 | { 27148 | std::vector<expression_node_ptr> arg_list; 27149 | 27150 | if (!details::imatch(current_token().value,"switch")) 27151 | { 27152 | set_error(make_error( 27153 | parser_error::e_syntax, 27154 | current_token(), 27155 | "ERR090 - Expected keyword 'switch'", 27156 | exprtk_error_location)); 27157 | 27158 | return error_node(); 27159 | } 27160 | 27161 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 27162 | 27163 | next_token(); 27164 | 27165 | if (!token_is(token_t::e_lcrlbracket)) 27166 | { 27167 | set_error(make_error( 27168 | parser_error::e_syntax, 27169 | current_token(), 27170 | "ERR091 - Expected '{' for call to switch statement", 27171 | exprtk_error_location)); 27172 | 27173 | return error_node(); 27174 | } 27175 | 27176 | expression_node_ptr default_statement = error_node(); 27177 | 27178 | scoped_expression_delete defstmt_delete((*this), default_statement); 27179 | 27180 | for ( ; ; ) 27181 | { 27182 | if (details::imatch("case",current_token().value)) 27183 | { 27184 | next_token(); 27185 | 27186 | expression_node_ptr condition = parse_expression(); 27187 | 27188 | if (0 == condition) 27189 | return error_node(); 27190 | else if (!token_is(token_t::e_colon)) 27191 | { 27192 | set_error(make_error( 27193 | parser_error::e_syntax, 27194 | current_token(), 27195 | "ERR092 - Expected ':' for case of switch statement", 27196 | exprtk_error_location)); 27197 | 27198 | free_node(node_allocator_, condition); 27199 | 27200 | return error_node(); 27201 | } 27202 | 27203 | expression_node_ptr consequent = 27204 | (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) ? 27205 | parse_multi_sequence("switch-consequent") : 27206 | parse_expression(); 27207 | 27208 | if (0 == consequent) 27209 | { 27210 | free_node(node_allocator_, condition); 27211 | 27212 | return error_node(); 27213 | } 27214 | else if (!token_is(token_t::e_eof)) 27215 | { 27216 | set_error(make_error( 27217 | parser_error::e_syntax, 27218 | current_token(), 27219 | "ERR093 - Expected ';' at end of case for switch statement", 27220 | exprtk_error_location)); 27221 | 27222 | free_node(node_allocator_, condition ); 27223 | free_node(node_allocator_, consequent); 27224 | 27225 | return error_node(); 27226 | } 27227 | 27228 | // Can we optimise away the case statement? 27229 | if (is_constant_node(condition) && is_false(condition)) 27230 | { 27231 | free_node(node_allocator_, condition ); 27232 | free_node(node_allocator_, consequent); 27233 | } 27234 | else 27235 | { 27236 | arg_list.push_back(condition ); 27237 | arg_list.push_back(consequent); 27238 | } 27239 | 27240 | } 27241 | else if (details::imatch("default",current_token().value)) 27242 | { 27243 | if (0 != default_statement) 27244 | { 27245 | set_error(make_error( 27246 | parser_error::e_syntax, 27247 | current_token(), 27248 | "ERR094 - Multiple default cases for switch statement", 27249 | exprtk_error_location)); 27250 | 27251 | return error_node(); 27252 | } 27253 | 27254 | next_token(); 27255 | 27256 | if (!token_is(token_t::e_colon)) 27257 | { 27258 | set_error(make_error( 27259 | parser_error::e_syntax, 27260 | current_token(), 27261 | "ERR095 - Expected ':' for default of switch statement", 27262 | exprtk_error_location)); 27263 | 27264 | return error_node(); 27265 | } 27266 | 27267 | default_statement = 27268 | (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) ? 27269 | parse_multi_sequence("switch-default"): 27270 | parse_expression(); 27271 | 27272 | if (0 == default_statement) 27273 | return error_node(); 27274 | else if (!token_is(token_t::e_eof)) 27275 | { 27276 | set_error(make_error( 27277 | parser_error::e_syntax, 27278 | current_token(), 27279 | "ERR096 - Expected ';' at end of default for switch statement", 27280 | exprtk_error_location)); 27281 | 27282 | return error_node(); 27283 | } 27284 | } 27285 | else if (token_is(token_t::e_rcrlbracket)) 27286 | break; 27287 | else 27288 | { 27289 | set_error(make_error( 27290 | parser_error::e_syntax, 27291 | current_token(), 27292 | "ERR097 - Expected '}' at end of switch statement", 27293 | exprtk_error_location)); 27294 | 27295 | return error_node(); 27296 | } 27297 | } 27298 | 27299 | const bool default_statement_present = (0 != default_statement); 27300 | 27301 | if (default_statement_present) 27302 | { 27303 | arg_list.push_back(default_statement); 27304 | } 27305 | else 27306 | { 27307 | arg_list.push_back(node_allocator_.allocate_c<literal_node_t>(std::numeric_limits<T>::quiet_NaN())); 27308 | } 27309 | 27310 | expression_node_ptr result = expression_generator_.switch_statement(arg_list, (0 != default_statement)); 27311 | 27312 | svd.delete_ptr = (0 == result); 27313 | defstmt_delete.delete_ptr = (0 == result); 27314 | 27315 | return result; 27316 | } 27317 | 27318 | inline expression_node_ptr parse_multi_switch_statement() 27319 | { 27320 | std::vector<expression_node_ptr> arg_list; 27321 | 27322 | if (!details::imatch(current_token().value,"[*]")) 27323 | { 27324 | set_error(make_error( 27325 | parser_error::e_syntax, 27326 | current_token(), 27327 | "ERR098 - Expected token '[*]'", 27328 | exprtk_error_location)); 27329 | 27330 | return error_node(); 27331 | } 27332 | 27333 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 27334 | 27335 | next_token(); 27336 | 27337 | if (!token_is(token_t::e_lcrlbracket)) 27338 | { 27339 | set_error(make_error( 27340 | parser_error::e_syntax, 27341 | current_token(), 27342 | "ERR099 - Expected '{' for call to [*] statement", 27343 | exprtk_error_location)); 27344 | 27345 | return error_node(); 27346 | } 27347 | 27348 | for ( ; ; ) 27349 | { 27350 | if (!details::imatch("case",current_token().value)) 27351 | { 27352 | set_error(make_error( 27353 | parser_error::e_syntax, 27354 | current_token(), 27355 | "ERR100 - Expected a 'case' statement for multi-switch", 27356 | exprtk_error_location)); 27357 | 27358 | return error_node(); 27359 | } 27360 | 27361 | next_token(); 27362 | 27363 | expression_node_ptr condition = parse_expression(); 27364 | 27365 | if (0 == condition) 27366 | return error_node(); 27367 | 27368 | if (!token_is(token_t::e_colon)) 27369 | { 27370 | set_error(make_error( 27371 | parser_error::e_syntax, 27372 | current_token(), 27373 | "ERR101 - Expected ':' for case of [*] statement", 27374 | exprtk_error_location)); 27375 | 27376 | return error_node(); 27377 | } 27378 | 27379 | expression_node_ptr consequent = 27380 | (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) ? 27381 | parse_multi_sequence("multi-switch-consequent") : 27382 | parse_expression(); 27383 | 27384 | if (0 == consequent) 27385 | return error_node(); 27386 | 27387 | if (!token_is(token_t::e_eof)) 27388 | { 27389 | set_error(make_error( 27390 | parser_error::e_syntax, 27391 | current_token(), 27392 | "ERR102 - Expected ';' at end of case for [*] statement", 27393 | exprtk_error_location)); 27394 | 27395 | return error_node(); 27396 | } 27397 | 27398 | // Can we optimise away the case statement? 27399 | if (is_constant_node(condition) && is_false(condition)) 27400 | { 27401 | free_node(node_allocator_, condition ); 27402 | free_node(node_allocator_, consequent); 27403 | } 27404 | else 27405 | { 27406 | arg_list.push_back(condition ); 27407 | arg_list.push_back(consequent); 27408 | } 27409 | 27410 | if (token_is(token_t::e_rcrlbracket,prsrhlpr_t::e_hold)) 27411 | { 27412 | break; 27413 | } 27414 | } 27415 | 27416 | if (!token_is(token_t::e_rcrlbracket)) 27417 | { 27418 | set_error(make_error( 27419 | parser_error::e_syntax, 27420 | current_token(), 27421 | "ERR103 - Expected '}' at end of [*] statement", 27422 | exprtk_error_location)); 27423 | 27424 | return error_node(); 27425 | } 27426 | 27427 | const expression_node_ptr result = expression_generator_.multi_switch_statement(arg_list); 27428 | 27429 | svd.delete_ptr = (0 == result); 27430 | 27431 | return result; 27432 | } 27433 | 27434 | inline expression_node_ptr parse_vararg_function() 27435 | { 27436 | std::vector<expression_node_ptr> arg_list; 27437 | 27438 | details::operator_type opt_type = details::e_default; 27439 | const std::string symbol = current_token().value; 27440 | 27441 | if (details::imatch(symbol,"~")) 27442 | { 27443 | next_token(); 27444 | return check_block_statement_closure(parse_multi_sequence()); 27445 | } 27446 | else if (details::imatch(symbol,"[*]")) 27447 | { 27448 | return check_block_statement_closure(parse_multi_switch_statement()); 27449 | } 27450 | else if (details::imatch(symbol, "avg" )) opt_type = details::e_avg ; 27451 | else if (details::imatch(symbol, "mand")) opt_type = details::e_mand; 27452 | else if (details::imatch(symbol, "max" )) opt_type = details::e_max ; 27453 | else if (details::imatch(symbol, "min" )) opt_type = details::e_min ; 27454 | else if (details::imatch(symbol, "mor" )) opt_type = details::e_mor ; 27455 | else if (details::imatch(symbol, "mul" )) opt_type = details::e_prod; 27456 | else if (details::imatch(symbol, "sum" )) opt_type = details::e_sum ; 27457 | else 27458 | { 27459 | set_error(make_error( 27460 | parser_error::e_syntax, 27461 | current_token(), 27462 | "ERR104 - Unsupported built-in vararg function: " + symbol, 27463 | exprtk_error_location)); 27464 | 27465 | return error_node(); 27466 | } 27467 | 27468 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 27469 | 27470 | lodge_symbol(symbol, e_st_function); 27471 | 27472 | next_token(); 27473 | 27474 | if (!token_is(token_t::e_lbracket)) 27475 | { 27476 | set_error(make_error( 27477 | parser_error::e_syntax, 27478 | current_token(), 27479 | "ERR105 - Expected '(' for call to vararg function: " + symbol, 27480 | exprtk_error_location)); 27481 | 27482 | return error_node(); 27483 | } 27484 | 27485 | if (token_is(token_t::e_rbracket)) 27486 | { 27487 | set_error(make_error( 27488 | parser_error::e_syntax, 27489 | current_token(), 27490 | "ERR106 - vararg function: " + symbol + 27491 | " requires at least one input parameter", 27492 | exprtk_error_location)); 27493 | 27494 | return error_node(); 27495 | } 27496 | 27497 | for ( ; ; ) 27498 | { 27499 | expression_node_ptr arg = parse_expression(); 27500 | 27501 | if (0 == arg) 27502 | return error_node(); 27503 | else 27504 | arg_list.push_back(arg); 27505 | 27506 | if (token_is(token_t::e_rbracket)) 27507 | break; 27508 | else if (!token_is(token_t::e_comma)) 27509 | { 27510 | set_error(make_error( 27511 | parser_error::e_syntax, 27512 | current_token(), 27513 | "ERR107 - Expected ',' for call to vararg function: " + symbol, 27514 | exprtk_error_location)); 27515 | 27516 | return error_node(); 27517 | } 27518 | } 27519 | 27520 | const expression_node_ptr result = expression_generator_.vararg_function(opt_type,arg_list); 27521 | 27522 | svd.delete_ptr = (0 == result); 27523 | return result; 27524 | } 27525 | 27526 | #ifndef exprtk_disable_string_capabilities 27527 | inline expression_node_ptr parse_string_range_statement(expression_node_ptr& expression) 27528 | { 27529 | if (!token_is(token_t::e_lsqrbracket)) 27530 | { 27531 | set_error(make_error( 27532 | parser_error::e_syntax, 27533 | current_token(), 27534 | "ERR108 - Expected '[' as start of string range definition", 27535 | exprtk_error_location)); 27536 | 27537 | free_node(node_allocator_, expression); 27538 | 27539 | return error_node(); 27540 | } 27541 | else if (token_is(token_t::e_rsqrbracket)) 27542 | { 27543 | return node_allocator_.allocate<details::string_size_node<T> >(expression); 27544 | } 27545 | 27546 | range_t rp; 27547 | 27548 | if (!parse_range(rp,true)) 27549 | { 27550 | free_node(node_allocator_, expression); 27551 | 27552 | return error_node(); 27553 | } 27554 | 27555 | expression_node_ptr result = expression_generator_(expression,rp); 27556 | 27557 | if (0 == result) 27558 | { 27559 | set_error(make_error( 27560 | parser_error::e_syntax, 27561 | current_token(), 27562 | "ERR109 - Failed to generate string range node", 27563 | exprtk_error_location)); 27564 | 27565 | free_node(node_allocator_, expression); 27566 | rp.free(); 27567 | } 27568 | 27569 | rp.clear(); 27570 | 27571 | if (result && result->valid()) 27572 | { 27573 | return result; 27574 | } 27575 | 27576 | set_error(make_error( 27577 | parser_error::e_synthesis, 27578 | current_token(), 27579 | "ERR110 - Failed to synthesize node: string_range_node", 27580 | exprtk_error_location)); 27581 | 27582 | free_node(node_allocator_, result); 27583 | rp.free(); 27584 | return error_node(); 27585 | } 27586 | #else 27587 | inline expression_node_ptr parse_string_range_statement(expression_node_ptr&) 27588 | { 27589 | return error_node(); 27590 | } 27591 | #endif 27592 | 27593 | inline bool parse_pending_string_rangesize(expression_node_ptr& expression) 27594 | { 27595 | // Allow no more than 100 range calls, eg: s[][][]...[][] 27596 | const std::size_t max_rangesize_parses = 100; 27597 | 27598 | std::size_t i = 0; 27599 | 27600 | while 27601 | ( 27602 | (0 != expression) && 27603 | (i++ < max_rangesize_parses) && 27604 | error_list_.empty() && 27605 | is_generally_string_node(expression) && 27606 | token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold) 27607 | ) 27608 | { 27609 | expression = parse_string_range_statement(expression); 27610 | } 27611 | 27612 | return (i > 1); 27613 | } 27614 | 27615 | inline void parse_pending_vector_index_operator(expression_node_ptr& expression) 27616 | { 27617 | if 27618 | ( 27619 | (0 != expression) && 27620 | error_list_.empty() && 27621 | is_ivector_node(expression) 27622 | ) 27623 | { 27624 | if ( 27625 | settings_.commutative_check_enabled() && 27626 | token_is(token_t::e_mul,prsrhlpr_t::e_hold) && 27627 | peek_token_is(token_t::e_lsqrbracket) 27628 | ) 27629 | { 27630 | token_is(token_t::e_mul); 27631 | token_is(token_t::e_lsqrbracket); 27632 | } 27633 | else if (token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold)) 27634 | { 27635 | token_is(token_t::e_lsqrbracket); 27636 | } 27637 | else if ( 27638 | token_is(token_t::e_rbracket,prsrhlpr_t::e_hold) && 27639 | peek_token_is(token_t::e_lsqrbracket) 27640 | ) 27641 | { 27642 | token_is(token_t::e_rbracket ); 27643 | token_is(token_t::e_lsqrbracket); 27644 | } 27645 | else 27646 | return; 27647 | 27648 | details::vector_interface<T>* vi = dynamic_cast<details::vector_interface<T>*>(expression); 27649 | 27650 | if (vi) 27651 | { 27652 | details::vector_holder<T>& vec = vi->vec()->vec_holder(); 27653 | const std::string vector_name = sem_.get_vector_name(vec.data()); 27654 | expression_node_ptr index = parse_vector_index(vector_name); 27655 | 27656 | if (index) 27657 | { 27658 | expression = synthesize_vector_element(vector_name, &vec, expression, index); 27659 | return; 27660 | } 27661 | } 27662 | 27663 | free_node(node_allocator_, expression); 27664 | expression = error_node(); 27665 | } 27666 | } 27667 | 27668 | template <typename Allocator1, 27669 | typename Allocator2, 27670 | template <typename, typename> class Sequence> 27671 | inline expression_node_ptr simplify(Sequence<expression_node_ptr,Allocator1>& expression_list, 27672 | Sequence<bool,Allocator2>& side_effect_list, 27673 | const bool specialise_on_final_type = false) 27674 | { 27675 | if (expression_list.empty()) 27676 | return error_node(); 27677 | else if (1 == expression_list.size()) 27678 | return expression_list[0]; 27679 | 27680 | Sequence<expression_node_ptr,Allocator1> tmp_expression_list; 27681 | 27682 | exprtk_debug(("simplify() - expression_list.size: %d side_effect_list.size(): %d\n", 27683 | static_cast<int>(expression_list .size()), 27684 | static_cast<int>(side_effect_list.size()))); 27685 | 27686 | bool return_node_present = false; 27687 | 27688 | for (std::size_t i = 0; i < (expression_list.size() - 1); ++i) 27689 | { 27690 | if (is_variable_node(expression_list[i])) 27691 | continue; 27692 | else if ( 27693 | is_return_node (expression_list[i]) || 27694 | is_break_node (expression_list[i]) || 27695 | is_continue_node(expression_list[i]) 27696 | ) 27697 | { 27698 | tmp_expression_list.push_back(expression_list[i]); 27699 | 27700 | // Remove all subexpressions after first short-circuit 27701 | // node has been encountered. 27702 | 27703 | for (std::size_t j = i + 1; j < expression_list.size(); ++j) 27704 | { 27705 | free_node(node_allocator_, expression_list[j]); 27706 | } 27707 | 27708 | return_node_present = true; 27709 | 27710 | break; 27711 | } 27712 | else if ( 27713 | is_constant_node(expression_list[i]) || 27714 | is_null_node (expression_list[i]) || 27715 | !side_effect_list[i] 27716 | ) 27717 | { 27718 | free_node(node_allocator_, expression_list[i]); 27719 | continue; 27720 | } 27721 | else 27722 | tmp_expression_list.push_back(expression_list[i]); 27723 | } 27724 | 27725 | if (!return_node_present) 27726 | { 27727 | tmp_expression_list.push_back(expression_list.back()); 27728 | } 27729 | 27730 | expression_list.swap(tmp_expression_list); 27731 | 27732 | if (tmp_expression_list.size() > expression_list.size()) 27733 | { 27734 | exprtk_debug(("simplify() - Reduced subexpressions from %d to %d\n", 27735 | static_cast<int>(tmp_expression_list.size()), 27736 | static_cast<int>(expression_list .size()))); 27737 | } 27738 | 27739 | if ( 27740 | return_node_present || 27741 | side_effect_list.back() || 27742 | (expression_list.size() > 1) 27743 | ) 27744 | state_.activate_side_effect("simplify()"); 27745 | 27746 | if (1 == expression_list.size()) 27747 | return expression_list[0]; 27748 | else if (specialise_on_final_type && is_generally_string_node(expression_list.back())) 27749 | return expression_generator_.vararg_function(details::e_smulti,expression_list); 27750 | else 27751 | return expression_generator_.vararg_function(details::e_multi,expression_list); 27752 | } 27753 | 27754 | inline expression_node_ptr parse_multi_sequence(const std::string& source = "", 27755 | const bool enforce_crlbrackets = false) 27756 | { 27757 | token_t::token_type open_bracket = token_t::e_lcrlbracket; 27758 | token_t::token_type close_bracket = token_t::e_rcrlbracket; 27759 | token_t::token_type separator = token_t::e_eof; 27760 | 27761 | if (!token_is(open_bracket)) 27762 | { 27763 | if (!enforce_crlbrackets && token_is(token_t::e_lbracket)) 27764 | { 27765 | open_bracket = token_t::e_lbracket; 27766 | close_bracket = token_t::e_rbracket; 27767 | separator = token_t::e_comma; 27768 | } 27769 | else 27770 | { 27771 | set_error(make_error( 27772 | parser_error::e_syntax, 27773 | current_token(), 27774 | "ERR111 - Expected '" + token_t::to_str(open_bracket) + "' for call to multi-sequence" + 27775 | ((!source.empty()) ? std::string(" section of " + source): ""), 27776 | exprtk_error_location)); 27777 | 27778 | return error_node(); 27779 | } 27780 | } 27781 | else if (token_is(close_bracket)) 27782 | { 27783 | return node_allocator_.allocate<details::null_node<T> >(); 27784 | } 27785 | 27786 | std::vector<expression_node_ptr> arg_list; 27787 | std::vector<bool> side_effect_list; 27788 | 27789 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 27790 | 27791 | scope_handler sh(*this); 27792 | 27793 | scoped_bool_or_restorer sbr(state_.side_effect_present); 27794 | 27795 | for ( ; ; ) 27796 | { 27797 | state_.side_effect_present = false; 27798 | 27799 | expression_node_ptr arg = parse_expression(); 27800 | 27801 | if (0 == arg) 27802 | return error_node(); 27803 | else 27804 | { 27805 | arg_list.push_back(arg); 27806 | side_effect_list.push_back(state_.side_effect_present); 27807 | } 27808 | 27809 | if (token_is(close_bracket)) 27810 | break; 27811 | 27812 | const bool is_next_close = peek_token_is(close_bracket); 27813 | 27814 | if (!token_is(separator) && is_next_close) 27815 | { 27816 | set_error(make_error( 27817 | parser_error::e_syntax, 27818 | current_token(), 27819 | "ERR112 - Expected '" + lexer::token::seperator_to_str(separator) + "' for call to multi-sequence section of " + source, 27820 | exprtk_error_location)); 27821 | 27822 | return error_node(); 27823 | } 27824 | 27825 | if (token_is(close_bracket)) 27826 | break; 27827 | } 27828 | 27829 | expression_node_ptr result = simplify(arg_list, side_effect_list, source.empty()); 27830 | 27831 | svd.delete_ptr = (0 == result); 27832 | return result; 27833 | } 27834 | 27835 | inline bool parse_range(range_t& rp, const bool skip_lsqr = false) 27836 | { 27837 | // Examples of valid ranges: 27838 | // 1. [1:5] -> [1,5) 27839 | // 2. [ :5] -> [0,5) 27840 | // 3. [1: ] -> [1,end) 27841 | // 4. [x:y] -> [x,y) where x <= y 27842 | // 5. [x+1:y/2] -> [x+1,y/2) where x+1 <= y/2 27843 | // 6. [ :y] -> [0,y) where 0 <= y 27844 | // 7. [x: ] -> [x,end) where x <= end 27845 | 27846 | rp.clear(); 27847 | 27848 | if (!skip_lsqr && !token_is(token_t::e_lsqrbracket)) 27849 | { 27850 | set_error(make_error( 27851 | parser_error::e_syntax, 27852 | current_token(), 27853 | "ERR113 - Expected '[' for start of range", 27854 | exprtk_error_location)); 27855 | 27856 | return false; 27857 | } 27858 | 27859 | if (token_is(token_t::e_colon)) 27860 | { 27861 | rp.n0_c.first = true; 27862 | rp.n0_c.second = 0; 27863 | rp.cache.first = 0; 27864 | } 27865 | else 27866 | { 27867 | expression_node_ptr r0 = parse_expression(); 27868 | 27869 | if (0 == r0) 27870 | { 27871 | set_error(make_error( 27872 | parser_error::e_syntax, 27873 | current_token(), 27874 | "ERR114 - Failed parse begin section of range", 27875 | exprtk_error_location)); 27876 | 27877 | return false; 27878 | } 27879 | else if (is_constant_node(r0)) 27880 | { 27881 | const T r0_value = r0->value(); 27882 | 27883 | if (r0_value >= T(0)) 27884 | { 27885 | rp.n0_c.first = true; 27886 | rp.n0_c.second = static_cast<std::size_t>(details::numeric::to_int64(r0_value)); 27887 | rp.cache.first = rp.n0_c.second; 27888 | } 27889 | 27890 | free_node(node_allocator_, r0); 27891 | 27892 | if (r0_value < T(0)) 27893 | { 27894 | set_error(make_error( 27895 | parser_error::e_syntax, 27896 | current_token(), 27897 | "ERR115 - Range lower bound less than zero! Constraint: r0 >= 0", 27898 | exprtk_error_location)); 27899 | 27900 | return false; 27901 | } 27902 | } 27903 | else 27904 | { 27905 | rp.n0_e.first = true; 27906 | rp.n0_e.second = r0; 27907 | } 27908 | 27909 | if (!token_is(token_t::e_colon)) 27910 | { 27911 | set_error(make_error( 27912 | parser_error::e_syntax, 27913 | current_token(), 27914 | "ERR116 - Expected ':' for break in range", 27915 | exprtk_error_location)); 27916 | 27917 | rp.free(); 27918 | 27919 | return false; 27920 | } 27921 | } 27922 | 27923 | if (token_is(token_t::e_rsqrbracket)) 27924 | { 27925 | rp.n1_c.first = true; 27926 | rp.n1_c.second = std::numeric_limits<std::size_t>::max(); 27927 | } 27928 | else 27929 | { 27930 | expression_node_ptr r1 = parse_expression(); 27931 | 27932 | if (0 == r1) 27933 | { 27934 | set_error(make_error( 27935 | parser_error::e_syntax, 27936 | current_token(), 27937 | "ERR117 - Failed parse end section of range", 27938 | exprtk_error_location)); 27939 | 27940 | rp.free(); 27941 | 27942 | return false; 27943 | } 27944 | else if (is_constant_node(r1)) 27945 | { 27946 | const T r1_value = r1->value(); 27947 | 27948 | if (r1_value >= T(0)) 27949 | { 27950 | rp.n1_c.first = true; 27951 | rp.n1_c.second = static_cast<std::size_t>(details::numeric::to_int64(r1_value)); 27952 | rp.cache.second = rp.n1_c.second; 27953 | } 27954 | 27955 | free_node(node_allocator_, r1); 27956 | 27957 | if (r1_value < T(0)) 27958 | { 27959 | set_error(make_error( 27960 | parser_error::e_syntax, 27961 | current_token(), 27962 | "ERR118 - Range upper bound less than zero! Constraint: r1 >= 0", 27963 | exprtk_error_location)); 27964 | 27965 | rp.free(); 27966 | 27967 | return false; 27968 | } 27969 | } 27970 | else 27971 | { 27972 | rp.n1_e.first = true; 27973 | rp.n1_e.second = r1; 27974 | } 27975 | 27976 | if (!token_is(token_t::e_rsqrbracket)) 27977 | { 27978 | set_error(make_error( 27979 | parser_error::e_syntax, 27980 | current_token(), 27981 | "ERR119 - Expected ']' for start of range", 27982 | exprtk_error_location)); 27983 | 27984 | rp.free(); 27985 | 27986 | return false; 27987 | } 27988 | } 27989 | 27990 | if (rp.const_range()) 27991 | { 27992 | std::size_t r0 = 0; 27993 | std::size_t r1 = 0; 27994 | 27995 | bool rp_result = false; 27996 | 27997 | try 27998 | { 27999 | rp_result = rp(r0, r1); 28000 | } 28001 | catch (std::runtime_error&) 28002 | {} 28003 | 28004 | if (!rp_result || (r0 > r1)) 28005 | { 28006 | set_error(make_error( 28007 | parser_error::e_syntax, 28008 | current_token(), 28009 | "ERR120 - Invalid range, Constraint: r0 <= r1", 28010 | exprtk_error_location)); 28011 | 28012 | return false; 28013 | } 28014 | } 28015 | 28016 | return true; 28017 | } 28018 | 28019 | inline void lodge_symbol(const std::string& symbol, 28020 | const symbol_type st) 28021 | { 28022 | dec_.add_symbol(symbol,st); 28023 | } 28024 | 28025 | #ifndef exprtk_disable_string_capabilities 28026 | inline expression_node_ptr parse_string() 28027 | { 28028 | const std::string symbol = current_token().value; 28029 | 28030 | typedef details::stringvar_node<T>* strvar_node_t; 28031 | 28032 | expression_node_ptr result = error_node(); 28033 | strvar_node_t const_str_node = static_cast<strvar_node_t>(0); 28034 | 28035 | scope_element& se = sem_.get_active_element(symbol); 28036 | 28037 | if (scope_element::e_string == se.type) 28038 | { 28039 | se.active = true; 28040 | result = se.str_node; 28041 | lodge_symbol(symbol, e_st_local_string); 28042 | } 28043 | else 28044 | { 28045 | typedef typename symtab_store::string_context str_ctxt_t; 28046 | str_ctxt_t str_ctx = symtab_store_.get_string_context(symbol); 28047 | 28048 | if ((0 == str_ctx.str_var) || !symtab_store_.is_conststr_stringvar(symbol)) 28049 | { 28050 | set_error(make_error( 28051 | parser_error::e_syntax, 28052 | current_token(), 28053 | "ERR121 - Unknown string symbol", 28054 | exprtk_error_location)); 28055 | 28056 | return error_node(); 28057 | } 28058 | 28059 | assert(str_ctx.str_var != 0); 28060 | assert(str_ctx.symbol_table != 0); 28061 | 28062 | result = str_ctx.str_var; 28063 | 28064 | if (symtab_store_.is_constant_string(symbol)) 28065 | { 28066 | const_str_node = static_cast<strvar_node_t>(result); 28067 | result = expression_generator_(const_str_node->str()); 28068 | } 28069 | else if (symbol_table_t::e_immutable == str_ctx.symbol_table->mutability()) 28070 | { 28071 | lodge_immutable_symbol( 28072 | current_token(), 28073 | make_memory_range(str_ctx.str_var->base(), str_ctx.str_var->size())); 28074 | } 28075 | 28076 | lodge_symbol(symbol, e_st_string); 28077 | } 28078 | 28079 | if (peek_token_is(token_t::e_lsqrbracket)) 28080 | { 28081 | next_token(); 28082 | 28083 | if (peek_token_is(token_t::e_rsqrbracket)) 28084 | { 28085 | next_token(); 28086 | next_token(); 28087 | 28088 | if (const_str_node) 28089 | { 28090 | free_node(node_allocator_, result); 28091 | 28092 | return expression_generator_(T(const_str_node->size())); 28093 | } 28094 | else 28095 | return node_allocator_.allocate<details::stringvar_size_node<T> > 28096 | (static_cast<details::stringvar_node<T>*>(result)->ref()); 28097 | } 28098 | 28099 | range_t rp; 28100 | 28101 | if (!parse_range(rp)) 28102 | { 28103 | free_node(node_allocator_, result); 28104 | 28105 | return error_node(); 28106 | } 28107 | else if (const_str_node) 28108 | { 28109 | free_node(node_allocator_, result); 28110 | result = expression_generator_(const_str_node->ref(),rp); 28111 | } 28112 | else 28113 | result = expression_generator_(static_cast<details::stringvar_node<T>*> 28114 | (result)->ref(), rp); 28115 | 28116 | if (result) 28117 | rp.clear(); 28118 | } 28119 | else 28120 | next_token(); 28121 | 28122 | return result; 28123 | } 28124 | #else 28125 | inline expression_node_ptr parse_string() 28126 | { 28127 | return error_node(); 28128 | } 28129 | #endif 28130 | 28131 | #ifndef exprtk_disable_string_capabilities 28132 | inline expression_node_ptr parse_const_string() 28133 | { 28134 | const std::string const_str = current_token().value; 28135 | expression_node_ptr result = expression_generator_(const_str); 28136 | 28137 | if (peek_token_is(token_t::e_lsqrbracket)) 28138 | { 28139 | next_token(); 28140 | 28141 | if (peek_token_is(token_t::e_rsqrbracket)) 28142 | { 28143 | next_token(); 28144 | next_token(); 28145 | 28146 | free_node(node_allocator_, result); 28147 | 28148 | return expression_generator_(T(const_str.size())); 28149 | } 28150 | 28151 | range_t rp; 28152 | 28153 | if (!parse_range(rp)) 28154 | { 28155 | free_node(node_allocator_, result); 28156 | rp.free(); 28157 | 28158 | return error_node(); 28159 | } 28160 | 28161 | free_node(node_allocator_, result); 28162 | 28163 | if (rp.n1_c.first && (rp.n1_c.second == std::numeric_limits<std::size_t>::max())) 28164 | { 28165 | rp.n1_c.second = const_str.size() - 1; 28166 | rp.cache.second = rp.n1_c.second; 28167 | } 28168 | 28169 | if ( 28170 | (rp.n0_c.first && (rp.n0_c.second >= const_str.size())) || 28171 | (rp.n1_c.first && (rp.n1_c.second >= const_str.size())) 28172 | ) 28173 | { 28174 | set_error(make_error( 28175 | parser_error::e_syntax, 28176 | current_token(), 28177 | "ERR122 - Overflow in range for string: '" + const_str + "'[" + 28178 | (rp.n0_c.first ? details::to_str(static_cast<int>(rp.n0_c.second)) : "?") + ":" + 28179 | (rp.n1_c.first ? details::to_str(static_cast<int>(rp.n1_c.second)) : "?") + "]", 28180 | exprtk_error_location)); 28181 | 28182 | rp.free(); 28183 | 28184 | return error_node(); 28185 | } 28186 | 28187 | result = expression_generator_(const_str,rp); 28188 | 28189 | if (result) 28190 | rp.clear(); 28191 | } 28192 | else 28193 | next_token(); 28194 | 28195 | return result; 28196 | } 28197 | #else 28198 | inline expression_node_ptr parse_const_string() 28199 | { 28200 | return error_node(); 28201 | } 28202 | #endif 28203 | 28204 | inline expression_node_ptr parse_vector_index(const std::string& vector_name = "") 28205 | { 28206 | expression_node_ptr index_expr = error_node(); 28207 | 28208 | if (0 == (index_expr = parse_expression())) 28209 | { 28210 | set_error(make_error( 28211 | parser_error::e_syntax, 28212 | current_token(), 28213 | "ERR123 - Failed to parse index for vector: '" + vector_name + "'", 28214 | exprtk_error_location)); 28215 | 28216 | return error_node(); 28217 | } 28218 | else if (!token_is(token_t::e_rsqrbracket)) 28219 | { 28220 | set_error(make_error( 28221 | parser_error::e_syntax, 28222 | current_token(), 28223 | "ERR124 - Expected ']' for index of vector: '" + vector_name + "'", 28224 | exprtk_error_location)); 28225 | 28226 | free_node(node_allocator_, index_expr); 28227 | 28228 | return error_node(); 28229 | } 28230 | 28231 | return index_expr; 28232 | } 28233 | 28234 | inline expression_node_ptr parse_vector() 28235 | { 28236 | const std::string vector_name = current_token().value; 28237 | 28238 | vector_holder_ptr vec = vector_holder_ptr(0); 28239 | 28240 | const scope_element& se = sem_.get_active_element(vector_name); 28241 | 28242 | if ( 28243 | !details::imatch(se.name, vector_name) || 28244 | (se.depth > state_.scope_depth) || 28245 | (scope_element::e_vector != se.type) 28246 | ) 28247 | { 28248 | typedef typename symtab_store::vector_context vec_ctxt_t; 28249 | vec_ctxt_t vec_ctx = symtab_store_.get_vector_context(vector_name); 28250 | 28251 | if (0 == vec_ctx.vector_holder) 28252 | { 28253 | set_error(make_error( 28254 | parser_error::e_syntax, 28255 | current_token(), 28256 | "ERR125 - Symbol '" + vector_name + " not a vector", 28257 | exprtk_error_location)); 28258 | 28259 | return error_node(); 28260 | } 28261 | 28262 | assert(0 != vec_ctx.vector_holder); 28263 | assert(0 != vec_ctx.symbol_table ); 28264 | 28265 | vec = vec_ctx.vector_holder; 28266 | 28267 | if (symbol_table_t::e_immutable == vec_ctx.symbol_table->mutability()) 28268 | { 28269 | lodge_immutable_symbol( 28270 | current_token(), 28271 | make_memory_range(vec->data(), vec->size())); 28272 | } 28273 | } 28274 | else 28275 | { 28276 | vec = se.vec_node; 28277 | } 28278 | 28279 | assert(0 != vec); 28280 | 28281 | next_token(); 28282 | 28283 | if (!token_is(token_t::e_lsqrbracket)) 28284 | { 28285 | return node_allocator_.allocate<vector_node_t>(vec); 28286 | } 28287 | else if (token_is(token_t::e_rsqrbracket)) 28288 | { 28289 | return (vec->rebaseable()) ? 28290 | node_allocator_.allocate<vector_size_node_t>(vec) : 28291 | expression_generator_(T(vec->size())); 28292 | } 28293 | 28294 | expression_node_ptr index_expr = parse_vector_index(vector_name); 28295 | 28296 | if (index_expr) 28297 | { 28298 | expression_node_ptr vec_node = node_allocator_.allocate<vector_node_t>(vec); 28299 | 28300 | return synthesize_vector_element(vector_name, vec, vec_node, index_expr); 28301 | } 28302 | 28303 | return error_node(); 28304 | } 28305 | 28306 | inline expression_node_ptr synthesize_vector_element(const std::string& vector_name, 28307 | vector_holder_ptr vec, 28308 | expression_node_ptr vec_node, 28309 | expression_node_ptr index_expr) 28310 | { 28311 | // Perform compile-time range check 28312 | if (details::is_constant_node(index_expr)) 28313 | { 28314 | const std::size_t index = static_cast<std::size_t>(details::numeric::to_int32(index_expr->value())); 28315 | const std::size_t vec_size = vec->size(); 28316 | 28317 | if (index >= vec_size) 28318 | { 28319 | set_error(make_error( 28320 | parser_error::e_syntax, 28321 | current_token(), 28322 | "ERR126 - Index of " + details::to_str(index) + " out of range for " 28323 | "vector '" + vector_name + "' of size " + details::to_str(vec_size), 28324 | exprtk_error_location)); 28325 | 28326 | free_node(node_allocator_, vec_node ); 28327 | free_node(node_allocator_, index_expr); 28328 | 28329 | return error_node(); 28330 | } 28331 | } 28332 | 28333 | return expression_generator_.vector_element(vector_name, vec, vec_node, index_expr); 28334 | } 28335 | 28336 | inline expression_node_ptr parse_vararg_function_call(ivararg_function<T>* vararg_function, const std::string& vararg_function_name) 28337 | { 28338 | std::vector<expression_node_ptr> arg_list; 28339 | 28340 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 28341 | 28342 | next_token(); 28343 | 28344 | if (token_is(token_t::e_lbracket)) 28345 | { 28346 | if (token_is(token_t::e_rbracket)) 28347 | { 28348 | if (!vararg_function->allow_zero_parameters()) 28349 | { 28350 | set_error(make_error( 28351 | parser_error::e_syntax, 28352 | current_token(), 28353 | "ERR127 - Zero parameter call to vararg function: " 28354 | + vararg_function_name + " not allowed", 28355 | exprtk_error_location)); 28356 | 28357 | return error_node(); 28358 | } 28359 | } 28360 | else 28361 | { 28362 | for ( ; ; ) 28363 | { 28364 | expression_node_ptr arg = parse_expression(); 28365 | 28366 | if (0 == arg) 28367 | return error_node(); 28368 | else 28369 | arg_list.push_back(arg); 28370 | 28371 | if (token_is(token_t::e_rbracket)) 28372 | break; 28373 | else if (!token_is(token_t::e_comma)) 28374 | { 28375 | set_error(make_error( 28376 | parser_error::e_syntax, 28377 | current_token(), 28378 | "ERR128 - Expected ',' for call to vararg function: " 28379 | + vararg_function_name, 28380 | exprtk_error_location)); 28381 | 28382 | return error_node(); 28383 | } 28384 | } 28385 | } 28386 | } 28387 | else if (!vararg_function->allow_zero_parameters()) 28388 | { 28389 | set_error(make_error( 28390 | parser_error::e_syntax, 28391 | current_token(), 28392 | "ERR129 - Zero parameter call to vararg function: " 28393 | + vararg_function_name + " not allowed", 28394 | exprtk_error_location)); 28395 | 28396 | return error_node(); 28397 | } 28398 | 28399 | if (arg_list.size() < vararg_function->min_num_args()) 28400 | { 28401 | set_error(make_error( 28402 | parser_error::e_syntax, 28403 | current_token(), 28404 | "ERR130 - Invalid number of parameters to call to vararg function: " 28405 | + vararg_function_name + ", require at least " 28406 | + details::to_str(static_cast<int>(vararg_function->min_num_args())) + " parameters", 28407 | exprtk_error_location)); 28408 | 28409 | return error_node(); 28410 | } 28411 | else if (arg_list.size() > vararg_function->max_num_args()) 28412 | { 28413 | set_error(make_error( 28414 | parser_error::e_syntax, 28415 | current_token(), 28416 | "ERR131 - Invalid number of parameters to call to vararg function: " 28417 | + vararg_function_name + ", require no more than " 28418 | + details::to_str(static_cast<int>(vararg_function->max_num_args())) + " parameters", 28419 | exprtk_error_location)); 28420 | 28421 | return error_node(); 28422 | } 28423 | 28424 | expression_node_ptr result = expression_generator_.vararg_function_call(vararg_function,arg_list); 28425 | 28426 | svd.delete_ptr = (0 == result); 28427 | 28428 | return result; 28429 | } 28430 | 28431 | class type_checker 28432 | { 28433 | public: 28434 | 28435 | enum return_type_t 28436 | { 28437 | e_overload = ' ', 28438 | e_numeric = 'T', 28439 | e_string = 'S' 28440 | }; 28441 | 28442 | struct function_prototype_t 28443 | { 28444 | return_type_t return_type; 28445 | std::string param_seq; 28446 | }; 28447 | 28448 | typedef parser<T> parser_t; 28449 | typedef std::vector<function_prototype_t> function_definition_list_t; 28450 | 28451 | type_checker(parser_t& p, 28452 | const std::string& func_name, 28453 | const std::string& func_prototypes, 28454 | const return_type_t default_return_type) 28455 | : invalid_state_(true) 28456 | , parser_(p) 28457 | , function_name_(func_name) 28458 | , default_return_type_(default_return_type) 28459 | { 28460 | parse_function_prototypes(func_prototypes); 28461 | } 28462 | 28463 | bool verify(const std::string& param_seq, std::size_t& pseq_index) 28464 | { 28465 | if (function_definition_list_.empty()) 28466 | return true; 28467 | 28468 | std::vector<std::pair<std::size_t,char> > error_list; 28469 | 28470 | for (std::size_t i = 0; i < function_definition_list_.size(); ++i) 28471 | { 28472 | details::char_t diff_value = 0; 28473 | std::size_t diff_index = 0; 28474 | 28475 | const bool result = details::sequence_match(function_definition_list_[i].param_seq, 28476 | param_seq, 28477 | diff_index, diff_value); 28478 | 28479 | if (result) 28480 | { 28481 | pseq_index = i; 28482 | return true; 28483 | } 28484 | else 28485 | error_list.push_back(std::make_pair(diff_index, diff_value)); 28486 | } 28487 | 28488 | if (1 == error_list.size()) 28489 | { 28490 | parser_.set_error(make_error( 28491 | parser_error::e_syntax, 28492 | parser_.current_token(), 28493 | "ERR132 - Failed parameter type check for function '" + function_name_ + "', " 28494 | "Expected '" + function_definition_list_[0].param_seq + 28495 | "' call set: '" + param_seq + "'", 28496 | exprtk_error_location)); 28497 | } 28498 | else 28499 | { 28500 | // find first with largest diff_index; 28501 | std::size_t max_diff_index = 0; 28502 | 28503 | for (std::size_t i = 1; i < error_list.size(); ++i) 28504 | { 28505 | if (error_list[i].first > error_list[max_diff_index].first) 28506 | { 28507 | max_diff_index = i; 28508 | } 28509 | } 28510 | 28511 | parser_.set_error(make_error( 28512 | parser_error::e_syntax, 28513 | parser_.current_token(), 28514 | "ERR133 - Failed parameter type check for function '" + function_name_ + "', " 28515 | "Best match: '" + function_definition_list_[max_diff_index].param_seq + 28516 | "' call set: '" + param_seq + "'", 28517 | exprtk_error_location)); 28518 | } 28519 | 28520 | return false; 28521 | } 28522 | 28523 | std::size_t paramseq_count() const 28524 | { 28525 | return function_definition_list_.size(); 28526 | } 28527 | 28528 | std::string paramseq(const std::size_t& index) const 28529 | { 28530 | return function_definition_list_[index].param_seq; 28531 | } 28532 | 28533 | return_type_t return_type(const std::size_t& index) const 28534 | { 28535 | return function_definition_list_[index].return_type; 28536 | } 28537 | 28538 | bool invalid() const 28539 | { 28540 | return !invalid_state_; 28541 | } 28542 | 28543 | bool allow_zero_parameters() const 28544 | { 28545 | 28546 | for (std::size_t i = 0; i < function_definition_list_.size(); ++i) 28547 | { 28548 | if (std::string::npos != function_definition_list_[i].param_seq.find("Z")) 28549 | { 28550 | return true; 28551 | } 28552 | } 28553 | 28554 | return false; 28555 | } 28556 | 28557 | private: 28558 | 28559 | std::vector<std::string> split_param_seq(const std::string& param_seq, const details::char_t delimiter = '|') const 28560 | { 28561 | std::string::const_iterator current_begin = param_seq.begin(); 28562 | std::string::const_iterator iter = param_seq.begin(); 28563 | 28564 | std::vector<std::string> result; 28565 | 28566 | while (iter != param_seq.end()) 28567 | { 28568 | if (*iter == delimiter) 28569 | { 28570 | result.push_back(std::string(current_begin, iter)); 28571 | current_begin = ++iter; 28572 | } 28573 | else 28574 | ++iter; 28575 | } 28576 | 28577 | if (current_begin != iter) 28578 | { 28579 | result.push_back(std::string(current_begin, iter)); 28580 | } 28581 | 28582 | return result; 28583 | } 28584 | 28585 | inline bool is_valid_token(std::string param_seq, 28586 | function_prototype_t& funcproto) const 28587 | { 28588 | // Determine return type 28589 | funcproto.return_type = default_return_type_; 28590 | 28591 | if (param_seq.size() > 2) 28592 | { 28593 | if (':' == param_seq[1]) 28594 | { 28595 | // Note: Only overloaded igeneric functions can have return 28596 | // type definitions. 28597 | if (type_checker::e_overload != default_return_type_) 28598 | return false; 28599 | 28600 | switch (param_seq[0]) 28601 | { 28602 | case 'T' : funcproto.return_type = type_checker::e_numeric; 28603 | break; 28604 | 28605 | case 'S' : funcproto.return_type = type_checker::e_string; 28606 | break; 28607 | 28608 | default : return false; 28609 | } 28610 | 28611 | param_seq.erase(0,2); 28612 | } 28613 | } 28614 | 28615 | if ( 28616 | (std::string::npos != param_seq.find("?*")) || 28617 | (std::string::npos != param_seq.find("**")) 28618 | ) 28619 | { 28620 | return false; 28621 | } 28622 | else if ( 28623 | (std::string::npos == param_seq.find_first_not_of("STV*?|")) || 28624 | ("Z" == param_seq) 28625 | ) 28626 | { 28627 | funcproto.param_seq = param_seq; 28628 | return true; 28629 | } 28630 | 28631 | return false; 28632 | } 28633 | 28634 | void parse_function_prototypes(const std::string& func_prototypes) 28635 | { 28636 | if (func_prototypes.empty()) 28637 | return; 28638 | 28639 | std::vector<std::string> param_seq_list = split_param_seq(func_prototypes); 28640 | 28641 | typedef std::map<std::string,std::size_t> param_seq_map_t; 28642 | param_seq_map_t param_seq_map; 28643 | 28644 | for (std::size_t i = 0; i < param_seq_list.size(); ++i) 28645 | { 28646 | function_prototype_t func_proto; 28647 | 28648 | if (!is_valid_token(param_seq_list[i], func_proto)) 28649 | { 28650 | invalid_state_ = false; 28651 | 28652 | parser_.set_error(make_error( 28653 | parser_error::e_syntax, 28654 | parser_.current_token(), 28655 | "ERR134 - Invalid parameter sequence of '" + param_seq_list[i] + 28656 | "' for function: " + function_name_, 28657 | exprtk_error_location)); 28658 | return; 28659 | } 28660 | 28661 | param_seq_map_t::const_iterator seq_itr = param_seq_map.find(param_seq_list[i]); 28662 | 28663 | if (param_seq_map.end() != seq_itr) 28664 | { 28665 | invalid_state_ = false; 28666 | 28667 | parser_.set_error(make_error( 28668 | parser_error::e_syntax, 28669 | parser_.current_token(), 28670 | "ERR135 - Function '" + function_name_ + "' has a parameter sequence conflict between " + 28671 | "pseq_idx[" + details::to_str(seq_itr->second) + "] and" + 28672 | "pseq_idx[" + details::to_str(i) + "] " + 28673 | "param seq: " + param_seq_list[i], 28674 | exprtk_error_location)); 28675 | return; 28676 | } 28677 | 28678 | function_definition_list_.push_back(func_proto); 28679 | } 28680 | } 28681 | 28682 | type_checker(const type_checker&) exprtk_delete; 28683 | type_checker& operator=(const type_checker&) exprtk_delete; 28684 | 28685 | bool invalid_state_; 28686 | parser_t& parser_; 28687 | std::string function_name_; 28688 | const return_type_t default_return_type_; 28689 | function_definition_list_t function_definition_list_; 28690 | }; 28691 | 28692 | inline expression_node_ptr parse_generic_function_call(igeneric_function<T>* function, const std::string& function_name) 28693 | { 28694 | std::vector<expression_node_ptr> arg_list; 28695 | 28696 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 28697 | 28698 | next_token(); 28699 | 28700 | std::string param_type_list; 28701 | 28702 | type_checker tc( 28703 | (*this), 28704 | function_name, 28705 | function->parameter_sequence, 28706 | type_checker::e_string); 28707 | 28708 | if (tc.invalid()) 28709 | { 28710 | set_error(make_error( 28711 | parser_error::e_syntax, 28712 | current_token(), 28713 | "ERR136 - Type checker instantiation failure for generic function: " + function_name, 28714 | exprtk_error_location)); 28715 | 28716 | return error_node(); 28717 | } 28718 | 28719 | if (token_is(token_t::e_lbracket)) 28720 | { 28721 | if (token_is(token_t::e_rbracket)) 28722 | { 28723 | if ( 28724 | !function->allow_zero_parameters() && 28725 | !tc .allow_zero_parameters() 28726 | ) 28727 | { 28728 | set_error(make_error( 28729 | parser_error::e_syntax, 28730 | current_token(), 28731 | "ERR137 - Zero parameter call to generic function: " 28732 | + function_name + " not allowed", 28733 | exprtk_error_location)); 28734 | 28735 | return error_node(); 28736 | } 28737 | } 28738 | else 28739 | { 28740 | for ( ; ; ) 28741 | { 28742 | expression_node_ptr arg = parse_expression(); 28743 | 28744 | if (0 == arg) 28745 | return error_node(); 28746 | 28747 | if (is_ivector_node(arg)) 28748 | param_type_list += 'V'; 28749 | else if (is_generally_string_node(arg)) 28750 | param_type_list += 'S'; 28751 | else // Everything else is assumed to be a scalar returning expression 28752 | param_type_list += 'T'; 28753 | 28754 | arg_list.push_back(arg); 28755 | 28756 | if (token_is(token_t::e_rbracket)) 28757 | break; 28758 | else if (!token_is(token_t::e_comma)) 28759 | { 28760 | set_error(make_error( 28761 | parser_error::e_syntax, 28762 | current_token(), 28763 | "ERR138 - Expected ',' for call to generic function: " + function_name, 28764 | exprtk_error_location)); 28765 | 28766 | return error_node(); 28767 | } 28768 | } 28769 | } 28770 | } 28771 | else if ( 28772 | !function->parameter_sequence.empty() && 28773 | function->allow_zero_parameters () && 28774 | !tc .allow_zero_parameters () 28775 | ) 28776 | { 28777 | set_error(make_error( 28778 | parser_error::e_syntax, 28779 | current_token(), 28780 | "ERR139 - Zero parameter call to generic function: " 28781 | + function_name + " not allowed", 28782 | exprtk_error_location)); 28783 | 28784 | return error_node(); 28785 | } 28786 | 28787 | std::size_t param_seq_index = 0; 28788 | 28789 | if ( 28790 | state_.type_check_enabled && 28791 | !tc.verify(param_type_list, param_seq_index) 28792 | ) 28793 | { 28794 | set_error(make_error( 28795 | parser_error::e_syntax, 28796 | current_token(), 28797 | "ERR140 - Invalid input parameter sequence for call to generic function: " + function_name, 28798 | exprtk_error_location)); 28799 | 28800 | return error_node(); 28801 | } 28802 | 28803 | expression_node_ptr result = 28804 | (tc.paramseq_count() <= 1) ? 28805 | expression_generator_ 28806 | .generic_function_call(function, arg_list) : 28807 | expression_generator_ 28808 | .generic_function_call(function, arg_list, param_seq_index); 28809 | 28810 | svd.delete_ptr = (0 == result); 28811 | 28812 | return result; 28813 | } 28814 | 28815 | inline bool parse_igeneric_function_params(std::string& param_type_list, 28816 | std::vector<expression_node_ptr>& arg_list, 28817 | const std::string& function_name, 28818 | igeneric_function<T>* function, 28819 | const type_checker& tc) 28820 | { 28821 | if (token_is(token_t::e_lbracket)) 28822 | { 28823 | if (token_is(token_t::e_rbracket)) 28824 | { 28825 | if ( 28826 | !function->allow_zero_parameters() && 28827 | !tc .allow_zero_parameters() 28828 | ) 28829 | { 28830 | set_error(make_error( 28831 | parser_error::e_syntax, 28832 | current_token(), 28833 | "ERR141 - Zero parameter call to generic function: " 28834 | + function_name + " not allowed", 28835 | exprtk_error_location)); 28836 | 28837 | return false; 28838 | } 28839 | } 28840 | else 28841 | { 28842 | for ( ; ; ) 28843 | { 28844 | expression_node_ptr arg = parse_expression(); 28845 | 28846 | if (0 == arg) 28847 | return false; 28848 | 28849 | if (is_ivector_node(arg)) 28850 | param_type_list += 'V'; 28851 | else if (is_generally_string_node(arg)) 28852 | param_type_list += 'S'; 28853 | else // Everything else is a scalar returning expression 28854 | param_type_list += 'T'; 28855 | 28856 | arg_list.push_back(arg); 28857 | 28858 | if (token_is(token_t::e_rbracket)) 28859 | break; 28860 | else if (!token_is(token_t::e_comma)) 28861 | { 28862 | set_error(make_error( 28863 | parser_error::e_syntax, 28864 | current_token(), 28865 | "ERR142 - Expected ',' for call to string function: " + function_name, 28866 | exprtk_error_location)); 28867 | 28868 | return false; 28869 | } 28870 | } 28871 | } 28872 | 28873 | return true; 28874 | } 28875 | else 28876 | return false; 28877 | } 28878 | 28879 | #ifndef exprtk_disable_string_capabilities 28880 | inline expression_node_ptr parse_string_function_call(igeneric_function<T>* function, const std::string& function_name) 28881 | { 28882 | // Move pass the function name 28883 | next_token(); 28884 | 28885 | std::string param_type_list; 28886 | 28887 | type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_string); 28888 | 28889 | if ( 28890 | (!function->parameter_sequence.empty()) && 28891 | (0 == tc.paramseq_count()) 28892 | ) 28893 | { 28894 | return error_node(); 28895 | } 28896 | 28897 | std::vector<expression_node_ptr> arg_list; 28898 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 28899 | 28900 | if (!parse_igeneric_function_params(param_type_list, arg_list, function_name, function, tc)) 28901 | { 28902 | return error_node(); 28903 | } 28904 | 28905 | std::size_t param_seq_index = 0; 28906 | 28907 | if (!tc.verify(param_type_list, param_seq_index)) 28908 | { 28909 | set_error(make_error( 28910 | parser_error::e_syntax, 28911 | current_token(), 28912 | "ERR143 - Invalid input parameter sequence for call to string function: " + function_name, 28913 | exprtk_error_location)); 28914 | 28915 | return error_node(); 28916 | } 28917 | 28918 | expression_node_ptr result = 28919 | (tc.paramseq_count() <= 1) ? 28920 | expression_generator_ 28921 | .string_function_call(function, arg_list) : 28922 | expression_generator_ 28923 | .string_function_call(function, arg_list, param_seq_index); 28924 | 28925 | svd.delete_ptr = (0 == result); 28926 | 28927 | return result; 28928 | } 28929 | 28930 | inline expression_node_ptr parse_overload_function_call(igeneric_function<T>* function, const std::string& function_name) 28931 | { 28932 | // Move pass the function name 28933 | next_token(); 28934 | 28935 | std::string param_type_list; 28936 | 28937 | type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_overload); 28938 | 28939 | if ( 28940 | (!function->parameter_sequence.empty()) && 28941 | (0 == tc.paramseq_count()) 28942 | ) 28943 | { 28944 | return error_node(); 28945 | } 28946 | 28947 | std::vector<expression_node_ptr> arg_list; 28948 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 28949 | 28950 | if (!parse_igeneric_function_params(param_type_list, arg_list, function_name, function, tc)) 28951 | { 28952 | return error_node(); 28953 | } 28954 | 28955 | std::size_t param_seq_index = 0; 28956 | 28957 | if (!tc.verify(param_type_list, param_seq_index)) 28958 | { 28959 | set_error(make_error( 28960 | parser_error::e_syntax, 28961 | current_token(), 28962 | "ERR144 - Invalid input parameter sequence for call to overloaded function: " + function_name, 28963 | exprtk_error_location)); 28964 | 28965 | return error_node(); 28966 | } 28967 | 28968 | expression_node_ptr result = error_node(); 28969 | 28970 | if (type_checker::e_numeric == tc.return_type(param_seq_index)) 28971 | { 28972 | if (tc.paramseq_count() <= 1) 28973 | result = expression_generator_ 28974 | .generic_function_call(function, arg_list); 28975 | else 28976 | result = expression_generator_ 28977 | .generic_function_call(function, arg_list, param_seq_index); 28978 | } 28979 | else if (type_checker::e_string == tc.return_type(param_seq_index)) 28980 | { 28981 | if (tc.paramseq_count() <= 1) 28982 | result = expression_generator_ 28983 | .string_function_call(function, arg_list); 28984 | else 28985 | result = expression_generator_ 28986 | .string_function_call(function, arg_list, param_seq_index); 28987 | } 28988 | else 28989 | { 28990 | set_error(make_error( 28991 | parser_error::e_syntax, 28992 | current_token(), 28993 | "ERR145 - Invalid return type for call to overloaded function: " + function_name, 28994 | exprtk_error_location)); 28995 | } 28996 | 28997 | svd.delete_ptr = (0 == result); 28998 | return result; 28999 | } 29000 | #endif 29001 | 29002 | template <typename Type, std::size_t NumberOfParameters> 29003 | struct parse_special_function_impl 29004 | { 29005 | static inline expression_node_ptr process(parser<Type>& p, const details::operator_type opt_type, const std::string& sf_name) 29006 | { 29007 | expression_node_ptr branch[NumberOfParameters]; 29008 | expression_node_ptr result = error_node(); 29009 | 29010 | std::fill_n(branch, NumberOfParameters, reinterpret_cast<expression_node_ptr>(0)); 29011 | 29012 | scoped_delete<expression_node_t,NumberOfParameters> sd(p,branch); 29013 | 29014 | p.next_token(); 29015 | 29016 | if (!p.token_is(token_t::e_lbracket)) 29017 | { 29018 | p.set_error(make_error( 29019 | parser_error::e_syntax, 29020 | p.current_token(), 29021 | "ERR146 - Expected '(' for special function '" + sf_name + "'", 29022 | exprtk_error_location)); 29023 | 29024 | return error_node(); 29025 | } 29026 | 29027 | for (std::size_t i = 0; i < NumberOfParameters; ++i) 29028 | { 29029 | branch[i] = p.parse_expression(); 29030 | 29031 | if (0 == branch[i]) 29032 | { 29033 | return p.error_node(); 29034 | } 29035 | else if (i < (NumberOfParameters - 1)) 29036 | { 29037 | if (!p.token_is(token_t::e_comma)) 29038 | { 29039 | p.set_error(make_error( 29040 | parser_error::e_syntax, 29041 | p.current_token(), 29042 | "ERR147 - Expected ',' before next parameter of special function '" + sf_name + "'", 29043 | exprtk_error_location)); 29044 | 29045 | return p.error_node(); 29046 | } 29047 | } 29048 | } 29049 | 29050 | if (!p.token_is(token_t::e_rbracket)) 29051 | { 29052 | p.set_error(make_error( 29053 | parser_error::e_syntax, 29054 | p.current_token(), 29055 | "ERR148 - Invalid number of parameters for special function '" + sf_name + "'", 29056 | exprtk_error_location)); 29057 | 29058 | return p.error_node(); 29059 | } 29060 | else 29061 | result = p.expression_generator_.special_function(opt_type,branch); 29062 | 29063 | sd.delete_ptr = (0 == result); 29064 | 29065 | return result; 29066 | } 29067 | }; 29068 | 29069 | inline expression_node_ptr parse_special_function() 29070 | { 29071 | const std::string sf_name = current_token().value; 29072 | 29073 | // Expect: $fDD(expr0,expr1,expr2) or $fDD(expr0,expr1,expr2,expr3) 29074 | if ( 29075 | !details::is_digit(sf_name[2]) || 29076 | !details::is_digit(sf_name[3]) 29077 | ) 29078 | { 29079 | set_error(make_error( 29080 | parser_error::e_token, 29081 | current_token(), 29082 | "ERR149 - Invalid special function[1]: " + sf_name, 29083 | exprtk_error_location)); 29084 | 29085 | return error_node(); 29086 | } 29087 | 29088 | const int id = (sf_name[2] - '0') * 10 + 29089 | (sf_name[3] - '0'); 29090 | 29091 | if (id >= details::e_sffinal) 29092 | { 29093 | set_error(make_error( 29094 | parser_error::e_token, 29095 | current_token(), 29096 | "ERR150 - Invalid special function[2]: " + sf_name, 29097 | exprtk_error_location)); 29098 | 29099 | return error_node(); 29100 | } 29101 | 29102 | const int sf_3_to_4 = details::e_sf48; 29103 | const details::operator_type opt_type = details::operator_type(id + 1000); 29104 | const std::size_t NumberOfParameters = (id < (sf_3_to_4 - 1000)) ? 3U : 4U; 29105 | 29106 | switch (NumberOfParameters) 29107 | { 29108 | case 3 : return parse_special_function_impl<T,3>::process((*this), opt_type, sf_name); 29109 | case 4 : return parse_special_function_impl<T,4>::process((*this), opt_type, sf_name); 29110 | default : return error_node(); 29111 | } 29112 | } 29113 | 29114 | inline expression_node_ptr parse_null_statement() 29115 | { 29116 | next_token(); 29117 | return node_allocator_.allocate<details::null_node<T> >(); 29118 | } 29119 | 29120 | #ifndef exprtk_disable_break_continue 29121 | inline expression_node_ptr parse_break_statement() 29122 | { 29123 | if (state_.parsing_break_stmt) 29124 | { 29125 | set_error(make_error( 29126 | parser_error::e_syntax, 29127 | current_token(), 29128 | "ERR151 - Invoking 'break' within a break call is not allowed", 29129 | exprtk_error_location)); 29130 | 29131 | return error_node(); 29132 | } 29133 | else if (0 == state_.parsing_loop_stmt_count) 29134 | { 29135 | set_error(make_error( 29136 | parser_error::e_syntax, 29137 | current_token(), 29138 | "ERR152 - Invalid use of 'break', allowed only in the scope of a loop", 29139 | exprtk_error_location)); 29140 | 29141 | return error_node(); 29142 | } 29143 | 29144 | scoped_bool_negator sbn(state_.parsing_break_stmt); 29145 | 29146 | if (!brkcnt_list_.empty()) 29147 | { 29148 | next_token(); 29149 | 29150 | brkcnt_list_.front() = true; 29151 | 29152 | expression_node_ptr return_expr = error_node(); 29153 | 29154 | if (token_is(token_t::e_lsqrbracket)) 29155 | { 29156 | if (0 == (return_expr = parse_expression())) 29157 | { 29158 | set_error(make_error( 29159 | parser_error::e_syntax, 29160 | current_token(), 29161 | "ERR153 - Failed to parse return expression for 'break' statement", 29162 | exprtk_error_location)); 29163 | 29164 | return error_node(); 29165 | } 29166 | else if (!token_is(token_t::e_rsqrbracket)) 29167 | { 29168 | set_error(make_error( 29169 | parser_error::e_syntax, 29170 | current_token(), 29171 | "ERR154 - Expected ']' at the completion of break's return expression", 29172 | exprtk_error_location)); 29173 | 29174 | free_node(node_allocator_, return_expr); 29175 | 29176 | return error_node(); 29177 | } 29178 | } 29179 | 29180 | state_.activate_side_effect("parse_break_statement()"); 29181 | 29182 | return node_allocator_.allocate<details::break_node<T> >(return_expr); 29183 | } 29184 | else 29185 | { 29186 | set_error(make_error( 29187 | parser_error::e_syntax, 29188 | current_token(), 29189 | "ERR155 - Invalid use of 'break', allowed only in the scope of a loop", 29190 | exprtk_error_location)); 29191 | } 29192 | 29193 | return error_node(); 29194 | } 29195 | 29196 | inline expression_node_ptr parse_continue_statement() 29197 | { 29198 | if (0 == state_.parsing_loop_stmt_count) 29199 | { 29200 | set_error(make_error( 29201 | parser_error::e_syntax, 29202 | current_token(), 29203 | "ERR156 - Invalid use of 'continue', allowed only in the scope of a loop", 29204 | exprtk_error_location)); 29205 | 29206 | return error_node(); 29207 | } 29208 | else 29209 | { 29210 | next_token(); 29211 | 29212 | brkcnt_list_.front() = true; 29213 | state_.activate_side_effect("parse_continue_statement()"); 29214 | 29215 | return node_allocator_.allocate<details::continue_node<T> >(); 29216 | } 29217 | } 29218 | #endif 29219 | 29220 | inline expression_node_ptr parse_define_vector_statement(const std::string& vec_name) 29221 | { 29222 | expression_node_ptr size_expression_node = error_node(); 29223 | 29224 | if (!token_is(token_t::e_lsqrbracket)) 29225 | { 29226 | set_error(make_error( 29227 | parser_error::e_syntax, 29228 | current_token(), 29229 | "ERR157 - Expected '[' as part of vector size definition", 29230 | exprtk_error_location)); 29231 | 29232 | return error_node(); 29233 | } 29234 | else if (0 == (size_expression_node = parse_expression())) 29235 | { 29236 | set_error(make_error( 29237 | parser_error::e_syntax, 29238 | current_token(), 29239 | "ERR158 - Failed to determine size of vector '" + vec_name + "'", 29240 | exprtk_error_location)); 29241 | 29242 | return error_node(); 29243 | } 29244 | else if (!is_constant_node(size_expression_node)) 29245 | { 29246 | const bool is_rebaseble_vector = 29247 | (size_expression_node->type() == details::expression_node<T>::e_vecsize) && 29248 | static_cast<details::vector_size_node<T>*>(size_expression_node)->vec_holder()->rebaseable(); 29249 | 29250 | free_node(node_allocator_, size_expression_node); 29251 | 29252 | const std::string error_msg = (is_rebaseble_vector) ? 29253 | std::string("Rebasable/Resizable vector cannot be used to define the size of vector") : 29254 | std::string("Expected a constant literal number as size of vector"); 29255 | set_error(make_error( 29256 | parser_error::e_syntax, 29257 | current_token(), 29258 | "ERR159 - " + error_msg + " '" + vec_name + "'", 29259 | exprtk_error_location)); 29260 | 29261 | return error_node(); 29262 | } 29263 | 29264 | const T vector_size = size_expression_node->value(); 29265 | 29266 | free_node(node_allocator_, size_expression_node); 29267 | 29268 | const std::size_t max_vector_size = settings_.max_local_vector_size(); 29269 | 29270 | if ( 29271 | (vector_size <= T(0)) || 29272 | std::not_equal_to<T>() 29273 | (T(0),vector_size - details::numeric::trunc(vector_size)) || 29274 | (static_cast<std::size_t>(vector_size) > max_vector_size) 29275 | ) 29276 | { 29277 | set_error(make_error( 29278 | parser_error::e_syntax, 29279 | current_token(), 29280 | "ERR160 - Invalid vector size. Must be an integer in the " 29281 | "range [0," + details::to_str(static_cast<std::size_t>(max_vector_size)) + "], size: " + 29282 | details::to_str(details::numeric::to_int32(vector_size)), 29283 | exprtk_error_location)); 29284 | 29285 | return error_node(); 29286 | } 29287 | 29288 | typename symbol_table_t::vector_holder_ptr vec_holder = typename symbol_table_t::vector_holder_ptr(0); 29289 | 29290 | const std::size_t vec_size = static_cast<std::size_t>(details::numeric::to_int32(vector_size)); 29291 | const std::size_t predicted_total_lclsymb_size = sizeof(T) * vec_size + sem_.total_local_symb_size_bytes(); 29292 | 29293 | if (predicted_total_lclsymb_size > settings().max_total_local_symbol_size_bytes()) 29294 | { 29295 | set_error(make_error( 29296 | parser_error::e_syntax, 29297 | current_token(), 29298 | "ERR161 - Adding vector '" + vec_name + "' of size " + details::to_str(vec_size) + " bytes " 29299 | "will exceed max total local symbol size of: " + details::to_str(settings().max_total_local_symbol_size_bytes()) + " bytes, " 29300 | "current total size: " + details::to_str(sem_.total_local_symb_size_bytes()) + " bytes", 29301 | exprtk_error_location)); 29302 | 29303 | return error_node(); 29304 | } 29305 | 29306 | scope_element& se = sem_.get_element(vec_name); 29307 | 29308 | if (se.name == vec_name) 29309 | { 29310 | if (se.active) 29311 | { 29312 | set_error(make_error( 29313 | parser_error::e_syntax, 29314 | current_token(), 29315 | "ERR162 - Illegal redefinition of local vector: '" + vec_name + "'", 29316 | exprtk_error_location)); 29317 | 29318 | return error_node(); 29319 | } 29320 | else if ( 29321 | (se.size == vec_size) && 29322 | (scope_element::e_vector == se.type) 29323 | ) 29324 | { 29325 | vec_holder = se.vec_node; 29326 | se.active = true; 29327 | se.depth = state_.scope_depth; 29328 | se.ref_count++; 29329 | } 29330 | } 29331 | 29332 | if (0 == vec_holder) 29333 | { 29334 | scope_element nse; 29335 | nse.name = vec_name; 29336 | nse.active = true; 29337 | nse.ref_count = 1; 29338 | nse.type = scope_element::e_vector; 29339 | nse.depth = state_.scope_depth; 29340 | nse.size = vec_size; 29341 | nse.data = new T[vec_size]; 29342 | nse.vec_node = new typename scope_element::vector_holder_t(reinterpret_cast<T*>(nse.data),nse.size); 29343 | 29344 | details::set_zero_value(reinterpret_cast<T*>(nse.data),vec_size); 29345 | 29346 | if (!sem_.add_element(nse)) 29347 | { 29348 | set_error(make_error( 29349 | parser_error::e_syntax, 29350 | current_token(), 29351 | "ERR163 - Failed to add new local vector '" + vec_name + "' to SEM", 29352 | exprtk_error_location)); 29353 | 29354 | sem_.free_element(nse); 29355 | 29356 | return error_node(); 29357 | } 29358 | 29359 | assert(sem_.total_local_symb_size_bytes() <= settings().max_total_local_symbol_size_bytes()); 29360 | 29361 | vec_holder = nse.vec_node; 29362 | 29363 | exprtk_debug(("parse_define_vector_statement() - INFO - Added new local vector: %s[%d]\n", 29364 | nse.name.c_str(), 29365 | static_cast<int>(nse.size))); 29366 | } 29367 | 29368 | state_.activate_side_effect("parse_define_vector_statement()"); 29369 | 29370 | lodge_symbol(vec_name, e_st_local_vector); 29371 | 29372 | std::vector<expression_node_ptr> vec_initilizer_list; 29373 | 29374 | scoped_vec_delete<expression_node_t> svd((*this), vec_initilizer_list); 29375 | 29376 | bool single_value_initialiser = false; 29377 | bool range_value_initialiser = false; 29378 | bool vec_to_vec_initialiser = false; 29379 | bool null_initialisation = false; 29380 | 29381 | if (!token_is(token_t::e_rsqrbracket)) 29382 | { 29383 | set_error(make_error( 29384 | parser_error::e_syntax, 29385 | current_token(), 29386 | "ERR164 - Expected ']' as part of vector size definition", 29387 | exprtk_error_location)); 29388 | 29389 | return error_node(); 29390 | } 29391 | else if (!token_is(token_t::e_eof, prsrhlpr_t::e_hold)) 29392 | { 29393 | if (!token_is(token_t::e_assign)) 29394 | { 29395 | set_error(make_error( 29396 | parser_error::e_syntax, 29397 | current_token(), 29398 | "ERR165 - Expected ':=' as part of vector definition", 29399 | exprtk_error_location)); 29400 | 29401 | return error_node(); 29402 | } 29403 | else if (token_is(token_t::e_lsqrbracket)) 29404 | { 29405 | expression_node_ptr initialiser_component = parse_expression(); 29406 | 29407 | if (0 == initialiser_component) 29408 | { 29409 | set_error(make_error( 29410 | parser_error::e_syntax, 29411 | current_token(), 29412 | "ERR166 - Failed to parse first component of vector initialiser for vector: " + vec_name, 29413 | exprtk_error_location)); 29414 | 29415 | return error_node(); 29416 | } 29417 | 29418 | vec_initilizer_list.push_back(initialiser_component); 29419 | 29420 | if (token_is(token_t::e_colon)) 29421 | { 29422 | initialiser_component = parse_expression(); 29423 | 29424 | if (0 == initialiser_component) 29425 | { 29426 | set_error(make_error( 29427 | parser_error::e_syntax, 29428 | current_token(), 29429 | "ERR167 - Failed to parse second component of vector initialiser for vector: " + vec_name, 29430 | exprtk_error_location)); 29431 | 29432 | return error_node(); 29433 | } 29434 | 29435 | vec_initilizer_list.push_back(initialiser_component); 29436 | } 29437 | 29438 | if (!token_is(token_t::e_rsqrbracket)) 29439 | { 29440 | set_error(make_error( 29441 | parser_error::e_syntax, 29442 | current_token(), 29443 | "ERR168 - Expected ']' to close single value vector initialiser", 29444 | exprtk_error_location)); 29445 | 29446 | return error_node(); 29447 | } 29448 | 29449 | switch (vec_initilizer_list.size()) 29450 | { 29451 | case 1 : single_value_initialiser = true; break; 29452 | case 2 : range_value_initialiser = true; break; 29453 | } 29454 | } 29455 | else if (!token_is(token_t::e_lcrlbracket)) 29456 | { 29457 | expression_node_ptr initialiser = error_node(); 29458 | 29459 | // Is this a vector to vector assignment and initialisation? 29460 | if (token_t::e_symbol == current_token().type) 29461 | { 29462 | // Is it a locally defined vector? 29463 | const scope_element& lcl_se = sem_.get_active_element(current_token().value); 29464 | 29465 | if (scope_element::e_vector == lcl_se.type) 29466 | { 29467 | if (0 != (initialiser = parse_expression())) 29468 | vec_initilizer_list.push_back(initialiser); 29469 | else 29470 | return error_node(); 29471 | } 29472 | // Are we dealing with a user defined vector? 29473 | else if (symtab_store_.is_vector(current_token().value)) 29474 | { 29475 | lodge_symbol(current_token().value, e_st_vector); 29476 | 29477 | if (0 != (initialiser = parse_expression())) 29478 | vec_initilizer_list.push_back(initialiser); 29479 | else 29480 | return error_node(); 29481 | } 29482 | // Are we dealing with a null initialisation vector definition? 29483 | else if (token_is(token_t::e_symbol,"null")) 29484 | null_initialisation = true; 29485 | } 29486 | 29487 | if (!null_initialisation) 29488 | { 29489 | if (0 == initialiser) 29490 | { 29491 | set_error(make_error( 29492 | parser_error::e_syntax, 29493 | current_token(), 29494 | "ERR169 - Expected '{' as part of vector initialiser list", 29495 | exprtk_error_location)); 29496 | 29497 | return error_node(); 29498 | } 29499 | else 29500 | vec_to_vec_initialiser = true; 29501 | } 29502 | } 29503 | else if (!token_is(token_t::e_rcrlbracket)) 29504 | { 29505 | for ( ; ; ) 29506 | { 29507 | expression_node_ptr initialiser = parse_expression(); 29508 | 29509 | if (0 == initialiser) 29510 | { 29511 | set_error(make_error( 29512 | parser_error::e_syntax, 29513 | current_token(), 29514 | "ERR170 - Expected '{' as part of vector initialiser list", 29515 | exprtk_error_location)); 29516 | 29517 | return error_node(); 29518 | } 29519 | else 29520 | vec_initilizer_list.push_back(initialiser); 29521 | 29522 | if (token_is(token_t::e_rcrlbracket)) 29523 | break; 29524 | 29525 | const bool is_next_close = peek_token_is(token_t::e_rcrlbracket); 29526 | 29527 | if (!token_is(token_t::e_comma) && is_next_close) 29528 | { 29529 | set_error(make_error( 29530 | parser_error::e_syntax, 29531 | current_token(), 29532 | "ERR171 - Expected ',' between vector initialisers", 29533 | exprtk_error_location)); 29534 | 29535 | return error_node(); 29536 | } 29537 | 29538 | if (token_is(token_t::e_rcrlbracket)) 29539 | break; 29540 | } 29541 | } 29542 | 29543 | if ( 29544 | !token_is(token_t::e_rbracket , prsrhlpr_t::e_hold) && 29545 | !token_is(token_t::e_rcrlbracket, prsrhlpr_t::e_hold) && 29546 | !token_is(token_t::e_rsqrbracket, prsrhlpr_t::e_hold) 29547 | ) 29548 | { 29549 | if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold)) 29550 | { 29551 | set_error(make_error( 29552 | parser_error::e_syntax, 29553 | current_token(), 29554 | "ERR172 - Expected ';' at end of vector definition", 29555 | exprtk_error_location)); 29556 | 29557 | return error_node(); 29558 | } 29559 | } 29560 | 29561 | if ( 29562 | !single_value_initialiser && 29563 | !range_value_initialiser && 29564 | (T(vec_initilizer_list.size()) > vector_size) 29565 | ) 29566 | { 29567 | set_error(make_error( 29568 | parser_error::e_syntax, 29569 | current_token(), 29570 | "ERR173 - Initialiser list larger than the number of elements in the vector: '" + vec_name + "'", 29571 | exprtk_error_location)); 29572 | 29573 | return error_node(); 29574 | } 29575 | } 29576 | 29577 | expression_node_ptr result = error_node(); 29578 | 29579 | if ( 29580 | (vec_initilizer_list.size() == 1) && 29581 | single_value_initialiser 29582 | ) 29583 | { 29584 | if (details::is_constant_node(vec_initilizer_list[0])) 29585 | { 29586 | // vector_init_zero_value_node var v[10] := [0] 29587 | if (T(0) == vec_initilizer_list[0]->value()) 29588 | { 29589 | result = node_allocator_ 29590 | .allocate<details::vector_init_zero_value_node<T> >( 29591 | (*vec_holder)[0], 29592 | vec_size, 29593 | vec_initilizer_list); 29594 | } 29595 | else 29596 | { 29597 | // vector_init_single_constvalue_node var v[10] := [123] 29598 | result = node_allocator_ 29599 | .allocate<details::vector_init_single_constvalue_node<T> >( 29600 | (*vec_holder)[0], 29601 | vec_size, 29602 | vec_initilizer_list); 29603 | } 29604 | } 29605 | else 29606 | { 29607 | // vector_init_single_value_node var v[10] := [123 + (x / y)] 29608 | result = node_allocator_ 29609 | .allocate<details::vector_init_single_value_node<T> >( 29610 | (*vec_holder)[0], 29611 | vec_size, 29612 | vec_initilizer_list); 29613 | } 29614 | } 29615 | else if ( 29616 | (vec_initilizer_list.size() == 2) && 29617 | range_value_initialiser 29618 | ) 29619 | { 29620 | bool base_const = details::is_constant_node(vec_initilizer_list[0]); 29621 | bool inc_const = details::is_constant_node(vec_initilizer_list[1]); 29622 | 29623 | if (base_const && inc_const) 29624 | { 29625 | // vector_init_single_value_node var v[10] := [1 : 3.5] 29626 | result = node_allocator_ 29627 | .allocate<details::vector_init_iota_constconst_node<T> >( 29628 | (*vec_holder)[0], 29629 | vec_size, 29630 | vec_initilizer_list); 29631 | } 29632 | else if (base_const && !inc_const) 29633 | { 29634 | // vector_init_single_value_node var v[10] := [1 : x + y] 29635 | result = node_allocator_ 29636 | .allocate<details::vector_init_iota_constnconst_node<T> >( 29637 | (*vec_holder)[0], 29638 | vec_size, 29639 | vec_initilizer_list); 29640 | } 29641 | else if (!base_const && inc_const) 29642 | { 29643 | // vector_init_single_value_node var v[10] := [x + y : 3] 29644 | result = node_allocator_ 29645 | .allocate<details::vector_init_iota_nconstconst_node<T> >( 29646 | (*vec_holder)[0], 29647 | vec_size, 29648 | vec_initilizer_list); 29649 | } 29650 | else if (!base_const && !inc_const) 29651 | { 29652 | // vector_init_single_value_node var v[10] := [x + y : z / w] 29653 | result = node_allocator_ 29654 | .allocate<details::vector_init_iota_nconstnconst_node<T> >( 29655 | (*vec_holder)[0], 29656 | vec_size, 29657 | vec_initilizer_list); 29658 | } 29659 | } 29660 | else if (null_initialisation) 29661 | result = expression_generator_(T(0.0)); 29662 | else if (vec_to_vec_initialiser) 29663 | { 29664 | expression_node_ptr vec_node = node_allocator_.allocate<vector_node_t>(vec_holder); 29665 | 29666 | result = expression_generator_( 29667 | details::e_assign, 29668 | vec_node, 29669 | vec_initilizer_list[0]); 29670 | } 29671 | else 29672 | { 29673 | result = node_allocator_ 29674 | .allocate<details::vector_initialisation_node<T> >( 29675 | (*vec_holder)[0], 29676 | vec_size, 29677 | vec_initilizer_list, 29678 | single_value_initialiser); 29679 | } 29680 | 29681 | svd.delete_ptr = false; 29682 | 29683 | if (result && result->valid()) 29684 | { 29685 | return result; 29686 | } 29687 | 29688 | details::free_node(node_allocator_, result); 29689 | 29690 | set_error(make_error( 29691 | parser_error::e_synthesis, 29692 | current_token(), 29693 | "ERR174 - Failed to generate initialisation node for vector: " + vec_name, 29694 | exprtk_error_location)); 29695 | 29696 | return error_node(); 29697 | } 29698 | 29699 | #ifndef exprtk_disable_string_capabilities 29700 | inline expression_node_ptr parse_define_string_statement(const std::string& str_name, expression_node_ptr initialisation_expression) 29701 | { 29702 | stringvar_node_t* str_node = reinterpret_cast<stringvar_node_t*>(0); 29703 | 29704 | scope_element& se = sem_.get_element(str_name); 29705 | 29706 | if (se.name == str_name) 29707 | { 29708 | if (se.active) 29709 | { 29710 | set_error(make_error( 29711 | parser_error::e_syntax, 29712 | current_token(), 29713 | "ERR175 - Illegal redefinition of local variable: '" + str_name + "'", 29714 | exprtk_error_location)); 29715 | 29716 | free_node(node_allocator_, initialisation_expression); 29717 | 29718 | return error_node(); 29719 | } 29720 | else if (scope_element::e_string == se.type) 29721 | { 29722 | str_node = se.str_node; 29723 | se.active = true; 29724 | se.depth = state_.scope_depth; 29725 | se.ref_count++; 29726 | } 29727 | } 29728 | 29729 | if (0 == str_node) 29730 | { 29731 | scope_element nse; 29732 | nse.name = str_name; 29733 | nse.active = true; 29734 | nse.ref_count = 1; 29735 | nse.type = scope_element::e_string; 29736 | nse.depth = state_.scope_depth; 29737 | nse.data = new std::string; 29738 | nse.str_node = new stringvar_node_t(*reinterpret_cast<std::string*>(nse.data)); 29739 | 29740 | if (!sem_.add_element(nse)) 29741 | { 29742 | set_error(make_error( 29743 | parser_error::e_syntax, 29744 | current_token(), 29745 | "ERR176 - Failed to add new local string variable '" + str_name + "' to SEM", 29746 | exprtk_error_location)); 29747 | 29748 | free_node(node_allocator_, initialisation_expression); 29749 | 29750 | sem_.free_element(nse); 29751 | 29752 | return error_node(); 29753 | } 29754 | 29755 | assert(sem_.total_local_symb_size_bytes() <= settings().max_total_local_symbol_size_bytes()); 29756 | 29757 | str_node = nse.str_node; 29758 | 29759 | exprtk_debug(("parse_define_string_statement() - INFO - Added new local string variable: %s\n", nse.name.c_str())); 29760 | } 29761 | 29762 | lodge_symbol(str_name, e_st_local_string); 29763 | 29764 | state_.activate_side_effect("parse_define_string_statement()"); 29765 | 29766 | expression_node_ptr branch[2] = {0}; 29767 | 29768 | branch[0] = str_node; 29769 | branch[1] = initialisation_expression; 29770 | 29771 | return expression_generator_(details::e_assign,branch); 29772 | } 29773 | #else 29774 | inline expression_node_ptr parse_define_string_statement(const std::string&, expression_node_ptr) 29775 | { 29776 | return error_node(); 29777 | } 29778 | #endif 29779 | 29780 | inline bool local_variable_is_shadowed(const std::string& symbol) 29781 | { 29782 | const scope_element& se = sem_.get_element(symbol); 29783 | return (se.name == symbol) && se.active; 29784 | } 29785 | 29786 | inline expression_node_ptr parse_define_var_statement() 29787 | { 29788 | if (settings_.vardef_disabled()) 29789 | { 29790 | set_error(make_error( 29791 | parser_error::e_syntax, 29792 | current_token(), 29793 | "ERR177 - Illegal variable definition", 29794 | exprtk_error_location)); 29795 | 29796 | return error_node(); 29797 | } 29798 | else if (!details::imatch(current_token().value,"var")) 29799 | { 29800 | return error_node(); 29801 | } 29802 | else 29803 | next_token(); 29804 | 29805 | const std::string var_name = current_token().value; 29806 | 29807 | expression_node_ptr initialisation_expression = error_node(); 29808 | 29809 | if (!token_is(token_t::e_symbol)) 29810 | { 29811 | set_error(make_error( 29812 | parser_error::e_syntax, 29813 | current_token(), 29814 | "ERR178 - Expected a symbol for variable definition", 29815 | exprtk_error_location)); 29816 | 29817 | return error_node(); 29818 | } 29819 | else if (details::is_reserved_symbol(var_name)) 29820 | { 29821 | set_error(make_error( 29822 | parser_error::e_syntax, 29823 | current_token(), 29824 | "ERR179 - Illegal redefinition of reserved keyword: '" + var_name + "'", 29825 | exprtk_error_location)); 29826 | 29827 | return error_node(); 29828 | } 29829 | else if (symtab_store_.symbol_exists(var_name)) 29830 | { 29831 | set_error(make_error( 29832 | parser_error::e_syntax, 29833 | current_token(), 29834 | "ERR180 - Illegal redefinition of variable '" + var_name + "'", 29835 | exprtk_error_location)); 29836 | 29837 | return error_node(); 29838 | } 29839 | else if (local_variable_is_shadowed(var_name)) 29840 | { 29841 | set_error(make_error( 29842 | parser_error::e_syntax, 29843 | current_token(), 29844 | "ERR181 - Illegal redefinition of local variable: '" + var_name + "'", 29845 | exprtk_error_location)); 29846 | 29847 | return error_node(); 29848 | } 29849 | else if (token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold)) 29850 | { 29851 | return parse_define_vector_statement(var_name); 29852 | } 29853 | else if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) 29854 | { 29855 | return parse_uninitialised_var_statement(var_name); 29856 | } 29857 | else if (token_is(token_t::e_assign)) 29858 | { 29859 | if (0 == (initialisation_expression = parse_expression())) 29860 | { 29861 | set_error(make_error( 29862 | parser_error::e_syntax, 29863 | current_token(), 29864 | "ERR182 - Failed to parse initialisation expression for variable '" + var_name + "'", 29865 | exprtk_error_location)); 29866 | 29867 | return error_node(); 29868 | } 29869 | } 29870 | 29871 | if ( 29872 | !token_is(token_t::e_rbracket , prsrhlpr_t::e_hold) && 29873 | !token_is(token_t::e_rcrlbracket, prsrhlpr_t::e_hold) && 29874 | !token_is(token_t::e_rsqrbracket, prsrhlpr_t::e_hold) 29875 | ) 29876 | { 29877 | if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold)) 29878 | { 29879 | set_error(make_error( 29880 | parser_error::e_syntax, 29881 | current_token(), 29882 | "ERR183 - Expected ';' after variable '" + var_name + "' definition", 29883 | exprtk_error_location)); 29884 | 29885 | free_node(node_allocator_, initialisation_expression); 29886 | 29887 | return error_node(); 29888 | } 29889 | } 29890 | 29891 | if ( 29892 | (0 != initialisation_expression) && 29893 | details::is_generally_string_node(initialisation_expression) 29894 | ) 29895 | { 29896 | return parse_define_string_statement(var_name,initialisation_expression); 29897 | } 29898 | 29899 | expression_node_ptr var_node = reinterpret_cast<expression_node_ptr>(0); 29900 | 29901 | scope_element& se = sem_.get_element(var_name); 29902 | 29903 | if (se.name == var_name) 29904 | { 29905 | if (se.active) 29906 | { 29907 | set_error(make_error( 29908 | parser_error::e_syntax, 29909 | current_token(), 29910 | "ERR184 - Illegal redefinition of local variable: '" + var_name + "'", 29911 | exprtk_error_location)); 29912 | 29913 | free_node(node_allocator_, initialisation_expression); 29914 | 29915 | return error_node(); 29916 | } 29917 | else if (scope_element::e_variable == se.type) 29918 | { 29919 | var_node = se.var_node; 29920 | se.active = true; 29921 | se.depth = state_.scope_depth; 29922 | se.ref_count++; 29923 | } 29924 | } 29925 | 29926 | if (0 == var_node) 29927 | { 29928 | const std::size_t predicted_total_lclsymb_size = sizeof(T) + sem_.total_local_symb_size_bytes(); 29929 | 29930 | if (predicted_total_lclsymb_size > settings().max_total_local_symbol_size_bytes()) 29931 | { 29932 | set_error(make_error( 29933 | parser_error::e_syntax, 29934 | current_token(), 29935 | "ERR185 - Adding variable '" + var_name + "' " 29936 | "will exceed max total local symbol size of: " + details::to_str(settings().max_total_local_symbol_size_bytes()) + " bytes, " 29937 | "current total size: " + details::to_str(sem_.total_local_symb_size_bytes()) + " bytes", 29938 | exprtk_error_location)); 29939 | 29940 | free_node(node_allocator_, initialisation_expression); 29941 | 29942 | return error_node(); 29943 | } 29944 | 29945 | scope_element nse; 29946 | nse.name = var_name; 29947 | nse.active = true; 29948 | nse.ref_count = 1; 29949 | nse.type = scope_element::e_variable; 29950 | nse.depth = state_.scope_depth; 29951 | nse.data = new T(T(0)); 29952 | nse.var_node = node_allocator_.allocate<variable_node_t>(*reinterpret_cast<T*>(nse.data)); 29953 | 29954 | if (!sem_.add_element(nse)) 29955 | { 29956 | set_error(make_error( 29957 | parser_error::e_syntax, 29958 | current_token(), 29959 | "ERR186 - Failed to add new local variable '" + var_name + "' to SEM", 29960 | exprtk_error_location)); 29961 | 29962 | free_node(node_allocator_, initialisation_expression); 29963 | 29964 | sem_.free_element(nse); 29965 | 29966 | return error_node(); 29967 | } 29968 | 29969 | assert(sem_.total_local_symb_size_bytes() <= settings().max_total_local_symbol_size_bytes()); 29970 | 29971 | var_node = nse.var_node; 29972 | 29973 | exprtk_debug(("parse_define_var_statement() - INFO - Added new local variable: %s\n", nse.name.c_str())); 29974 | } 29975 | 29976 | state_.activate_side_effect("parse_define_var_statement()"); 29977 | 29978 | lodge_symbol(var_name, e_st_local_variable); 29979 | 29980 | expression_node_ptr branch[2] = {0}; 29981 | 29982 | branch[0] = var_node; 29983 | branch[1] = initialisation_expression ? initialisation_expression : expression_generator_(T(0)); 29984 | 29985 | return expression_generator_(details::e_assign,branch); 29986 | } 29987 | 29988 | inline expression_node_ptr parse_define_constvar_statement() 29989 | { 29990 | if (settings_.vardef_disabled()) 29991 | { 29992 | set_error(make_error( 29993 | parser_error::e_syntax, 29994 | current_token(), 29995 | "ERR187 - Illegal const variable definition", 29996 | exprtk_error_location)); 29997 | 29998 | return error_node(); 29999 | } 30000 | else if (!token_is("const")) 30001 | { 30002 | set_error(make_error( 30003 | parser_error::e_syntax, 30004 | current_token(), 30005 | "ERR188 - Expected 'const' keyword for const-variable definition", 30006 | exprtk_error_location)); 30007 | 30008 | return error_node(); 30009 | } 30010 | else if (!token_is("var")) 30011 | { 30012 | set_error(make_error( 30013 | parser_error::e_syntax, 30014 | current_token(), 30015 | "ERR189 - Expected 'var' keyword for const-variable definition", 30016 | exprtk_error_location)); 30017 | 30018 | return error_node(); 30019 | } 30020 | 30021 | const std::string var_name = current_token().value; 30022 | 30023 | expression_node_ptr initialisation_expression = error_node(); 30024 | 30025 | if (!token_is(token_t::e_symbol)) 30026 | { 30027 | set_error(make_error( 30028 | parser_error::e_syntax, 30029 | current_token(), 30030 | "ERR190 - Expected a symbol for const-variable definition", 30031 | exprtk_error_location)); 30032 | 30033 | return error_node(); 30034 | } 30035 | else if (details::is_reserved_symbol(var_name)) 30036 | { 30037 | set_error(make_error( 30038 | parser_error::e_syntax, 30039 | current_token(), 30040 | "ERR191 - Illegal redefinition of reserved keyword: '" + var_name + "'", 30041 | exprtk_error_location)); 30042 | 30043 | return error_node(); 30044 | } 30045 | else if (symtab_store_.symbol_exists(var_name)) 30046 | { 30047 | set_error(make_error( 30048 | parser_error::e_syntax, 30049 | current_token(), 30050 | "ERR192 - Illegal redefinition of variable '" + var_name + "'", 30051 | exprtk_error_location)); 30052 | 30053 | return error_node(); 30054 | } 30055 | else if (local_variable_is_shadowed(var_name)) 30056 | { 30057 | set_error(make_error( 30058 | parser_error::e_syntax, 30059 | current_token(), 30060 | "ERR193 - Illegal redefinition of local variable: '" + var_name + "'", 30061 | exprtk_error_location)); 30062 | 30063 | return error_node(); 30064 | } 30065 | else if (!token_is(token_t::e_assign)) 30066 | { 30067 | set_error(make_error( 30068 | parser_error::e_syntax, 30069 | current_token(), 30070 | "ERR194 - Expected assignment operator after const-variable: '" + var_name + "' definition", 30071 | exprtk_error_location)); 30072 | 30073 | return error_node(); 30074 | } 30075 | else if (0 == (initialisation_expression = parse_expression())) 30076 | { 30077 | set_error(make_error( 30078 | parser_error::e_syntax, 30079 | current_token(), 30080 | "ERR195 - Failed to parse initialisation expression for const-variable: '" + var_name + "'", 30081 | exprtk_error_location)); 30082 | 30083 | return error_node(); 30084 | } 30085 | 30086 | if (!details::is_literal_node(initialisation_expression)) 30087 | { 30088 | set_error(make_error( 30089 | parser_error::e_syntax, 30090 | current_token(), 30091 | "ERR196 - initialisation expression for const-variable: '" + var_name + "' must be a constant/literal", 30092 | exprtk_error_location)); 30093 | 30094 | free_node(node_allocator_, initialisation_expression); 30095 | 30096 | return error_node(); 30097 | } 30098 | 30099 | assert(initialisation_expression); 30100 | 30101 | const T init_value = initialisation_expression->value(); 30102 | 30103 | free_node(node_allocator_, initialisation_expression); 30104 | 30105 | expression_node_ptr var_node = reinterpret_cast<expression_node_ptr>(0); 30106 | 30107 | scope_element& se = sem_.get_element(var_name); 30108 | 30109 | if (se.name == var_name) 30110 | { 30111 | if (se.active) 30112 | { 30113 | set_error(make_error( 30114 | parser_error::e_syntax, 30115 | current_token(), 30116 | "ERR197 - Illegal redefinition of local variable: '" + var_name + "'", 30117 | exprtk_error_location)); 30118 | 30119 | return error_node(); 30120 | } 30121 | else if (scope_element::e_literal == se.type) 30122 | { 30123 | var_node = se.var_node; 30124 | se.active = true; 30125 | se.depth = state_.scope_depth; 30126 | se.ref_count++; 30127 | } 30128 | } 30129 | 30130 | if (0 == var_node) 30131 | { 30132 | const std::size_t predicted_total_lclsymb_size = sizeof(T) + sem_.total_local_symb_size_bytes(); 30133 | 30134 | if (predicted_total_lclsymb_size > settings().max_total_local_symbol_size_bytes()) 30135 | { 30136 | set_error(make_error( 30137 | parser_error::e_syntax, 30138 | current_token(), 30139 | "ERR198 - Adding variable '" + var_name + "' " 30140 | "will exceed max total local symbol size of: " + details::to_str(settings().max_total_local_symbol_size_bytes()) + " bytes, " 30141 | "current total size: " + details::to_str(sem_.total_local_symb_size_bytes()) + " bytes", 30142 | exprtk_error_location)); 30143 | 30144 | return error_node(); 30145 | } 30146 | 30147 | scope_element nse; 30148 | nse.name = var_name; 30149 | nse.active = true; 30150 | nse.ref_count = 1; 30151 | nse.type = scope_element::e_literal; 30152 | nse.depth = state_.scope_depth; 30153 | nse.data = 0; 30154 | nse.var_node = node_allocator_.allocate<literal_node_t>(init_value); 30155 | 30156 | if (!sem_.add_element(nse)) 30157 | { 30158 | set_error(make_error( 30159 | parser_error::e_syntax, 30160 | current_token(), 30161 | "ERR199 - Failed to add new local const-variable '" + var_name + "' to SEM", 30162 | exprtk_error_location)); 30163 | 30164 | sem_.free_element(nse); 30165 | 30166 | return error_node(); 30167 | } 30168 | 30169 | assert(sem_.total_local_symb_size_bytes() <= settings().max_total_local_symbol_size_bytes()); 30170 | 30171 | var_node = nse.var_node; 30172 | 30173 | exprtk_debug(("parse_define_constvar_statement() - INFO - Added new local const-variable: %s\n", nse.name.c_str())); 30174 | } 30175 | 30176 | state_.activate_side_effect("parse_define_constvar_statement()"); 30177 | 30178 | lodge_symbol(var_name, e_st_local_variable); 30179 | 30180 | return expression_generator_(var_node->value()); 30181 | } 30182 | 30183 | inline expression_node_ptr parse_uninitialised_var_statement(const std::string& var_name) 30184 | { 30185 | if ( 30186 | !token_is(token_t::e_lcrlbracket) || 30187 | !token_is(token_t::e_rcrlbracket) 30188 | ) 30189 | { 30190 | set_error(make_error( 30191 | parser_error::e_syntax, 30192 | current_token(), 30193 | "ERR200 - Expected a '{}' for uninitialised var definition", 30194 | exprtk_error_location)); 30195 | 30196 | return error_node(); 30197 | } 30198 | else if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold)) 30199 | { 30200 | set_error(make_error( 30201 | parser_error::e_syntax, 30202 | current_token(), 30203 | "ERR201 - Expected ';' after uninitialised variable definition", 30204 | exprtk_error_location)); 30205 | 30206 | return error_node(); 30207 | } 30208 | 30209 | expression_node_ptr var_node = reinterpret_cast<expression_node_ptr>(0); 30210 | 30211 | scope_element& se = sem_.get_element(var_name); 30212 | 30213 | if (se.name == var_name) 30214 | { 30215 | if (se.active) 30216 | { 30217 | set_error(make_error( 30218 | parser_error::e_syntax, 30219 | current_token(), 30220 | "ERR202 - Illegal redefinition of local variable: '" + var_name + "'", 30221 | exprtk_error_location)); 30222 | 30223 | return error_node(); 30224 | } 30225 | else if (scope_element::e_variable == se.type) 30226 | { 30227 | var_node = se.var_node; 30228 | se.active = true; 30229 | se.ref_count++; 30230 | } 30231 | } 30232 | 30233 | if (0 == var_node) 30234 | { 30235 | const std::size_t predicted_total_lclsymb_size = sizeof(T) + sem_.total_local_symb_size_bytes(); 30236 | 30237 | if (predicted_total_lclsymb_size > settings().max_total_local_symbol_size_bytes()) 30238 | { 30239 | set_error(make_error( 30240 | parser_error::e_syntax, 30241 | current_token(), 30242 | "ERR203 - Adding variable '" + var_name + "' " 30243 | "will exceed max total local symbol size of: " + details::to_str(settings().max_total_local_symbol_size_bytes()) + " bytes, " 30244 | "current total size: " + details::to_str(sem_.total_local_symb_size_bytes()) + " bytes", 30245 | exprtk_error_location)); 30246 | 30247 | return error_node(); 30248 | } 30249 | 30250 | scope_element nse; 30251 | nse.name = var_name; 30252 | nse.active = true; 30253 | nse.ref_count = 1; 30254 | nse.type = scope_element::e_variable; 30255 | nse.depth = state_.scope_depth; 30256 | nse.ip_index = sem_.next_ip_index(); 30257 | nse.data = new T(T(0)); 30258 | nse.var_node = node_allocator_.allocate<variable_node_t>(*reinterpret_cast<T*>(nse.data)); 30259 | 30260 | if (!sem_.add_element(nse)) 30261 | { 30262 | set_error(make_error( 30263 | parser_error::e_syntax, 30264 | current_token(), 30265 | "ERR204 - Failed to add new local variable '" + var_name + "' to SEM", 30266 | exprtk_error_location)); 30267 | 30268 | sem_.free_element(nse); 30269 | 30270 | return error_node(); 30271 | } 30272 | 30273 | assert(sem_.total_local_symb_size_bytes() <= settings().max_total_local_symbol_size_bytes()); 30274 | 30275 | exprtk_debug(("parse_uninitialised_var_statement() - INFO - Added new local variable: %s\n", 30276 | nse.name.c_str())); 30277 | } 30278 | 30279 | lodge_symbol(var_name, e_st_local_variable); 30280 | 30281 | state_.activate_side_effect("parse_uninitialised_var_statement()"); 30282 | 30283 | return expression_generator_(T(0)); 30284 | } 30285 | 30286 | inline expression_node_ptr parse_swap_statement() 30287 | { 30288 | if (!details::imatch(current_token().value,"swap")) 30289 | { 30290 | return error_node(); 30291 | } 30292 | else 30293 | next_token(); 30294 | 30295 | if (!token_is(token_t::e_lbracket)) 30296 | { 30297 | set_error(make_error( 30298 | parser_error::e_syntax, 30299 | current_token(), 30300 | "ERR205 - Expected '(' at start of swap statement", 30301 | exprtk_error_location)); 30302 | 30303 | return error_node(); 30304 | } 30305 | 30306 | expression_node_ptr variable0 = error_node(); 30307 | expression_node_ptr variable1 = error_node(); 30308 | 30309 | bool variable0_generated = false; 30310 | bool variable1_generated = false; 30311 | 30312 | const std::string var0_name = current_token().value; 30313 | 30314 | if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold)) 30315 | { 30316 | set_error(make_error( 30317 | parser_error::e_syntax, 30318 | current_token(), 30319 | "ERR206 - Expected a symbol for variable or vector element definition", 30320 | exprtk_error_location)); 30321 | 30322 | return error_node(); 30323 | } 30324 | else if (peek_token_is(token_t::e_lsqrbracket)) 30325 | { 30326 | if (0 == (variable0 = parse_vector())) 30327 | { 30328 | set_error(make_error( 30329 | parser_error::e_syntax, 30330 | current_token(), 30331 | "ERR207 - First parameter to swap is an invalid vector element: '" + var0_name + "'", 30332 | exprtk_error_location)); 30333 | 30334 | return error_node(); 30335 | } 30336 | 30337 | variable0_generated = true; 30338 | } 30339 | else 30340 | { 30341 | if (symtab_store_.is_variable(var0_name)) 30342 | { 30343 | variable0 = symtab_store_.get_variable(var0_name); 30344 | } 30345 | 30346 | const scope_element& se = sem_.get_element(var0_name); 30347 | 30348 | if ( 30349 | (se.active) && 30350 | (se.name == var0_name) && 30351 | (scope_element::e_variable == se.type) 30352 | ) 30353 | { 30354 | variable0 = se.var_node; 30355 | } 30356 | 30357 | lodge_symbol(var0_name, e_st_variable); 30358 | 30359 | if (0 == variable0) 30360 | { 30361 | set_error(make_error( 30362 | parser_error::e_syntax, 30363 | current_token(), 30364 | "ERR208 - First parameter to swap is an invalid variable: '" + var0_name + "'", 30365 | exprtk_error_location)); 30366 | 30367 | return error_node(); 30368 | } 30369 | else 30370 | next_token(); 30371 | } 30372 | 30373 | if (!token_is(token_t::e_comma)) 30374 | { 30375 | set_error(make_error( 30376 | parser_error::e_syntax, 30377 | current_token(), 30378 | "ERR209 - Expected ',' between parameters to swap", 30379 | exprtk_error_location)); 30380 | 30381 | if (variable0_generated) 30382 | { 30383 | free_node(node_allocator_, variable0); 30384 | } 30385 | 30386 | return error_node(); 30387 | } 30388 | 30389 | const std::string var1_name = current_token().value; 30390 | 30391 | if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold)) 30392 | { 30393 | set_error(make_error( 30394 | parser_error::e_syntax, 30395 | current_token(), 30396 | "ERR210 - Expected a symbol for variable or vector element definition", 30397 | exprtk_error_location)); 30398 | 30399 | if (variable0_generated) 30400 | { 30401 | free_node(node_allocator_, variable0); 30402 | } 30403 | 30404 | return error_node(); 30405 | } 30406 | else if (peek_token_is(token_t::e_lsqrbracket)) 30407 | { 30408 | if (0 == (variable1 = parse_vector())) 30409 | { 30410 | set_error(make_error( 30411 | parser_error::e_syntax, 30412 | current_token(), 30413 | "ERR211 - Second parameter to swap is an invalid vector element: '" + var1_name + "'", 30414 | exprtk_error_location)); 30415 | 30416 | if (variable0_generated) 30417 | { 30418 | free_node(node_allocator_, variable0); 30419 | } 30420 | 30421 | return error_node(); 30422 | } 30423 | 30424 | variable1_generated = true; 30425 | } 30426 | else 30427 | { 30428 | if (symtab_store_.is_variable(var1_name)) 30429 | { 30430 | variable1 = symtab_store_.get_variable(var1_name); 30431 | } 30432 | 30433 | const scope_element& se = sem_.get_element(var1_name); 30434 | 30435 | if ( 30436 | (se.active) && 30437 | (se.name == var1_name) && 30438 | (scope_element::e_variable == se.type) 30439 | ) 30440 | { 30441 | variable1 = se.var_node; 30442 | } 30443 | 30444 | lodge_symbol(var1_name, e_st_variable); 30445 | 30446 | if (0 == variable1) 30447 | { 30448 | set_error(make_error( 30449 | parser_error::e_syntax, 30450 | current_token(), 30451 | "ERR212 - Second parameter to swap is an invalid variable: '" + var1_name + "'", 30452 | exprtk_error_location)); 30453 | 30454 | if (variable0_generated) 30455 | { 30456 | free_node(node_allocator_, variable0); 30457 | } 30458 | 30459 | return error_node(); 30460 | } 30461 | else 30462 | next_token(); 30463 | } 30464 | 30465 | if (!token_is(token_t::e_rbracket)) 30466 | { 30467 | set_error(make_error( 30468 | parser_error::e_syntax, 30469 | current_token(), 30470 | "ERR213 - Expected ')' at end of swap statement", 30471 | exprtk_error_location)); 30472 | 30473 | if (variable0_generated) 30474 | { 30475 | free_node(node_allocator_, variable0); 30476 | } 30477 | 30478 | if (variable1_generated) 30479 | { 30480 | free_node(node_allocator_, variable1); 30481 | } 30482 | 30483 | return error_node(); 30484 | } 30485 | 30486 | typedef details::variable_node<T>* variable_node_ptr; 30487 | 30488 | variable_node_ptr v0 = variable_node_ptr(0); 30489 | variable_node_ptr v1 = variable_node_ptr(0); 30490 | 30491 | expression_node_ptr result = error_node(); 30492 | 30493 | if ( 30494 | (0 != (v0 = dynamic_cast<variable_node_ptr>(variable0))) && 30495 | (0 != (v1 = dynamic_cast<variable_node_ptr>(variable1))) 30496 | ) 30497 | { 30498 | result = node_allocator_.allocate<details::swap_node<T> >(v0, v1); 30499 | 30500 | if (variable0_generated) 30501 | { 30502 | free_node(node_allocator_, variable0); 30503 | } 30504 | 30505 | if (variable1_generated) 30506 | { 30507 | free_node(node_allocator_, variable1); 30508 | } 30509 | } 30510 | else 30511 | result = node_allocator_.allocate<details::swap_generic_node<T> > 30512 | (variable0, variable1); 30513 | 30514 | state_.activate_side_effect("parse_swap_statement()"); 30515 | 30516 | return result; 30517 | } 30518 | 30519 | #ifndef exprtk_disable_return_statement 30520 | inline expression_node_ptr parse_return_statement() 30521 | { 30522 | if (state_.parsing_return_stmt) 30523 | { 30524 | set_error(make_error( 30525 | parser_error::e_syntax, 30526 | current_token(), 30527 | "ERR214 - Return call within a return call is not allowed", 30528 | exprtk_error_location)); 30529 | 30530 | return error_node(); 30531 | } 30532 | 30533 | scoped_bool_negator sbn(state_.parsing_return_stmt); 30534 | 30535 | std::vector<expression_node_ptr> arg_list; 30536 | 30537 | scoped_vec_delete<expression_node_t> svd((*this), arg_list); 30538 | 30539 | if (!details::imatch(current_token().value,"return")) 30540 | { 30541 | return error_node(); 30542 | } 30543 | else 30544 | next_token(); 30545 | 30546 | if (!token_is(token_t::e_lsqrbracket)) 30547 | { 30548 | set_error(make_error( 30549 | parser_error::e_syntax, 30550 | current_token(), 30551 | "ERR215 - Expected '[' at start of return statement", 30552 | exprtk_error_location)); 30553 | 30554 | return error_node(); 30555 | } 30556 | else if (!token_is(token_t::e_rsqrbracket)) 30557 | { 30558 | for ( ; ; ) 30559 | { 30560 | expression_node_ptr arg = parse_expression(); 30561 | 30562 | if (0 == arg) 30563 | return error_node(); 30564 | 30565 | arg_list.push_back(arg); 30566 | 30567 | if (token_is(token_t::e_rsqrbracket)) 30568 | break; 30569 | else if (!token_is(token_t::e_comma)) 30570 | { 30571 | set_error(make_error( 30572 | parser_error::e_syntax, 30573 | current_token(), 30574 | "ERR216 - Expected ',' between values during call to return", 30575 | exprtk_error_location)); 30576 | 30577 | return error_node(); 30578 | } 30579 | } 30580 | } 30581 | else if (settings_.zero_return_disabled()) 30582 | { 30583 | set_error(make_error( 30584 | parser_error::e_syntax, 30585 | current_token(), 30586 | "ERR217 - Zero parameter return statement not allowed", 30587 | exprtk_error_location)); 30588 | 30589 | return error_node(); 30590 | } 30591 | 30592 | const lexer::token prev_token = current_token(); 30593 | 30594 | if (token_is(token_t::e_rsqrbracket)) 30595 | { 30596 | if (!arg_list.empty()) 30597 | { 30598 | set_error(make_error( 30599 | parser_error::e_syntax, 30600 | prev_token, 30601 | "ERR218 - Invalid ']' found during return call", 30602 | exprtk_error_location)); 30603 | 30604 | return error_node(); 30605 | } 30606 | } 30607 | 30608 | std::string ret_param_type_list; 30609 | 30610 | for (std::size_t i = 0; i < arg_list.size(); ++i) 30611 | { 30612 | if (0 == arg_list[i]) 30613 | return error_node(); 30614 | else if (is_ivector_node(arg_list[i])) 30615 | ret_param_type_list += 'V'; 30616 | else if (is_generally_string_node(arg_list[i])) 30617 | ret_param_type_list += 'S'; 30618 | else 30619 | ret_param_type_list += 'T'; 30620 | } 30621 | 30622 | dec_.retparam_list_.push_back(ret_param_type_list); 30623 | 30624 | expression_node_ptr result = expression_generator_.return_call(arg_list); 30625 | 30626 | svd.delete_ptr = (0 == result); 30627 | 30628 | state_.return_stmt_present = true; 30629 | 30630 | state_.activate_side_effect("parse_return_statement()"); 30631 | 30632 | return result; 30633 | } 30634 | #else 30635 | inline expression_node_ptr parse_return_statement() 30636 | { 30637 | return error_node(); 30638 | } 30639 | #endif 30640 | 30641 | inline expression_node_ptr parse_assert_statement() 30642 | { 30643 | assert(details::imatch(current_token().value, "assert")); 30644 | 30645 | if (state_.parsing_assert_stmt) 30646 | { 30647 | set_error(make_error( 30648 | parser_error::e_syntax, 30649 | current_token(), 30650 | "ERR219 - Assert statement within an assert statement is not allowed", 30651 | exprtk_error_location)); 30652 | 30653 | return error_node(); 30654 | } 30655 | 30656 | scoped_bool_negator sbn(state_.parsing_assert_stmt); 30657 | 30658 | next_token(); 30659 | 30660 | std::vector<expression_node_ptr> assert_arg_list(3, error_node()); 30661 | scoped_vec_delete<expression_node_t> svd((*this), assert_arg_list); 30662 | 30663 | expression_node_ptr& assert_condition = assert_arg_list[0]; 30664 | expression_node_ptr& assert_message = assert_arg_list[1]; 30665 | expression_node_ptr& assert_id = assert_arg_list[2]; 30666 | 30667 | if (!token_is(token_t::e_lbracket)) 30668 | { 30669 | set_error(make_error( 30670 | parser_error::e_syntax, 30671 | current_token(), 30672 | "ERR220 - Expected '(' at start of assert statement", 30673 | exprtk_error_location)); 30674 | 30675 | return error_node(); 30676 | } 30677 | 30678 | const token_t start_token = current_token(); 30679 | 30680 | // Parse the assert condition 30681 | if (0 == (assert_condition = parse_expression())) 30682 | { 30683 | set_error(make_error( 30684 | parser_error::e_syntax, 30685 | current_token(), 30686 | "ERR221 - Failed to parse condition for assert statement", 30687 | exprtk_error_location)); 30688 | 30689 | return error_node(); 30690 | } 30691 | 30692 | const token_t end_token = current_token(); 30693 | 30694 | if (!token_is(token_t::e_rbracket)) 30695 | { 30696 | if (!token_is(token_t::e_comma)) 30697 | { 30698 | set_error(make_error( 30699 | parser_error::e_syntax, 30700 | current_token(), 30701 | "ERR222 - Expected ',' between condition and message for assert statement", 30702 | exprtk_error_location)); 30703 | 30704 | return error_node(); 30705 | } 30706 | // Parse the assert message 30707 | else if ( 30708 | (0 == (assert_message = parse_expression())) || 30709 | !details::is_generally_string_node(assert_message) 30710 | ) 30711 | { 30712 | set_error(make_error( 30713 | parser_error::e_syntax, 30714 | current_token(), 30715 | "ERR223 - " + 30716 | (assert_message ? 30717 | std::string("Expected string for assert message") : 30718 | std::string("Failed to parse message for assert statement")), 30719 | exprtk_error_location)); 30720 | 30721 | return error_node(); 30722 | } 30723 | else if (!token_is(token_t::e_rbracket)) 30724 | { 30725 | if (!token_is(token_t::e_comma)) 30726 | { 30727 | set_error(make_error( 30728 | parser_error::e_syntax, 30729 | current_token(), 30730 | "ERR224 - Expected ',' between message and ID for assert statement", 30731 | exprtk_error_location)); 30732 | 30733 | return error_node(); 30734 | } 30735 | // Parse assert ID 30736 | else if ( 30737 | (0 == (assert_id = parse_expression())) || 30738 | !details::is_const_string_node(assert_id) 30739 | ) 30740 | { 30741 | set_error(make_error( 30742 | parser_error::e_syntax, 30743 | current_token(), 30744 | "ERR225 - " + 30745 | (assert_id ? 30746 | std::string("Expected literal string for assert ID") : 30747 | std::string("Failed to parse string for assert ID")), 30748 | exprtk_error_location)); 30749 | 30750 | return error_node(); 30751 | } 30752 | else if (!token_is(token_t::e_rbracket)) 30753 | { 30754 | set_error(make_error( 30755 | parser_error::e_syntax, 30756 | current_token(), 30757 | "ERR226 - Expected ')' at start of assert statement", 30758 | exprtk_error_location)); 30759 | 30760 | return error_node(); 30761 | } 30762 | } 30763 | } 30764 | 30765 | exprtk::assert_check::assert_context context; 30766 | context.condition = lexer().substr(start_token.position, end_token.position); 30767 | context.offet = start_token.position; 30768 | 30769 | if (0 == assert_check_) 30770 | { 30771 | exprtk_debug(("parse_assert_statement() - assert functionality is disabled. assert condition: %s\n", 30772 | context.condition.c_str())); 30773 | 30774 | return new details::null_node<T>(); 30775 | } 30776 | 30777 | #ifndef exprtk_disable_string_capabilities 30778 | if (assert_message && details::is_const_string_node(assert_message)) 30779 | { 30780 | context.message = dynamic_cast<details::string_base_node<T>*>(assert_message)->str(); 30781 | } 30782 | 30783 | if (assert_id && details::is_const_string_node(assert_id)) 30784 | { 30785 | context.id = dynamic_cast<details::string_base_node<T>*>(assert_id)->str(); 30786 | 30787 | if (assert_ids_.end() != assert_ids_.find(context.id)) 30788 | { 30789 | set_error(make_error( 30790 | parser_error::e_syntax, 30791 | current_token(), 30792 | "ERR227 - Duplicate assert ID: " + context.id, 30793 | exprtk_error_location)); 30794 | 30795 | return error_node(); 30796 | } 30797 | 30798 | assert_ids_.insert(context.id); 30799 | free_node(node_allocator_, assert_id); 30800 | } 30801 | #endif 30802 | 30803 | expression_node_ptr result_node = 30804 | expression_generator_.assert_call( 30805 | assert_condition, 30806 | assert_message, 30807 | context); 30808 | 30809 | exprtk_debug(("parse_assert_statement() - assert condition: [%s]\n", context.condition.c_str() )); 30810 | exprtk_debug(("parse_assert_statement() - assert message: [%s]\n", context.message .c_str() )); 30811 | exprtk_debug(("parse_assert_statement() - assert id: [%s]\n", context.id .c_str() )); 30812 | exprtk_debug(("parse_assert_statement() - assert offset: [%d]\n", static_cast<int>(context.offet))); 30813 | 30814 | if (0 == result_node) 30815 | { 30816 | set_error(make_error( 30817 | parser_error::e_syntax, 30818 | current_token(), 30819 | "ERR228 - Failed to synthesize assert", 30820 | exprtk_error_location)); 30821 | 30822 | return error_node(); 30823 | } 30824 | 30825 | svd.delete_ptr = false; 30826 | return result_node; 30827 | } 30828 | 30829 | inline bool post_variable_process(const std::string& symbol) 30830 | { 30831 | if ( 30832 | peek_token_is(token_t::e_lbracket ) || 30833 | peek_token_is(token_t::e_lcrlbracket) || 30834 | peek_token_is(token_t::e_lsqrbracket) 30835 | ) 30836 | { 30837 | if (!settings_.commutative_check_enabled()) 30838 | { 30839 | set_error(make_error( 30840 | parser_error::e_syntax, 30841 | current_token(), 30842 | "ERR229 - Invalid sequence of variable '" + symbol + "' and bracket", 30843 | exprtk_error_location)); 30844 | 30845 | return false; 30846 | } 30847 | 30848 | lexer().insert_front(token_t::e_mul); 30849 | } 30850 | 30851 | return true; 30852 | } 30853 | 30854 | inline bool post_bracket_process(const typename token_t::token_type& token, expression_node_ptr& branch) 30855 | { 30856 | bool implied_mul = false; 30857 | 30858 | if (details::is_generally_string_node(branch)) 30859 | return true; 30860 | 30861 | if (details::is_ivector_node(branch)) 30862 | return true; 30863 | 30864 | const lexer::parser_helper::token_advance_mode hold = prsrhlpr_t::e_hold; 30865 | 30866 | switch (token) 30867 | { 30868 | case token_t::e_lcrlbracket : implied_mul = token_is(token_t::e_lbracket , hold) || 30869 | token_is(token_t::e_lcrlbracket, hold) || 30870 | token_is(token_t::e_lsqrbracket, hold) ; 30871 | break; 30872 | 30873 | case token_t::e_lbracket : implied_mul = token_is(token_t::e_lbracket , hold) || 30874 | token_is(token_t::e_lcrlbracket, hold) || 30875 | token_is(token_t::e_lsqrbracket, hold) ; 30876 | break; 30877 | 30878 | case token_t::e_lsqrbracket : implied_mul = token_is(token_t::e_lbracket , hold) || 30879 | token_is(token_t::e_lcrlbracket, hold) || 30880 | token_is(token_t::e_lsqrbracket, hold) ; 30881 | break; 30882 | 30883 | default : return true; 30884 | } 30885 | 30886 | if (implied_mul) 30887 | { 30888 | if (!settings_.commutative_check_enabled()) 30889 | { 30890 | set_error(make_error( 30891 | parser_error::e_syntax, 30892 | current_token(), 30893 | "ERR230 - Invalid sequence of brackets", 30894 | exprtk_error_location)); 30895 | 30896 | return false; 30897 | } 30898 | else if (token_t::e_eof != current_token().type) 30899 | { 30900 | lexer().insert_front(current_token().type); 30901 | lexer().insert_front(token_t::e_mul); 30902 | next_token(); 30903 | } 30904 | } 30905 | 30906 | return true; 30907 | } 30908 | 30909 | typedef typename interval_container_t<const void*>::interval_t interval_t; 30910 | typedef interval_container_t<const void*> immutable_memory_map_t; 30911 | typedef std::map<interval_t,token_t> immutable_symtok_map_t; 30912 | 30913 | inline interval_t make_memory_range(const T& t) 30914 | { 30915 | const T* begin = reinterpret_cast<const T*>(&t); 30916 | const T* end = begin + 1; 30917 | return interval_t(begin, end); 30918 | } 30919 | 30920 | inline interval_t make_memory_range(const T* begin, const std::size_t size) 30921 | { 30922 | return interval_t(begin, begin + size); 30923 | } 30924 | 30925 | inline interval_t make_memory_range(details::char_cptr begin, const std::size_t size) 30926 | { 30927 | return interval_t(begin, begin + size); 30928 | } 30929 | 30930 | void lodge_immutable_symbol(const lexer::token& token, const interval_t interval) 30931 | { 30932 | immutable_memory_map_.add_interval(interval); 30933 | immutable_symtok_map_[interval] = token; 30934 | } 30935 | 30936 | inline expression_node_ptr parse_symtab_symbol() 30937 | { 30938 | const std::string symbol = current_token().value; 30939 | 30940 | // Are we dealing with a variable or a special constant? 30941 | typedef typename symtab_store::variable_context var_ctxt_t; 30942 | var_ctxt_t var_ctx = symtab_store_.get_variable_context(symbol); 30943 | 30944 | if (var_ctx.variable) 30945 | { 30946 | assert(var_ctx.symbol_table); 30947 | 30948 | expression_node_ptr result_variable = var_ctx.variable; 30949 | 30950 | if (symtab_store_.is_constant_node(symbol)) 30951 | { 30952 | result_variable = expression_generator_(var_ctx.variable->value()); 30953 | } 30954 | else if (symbol_table_t::e_immutable == var_ctx.symbol_table->mutability()) 30955 | { 30956 | lodge_immutable_symbol(current_token(), make_memory_range(var_ctx.variable->ref())); 30957 | result_variable = var_ctx.variable; 30958 | } 30959 | 30960 | if (!post_variable_process(symbol)) 30961 | return error_node(); 30962 | 30963 | lodge_symbol(symbol, e_st_variable); 30964 | 30965 | next_token(); 30966 | 30967 | return result_variable; 30968 | } 30969 | 30970 | // Are we dealing with a locally defined variable, vector or string? 30971 | if (!sem_.empty()) 30972 | { 30973 | scope_element& se = sem_.get_active_element(symbol); 30974 | 30975 | if (se.active && details::imatch(se.name, symbol)) 30976 | { 30977 | if ( 30978 | (scope_element::e_variable == se.type) || 30979 | (scope_element::e_literal == se.type) 30980 | ) 30981 | { 30982 | se.active = true; 30983 | lodge_symbol(symbol, e_st_local_variable); 30984 | 30985 | if (!post_variable_process(symbol)) 30986 | return error_node(); 30987 | 30988 | next_token(); 30989 | 30990 | return (scope_element::e_variable == se.type) ? 30991 | se.var_node : 30992 | expression_generator_(se.var_node->value()); 30993 | } 30994 | else if (scope_element::e_vector == se.type) 30995 | { 30996 | return parse_vector(); 30997 | } 30998 | #ifndef exprtk_disable_string_capabilities 30999 | else if (scope_element::e_string == se.type) 31000 | { 31001 | return parse_string(); 31002 | } 31003 | #endif 31004 | } 31005 | } 31006 | 31007 | #ifndef exprtk_disable_string_capabilities 31008 | // Are we dealing with a string variable? 31009 | if (symtab_store_.is_stringvar(symbol)) 31010 | { 31011 | return parse_string(); 31012 | } 31013 | #endif 31014 | 31015 | { 31016 | // Are we dealing with a function? 31017 | ifunction<T>* function = symtab_store_.get_function(symbol); 31018 | 31019 | if (function) 31020 | { 31021 | lodge_symbol(symbol, e_st_function); 31022 | 31023 | expression_node_ptr func_node = 31024 | parse_function_invocation(function,symbol); 31025 | 31026 | if (func_node) 31027 | return func_node; 31028 | else 31029 | { 31030 | set_error(make_error( 31031 | parser_error::e_syntax, 31032 | current_token(), 31033 | "ERR231 - Failed to generate node for function: '" + symbol + "'", 31034 | exprtk_error_location)); 31035 | 31036 | return error_node(); 31037 | } 31038 | } 31039 | } 31040 | 31041 | { 31042 | // Are we dealing with a vararg function? 31043 | ivararg_function<T>* vararg_function = symtab_store_.get_vararg_function(symbol); 31044 | 31045 | if (vararg_function) 31046 | { 31047 | lodge_symbol(symbol, e_st_function); 31048 | 31049 | expression_node_ptr vararg_func_node = 31050 | parse_vararg_function_call(vararg_function, symbol); 31051 | 31052 | if (vararg_func_node) 31053 | return vararg_func_node; 31054 | else 31055 | { 31056 | set_error(make_error( 31057 | parser_error::e_syntax, 31058 | current_token(), 31059 | "ERR232 - Failed to generate node for vararg function: '" + symbol + "'", 31060 | exprtk_error_location)); 31061 | 31062 | return error_node(); 31063 | } 31064 | } 31065 | } 31066 | 31067 | { 31068 | // Are we dealing with a vararg generic function? 31069 | igeneric_function<T>* generic_function = symtab_store_.get_generic_function(symbol); 31070 | 31071 | if (generic_function) 31072 | { 31073 | lodge_symbol(symbol, e_st_function); 31074 | 31075 | expression_node_ptr genericfunc_node = 31076 | parse_generic_function_call(generic_function, symbol); 31077 | 31078 | if (genericfunc_node) 31079 | return genericfunc_node; 31080 | else 31081 | { 31082 | set_error(make_error( 31083 | parser_error::e_syntax, 31084 | current_token(), 31085 | "ERR233 - Failed to generate node for generic function: '" + symbol + "'", 31086 | exprtk_error_location)); 31087 | 31088 | return error_node(); 31089 | } 31090 | } 31091 | } 31092 | 31093 | #ifndef exprtk_disable_string_capabilities 31094 | { 31095 | // Are we dealing with a vararg string returning function? 31096 | igeneric_function<T>* string_function = symtab_store_.get_string_function(symbol); 31097 | 31098 | if (string_function) 31099 | { 31100 | lodge_symbol(symbol, e_st_function); 31101 | 31102 | expression_node_ptr stringfunc_node = 31103 | parse_string_function_call(string_function, symbol); 31104 | 31105 | if (stringfunc_node) 31106 | return stringfunc_node; 31107 | else 31108 | { 31109 | set_error(make_error( 31110 | parser_error::e_syntax, 31111 | current_token(), 31112 | "ERR234 - Failed to generate node for string function: '" + symbol + "'", 31113 | exprtk_error_location)); 31114 | 31115 | return error_node(); 31116 | } 31117 | } 31118 | } 31119 | 31120 | { 31121 | // Are we dealing with a vararg overloaded scalar/string returning function? 31122 | igeneric_function<T>* overload_function = symtab_store_.get_overload_function(symbol); 31123 | 31124 | if (overload_function) 31125 | { 31126 | lodge_symbol(symbol, e_st_function); 31127 | 31128 | expression_node_ptr overloadfunc_node = 31129 | parse_overload_function_call(overload_function, symbol); 31130 | 31131 | if (overloadfunc_node) 31132 | return overloadfunc_node; 31133 | else 31134 | { 31135 | set_error(make_error( 31136 | parser_error::e_syntax, 31137 | current_token(), 31138 | "ERR235 - Failed to generate node for overload function: '" + symbol + "'", 31139 | exprtk_error_location)); 31140 | 31141 | return error_node(); 31142 | } 31143 | } 31144 | } 31145 | #endif 31146 | 31147 | // Are we dealing with a vector? 31148 | if (symtab_store_.is_vector(symbol)) 31149 | { 31150 | lodge_symbol(symbol, e_st_vector); 31151 | return parse_vector(); 31152 | } 31153 | 31154 | if (details::is_reserved_symbol(symbol)) 31155 | { 31156 | if ( 31157 | settings_.function_enabled(symbol) || 31158 | !details::is_base_function(symbol) 31159 | ) 31160 | { 31161 | set_error(make_error( 31162 | parser_error::e_syntax, 31163 | current_token(), 31164 | "ERR236 - Invalid use of reserved symbol '" + symbol + "'", 31165 | exprtk_error_location)); 31166 | 31167 | return error_node(); 31168 | } 31169 | } 31170 | 31171 | // Should we handle unknown symbols? 31172 | if (resolve_unknown_symbol_ && unknown_symbol_resolver_) 31173 | { 31174 | if (!(settings_.rsrvd_sym_usr_disabled() && details::is_reserved_symbol(symbol))) 31175 | { 31176 | symbol_table_t& symtab = symtab_store_.get_symbol_table(); 31177 | 31178 | std::string error_message; 31179 | 31180 | if (unknown_symbol_resolver::e_usrmode_default == unknown_symbol_resolver_->mode) 31181 | { 31182 | T default_value = T(0); 31183 | 31184 | typename unknown_symbol_resolver::usr_symbol_type usr_symbol_type = unknown_symbol_resolver::e_usr_unknown_type; 31185 | 31186 | if (unknown_symbol_resolver_->process(symbol, usr_symbol_type, default_value, error_message)) 31187 | { 31188 | bool create_result = false; 31189 | 31190 | switch (usr_symbol_type) 31191 | { 31192 | case unknown_symbol_resolver::e_usr_variable_type : 31193 | create_result = symtab.create_variable(symbol, default_value); 31194 | break; 31195 | 31196 | case unknown_symbol_resolver::e_usr_constant_type : 31197 | create_result = symtab.add_constant(symbol, default_value); 31198 | break; 31199 | 31200 | default : create_result = false; 31201 | } 31202 | 31203 | if (create_result) 31204 | { 31205 | expression_node_ptr var = symtab_store_.get_variable(symbol); 31206 | 31207 | if (var) 31208 | { 31209 | if (symtab_store_.is_constant_node(symbol)) 31210 | { 31211 | var = expression_generator_(var->value()); 31212 | } 31213 | 31214 | lodge_symbol(symbol, e_st_variable); 31215 | 31216 | if (!post_variable_process(symbol)) 31217 | return error_node(); 31218 | 31219 | next_token(); 31220 | 31221 | return var; 31222 | } 31223 | } 31224 | } 31225 | 31226 | set_error(make_error( 31227 | parser_error::e_symtab, 31228 | current_token(), 31229 | "ERR237 - Failed to create variable: '" + symbol + "'" + 31230 | (error_message.empty() ? "" : " - " + error_message), 31231 | exprtk_error_location)); 31232 | 31233 | } 31234 | else if (unknown_symbol_resolver::e_usrmode_extended == unknown_symbol_resolver_->mode) 31235 | { 31236 | if (unknown_symbol_resolver_->process(symbol, symtab, error_message)) 31237 | { 31238 | expression_node_ptr result = parse_symtab_symbol(); 31239 | 31240 | if (result) 31241 | { 31242 | return result; 31243 | } 31244 | } 31245 | 31246 | set_error(make_error( 31247 | parser_error::e_symtab, 31248 | current_token(), 31249 | "ERR238 - Failed to resolve symbol: '" + symbol + "'" + 31250 | (error_message.empty() ? "" : " - " + error_message), 31251 | exprtk_error_location)); 31252 | } 31253 | 31254 | return error_node(); 31255 | } 31256 | } 31257 | 31258 | set_error(make_error( 31259 | parser_error::e_syntax, 31260 | current_token(), 31261 | "ERR239 - Undefined symbol: '" + symbol + "'", 31262 | exprtk_error_location)); 31263 | 31264 | return error_node(); 31265 | } 31266 | 31267 | inline expression_node_ptr check_block_statement_closure(expression_node_ptr expression) 31268 | { 31269 | if ( 31270 | expression && 31271 | ( 31272 | (current_token().type == token_t::e_symbol) || 31273 | (current_token().type == token_t::e_number) 31274 | ) 31275 | ) 31276 | { 31277 | free_node(node_allocator_, expression); 31278 | 31279 | set_error(make_error( 31280 | parser_error::e_syntax, 31281 | current_token(), 31282 | "ERR240 - Invalid syntax '" + current_token().value + "' possible missing operator or context", 31283 | exprtk_error_location)); 31284 | 31285 | return error_node(); 31286 | } 31287 | 31288 | return expression; 31289 | } 31290 | 31291 | inline expression_node_ptr parse_symbol() 31292 | { 31293 | static const std::string symbol_if = "if" ; 31294 | static const std::string symbol_while = "while" ; 31295 | static const std::string symbol_repeat = "repeat" ; 31296 | static const std::string symbol_for = "for" ; 31297 | static const std::string symbol_switch = "switch" ; 31298 | static const std::string symbol_null = "null" ; 31299 | static const std::string symbol_break = "break" ; 31300 | static const std::string symbol_continue = "continue" 31301 | static const std::string symbol_var = "var" ; 31302 | static const std::string symbol_const = "const" ; 31303 | static const std::string symbol_swap = "swap" ; 31304 | static const std::string symbol_return = "return" ; 31305 | static const std::string symbol_not = "not" ; 31306 | static const std::string symbol_assert = "assert" ; 31307 | 31308 | const std::string symbol = current_token().value; 31309 | 31310 | if (valid_vararg_operation(symbol)) 31311 | { 31312 | return parse_vararg_function(); 31313 | } 31314 | else if (details::imatch(symbol, symbol_not)) 31315 | { 31316 | return parse_not_statement(); 31317 | } 31318 | else if (valid_base_operation(symbol)) 31319 | { 31320 | return parse_base_operation(); 31321 | } 31322 | else if ( 31323 | details::imatch(symbol, symbol_if) && 31324 | settings_.control_struct_enabled(symbol) 31325 | ) 31326 | { 31327 | return parse_conditional_statement(); 31328 | } 31329 | else if ( 31330 | details::imatch(symbol, symbol_while) && 31331 | settings_.control_struct_enabled(symbol) 31332 | ) 31333 | { 31334 | return check_block_statement_closure(parse_while_loop()); 31335 | } 31336 | else if ( 31337 | details::imatch(symbol, symbol_repeat) && 31338 | settings_.control_struct_enabled(symbol) 31339 | ) 31340 | { 31341 | return check_block_statement_closure(parse_repeat_until_loop()); 31342 | } 31343 | else if ( 31344 | details::imatch(symbol, symbol_for) && 31345 | settings_.control_struct_enabled(symbol) 31346 | ) 31347 | { 31348 | return check_block_statement_closure(parse_for_loop()); 31349 | } 31350 | else if ( 31351 | details::imatch(symbol, symbol_switch) && 31352 | settings_.control_struct_enabled(symbol) 31353 | ) 31354 | { 31355 | return check_block_statement_closure(parse_switch_statement()); 31356 | } 31357 | else if (details::is_valid_sf_symbol(symbol)) 31358 | { 31359 | return parse_special_function(); 31360 | } 31361 | else if (details::imatch(symbol, symbol_null)) 31362 | { 31363 | return parse_null_statement(); 31364 | } 31365 | #ifndef exprtk_disable_break_continue 31366 | else if (details::imatch(symbol, symbol_break)) 31367 | { 31368 | return parse_break_statement(); 31369 | } 31370 | else if (details::imatch(symbol, symbol_continue)) 31371 | { 31372 | return parse_continue_statement(); 31373 | } 31374 | #endif 31375 | else if (details::imatch(symbol, symbol_var)) 31376 | { 31377 | return parse_define_var_statement(); 31378 | } 31379 | else if (details::imatch(symbol, symbol_const)) 31380 | { 31381 | return parse_define_constvar_statement(); 31382 | } 31383 | else if (details::imatch(symbol, symbol_swap)) 31384 | { 31385 | return parse_swap_statement(); 31386 | } 31387 | #ifndef exprtk_disable_return_statement 31388 | else if ( 31389 | details::imatch(symbol, symbol_return) && 31390 | settings_.control_struct_enabled(symbol) 31391 | ) 31392 | { 31393 | return check_block_statement_closure(parse_return_statement()); 31394 | } 31395 | #endif 31396 | else if (details::imatch(symbol, symbol_assert)) 31397 | { 31398 | return parse_assert_statement(); 31399 | } 31400 | else if (symtab_store_.valid() || !sem_.empty()) 31401 | { 31402 | return parse_symtab_symbol(); 31403 | } 31404 | else 31405 | { 31406 | set_error(make_error( 31407 | parser_error::e_symtab, 31408 | current_token(), 31409 | "ERR241 - Unknown variable or function encountered. Symbol table(s) " 31410 | "is either invalid or does not contain symbol: '" + symbol + "'", 31411 | exprtk_error_location)); 31412 | 31413 | return error_node(); 31414 | } 31415 | } 31416 | 31417 | inline expression_node_ptr parse_branch(precedence_level precedence = e_level00) 31418 | { 31419 | stack_limit_handler slh(*this); 31420 | 31421 | if (!slh) 31422 | { 31423 | return error_node(); 31424 | } 31425 | 31426 | expression_node_ptr branch = error_node(); 31427 | 31428 | if (token_t::e_number == current_token().type) 31429 | { 31430 | T numeric_value = T(0); 31431 | 31432 | if (details::string_to_real(current_token().value, numeric_value)) 31433 | { 31434 | expression_node_ptr literal_exp = expression_generator_(numeric_value); 31435 | 31436 | if (0 == literal_exp) 31437 | { 31438 | set_error(make_error( 31439 | parser_error::e_numeric, 31440 | current_token(), 31441 | "ERR242 - Failed generate node for scalar: '" + current_token().value + "'", 31442 | exprtk_error_location)); 31443 | 31444 | return error_node(); 31445 | } 31446 | 31447 | next_token(); 31448 | branch = literal_exp; 31449 | } 31450 | else 31451 | { 31452 | set_error(make_error( 31453 | parser_error::e_numeric, 31454 | current_token(), 31455 | "ERR243 - Failed to convert '" + current_token().value + "' to a number", 31456 | exprtk_error_location)); 31457 | 31458 | return error_node(); 31459 | } 31460 | } 31461 | else if (token_t::e_symbol == current_token().type) 31462 | { 31463 | branch = parse_symbol(); 31464 | } 31465 | #ifndef exprtk_disable_string_capabilities 31466 | else if (token_t::e_string == current_token().type) 31467 | { 31468 | branch = parse_const_string(); 31469 | } 31470 | #endif 31471 | else if (token_t::e_lbracket == current_token().type) 31472 | { 31473 | next_token(); 31474 | 31475 | if (0 == (branch = parse_expression())) 31476 | { 31477 | return error_node(); 31478 | } 31479 | 31480 | token_is(token_t::e_eof); 31481 | 31482 | if (!token_is(token_t::e_rbracket)) 31483 | { 31484 | set_error(make_error( 31485 | parser_error::e_syntax, 31486 | current_token(), 31487 | "ERR244 - Expected ')' instead of: '" + current_token().value + "'", 31488 | exprtk_error_location)); 31489 | 31490 | details::free_node(node_allocator_, branch); 31491 | 31492 | return error_node(); 31493 | } 31494 | else if (!post_bracket_process(token_t::e_lbracket,branch)) 31495 | { 31496 | details::free_node(node_allocator_, branch); 31497 | 31498 | return error_node(); 31499 | } 31500 | 31501 | parse_pending_vector_index_operator(branch); 31502 | } 31503 | else if (token_t::e_lsqrbracket == current_token().type) 31504 | { 31505 | next_token(); 31506 | 31507 | if (0 == (branch = parse_expression())) 31508 | return error_node(); 31509 | else if (!token_is(token_t::e_rsqrbracket)) 31510 | { 31511 | set_error(make_error( 31512 | parser_error::e_syntax, 31513 | current_token(), 31514 | "ERR245 - Expected ']' instead of: '" + current_token().value + "'", 31515 | exprtk_error_location)); 31516 | 31517 | details::free_node(node_allocator_, branch); 31518 | 31519 | return error_node(); 31520 | } 31521 | else if (!post_bracket_process(token_t::e_lsqrbracket,branch)) 31522 | { 31523 | details::free_node(node_allocator_, branch); 31524 | 31525 | return error_node(); 31526 | } 31527 | } 31528 | else if (token_t::e_lcrlbracket == current_token().type) 31529 | { 31530 | next_token(); 31531 | 31532 | if (0 == (branch = parse_expression())) 31533 | return error_node(); 31534 | else if (!token_is(token_t::e_rcrlbracket)) 31535 | { 31536 | set_error(make_error( 31537 | parser_error::e_syntax, 31538 | current_token(), 31539 | "ERR246 - Expected '}' instead of: '" + current_token().value + "'", 31540 | exprtk_error_location)); 31541 | 31542 | details::free_node(node_allocator_, branch); 31543 | 31544 | return error_node(); 31545 | } 31546 | else if (!post_bracket_process(token_t::e_lcrlbracket,branch)) 31547 | { 31548 | details::free_node(node_allocator_, branch); 31549 | 31550 | return error_node(); 31551 | } 31552 | } 31553 | else if (token_t::e_sub == current_token().type) 31554 | { 31555 | next_token(); 31556 | branch = parse_expression(e_level11); 31557 | 31558 | if ( 31559 | branch && 31560 | !( 31561 | details::is_neg_unary_node (branch) && 31562 | simplify_unary_negation_branch(branch) 31563 | ) 31564 | ) 31565 | { 31566 | expression_node_ptr result = expression_generator_(details::e_neg,branch); 31567 | 31568 | if (0 == result) 31569 | { 31570 | details::free_node(node_allocator_, branch); 31571 | 31572 | return error_node(); 31573 | } 31574 | else 31575 | branch = result; 31576 | } 31577 | } 31578 | else if (token_t::e_add == current_token().type) 31579 | { 31580 | next_token(); 31581 | branch = parse_expression(e_level13); 31582 | } 31583 | else if (token_t::e_eof == current_token().type) 31584 | { 31585 | set_error(make_error( 31586 | parser_error::e_syntax, 31587 | current_token(), 31588 | "ERR247 - Premature end of expression[1]", 31589 | exprtk_error_location)); 31590 | 31591 | return error_node(); 31592 | } 31593 | else 31594 | { 31595 | set_error(make_error( 31596 | parser_error::e_syntax, 31597 | current_token(), 31598 | "ERR248 - Premature end of expression[2]", 31599 | exprtk_error_location)); 31600 | 31601 | return error_node(); 31602 | } 31603 | 31604 | if ( 31605 | branch && 31606 | (e_level00 == precedence) && 31607 | token_is(token_t::e_ternary,prsrhlpr_t::e_hold) 31608 | ) 31609 | { 31610 | branch = parse_ternary_conditional_statement(branch); 31611 | } 31612 | 31613 | parse_pending_string_rangesize(branch); 31614 | 31615 | return branch; 31616 | } 31617 | 31618 | template <typename Type> 31619 | class expression_generator 31620 | { 31621 | public: 31622 | 31623 | typedef details::expression_node<Type>* expression_node_ptr; 31624 | typedef expression_node_ptr (*synthesize_functor_t)(expression_generator<T>&, const details::operator_type& operation, expression_node_ptr (&branch)[2]); 31625 | typedef std::map<std::string,synthesize_functor_t> synthesize_map_t; 31626 | typedef typename exprtk::parser<Type> parser_t; 31627 | typedef const Type& vtype; 31628 | typedef const Type ctype; 31629 | 31630 | inline void init_synthesize_map() 31631 | { 31632 | #ifndef exprtk_disable_enhanced_features 31633 | synthesize_map_["(v)o(v)"] = synthesize_vov_expression::process; 31634 | synthesize_map_["(c)o(v)"] = synthesize_cov_expression::process; 31635 | synthesize_map_["(v)o(c)"] = synthesize_voc_expression::process; 31636 | 31637 | #define register_synthezier(S) \ 31638 | synthesize_map_[S ::node_type::id()] = S ::process; \ 31639 | 31640 | register_synthezier(synthesize_vovov_expression0) 31641 | register_synthezier(synthesize_vovov_expression1) 31642 | register_synthezier(synthesize_vovoc_expression0) 31643 | register_synthezier(synthesize_vovoc_expression1) 31644 | register_synthezier(synthesize_vocov_expression0) 31645 | register_synthezier(synthesize_vocov_expression1) 31646 | register_synthezier(synthesize_covov_expression0) 31647 | register_synthezier(synthesize_covov_expression1) 31648 | register_synthezier(synthesize_covoc_expression0) 31649 | register_synthezier(synthesize_covoc_expression1) 31650 | register_synthezier(synthesize_cocov_expression1) 31651 | register_synthezier(synthesize_vococ_expression0) 31652 | 31653 | register_synthezier(synthesize_vovovov_expression0) 31654 | register_synthezier(synthesize_vovovoc_expression0) 31655 | register_synthezier(synthesize_vovocov_expression0) 31656 | register_synthezier(synthesize_vocovov_expression0) 31657 | register_synthezier(synthesize_covovov_expression0) 31658 | register_synthezier(synthesize_covocov_expression0) 31659 | register_synthezier(synthesize_vocovoc_expression0) 31660 | register_synthezier(synthesize_covovoc_expression0) 31661 | register_synthezier(synthesize_vococov_expression0) 31662 | 31663 | register_synthezier(synthesize_vovovov_expression1) 31664 | register_synthezier(synthesize_vovovoc_expression1) 31665 | register_synthezier(synthesize_vovocov_expression1) 31666 | register_synthezier(synthesize_vocovov_expression1) 31667 | register_synthezier(synthesize_covovov_expression1) 31668 | register_synthezier(synthesize_covocov_expression1) 31669 | register_synthezier(synthesize_vocovoc_expression1) 31670 | register_synthezier(synthesize_covovoc_expression1) 31671 | register_synthezier(synthesize_vococov_expression1) 31672 | 31673 | register_synthezier(synthesize_vovovov_expression2) 31674 | register_synthezier(synthesize_vovovoc_expression2) 31675 | register_synthezier(synthesize_vovocov_expression2) 31676 | register_synthezier(synthesize_vocovov_expression2) 31677 | register_synthezier(synthesize_covovov_expression2) 31678 | register_synthezier(synthesize_covocov_expression2) 31679 | register_synthezier(synthesize_vocovoc_expression2) 31680 | register_synthezier(synthesize_covovoc_expression2) 31681 | 31682 | register_synthezier(synthesize_vovovov_expression3) 31683 | register_synthezier(synthesize_vovovoc_expression3) 31684 | register_synthezier(synthesize_vovocov_expression3) 31685 | register_synthezier(synthesize_vocovov_expression3) 31686 | register_synthezier(synthesize_covovov_expression3) 31687 | register_synthezier(synthesize_covocov_expression3) 31688 | register_synthezier(synthesize_vocovoc_expression3) 31689 | register_synthezier(synthesize_covovoc_expression3) 31690 | register_synthezier(synthesize_vococov_expression3) 31691 | 31692 | register_synthezier(synthesize_vovovov_expression4) 31693 | register_synthezier(synthesize_vovovoc_expression4) 31694 | register_synthezier(synthesize_vovocov_expression4) 31695 | register_synthezier(synthesize_vocovov_expression4) 31696 | register_synthezier(synthesize_covovov_expression4) 31697 | register_synthezier(synthesize_covocov_expression4) 31698 | register_synthezier(synthesize_vocovoc_expression4) 31699 | register_synthezier(synthesize_covovoc_expression4) 31700 | 31701 | #undef register_synthezier 31702 | #endif 31703 | } 31704 | 31705 | inline void set_parser(parser_t& p) 31706 | { 31707 | parser_ = &p; 31708 | } 31709 | 31710 | inline void set_uom(unary_op_map_t& unary_op_map) 31711 | { 31712 | unary_op_map_ = &unary_op_map; 31713 | } 31714 | 31715 | inline void set_bom(binary_op_map_t& binary_op_map) 31716 | { 31717 | binary_op_map_ = &binary_op_map; 31718 | } 31719 | 31720 | inline void set_ibom(inv_binary_op_map_t& inv_binary_op_map) 31721 | { 31722 | inv_binary_op_map_ = &inv_binary_op_map; 31723 | } 31724 | 31725 | inline void set_sf3m(sf3_map_t& sf3_map) 31726 | { 31727 | sf3_map_ = &sf3_map; 31728 | } 31729 | 31730 | inline void set_sf4m(sf4_map_t& sf4_map) 31731 | { 31732 | sf4_map_ = &sf4_map; 31733 | } 31734 | 31735 | inline void set_allocator(details::node_allocator& na) 31736 | { 31737 | node_allocator_ = &na; 31738 | } 31739 | 31740 | inline void set_strength_reduction_state(const bool enabled) 31741 | { 31742 | strength_reduction_enabled_ = enabled; 31743 | } 31744 | 31745 | inline bool strength_reduction_enabled() const 31746 | { 31747 | return strength_reduction_enabled_; 31748 | } 31749 | 31750 | inline bool valid_operator(const details::operator_type& operation, binary_functor_t& bop) 31751 | { 31752 | typename binary_op_map_t::iterator bop_itr = binary_op_map_->find(operation); 31753 | 31754 | if (binary_op_map_->end() == bop_itr) 31755 | return false; 31756 | 31757 | bop = bop_itr->second; 31758 | 31759 | return true; 31760 | } 31761 | 31762 | inline bool valid_operator(const details::operator_type& operation, unary_functor_t& uop) 31763 | { 31764 | typename unary_op_map_t::iterator uop_itr = unary_op_map_->find(operation); 31765 | 31766 | if ((*unary_op_map_).end() == uop_itr) 31767 | return false; 31768 | 31769 | uop = uop_itr->second; 31770 | 31771 | return true; 31772 | } 31773 | 31774 | inline details::operator_type get_operator(const binary_functor_t& bop) const 31775 | { 31776 | return (*inv_binary_op_map_).find(bop)->second; 31777 | } 31778 | 31779 | inline expression_node_ptr operator() (const Type& v) const 31780 | { 31781 | return node_allocator_->allocate<literal_node_t>(v); 31782 | } 31783 | 31784 | #ifndef exprtk_disable_string_capabilities 31785 | inline expression_node_ptr operator() (const std::string& s) const 31786 | { 31787 | return node_allocator_->allocate<string_literal_node_t>(s); 31788 | } 31789 | 31790 | inline expression_node_ptr operator() (std::string& s, range_t& rp) const 31791 | { 31792 | return node_allocator_->allocate_rr<string_range_node_t>(s,rp); 31793 | } 31794 | 31795 | inline expression_node_ptr operator() (const std::string& s, range_t& rp) const 31796 | { 31797 | return node_allocator_->allocate_tt<const_string_range_node_t>(s,rp); 31798 | } 31799 | 31800 | inline expression_node_ptr operator() (expression_node_ptr branch, range_t& rp) const 31801 | { 31802 | if (is_generally_string_node(branch)) 31803 | return node_allocator_->allocate_tt<generic_string_range_node_t>(branch,rp); 31804 | else 31805 | return error_node(); 31806 | } 31807 | #endif 31808 | 31809 | inline bool unary_optimisable(const details::operator_type& operation) const 31810 | { 31811 | return (details::e_abs == operation) || (details::e_acos == operation) || 31812 | (details::e_acosh == operation) || (details::e_asin == operation) || 31813 | (details::e_asinh == operation) || (details::e_atan == operation) || 31814 | (details::e_atanh == operation) || (details::e_ceil == operation) || 31815 | (details::e_cos == operation) || (details::e_cosh == operation) || 31816 | (details::e_exp == operation) || (details::e_expm1 == operation) || 31817 | (details::e_floor == operation) || (details::e_log == operation) || 31818 | (details::e_log10 == operation) || (details::e_log2 == operation) || 31819 | (details::e_log1p == operation) || (details::e_neg == operation) || 31820 | (details::e_pos == operation) || (details::e_round == operation) || 31821 | (details::e_sin == operation) || (details::e_sinc == operation) || 31822 | (details::e_sinh == operation) || (details::e_sqrt == operation) || 31823 | (details::e_tan == operation) || (details::e_tanh == operation) || 31824 | (details::e_cot == operation) || (details::e_sec == operation) || 31825 | (details::e_csc == operation) || (details::e_r2d == operation) || 31826 | (details::e_d2r == operation) || (details::e_d2g == operation) || 31827 | (details::e_g2d == operation) || (details::e_notl == operation) || 31828 | (details::e_sgn == operation) || (details::e_erf == operation) || 31829 | (details::e_erfc == operation) || (details::e_ncdf == operation) || 31830 | (details::e_frac == operation) || (details::e_trunc == operation) ; 31831 | } 31832 | 31833 | inline bool sf3_optimisable(const std::string& sf3id, trinary_functor_t& tfunc) const 31834 | { 31835 | typename sf3_map_t::const_iterator itr = sf3_map_->find(sf3id); 31836 | 31837 | if (sf3_map_->end() == itr) 31838 | return false; 31839 | else 31840 | tfunc = itr->second.first; 31841 | 31842 | return true; 31843 | } 31844 | 31845 | inline bool sf4_optimisable(const std::string& sf4id, quaternary_functor_t& qfunc) const 31846 | { 31847 | typename sf4_map_t::const_iterator itr = sf4_map_->find(sf4id); 31848 | 31849 | if (sf4_map_->end() == itr) 31850 | return false; 31851 | else 31852 | qfunc = itr->second.first; 31853 | 31854 | return true; 31855 | } 31856 | 31857 | inline bool sf3_optimisable(const std::string& sf3id, details::operator_type& operation) const 31858 | { 31859 | typename sf3_map_t::const_iterator itr = sf3_map_->find(sf3id); 31860 | 31861 | if (sf3_map_->end() == itr) 31862 | return false; 31863 | else 31864 | operation = itr->second.second; 31865 | 31866 | return true; 31867 | } 31868 | 31869 | inline bool sf4_optimisable(const std::string& sf4id, details::operator_type& operation) const 31870 | { 31871 | typename sf4_map_t::const_iterator itr = sf4_map_->find(sf4id); 31872 | 31873 | if (sf4_map_->end() == itr) 31874 | return false; 31875 | else 31876 | operation = itr->second.second; 31877 | 31878 | return true; 31879 | } 31880 | 31881 | inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[1]) 31882 | { 31883 | if (0 == branch[0]) 31884 | { 31885 | return error_node(); 31886 | } 31887 | else if (details::is_null_node(branch[0])) 31888 | { 31889 | return branch[0]; 31890 | } 31891 | else if (details::is_break_node(branch[0])) 31892 | { 31893 | return error_node(); 31894 | } 31895 | else if (details::is_continue_node(branch[0])) 31896 | { 31897 | return error_node(); 31898 | } 31899 | else if (details::is_constant_node(branch[0])) 31900 | { 31901 | return synthesize_expression<unary_node_t,1>(operation,branch); 31902 | } 31903 | else if (unary_optimisable(operation) && details::is_variable_node(branch[0])) 31904 | { 31905 | return synthesize_uv_expression(operation,branch); 31906 | } 31907 | else if (unary_optimisable(operation) && details::is_ivector_node(branch[0])) 31908 | { 31909 | return synthesize_uvec_expression(operation,branch); 31910 | } 31911 | else 31912 | return synthesize_unary_expression(operation,branch); 31913 | } 31914 | 31915 | inline bool is_assignment_operation(const details::operator_type& operation) const 31916 | { 31917 | return ( 31918 | (details::e_addass == operation) || 31919 | (details::e_subass == operation) || 31920 | (details::e_mulass == operation) || 31921 | (details::e_divass == operation) || 31922 | (details::e_modass == operation) 31923 | ) && 31924 | parser_->settings_.assignment_enabled(operation); 31925 | } 31926 | 31927 | #ifndef exprtk_disable_string_capabilities 31928 | inline bool valid_string_operation(const details::operator_type& operation) const 31929 | { 31930 | return (details::e_add == operation) || 31931 | (details::e_lt == operation) || 31932 | (details::e_lte == operation) || 31933 | (details::e_gt == operation) || 31934 | (details::e_gte == operation) || 31935 | (details::e_eq == operation) || 31936 | (details::e_ne == operation) || 31937 | (details::e_in == operation) || 31938 | (details::e_like == operation) || 31939 | (details::e_ilike == operation) || 31940 | (details::e_assign == operation) || 31941 | (details::e_addass == operation) || 31942 | (details::e_swap == operation) ; 31943 | } 31944 | #else 31945 | inline bool valid_string_operation(const details::operator_type&) const 31946 | { 31947 | return false; 31948 | } 31949 | #endif 31950 | 31951 | inline std::string to_str(const details::operator_type& operation) const 31952 | { 31953 | switch (operation) 31954 | { 31955 | case details::e_add : return "+" ; 31956 | case details::e_sub : return "-" ; 31957 | case details::e_mul : return "*" ; 31958 | case details::e_div : return "/" ; 31959 | case details::e_mod : return "%" ; 31960 | case details::e_pow : return "^" ; 31961 | case details::e_lt : return "<" ; 31962 | case details::e_lte : return "<=" ; 31963 | case details::e_gt : return ">" ; 31964 | case details::e_gte : return ">=" ; 31965 | case details::e_eq : return "==" ; 31966 | case details::e_ne : return "!=" ; 31967 | case details::e_and : return "and" ; 31968 | case details::e_nand : return "nand" ; 31969 | case details::e_or : return "or" ; 31970 | case details::e_nor : return "nor" ; 31971 | case details::e_xor : return "xor" ; 31972 | case details::e_xnor : return "xnor" ; 31973 | default : return "UNKNOWN" 31974 | } 31975 | } 31976 | 31977 | inline bool operation_optimisable(const details::operator_type& operation) const 31978 | { 31979 | return (details::e_add == operation) || 31980 | (details::e_sub == operation) || 31981 | (details::e_mul == operation) || 31982 | (details::e_div == operation) || 31983 | (details::e_mod == operation) || 31984 | (details::e_pow == operation) || 31985 | (details::e_lt == operation) || 31986 | (details::e_lte == operation) || 31987 | (details::e_gt == operation) || 31988 | (details::e_gte == operation) || 31989 | (details::e_eq == operation) || 31990 | (details::e_ne == operation) || 31991 | (details::e_and == operation) || 31992 | (details::e_nand == operation) || 31993 | (details::e_or == operation) || 31994 | (details::e_nor == operation) || 31995 | (details::e_xor == operation) || 31996 | (details::e_xnor == operation) ; 31997 | } 31998 | 31999 | inline std::string branch_to_id(expression_node_ptr branch) const 32000 | { 32001 | static const std::string null_str ("(null)" ); 32002 | static const std::string const_str ("(c)" ); 32003 | static const std::string var_str ("(v)" ); 32004 | static const std::string vov_str ("(vov)" ); 32005 | static const std::string cov_str ("(cov)" ); 32006 | static const std::string voc_str ("(voc)" ); 32007 | static const std::string str_str ("(s)" ); 32008 | static const std::string strrng_str ("(rngs)" ); 32009 | static const std::string cs_str ("(cs)" ); 32010 | static const std::string cstrrng_str("(crngs)"); 32011 | 32012 | if (details::is_null_node(branch)) 32013 | return null_str; 32014 | else if (details::is_constant_node(branch)) 32015 | return const_str; 32016 | else if (details::is_variable_node(branch)) 32017 | return var_str; 32018 | else if (details::is_vov_node(branch)) 32019 | return vov_str; 32020 | else if (details::is_cov_node(branch)) 32021 | return cov_str; 32022 | else if (details::is_voc_node(branch)) 32023 | return voc_str; 32024 | else if (details::is_string_node(branch)) 32025 | return str_str; 32026 | else if (details::is_const_string_node(branch)) 32027 | return cs_str; 32028 | else if (details::is_string_range_node(branch)) 32029 | return strrng_str; 32030 | else if (details::is_const_string_range_node(branch)) 32031 | return cstrrng_str; 32032 | else if (details::is_t0ot1ot2_node(branch)) 32033 | return "(" + dynamic_cast<details::T0oT1oT2_base_node<T>*>(branch)->type_id() + ")" 32034 | else if (details::is_t0ot1ot2ot3_node(branch)) 32035 | return "(" + dynamic_cast<details::T0oT1oT2oT3_base_node<T>*>(branch)->type_id() + ")" 32036 | else 32037 | return "ERROR" 32038 | } 32039 | 32040 | inline std::string branch_to_id(expression_node_ptr (&branch)[2]) const 32041 | { 32042 | return branch_to_id(branch[0]) + std::string("o") + branch_to_id(branch[1]); 32043 | } 32044 | 32045 | inline bool cov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32046 | { 32047 | if (!operation_optimisable(operation)) 32048 | return false; 32049 | else 32050 | return details::is_constant_node(branch[0]) && 32051 | details::is_variable_node(branch[1]) ; 32052 | } 32053 | 32054 | inline bool voc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32055 | { 32056 | if (!operation_optimisable(operation)) 32057 | return false; 32058 | else 32059 | return details::is_variable_node(branch[0]) && 32060 | details::is_constant_node(branch[1]) ; 32061 | } 32062 | 32063 | inline bool vov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32064 | { 32065 | if (!operation_optimisable(operation)) 32066 | return false; 32067 | else 32068 | return details::is_variable_node(branch[0]) && 32069 | details::is_variable_node(branch[1]) ; 32070 | } 32071 | 32072 | inline bool cob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32073 | { 32074 | if (!operation_optimisable(operation)) 32075 | return false; 32076 | else 32077 | return details::is_constant_node(branch[0]) && 32078 | !details::is_constant_node(branch[1]) ; 32079 | } 32080 | 32081 | inline bool boc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32082 | { 32083 | if (!operation_optimisable(operation)) 32084 | return false; 32085 | else 32086 | return !details::is_constant_node(branch[0]) && 32087 | details::is_constant_node(branch[1]) ; 32088 | } 32089 | 32090 | inline bool cocob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32091 | { 32092 | if ( 32093 | (details::e_add == operation) || 32094 | (details::e_sub == operation) || 32095 | (details::e_mul == operation) || 32096 | (details::e_div == operation) 32097 | ) 32098 | { 32099 | return (details::is_constant_node(branch[0]) && details::is_cob_node(branch[1])) || 32100 | (details::is_constant_node(branch[1]) && details::is_cob_node(branch[0])) ; 32101 | } 32102 | else 32103 | return false; 32104 | } 32105 | 32106 | inline bool coboc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32107 | { 32108 | if ( 32109 | (details::e_add == operation) || 32110 | (details::e_sub == operation) || 32111 | (details::e_mul == operation) || 32112 | (details::e_div == operation) 32113 | ) 32114 | { 32115 | return (details::is_constant_node(branch[0]) && details::is_boc_node(branch[1])) || 32116 | (details::is_constant_node(branch[1]) && details::is_boc_node(branch[0])) ; 32117 | } 32118 | else 32119 | return false; 32120 | } 32121 | 32122 | inline bool uvouv_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32123 | { 32124 | if (!operation_optimisable(operation)) 32125 | return false; 32126 | else 32127 | return details::is_uv_node(branch[0]) && 32128 | details::is_uv_node(branch[1]) ; 32129 | } 32130 | 32131 | inline bool vob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32132 | { 32133 | if (!operation_optimisable(operation)) 32134 | return false; 32135 | else 32136 | return details::is_variable_node(branch[0]) && 32137 | !details::is_variable_node(branch[1]) ; 32138 | } 32139 | 32140 | inline bool bov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32141 | { 32142 | if (!operation_optimisable(operation)) 32143 | return false; 32144 | else 32145 | return !details::is_variable_node(branch[0]) && 32146 | details::is_variable_node(branch[1]) ; 32147 | } 32148 | 32149 | inline bool binext_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32150 | { 32151 | if (!operation_optimisable(operation)) 32152 | return false; 32153 | else 32154 | return !details::is_constant_node(branch[0]) || 32155 | !details::is_constant_node(branch[1]) ; 32156 | } 32157 | 32158 | inline bool is_invalid_assignment_op(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32159 | { 32160 | if (is_assignment_operation(operation)) 32161 | { 32162 | const bool b1_is_genstring = details::is_generally_string_node(branch[1]); 32163 | 32164 | if (details::is_string_node(branch[0])) 32165 | return !b1_is_genstring; 32166 | else if (details::is_literal_node(branch[0])) 32167 | return true; 32168 | else 32169 | return ( 32170 | !details::is_variable_node (branch[0]) && 32171 | !details::is_vector_elem_node (branch[0]) && 32172 | !details::is_vector_celem_node (branch[0]) && 32173 | !details::is_vector_elem_rtc_node (branch[0]) && 32174 | !details::is_vector_celem_rtc_node (branch[0]) && 32175 | !details::is_rebasevector_elem_node (branch[0]) && 32176 | !details::is_rebasevector_celem_node (branch[0]) && 32177 | !details::is_rebasevector_elem_rtc_node (branch[0]) && 32178 | !details::is_rebasevector_celem_rtc_node(branch[0]) && 32179 | !details::is_vector_node (branch[0]) 32180 | ) 32181 | || b1_is_genstring; 32182 | } 32183 | else 32184 | return false; 32185 | } 32186 | 32187 | inline bool is_constpow_operation(const details::operator_type& operation, expression_node_ptr(&branch)[2]) const 32188 | { 32189 | if ( 32190 | !details::is_constant_node(branch[1]) || 32191 | details::is_constant_node(branch[0]) || 32192 | details::is_variable_node(branch[0]) || 32193 | details::is_vector_node (branch[0]) || 32194 | details::is_generally_string_node(branch[0]) 32195 | ) 32196 | return false; 32197 | 32198 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 32199 | 32200 | return cardinal_pow_optimisable(operation, c); 32201 | } 32202 | 32203 | inline bool is_invalid_break_continue_op(expression_node_ptr (&branch)[2]) const 32204 | { 32205 | return ( 32206 | details::is_break_node (branch[0]) || 32207 | details::is_break_node (branch[1]) || 32208 | details::is_continue_node(branch[0]) || 32209 | details::is_continue_node(branch[1]) 32210 | ); 32211 | } 32212 | 32213 | inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32214 | { 32215 | const bool b0_string = is_generally_string_node(branch[0]); 32216 | const bool b1_string = is_generally_string_node(branch[1]); 32217 | 32218 | bool result = false; 32219 | 32220 | if (b0_string != b1_string) 32221 | result = true; 32222 | else if (!valid_string_operation(operation) && b0_string && b1_string) 32223 | result = true; 32224 | 32225 | if (result) 32226 | { 32227 | parser_->set_synthesis_error("Invalid string operation"); 32228 | } 32229 | 32230 | return result; 32231 | } 32232 | 32233 | inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[3]) const 32234 | { 32235 | const bool b0_string = is_generally_string_node(branch[0]); 32236 | const bool b1_string = is_generally_string_node(branch[1]); 32237 | const bool b2_string = is_generally_string_node(branch[2]); 32238 | 32239 | bool result = false; 32240 | 32241 | if ((b0_string != b1_string) || (b1_string != b2_string)) 32242 | result = true; 32243 | else if ((details::e_inrange != operation) && b0_string && b1_string && b2_string) 32244 | result = true; 32245 | 32246 | if (result) 32247 | { 32248 | parser_->set_synthesis_error("Invalid string operation"); 32249 | } 32250 | 32251 | return result; 32252 | } 32253 | 32254 | inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32255 | { 32256 | const bool b0_string = is_generally_string_node(branch[0]); 32257 | const bool b1_string = is_generally_string_node(branch[1]); 32258 | 32259 | return (b0_string && b1_string && valid_string_operation(operation)); 32260 | } 32261 | 32262 | inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[3]) const 32263 | { 32264 | const bool b0_string = is_generally_string_node(branch[0]); 32265 | const bool b1_string = is_generally_string_node(branch[1]); 32266 | const bool b2_string = is_generally_string_node(branch[2]); 32267 | 32268 | return (b0_string && b1_string && b2_string && (details::e_inrange == operation)); 32269 | } 32270 | 32271 | #ifndef exprtk_disable_sc_andor 32272 | inline bool is_shortcircuit_expression(const details::operator_type& operation) const 32273 | { 32274 | return ( 32275 | (details::e_scand == operation) || 32276 | (details::e_scor == operation) 32277 | ); 32278 | } 32279 | #else 32280 | inline bool is_shortcircuit_expression(const details::operator_type&) const 32281 | { 32282 | return false; 32283 | } 32284 | #endif 32285 | 32286 | inline bool is_null_present(expression_node_ptr (&branch)[2]) const 32287 | { 32288 | return ( 32289 | details::is_null_node(branch[0]) || 32290 | details::is_null_node(branch[1]) 32291 | ); 32292 | } 32293 | 32294 | inline bool is_vector_eqineq_logic_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32295 | { 32296 | if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1])) 32297 | return false; 32298 | else 32299 | return ( 32300 | (details::e_lt == operation) || 32301 | (details::e_lte == operation) || 32302 | (details::e_gt == operation) || 32303 | (details::e_gte == operation) || 32304 | (details::e_eq == operation) || 32305 | (details::e_ne == operation) || 32306 | (details::e_equal == operation) || 32307 | (details::e_and == operation) || 32308 | (details::e_nand == operation) || 32309 | (details::e_or == operation) || 32310 | (details::e_nor == operation) || 32311 | (details::e_xor == operation) || 32312 | (details::e_xnor == operation) 32313 | ); 32314 | } 32315 | 32316 | inline bool is_vector_arithmetic_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32317 | { 32318 | if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1])) 32319 | return false; 32320 | else 32321 | return ( 32322 | (details::e_add == operation) || 32323 | (details::e_sub == operation) || 32324 | (details::e_mul == operation) || 32325 | (details::e_div == operation) || 32326 | (details::e_pow == operation) 32327 | ); 32328 | } 32329 | 32330 | inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[2]) 32331 | { 32332 | if ((0 == branch[0]) || (0 == branch[1])) 32333 | { 32334 | parser_->set_error(parser_error::make_error( 32335 | parser_error::e_syntax, 32336 | parser_->current_state().token, 32337 | "ERR249 - Invalid branches received for operator '" + details::to_str(operation) + "'", 32338 | exprtk_error_location)); 32339 | 32340 | return error_node(); 32341 | } 32342 | else if (is_invalid_string_op(operation,branch)) 32343 | { 32344 | parser_->set_error(parser_error::make_error( 32345 | parser_error::e_syntax, 32346 | parser_->current_state().token, 32347 | "ERR250 - Invalid branch pair for string operator '" + details::to_str(operation) + "'", 32348 | exprtk_error_location)); 32349 | 32350 | return error_node(); 32351 | } 32352 | else if (is_invalid_assignment_op(operation,branch)) 32353 | { 32354 | parser_->set_error(parser_error::make_error( 32355 | parser_error::e_syntax, 32356 | parser_->current_state().token, 32357 | "ERR251 - Invalid branch pair for assignment operator '" + details::to_str(operation) + "'", 32358 | exprtk_error_location)); 32359 | 32360 | return error_node(); 32361 | } 32362 | else if (is_invalid_break_continue_op(branch)) 32363 | { 32364 | parser_->set_error(parser_error::make_error( 32365 | parser_error::e_syntax, 32366 | parser_->current_state().token, 32367 | "ERR252 - Invalid branch pair for break/continue operator '" + details::to_str(operation) + "'", 32368 | exprtk_error_location)); 32369 | 32370 | return error_node(); 32371 | } 32372 | else if (details::e_assign == operation) 32373 | { 32374 | return synthesize_assignment_expression(operation, branch); 32375 | } 32376 | else if (details::e_swap == operation) 32377 | { 32378 | return synthesize_swap_expression(branch); 32379 | } 32380 | else if (is_assignment_operation(operation)) 32381 | { 32382 | return synthesize_assignment_operation_expression(operation, branch); 32383 | } 32384 | else if (is_vector_eqineq_logic_operation(operation, branch)) 32385 | { 32386 | return synthesize_veceqineqlogic_operation_expression(operation, branch); 32387 | } 32388 | else if (is_vector_arithmetic_operation(operation, branch)) 32389 | { 32390 | return synthesize_vecarithmetic_operation_expression(operation, branch); 32391 | } 32392 | else if (is_shortcircuit_expression(operation)) 32393 | { 32394 | return synthesize_shortcircuit_expression(operation, branch); 32395 | } 32396 | else if (is_string_operation(operation, branch)) 32397 | { 32398 | return synthesize_string_expression(operation, branch); 32399 | } 32400 | else if (is_null_present(branch)) 32401 | { 32402 | return synthesize_null_expression(operation, branch); 32403 | } 32404 | #ifndef exprtk_disable_cardinal_pow_optimisation 32405 | else if (is_constpow_operation(operation, branch)) 32406 | { 32407 | return cardinal_pow_optimisation(branch); 32408 | } 32409 | #endif 32410 | 32411 | expression_node_ptr result = error_node(); 32412 | 32413 | #ifndef exprtk_disable_enhanced_features 32414 | if (synthesize_expression(operation, branch, result)) 32415 | { 32416 | return result; 32417 | } 32418 | else 32419 | #endif 32420 | 32421 | { 32422 | /* 32423 | Possible reductions: 32424 | 1. c o cob -> cob 32425 | 2. cob o c -> cob 32426 | 3. c o boc -> boc 32427 | 4. boc o c -> boc 32428 | */ 32429 | result = error_node(); 32430 | 32431 | if (cocob_optimisable(operation, branch)) 32432 | { 32433 | result = synthesize_cocob_expression::process((*this), operation, branch); 32434 | } 32435 | else if (coboc_optimisable(operation, branch) && (0 == result)) 32436 | { 32437 | result = synthesize_coboc_expression::process((*this), operation, branch); 32438 | } 32439 | 32440 | if (result) 32441 | return result; 32442 | } 32443 | 32444 | if (uvouv_optimisable(operation, branch)) 32445 | { 32446 | return synthesize_uvouv_expression(operation, branch); 32447 | } 32448 | else if (vob_optimisable(operation, branch)) 32449 | { 32450 | return synthesize_vob_expression::process((*this), operation, branch); 32451 | } 32452 | else if (bov_optimisable(operation, branch)) 32453 | { 32454 | return synthesize_bov_expression::process((*this), operation, branch); 32455 | } 32456 | else if (cob_optimisable(operation, branch)) 32457 | { 32458 | return synthesize_cob_expression::process((*this), operation, branch); 32459 | } 32460 | else if (boc_optimisable(operation, branch)) 32461 | { 32462 | return synthesize_boc_expression::process((*this), operation, branch); 32463 | } 32464 | #ifndef exprtk_disable_enhanced_features 32465 | else if (cov_optimisable(operation, branch)) 32466 | { 32467 | return synthesize_cov_expression::process((*this), operation, branch); 32468 | } 32469 | #endif 32470 | else if (binext_optimisable(operation, branch)) 32471 | { 32472 | return synthesize_binary_ext_expression::process((*this), operation, branch); 32473 | } 32474 | else 32475 | return synthesize_expression<binary_node_t,2>(operation, branch); 32476 | } 32477 | 32478 | inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[3]) 32479 | { 32480 | if ( 32481 | (0 == branch[0]) || 32482 | (0 == branch[1]) || 32483 | (0 == branch[2]) 32484 | ) 32485 | { 32486 | details::free_all_nodes(*node_allocator_,branch); 32487 | 32488 | parser_->set_error(parser_error::make_error( 32489 | parser_error::e_syntax, 32490 | parser_->current_state().token, 32491 | "ERR253 - Invalid branches operator '" + details::to_str(operation) + "'", 32492 | exprtk_error_location)); 32493 | 32494 | return error_node(); 32495 | } 32496 | else if (is_invalid_string_op(operation, branch)) 32497 | { 32498 | parser_->set_error(parser_error::make_error( 32499 | parser_error::e_syntax, 32500 | parser_->current_state().token, 32501 | "ERR254 - Invalid branches for string operator '" + details::to_str(operation) + "'", 32502 | exprtk_error_location)); 32503 | 32504 | return error_node(); 32505 | } 32506 | else if (is_string_operation(operation, branch)) 32507 | { 32508 | return synthesize_string_expression(operation, branch); 32509 | } 32510 | else 32511 | return synthesize_expression<trinary_node_t,3>(operation, branch); 32512 | } 32513 | 32514 | inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[4]) 32515 | { 32516 | return synthesize_expression<quaternary_node_t,4>(operation,branch); 32517 | } 32518 | 32519 | inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr b0) 32520 | { 32521 | expression_node_ptr branch[1] = { b0 }; 32522 | return (*this)(operation,branch); 32523 | } 32524 | 32525 | inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr& b0, expression_node_ptr& b1) 32526 | { 32527 | expression_node_ptr result = error_node(); 32528 | 32529 | if ((0 != b0) && (0 != b1)) 32530 | { 32531 | expression_node_ptr branch[2] = { b0, b1 }; 32532 | result = expression_generator<Type>::operator()(operation, branch); 32533 | b0 = branch[0]; 32534 | b1 = branch[1]; 32535 | } 32536 | 32537 | return result; 32538 | } 32539 | 32540 | inline expression_node_ptr conditional(expression_node_ptr condition, 32541 | expression_node_ptr consequent, 32542 | expression_node_ptr alternative) const 32543 | { 32544 | if ((0 == condition) || (0 == consequent)) 32545 | { 32546 | details::free_node(*node_allocator_, condition ); 32547 | details::free_node(*node_allocator_, consequent ); 32548 | details::free_node(*node_allocator_, alternative); 32549 | 32550 | const std::string invalid_branches = 32551 | ((0 == condition ) ? std::string("condition ") : "") + 32552 | ((0 == consequent) ? std::string("consequent") : "") ; 32553 | 32554 | parser_->set_error(parser_error::make_error( 32555 | parser_error::e_parser, 32556 | parser_->current_state().token, 32557 | "ERR255 - Invalid " + invalid_branches + " for conditional statement", 32558 | exprtk_error_location)); 32559 | 32560 | return error_node(); 32561 | } 32562 | // Can the condition be immediately evaluated? if so optimise. 32563 | else if (details::is_constant_node(condition)) 32564 | { 32565 | // True branch 32566 | if (details::is_true(condition)) 32567 | { 32568 | details::free_node(*node_allocator_, condition ); 32569 | details::free_node(*node_allocator_, alternative); 32570 | 32571 | return consequent; 32572 | } 32573 | // False branch 32574 | else 32575 | { 32576 | details::free_node(*node_allocator_, condition ); 32577 | details::free_node(*node_allocator_, consequent); 32578 | 32579 | if (alternative) 32580 | return alternative; 32581 | else 32582 | return node_allocator_->allocate<details::null_node<T> >(); 32583 | } 32584 | } 32585 | 32586 | expression_node_ptr result = error_node(); 32587 | std::string node_name = "Unknown!" 32588 | 32589 | if ((0 != consequent) && (0 != alternative)) 32590 | { 32591 | result = node_allocator_->allocate<conditional_node_t>(condition, consequent, alternative); 32592 | node_name = "conditional_node_t" 32593 | } 32594 | else 32595 | { 32596 | result = node_allocator_->allocate<cons_conditional_node_t>(condition, consequent); 32597 | node_name = "cons_conditional_node_t" 32598 | } 32599 | 32600 | if (result && result->valid()) 32601 | { 32602 | return result; 32603 | } 32604 | 32605 | parser_->set_error(parser_error::make_error( 32606 | parser_error::e_parser, 32607 | token_t(), 32608 | "ERR256 - Failed to synthesize node: " + node_name, 32609 | exprtk_error_location)); 32610 | 32611 | details::free_node(*node_allocator_, result); 32612 | return error_node(); 32613 | } 32614 | 32615 | #ifndef exprtk_disable_string_capabilities 32616 | inline expression_node_ptr conditional_string(expression_node_ptr condition, 32617 | expression_node_ptr consequent, 32618 | expression_node_ptr alternative) const 32619 | { 32620 | if ((0 == condition) || (0 == consequent)) 32621 | { 32622 | details::free_node(*node_allocator_, condition ); 32623 | details::free_node(*node_allocator_, consequent ); 32624 | details::free_node(*node_allocator_, alternative); 32625 | 32626 | const std::string invalid_branches = 32627 | ((0 == condition ) ? std::string("condition ") : "") + 32628 | ((0 == consequent) ? std::string("consequent") : "") ; 32629 | 32630 | parser_->set_error(parser_error::make_error( 32631 | parser_error::e_parser, 32632 | parser_->current_state().token, 32633 | "ERR257 - Invalid " + invalid_branches + " for string conditional statement", 32634 | exprtk_error_location)); 32635 | 32636 | return error_node(); 32637 | } 32638 | // Can the condition be immediately evaluated? if so optimise. 32639 | else if (details::is_constant_node(condition)) 32640 | { 32641 | // True branch 32642 | if (details::is_true(condition)) 32643 | { 32644 | details::free_node(*node_allocator_, condition ); 32645 | details::free_node(*node_allocator_, alternative); 32646 | 32647 | return consequent; 32648 | } 32649 | // False branch 32650 | else 32651 | { 32652 | details::free_node(*node_allocator_, condition ); 32653 | details::free_node(*node_allocator_, consequent); 32654 | 32655 | if (alternative) 32656 | return alternative; 32657 | else 32658 | return node_allocator_-> 32659 | allocate_c<details::string_literal_node<Type> >(""); 32660 | } 32661 | } 32662 | else if ((0 != consequent) && (0 != alternative)) 32663 | { 32664 | expression_node_ptr result = 32665 | node_allocator_->allocate<conditional_string_node_t>(condition, consequent, alternative); 32666 | 32667 | if (result && result->valid()) 32668 | { 32669 | return result; 32670 | } 32671 | 32672 | parser_->set_error(parser_error::make_error( 32673 | parser_error::e_parser, 32674 | token_t(), 32675 | "ERR258 - Failed to synthesize node: conditional_string_node_t", 32676 | exprtk_error_location)); 32677 | 32678 | details::free_node(*node_allocator_, result); 32679 | } 32680 | 32681 | return error_node(); 32682 | } 32683 | #else 32684 | inline expression_node_ptr conditional_string(expression_node_ptr, 32685 | expression_node_ptr, 32686 | expression_node_ptr) const 32687 | { 32688 | return error_node(); 32689 | } 32690 | #endif 32691 | 32692 | inline expression_node_ptr conditional_vector(expression_node_ptr condition, 32693 | expression_node_ptr consequent, 32694 | expression_node_ptr alternative) const 32695 | { 32696 | if ((0 == condition) || (0 == consequent)) 32697 | { 32698 | details::free_node(*node_allocator_, condition ); 32699 | details::free_node(*node_allocator_, consequent ); 32700 | details::free_node(*node_allocator_, alternative); 32701 | 32702 | const std::string invalid_branches = 32703 | ((0 == condition ) ? std::string("condition ") : "") + 32704 | ((0 == consequent) ? std::string("consequent") : "") ; 32705 | 32706 | parser_->set_error(parser_error::make_error( 32707 | parser_error::e_parser, 32708 | parser_->current_state().token, 32709 | "ERR259 - Invalid " + invalid_branches + " for vector conditional statement", 32710 | exprtk_error_location)); 32711 | 32712 | return error_node(); 32713 | } 32714 | // Can the condition be immediately evaluated? if so optimise. 32715 | else if (details::is_constant_node(condition)) 32716 | { 32717 | // True branch 32718 | if (details::is_true(condition)) 32719 | { 32720 | details::free_node(*node_allocator_, condition ); 32721 | details::free_node(*node_allocator_, alternative); 32722 | 32723 | return consequent; 32724 | } 32725 | // False branch 32726 | else 32727 | { 32728 | details::free_node(*node_allocator_, condition ); 32729 | details::free_node(*node_allocator_, consequent); 32730 | 32731 | if (alternative) 32732 | return alternative; 32733 | else 32734 | return node_allocator_->allocate<details::null_node<T> >(); 32735 | 32736 | } 32737 | } 32738 | else if ((0 != consequent) && (0 != alternative)) 32739 | { 32740 | return node_allocator_-> 32741 | allocate<conditional_vector_node_t>(condition, consequent, alternative); 32742 | } 32743 | else 32744 | return error_node(); 32745 | } 32746 | 32747 | inline loop_runtime_check_ptr get_loop_runtime_check(const loop_runtime_check::loop_types loop_type) const 32748 | { 32749 | if ( 32750 | parser_->loop_runtime_check_ && 32751 | (loop_type == (parser_->loop_runtime_check_->loop_set & loop_type)) 32752 | ) 32753 | { 32754 | return parser_->loop_runtime_check_; 32755 | } 32756 | 32757 | return loop_runtime_check_ptr(0); 32758 | } 32759 | 32760 | inline vector_access_runtime_check_ptr get_vector_access_runtime_check() const 32761 | { 32762 | return parser_->vector_access_runtime_check_; 32763 | } 32764 | 32765 | inline expression_node_ptr while_loop(expression_node_ptr& condition, 32766 | expression_node_ptr& branch, 32767 | const bool break_continue_present = false) const 32768 | { 32769 | if ( 32770 | !break_continue_present && 32771 | !parser_->state_.return_stmt_present && 32772 | details::is_constant_node(condition) 32773 | ) 32774 | { 32775 | expression_node_ptr result = error_node(); 32776 | if (details::is_true(condition)) 32777 | { 32778 | // Infinite loops are not allowed. 32779 | 32780 | parser_->set_error(parser_error::make_error( 32781 | parser_error::e_parser, 32782 | parser_->current_state().token, 32783 | "ERR260 - Infinite loop condition without 'break' or 'return' not allowed in while-loops", 32784 | exprtk_error_location)); 32785 | 32786 | result = error_node(); 32787 | } 32788 | else 32789 | result = node_allocator_->allocate<details::null_node<Type> >(); 32790 | 32791 | details::free_node(*node_allocator_, condition); 32792 | details::free_node(*node_allocator_, branch ); 32793 | 32794 | return result; 32795 | } 32796 | else if (details::is_null_node(condition)) 32797 | { 32798 | details::free_node(*node_allocator_,condition); 32799 | 32800 | return branch; 32801 | } 32802 | 32803 | loop_runtime_check_ptr rtc = get_loop_runtime_check(loop_runtime_check::e_while_loop); 32804 | 32805 | if (!break_continue_present) 32806 | { 32807 | if (rtc) 32808 | return node_allocator_->allocate<while_loop_rtc_node_t> 32809 | (condition, branch, rtc); 32810 | else 32811 | return node_allocator_->allocate<while_loop_node_t> 32812 | (condition, branch); 32813 | } 32814 | #ifndef exprtk_disable_break_continue 32815 | else 32816 | { 32817 | if (rtc) 32818 | return node_allocator_->allocate<while_loop_bc_rtc_node_t> 32819 | (condition, branch, rtc); 32820 | else 32821 | return node_allocator_->allocate<while_loop_bc_node_t> 32822 | (condition, branch); 32823 | } 32824 | #else 32825 | return error_node(); 32826 | #endif 32827 | } 32828 | 32829 | inline expression_node_ptr repeat_until_loop(expression_node_ptr& condition, 32830 | expression_node_ptr& branch, 32831 | const bool break_continue_present = false) const 32832 | { 32833 | if (!break_continue_present && details::is_constant_node(condition)) 32834 | { 32835 | if ( 32836 | details::is_true(condition) && 32837 | details::is_constant_node(branch) 32838 | ) 32839 | { 32840 | free_node(*node_allocator_,condition); 32841 | 32842 | return branch; 32843 | } 32844 | 32845 | details::free_node(*node_allocator_, condition); 32846 | details::free_node(*node_allocator_, branch ); 32847 | 32848 | return error_node(); 32849 | } 32850 | else if (details::is_null_node(condition)) 32851 | { 32852 | details::free_node(*node_allocator_,condition); 32853 | 32854 | return branch; 32855 | } 32856 | 32857 | loop_runtime_check_ptr rtc = get_loop_runtime_check(loop_runtime_check::e_repeat_until_loop); 32858 | 32859 | if (!break_continue_present) 32860 | { 32861 | if (rtc) 32862 | return node_allocator_->allocate<repeat_until_loop_rtc_node_t> 32863 | (condition, branch, rtc); 32864 | else 32865 | return node_allocator_->allocate<repeat_until_loop_node_t> 32866 | (condition, branch); 32867 | } 32868 | #ifndef exprtk_disable_break_continue 32869 | else 32870 | { 32871 | if (rtc) 32872 | return node_allocator_->allocate<repeat_until_loop_bc_rtc_node_t> 32873 | (condition, branch, rtc); 32874 | else 32875 | return node_allocator_->allocate<repeat_until_loop_bc_node_t> 32876 | (condition, branch); 32877 | } 32878 | #else 32879 | return error_node(); 32880 | #endif 32881 | } 32882 | 32883 | inline expression_node_ptr for_loop(expression_node_ptr& initialiser, 32884 | expression_node_ptr& condition, 32885 | expression_node_ptr& incrementor, 32886 | expression_node_ptr& loop_body, 32887 | bool break_continue_present = false) const 32888 | { 32889 | if ( 32890 | !break_continue_present && 32891 | !parser_->state_.return_stmt_present && 32892 | details::is_constant_node(condition) 32893 | ) 32894 | { 32895 | expression_node_ptr result = error_node(); 32896 | 32897 | if (details::is_true(condition)) 32898 | { 32899 | // Infinite loops are not allowed. 32900 | 32901 | parser_->set_error(parser_error::make_error( 32902 | parser_error::e_parser, 32903 | parser_->current_state().token, 32904 | "ERR261 - Infinite loop condition without 'break' or 'return' not allowed in for-loop", 32905 | exprtk_error_location)); 32906 | 32907 | result = error_node(); 32908 | } 32909 | else 32910 | result = node_allocator_->allocate<details::null_node<Type> >(); 32911 | 32912 | details::free_node(*node_allocator_, initialiser); 32913 | details::free_node(*node_allocator_, condition ); 32914 | details::free_node(*node_allocator_, incrementor); 32915 | details::free_node(*node_allocator_, loop_body ); 32916 | 32917 | return result; 32918 | } 32919 | else if (details::is_null_node(condition) || (0 == condition)) 32920 | { 32921 | details::free_node(*node_allocator_, initialiser); 32922 | details::free_node(*node_allocator_, condition ); 32923 | details::free_node(*node_allocator_, incrementor); 32924 | 32925 | return loop_body; 32926 | } 32927 | 32928 | loop_runtime_check_ptr rtc = get_loop_runtime_check(loop_runtime_check::e_for_loop); 32929 | 32930 | if (!break_continue_present) 32931 | { 32932 | if (rtc) 32933 | return node_allocator_->allocate<for_loop_rtc_node_t> 32934 | ( 32935 | initialiser, 32936 | condition, 32937 | incrementor, 32938 | loop_body, 32939 | rtc 32940 | ); 32941 | else 32942 | return node_allocator_->allocate<for_loop_node_t> 32943 | ( 32944 | initialiser, 32945 | condition, 32946 | incrementor, 32947 | loop_body 32948 | ); 32949 | } 32950 | #ifndef exprtk_disable_break_continue 32951 | else 32952 | { 32953 | if (rtc) 32954 | return node_allocator_->allocate<for_loop_bc_rtc_node_t> 32955 | ( 32956 | initialiser, 32957 | condition, 32958 | incrementor, 32959 | loop_body, 32960 | rtc 32961 | ); 32962 | else 32963 | return node_allocator_->allocate<for_loop_bc_node_t> 32964 | ( 32965 | initialiser, 32966 | condition, 32967 | incrementor, 32968 | loop_body 32969 | ); 32970 | } 32971 | #else 32972 | return error_node(); 32973 | #endif 32974 | } 32975 | 32976 | template <typename Allocator, 32977 | template <typename, typename> class Sequence> 32978 | inline expression_node_ptr const_optimise_switch(Sequence<expression_node_ptr,Allocator>& arg_list) 32979 | { 32980 | expression_node_ptr result = error_node(); 32981 | 32982 | for (std::size_t i = 0; i < (arg_list.size() / 2); ++i) 32983 | { 32984 | expression_node_ptr condition = arg_list[(2 * i) ]; 32985 | expression_node_ptr consequent = arg_list[(2 * i) + 1]; 32986 | 32987 | if ((0 == result) && details::is_true(condition)) 32988 | { 32989 | result = consequent; 32990 | break; 32991 | } 32992 | } 32993 | 32994 | if (0 == result) 32995 | { 32996 | result = arg_list.back(); 32997 | } 32998 | 32999 | for (std::size_t i = 0; i < arg_list.size(); ++i) 33000 | { 33001 | expression_node_ptr current_expr = arg_list[i]; 33002 | 33003 | if (current_expr && (current_expr != result)) 33004 | { 33005 | free_node(*node_allocator_,current_expr); 33006 | } 33007 | } 33008 | 33009 | return result; 33010 | } 33011 | 33012 | template <typename Allocator, 33013 | template <typename, typename> class Sequence> 33014 | inline expression_node_ptr const_optimise_mswitch(Sequence<expression_node_ptr,Allocator>& arg_list) 33015 | { 33016 | expression_node_ptr result = error_node(); 33017 | 33018 | for (std::size_t i = 0; i < (arg_list.size() / 2); ++i) 33019 | { 33020 | expression_node_ptr condition = arg_list[(2 * i) ]; 33021 | expression_node_ptr consequent = arg_list[(2 * i) + 1]; 33022 | 33023 | if (details::is_true(condition)) 33024 | { 33025 | result = consequent; 33026 | } 33027 | } 33028 | 33029 | if (0 == result) 33030 | { 33031 | const T zero = T(0); 33032 | result = node_allocator_->allocate<literal_node_t>(zero); 33033 | } 33034 | 33035 | for (std::size_t i = 0; i < arg_list.size(); ++i) 33036 | { 33037 | expression_node_ptr& current_expr = arg_list[i]; 33038 | 33039 | if (current_expr && (current_expr != result)) 33040 | { 33041 | details::free_node(*node_allocator_,current_expr); 33042 | } 33043 | } 33044 | 33045 | return result; 33046 | } 33047 | 33048 | struct switch_nodes 33049 | { 33050 | typedef std::vector<std::pair<expression_node_ptr,bool> > arg_list_t; 33051 | 33052 | #define case_stmt(N) \ 33053 | if (is_true(arg[(2 * N)].first)) { return arg[(2 * N) + 1].first->value(); } \ 33054 | 33055 | struct switch_impl_1 33056 | { 33057 | static inline T process(const arg_list_t& arg) 33058 | { 33059 | case_stmt(0) 33060 | 33061 | assert(arg.size() == ((2 * 1) + 1)); 33062 | 33063 | return arg.back().first->value(); 33064 | } 33065 | }; 33066 | 33067 | struct switch_impl_2 33068 | { 33069 | static inline T process(const arg_list_t& arg) 33070 | { 33071 | case_stmt(0) case_stmt(1) 33072 | 33073 | assert(arg.size() == ((2 * 2) + 1)); 33074 | 33075 | return arg.back().first->value(); 33076 | } 33077 | }; 33078 | 33079 | struct switch_impl_3 33080 | { 33081 | static inline T process(const arg_list_t& arg) 33082 | { 33083 | case_stmt(0) case_stmt(1) 33084 | case_stmt(2) 33085 | 33086 | assert(arg.size() == ((2 * 3) + 1)); 33087 | 33088 | return arg.back().first->value(); 33089 | } 33090 | }; 33091 | 33092 | struct switch_impl_4 33093 | { 33094 | static inline T process(const arg_list_t& arg) 33095 | { 33096 | case_stmt(0) case_stmt(1) 33097 | case_stmt(2) case_stmt(3) 33098 | 33099 | assert(arg.size() == ((2 * 4) + 1)); 33100 | 33101 | return arg.back().first->value(); 33102 | } 33103 | }; 33104 | 33105 | struct switch_impl_5 33106 | { 33107 | static inline T process(const arg_list_t& arg) 33108 | { 33109 | case_stmt(0) case_stmt(1) 33110 | case_stmt(2) case_stmt(3) 33111 | case_stmt(4) 33112 | 33113 | assert(arg.size() == ((2 * 5) + 1)); 33114 | 33115 | return arg.back().first->value(); 33116 | } 33117 | }; 33118 | 33119 | struct switch_impl_6 33120 | { 33121 | static inline T process(const arg_list_t& arg) 33122 | { 33123 | case_stmt(0) case_stmt(1) 33124 | case_stmt(2) case_stmt(3) 33125 | case_stmt(4) case_stmt(5) 33126 | 33127 | assert(arg.size() == ((2 * 6) + 1)); 33128 | 33129 | return arg.back().first->value(); 33130 | } 33131 | }; 33132 | 33133 | struct switch_impl_7 33134 | { 33135 | static inline T process(const arg_list_t& arg) 33136 | { 33137 | case_stmt(0) case_stmt(1) 33138 | case_stmt(2) case_stmt(3) 33139 | case_stmt(4) case_stmt(5) 33140 | case_stmt(6) 33141 | 33142 | assert(arg.size() == ((2 * 7) + 1)); 33143 | 33144 | return arg.back().first->value(); 33145 | } 33146 | }; 33147 | 33148 | #undef case_stmt 33149 | }; 33150 | 33151 | template <typename Allocator, 33152 | template <typename, typename> class Sequence> 33153 | inline expression_node_ptr switch_statement(Sequence<expression_node_ptr,Allocator>& arg_list, const bool default_statement_present) 33154 | { 33155 | if (arg_list.empty()) 33156 | return error_node(); 33157 | else if ( 33158 | !all_nodes_valid(arg_list) || 33159 | (!default_statement_present && (arg_list.size() < 2)) 33160 | ) 33161 | { 33162 | details::free_all_nodes(*node_allocator_,arg_list); 33163 | 33164 | return error_node(); 33165 | } 33166 | else if (is_constant_foldable(arg_list)) 33167 | return const_optimise_switch(arg_list); 33168 | 33169 | switch ((arg_list.size() - 1) / 2) 33170 | { 33171 | #define case_stmt(N) \ 33172 | case N : \ 33173 | return node_allocator_-> \ 33174 | allocate<details::switch_n_node \ 33175 | <Type,typename switch_nodes::switch_impl_##N > >(arg_list); \ 33176 | 33177 | case_stmt(1) 33178 | case_stmt(2) 33179 | case_stmt(3) 33180 | case_stmt(4) 33181 | case_stmt(5) 33182 | case_stmt(6) 33183 | case_stmt(7) 33184 | #undef case_stmt 33185 | 33186 | default : return node_allocator_->allocate<details::switch_node<Type> >(arg_list); 33187 | } 33188 | } 33189 | 33190 | template <typename Allocator, 33191 | template <typename, typename> class Sequence> 33192 | inline expression_node_ptr multi_switch_statement(Sequence<expression_node_ptr,Allocator>& arg_list) 33193 | { 33194 | if (!all_nodes_valid(arg_list)) 33195 | { 33196 | details::free_all_nodes(*node_allocator_,arg_list); 33197 | 33198 | return error_node(); 33199 | } 33200 | else if (is_constant_foldable(arg_list)) 33201 | return const_optimise_mswitch(arg_list); 33202 | else 33203 | return node_allocator_->allocate<details::multi_switch_node<Type> >(arg_list); 33204 | } 33205 | 33206 | inline expression_node_ptr assert_call(expression_node_ptr& assert_condition, 33207 | expression_node_ptr& assert_message, 33208 | const assert_check::assert_context& context) 33209 | { 33210 | typedef details::assert_node<Type> alloc_type; 33211 | 33212 | expression_node_ptr result = node_allocator_->allocate_rrrr<alloc_type> 33213 | (assert_condition, assert_message, parser_->assert_check_, context); 33214 | 33215 | if (result && result->valid()) 33216 | { 33217 | parser_->state_.activate_side_effect("assert_call()"); 33218 | return result; 33219 | } 33220 | 33221 | details::free_node(*node_allocator_, result ); 33222 | details::free_node(*node_allocator_, assert_condition); 33223 | details::free_node(*node_allocator_, assert_message ); 33224 | 33225 | return error_node(); 33226 | } 33227 | 33228 | #define unary_opr_switch_statements \ 33229 | case_stmt(details::e_abs , details::abs_op ) \ 33230 | case_stmt(details::e_acos , details::acos_op ) \ 33231 | case_stmt(details::e_acosh , details::acosh_op) \ 33232 | case_stmt(details::e_asin , details::asin_op ) \ 33233 | case_stmt(details::e_asinh , details::asinh_op) \ 33234 | case_stmt(details::e_atan , details::atan_op ) \ 33235 | case_stmt(details::e_atanh , details::atanh_op) \ 33236 | case_stmt(details::e_ceil , details::ceil_op ) \ 33237 | case_stmt(details::e_cos , details::cos_op ) \ 33238 | case_stmt(details::e_cosh , details::cosh_op ) \ 33239 | case_stmt(details::e_exp , details::exp_op ) \ 33240 | case_stmt(details::e_expm1 , details::expm1_op) \ 33241 | case_stmt(details::e_floor , details::floor_op) \ 33242 | case_stmt(details::e_log , details::log_op ) \ 33243 | case_stmt(details::e_log10 , details::log10_op) \ 33244 | case_stmt(details::e_log2 , details::log2_op ) \ 33245 | case_stmt(details::e_log1p , details::log1p_op) \ 33246 | case_stmt(details::e_neg , details::neg_op ) \ 33247 | case_stmt(details::e_pos , details::pos_op ) \ 33248 | case_stmt(details::e_round , details::round_op) \ 33249 | case_stmt(details::e_sin , details::sin_op ) \ 33250 | case_stmt(details::e_sinc , details::sinc_op ) \ 33251 | case_stmt(details::e_sinh , details::sinh_op ) \ 33252 | case_stmt(details::e_sqrt , details::sqrt_op ) \ 33253 | case_stmt(details::e_tan , details::tan_op ) \ 33254 | case_stmt(details::e_tanh , details::tanh_op ) \ 33255 | case_stmt(details::e_cot , details::cot_op ) \ 33256 | case_stmt(details::e_sec , details::sec_op ) \ 33257 | case_stmt(details::e_csc , details::csc_op ) \ 33258 | case_stmt(details::e_r2d , details::r2d_op ) \ 33259 | case_stmt(details::e_d2r , details::d2r_op ) \ 33260 | case_stmt(details::e_d2g , details::d2g_op ) \ 33261 | case_stmt(details::e_g2d , details::g2d_op ) \ 33262 | case_stmt(details::e_notl , details::notl_op ) \ 33263 | case_stmt(details::e_sgn , details::sgn_op ) \ 33264 | case_stmt(details::e_erf , details::erf_op ) \ 33265 | case_stmt(details::e_erfc , details::erfc_op ) \ 33266 | case_stmt(details::e_ncdf , details::ncdf_op ) \ 33267 | case_stmt(details::e_frac , details::frac_op ) \ 33268 | case_stmt(details::e_trunc , details::trunc_op) \ 33269 | 33270 | inline expression_node_ptr synthesize_uv_expression(const details::operator_type& operation, 33271 | expression_node_ptr (&branch)[1]) 33272 | { 33273 | T& v = static_cast<details::variable_node<T>*>(branch[0])->ref(); 33274 | 33275 | switch (operation) 33276 | { 33277 | #define case_stmt(op0, op1) \ 33278 | case op0 : return node_allocator_-> \ 33279 | allocate<typename details::unary_variable_node<Type,op1<Type> > >(v); \ 33280 | 33281 | unary_opr_switch_statements 33282 | #undef case_stmt 33283 | default : return error_node(); 33284 | } 33285 | } 33286 | 33287 | inline expression_node_ptr synthesize_uvec_expression(const details::operator_type& operation, 33288 | expression_node_ptr (&branch)[1]) 33289 | { 33290 | switch (operation) 33291 | { 33292 | #define case_stmt(op0, op1) \ 33293 | case op0 : return node_allocator_-> \ 33294 | allocate<typename details::unary_vector_node<Type,op1<Type> > > \ 33295 | (operation, branch[0]); \ 33296 | 33297 | unary_opr_switch_statements 33298 | #undef case_stmt 33299 | default : return error_node(); 33300 | } 33301 | } 33302 | 33303 | inline expression_node_ptr synthesize_unary_expression(const details::operator_type& operation, 33304 | expression_node_ptr (&branch)[1]) 33305 | { 33306 | switch (operation) 33307 | { 33308 | #define case_stmt(op0, op1) \ 33309 | case op0 : return node_allocator_-> \ 33310 | allocate<typename details::unary_branch_node<Type,op1<Type> > >(branch[0]); \ 33311 | 33312 | unary_opr_switch_statements 33313 | #undef case_stmt 33314 | default : return error_node(); 33315 | } 33316 | } 33317 | 33318 | inline expression_node_ptr const_optimise_sf3(const details::operator_type& operation, 33319 | expression_node_ptr (&branch)[3]) 33320 | { 33321 | expression_node_ptr temp_node = error_node(); 33322 | 33323 | switch (operation) 33324 | { 33325 | #define case_stmt(op) \ 33326 | case details::e_sf##op : temp_node = node_allocator_-> \ 33327 | allocate<details::sf3_node<Type,details::sf##op##_op<Type> > > \ 33328 | (operation, branch); \ 33329 | break; \ 33330 | 33331 | case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03) 33332 | case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07) 33333 | case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11) 33334 | case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15) 33335 | case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19) 33336 | case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23) 33337 | case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27) 33338 | case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31) 33339 | case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35) 33340 | case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39) 33341 | case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43) 33342 | case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47) 33343 | #undef case_stmt 33344 | default : return error_node(); 33345 | } 33346 | 33347 | assert(temp_node); 33348 | 33349 | const T v = temp_node->value(); 33350 | 33351 | details::free_node(*node_allocator_,temp_node); 33352 | 33353 | return node_allocator_->allocate<literal_node_t>(v); 33354 | } 33355 | 33356 | inline expression_node_ptr varnode_optimise_sf3(const details::operator_type& operation, expression_node_ptr (&branch)[3]) 33357 | { 33358 | typedef details::variable_node<Type>* variable_ptr; 33359 | 33360 | const Type& v0 = static_cast<variable_ptr>(branch[0])->ref(); 33361 | const Type& v1 = static_cast<variable_ptr>(branch[1])->ref(); 33362 | const Type& v2 = static_cast<variable_ptr>(branch[2])->ref(); 33363 | 33364 | switch (operation) 33365 | { 33366 | #define case_stmt(op) \ 33367 | case details::e_sf##op : return node_allocator_-> \ 33368 | allocate_rrr<details::sf3_var_node<Type,details::sf##op##_op<Type> > > \ 33369 | (v0, v1, v2); \ 33370 | 33371 | case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03) 33372 | case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07) 33373 | case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11) 33374 | case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15) 33375 | case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19) 33376 | case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23) 33377 | case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27) 33378 | case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31) 33379 | case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35) 33380 | case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39) 33381 | case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43) 33382 | case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47) 33383 | #undef case_stmt 33384 | default : return error_node(); 33385 | } 33386 | } 33387 | 33388 | inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[3]) 33389 | { 33390 | if (!all_nodes_valid(branch)) 33391 | return error_node(); 33392 | else if (is_constant_foldable(branch)) 33393 | return const_optimise_sf3(operation,branch); 33394 | else if (all_nodes_variables(branch)) 33395 | return varnode_optimise_sf3(operation,branch); 33396 | else 33397 | { 33398 | switch (operation) 33399 | { 33400 | #define case_stmt(op) \ 33401 | case details::e_sf##op : return node_allocator_-> \ 33402 | allocate<details::sf3_node<Type,details::sf##op##_op<Type> > > \ 33403 | (operation, branch); \ 33404 | 33405 | case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03) 33406 | case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07) 33407 | case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11) 33408 | case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15) 33409 | case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19) 33410 | case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23) 33411 | case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27) 33412 | case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31) 33413 | case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35) 33414 | case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39) 33415 | case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43) 33416 | case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47) 33417 | #undef case_stmt 33418 | default : return error_node(); 33419 | } 33420 | } 33421 | } 33422 | 33423 | inline expression_node_ptr const_optimise_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4]) 33424 | { 33425 | expression_node_ptr temp_node = error_node(); 33426 | 33427 | switch (operation) 33428 | { 33429 | #define case_stmt(op) \ 33430 | case details::e_sf##op : temp_node = node_allocator_-> \ 33431 | allocate<details::sf4_node<Type,details::sf##op##_op<Type> > > \ 33432 | (operation, branch); \ 33433 | break; \ 33434 | 33435 | case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51) 33436 | case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55) 33437 | case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59) 33438 | case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63) 33439 | case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67) 33440 | case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71) 33441 | case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75) 33442 | case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79) 33443 | case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83) 33444 | case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87) 33445 | case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91) 33446 | case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95) 33447 | case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99) 33448 | #undef case_stmt 33449 | default : return error_node(); 33450 | } 33451 | 33452 | assert(temp_node); 33453 | 33454 | const T v = temp_node->value(); 33455 | 33456 | details::free_node(*node_allocator_,temp_node); 33457 | 33458 | return node_allocator_->allocate<literal_node_t>(v); 33459 | } 33460 | 33461 | inline expression_node_ptr varnode_optimise_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4]) 33462 | { 33463 | typedef details::variable_node<Type>* variable_ptr; 33464 | 33465 | const Type& v0 = static_cast<variable_ptr>(branch[0])->ref(); 33466 | const Type& v1 = static_cast<variable_ptr>(branch[1])->ref(); 33467 | const Type& v2 = static_cast<variable_ptr>(branch[2])->ref(); 33468 | const Type& v3 = static_cast<variable_ptr>(branch[3])->ref(); 33469 | 33470 | switch (operation) 33471 | { 33472 | #define case_stmt(op) \ 33473 | case details::e_sf##op : return node_allocator_-> \ 33474 | allocate_rrrr<details::sf4_var_node<Type,details::sf##op##_op<Type> > > \ 33475 | (v0, v1, v2, v3); \ 33476 | 33477 | case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51) 33478 | case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55) 33479 | case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59) 33480 | case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63) 33481 | case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67) 33482 | case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71) 33483 | case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75) 33484 | case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79) 33485 | case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83) 33486 | case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87) 33487 | case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91) 33488 | case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95) 33489 | case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99) 33490 | #undef case_stmt 33491 | default : return error_node(); 33492 | } 33493 | } 33494 | 33495 | inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[4]) 33496 | { 33497 | if (!all_nodes_valid(branch)) 33498 | return error_node(); 33499 | else if (is_constant_foldable(branch)) 33500 | return const_optimise_sf4(operation,branch); 33501 | else if (all_nodes_variables(branch)) 33502 | return varnode_optimise_sf4(operation,branch); 33503 | switch (operation) 33504 | { 33505 | #define case_stmt(op) \ 33506 | case details::e_sf##op : return node_allocator_-> \ 33507 | allocate<details::sf4_node<Type,details::sf##op##_op<Type> > > \ 33508 | (operation, branch); \ 33509 | 33510 | case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51) 33511 | case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55) 33512 | case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59) 33513 | case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63) 33514 | case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67) 33515 | case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71) 33516 | case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75) 33517 | case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79) 33518 | case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83) 33519 | case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87) 33520 | case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91) 33521 | case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95) 33522 | case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99) 33523 | #undef case_stmt 33524 | default : return error_node(); 33525 | } 33526 | } 33527 | 33528 | template <typename Allocator, 33529 | template <typename, typename> class Sequence> 33530 | inline expression_node_ptr const_optimise_varargfunc(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list) 33531 | { 33532 | expression_node_ptr temp_node = error_node(); 33533 | 33534 | switch (operation) 33535 | { 33536 | #define case_stmt(op0, op1) \ 33537 | case op0 : temp_node = node_allocator_-> \ 33538 | allocate<details::vararg_node<Type,op1<Type> > > \ 33539 | (arg_list); \ 33540 | break; \ 33541 | 33542 | case_stmt(details::e_sum , details::vararg_add_op ) 33543 | case_stmt(details::e_prod , details::vararg_mul_op ) 33544 | case_stmt(details::e_avg , details::vararg_avg_op ) 33545 | case_stmt(details::e_min , details::vararg_min_op ) 33546 | case_stmt(details::e_max , details::vararg_max_op ) 33547 | case_stmt(details::e_mand , details::vararg_mand_op ) 33548 | case_stmt(details::e_mor , details::vararg_mor_op ) 33549 | case_stmt(details::e_multi , details::vararg_multi_op) 33550 | #undef case_stmt 33551 | default : return error_node(); 33552 | } 33553 | 33554 | const T v = temp_node->value(); 33555 | 33556 | details::free_node(*node_allocator_,temp_node); 33557 | 33558 | return node_allocator_->allocate<literal_node_t>(v); 33559 | } 33560 | 33561 | inline bool special_one_parameter_vararg(const details::operator_type& operation) const 33562 | { 33563 | return ( 33564 | (details::e_sum == operation) || 33565 | (details::e_prod == operation) || 33566 | (details::e_avg == operation) || 33567 | (details::e_min == operation) || 33568 | (details::e_max == operation) 33569 | ); 33570 | } 33571 | 33572 | template <typename Allocator, 33573 | template <typename, typename> class Sequence> 33574 | inline expression_node_ptr varnode_optimise_varargfunc(const details::operator_type& operation, 33575 | Sequence<expression_node_ptr,Allocator>& arg_list) 33576 | { 33577 | switch (operation) 33578 | { 33579 | #define case_stmt(op0, op1) \ 33580 | case op0 : return node_allocator_-> \ 33581 | allocate<details::vararg_varnode<Type,op1<Type> > >(arg_list); \ 33582 | 33583 | case_stmt(details::e_sum , details::vararg_add_op ) 33584 | case_stmt(details::e_prod , details::vararg_mul_op ) 33585 | case_stmt(details::e_avg , details::vararg_avg_op ) 33586 | case_stmt(details::e_min , details::vararg_min_op ) 33587 | case_stmt(details::e_max , details::vararg_max_op ) 33588 | case_stmt(details::e_mand , details::vararg_mand_op ) 33589 | case_stmt(details::e_mor , details::vararg_mor_op ) 33590 | case_stmt(details::e_multi , details::vararg_multi_op) 33591 | #undef case_stmt 33592 | default : return error_node(); 33593 | } 33594 | } 33595 | 33596 | template <typename Allocator, 33597 | template <typename, typename> class Sequence> 33598 | inline expression_node_ptr vectorize_func(const details::operator_type& operation, 33599 | Sequence<expression_node_ptr,Allocator>& arg_list) 33600 | { 33601 | if (1 == arg_list.size()) 33602 | { 33603 | switch (operation) 33604 | { 33605 | #define case_stmt(op0, op1) \ 33606 | case op0 : return node_allocator_-> \ 33607 | allocate<details::vectorize_node<Type,op1<Type> > >(arg_list[0]); \ 33608 | 33609 | case_stmt(details::e_sum , details::vec_add_op) 33610 | case_stmt(details::e_prod , details::vec_mul_op) 33611 | case_stmt(details::e_avg , details::vec_avg_op) 33612 | case_stmt(details::e_min , details::vec_min_op) 33613 | case_stmt(details::e_max , details::vec_max_op) 33614 | #undef case_stmt 33615 | default : return error_node(); 33616 | } 33617 | } 33618 | else 33619 | return error_node(); 33620 | } 33621 | 33622 | template <typename Allocator, 33623 | template <typename, typename> class Sequence> 33624 | inline expression_node_ptr vararg_function(const details::operator_type& operation, 33625 | Sequence<expression_node_ptr,Allocator>& arg_list) 33626 | { 33627 | if (!all_nodes_valid(arg_list)) 33628 | { 33629 | details::free_all_nodes(*node_allocator_,arg_list); 33630 | 33631 | return error_node(); 33632 | } 33633 | else if (is_constant_foldable(arg_list)) 33634 | return const_optimise_varargfunc(operation,arg_list); 33635 | else if ((1 == arg_list.size()) && details::is_ivector_node(arg_list[0])) 33636 | return vectorize_func(operation,arg_list); 33637 | else if ((1 == arg_list.size()) && special_one_parameter_vararg(operation)) 33638 | return arg_list[0]; 33639 | else if (all_nodes_variables(arg_list)) 33640 | return varnode_optimise_varargfunc(operation,arg_list); 33641 | 33642 | #ifndef exprtk_disable_string_capabilities 33643 | if (details::e_smulti == operation) 33644 | { 33645 | expression_node_ptr result = node_allocator_-> 33646 | allocate<details::str_vararg_node<Type,details::vararg_multi_op<Type> > >(arg_list); 33647 | if (result && result->valid()) 33648 | { 33649 | return result; 33650 | } 33651 | 33652 | parser_->set_error(parser_error::make_error( 33653 | parser_error::e_synthesis, 33654 | token_t(), 33655 | "ERR262 - Failed to synthesize node: str_vararg_node<vararg_multi_op>", 33656 | exprtk_error_location)); 33657 | 33658 | details::free_node(*node_allocator_, result); 33659 | } 33660 | else 33661 | #endif 33662 | { 33663 | expression_node_ptr result = error_node(); 33664 | 33665 | switch (operation) 33666 | { 33667 | #define case_stmt(op0, op1) \ 33668 | case op0 : result = node_allocator_-> \ 33669 | allocate<details::vararg_node<Type,op1<Type> > >(arg_list); \ 33670 | break; \ 33671 | 33672 | case_stmt(details::e_sum , details::vararg_add_op ) 33673 | case_stmt(details::e_prod , details::vararg_mul_op ) 33674 | case_stmt(details::e_avg , details::vararg_avg_op ) 33675 | case_stmt(details::e_min , details::vararg_min_op ) 33676 | case_stmt(details::e_max , details::vararg_max_op ) 33677 | case_stmt(details::e_mand , details::vararg_mand_op ) 33678 | case_stmt(details::e_mor , details::vararg_mor_op ) 33679 | case_stmt(details::e_multi , details::vararg_multi_op) 33680 | #undef case_stmt 33681 | default : return error_node(); 33682 | } 33683 | 33684 | if (result && result->valid()) 33685 | { 33686 | return result; 33687 | } 33688 | 33689 | parser_->set_error(parser_error::make_error( 33690 | parser_error::e_synthesis, 33691 | token_t(), 33692 | "ERR263 - Failed to synthesize node: vararg_node", 33693 | exprtk_error_location)); 33694 | 33695 | details::free_node(*node_allocator_, result); 33696 | } 33697 | 33698 | return error_node(); 33699 | } 33700 | 33701 | template <std::size_t N> 33702 | inline expression_node_ptr function(ifunction_t* f, expression_node_ptr (&b)[N]) 33703 | { 33704 | typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t; 33705 | expression_node_ptr result = synthesize_expression<function_N_node_t,N>(f,b); 33706 | 33707 | if (0 == result) 33708 | return error_node(); 33709 | else 33710 | { 33711 | // Can the function call be completely optimised? 33712 | if (details::is_constant_node(result)) 33713 | return result; 33714 | else if (!all_nodes_valid(b)) 33715 | { 33716 | details::free_node(*node_allocator_,result); 33717 | std::fill_n(b, N, reinterpret_cast<expression_node_ptr>(0)); 33718 | 33719 | return error_node(); 33720 | } 33721 | else if (N != f->param_count) 33722 | { 33723 | details::free_node(*node_allocator_,result); 33724 | std::fill_n(b, N, reinterpret_cast<expression_node_ptr>(0)); 33725 | 33726 | return error_node(); 33727 | } 33728 | 33729 | function_N_node_t* func_node_ptr = reinterpret_cast<function_N_node_t*>(result); 33730 | 33731 | if (!func_node_ptr->init_branches(b)) 33732 | { 33733 | details::free_node(*node_allocator_,result); 33734 | std::fill_n(b, N, reinterpret_cast<expression_node_ptr>(0)); 33735 | 33736 | return error_node(); 33737 | } 33738 | 33739 | if (result && result->valid()) 33740 | { 33741 | return result; 33742 | } 33743 | 33744 | parser_->set_error(parser_error::make_error( 33745 | parser_error::e_synthesis, 33746 | token_t(), 33747 | "ERR264 - Failed to synthesize node: function_N_node_t", 33748 | exprtk_error_location)); 33749 | 33750 | details::free_node(*node_allocator_, result); 33751 | return error_node(); 33752 | } 33753 | } 33754 | 33755 | inline expression_node_ptr function(ifunction_t* f) 33756 | { 33757 | typedef typename details::function_N_node<Type,ifunction_t,0> function_N_node_t; 33758 | return node_allocator_->allocate<function_N_node_t>(f); 33759 | } 33760 | 33761 | inline expression_node_ptr vararg_function_call(ivararg_function_t* vaf, 33762 | std::vector<expression_node_ptr>& arg_list) 33763 | { 33764 | if (!all_nodes_valid(arg_list)) 33765 | { 33766 | details::free_all_nodes(*node_allocator_,arg_list); 33767 | 33768 | return error_node(); 33769 | } 33770 | 33771 | typedef details::vararg_function_node<Type,ivararg_function_t> alloc_type; 33772 | 33773 | expression_node_ptr result = node_allocator_->allocate<alloc_type>(vaf,arg_list); 33774 | 33775 | if ( 33776 | !arg_list.empty() && 33777 | !vaf->has_side_effects() && 33778 | is_constant_foldable(arg_list) 33779 | ) 33780 | { 33781 | const Type v = result->value(); 33782 | details::free_node(*node_allocator_,result); 33783 | result = node_allocator_->allocate<literal_node_t>(v); 33784 | } 33785 | 33786 | parser_->state_.activate_side_effect("vararg_function_call()"); 33787 | 33788 | if (result && result->valid()) 33789 | { 33790 | return result; 33791 | } 33792 | 33793 | parser_->set_error(parser_error::make_error( 33794 | parser_error::e_synthesis, 33795 | token_t(), 33796 | "ERR265 - Failed to synthesize node: vararg_function_node<ivararg_function_t>", 33797 | exprtk_error_location)); 33798 | 33799 | details::free_node(*node_allocator_, result); 33800 | return error_node(); 33801 | } 33802 | 33803 | inline expression_node_ptr generic_function_call(igeneric_function_t* gf, 33804 | std::vector<expression_node_ptr>& arg_list, 33805 | const std::size_t& param_seq_index = std::numeric_limits<std::size_t>::max()) 33806 | { 33807 | if (!all_nodes_valid(arg_list)) 33808 | { 33809 | details::free_all_nodes(*node_allocator_,arg_list); 33810 | return error_node(); 33811 | } 33812 | 33813 | typedef details::generic_function_node <Type,igeneric_function_t> alloc_type1; 33814 | typedef details::multimode_genfunction_node<Type,igeneric_function_t> alloc_type2; 33815 | 33816 | const std::size_t no_psi = std::numeric_limits<std::size_t>::max(); 33817 | 33818 | expression_node_ptr result = error_node(); 33819 | std::string node_name = "Unknown" 33820 | 33821 | if (no_psi == param_seq_index) 33822 | { 33823 | result = node_allocator_->allocate<alloc_type1>(arg_list,gf); 33824 | node_name = "generic_function_node<igeneric_function_t>" 33825 | } 33826 | else 33827 | { 33828 | result = node_allocator_->allocate<alloc_type2>(gf, param_seq_index, arg_list); 33829 | node_name = "multimode_genfunction_node<igeneric_function_t>" 33830 | } 33831 | 33832 | alloc_type1* genfunc_node_ptr = static_cast<alloc_type1*>(result); 33833 | 33834 | assert(genfunc_node_ptr); 33835 | 33836 | if ( 33837 | !arg_list.empty() && 33838 | !gf->has_side_effects() && 33839 | parser_->state_.type_check_enabled && 33840 | is_constant_foldable(arg_list) 33841 | ) 33842 | { 33843 | genfunc_node_ptr->init_branches(); 33844 | 33845 | const Type v = result->value(); 33846 | 33847 | details::free_node(*node_allocator_,result); 33848 | 33849 | return node_allocator_->allocate<literal_node_t>(v); 33850 | } 33851 | else if (genfunc_node_ptr->init_branches()) 33852 | { 33853 | if (result && result->valid()) 33854 | { 33855 | parser_->state_.activate_side_effect("generic_function_call()"); 33856 | return result; 33857 | } 33858 | 33859 | parser_->set_error(parser_error::make_error( 33860 | parser_error::e_synthesis, 33861 | token_t(), 33862 | "ERR266 - Failed to synthesize node: " + node_name, 33863 | exprtk_error_location)); 33864 | 33865 | details::free_node(*node_allocator_, result); 33866 | return error_node(); 33867 | } 33868 | else 33869 | { 33870 | details::free_node(*node_allocator_, result); 33871 | details::free_all_nodes(*node_allocator_, arg_list); 33872 | 33873 | return error_node(); 33874 | } 33875 | } 33876 | 33877 | #ifndef exprtk_disable_string_capabilities 33878 | inline expression_node_ptr string_function_call(igeneric_function_t* gf, 33879 | std::vector<expression_node_ptr>& arg_list, 33880 | const std::size_t& param_seq_index = std::numeric_limits<std::size_t>::max()) 33881 | { 33882 | if (!all_nodes_valid(arg_list)) 33883 | { 33884 | details::free_all_nodes(*node_allocator_,arg_list); 33885 | return error_node(); 33886 | } 33887 | 33888 | typedef details::string_function_node <Type,igeneric_function_t> alloc_type1; 33889 | typedef details::multimode_strfunction_node<Type,igeneric_function_t> alloc_type2; 33890 | 33891 | const std::size_t no_psi = std::numeric_limits<std::size_t>::max(); 33892 | 33893 | expression_node_ptr result = error_node(); 33894 | std::string node_name = "Unknown" 33895 | 33896 | if (no_psi == param_seq_index) 33897 | { 33898 | result = node_allocator_->allocate<alloc_type1>(gf,arg_list); 33899 | node_name = "string_function_node<igeneric_function_t>" 33900 | } 33901 | else 33902 | { 33903 | result = node_allocator_->allocate<alloc_type2>(gf, param_seq_index, arg_list); 33904 | node_name = "multimode_strfunction_node<igeneric_function_t>" 33905 | } 33906 | 33907 | alloc_type1* strfunc_node_ptr = static_cast<alloc_type1*>(result); 33908 | 33909 | assert(strfunc_node_ptr); 33910 | 33911 | if ( 33912 | !arg_list.empty() && 33913 | !gf->has_side_effects() && 33914 | is_constant_foldable(arg_list) 33915 | ) 33916 | { 33917 | strfunc_node_ptr->init_branches(); 33918 | 33919 | const Type v = result->value(); 33920 | 33921 | details::free_node(*node_allocator_,result); 33922 | 33923 | return node_allocator_->allocate<literal_node_t>(v); 33924 | } 33925 | else if (strfunc_node_ptr->init_branches()) 33926 | { 33927 | if (result && result->valid()) 33928 | { 33929 | parser_->state_.activate_side_effect("string_function_call()"); 33930 | return result; 33931 | } 33932 | 33933 | parser_->set_error(parser_error::make_error( 33934 | parser_error::e_synthesis, 33935 | token_t(), 33936 | "ERR267 - Failed to synthesize node: " + node_name, 33937 | exprtk_error_location)); 33938 | 33939 | details::free_node(*node_allocator_, result); 33940 | return error_node(); 33941 | } 33942 | else 33943 | { 33944 | details::free_node (*node_allocator_,result ); 33945 | details::free_all_nodes(*node_allocator_,arg_list); 33946 | 33947 | return error_node(); 33948 | } 33949 | } 33950 | #endif 33951 | 33952 | #ifndef exprtk_disable_return_statement 33953 | inline expression_node_ptr return_call(std::vector<expression_node_ptr>& arg_list) 33954 | { 33955 | if (!all_nodes_valid(arg_list)) 33956 | { 33957 | details::free_all_nodes(*node_allocator_,arg_list); 33958 | return error_node(); 33959 | } 33960 | 33961 | typedef details::return_node<Type> alloc_type; 33962 | 33963 | expression_node_ptr result = node_allocator_-> 33964 | allocate_rr<alloc_type>(arg_list,parser_->results_ctx()); 33965 | 33966 | alloc_type* return_node_ptr = static_cast<alloc_type*>(result); 33967 | 33968 | assert(return_node_ptr); 33969 | 33970 | if (return_node_ptr->init_branches()) 33971 | { 33972 | if (result && result->valid()) 33973 | { 33974 | parser_->state_.activate_side_effect("return_call()"); 33975 | return result; 33976 | } 33977 | 33978 | parser_->set_error(parser_error::make_error( 33979 | parser_error::e_synthesis, 33980 | token_t(), 33981 | "ERR268 - Failed to synthesize node: return_node", 33982 | exprtk_error_location)); 33983 | 33984 | details::free_node(*node_allocator_, result); 33985 | return error_node(); 33986 | } 33987 | else 33988 | { 33989 | details::free_node (*node_allocator_, result ); 33990 | details::free_all_nodes(*node_allocator_, arg_list); 33991 | 33992 | return error_node(); 33993 | } 33994 | } 33995 | 33996 | inline expression_node_ptr return_envelope(expression_node_ptr body, 33997 | results_context_t* rc, 33998 | bool*& return_invoked) 33999 | { 34000 | typedef details::return_envelope_node<Type> alloc_type; 34001 | 34002 | expression_node_ptr result = node_allocator_-> 34003 | allocate_cr<alloc_type>(body,(*rc)); 34004 | 34005 | return_invoked = static_cast<alloc_type*>(result)->retinvk_ptr(); 34006 | 34007 | return result; 34008 | } 34009 | #else 34010 | inline expression_node_ptr return_call(std::vector<expression_node_ptr>&) 34011 | { 34012 | return error_node(); 34013 | } 34014 | 34015 | inline expression_node_ptr return_envelope(expression_node_ptr, 34016 | results_context_t*, 34017 | bool*&) 34018 | { 34019 | return error_node(); 34020 | } 34021 | #endif 34022 | 34023 | inline expression_node_ptr vector_element(const std::string& symbol, 34024 | vector_holder_ptr vector_base, 34025 | expression_node_ptr vec_node, 34026 | expression_node_ptr index) 34027 | { 34028 | expression_node_ptr result = error_node(); 34029 | std::string node_name = "Unknown" 34030 | 34031 | if (details::is_constant_node(index)) 34032 | { 34033 | const std::size_t vec_index = static_cast<std::size_t>(details::numeric::to_int64(index->value())); 34034 | 34035 | details::free_node(*node_allocator_,index); 34036 | 34037 | if (vec_index >= vector_base->size()) 34038 | { 34039 | parser_->set_error(parser_error::make_error( 34040 | parser_error::e_parser, 34041 | token_t(), 34042 | "ERR269 - Index of " + details::to_str(vec_index) + " out of range for " 34043 | "vector '" + symbol + "' of size " + details::to_str(vector_base->size()), 34044 | exprtk_error_location)); 34045 | 34046 | details::free_node(*node_allocator_,vec_node); 34047 | 34048 | return error_node(); 34049 | } 34050 | 34051 | if (vector_base->rebaseable()) 34052 | { 34053 | vector_access_runtime_check_ptr rtc = get_vector_access_runtime_check(); 34054 | 34055 | result = (rtc) ? 34056 | node_allocator_->allocate<rebasevector_celem_rtc_node_t>(vec_node, vec_index, vector_base, rtc) : 34057 | node_allocator_->allocate<rebasevector_celem_node_t >(vec_node, vec_index, vector_base ) ; 34058 | 34059 | node_name = (rtc) ? 34060 | "rebasevector_elem_rtc_node_t" : 34061 | "rebasevector_elem_node_t" ; 34062 | 34063 | if (result && result->valid()) 34064 | { 34065 | return result; 34066 | } 34067 | 34068 | parser_->set_error(parser_error::make_error( 34069 | parser_error::e_synthesis, 34070 | token_t(), 34071 | "ERR270 - Failed to synthesize node: " + node_name + " for vector: " + symbol, 34072 | exprtk_error_location)); 34073 | 34074 | details::free_node(*node_allocator_, result); 34075 | return error_node(); 34076 | } 34077 | else if (details::is_ivector_node(vec_node) && !details::is_vector_node(vec_node)) 34078 | { 34079 | vector_access_runtime_check_ptr rtc = get_vector_access_runtime_check(); 34080 | 34081 | result = (rtc) ? 34082 | node_allocator_->allocate<vector_celem_rtc_node_t>(vec_node, vec_index, vector_base, rtc) : 34083 | node_allocator_->allocate<vector_celem_node_t >(vec_node, vec_index, vector_base ) ; 34084 | 34085 | node_name = (rtc) ? 34086 | "vector_elem_rtc_node_t" : 34087 | "vector_elem_node_t" ; 34088 | 34089 | if (result && result->valid()) 34090 | { 34091 | return result; 34092 | } 34093 | 34094 | parser_->set_error(parser_error::make_error( 34095 | parser_error::e_synthesis, 34096 | token_t(), 34097 | "ERR271 - Failed to synthesize node: " + node_name + " for vector: " + symbol, 34098 | exprtk_error_location)); 34099 | 34100 | details::free_node(*node_allocator_, result); 34101 | return error_node(); 34102 | } 34103 | 34104 | const scope_element& se = parser_->sem_.get_element(symbol,vec_index); 34105 | 34106 | if (se.index == vec_index) 34107 | { 34108 | result = se.var_node; 34109 | details::free_node(*node_allocator_,vec_node); 34110 | } 34111 | else 34112 | { 34113 | scope_element nse; 34114 | nse.name = symbol; 34115 | nse.active = true; 34116 | nse.ref_count = 1; 34117 | nse.type = scope_element::e_vecelem; 34118 | nse.index = vec_index; 34119 | nse.depth = parser_->state_.scope_depth; 34120 | nse.data = 0; 34121 | nse.var_node = node_allocator_->allocate<variable_node_t>((*(*vector_base)[vec_index])); 34122 | 34123 | if (!parser_->sem_.add_element(nse)) 34124 | { 34125 | parser_->set_synthesis_error("Failed to add new local vector element to SEM [1]"); 34126 | 34127 | parser_->sem_.free_element(nse); 34128 | 34129 | result = error_node(); 34130 | } 34131 | 34132 | assert(parser_->sem_.total_local_symb_size_bytes() <= parser_->settings().max_total_local_symbol_size_bytes()); 34133 | 34134 | details::free_node(*node_allocator_,vec_node); 34135 | 34136 | exprtk_debug(("vector_element() - INFO - Added new local vector element: %s\n", nse.name.c_str())); 34137 | 34138 | parser_->state_.activate_side_effect("vector_element()"); 34139 | 34140 | result = nse.var_node; 34141 | node_name = "variable_node_t" 34142 | } 34143 | } 34144 | else 34145 | { 34146 | vector_access_runtime_check_ptr rtc = get_vector_access_runtime_check(); 34147 | 34148 | if (vector_base->rebaseable()) 34149 | { 34150 | result = (rtc) ? 34151 | node_allocator_->allocate<rebasevector_elem_rtc_node_t>(vec_node, index, vector_base, rtc) : 34152 | node_allocator_->allocate<rebasevector_elem_node_t >(vec_node, index, vector_base ) ; 34153 | 34154 | node_name = (rtc) ? 34155 | "rebasevector_elem_rtc_node_t" : 34156 | "rebasevector_elem_node_t" ; 34157 | } 34158 | else 34159 | { 34160 | result = rtc ? 34161 | node_allocator_->allocate<vector_elem_rtc_node_t>(vec_node, index, vector_base, rtc) : 34162 | node_allocator_->allocate<vector_elem_node_t >(vec_node, index, vector_base ) ; 34163 | 34164 | node_name = (rtc) ? 34165 | "vector_elem_rtc_node_t" : 34166 | "vector_elem_node_t" ; 34167 | } 34168 | } 34169 | 34170 | if (result && result->valid()) 34171 | { 34172 | return result; 34173 | } 34174 | 34175 | parser_->set_error(parser_error::make_error( 34176 | parser_error::e_synthesis, 34177 | token_t(), 34178 | "ERR272 - Failed to synthesize node: " + node_name, 34179 | exprtk_error_location)); 34180 | 34181 | details::free_node(*node_allocator_, result); 34182 | return error_node(); 34183 | } 34184 | 34185 | private: 34186 | 34187 | template <std::size_t N, typename NodePtr> 34188 | inline bool is_constant_foldable(NodePtr (&b)[N]) const 34189 | { 34190 | for (std::size_t i = 0; i < N; ++i) 34191 | { 34192 | if (0 == b[i]) 34193 | return false; 34194 | else if (!details::is_constant_node(b[i])) 34195 | return false; 34196 | } 34197 | 34198 | return true; 34199 | } 34200 | 34201 | template <typename NodePtr, 34202 | typename Allocator, 34203 | template <typename, typename> class Sequence> 34204 | inline bool is_constant_foldable(const Sequence<NodePtr,Allocator>& b) const 34205 | { 34206 | for (std::size_t i = 0; i < b.size(); ++i) 34207 | { 34208 | if (0 == b[i]) 34209 | return false; 34210 | else if (!details::is_constant_node(b[i])) 34211 | return false; 34212 | } 34213 | 34214 | return true; 34215 | } 34216 | 34217 | void lodge_assignment(symbol_type cst, expression_node_ptr node) 34218 | { 34219 | parser_->state_.activate_side_effect("lodge_assignment()"); 34220 | 34221 | if (!parser_->dec_.collect_assignments()) 34222 | return; 34223 | 34224 | std::string symbol_name; 34225 | 34226 | switch (cst) 34227 | { 34228 | case e_st_variable : symbol_name = parser_->symtab_store_ 34229 | .get_variable_name(node); 34230 | break; 34231 | 34232 | #ifndef exprtk_disable_string_capabilities 34233 | case e_st_string : symbol_name = parser_->symtab_store_ 34234 | .get_stringvar_name(node); 34235 | break; 34236 | #endif 34237 | 34238 | case e_st_vector : { 34239 | typedef details::vector_holder<T> vector_holder_t; 34240 | 34241 | vector_holder_t& vh = static_cast<vector_node_t*>(node)->vec_holder(); 34242 | 34243 | symbol_name = parser_->symtab_store_.get_vector_name(&vh); 34244 | } 34245 | break; 34246 | 34247 | case e_st_vecelem : { 34248 | typedef details::vector_holder<T> vector_holder_t; 34249 | 34250 | vector_holder_t& vh = static_cast<vector_elem_node_t*>(node)->vec_holder(); 34251 | 34252 | symbol_name = parser_->symtab_store_.get_vector_name(&vh); 34253 | 34254 | cst = e_st_vector; 34255 | } 34256 | break; 34257 | 34258 | default : return; 34259 | } 34260 | 34261 | if (!symbol_name.empty()) 34262 | { 34263 | parser_->dec_.add_assignment(symbol_name,cst); 34264 | } 34265 | } 34266 | 34267 | const void* base_ptr(expression_node_ptr node) 34268 | { 34269 | if (node) 34270 | { 34271 | switch (node->type()) 34272 | { 34273 | case details::expression_node<T>::e_variable: 34274 | return reinterpret_cast<const void*>(&static_cast<variable_node_t*>(node)->ref()); 34275 | 34276 | case details::expression_node<T>::e_vecelem: 34277 | return reinterpret_cast<const void*>(&static_cast<vector_elem_node_t*>(node)->ref()); 34278 | 34279 | case details::expression_node<T>::e_veccelem: 34280 | return reinterpret_cast<const void*>(&static_cast<vector_celem_node_t*>(node)->ref()); 34281 | 34282 | case details::expression_node<T>::e_vecelemrtc: 34283 | return reinterpret_cast<const void*>(&static_cast<vector_elem_rtc_node_t*>(node)->ref()); 34284 | 34285 | case details::expression_node<T>::e_veccelemrtc: 34286 | return reinterpret_cast<const void*>(&static_cast<vector_celem_rtc_node_t*>(node)->ref()); 34287 | 34288 | case details::expression_node<T>::e_rbvecelem: 34289 | return reinterpret_cast<const void*>(&static_cast<rebasevector_elem_node_t*>(node)->ref()); 34290 | 34291 | case details::expression_node<T>::e_rbvecelemrtc: 34292 | return reinterpret_cast<const void*>(&static_cast<rebasevector_elem_rtc_node_t*>(node)->ref()); 34293 | 34294 | case details::expression_node<T>::e_rbveccelem: 34295 | return reinterpret_cast<const void*>(&static_cast<rebasevector_celem_node_t*>(node)->ref()); 34296 | 34297 | case details::expression_node<T>::e_rbveccelemrtc: 34298 | return reinterpret_cast<const void*>(&static_cast<rebasevector_celem_rtc_node_t*>(node)->ref()); 34299 | 34300 | case details::expression_node<T>::e_vector: 34301 | return reinterpret_cast<const void*>(static_cast<vector_node_t*>(node)->vec_holder().data()); 34302 | 34303 | #ifndef exprtk_disable_string_capabilities 34304 | case details::expression_node<T>::e_stringvar: 34305 | return reinterpret_cast<const void*>((static_cast<stringvar_node_t*>(node)->base())); 34306 | 34307 | case details::expression_node<T>::e_stringvarrng: 34308 | return reinterpret_cast<const void*>((static_cast<string_range_node_t*>(node)->base())); 34309 | #endif 34310 | default : return reinterpret_cast<const void*>(0); 34311 | } 34312 | } 34313 | 34314 | return reinterpret_cast<const void*>(0); 34315 | } 34316 | 34317 | bool assign_immutable_symbol(expression_node_ptr node) 34318 | { 34319 | interval_t interval; 34320 | const void* baseptr_addr = base_ptr(node); 34321 | 34322 | exprtk_debug(("assign_immutable_symbol - base ptr addr: %p\n", baseptr_addr)); 34323 | 34324 | if (parser_->immutable_memory_map_.in_interval(baseptr_addr,interval)) 34325 | { 34326 | typename immutable_symtok_map_t::iterator itr = parser_->immutable_symtok_map_.find(interval); 34327 | 34328 | if (parser_->immutable_symtok_map_.end() != itr) 34329 | { 34330 | token_t& token = itr->second; 34331 | parser_->set_error(parser_error::make_error( 34332 | parser_error::e_parser, 34333 | token, 34334 | "ERR273 - Symbol '" + token.value + "' cannot be assigned-to as it is immutable.", 34335 | exprtk_error_location)); 34336 | } 34337 | else 34338 | parser_->set_synthesis_error("Unable to assign symbol is immutable."); 34339 | 34340 | return true; 34341 | } 34342 | 34343 | return false; 34344 | } 34345 | 34346 | inline expression_node_ptr synthesize_assignment_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2]) 34347 | { 34348 | if (assign_immutable_symbol(branch[0])) 34349 | { 34350 | return error_node(); 34351 | } 34352 | else if (details::is_variable_node(branch[0])) 34353 | { 34354 | lodge_assignment(e_st_variable,branch[0]); 34355 | return synthesize_expression<assignment_node_t,2>(operation,branch); 34356 | } 34357 | else if (details::is_vector_elem_node(branch[0]) || details::is_vector_celem_node(branch[0])) 34358 | { 34359 | lodge_assignment(e_st_vecelem,branch[0]); 34360 | return synthesize_expression<assignment_vec_elem_node_t, 2>(operation, branch); 34361 | } 34362 | else if (details::is_vector_elem_rtc_node(branch[0]) || details::is_vector_celem_rtc_node(branch[0])) 34363 | { 34364 | lodge_assignment(e_st_vecelem,branch[0]); 34365 | return synthesize_expression<assignment_vec_elem_rtc_node_t, 2>(operation, branch); 34366 | } 34367 | else if (details::is_rebasevector_elem_node(branch[0])) 34368 | { 34369 | lodge_assignment(e_st_vecelem,branch[0]); 34370 | return synthesize_expression<assignment_rebasevec_elem_node_t, 2>(operation, branch); 34371 | } 34372 | else if (details::is_rebasevector_elem_rtc_node(branch[0])) 34373 | { 34374 | lodge_assignment(e_st_vecelem,branch[0]); 34375 | return synthesize_expression<assignment_rebasevec_elem_rtc_node_t, 2>(operation, branch); 34376 | } 34377 | else if (details::is_rebasevector_celem_node(branch[0])) 34378 | { 34379 | lodge_assignment(e_st_vecelem,branch[0]); 34380 | return synthesize_expression<assignment_rebasevec_celem_node_t, 2>(operation, branch); 34381 | } 34382 | #ifndef exprtk_disable_string_capabilities 34383 | else if (details::is_string_node(branch[0])) 34384 | { 34385 | lodge_assignment(e_st_string,branch[0]); 34386 | return synthesize_expression<assignment_string_node_t,2>(operation, branch); 34387 | } 34388 | else if (details::is_string_range_node(branch[0])) 34389 | { 34390 | lodge_assignment(e_st_string,branch[0]); 34391 | return synthesize_expression<assignment_string_range_node_t,2>(operation, branch); 34392 | } 34393 | #endif 34394 | else if (details::is_vector_node(branch[0])) 34395 | { 34396 | lodge_assignment(e_st_vector,branch[0]); 34397 | 34398 | if (details::is_ivector_node(branch[1])) 34399 | return synthesize_expression<assignment_vecvec_node_t,2>(operation, branch); 34400 | else 34401 | return synthesize_expression<assignment_vec_node_t,2>(operation, branch); 34402 | } 34403 | else if (details::is_literal_node(branch[0])) 34404 | { 34405 | parser_->set_error(parser_error::make_error( 34406 | parser_error::e_syntax, 34407 | parser_->current_state().token, 34408 | "ERR274 - Cannot assign value to const variable", 34409 | exprtk_error_location)); 34410 | 34411 | return error_node(); 34412 | } 34413 | else 34414 | { 34415 | parser_->set_error(parser_error::make_error( 34416 | parser_error::e_syntax, 34417 | parser_->current_state().token, 34418 | "ERR275 - Invalid branches for assignment operator '" + details::to_str(operation) + "'", 34419 | exprtk_error_location)); 34420 | 34421 | return error_node(); 34422 | } 34423 | } 34424 | 34425 | inline expression_node_ptr synthesize_assignment_operation_expression(const details::operator_type& operation, 34426 | expression_node_ptr (&branch)[2]) 34427 | { 34428 | if (assign_immutable_symbol(branch[0])) 34429 | { 34430 | return error_node(); 34431 | } 34432 | 34433 | expression_node_ptr result = error_node(); 34434 | std::string node_name = "Unknown" 34435 | 34436 | if (details::is_variable_node(branch[0])) 34437 | { 34438 | lodge_assignment(e_st_variable,branch[0]); 34439 | 34440 | switch (operation) 34441 | { 34442 | #define case_stmt(op0, op1) \ 34443 | case op0 : result = node_allocator_-> \ 34444 | template allocate_rrr<typename details::assignment_op_node<Type,op1<Type> > > \ 34445 | (operation, branch[0], branch[1]); \ 34446 | node_name = "assignment_op_node" \ 34447 | break; \ 34448 | 34449 | case_stmt(details::e_addass , details::add_op) 34450 | case_stmt(details::e_subass , details::sub_op) 34451 | case_stmt(details::e_mulass , details::mul_op) 34452 | case_stmt(details::e_divass , details::div_op) 34453 | case_stmt(details::e_modass , details::mod_op) 34454 | #undef case_stmt 34455 | default : return error_node(); 34456 | } 34457 | } 34458 | else if (details::is_vector_elem_node(branch[0])) 34459 | { 34460 | lodge_assignment(e_st_vecelem,branch[0]); 34461 | 34462 | switch (operation) 34463 | { 34464 | #define case_stmt(op0, op1) \ 34465 | case op0 : result = node_allocator_-> \ 34466 | template allocate_rrr<typename details::assignment_vec_elem_op_node<Type,op1<Type> > > \ 34467 | (operation, branch[0], branch[1]); \ 34468 | node_name = "assignment_vec_elem_op_node" \ 34469 | break; \ 34470 | 34471 | case_stmt(details::e_addass , details::add_op) 34472 | case_stmt(details::e_subass , details::sub_op) 34473 | case_stmt(details::e_mulass , details::mul_op) 34474 | case_stmt(details::e_divass , details::div_op) 34475 | case_stmt(details::e_modass , details::mod_op) 34476 | #undef case_stmt 34477 | default : return error_node(); 34478 | } 34479 | } 34480 | else if (details::is_vector_elem_rtc_node(branch[0])) 34481 | { 34482 | lodge_assignment(e_st_vecelem,branch[0]); 34483 | 34484 | switch (operation) 34485 | { 34486 | #define case_stmt(op0, op1) \ 34487 | case op0 : result = node_allocator_-> \ 34488 | template allocate_rrr<typename details::assignment_vec_elem_op_rtc_node<Type,op1<Type> > > \ 34489 | (operation, branch[0], branch[1]); \ 34490 | node_name = "assignment_vec_elem_op_rtc_node" \ 34491 | break; \ 34492 | 34493 | case_stmt(details::e_addass , details::add_op) 34494 | case_stmt(details::e_subass , details::sub_op) 34495 | case_stmt(details::e_mulass , details::mul_op) 34496 | case_stmt(details::e_divass , details::div_op) 34497 | case_stmt(details::e_modass , details::mod_op) 34498 | #undef case_stmt 34499 | default : return error_node(); 34500 | } 34501 | } 34502 | else if (details::is_vector_celem_rtc_node(branch[0])) 34503 | { 34504 | lodge_assignment(e_st_vecelem,branch[0]); 34505 | 34506 | switch (operation) 34507 | { 34508 | #define case_stmt(op0, op1) \ 34509 | case op0 : result = node_allocator_-> \ 34510 | template allocate_rrr<typename details::assignment_vec_celem_op_rtc_node<Type,op1<Type> > > \ 34511 | (operation, branch[0], branch[1]); \ 34512 | node_name = "assignment_vec_celem_op_rtc_node" \ 34513 | break; \ 34514 | 34515 | case_stmt(details::e_addass , details::add_op) 34516 | case_stmt(details::e_subass , details::sub_op) 34517 | case_stmt(details::e_mulass , details::mul_op) 34518 | case_stmt(details::e_divass , details::div_op) 34519 | case_stmt(details::e_modass , details::mod_op) 34520 | #undef case_stmt 34521 | default : return error_node(); 34522 | } 34523 | } 34524 | else if (details::is_rebasevector_elem_node(branch[0])) 34525 | { 34526 | lodge_assignment(e_st_vecelem,branch[0]); 34527 | 34528 | switch (operation) 34529 | { 34530 | #define case_stmt(op0, op1) \ 34531 | case op0 : result = node_allocator_-> \ 34532 | template allocate_rrr<typename details::assignment_rebasevec_elem_op_node<Type,op1<Type> > > \ 34533 | (operation, branch[0], branch[1]); \ 34534 | node_name = "assignment_rebasevec_elem_op_node" \ 34535 | break; \ 34536 | 34537 | case_stmt(details::e_addass , details::add_op) 34538 | case_stmt(details::e_subass , details::sub_op) 34539 | case_stmt(details::e_mulass , details::mul_op) 34540 | case_stmt(details::e_divass , details::div_op) 34541 | case_stmt(details::e_modass , details::mod_op) 34542 | #undef case_stmt 34543 | default : return error_node(); 34544 | } 34545 | } 34546 | else if (details::is_rebasevector_celem_node(branch[0])) 34547 | { 34548 | lodge_assignment(e_st_vecelem,branch[0]); 34549 | 34550 | switch (operation) 34551 | { 34552 | #define case_stmt(op0, op1) \ 34553 | case op0 : result = node_allocator_-> \ 34554 | template allocate_rrr<typename details::assignment_rebasevec_celem_op_node<Type,op1<Type> > > \ 34555 | (operation, branch[0], branch[1]); \ 34556 | node_name = "assignment_rebasevec_celem_op_node" \ 34557 | break; \ 34558 | 34559 | case_stmt(details::e_addass , details::add_op) 34560 | case_stmt(details::e_subass , details::sub_op) 34561 | case_stmt(details::e_mulass , details::mul_op) 34562 | case_stmt(details::e_divass , details::div_op) 34563 | case_stmt(details::e_modass , details::mod_op) 34564 | #undef case_stmt 34565 | default : return error_node(); 34566 | } 34567 | } 34568 | else if (details::is_rebasevector_elem_rtc_node(branch[0])) 34569 | { 34570 | lodge_assignment(e_st_vecelem,branch[0]); 34571 | 34572 | switch (operation) 34573 | { 34574 | #define case_stmt(op0, op1) \ 34575 | case op0 : result = node_allocator_-> \ 34576 | template allocate_rrr<typename details::assignment_rebasevec_elem_op_rtc_node<Type,op1<Type> > > \ 34577 | (operation, branch[0], branch[1]); \ 34578 | node_name = "assignment_rebasevec_elem_op_rtc_node" \ 34579 | break; \ 34580 | 34581 | case_stmt(details::e_addass , details::add_op) 34582 | case_stmt(details::e_subass , details::sub_op) 34583 | case_stmt(details::e_mulass , details::mul_op) 34584 | case_stmt(details::e_divass , details::div_op) 34585 | case_stmt(details::e_modass , details::mod_op) 34586 | #undef case_stmt 34587 | default : return error_node(); 34588 | } 34589 | } 34590 | else if (details::is_rebasevector_celem_rtc_node(branch[0])) 34591 | { 34592 | lodge_assignment(e_st_vecelem,branch[0]); 34593 | 34594 | switch (operation) 34595 | { 34596 | #define case_stmt(op0, op1) \ 34597 | case op0 : result = node_allocator_-> \ 34598 | template allocate_rrr<typename details::assignment_rebasevec_celem_op_rtc_node<Type,op1<Type> > > \ 34599 | (operation, branch[0], branch[1]); \ 34600 | node_name = "assignment_rebasevec_celem_op_rtc_node" \ 34601 | break; \ 34602 | 34603 | case_stmt(details::e_addass , details::add_op) 34604 | case_stmt(details::e_subass , details::sub_op) 34605 | case_stmt(details::e_mulass , details::mul_op) 34606 | case_stmt(details::e_divass , details::div_op) 34607 | case_stmt(details::e_modass , details::mod_op) 34608 | #undef case_stmt 34609 | default : return error_node(); 34610 | } 34611 | } 34612 | else if (details::is_vector_node(branch[0])) 34613 | { 34614 | lodge_assignment(e_st_vector,branch[0]); 34615 | 34616 | if (details::is_ivector_node(branch[1])) 34617 | { 34618 | switch (operation) 34619 | { 34620 | #define case_stmt(op0, op1) \ 34621 | case op0 : result = node_allocator_-> \ 34622 | template allocate_rrr<typename details::assignment_vecvec_op_node<Type,op1<Type> > > \ 34623 | (operation, branch[0], branch[1]); \ 34624 | node_name = "assignment_rebasevec_celem_op_node" \ 34625 | break; \ 34626 | 34627 | case_stmt(details::e_addass , details::add_op) 34628 | case_stmt(details::e_subass , details::sub_op) 34629 | case_stmt(details::e_mulass , details::mul_op) 34630 | case_stmt(details::e_divass , details::div_op) 34631 | case_stmt(details::e_modass , details::mod_op) 34632 | #undef case_stmt 34633 | default : return error_node(); 34634 | } 34635 | } 34636 | else 34637 | { 34638 | switch (operation) 34639 | { 34640 | #define case_stmt(op0, op1) \ 34641 | case op0 : result = node_allocator_-> \ 34642 | template allocate_rrr<typename details::assignment_vec_op_node<Type,op1<Type> > > \ 34643 | (operation, branch[0], branch[1]); \ 34644 | node_name = "assignment_vec_op_node" \ 34645 | break; \ 34646 | 34647 | case_stmt(details::e_addass , details::add_op) 34648 | case_stmt(details::e_subass , details::sub_op) 34649 | case_stmt(details::e_mulass , details::mul_op) 34650 | case_stmt(details::e_divass , details::div_op) 34651 | case_stmt(details::e_modass , details::mod_op) 34652 | #undef case_stmt 34653 | default : return error_node(); 34654 | } 34655 | } 34656 | } 34657 | #ifndef exprtk_disable_string_capabilities 34658 | else if ( 34659 | (details::e_addass == operation) && 34660 | details::is_string_node(branch[0]) 34661 | ) 34662 | { 34663 | typedef details::assignment_string_node<T,details::asn_addassignment> addass_t; 34664 | 34665 | lodge_assignment(e_st_string,branch[0]); 34666 | 34667 | result = synthesize_expression<addass_t,2>(operation,branch); 34668 | node_name = "assignment_string_node<T,details::asn_addassignment>" 34669 | } 34670 | #endif 34671 | else 34672 | { 34673 | parser_->set_error(parser_error::make_error( 34674 | parser_error::e_syntax, 34675 | parser_->current_state().token, 34676 | "ERR276 - Invalid branches for assignment operator '" + details::to_str(operation) + "'", 34677 | exprtk_error_location)); 34678 | 34679 | return error_node(); 34680 | } 34681 | 34682 | if (result && result->valid()) 34683 | { 34684 | return result; 34685 | } 34686 | 34687 | parser_->set_error(parser_error::make_error( 34688 | parser_error::e_synthesis, 34689 | token_t(), 34690 | "ERR277 - Failed to synthesize node: " + node_name, 34691 | exprtk_error_location)); 34692 | 34693 | details::free_node(*node_allocator_, result); 34694 | return error_node(); 34695 | } 34696 | 34697 | inline expression_node_ptr synthesize_veceqineqlogic_operation_expression(const details::operator_type& operation, 34698 | expression_node_ptr (&branch)[2]) 34699 | { 34700 | const bool is_b0_ivec = details::is_ivector_node(branch[0]); 34701 | const bool is_b1_ivec = details::is_ivector_node(branch[1]); 34702 | 34703 | #define batch_eqineq_logic_case \ 34704 | case_stmt(details::e_lt , details::lt_op ) \ 34705 | case_stmt(details::e_lte , details::lte_op ) \ 34706 | case_stmt(details::e_gt , details::gt_op ) \ 34707 | case_stmt(details::e_gte , details::gte_op ) \ 34708 | case_stmt(details::e_eq , details::eq_op ) \ 34709 | case_stmt(details::e_ne , details::ne_op ) \ 34710 | case_stmt(details::e_equal , details::equal_op) \ 34711 | case_stmt(details::e_and , details::and_op ) \ 34712 | case_stmt(details::e_nand , details::nand_op ) \ 34713 | case_stmt(details::e_or , details::or_op ) \ 34714 | case_stmt(details::e_nor , details::nor_op ) \ 34715 | case_stmt(details::e_xor , details::xor_op ) \ 34716 | case_stmt(details::e_xnor , details::xnor_op ) \ 34717 | 34718 | expression_node_ptr result = error_node(); 34719 | std::string node_name = "Unknown" 34720 | 34721 | if (is_b0_ivec && is_b1_ivec) 34722 | { 34723 | switch (operation) 34724 | { 34725 | #define case_stmt(op0, op1) \ 34726 | case op0 : result = node_allocator_-> \ 34727 | template allocate_rrr<typename details::vec_binop_vecvec_node<Type,op1<Type> > > \ 34728 | (operation, branch[0], branch[1]); \ 34729 | node_name = "vec_binop_vecvec_node" \ 34730 | break; \ 34731 | 34732 | batch_eqineq_logic_case 34733 | #undef case_stmt 34734 | default : return error_node(); 34735 | } 34736 | } 34737 | else if (is_b0_ivec && !is_b1_ivec) 34738 | { 34739 | switch (operation) 34740 | { 34741 | #define case_stmt(op0, op1) \ 34742 | case op0 : result = node_allocator_-> \ 34743 | template allocate_rrr<typename details::vec_binop_vecval_node<Type,op1<Type> > > \ 34744 | (operation, branch[0], branch[1]); \ 34745 | node_name = "vec_binop_vecval_node" \ 34746 | break; \ 34747 | 34748 | batch_eqineq_logic_case 34749 | #undef case_stmt 34750 | default : return error_node(); 34751 | } 34752 | } 34753 | else if (!is_b0_ivec && is_b1_ivec) 34754 | { 34755 | switch (operation) 34756 | { 34757 | #define case_stmt(op0, op1) \ 34758 | case op0 : result = node_allocator_-> \ 34759 | template allocate_rrr<typename details::vec_binop_valvec_node<Type,op1<Type> > > \ 34760 | (operation, branch[0], branch[1]); \ 34761 | node_name = "vec_binop_valvec_node" \ 34762 | break; \ 34763 | 34764 | batch_eqineq_logic_case 34765 | #undef case_stmt 34766 | default : return error_node(); 34767 | } 34768 | } 34769 | else 34770 | return error_node(); 34771 | 34772 | if (result && result->valid()) 34773 | { 34774 | return result; 34775 | } 34776 | 34777 | parser_->set_error(parser_error::make_error( 34778 | parser_error::e_synthesis, 34779 | token_t(), 34780 | "ERR278 - Failed to synthesize node: " + node_name, 34781 | exprtk_error_location)); 34782 | 34783 | details::free_node(*node_allocator_, result); 34784 | return error_node(); 34785 | 34786 | #undef batch_eqineq_logic_case 34787 | } 34788 | 34789 | inline expression_node_ptr synthesize_vecarithmetic_operation_expression(const details::operator_type& operation, 34790 | expression_node_ptr (&branch)[2]) 34791 | { 34792 | const bool is_b0_ivec = details::is_ivector_node(branch[0]); 34793 | const bool is_b1_ivec = details::is_ivector_node(branch[1]); 34794 | 34795 | #define vector_ops \ 34796 | case_stmt(details::e_add , details::add_op) \ 34797 | case_stmt(details::e_sub , details::sub_op) \ 34798 | case_stmt(details::e_mul , details::mul_op) \ 34799 | case_stmt(details::e_div , details::div_op) \ 34800 | case_stmt(details::e_mod , details::mod_op) \ 34801 | 34802 | expression_node_ptr result = error_node(); 34803 | std::string node_name = "Unknown" 34804 | 34805 | if (is_b0_ivec && is_b1_ivec) 34806 | { 34807 | switch (operation) 34808 | { 34809 | #define case_stmt(op0, op1) \ 34810 | case op0 : result = node_allocator_-> \ 34811 | template allocate_rrr<typename details::vec_binop_vecvec_node<Type,op1<Type> > > \ 34812 | (operation, branch[0], branch[1]); \ 34813 | node_name = "vec_binop_vecvec_node" \ 34814 | break; \ 34815 | 34816 | vector_ops 34817 | case_stmt(details::e_pow,details:: pow_op) 34818 | #undef case_stmt 34819 | default : return error_node(); 34820 | } 34821 | } 34822 | else if (is_b0_ivec && !is_b1_ivec) 34823 | { 34824 | switch (operation) 34825 | { 34826 | #define case_stmt(op0, op1) \ 34827 | case op0 : result = node_allocator_-> \ 34828 | template allocate_rrr<typename details::vec_binop_vecval_node<Type,op1<Type> > > \ 34829 | (operation, branch[0], branch[1]); \ 34830 | node_name = "vec_binop_vecval_node(b0ivec,!b1ivec)" \ 34831 | break; \ 34832 | 34833 | vector_ops 34834 | case_stmt(details::e_pow,details:: pow_op) 34835 | #undef case_stmt 34836 | default : return error_node(); 34837 | } 34838 | } 34839 | else if (!is_b0_ivec && is_b1_ivec) 34840 | { 34841 | switch (operation) 34842 | { 34843 | #define case_stmt(op0, op1) \ 34844 | case op0 : result = node_allocator_-> \ 34845 | template allocate_rrr<typename details::vec_binop_valvec_node<Type,op1<Type> > > \ 34846 | (operation, branch[0], branch[1]); \ 34847 | node_name = "vec_binop_vecval_node(!b0ivec,b1ivec)" \ 34848 | break; \ 34849 | 34850 | vector_ops 34851 | #undef case_stmt 34852 | default : return error_node(); 34853 | } 34854 | } 34855 | else 34856 | return error_node(); 34857 | 34858 | if (result && result->valid()) 34859 | { 34860 | return result; 34861 | } 34862 | 34863 | parser_->set_error(parser_error::make_error( 34864 | parser_error::e_synthesis, 34865 | token_t(), 34866 | "ERR279 - Failed to synthesize node: " + node_name, 34867 | exprtk_error_location)); 34868 | 34869 | details::free_node(*node_allocator_, result); 34870 | return error_node(); 34871 | 34872 | #undef vector_ops 34873 | } 34874 | 34875 | inline expression_node_ptr synthesize_swap_expression(expression_node_ptr (&branch)[2]) 34876 | { 34877 | const bool v0_is_ivar = details::is_ivariable_node(branch[0]); 34878 | const bool v1_is_ivar = details::is_ivariable_node(branch[1]); 34879 | 34880 | const bool v0_is_ivec = details::is_ivector_node (branch[0]); 34881 | const bool v1_is_ivec = details::is_ivector_node (branch[1]); 34882 | 34883 | #ifndef exprtk_disable_string_capabilities 34884 | const bool v0_is_str = details::is_generally_string_node(branch[0]); 34885 | const bool v1_is_str = details::is_generally_string_node(branch[1]); 34886 | #endif 34887 | 34888 | expression_node_ptr result = error_node(); 34889 | std::string node_name = "Unknown" 34890 | 34891 | if (v0_is_ivar && v1_is_ivar) 34892 | { 34893 | typedef details::variable_node<T>* variable_node_ptr; 34894 | 34895 | variable_node_ptr v0 = variable_node_ptr(0); 34896 | variable_node_ptr v1 = variable_node_ptr(0); 34897 | 34898 | if ( 34899 | (0 != (v0 = dynamic_cast<variable_node_ptr>(branch[0]))) && 34900 | (0 != (v1 = dynamic_cast<variable_node_ptr>(branch[1]))) 34901 | ) 34902 | { 34903 | result = node_allocator_->allocate<details::swap_node<T> >(v0,v1); 34904 | node_name = "swap_node" 34905 | } 34906 | else 34907 | { 34908 | result = node_allocator_->allocate<details::swap_generic_node<T> >(branch[0],branch[1]); 34909 | node_name = "swap_generic_node" 34910 | } 34911 | } 34912 | else if (v0_is_ivec && v1_is_ivec) 34913 | { 34914 | result = node_allocator_->allocate<details::swap_vecvec_node<T> >(branch[0],branch[1]); 34915 | node_name = "swap_vecvec_node" 34916 | } 34917 | #ifndef exprtk_disable_string_capabilities 34918 | else if (v0_is_str && v1_is_str) 34919 | { 34920 | if (is_string_node(branch[0]) && is_string_node(branch[1])) 34921 | { 34922 | result = node_allocator_->allocate<details::swap_string_node<T> > 34923 | (branch[0], branch[1]); 34924 | node_name = "swap_string_node" 34925 | } 34926 | else 34927 | { 34928 | result = node_allocator_->allocate<details::swap_genstrings_node<T> > 34929 | (branch[0], branch[1]); 34930 | node_name = "swap_genstrings_node" 34931 | } 34932 | } 34933 | #endif 34934 | else 34935 | { 34936 | parser_->set_synthesis_error("Only variables, strings, vectors or vector elements can be swapped"); 34937 | return error_node(); 34938 | } 34939 | 34940 | if (result && result->valid()) 34941 | { 34942 | parser_->state_.activate_side_effect("synthesize_swap_expression()"); 34943 | return result; 34944 | } 34945 | 34946 | parser_->set_error(parser_error::make_error( 34947 | parser_error::e_synthesis, 34948 | token_t(), 34949 | "ERR280 - Failed to synthesize node: " + node_name, 34950 | exprtk_error_location)); 34951 | 34952 | details::free_node(*node_allocator_, result); 34953 | return error_node(); 34954 | } 34955 | 34956 | #ifndef exprtk_disable_sc_andor 34957 | inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2]) 34958 | { 34959 | expression_node_ptr result = error_node(); 34960 | 34961 | if (details::is_constant_node(branch[0])) 34962 | { 34963 | if ( 34964 | (details::e_scand == operation) && 34965 | std::equal_to<T>()(T(0),branch[0]->value()) 34966 | ) 34967 | result = node_allocator_->allocate_c<literal_node_t>(T(0)); 34968 | else if ( 34969 | (details::e_scor == operation) && 34970 | std::not_equal_to<T>()(T(0),branch[0]->value()) 34971 | ) 34972 | result = node_allocator_->allocate_c<literal_node_t>(T(1)); 34973 | } 34974 | 34975 | if (details::is_constant_node(branch[1]) && (0 == result)) 34976 | { 34977 | if ( 34978 | (details::e_scand == operation) && 34979 | std::equal_to<T>()(T(0),branch[1]->value()) 34980 | ) 34981 | result = node_allocator_->allocate_c<literal_node_t>(T(0)); 34982 | else if ( 34983 | (details::e_scor == operation) && 34984 | std::not_equal_to<T>()(T(0),branch[1]->value()) 34985 | ) 34986 | result = node_allocator_->allocate_c<literal_node_t>(T(1)); 34987 | } 34988 | 34989 | if (result) 34990 | { 34991 | details::free_node(*node_allocator_, branch[0]); 34992 | details::free_node(*node_allocator_, branch[1]); 34993 | 34994 | return result; 34995 | } 34996 | else if (details::e_scand == operation) 34997 | { 34998 | return synthesize_expression<scand_node_t,2>(operation, branch); 34999 | } 35000 | else if (details::e_scor == operation) 35001 | { 35002 | return synthesize_expression<scor_node_t,2>(operation, branch); 35003 | } 35004 | else 35005 | return error_node(); 35006 | } 35007 | #else 35008 | inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type&, expression_node_ptr (&)[2]) 35009 | { 35010 | return error_node(); 35011 | } 35012 | #endif 35013 | 35014 | #define basic_opr_switch_statements \ 35015 | case_stmt(details::e_add , details::add_op) \ 35016 | case_stmt(details::e_sub , details::sub_op) \ 35017 | case_stmt(details::e_mul , details::mul_op) \ 35018 | case_stmt(details::e_div , details::div_op) \ 35019 | case_stmt(details::e_mod , details::mod_op) \ 35020 | case_stmt(details::e_pow , details::pow_op) \ 35021 | 35022 | #define extended_opr_switch_statements \ 35023 | case_stmt(details::e_lt , details::lt_op ) \ 35024 | case_stmt(details::e_lte , details::lte_op ) \ 35025 | case_stmt(details::e_gt , details::gt_op ) \ 35026 | case_stmt(details::e_gte , details::gte_op ) \ 35027 | case_stmt(details::e_eq , details::eq_op ) \ 35028 | case_stmt(details::e_ne , details::ne_op ) \ 35029 | case_stmt(details::e_and , details::and_op ) \ 35030 | case_stmt(details::e_nand , details::nand_op) \ 35031 | case_stmt(details::e_or , details::or_op ) \ 35032 | case_stmt(details::e_nor , details::nor_op ) \ 35033 | case_stmt(details::e_xor , details::xor_op ) \ 35034 | case_stmt(details::e_xnor , details::xnor_op) \ 35035 | 35036 | #ifndef exprtk_disable_cardinal_pow_optimisation 35037 | template <typename TType, template <typename, typename> class IPowNode> 35038 | inline expression_node_ptr cardinal_pow_optimisation_impl(const TType& v, const unsigned int& p) 35039 | { 35040 | switch (p) 35041 | { 35042 | #define case_stmt(cp) \ 35043 | case cp : return node_allocator_-> \ 35044 | allocate<IPowNode<T,details::numeric::fast_exp<T,cp> > >(v); \ 35045 | 35046 | case_stmt( 1) case_stmt( 2) case_stmt( 3) case_stmt( 4) 35047 | case_stmt( 5) case_stmt( 6) case_stmt( 7) case_stmt( 8) 35048 | case_stmt( 9) case_stmt(10) case_stmt(11) case_stmt(12) 35049 | case_stmt(13) case_stmt(14) case_stmt(15) case_stmt(16) 35050 | case_stmt(17) case_stmt(18) case_stmt(19) case_stmt(20) 35051 | case_stmt(21) case_stmt(22) case_stmt(23) case_stmt(24) 35052 | case_stmt(25) case_stmt(26) case_stmt(27) case_stmt(28) 35053 | case_stmt(29) case_stmt(30) case_stmt(31) case_stmt(32) 35054 | case_stmt(33) case_stmt(34) case_stmt(35) case_stmt(36) 35055 | case_stmt(37) case_stmt(38) case_stmt(39) case_stmt(40) 35056 | case_stmt(41) case_stmt(42) case_stmt(43) case_stmt(44) 35057 | case_stmt(45) case_stmt(46) case_stmt(47) case_stmt(48) 35058 | case_stmt(49) case_stmt(50) case_stmt(51) case_stmt(52) 35059 | case_stmt(53) case_stmt(54) case_stmt(55) case_stmt(56) 35060 | case_stmt(57) case_stmt(58) case_stmt(59) case_stmt(60) 35061 | #undef case_stmt 35062 | default : return error_node(); 35063 | } 35064 | } 35065 | 35066 | inline expression_node_ptr cardinal_pow_optimisation(const T& v, const T& c) 35067 | { 35068 | const bool not_recipricol = (c >= T(0)); 35069 | const unsigned int p = static_cast<unsigned int>(details::numeric::to_int32(details::numeric::abs(c))); 35070 | 35071 | if (0 == p) 35072 | return node_allocator_->allocate_c<literal_node_t>(T(1)); 35073 | else if (std::equal_to<T>()(T(2),c)) 35074 | { 35075 | return node_allocator_-> 35076 | template allocate_rr<typename details::vov_node<Type,details::mul_op<Type> > >(v,v); 35077 | } 35078 | else 35079 | { 35080 | if (not_recipricol) 35081 | return cardinal_pow_optimisation_impl<T,details::ipow_node>(v,p); 35082 | else 35083 | return cardinal_pow_optimisation_impl<T,details::ipowinv_node>(v,p); 35084 | } 35085 | } 35086 | 35087 | inline bool cardinal_pow_optimisable(const details::operator_type& operation, const T& c) const 35088 | { 35089 | return (details::e_pow == operation) && (details::numeric::abs(c) <= T(60)) && details::numeric::is_integer(c); 35090 | } 35091 | 35092 | inline expression_node_ptr cardinal_pow_optimisation(expression_node_ptr (&branch)[2]) 35093 | { 35094 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 35095 | const bool not_recipricol = (c >= T(0)); 35096 | const unsigned int p = static_cast<unsigned int>(details::numeric::to_int32(details::numeric::abs(c))); 35097 | 35098 | node_allocator_->free(branch[1]); 35099 | 35100 | if (0 == p) 35101 | { 35102 | details::free_all_nodes(*node_allocator_, branch); 35103 | 35104 | return node_allocator_->allocate_c<literal_node_t>(T(1)); 35105 | } 35106 | else if (not_recipricol) 35107 | return cardinal_pow_optimisation_impl<expression_node_ptr,details::bipow_node>(branch[0],p); 35108 | else 35109 | return cardinal_pow_optimisation_impl<expression_node_ptr,details::bipowinv_node>(branch[0],p); 35110 | } 35111 | #else 35112 | inline expression_node_ptr cardinal_pow_optimisation(T&, const T&) 35113 | { 35114 | return error_node(); 35115 | } 35116 | 35117 | inline bool cardinal_pow_optimisable(const details::operator_type&, const T&) 35118 | { 35119 | return false; 35120 | } 35121 | 35122 | inline expression_node_ptr cardinal_pow_optimisation(expression_node_ptr(&)[2]) 35123 | { 35124 | return error_node(); 35125 | } 35126 | #endif 35127 | 35128 | struct synthesize_binary_ext_expression 35129 | { 35130 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 35131 | const details::operator_type& operation, 35132 | expression_node_ptr (&branch)[2]) 35133 | { 35134 | const bool left_neg = is_neg_unary_node(branch[0]); 35135 | const bool right_neg = is_neg_unary_node(branch[1]); 35136 | 35137 | if (left_neg && right_neg) 35138 | { 35139 | if ( 35140 | (details::e_add == operation) || 35141 | (details::e_sub == operation) || 35142 | (details::e_mul == operation) || 35143 | (details::e_div == operation) 35144 | ) 35145 | { 35146 | if ( 35147 | !expr_gen.parser_->simplify_unary_negation_branch(branch[0]) || 35148 | !expr_gen.parser_->simplify_unary_negation_branch(branch[1]) 35149 | ) 35150 | { 35151 | details::free_all_nodes(*expr_gen.node_allocator_,branch); 35152 | 35153 | return error_node(); 35154 | } 35155 | } 35156 | 35157 | switch (operation) 35158 | { 35159 | // -f(x + 1) + -g(y + 1) --> -(f(x + 1) + g(y + 1)) 35160 | case details::e_add : return expr_gen(details::e_neg, 35161 | expr_gen.node_allocator_-> 35162 | template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > > 35163 | (branch[0],branch[1])); 35164 | 35165 | // -f(x + 1) - -g(y + 1) --> g(y + 1) - f(x + 1) 35166 | case details::e_sub : return expr_gen.node_allocator_-> 35167 | template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > > 35168 | (branch[1],branch[0]); 35169 | 35170 | default : break; 35171 | } 35172 | } 35173 | else if (left_neg && !right_neg) 35174 | { 35175 | if ( 35176 | (details::e_add == operation) || 35177 | (details::e_sub == operation) || 35178 | (details::e_mul == operation) || 35179 | (details::e_div == operation) 35180 | ) 35181 | { 35182 | if (!expr_gen.parser_->simplify_unary_negation_branch(branch[0])) 35183 | { 35184 | details::free_all_nodes(*expr_gen.node_allocator_,branch); 35185 | 35186 | return error_node(); 35187 | } 35188 | 35189 | switch (operation) 35190 | { 35191 | // -f(x + 1) + g(y + 1) --> g(y + 1) - f(x + 1) 35192 | case details::e_add : return expr_gen.node_allocator_-> 35193 | template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > > 35194 | (branch[1], branch[0]); 35195 | 35196 | // -f(x + 1) - g(y + 1) --> -(f(x + 1) + g(y + 1)) 35197 | case details::e_sub : return expr_gen(details::e_neg, 35198 | expr_gen.node_allocator_-> 35199 | template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > > 35200 | (branch[0], branch[1])); 35201 | 35202 | // -f(x + 1) * g(y + 1) --> -(f(x + 1) * g(y + 1)) 35203 | case details::e_mul : return expr_gen(details::e_neg, 35204 | expr_gen.node_allocator_-> 35205 | template allocate<typename details::binary_ext_node<Type,details::mul_op<Type> > > 35206 | (branch[0], branch[1])); 35207 | 35208 | // -f(x + 1) / g(y + 1) --> -(f(x + 1) / g(y + 1)) 35209 | case details::e_div : return expr_gen(details::e_neg, 35210 | expr_gen.node_allocator_-> 35211 | template allocate<typename details::binary_ext_node<Type,details::div_op<Type> > > 35212 | (branch[0], branch[1])); 35213 | 35214 | default : return error_node(); 35215 | } 35216 | } 35217 | } 35218 | else if (!left_neg && right_neg) 35219 | { 35220 | if ( 35221 | (details::e_add == operation) || 35222 | (details::e_sub == operation) || 35223 | (details::e_mul == operation) || 35224 | (details::e_div == operation) 35225 | ) 35226 | { 35227 | if (!expr_gen.parser_->simplify_unary_negation_branch(branch[1])) 35228 | { 35229 | details::free_all_nodes(*expr_gen.node_allocator_,branch); 35230 | 35231 | return error_node(); 35232 | } 35233 | 35234 | switch (operation) 35235 | { 35236 | // f(x + 1) + -g(y + 1) --> f(x + 1) - g(y + 1) 35237 | case details::e_add : return expr_gen.node_allocator_-> 35238 | template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > > 35239 | (branch[0], branch[1]); 35240 | 35241 | // f(x + 1) - - g(y + 1) --> f(x + 1) + g(y + 1) 35242 | case details::e_sub : return expr_gen.node_allocator_-> 35243 | template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > > 35244 | (branch[0], branch[1]); 35245 | 35246 | // f(x + 1) * -g(y + 1) --> -(f(x + 1) * g(y + 1)) 35247 | case details::e_mul : return expr_gen(details::e_neg, 35248 | expr_gen.node_allocator_-> 35249 | template allocate<typename details::binary_ext_node<Type,details::mul_op<Type> > > 35250 | (branch[0], branch[1])); 35251 | 35252 | // f(x + 1) / -g(y + 1) --> -(f(x + 1) / g(y + 1)) 35253 | case details::e_div : return expr_gen(details::e_neg, 35254 | expr_gen.node_allocator_-> 35255 | template allocate<typename details::binary_ext_node<Type,details::div_op<Type> > > 35256 | (branch[0], branch[1])); 35257 | 35258 | default : return error_node(); 35259 | } 35260 | } 35261 | } 35262 | 35263 | switch (operation) 35264 | { 35265 | #define case_stmt(op0, op1) \ 35266 | case op0 : return expr_gen.node_allocator_-> \ 35267 | template allocate<typename details::binary_ext_node<Type,op1<Type> > > \ 35268 | (branch[0], branch[1]); \ 35269 | 35270 | basic_opr_switch_statements 35271 | extended_opr_switch_statements 35272 | #undef case_stmt 35273 | default : return error_node(); 35274 | } 35275 | } 35276 | }; 35277 | 35278 | struct synthesize_vob_expression 35279 | { 35280 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 35281 | const details::operator_type& operation, 35282 | expression_node_ptr (&branch)[2]) 35283 | { 35284 | const Type& v = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 35285 | 35286 | #ifndef exprtk_disable_enhanced_features 35287 | if (details::is_sf3ext_node(branch[1])) 35288 | { 35289 | expression_node_ptr result = error_node(); 35290 | 35291 | const bool synthesis_result = 35292 | synthesize_sf4ext_expression::template compile_right<vtype> 35293 | (expr_gen, v, operation, branch[1], result); 35294 | 35295 | if (synthesis_result) 35296 | { 35297 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35298 | return result; 35299 | } 35300 | } 35301 | #endif 35302 | 35303 | if ( 35304 | (details::e_mul == operation) || 35305 | (details::e_div == operation) 35306 | ) 35307 | { 35308 | if (details::is_uv_node(branch[1])) 35309 | { 35310 | typedef details::uv_base_node<Type>* uvbn_ptr_t; 35311 | 35312 | details::operator_type o = static_cast<uvbn_ptr_t>(branch[1])->operation(); 35313 | 35314 | if (details::e_neg == o) 35315 | { 35316 | const Type& v1 = static_cast<uvbn_ptr_t>(branch[1])->v(); 35317 | 35318 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35319 | 35320 | switch (operation) 35321 | { 35322 | case details::e_mul : return expr_gen(details::e_neg, 35323 | expr_gen.node_allocator_-> 35324 | template allocate_rr<typename details:: 35325 | vov_node<Type,details::mul_op<Type> > >(v,v1)); 35326 | 35327 | case details::e_div : return expr_gen(details::e_neg, 35328 | expr_gen.node_allocator_-> 35329 | template allocate_rr<typename details:: 35330 | vov_node<Type,details::div_op<Type> > >(v,v1)); 35331 | 35332 | default : break; 35333 | } 35334 | } 35335 | } 35336 | } 35337 | 35338 | switch (operation) 35339 | { 35340 | #define case_stmt(op0, op1) \ 35341 | case op0 : return expr_gen.node_allocator_-> \ 35342 | template allocate_rc<typename details::vob_node<Type,op1<Type> > > \ 35343 | (v, branch[1]); \ 35344 | 35345 | basic_opr_switch_statements 35346 | extended_opr_switch_statements 35347 | #undef case_stmt 35348 | default : return error_node(); 35349 | } 35350 | } 35351 | }; 35352 | 35353 | struct synthesize_bov_expression 35354 | { 35355 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 35356 | const details::operator_type& operation, 35357 | expression_node_ptr (&branch)[2]) 35358 | { 35359 | const Type& v = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 35360 | 35361 | #ifndef exprtk_disable_enhanced_features 35362 | if (details::is_sf3ext_node(branch[0])) 35363 | { 35364 | expression_node_ptr result = error_node(); 35365 | 35366 | const bool synthesis_result = 35367 | synthesize_sf4ext_expression::template compile_left<vtype> 35368 | (expr_gen, v, operation, branch[0], result); 35369 | 35370 | if (synthesis_result) 35371 | { 35372 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35373 | 35374 | return result; 35375 | } 35376 | } 35377 | #endif 35378 | 35379 | if ( 35380 | (details::e_add == operation) || 35381 | (details::e_sub == operation) || 35382 | (details::e_mul == operation) || 35383 | (details::e_div == operation) 35384 | ) 35385 | { 35386 | if (details::is_uv_node(branch[0])) 35387 | { 35388 | typedef details::uv_base_node<Type>* uvbn_ptr_t; 35389 | 35390 | details::operator_type o = static_cast<uvbn_ptr_t>(branch[0])->operation(); 35391 | 35392 | if (details::e_neg == o) 35393 | { 35394 | const Type& v0 = static_cast<uvbn_ptr_t>(branch[0])->v(); 35395 | 35396 | details::free_node(*expr_gen.node_allocator_,branch[0]); 35397 | 35398 | switch (operation) 35399 | { 35400 | case details::e_add : return expr_gen.node_allocator_-> 35401 | template allocate_rr<typename details:: 35402 | vov_node<Type,details::sub_op<Type> > >(v,v0); 35403 | 35404 | case details::e_sub : return expr_gen(details::e_neg, 35405 | expr_gen.node_allocator_-> 35406 | template allocate_rr<typename details:: 35407 | vov_node<Type,details::add_op<Type> > >(v0,v)); 35408 | 35409 | case details::e_mul : return expr_gen(details::e_neg, 35410 | expr_gen.node_allocator_-> 35411 | template allocate_rr<typename details:: 35412 | vov_node<Type,details::mul_op<Type> > >(v0,v)); 35413 | 35414 | case details::e_div : return expr_gen(details::e_neg, 35415 | expr_gen.node_allocator_-> 35416 | template allocate_rr<typename details:: 35417 | vov_node<Type,details::div_op<Type> > >(v0,v)); 35418 | default : break; 35419 | } 35420 | } 35421 | } 35422 | } 35423 | 35424 | switch (operation) 35425 | { 35426 | #define case_stmt(op0, op1) \ 35427 | case op0 : return expr_gen.node_allocator_-> \ 35428 | template allocate_cr<typename details::bov_node<Type,op1<Type> > > \ 35429 | (branch[0], v); \ 35430 | 35431 | basic_opr_switch_statements 35432 | extended_opr_switch_statements 35433 | #undef case_stmt 35434 | default : return error_node(); 35435 | } 35436 | } 35437 | }; 35438 | 35439 | struct synthesize_cob_expression 35440 | { 35441 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 35442 | const details::operator_type& operation, 35443 | expression_node_ptr (&branch)[2]) 35444 | { 35445 | const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); 35446 | 35447 | details::free_node(*expr_gen.node_allocator_,branch[0]); 35448 | 35449 | if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation)) 35450 | { 35451 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35452 | 35453 | return expr_gen(T(0)); 35454 | } 35455 | else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation)) 35456 | { 35457 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35458 | 35459 | return expr_gen(T(0)); 35460 | } 35461 | else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation)) 35462 | return branch[1]; 35463 | else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation)) 35464 | return branch[1]; 35465 | 35466 | if (details::is_cob_node(branch[1])) 35467 | { 35468 | // Simplify expressions of the form: 35469 | // 1. (1 * (2 * (3 * (4 * (5 * (6 * (7 * (8 * (9 + x))))))))) --> 40320 * (9 + x) 35470 | // 2. (1 + (2 + (3 + (4 + (5 + (6 + (7 + (8 + (9 + x))))))))) --> 45 + x 35471 | if ( 35472 | (details::e_mul == operation) || 35473 | (details::e_add == operation) 35474 | ) 35475 | { 35476 | details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]); 35477 | 35478 | if (operation == cobnode->operation()) 35479 | { 35480 | switch (operation) 35481 | { 35482 | case details::e_add : cobnode->set_c(c + cobnode->c()); break; 35483 | case details::e_mul : cobnode->set_c(c * cobnode->c()); break; 35484 | default : return error_node(); 35485 | } 35486 | 35487 | return cobnode; 35488 | } 35489 | } 35490 | 35491 | if (operation == details::e_mul) 35492 | { 35493 | details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]); 35494 | details::operator_type cob_opr = cobnode->operation(); 35495 | 35496 | if ( 35497 | (details::e_div == cob_opr) || 35498 | (details::e_mul == cob_opr) 35499 | ) 35500 | { 35501 | switch (cob_opr) 35502 | { 35503 | case details::e_div : cobnode->set_c(c * cobnode->c()); break; 35504 | case details::e_mul : cobnode->set_c(cobnode->c() / c); break; 35505 | default : return error_node(); 35506 | } 35507 | 35508 | return cobnode; 35509 | } 35510 | } 35511 | else if (operation == details::e_div) 35512 | { 35513 | details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]); 35514 | details::operator_type cob_opr = cobnode->operation(); 35515 | 35516 | if ( 35517 | (details::e_div == cob_opr) || 35518 | (details::e_mul == cob_opr) 35519 | ) 35520 | { 35521 | details::expression_node<Type>* new_cobnode = error_node(); 35522 | 35523 | switch (cob_opr) 35524 | { 35525 | case details::e_div : new_cobnode = expr_gen.node_allocator_-> 35526 | template allocate_tt<typename details::cob_node<Type,details::mul_op<Type> > > 35527 | (c / cobnode->c(), cobnode->move_branch(0)); 35528 | break; 35529 | 35530 | case details::e_mul : new_cobnode = expr_gen.node_allocator_-> 35531 | template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > > 35532 | (c / cobnode->c(), cobnode->move_branch(0)); 35533 | break; 35534 | 35535 | default : return error_node(); 35536 | } 35537 | 35538 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35539 | 35540 | return new_cobnode; 35541 | } 35542 | } 35543 | } 35544 | #ifndef exprtk_disable_enhanced_features 35545 | else if (details::is_sf3ext_node(branch[1])) 35546 | { 35547 | expression_node_ptr result = error_node(); 35548 | 35549 | const bool synthesis_result = 35550 | synthesize_sf4ext_expression::template compile_right<ctype> 35551 | (expr_gen, c, operation, branch[1], result); 35552 | 35553 | if (synthesis_result) 35554 | { 35555 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35556 | 35557 | return result; 35558 | } 35559 | } 35560 | #endif 35561 | 35562 | switch (operation) 35563 | { 35564 | #define case_stmt(op0, op1) \ 35565 | case op0 : return expr_gen.node_allocator_-> \ 35566 | template allocate_tt<typename details::cob_node<Type,op1<Type> > > \ 35567 | (c, branch[1]); \ 35568 | 35569 | basic_opr_switch_statements 35570 | extended_opr_switch_statements 35571 | #undef case_stmt 35572 | default : return error_node(); 35573 | } 35574 | } 35575 | }; 35576 | 35577 | struct synthesize_boc_expression 35578 | { 35579 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 35580 | const details::operator_type& operation, 35581 | expression_node_ptr (&branch)[2]) 35582 | { 35583 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 35584 | 35585 | details::free_node(*(expr_gen.node_allocator_), branch[1]); 35586 | 35587 | if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation)) 35588 | { 35589 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35590 | 35591 | return expr_gen(T(0)); 35592 | } 35593 | else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation)) 35594 | { 35595 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35596 | 35597 | return expr_gen(std::numeric_limits<T>::quiet_NaN()); 35598 | } 35599 | else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation)) 35600 | return branch[0]; 35601 | else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation)) 35602 | return branch[0]; 35603 | 35604 | if (details::is_boc_node(branch[0])) 35605 | { 35606 | // Simplify expressions of the form: 35607 | // 1. (((((((((x + 9) * 8) * 7) * 6) * 5) * 4) * 3) * 2) * 1) --> (x + 9) * 40320 35608 | // 2. (((((((((x + 9) + 8) + 7) + 6) + 5) + 4) + 3) + 2) + 1) --> x + 45 35609 | if ( 35610 | (details::e_mul == operation) || 35611 | (details::e_add == operation) 35612 | ) 35613 | { 35614 | details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]); 35615 | 35616 | if (operation == bocnode->operation()) 35617 | { 35618 | switch (operation) 35619 | { 35620 | case details::e_add : bocnode->set_c(c + bocnode->c()); break; 35621 | case details::e_mul : bocnode->set_c(c * bocnode->c()); break; 35622 | default : return error_node(); 35623 | } 35624 | 35625 | return bocnode; 35626 | } 35627 | } 35628 | else if (operation == details::e_div) 35629 | { 35630 | details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]); 35631 | details::operator_type boc_opr = bocnode->operation(); 35632 | 35633 | if ( 35634 | (details::e_div == boc_opr) || 35635 | (details::e_mul == boc_opr) 35636 | ) 35637 | { 35638 | switch (boc_opr) 35639 | { 35640 | case details::e_div : bocnode->set_c(c * bocnode->c()); break; 35641 | case details::e_mul : bocnode->set_c(bocnode->c() / c); break; 35642 | default : return error_node(); 35643 | } 35644 | 35645 | return bocnode; 35646 | } 35647 | } 35648 | else if (operation == details::e_pow) 35649 | { 35650 | // (v ^ c0) ^ c1 --> v ^(c0 * c1) 35651 | details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]); 35652 | details::operator_type boc_opr = bocnode->operation(); 35653 | 35654 | if (details::e_pow == boc_opr) 35655 | { 35656 | bocnode->set_c(bocnode->c() * c); 35657 | 35658 | return bocnode; 35659 | } 35660 | } 35661 | } 35662 | 35663 | #ifndef exprtk_disable_enhanced_features 35664 | if (details::is_sf3ext_node(branch[0])) 35665 | { 35666 | expression_node_ptr result = error_node(); 35667 | 35668 | const bool synthesis_result = 35669 | synthesize_sf4ext_expression::template compile_left<ctype> 35670 | (expr_gen, c, operation, branch[0], result); 35671 | 35672 | if (synthesis_result) 35673 | { 35674 | free_node(*expr_gen.node_allocator_, branch[0]); 35675 | 35676 | return result; 35677 | } 35678 | } 35679 | #endif 35680 | 35681 | switch (operation) 35682 | { 35683 | #define case_stmt(op0, op1) \ 35684 | case op0 : return expr_gen.node_allocator_-> \ 35685 | template allocate_cr<typename details::boc_node<Type,op1<Type> > > \ 35686 | (branch[0], c); \ 35687 | 35688 | basic_opr_switch_statements 35689 | extended_opr_switch_statements 35690 | #undef case_stmt 35691 | default : return error_node(); 35692 | } 35693 | } 35694 | }; 35695 | 35696 | struct synthesize_cocob_expression 35697 | { 35698 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 35699 | const details::operator_type& operation, 35700 | expression_node_ptr (&branch)[2]) 35701 | { 35702 | expression_node_ptr result = error_node(); 35703 | 35704 | // (cob) o c --> cob 35705 | if (details::is_cob_node(branch[0])) 35706 | { 35707 | details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[0]); 35708 | 35709 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 35710 | 35711 | if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation)) 35712 | { 35713 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35714 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35715 | 35716 | return expr_gen(T(0)); 35717 | } 35718 | else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation)) 35719 | { 35720 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35721 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35722 | 35723 | return expr_gen(T(std::numeric_limits<T>::quiet_NaN())); 35724 | } 35725 | else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation)) 35726 | { 35727 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35728 | 35729 | return branch[0]; 35730 | } 35731 | else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation)) 35732 | { 35733 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35734 | 35735 | return branch[0]; 35736 | } 35737 | else if (std::equal_to<T>()(T(1),c) && (details::e_div == operation)) 35738 | { 35739 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35740 | 35741 | return branch[0]; 35742 | } 35743 | 35744 | const bool op_addsub = (details::e_add == cobnode->operation()) || 35745 | (details::e_sub == cobnode->operation()) ; 35746 | 35747 | if (op_addsub) 35748 | { 35749 | switch (operation) 35750 | { 35751 | case details::e_add : cobnode->set_c(cobnode->c() + c); break; 35752 | case details::e_sub : cobnode->set_c(cobnode->c() - c); break; 35753 | default : return error_node(); 35754 | } 35755 | 35756 | result = cobnode; 35757 | } 35758 | else if (details::e_mul == cobnode->operation()) 35759 | { 35760 | switch (operation) 35761 | { 35762 | case details::e_mul : cobnode->set_c(cobnode->c() * c); break; 35763 | case details::e_div : cobnode->set_c(cobnode->c() / c); break; 35764 | default : return error_node(); 35765 | } 35766 | 35767 | result = cobnode; 35768 | } 35769 | else if (details::e_div == cobnode->operation()) 35770 | { 35771 | if (details::e_mul == operation) 35772 | { 35773 | cobnode->set_c(cobnode->c() * c); 35774 | result = cobnode; 35775 | } 35776 | else if (details::e_div == operation) 35777 | { 35778 | result = expr_gen.node_allocator_-> 35779 | template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > > 35780 | (cobnode->c() / c, cobnode->move_branch(0)); 35781 | 35782 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35783 | } 35784 | } 35785 | 35786 | if (result) 35787 | { 35788 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35789 | } 35790 | } 35791 | 35792 | // c o (cob) --> cob 35793 | else if (details::is_cob_node(branch[1])) 35794 | { 35795 | details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]); 35796 | 35797 | const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); 35798 | 35799 | if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation)) 35800 | { 35801 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35802 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35803 | 35804 | return expr_gen(T(0)); 35805 | } 35806 | else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation)) 35807 | { 35808 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35809 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35810 | 35811 | return expr_gen(T(0)); 35812 | } 35813 | else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation)) 35814 | { 35815 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35816 | 35817 | return branch[1]; 35818 | } 35819 | else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation)) 35820 | { 35821 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35822 | 35823 | return branch[1]; 35824 | } 35825 | 35826 | if (details::e_add == cobnode->operation()) 35827 | { 35828 | if (details::e_add == operation) 35829 | { 35830 | cobnode->set_c(c + cobnode->c()); 35831 | result = cobnode; 35832 | } 35833 | else if (details::e_sub == operation) 35834 | { 35835 | result = expr_gen.node_allocator_-> 35836 | template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > > 35837 | (c - cobnode->c(), cobnode->move_branch(0)); 35838 | 35839 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35840 | } 35841 | } 35842 | else if (details::e_sub == cobnode->operation()) 35843 | { 35844 | if (details::e_add == operation) 35845 | { 35846 | cobnode->set_c(c + cobnode->c()); 35847 | result = cobnode; 35848 | } 35849 | else if (details::e_sub == operation) 35850 | { 35851 | result = expr_gen.node_allocator_-> 35852 | template allocate_tt<typename details::cob_node<Type,details::add_op<Type> > > 35853 | (c - cobnode->c(), cobnode->move_branch(0)); 35854 | 35855 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35856 | } 35857 | } 35858 | else if (details::e_mul == cobnode->operation()) 35859 | { 35860 | if (details::e_mul == operation) 35861 | { 35862 | cobnode->set_c(c * cobnode->c()); 35863 | result = cobnode; 35864 | } 35865 | else if (details::e_div == operation) 35866 | { 35867 | result = expr_gen.node_allocator_-> 35868 | template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > > 35869 | (c / cobnode->c(), cobnode->move_branch(0)); 35870 | 35871 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35872 | } 35873 | } 35874 | else if (details::e_div == cobnode->operation()) 35875 | { 35876 | if (details::e_mul == operation) 35877 | { 35878 | cobnode->set_c(c * cobnode->c()); 35879 | result = cobnode; 35880 | } 35881 | else if (details::e_div == operation) 35882 | { 35883 | result = expr_gen.node_allocator_-> 35884 | template allocate_tt<typename details::cob_node<Type,details::mul_op<Type> > > 35885 | (c / cobnode->c(), cobnode->move_branch(0)); 35886 | 35887 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35888 | } 35889 | } 35890 | 35891 | if (result) 35892 | { 35893 | details::free_node(*expr_gen.node_allocator_,branch[0]); 35894 | } 35895 | } 35896 | 35897 | return result; 35898 | } 35899 | }; 35900 | 35901 | struct synthesize_coboc_expression 35902 | { 35903 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 35904 | const details::operator_type& operation, 35905 | expression_node_ptr (&branch)[2]) 35906 | { 35907 | expression_node_ptr result = error_node(); 35908 | 35909 | // (boc) o c --> boc 35910 | if (details::is_boc_node(branch[0])) 35911 | { 35912 | details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]); 35913 | 35914 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 35915 | 35916 | if (details::e_add == bocnode->operation()) 35917 | { 35918 | switch (operation) 35919 | { 35920 | case details::e_add : bocnode->set_c(bocnode->c() + c); break; 35921 | case details::e_sub : bocnode->set_c(bocnode->c() - c); break; 35922 | default : return error_node(); 35923 | } 35924 | 35925 | result = bocnode; 35926 | } 35927 | else if (details::e_mul == bocnode->operation()) 35928 | { 35929 | switch (operation) 35930 | { 35931 | case details::e_mul : bocnode->set_c(bocnode->c() * c); break; 35932 | case details::e_div : bocnode->set_c(bocnode->c() / c); break; 35933 | default : return error_node(); 35934 | } 35935 | 35936 | result = bocnode; 35937 | } 35938 | else if (details::e_sub == bocnode->operation()) 35939 | { 35940 | if (details::e_add == operation) 35941 | { 35942 | result = expr_gen.node_allocator_-> 35943 | template allocate_tt<typename details::boc_node<Type,details::add_op<Type> > > 35944 | (bocnode->move_branch(0), c - bocnode->c()); 35945 | 35946 | details::free_node(*expr_gen.node_allocator_,branch[0]); 35947 | } 35948 | else if (details::e_sub == operation) 35949 | { 35950 | bocnode->set_c(bocnode->c() + c); 35951 | result = bocnode; 35952 | } 35953 | } 35954 | else if (details::e_div == bocnode->operation()) 35955 | { 35956 | switch (operation) 35957 | { 35958 | case details::e_div : bocnode->set_c(bocnode->c() * c); break; 35959 | case details::e_mul : bocnode->set_c(bocnode->c() / c); break; 35960 | default : return error_node(); 35961 | } 35962 | 35963 | result = bocnode; 35964 | } 35965 | 35966 | if (result) 35967 | { 35968 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35969 | } 35970 | } 35971 | 35972 | // c o (boc) --> boc 35973 | else if (details::is_boc_node(branch[1])) 35974 | { 35975 | details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[1]); 35976 | 35977 | const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); 35978 | 35979 | if (details::e_add == bocnode->operation()) 35980 | { 35981 | if (details::e_add == operation) 35982 | { 35983 | bocnode->set_c(c + bocnode->c()); 35984 | result = bocnode; 35985 | } 35986 | else if (details::e_sub == operation) 35987 | { 35988 | result = expr_gen.node_allocator_-> 35989 | template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > > 35990 | (c - bocnode->c(), bocnode->move_branch(0)); 35991 | 35992 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35993 | } 35994 | } 35995 | else if (details::e_sub == bocnode->operation()) 35996 | { 35997 | if (details::e_add == operation) 35998 | { 35999 | result = expr_gen.node_allocator_-> 36000 | template allocate_tt<typename details::boc_node<Type,details::add_op<Type> > > 36001 | (bocnode->move_branch(0), c - bocnode->c()); 36002 | 36003 | details::free_node(*expr_gen.node_allocator_,branch[1]); 36004 | } 36005 | else if (details::e_sub == operation) 36006 | { 36007 | result = expr_gen.node_allocator_-> 36008 | template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > > 36009 | (c + bocnode->c(), bocnode->move_branch(0)); 36010 | 36011 | details::free_node(*expr_gen.node_allocator_,branch[1]); 36012 | } 36013 | } 36014 | else if (details::e_mul == bocnode->operation()) 36015 | { 36016 | if (details::e_mul == operation) 36017 | { 36018 | bocnode->set_c(c * bocnode->c()); 36019 | result = bocnode; 36020 | } 36021 | else if (details::e_div == operation) 36022 | { 36023 | result = expr_gen.node_allocator_-> 36024 | template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > > 36025 | (c / bocnode->c(), bocnode->move_branch(0)); 36026 | 36027 | details::free_node(*expr_gen.node_allocator_,branch[1]); 36028 | } 36029 | } 36030 | else if (details::e_div == bocnode->operation()) 36031 | { 36032 | if (details::e_mul == operation) 36033 | { 36034 | bocnode->set_c(bocnode->c() / c); 36035 | result = bocnode; 36036 | } 36037 | else if (details::e_div == operation) 36038 | { 36039 | result = expr_gen.node_allocator_-> 36040 | template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > > 36041 | (c * bocnode->c(), bocnode->move_branch(0)); 36042 | 36043 | details::free_node(*expr_gen.node_allocator_,branch[1]); 36044 | } 36045 | } 36046 | 36047 | if (result) 36048 | { 36049 | details::free_node(*expr_gen.node_allocator_,branch[0]); 36050 | } 36051 | } 36052 | 36053 | return result; 36054 | } 36055 | }; 36056 | 36057 | #ifndef exprtk_disable_enhanced_features 36058 | inline bool synthesize_expression(const details::operator_type& operation, 36059 | expression_node_ptr (&branch)[2], 36060 | expression_node_ptr& result) 36061 | { 36062 | result = error_node(); 36063 | 36064 | if (!operation_optimisable(operation)) 36065 | return false; 36066 | 36067 | const std::string node_id = branch_to_id(branch); 36068 | 36069 | const typename synthesize_map_t::iterator itr = synthesize_map_.find(node_id); 36070 | 36071 | if (synthesize_map_.end() != itr) 36072 | { 36073 | result = itr->second((*this), operation, branch); 36074 | 36075 | return true; 36076 | } 36077 | else 36078 | return false; 36079 | } 36080 | 36081 | struct synthesize_vov_expression 36082 | { 36083 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36084 | const details::operator_type& operation, 36085 | expression_node_ptr (&branch)[2]) 36086 | { 36087 | const Type& v1 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 36088 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 36089 | 36090 | switch (operation) 36091 | { 36092 | #define case_stmt(op0, op1) \ 36093 | case op0 : return expr_gen.node_allocator_-> \ 36094 | template allocate_rr<typename details::vov_node<Type,op1<Type> > > \ 36095 | (v1, v2); \ 36096 | 36097 | basic_opr_switch_statements 36098 | extended_opr_switch_statements 36099 | #undef case_stmt 36100 | default : return error_node(); 36101 | } 36102 | } 36103 | }; 36104 | 36105 | struct synthesize_cov_expression 36106 | { 36107 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36108 | const details::operator_type& operation, 36109 | expression_node_ptr (&branch)[2]) 36110 | { 36111 | const Type c = static_cast<details::literal_node<Type>*> (branch[0])->value(); 36112 | const Type& v = static_cast<details::variable_node<Type>*>(branch[1])->ref (); 36113 | 36114 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 36115 | 36116 | if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation)) 36117 | return expr_gen(T(0)); 36118 | else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation)) 36119 | return expr_gen(T(0)); 36120 | else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation)) 36121 | return static_cast<details::variable_node<Type>*>(branch[1]); 36122 | else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation)) 36123 | return static_cast<details::variable_node<Type>*>(branch[1]); 36124 | 36125 | switch (operation) 36126 | { 36127 | #define case_stmt(op0, op1) \ 36128 | case op0 : return expr_gen.node_allocator_-> \ 36129 | template allocate_cr<typename details::cov_node<Type,op1<Type> > > \ 36130 | (c, v); \ 36131 | 36132 | basic_opr_switch_statements 36133 | extended_opr_switch_statements 36134 | #undef case_stmt 36135 | default : return error_node(); 36136 | } 36137 | } 36138 | }; 36139 | 36140 | struct synthesize_voc_expression 36141 | { 36142 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36143 | const details::operator_type& operation, 36144 | expression_node_ptr (&branch)[2]) 36145 | { 36146 | const Type& v = static_cast<details::variable_node<Type>*>(branch[0])->ref (); 36147 | const Type c = static_cast<details::literal_node<Type>*> (branch[1])->value(); 36148 | 36149 | details::free_node(*(expr_gen.node_allocator_), branch[1]); 36150 | 36151 | if (expr_gen.cardinal_pow_optimisable(operation,c)) 36152 | { 36153 | if (std::equal_to<T>()(T(1),c)) 36154 | return branch[0]; 36155 | else 36156 | return expr_gen.cardinal_pow_optimisation(v,c); 36157 | } 36158 | else if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation)) 36159 | return expr_gen(T(0)); 36160 | else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation)) 36161 | return expr_gen(std::numeric_limits<T>::quiet_NaN()); 36162 | else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation)) 36163 | return static_cast<details::variable_node<Type>*>(branch[0]); 36164 | else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation)) 36165 | return static_cast<details::variable_node<Type>*>(branch[0]); 36166 | else if (std::equal_to<T>()(T(1),c) && (details::e_div == operation)) 36167 | return static_cast<details::variable_node<Type>*>(branch[0]); 36168 | 36169 | switch (operation) 36170 | { 36171 | #define case_stmt(op0, op1) \ 36172 | case op0 : return expr_gen.node_allocator_-> \ 36173 | template allocate_rc<typename details::voc_node<Type,op1<Type> > > \ 36174 | (v, c); \ 36175 | 36176 | basic_opr_switch_statements 36177 | extended_opr_switch_statements 36178 | #undef case_stmt 36179 | default : return error_node(); 36180 | } 36181 | } 36182 | }; 36183 | 36184 | struct synthesize_sf3ext_expression 36185 | { 36186 | template <typename T0, typename T1, typename T2> 36187 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36188 | const details::operator_type& sf3opr, 36189 | T0 t0, T1 t1, T2 t2) 36190 | { 36191 | switch (sf3opr) 36192 | { 36193 | #define case_stmt(op) \ 36194 | case details::e_sf##op : return details::T0oT1oT2_sf3ext<T,T0,T1,T2,details::sf##op##_op<Type> >:: \ 36195 | allocate(*(expr_gen.node_allocator_), t0, t1, t2); \ 36196 | 36197 | case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03) 36198 | case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07) 36199 | case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11) 36200 | case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15) 36201 | case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19) 36202 | case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23) 36203 | case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27) 36204 | case_stmt(28) case_stmt(29) case_stmt(30) 36205 | #undef case_stmt 36206 | default : return error_node(); 36207 | } 36208 | } 36209 | 36210 | template <typename T0, typename T1, typename T2> 36211 | static inline bool compile(expression_generator<Type>& expr_gen, const std::string& id, 36212 | T0 t0, T1 t1, T2 t2, 36213 | expression_node_ptr& result) 36214 | { 36215 | details::operator_type sf3opr; 36216 | 36217 | if (!expr_gen.sf3_optimisable(id,sf3opr)) 36218 | return false; 36219 | else 36220 | result = synthesize_sf3ext_expression::template process<T0, T1, T2> 36221 | (expr_gen, sf3opr, t0, t1, t2); 36222 | 36223 | return true; 36224 | } 36225 | }; 36226 | 36227 | struct synthesize_sf4ext_expression 36228 | { 36229 | template <typename T0, typename T1, typename T2, typename T3> 36230 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36231 | const details::operator_type& sf4opr, 36232 | T0 t0, T1 t1, T2 t2, T3 t3) 36233 | { 36234 | switch (sf4opr) 36235 | { 36236 | #define case_stmt0(op) \ 36237 | case details::e_sf##op : return details::T0oT1oT2oT3_sf4ext<Type,T0,T1,T2,T3,details::sf##op##_op<Type> >:: \ 36238 | allocate(*(expr_gen.node_allocator_), t0, t1, t2, t3); \ 36239 | 36240 | #define case_stmt1(op) \ 36241 | case details::e_sf4ext##op : return details::T0oT1oT2oT3_sf4ext<Type,T0,T1,T2,T3,details::sfext##op##_op<Type> >:: \ 36242 | allocate(*(expr_gen.node_allocator_), t0, t1, t2, t3); \ 36243 | 36244 | case_stmt0(48) case_stmt0(49) case_stmt0(50) case_stmt0(51) 36245 | case_stmt0(52) case_stmt0(53) case_stmt0(54) case_stmt0(55) 36246 | case_stmt0(56) case_stmt0(57) case_stmt0(58) case_stmt0(59) 36247 | case_stmt0(60) case_stmt0(61) case_stmt0(62) case_stmt0(63) 36248 | case_stmt0(64) case_stmt0(65) case_stmt0(66) case_stmt0(67) 36249 | case_stmt0(68) case_stmt0(69) case_stmt0(70) case_stmt0(71) 36250 | case_stmt0(72) case_stmt0(73) case_stmt0(74) case_stmt0(75) 36251 | case_stmt0(76) case_stmt0(77) case_stmt0(78) case_stmt0(79) 36252 | case_stmt0(80) case_stmt0(81) case_stmt0(82) case_stmt0(83) 36253 | 36254 | case_stmt1(00) case_stmt1(01) case_stmt1(02) case_stmt1(03) 36255 | case_stmt1(04) case_stmt1(05) case_stmt1(06) case_stmt1(07) 36256 | case_stmt1(08) case_stmt1(09) case_stmt1(10) case_stmt1(11) 36257 | case_stmt1(12) case_stmt1(13) case_stmt1(14) case_stmt1(15) 36258 | case_stmt1(16) case_stmt1(17) case_stmt1(18) case_stmt1(19) 36259 | case_stmt1(20) case_stmt1(21) case_stmt1(22) case_stmt1(23) 36260 | case_stmt1(24) case_stmt1(25) case_stmt1(26) case_stmt1(27) 36261 | case_stmt1(28) case_stmt1(29) case_stmt1(30) case_stmt1(31) 36262 | case_stmt1(32) case_stmt1(33) case_stmt1(34) case_stmt1(35) 36263 | case_stmt1(36) case_stmt1(37) case_stmt1(38) case_stmt1(39) 36264 | case_stmt1(40) case_stmt1(41) case_stmt1(42) case_stmt1(43) 36265 | case_stmt1(44) case_stmt1(45) case_stmt1(46) case_stmt1(47) 36266 | case_stmt1(48) case_stmt1(49) case_stmt1(50) case_stmt1(51) 36267 | case_stmt1(52) case_stmt1(53) case_stmt1(54) case_stmt1(55) 36268 | case_stmt1(56) case_stmt1(57) case_stmt1(58) case_stmt1(59) 36269 | case_stmt1(60) case_stmt1(61) 36270 | 36271 | #undef case_stmt0 36272 | #undef case_stmt1 36273 | default : return error_node(); 36274 | } 36275 | } 36276 | 36277 | template <typename T0, typename T1, typename T2, typename T3> 36278 | static inline bool compile(expression_generator<Type>& expr_gen, const std::string& id, 36279 | T0 t0, T1 t1, T2 t2, T3 t3, 36280 | expression_node_ptr& result) 36281 | { 36282 | details::operator_type sf4opr; 36283 | 36284 | if (!expr_gen.sf4_optimisable(id,sf4opr)) 36285 | return false; 36286 | else 36287 | result = synthesize_sf4ext_expression::template process<T0, T1, T2, T3> 36288 | (expr_gen, sf4opr, t0, t1, t2, t3); 36289 | 36290 | return true; 36291 | } 36292 | 36293 | // T o (sf3ext) 36294 | template <typename ExternalType> 36295 | static inline bool compile_right(expression_generator<Type>& expr_gen, 36296 | ExternalType t, 36297 | const details::operator_type& operation, 36298 | expression_node_ptr& sf3node, 36299 | expression_node_ptr& result) 36300 | { 36301 | if (!details::is_sf3ext_node(sf3node)) 36302 | return false; 36303 | 36304 | typedef details::T0oT1oT2_base_node<Type>* sf3ext_base_ptr; 36305 | 36306 | sf3ext_base_ptr n = static_cast<sf3ext_base_ptr>(sf3node); 36307 | const std::string id = "t" + expr_gen.to_str(operation) + "(" + n->type_id() + ")" 36308 | 36309 | switch (n->type()) 36310 | { 36311 | case details::expression_node<Type>::e_covoc : return compile_right_impl 36312 | <typename covoc_t::sf3_type_node,ExternalType, ctype, vtype, ctype> 36313 | (expr_gen, id, t, sf3node, result); 36314 | 36315 | case details::expression_node<Type>::e_covov : return compile_right_impl 36316 | <typename covov_t::sf3_type_node,ExternalType, ctype, vtype, vtype> 36317 | (expr_gen, id, t, sf3node, result); 36318 | 36319 | case details::expression_node<Type>::e_vocov : return compile_right_impl 36320 | <typename vocov_t::sf3_type_node,ExternalType, vtype, ctype, vtype> 36321 | (expr_gen, id, t, sf3node, result); 36322 | 36323 | case details::expression_node<Type>::e_vovoc : return compile_right_impl 36324 | <typename vovoc_t::sf3_type_node,ExternalType, vtype, vtype, ctype> 36325 | (expr_gen, id, t, sf3node, result); 36326 | 36327 | case details::expression_node<Type>::e_vovov : return compile_right_impl 36328 | <typename vovov_t::sf3_type_node,ExternalType, vtype, vtype, vtype> 36329 | (expr_gen, id, t, sf3node, result); 36330 | 36331 | default : return false; 36332 | } 36333 | } 36334 | 36335 | // (sf3ext) o T 36336 | template <typename ExternalType> 36337 | static inline bool compile_left(expression_generator<Type>& expr_gen, 36338 | ExternalType t, 36339 | const details::operator_type& operation, 36340 | expression_node_ptr& sf3node, 36341 | expression_node_ptr& result) 36342 | { 36343 | if (!details::is_sf3ext_node(sf3node)) 36344 | return false; 36345 | 36346 | typedef details::T0oT1oT2_base_node<Type>* sf3ext_base_ptr; 36347 | 36348 | sf3ext_base_ptr n = static_cast<sf3ext_base_ptr>(sf3node); 36349 | 36350 | const std::string id = "(" + n->type_id() + ")" + expr_gen.to_str(operation) + "t" 36351 | 36352 | switch (n->type()) 36353 | { 36354 | case details::expression_node<Type>::e_covoc : return compile_left_impl 36355 | <typename covoc_t::sf3_type_node,ExternalType, ctype, vtype, ctype> 36356 | (expr_gen, id, t, sf3node, result); 36357 | 36358 | case details::expression_node<Type>::e_covov : return compile_left_impl 36359 | <typename covov_t::sf3_type_node,ExternalType, ctype, vtype, vtype> 36360 | (expr_gen, id, t, sf3node, result); 36361 | 36362 | case details::expression_node<Type>::e_vocov : return compile_left_impl 36363 | <typename vocov_t::sf3_type_node,ExternalType, vtype, ctype, vtype> 36364 | (expr_gen, id, t, sf3node, result); 36365 | 36366 | case details::expression_node<Type>::e_vovoc : return compile_left_impl 36367 | <typename vovoc_t::sf3_type_node,ExternalType, vtype, vtype, ctype> 36368 | (expr_gen, id, t, sf3node, result); 36369 | 36370 | case details::expression_node<Type>::e_vovov : return compile_left_impl 36371 | <typename vovov_t::sf3_type_node,ExternalType, vtype, vtype, vtype> 36372 | (expr_gen, id, t, sf3node, result); 36373 | 36374 | default : return false; 36375 | } 36376 | } 36377 | 36378 | template <typename SF3TypeNode, typename ExternalType, typename T0, typename T1, typename T2> 36379 | static inline bool compile_right_impl(expression_generator<Type>& expr_gen, 36380 | const std::string& id, 36381 | ExternalType t, 36382 | expression_node_ptr& node, 36383 | expression_node_ptr& result) 36384 | { 36385 | SF3TypeNode* n = dynamic_cast<SF3TypeNode*>(node); 36386 | 36387 | if (n) 36388 | { 36389 | T0 t0 = n->t0(); 36390 | T1 t1 = n->t1(); 36391 | T2 t2 = n->t2(); 36392 | 36393 | return synthesize_sf4ext_expression::template compile<ExternalType, T0, T1, T2> 36394 | (expr_gen, id, t, t0, t1, t2, result); 36395 | } 36396 | else 36397 | return false; 36398 | } 36399 | 36400 | template <typename SF3TypeNode, typename ExternalType, typename T0, typename T1, typename T2> 36401 | static inline bool compile_left_impl(expression_generator<Type>& expr_gen, 36402 | const std::string& id, 36403 | ExternalType t, 36404 | expression_node_ptr& node, 36405 | expression_node_ptr& result) 36406 | { 36407 | SF3TypeNode* n = dynamic_cast<SF3TypeNode*>(node); 36408 | 36409 | if (n) 36410 | { 36411 | T0 t0 = n->t0(); 36412 | T1 t1 = n->t1(); 36413 | T2 t2 = n->t2(); 36414 | 36415 | return synthesize_sf4ext_expression::template compile<T0, T1, T2, ExternalType> 36416 | (expr_gen, id, t0, t1, t2, t, result); 36417 | } 36418 | else 36419 | return false; 36420 | } 36421 | }; 36422 | 36423 | struct synthesize_vovov_expression0 36424 | { 36425 | typedef typename vovov_t::type0 node_type; 36426 | typedef typename vovov_t::sf3_type sf3_type; 36427 | 36428 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36429 | const details::operator_type& operation, 36430 | expression_node_ptr (&branch)[2]) 36431 | { 36432 | // (v0 o0 v1) o1 (v2) 36433 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]); 36434 | const Type& v0 = vov->v0(); 36435 | const Type& v1 = vov->v1(); 36436 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 36437 | const details::operator_type o0 = vov->operation(); 36438 | const details::operator_type o1 = operation; 36439 | 36440 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 36441 | 36442 | expression_node_ptr result = error_node(); 36443 | 36444 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36445 | { 36446 | // (v0 / v1) / v2 --> (vovov) v0 / (v1 * v2) 36447 | if ((details::e_div == o0) && (details::e_div == o1)) 36448 | { 36449 | const bool synthesis_result = 36450 | synthesize_sf3ext_expression:: 36451 | template compile<vtype, vtype, vtype>(expr_gen, "t/(t*t)", v0, v1, v2, result); 36452 | 36453 | exprtk_debug(("(v0 / v1) / v2 --> (vovov) v0 / (v1 * v2)\n")); 36454 | 36455 | return (synthesis_result) ? result : error_node(); 36456 | } 36457 | } 36458 | 36459 | const bool synthesis_result = 36460 | synthesize_sf3ext_expression::template compile<vtype, vtype, vtype> 36461 | (expr_gen, id(expr_gen, o0, o1), v0, v1, v2, result); 36462 | 36463 | if (synthesis_result) 36464 | return result; 36465 | 36466 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36467 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36468 | 36469 | if (!expr_gen.valid_operator(o0,f0)) 36470 | return error_node(); 36471 | else if (!expr_gen.valid_operator(o1,f1)) 36472 | return error_node(); 36473 | else 36474 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, f0, f1); 36475 | } 36476 | 36477 | static inline std::string id(expression_generator<Type>& expr_gen, 36478 | const details::operator_type o0, 36479 | const details::operator_type o1) 36480 | { 36481 | return details::build_string() 36482 | << "(t" << expr_gen.to_str(o0) 36483 | << "t)" << expr_gen.to_str(o1) 36484 | << "t" 36485 | } 36486 | }; 36487 | 36488 | struct synthesize_vovov_expression1 36489 | { 36490 | typedef typename vovov_t::type1 node_type; 36491 | typedef typename vovov_t::sf3_type sf3_type; 36492 | 36493 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36494 | const details::operator_type& operation, 36495 | expression_node_ptr (&branch)[2]) 36496 | { 36497 | // (v0) o0 (v1 o1 v2) 36498 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]); 36499 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 36500 | const Type& v1 = vov->v0(); 36501 | const Type& v2 = vov->v1(); 36502 | const details::operator_type o0 = operation; 36503 | const details::operator_type o1 = vov->operation(); 36504 | 36505 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 36506 | 36507 | expression_node_ptr result = error_node(); 36508 | 36509 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36510 | { 36511 | // v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1 36512 | if ((details::e_div == o0) && (details::e_div == o1)) 36513 | { 36514 | const bool synthesis_result = 36515 | synthesize_sf3ext_expression:: 36516 | template compile<vtype, vtype, vtype>(expr_gen, "(t*t)/t", v0, v2, v1, result); 36517 | 36518 | exprtk_debug(("v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1\n")); 36519 | 36520 | return (synthesis_result) ? result : error_node(); 36521 | } 36522 | } 36523 | 36524 | const bool synthesis_result = 36525 | synthesize_sf3ext_expression::template compile<vtype, vtype, vtype> 36526 | (expr_gen, id(expr_gen, o0, o1), v0, v1, v2, result); 36527 | 36528 | if (synthesis_result) 36529 | return result; 36530 | 36531 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36532 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36533 | 36534 | if (!expr_gen.valid_operator(o0,f0)) 36535 | return error_node(); 36536 | else if (!expr_gen.valid_operator(o1,f1)) 36537 | return error_node(); 36538 | else 36539 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, f0, f1); 36540 | } 36541 | 36542 | static inline std::string id(expression_generator<Type>& expr_gen, 36543 | const details::operator_type o0, 36544 | const details::operator_type o1) 36545 | { 36546 | return details::build_string() 36547 | << "t" << expr_gen.to_str(o0) 36548 | << "(t" << expr_gen.to_str(o1) 36549 | << "t)" 36550 | } 36551 | }; 36552 | 36553 | struct synthesize_vovoc_expression0 36554 | { 36555 | typedef typename vovoc_t::type0 node_type; 36556 | typedef typename vovoc_t::sf3_type sf3_type; 36557 | 36558 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36559 | const details::operator_type& operation, 36560 | expression_node_ptr (&branch)[2]) 36561 | { 36562 | // (v0 o0 v1) o1 (c) 36563 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]); 36564 | const Type& v0 = vov->v0(); 36565 | const Type& v1 = vov->v1(); 36566 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 36567 | const details::operator_type o0 = vov->operation(); 36568 | const details::operator_type o1 = operation; 36569 | 36570 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 36571 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 36572 | 36573 | expression_node_ptr result = error_node(); 36574 | 36575 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36576 | { 36577 | // (v0 / v1) / c --> (vovoc) v0 / (v1 * c) 36578 | if ((details::e_div == o0) && (details::e_div == o1)) 36579 | { 36580 | const bool synthesis_result = 36581 | synthesize_sf3ext_expression:: 36582 | template compile<vtype, vtype, ctype>(expr_gen, "t/(t*t)", v0, v1, c, result); 36583 | 36584 | exprtk_debug(("(v0 / v1) / c --> (vovoc) v0 / (v1 * c)\n")); 36585 | 36586 | return (synthesis_result) ? result : error_node(); 36587 | } 36588 | } 36589 | 36590 | const bool synthesis_result = 36591 | synthesize_sf3ext_expression::template compile<vtype, vtype, ctype> 36592 | (expr_gen, id(expr_gen, o0, o1), v0, v1, c, result); 36593 | 36594 | if (synthesis_result) 36595 | return result; 36596 | 36597 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36598 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36599 | 36600 | if (!expr_gen.valid_operator(o0,f0)) 36601 | return error_node(); 36602 | else if (!expr_gen.valid_operator(o1,f1)) 36603 | return error_node(); 36604 | else 36605 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, f0, f1); 36606 | } 36607 | 36608 | static inline std::string id(expression_generator<Type>& expr_gen, 36609 | const details::operator_type o0, 36610 | const details::operator_type o1) 36611 | { 36612 | return details::build_string() 36613 | << "(t" << expr_gen.to_str(o0) 36614 | << "t)" << expr_gen.to_str(o1) 36615 | << "t" 36616 | } 36617 | }; 36618 | 36619 | struct synthesize_vovoc_expression1 36620 | { 36621 | typedef typename vovoc_t::type1 node_type; 36622 | typedef typename vovoc_t::sf3_type sf3_type; 36623 | 36624 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36625 | const details::operator_type& operation, 36626 | expression_node_ptr (&branch)[2]) 36627 | { 36628 | // (v0) o0 (v1 o1 c) 36629 | const details::voc_base_node<Type>* voc = static_cast<const details::voc_base_node<Type>*>(branch[1]); 36630 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 36631 | const Type& v1 = voc->v(); 36632 | const Type c = voc->c(); 36633 | const details::operator_type o0 = operation; 36634 | const details::operator_type o1 = voc->operation(); 36635 | 36636 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 36637 | 36638 | expression_node_ptr result = error_node(); 36639 | 36640 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36641 | { 36642 | // v0 / (v1 / c) --> (vocov) (v0 * c) / v1 36643 | if ((details::e_div == o0) && (details::e_div == o1)) 36644 | { 36645 | const bool synthesis_result = 36646 | synthesize_sf3ext_expression:: 36647 | template compile<vtype, ctype, vtype>(expr_gen, "(t*t)/t", v0, c, v1, result); 36648 | 36649 | exprtk_debug(("v0 / (v1 / c) --> (vocov) (v0 * c) / v1\n")); 36650 | 36651 | return (synthesis_result) ? result : error_node(); 36652 | } 36653 | } 36654 | 36655 | const bool synthesis_result = 36656 | synthesize_sf3ext_expression::template compile<vtype, vtype, ctype> 36657 | (expr_gen, id(expr_gen, o0, o1), v0, v1, c, result); 36658 | 36659 | if (synthesis_result) 36660 | return result; 36661 | 36662 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36663 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36664 | 36665 | if (!expr_gen.valid_operator(o0,f0)) 36666 | return error_node(); 36667 | else if (!expr_gen.valid_operator(o1,f1)) 36668 | return error_node(); 36669 | else 36670 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, f0, f1); 36671 | } 36672 | 36673 | static inline std::string id(expression_generator<Type>& expr_gen, 36674 | const details::operator_type o0, 36675 | const details::operator_type o1) 36676 | { 36677 | return details::build_string() 36678 | << "t" << expr_gen.to_str(o0) 36679 | << "(t" << expr_gen.to_str(o1) 36680 | << "t)" 36681 | } 36682 | }; 36683 | 36684 | struct synthesize_vocov_expression0 36685 | { 36686 | typedef typename vocov_t::type0 node_type; 36687 | typedef typename vocov_t::sf3_type sf3_type; 36688 | 36689 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36690 | const details::operator_type& operation, 36691 | expression_node_ptr (&branch)[2]) 36692 | { 36693 | // (v0 o0 c) o1 (v1) 36694 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]); 36695 | const Type& v0 = voc->v(); 36696 | const Type c = voc->c(); 36697 | const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 36698 | const details::operator_type o0 = voc->operation(); 36699 | const details::operator_type o1 = operation; 36700 | 36701 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 36702 | 36703 | expression_node_ptr result = error_node(); 36704 | 36705 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36706 | { 36707 | // (v0 / c) / v1 --> (vovoc) v0 / (v1 * c) 36708 | if ((details::e_div == o0) && (details::e_div == o1)) 36709 | { 36710 | const bool synthesis_result = 36711 | synthesize_sf3ext_expression:: 36712 | template compile<vtype, vtype, ctype>(expr_gen, "t/(t*t)", v0, v1, c, result); 36713 | 36714 | exprtk_debug(("(v0 / c) / v1 --> (vovoc) v0 / (v1 * c)\n")); 36715 | 36716 | return (synthesis_result) ? result : error_node(); 36717 | } 36718 | } 36719 | 36720 | const bool synthesis_result = 36721 | synthesize_sf3ext_expression::template compile<vtype, ctype, vtype> 36722 | (expr_gen, id(expr_gen, o0, o1), v0, c, v1, result); 36723 | 36724 | if (synthesis_result) 36725 | return result; 36726 | 36727 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36728 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36729 | 36730 | if (!expr_gen.valid_operator(o0,f0)) 36731 | return error_node(); 36732 | else if (!expr_gen.valid_operator(o1,f1)) 36733 | return error_node(); 36734 | else 36735 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, f0, f1); 36736 | } 36737 | 36738 | static inline std::string id(expression_generator<Type>& expr_gen, 36739 | const details::operator_type o0, 36740 | const details::operator_type o1) 36741 | { 36742 | return details::build_string() 36743 | << "(t" << expr_gen.to_str(o0) 36744 | << "t)" << expr_gen.to_str(o1) 36745 | << "t" 36746 | } 36747 | }; 36748 | 36749 | struct synthesize_vocov_expression1 36750 | { 36751 | typedef typename vocov_t::type1 node_type; 36752 | typedef typename vocov_t::sf3_type sf3_type; 36753 | 36754 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36755 | const details::operator_type& operation, 36756 | expression_node_ptr (&branch)[2]) 36757 | { 36758 | // (v0) o0 (c o1 v1) 36759 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]); 36760 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 36761 | const Type c = cov->c(); 36762 | const Type& v1 = cov->v(); 36763 | const details::operator_type o0 = operation; 36764 | const details::operator_type o1 = cov->operation(); 36765 | 36766 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 36767 | 36768 | expression_node_ptr result = error_node(); 36769 | 36770 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36771 | { 36772 | // v0 / (c / v1) --> (vovoc) (v0 * v1) / c 36773 | if ((details::e_div == o0) && (details::e_div == o1)) 36774 | { 36775 | const bool synthesis_result = 36776 | synthesize_sf3ext_expression:: 36777 | template compile<vtype, vtype, ctype>(expr_gen, "(t*t)/t", v0, v1, c, result); 36778 | 36779 | exprtk_debug(("v0 / (c / v1) --> (vovoc) (v0 * v1) / c\n")); 36780 | 36781 | return (synthesis_result) ? result : error_node(); 36782 | } 36783 | } 36784 | 36785 | const bool synthesis_result = 36786 | synthesize_sf3ext_expression::template compile<vtype, ctype, vtype> 36787 | (expr_gen, id(expr_gen, o0, o1), v0, c, v1, result); 36788 | 36789 | if (synthesis_result) 36790 | return result; 36791 | 36792 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36793 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36794 | 36795 | if (!expr_gen.valid_operator(o0,f0)) 36796 | return error_node(); 36797 | else if (!expr_gen.valid_operator(o1,f1)) 36798 | return error_node(); 36799 | else 36800 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, f0, f1); 36801 | } 36802 | 36803 | static inline std::string id(expression_generator<Type>& expr_gen, 36804 | const details::operator_type o0, 36805 | const details::operator_type o1) 36806 | { 36807 | return details::build_string() 36808 | << "t" << expr_gen.to_str(o0) 36809 | << "(t" << expr_gen.to_str(o1) 36810 | << "t)" 36811 | } 36812 | }; 36813 | 36814 | struct synthesize_covov_expression0 36815 | { 36816 | typedef typename covov_t::type0 node_type; 36817 | typedef typename covov_t::sf3_type sf3_type; 36818 | 36819 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36820 | const details::operator_type& operation, 36821 | expression_node_ptr (&branch)[2]) 36822 | { 36823 | // (c o0 v0) o1 (v1) 36824 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]); 36825 | const Type c = cov->c(); 36826 | const Type& v0 = cov->v(); 36827 | const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 36828 | const details::operator_type o0 = cov->operation(); 36829 | const details::operator_type o1 = operation; 36830 | 36831 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 36832 | 36833 | expression_node_ptr result = error_node(); 36834 | 36835 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36836 | { 36837 | // (c / v0) / v1 --> (covov) c / (v0 * v1) 36838 | if ((details::e_div == o0) && (details::e_div == o1)) 36839 | { 36840 | const bool synthesis_result = 36841 | synthesize_sf3ext_expression:: 36842 | template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", c, v0, v1, result); 36843 | 36844 | exprtk_debug(("(c / v0) / v1 --> (covov) c / (v0 * v1)\n")); 36845 | 36846 | return (synthesis_result) ? result : error_node(); 36847 | } 36848 | } 36849 | 36850 | const bool synthesis_result = 36851 | synthesize_sf3ext_expression::template compile<ctype, vtype, vtype> 36852 | (expr_gen, id(expr_gen, o0, o1), c, v0, v1, result); 36853 | 36854 | if (synthesis_result) 36855 | return result; 36856 | 36857 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36858 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36859 | 36860 | if (!expr_gen.valid_operator(o0,f0)) 36861 | return error_node(); 36862 | else if (!expr_gen.valid_operator(o1,f1)) 36863 | return error_node(); 36864 | else 36865 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, f0, f1); 36866 | } 36867 | 36868 | static inline std::string id(expression_generator<Type>& expr_gen, 36869 | const details::operator_type o0, 36870 | const details::operator_type o1) 36871 | { 36872 | return details::build_string() 36873 | << "(t" << expr_gen.to_str(o0) 36874 | << "t)" << expr_gen.to_str(o1) 36875 | << "t" 36876 | } 36877 | }; 36878 | 36879 | struct synthesize_covov_expression1 36880 | { 36881 | typedef typename covov_t::type1 node_type; 36882 | typedef typename covov_t::sf3_type sf3_type; 36883 | 36884 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36885 | const details::operator_type& operation, 36886 | expression_node_ptr (&branch)[2]) 36887 | { 36888 | // (c) o0 (v0 o1 v1) 36889 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]); 36890 | const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); 36891 | const Type& v0 = vov->v0(); 36892 | const Type& v1 = vov->v1(); 36893 | const details::operator_type o0 = operation; 36894 | const details::operator_type o1 = vov->operation(); 36895 | 36896 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 36897 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 36898 | 36899 | expression_node_ptr result = error_node(); 36900 | 36901 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36902 | { 36903 | // c / (v0 / v1) --> (covov) (c * v1) / v0 36904 | if ((details::e_div == o0) && (details::e_div == o1)) 36905 | { 36906 | const bool synthesis_result = 36907 | synthesize_sf3ext_expression:: 36908 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", c, v1, v0, result); 36909 | 36910 | exprtk_debug(("c / (v0 / v1) --> (covov) (c * v1) / v0\n")); 36911 | 36912 | return (synthesis_result) ? result : error_node(); 36913 | } 36914 | } 36915 | 36916 | const bool synthesis_result = 36917 | synthesize_sf3ext_expression::template compile<ctype, vtype, vtype> 36918 | (expr_gen, id(expr_gen, o0, o1), c, v0, v1, result); 36919 | 36920 | if (synthesis_result) 36921 | return result; 36922 | 36923 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36924 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36925 | 36926 | if (!expr_gen.valid_operator(o0,f0)) 36927 | return error_node(); 36928 | else if (!expr_gen.valid_operator(o1,f1)) 36929 | return error_node(); 36930 | else 36931 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, f0, f1); 36932 | } 36933 | 36934 | static inline std::string id(expression_generator<Type>& expr_gen, 36935 | const details::operator_type o0, 36936 | const details::operator_type o1) 36937 | { 36938 | return details::build_string() 36939 | << "t" << expr_gen.to_str(o0) 36940 | << "(t" << expr_gen.to_str(o1) 36941 | << "t)" 36942 | } 36943 | }; 36944 | 36945 | struct synthesize_covoc_expression0 36946 | { 36947 | typedef typename covoc_t::type0 node_type; 36948 | typedef typename covoc_t::sf3_type sf3_type; 36949 | 36950 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36951 | const details::operator_type& operation, 36952 | expression_node_ptr (&branch)[2]) 36953 | { 36954 | // (c0 o0 v) o1 (c1) 36955 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]); 36956 | const Type c0 = cov->c(); 36957 | const Type& v = cov->v(); 36958 | const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); 36959 | const details::operator_type o0 = cov->operation(); 36960 | const details::operator_type o1 = operation; 36961 | 36962 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 36963 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 36964 | 36965 | expression_node_ptr result = error_node(); 36966 | 36967 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36968 | { 36969 | // (c0 + v) + c1 --> (cov) (c0 + c1) + v 36970 | if ((details::e_add == o0) && (details::e_add == o1)) 36971 | { 36972 | exprtk_debug(("(c0 + v) + c1 --> (cov) (c0 + c1) + v\n")); 36973 | 36974 | return expr_gen.node_allocator_-> 36975 | template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v); 36976 | } 36977 | // (c0 + v) - c1 --> (cov) (c0 - c1) + v 36978 | else if ((details::e_add == o0) && (details::e_sub == o1)) 36979 | { 36980 | exprtk_debug(("(c0 + v) - c1 --> (cov) (c0 - c1) + v\n")); 36981 | 36982 | return expr_gen.node_allocator_-> 36983 | template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v); 36984 | } 36985 | // (c0 - v) + c1 --> (cov) (c0 + c1) - v 36986 | else if ((details::e_sub == o0) && (details::e_add == o1)) 36987 | { 36988 | exprtk_debug(("(c0 - v) + c1 --> (cov) (c0 + c1) - v\n")); 36989 | 36990 | return expr_gen.node_allocator_-> 36991 | template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v); 36992 | } 36993 | // (c0 - v) - c1 --> (cov) (c0 - c1) - v 36994 | else if ((details::e_sub == o0) && (details::e_sub == o1)) 36995 | { 36996 | exprtk_debug(("(c0 - v) - c1 --> (cov) (c0 - c1) - v\n")); 36997 | 36998 | return expr_gen.node_allocator_-> 36999 | template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v); 37000 | } 37001 | // (c0 * v) * c1 --> (cov) (c0 * c1) * v 37002 | else if ((details::e_mul == o0) && (details::e_mul == o1)) 37003 | { 37004 | exprtk_debug(("(c0 * v) * c1 --> (cov) (c0 * c1) * v\n")); 37005 | 37006 | return expr_gen.node_allocator_-> 37007 | template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v); 37008 | } 37009 | // (c0 * v) / c1 --> (cov) (c0 / c1) * v 37010 | else if ((details::e_mul == o0) && (details::e_div == o1)) 37011 | { 37012 | exprtk_debug(("(c0 * v) / c1 --> (cov) (c0 / c1) * v\n")); 37013 | 37014 | return expr_gen.node_allocator_-> 37015 | template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v); 37016 | } 37017 | // (c0 / v) * c1 --> (cov) (c0 * c1) / v 37018 | else if ((details::e_div == o0) && (details::e_mul == o1)) 37019 | { 37020 | exprtk_debug(("(c0 / v) * c1 --> (cov) (c0 * c1) / v\n")); 37021 | 37022 | return expr_gen.node_allocator_-> 37023 | template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v); 37024 | } 37025 | // (c0 / v) / c1 --> (cov) (c0 / c1) / v 37026 | else if ((details::e_div == o0) && (details::e_div == o1)) 37027 | { 37028 | exprtk_debug(("(c0 / v) / c1 --> (cov) (c0 / c1) / v\n")); 37029 | 37030 | return expr_gen.node_allocator_-> 37031 | template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v); 37032 | } 37033 | } 37034 | 37035 | const bool synthesis_result = 37036 | synthesize_sf3ext_expression::template compile<ctype, vtype, ctype> 37037 | (expr_gen, id(expr_gen, o0, o1), c0, v, c1, result); 37038 | 37039 | if (synthesis_result) 37040 | return result; 37041 | 37042 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37043 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37044 | 37045 | if (!expr_gen.valid_operator(o0,f0)) 37046 | return error_node(); 37047 | else if (!expr_gen.valid_operator(o1,f1)) 37048 | return error_node(); 37049 | else 37050 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v, c1, f0, f1); 37051 | } 37052 | 37053 | static inline std::string id(expression_generator<Type>& expr_gen, 37054 | const details::operator_type o0, 37055 | const details::operator_type o1) 37056 | { 37057 | return details::build_string() 37058 | << "(t" << expr_gen.to_str(o0) 37059 | << "t)" << expr_gen.to_str(o1) 37060 | << "t" 37061 | } 37062 | }; 37063 | 37064 | struct synthesize_covoc_expression1 37065 | { 37066 | typedef typename covoc_t::type1 node_type; 37067 | typedef typename covoc_t::sf3_type sf3_type; 37068 | 37069 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37070 | const details::operator_type& operation, 37071 | expression_node_ptr (&branch)[2]) 37072 | { 37073 | // (c0) o0 (v o1 c1) 37074 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]); 37075 | const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); 37076 | const Type& v = voc->v(); 37077 | const Type c1 = voc->c(); 37078 | const details::operator_type o0 = operation; 37079 | const details::operator_type o1 = voc->operation(); 37080 | 37081 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37082 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37083 | 37084 | expression_node_ptr result = error_node(); 37085 | 37086 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37087 | { 37088 | // (c0) + (v + c1) --> (cov) (c0 + c1) + v 37089 | if ((details::e_add == o0) && (details::e_add == o1)) 37090 | { 37091 | exprtk_debug(("(c0) + (v + c1) --> (cov) (c0 + c1) + v\n")); 37092 | 37093 | return expr_gen.node_allocator_-> 37094 | template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v); 37095 | } 37096 | // (c0) + (v - c1) --> (cov) (c0 - c1) + v 37097 | else if ((details::e_add == o0) && (details::e_sub == o1)) 37098 | { 37099 | exprtk_debug(("(c0) + (v - c1) --> (cov) (c0 - c1) + v\n")); 37100 | 37101 | return expr_gen.node_allocator_-> 37102 | template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v); 37103 | } 37104 | // (c0) - (v + c1) --> (cov) (c0 - c1) - v 37105 | else if ((details::e_sub == o0) && (details::e_add == o1)) 37106 | { 37107 | exprtk_debug(("(c0) - (v + c1) --> (cov) (c0 - c1) - v\n")); 37108 | 37109 | return expr_gen.node_allocator_-> 37110 | template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v); 37111 | } 37112 | // (c0) - (v - c1) --> (cov) (c0 + c1) - v 37113 | else if ((details::e_sub == o0) && (details::e_sub == o1)) 37114 | { 37115 | exprtk_debug(("(c0) - (v - c1) --> (cov) (c0 + c1) - v\n")); 37116 | 37117 | return expr_gen.node_allocator_-> 37118 | template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v); 37119 | } 37120 | // (c0) * (v * c1) --> (voc) v * (c0 * c1) 37121 | else if ((details::e_mul == o0) && (details::e_mul == o1)) 37122 | { 37123 | exprtk_debug(("(c0) * (v * c1) --> (voc) v * (c0 * c1)\n")); 37124 | 37125 | return expr_gen.node_allocator_-> 37126 | template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v); 37127 | } 37128 | // (c0) * (v / c1) --> (cov) (c0 / c1) * v 37129 | else if ((details::e_mul == o0) && (details::e_div == 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::mul_op<Type> > >(c0 / c1, v); 37135 | } 37136 | // (c0) / (v * c1) --> (cov) (c0 / c1) / v 37137 | else if ((details::e_div == o0) && (details::e_mul == 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::div_op<Type> > >(c0 / c1, v); 37143 | } 37144 | // (c0) / (v / c1) --> (cov) (c0 * c1) / v 37145 | else if ((details::e_div == o0) && (details::e_div == 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::div_op<Type> > >(c0 * c1, v); 37151 | } 37152 | } 37153 | 37154 | const bool synthesis_result = 37155 | synthesize_sf3ext_expression::template compile<ctype, vtype, ctype> 37156 | (expr_gen, id(expr_gen, o0, o1), c0, v, c1, result); 37157 | 37158 | if (synthesis_result) 37159 | return result; 37160 | 37161 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37162 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37163 | 37164 | if (!expr_gen.valid_operator(o0,f0)) 37165 | return error_node(); 37166 | else if (!expr_gen.valid_operator(o1,f1)) 37167 | return error_node(); 37168 | else 37169 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v, c1, f0, f1); 37170 | } 37171 | 37172 | static inline std::string id(expression_generator<Type>& expr_gen, 37173 | const details::operator_type o0, 37174 | const details::operator_type o1) 37175 | { 37176 | return details::build_string() 37177 | << "t" << expr_gen.to_str(o0) 37178 | << "(t" << expr_gen.to_str(o1) 37179 | << "t)" 37180 | } 37181 | }; 37182 | 37183 | struct synthesize_cocov_expression0 37184 | { 37185 | typedef typename cocov_t::type0 node_type; 37186 | static inline expression_node_ptr process(expression_generator<Type>&, 37187 | const details::operator_type&, 37188 | expression_node_ptr (&)[2]) 37189 | { 37190 | // (c0 o0 c1) o1 (v) - Not possible. 37191 | return error_node(); 37192 | } 37193 | }; 37194 | 37195 | struct synthesize_cocov_expression1 37196 | { 37197 | typedef typename cocov_t::type1 node_type; 37198 | typedef typename cocov_t::sf3_type sf3_type; 37199 | 37200 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37201 | const details::operator_type& operation, 37202 | expression_node_ptr (&branch)[2]) 37203 | { 37204 | // (c0) o0 (c1 o1 v) 37205 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]); 37206 | const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); 37207 | const Type c1 = cov->c(); 37208 | const Type& v = cov->v(); 37209 | const details::operator_type o0 = operation; 37210 | const details::operator_type o1 = cov->operation(); 37211 | 37212 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37213 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37214 | 37215 | expression_node_ptr result = error_node(); 37216 | 37217 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37218 | { 37219 | // (c0) + (c1 + v) --> (cov) (c0 + c1) + v 37220 | if ((details::e_add == o0) && (details::e_add == o1)) 37221 | { 37222 | exprtk_debug(("(c0) + (c1 + v) --> (cov) (c0 + c1) + v\n")); 37223 | 37224 | return expr_gen.node_allocator_-> 37225 | template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v); 37226 | } 37227 | // (c0) + (c1 - v) --> (cov) (c0 + c1) - v 37228 | else if ((details::e_add == o0) && (details::e_sub == o1)) 37229 | { 37230 | exprtk_debug(("(c0) + (c1 - v) --> (cov) (c0 + c1) - v\n")); 37231 | 37232 | return expr_gen.node_allocator_-> 37233 | template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v); 37234 | } 37235 | // (c0) - (c1 + v) --> (cov) (c0 - c1) - v 37236 | else if ((details::e_sub == o0) && (details::e_add == o1)) 37237 | { 37238 | exprtk_debug(("(c0) - (c1 + v) --> (cov) (c0 - c1) - v\n")); 37239 | 37240 | return expr_gen.node_allocator_-> 37241 | template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v); 37242 | } 37243 | // (c0) - (c1 - v) --> (cov) (c0 - c1) + v 37244 | else if ((details::e_sub == o0) && (details::e_sub == o1)) 37245 | { 37246 | exprtk_debug(("(c0) - (c1 - v) --> (cov) (c0 - c1) + v\n")); 37247 | 37248 | return expr_gen.node_allocator_-> 37249 | template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v); 37250 | } 37251 | // (c0) * (c1 * v) --> (cov) (c0 * c1) * v 37252 | else if ((details::e_mul == o0) && (details::e_mul == o1)) 37253 | { 37254 | exprtk_debug(("(c0) * (c1 * v) --> (cov) (c0 * c1) * v\n")); 37255 | 37256 | return expr_gen.node_allocator_-> 37257 | template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v); 37258 | } 37259 | // (c0) * (c1 / v) --> (cov) (c0 * c1) / v 37260 | else if ((details::e_mul == o0) && (details::e_div == o1)) 37261 | { 37262 | exprtk_debug(("(c0) * (c1 / v) --> (cov) (c0 * c1) / v\n")); 37263 | 37264 | return expr_gen.node_allocator_-> 37265 | template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v); 37266 | } 37267 | // (c0) / (c1 * v) --> (cov) (c0 / c1) / v 37268 | else if ((details::e_div == o0) && (details::e_mul == o1)) 37269 | { 37270 | exprtk_debug(("(c0) / (c1 * v) --> (cov) (c0 / c1) / v\n")); 37271 | 37272 | return expr_gen.node_allocator_-> 37273 | template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v); 37274 | } 37275 | // (c0) / (c1 / v) --> (cov) (c0 / c1) * v 37276 | else if ((details::e_div == o0) && (details::e_div == o1)) 37277 | { 37278 | exprtk_debug(("(c0) / (c1 / v) --> (cov) (c0 / c1) * v\n")); 37279 | 37280 | return expr_gen.node_allocator_-> 37281 | template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v); 37282 | } 37283 | } 37284 | 37285 | const bool synthesis_result = 37286 | synthesize_sf3ext_expression::template compile<ctype, ctype, vtype> 37287 | (expr_gen, id(expr_gen, o0, o1), c0, c1, v, result); 37288 | 37289 | if (synthesis_result) 37290 | return result; 37291 | 37292 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37293 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37294 | 37295 | if (!expr_gen.valid_operator(o0,f0)) 37296 | return error_node(); 37297 | else if (!expr_gen.valid_operator(o1,f1)) 37298 | return error_node(); 37299 | else 37300 | return node_type::allocate(*(expr_gen.node_allocator_), c0, c1, v, f0, f1); 37301 | } 37302 | 37303 | static inline std::string id(expression_generator<Type>& expr_gen, 37304 | const details::operator_type o0, 37305 | const details::operator_type o1) 37306 | { 37307 | return details::build_string() 37308 | << "t" << expr_gen.to_str(o0) 37309 | << "(t" << expr_gen.to_str(o1) 37310 | << "t)" 37311 | } 37312 | }; 37313 | 37314 | struct synthesize_vococ_expression0 37315 | { 37316 | typedef typename vococ_t::type0 node_type; 37317 | typedef typename vococ_t::sf3_type sf3_type; 37318 | 37319 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37320 | const details::operator_type& operation, 37321 | expression_node_ptr (&branch)[2]) 37322 | { 37323 | // (v o0 c0) o1 (c1) 37324 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]); 37325 | const Type& v = voc->v(); 37326 | const Type& c0 = voc->c(); 37327 | const Type& c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); 37328 | const details::operator_type o0 = voc->operation(); 37329 | const details::operator_type o1 = operation; 37330 | 37331 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37332 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37333 | 37334 | expression_node_ptr result = error_node(); 37335 | 37336 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37337 | { 37338 | // (v + c0) + c1 --> (voc) v + (c0 + c1) 37339 | if ((details::e_add == o0) && (details::e_add == o1)) 37340 | { 37341 | exprtk_debug(("(v + c0) + c1 --> (voc) v + (c0 + c1)\n")); 37342 | 37343 | return expr_gen.node_allocator_-> 37344 | template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c0 + c1); 37345 | } 37346 | // (v + c0) - c1 --> (voc) v + (c0 - c1) 37347 | else if ((details::e_add == o0) && (details::e_sub == o1)) 37348 | { 37349 | exprtk_debug(("(v + c0) - c1 --> (voc) v + (c0 - c1)\n")); 37350 | 37351 | return expr_gen.node_allocator_-> 37352 | template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c0 - c1); 37353 | } 37354 | // (v - c0) + c1 --> (voc) v - (c0 + c1) 37355 | else if ((details::e_sub == o0) && (details::e_add == o1)) 37356 | { 37357 | exprtk_debug(("(v - c0) + c1 --> (voc) v - (c0 + c1)\n")); 37358 | 37359 | return expr_gen.node_allocator_-> 37360 | template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c1 - c0); 37361 | } 37362 | // (v - c0) - c1 --> (voc) v - (c0 + c1) 37363 | else if ((details::e_sub == o0) && (details::e_sub == o1)) 37364 | { 37365 | exprtk_debug(("(v - c0) - c1 --> (voc) v - (c0 + c1)\n")); 37366 | 37367 | return expr_gen.node_allocator_-> 37368 | template allocate_rc<typename details::voc_node<Type,details::sub_op<Type> > >(v, c0 + c1); 37369 | } 37370 | // (v * c0) * c1 --> (voc) v * (c0 * c1) 37371 | else if ((details::e_mul == o0) && (details::e_mul == o1)) 37372 | { 37373 | exprtk_debug(("(v * c0) * c1 --> (voc) v * (c0 * c1)\n")); 37374 | 37375 | return expr_gen.node_allocator_-> 37376 | template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c0 * c1); 37377 | } 37378 | // (v * c0) / c1 --> (voc) v * (c0 / c1) 37379 | else if ((details::e_mul == o0) && (details::e_div == o1)) 37380 | { 37381 | exprtk_debug(("(v * c0) / c1 --> (voc) v * (c0 / c1)\n")); 37382 | 37383 | return expr_gen.node_allocator_-> 37384 | template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c0 / c1); 37385 | } 37386 | // (v / c0) * c1 --> (voc) v * (c1 / c0) 37387 | else if ((details::e_div == o0) && (details::e_mul == o1)) 37388 | { 37389 | exprtk_debug(("(v / c0) * c1 --> (voc) v * (c1 / c0)\n")); 37390 | 37391 | return expr_gen.node_allocator_-> 37392 | template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c1 / c0); 37393 | } 37394 | // (v / c0) / c1 --> (voc) v / (c0 * c1) 37395 | else if ((details::e_div == o0) && (details::e_div == o1)) 37396 | { 37397 | exprtk_debug(("(v / c0) / c1 --> (voc) v / (c0 * c1)\n")); 37398 | 37399 | return expr_gen.node_allocator_-> 37400 | template allocate_rc<typename details::voc_node<Type,details::div_op<Type> > >(v, c0 * c1); 37401 | } 37402 | // (v ^ c0) ^ c1 --> (voc) v ^ (c0 * c1) 37403 | else if ((details::e_pow == o0) && (details::e_pow == o1)) 37404 | { 37405 | exprtk_debug(("(v ^ c0) ^ c1 --> (voc) v ^ (c0 * c1)\n")); 37406 | 37407 | return expr_gen.node_allocator_-> 37408 | template allocate_rc<typename details::voc_node<Type,details::pow_op<Type> > >(v, c0 * c1); 37409 | } 37410 | } 37411 | 37412 | const bool synthesis_result = 37413 | synthesize_sf3ext_expression::template compile<vtype, ctype, ctype> 37414 | (expr_gen, id(expr_gen, o0, o1), v, c0, c1, result); 37415 | 37416 | if (synthesis_result) 37417 | return result; 37418 | 37419 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37420 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37421 | 37422 | if (!expr_gen.valid_operator(o0,f0)) 37423 | return error_node(); 37424 | else if (!expr_gen.valid_operator(o1,f1)) 37425 | return error_node(); 37426 | else 37427 | return node_type::allocate(*(expr_gen.node_allocator_), v, c0, c1, f0, f1); 37428 | } 37429 | 37430 | static inline std::string id(expression_generator<Type>& expr_gen, 37431 | const details::operator_type o0, 37432 | const details::operator_type o1) 37433 | { 37434 | return details::build_string() 37435 | << "(t" << expr_gen.to_str(o0) 37436 | << "t)" << expr_gen.to_str(o1) 37437 | << "t" 37438 | } 37439 | }; 37440 | 37441 | struct synthesize_vococ_expression1 37442 | { 37443 | typedef typename vococ_t::type0 node_type; 37444 | 37445 | static inline expression_node_ptr process(expression_generator<Type>&, 37446 | const details::operator_type&, 37447 | expression_node_ptr (&)[2]) 37448 | { 37449 | // (v) o0 (c0 o1 c1) - Not possible. 37450 | exprtk_debug(("(v) o0 (c0 o1 c1) - Not possible.\n")); 37451 | return error_node(); 37452 | } 37453 | }; 37454 | 37455 | struct synthesize_vovovov_expression0 37456 | { 37457 | typedef typename vovovov_t::type0 node_type; 37458 | typedef typename vovovov_t::sf4_type sf4_type; 37459 | typedef typename node_type::T0 T0; 37460 | typedef typename node_type::T1 T1; 37461 | typedef typename node_type::T2 T2; 37462 | typedef typename node_type::T3 T3; 37463 | 37464 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37465 | const details::operator_type& operation, 37466 | expression_node_ptr (&branch)[2]) 37467 | { 37468 | // (v0 o0 v1) o1 (v2 o2 v3) 37469 | const details::vov_base_node<Type>* vov0 = static_cast<details::vov_base_node<Type>*>(branch[0]); 37470 | const details::vov_base_node<Type>* vov1 = static_cast<details::vov_base_node<Type>*>(branch[1]); 37471 | const Type& v0 = vov0->v0(); 37472 | const Type& v1 = vov0->v1(); 37473 | const Type& v2 = vov1->v0(); 37474 | const Type& v3 = vov1->v1(); 37475 | const details::operator_type o0 = vov0->operation(); 37476 | const details::operator_type o1 = operation; 37477 | const details::operator_type o2 = vov1->operation(); 37478 | 37479 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37480 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37481 | 37482 | expression_node_ptr result = error_node(); 37483 | 37484 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37485 | { 37486 | // (v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3) 37487 | if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 37488 | { 37489 | const bool synthesis_result = 37490 | synthesize_sf4ext_expression:: 37491 | template compile<vtype, vtype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, v3, result); 37492 | 37493 | exprtk_debug(("(v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3)\n")); 37494 | 37495 | return (synthesis_result) ? result : error_node(); 37496 | } 37497 | // (v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2) 37498 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 37499 | { 37500 | const bool synthesis_result = 37501 | synthesize_sf4ext_expression:: 37502 | template compile<vtype, vtype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", v0, v3, v1, v2, result); 37503 | 37504 | exprtk_debug(("(v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2)\n")); 37505 | 37506 | return (synthesis_result) ? result : error_node(); 37507 | } 37508 | // (v0 + v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2) 37509 | else if ((details::e_add == o0) && (details::e_div == o1) && (details::e_div == o2)) 37510 | { 37511 | const bool synthesis_result = 37512 | synthesize_sf4ext_expression:: 37513 | template compile<vtype, vtype, vtype, vtype>(expr_gen, "(t+t)*(t/t)", v0, v1, v3, v2, result); 37514 | 37515 | exprtk_debug(("(v0 + v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2)\n")); 37516 | 37517 | return (synthesis_result) ? result : error_node(); 37518 | } 37519 | // (v0 - v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2) 37520 | else if ((details::e_sub == o0) && (details::e_div == o1) && (details::e_div == o2)) 37521 | { 37522 | const bool synthesis_result = 37523 | synthesize_sf4ext_expression:: 37524 | template compile<vtype, vtype, vtype, vtype>(expr_gen, "(t-t)*(t/t)", v0, v1, v3, v2, result); 37525 | 37526 | exprtk_debug(("(v0 - v1) / (v2 / v3) --> (vovovov) (v0 - v1) * (v3 / v2)\n")); 37527 | 37528 | return (synthesis_result) ? result : error_node(); 37529 | } 37530 | // (v0 * v1) / (v2 / v3) --> (vovovov) ((v0 * v1) * v3) / v2 37531 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) 37532 | { 37533 | const bool synthesis_result = 37534 | synthesize_sf4ext_expression:: 37535 | template compile<vtype, vtype, vtype, vtype>(expr_gen, "((t*t)*t)/t", v0, v1, v3, v2, result); 37536 | 37537 | exprtk_debug(("(v0 * v1) / (v2 / v3) --> (vovovov) ((v0 * v1) * v3) / v2\n")); 37538 | 37539 | return (synthesis_result) ? result : error_node(); 37540 | } 37541 | } 37542 | 37543 | const bool synthesis_result = 37544 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 37545 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result); 37546 | 37547 | if (synthesis_result) 37548 | return result; 37549 | 37550 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37551 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37552 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 37553 | 37554 | if (!expr_gen.valid_operator(o0,f0)) 37555 | return error_node(); 37556 | else if (!expr_gen.valid_operator(o1,f1)) 37557 | return error_node(); 37558 | else if (!expr_gen.valid_operator(o2,f2)) 37559 | return error_node(); 37560 | else 37561 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2); 37562 | } 37563 | 37564 | static inline std::string id(expression_generator<Type>& expr_gen, 37565 | const details::operator_type o0, 37566 | const details::operator_type o1, 37567 | const details::operator_type o2) 37568 | { 37569 | return details::build_string() 37570 | << "(t" << expr_gen.to_str(o0) 37571 | << "t)" << expr_gen.to_str(o1) 37572 | << "(t" << expr_gen.to_str(o2) 37573 | << "t)" 37574 | } 37575 | }; 37576 | 37577 | struct synthesize_vovovoc_expression0 37578 | { 37579 | typedef typename vovovoc_t::type0 node_type; 37580 | typedef typename vovovoc_t::sf4_type sf4_type; 37581 | typedef typename node_type::T0 T0; 37582 | typedef typename node_type::T1 T1; 37583 | typedef typename node_type::T2 T2; 37584 | typedef typename node_type::T3 T3; 37585 | 37586 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37587 | const details::operator_type& operation, 37588 | expression_node_ptr (&branch)[2]) 37589 | { 37590 | // (v0 o0 v1) o1 (v2 o2 c) 37591 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]); 37592 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]); 37593 | const Type& v0 = vov->v0(); 37594 | const Type& v1 = vov->v1(); 37595 | const Type& v2 = voc->v (); 37596 | const Type c = voc->c (); 37597 | const details::operator_type o0 = vov->operation(); 37598 | const details::operator_type o1 = operation; 37599 | const details::operator_type o2 = voc->operation(); 37600 | 37601 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37602 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37603 | 37604 | expression_node_ptr result = error_node(); 37605 | 37606 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37607 | { 37608 | // (v0 / v1) * (v2 / c) --> (vovovoc) (v0 * v2) / (v1 * c) 37609 | if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 37610 | { 37611 | const bool synthesis_result = 37612 | synthesize_sf4ext_expression:: 37613 | template compile<vtype, vtype, vtype, ctype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, c, result); 37614 | 37615 | exprtk_debug(("(v0 / v1) * (v2 / c) --> (vovovoc) (v0 * v2) / (v1 * c)\n")); 37616 | 37617 | return (synthesis_result) ? result : error_node(); 37618 | } 37619 | // (v0 / v1) / (v2 / c) --> (vocovov) (v0 * c) / (v1 * v2) 37620 | if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 37621 | { 37622 | const bool synthesis_result = 37623 | synthesize_sf4ext_expression:: 37624 | template compile<vtype, ctype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", v0, c, v1, v2, result); 37625 | 37626 | exprtk_debug(("(v0 / v1) / (v2 / c) --> (vocovov) (v0 * c) / (v1 * v2)\n")); 37627 | 37628 | return (synthesis_result) ? result : error_node(); 37629 | } 37630 | } 37631 | 37632 | const bool synthesis_result = 37633 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 37634 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result); 37635 | 37636 | if (synthesis_result) 37637 | return result; 37638 | 37639 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37640 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37641 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 37642 | 37643 | if (!expr_gen.valid_operator(o0,f0)) 37644 | return error_node(); 37645 | else if (!expr_gen.valid_operator(o1,f1)) 37646 | return error_node(); 37647 | else if (!expr_gen.valid_operator(o2,f2)) 37648 | return error_node(); 37649 | else 37650 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2); 37651 | } 37652 | 37653 | static inline std::string id(expression_generator<Type>& expr_gen, 37654 | const details::operator_type o0, 37655 | const details::operator_type o1, 37656 | const details::operator_type o2) 37657 | { 37658 | return details::build_string() 37659 | << "(t" << expr_gen.to_str(o0) 37660 | << "t)" << expr_gen.to_str(o1) 37661 | << "(t" << expr_gen.to_str(o2) 37662 | << "t)" 37663 | } 37664 | }; 37665 | 37666 | struct synthesize_vovocov_expression0 37667 | { 37668 | typedef typename vovocov_t::type0 node_type; 37669 | typedef typename vovocov_t::sf4_type sf4_type; 37670 | typedef typename node_type::T0 T0; 37671 | typedef typename node_type::T1 T1; 37672 | typedef typename node_type::T2 T2; 37673 | typedef typename node_type::T3 T3; 37674 | 37675 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37676 | const details::operator_type& operation, 37677 | expression_node_ptr (&branch)[2]) 37678 | { 37679 | // (v0 o0 v1) o1 (c o2 v2) 37680 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]); 37681 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]); 37682 | const Type& v0 = vov->v0(); 37683 | const Type& v1 = vov->v1(); 37684 | const Type& v2 = cov->v (); 37685 | const Type c = cov->c (); 37686 | const details::operator_type o0 = vov->operation(); 37687 | const details::operator_type o1 = operation; 37688 | const details::operator_type o2 = cov->operation(); 37689 | 37690 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37691 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37692 | 37693 | expression_node_ptr result = error_node(); 37694 | 37695 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37696 | { 37697 | // (v0 / v1) * (c / v2) --> (vocovov) (v0 * c) / (v1 * v2) 37698 | if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 37699 | { 37700 | const bool synthesis_result = 37701 | synthesize_sf4ext_expression:: 37702 | template compile<vtype, ctype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", v0, c, v1, v2, result); 37703 | 37704 | exprtk_debug(("(v0 / v1) * (c / v2) --> (vocovov) (v0 * c) / (v1 * v2)\n")); 37705 | 37706 | return (synthesis_result) ? result : error_node(); 37707 | } 37708 | // (v0 / v1) / (c / v2) --> (vovovoc) (v0 * v2) / (v1 * c) 37709 | if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 37710 | { 37711 | const bool synthesis_result = 37712 | synthesize_sf4ext_expression:: 37713 | template compile<vtype, vtype, vtype, ctype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, c, result); 37714 | 37715 | exprtk_debug(("(v0 / v1) / (c / v2) --> (vovovoc) (v0 * v2) / (v1 * c)\n")); 37716 | 37717 | return (synthesis_result) ? result : error_node(); 37718 | } 37719 | } 37720 | 37721 | const bool synthesis_result = 37722 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 37723 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result); 37724 | 37725 | if (synthesis_result) 37726 | return result; 37727 | 37728 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37729 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37730 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 37731 | 37732 | if (!expr_gen.valid_operator(o0,f0)) 37733 | return error_node(); 37734 | else if (!expr_gen.valid_operator(o1,f1)) 37735 | return error_node(); 37736 | else if (!expr_gen.valid_operator(o2,f2)) 37737 | return error_node(); 37738 | else 37739 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2); 37740 | } 37741 | 37742 | static inline std::string id(expression_generator<Type>& expr_gen, 37743 | const details::operator_type o0, 37744 | const details::operator_type o1, 37745 | const details::operator_type o2) 37746 | { 37747 | return details::build_string() 37748 | << "(t" << expr_gen.to_str(o0) 37749 | << "t)" << expr_gen.to_str(o1) 37750 | << "(t" << expr_gen.to_str(o2) 37751 | << "t)" 37752 | } 37753 | }; 37754 | 37755 | struct synthesize_vocovov_expression0 37756 | { 37757 | typedef typename vocovov_t::type0 node_type; 37758 | typedef typename vocovov_t::sf4_type sf4_type; 37759 | typedef typename node_type::T0 T0; 37760 | typedef typename node_type::T1 T1; 37761 | typedef typename node_type::T2 T2; 37762 | typedef typename node_type::T3 T3; 37763 | 37764 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37765 | const details::operator_type& operation, 37766 | expression_node_ptr (&branch)[2]) 37767 | { 37768 | // (v0 o0 c) o1 (v1 o2 v2) 37769 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]); 37770 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]); 37771 | const Type c = voc->c (); 37772 | const Type& v0 = voc->v (); 37773 | const Type& v1 = vov->v0(); 37774 | const Type& v2 = vov->v1(); 37775 | const details::operator_type o0 = voc->operation(); 37776 | const details::operator_type o1 = operation; 37777 | const details::operator_type o2 = vov->operation(); 37778 | 37779 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37780 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37781 | 37782 | expression_node_ptr result = error_node(); 37783 | 37784 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37785 | { 37786 | // (v0 / c) * (v1 / v2) --> (vovocov) (v0 * v1) / (c * v2) 37787 | if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 37788 | { 37789 | const bool synthesis_result = 37790 | synthesize_sf4ext_expression:: 37791 | template compile<vtype, vtype, ctype, vtype>(expr_gen, "(t*t)/(t*t)", v0, v1, c, v2, result); 37792 | 37793 | exprtk_debug(("(v0 / c) * (v1 / v2) --> (vovocov) (v0 * v1) / (c * v2)\n")); 37794 | 37795 | return (synthesis_result) ? result : error_node(); 37796 | } 37797 | // (v0 / c) / (v1 / v2) --> (vovocov) (v0 * v2) / (c * v1) 37798 | if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 37799 | { 37800 | const bool synthesis_result = 37801 | synthesize_sf4ext_expression:: 37802 | template compile<vtype, vtype, ctype, vtype>(expr_gen, "(t*t)/(t*t)", v0, v2, c, v1, result); 37803 | 37804 | exprtk_debug(("(v0 / c) / (v1 / v2) --> (vovocov) (v0 * v2) / (c * v1)\n")); 37805 | 37806 | return (synthesis_result) ? result : error_node(); 37807 | } 37808 | } 37809 | 37810 | const bool synthesis_result = 37811 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 37812 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result); 37813 | 37814 | if (synthesis_result) 37815 | return result; 37816 | 37817 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37818 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37819 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 37820 | 37821 | if (!expr_gen.valid_operator(o0,f0)) 37822 | return error_node(); 37823 | else if (!expr_gen.valid_operator(o1,f1)) 37824 | return error_node(); 37825 | else if (!expr_gen.valid_operator(o2,f2)) 37826 | return error_node(); 37827 | else 37828 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2); 37829 | } 37830 | 37831 | static inline std::string id(expression_generator<Type>& expr_gen, 37832 | const details::operator_type o0, 37833 | const details::operator_type o1, 37834 | const details::operator_type o2) 37835 | { 37836 | return details::build_string() 37837 | << "(t" << expr_gen.to_str(o0) 37838 | << "t)" << expr_gen.to_str(o1) 37839 | << "(t" << expr_gen.to_str(o2) 37840 | << "t)" 37841 | } 37842 | }; 37843 | 37844 | struct synthesize_covovov_expression0 37845 | { 37846 | typedef typename covovov_t::type0 node_type; 37847 | typedef typename covovov_t::sf4_type sf4_type; 37848 | typedef typename node_type::T0 T0; 37849 | typedef typename node_type::T1 T1; 37850 | typedef typename node_type::T2 T2; 37851 | typedef typename node_type::T3 T3; 37852 | 37853 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37854 | const details::operator_type& operation, 37855 | expression_node_ptr (&branch)[2]) 37856 | { 37857 | // (c o0 v0) o1 (v1 o2 v2) 37858 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]); 37859 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]); 37860 | const Type c = cov->c (); 37861 | const Type& v0 = cov->v (); 37862 | const Type& v1 = vov->v0(); 37863 | const Type& v2 = vov->v1(); 37864 | const details::operator_type o0 = cov->operation(); 37865 | const details::operator_type o1 = operation; 37866 | const details::operator_type o2 = vov->operation(); 37867 | 37868 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37869 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37870 | 37871 | expression_node_ptr result = error_node(); 37872 | 37873 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37874 | { 37875 | // (c / v0) * (v1 / v2) --> (covovov) (c * v1) / (v0 * v2) 37876 | if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 37877 | { 37878 | const bool synthesis_result = 37879 | synthesize_sf4ext_expression:: 37880 | template compile<ctype, vtype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", c, v1, v0, v2, result); 37881 | 37882 | exprtk_debug(("(c / v0) * (v1 / v2) --> (covovov) (c * v1) / (v0 * v2)\n")); 37883 | 37884 | return (synthesis_result) ? result : error_node(); 37885 | } 37886 | // (c / v0) / (v1 / v2) --> (covovov) (c * v2) / (v0 * v1) 37887 | if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 37888 | { 37889 | const bool synthesis_result = 37890 | synthesize_sf4ext_expression:: 37891 | template compile<ctype, vtype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", c, v2, v0, v1, result); 37892 | 37893 | exprtk_debug(("(c / v0) / (v1 / v2) --> (covovov) (c * v2) / (v0 * v1)\n")); 37894 | 37895 | return (synthesis_result) ? result : error_node(); 37896 | } 37897 | } 37898 | 37899 | const bool synthesis_result = 37900 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 37901 | (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result); 37902 | 37903 | if (synthesis_result) 37904 | return result; 37905 | 37906 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37907 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37908 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 37909 | 37910 | if (!expr_gen.valid_operator(o0,f0)) 37911 | return error_node(); 37912 | else if (!expr_gen.valid_operator(o1,f1)) 37913 | return error_node(); 37914 | else if (!expr_gen.valid_operator(o2,f2)) 37915 | return error_node(); 37916 | else 37917 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2); 37918 | } 37919 | 37920 | static inline std::string id(expression_generator<Type>& expr_gen, 37921 | const details::operator_type o0, 37922 | const details::operator_type o1, 37923 | const details::operator_type o2) 37924 | { 37925 | return details::build_string() 37926 | << "(t" << expr_gen.to_str(o0) 37927 | << "t)" << expr_gen.to_str(o1) 37928 | << "(t" << expr_gen.to_str(o2) 37929 | << "t)" 37930 | } 37931 | }; 37932 | 37933 | struct synthesize_covocov_expression0 37934 | { 37935 | typedef typename covocov_t::type0 node_type; 37936 | typedef typename covocov_t::sf4_type sf4_type; 37937 | typedef typename node_type::T0 T0; 37938 | typedef typename node_type::T1 T1; 37939 | typedef typename node_type::T2 T2; 37940 | typedef typename node_type::T3 T3; 37941 | 37942 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37943 | const details::operator_type& operation, 37944 | expression_node_ptr (&branch)[2]) 37945 | { 37946 | // (c0 o0 v0) o1 (c1 o2 v1) 37947 | const details::cov_base_node<Type>* cov0 = static_cast<details::cov_base_node<Type>*>(branch[0]); 37948 | const details::cov_base_node<Type>* cov1 = static_cast<details::cov_base_node<Type>*>(branch[1]); 37949 | const Type c0 = cov0->c(); 37950 | const Type& v0 = cov0->v(); 37951 | const Type c1 = cov1->c(); 37952 | const Type& v1 = cov1->v(); 37953 | const details::operator_type o0 = cov0->operation(); 37954 | const details::operator_type o1 = operation; 37955 | const details::operator_type o2 = cov1->operation(); 37956 | 37957 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37958 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37959 | 37960 | expression_node_ptr result = error_node(); 37961 | 37962 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37963 | { 37964 | // (c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1 37965 | if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2)) 37966 | { 37967 | const bool synthesis_result = 37968 | synthesize_sf3ext_expression:: 37969 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result); 37970 | 37971 | exprtk_debug(("(c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n")); 37972 | 37973 | return (synthesis_result) ? result : error_node(); 37974 | } 37975 | // (c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1 37976 | else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2)) 37977 | { 37978 | const bool synthesis_result = 37979 | synthesize_sf3ext_expression:: 37980 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result); 37981 | 37982 | exprtk_debug(("(c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n")); 37983 | 37984 | return (synthesis_result) ? result : error_node(); 37985 | } 37986 | // (c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1 37987 | else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2)) 37988 | { 37989 | const bool synthesis_result = 37990 | synthesize_sf3ext_expression:: 37991 | template compile<ctype, vtype, vtype>(expr_gen, "(t-t)+t", (c0 - c1), v0, v1, result); 37992 | 37993 | exprtk_debug(("(c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1\n")); 37994 | 37995 | return (synthesis_result) ? result : error_node(); 37996 | } 37997 | // (c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1 37998 | else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2)) 37999 | { 38000 | const bool synthesis_result = 38001 | synthesize_sf3ext_expression:: 38002 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result); 38003 | 38004 | exprtk_debug(("(c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n")); 38005 | 38006 | return (synthesis_result) ? result : error_node(); 38007 | } 38008 | // (c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1) 38009 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38010 | { 38011 | const bool synthesis_result = 38012 | synthesize_sf3ext_expression:: 38013 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result); 38014 | 38015 | exprtk_debug(("(c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1)\n")); 38016 | 38017 | return (synthesis_result) ? result : error_node(); 38018 | } 38019 | // (c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1) 38020 | else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 38021 | { 38022 | const bool synthesis_result = 38023 | synthesize_sf3ext_expression:: 38024 | template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", (c0 * c1), v0, v1, result); 38025 | 38026 | exprtk_debug(("(c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1)\n")); 38027 | 38028 | return (synthesis_result) ? result : error_node(); 38029 | } 38030 | // (c0 / v0) / (c1 / v1) --> (covov) ((c0 / c1) * v1) / v0 38031 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 38032 | { 38033 | const bool synthesis_result = 38034 | synthesize_sf3ext_expression:: 38035 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v1, v0, result); 38036 | 38037 | exprtk_debug(("(c0 / v0) / (c1 / v1) --> (covov) ((c0 / c1) * v1) / v0\n")); 38038 | 38039 | return (synthesis_result) ? result : error_node(); 38040 | } 38041 | // (c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1) 38042 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) 38043 | { 38044 | const bool synthesis_result = 38045 | synthesize_sf3ext_expression:: 38046 | template compile<ctype, vtype, vtype>(expr_gen, "t*(t*t)", (c0 / c1), v0, v1, result); 38047 | 38048 | exprtk_debug(("(c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n")); 38049 | 38050 | return (synthesis_result) ? result : error_node(); 38051 | } 38052 | // (c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1) 38053 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38054 | { 38055 | const bool synthesis_result = 38056 | synthesize_sf3ext_expression:: 38057 | template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", (c0 / c1), v0, v1, result); 38058 | 38059 | exprtk_debug(("(c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1)\n")); 38060 | 38061 | return (synthesis_result) ? result : error_node(); 38062 | } 38063 | // (c * v0) +/- (c * v1) --> (covov) c * (v0 +/- v1) 38064 | else if ( 38065 | (std::equal_to<T>()(c0,c1)) && 38066 | (details::e_mul == o0) && 38067 | (details::e_mul == o2) && 38068 | ( 38069 | (details::e_add == o1) || 38070 | (details::e_sub == o1) 38071 | ) 38072 | ) 38073 | { 38074 | std::string specfunc; 38075 | 38076 | switch (o1) 38077 | { 38078 | case details::e_add : specfunc = "t*(t+t)" break; 38079 | case details::e_sub : specfunc = "t*(t-t)" break; 38080 | default : return error_node(); 38081 | } 38082 | 38083 | const bool synthesis_result = 38084 | synthesize_sf3ext_expression:: 38085 | template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result); 38086 | 38087 | exprtk_debug(("(c * v0) +/- (c * v1) --> (covov) c * (v0 +/- v1)\n")); 38088 | 38089 | return (synthesis_result) ? result : error_node(); 38090 | } 38091 | } 38092 | 38093 | const bool synthesis_result = 38094 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38095 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result); 38096 | 38097 | if (synthesis_result) 38098 | return result; 38099 | 38100 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38101 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 38102 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 38103 | 38104 | if (!expr_gen.valid_operator(o0,f0)) 38105 | return error_node(); 38106 | else if (!expr_gen.valid_operator(o1,f1)) 38107 | return error_node(); 38108 | else if (!expr_gen.valid_operator(o2,f2)) 38109 | return error_node(); 38110 | else 38111 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2); 38112 | } 38113 | 38114 | static inline std::string id(expression_generator<Type>& expr_gen, 38115 | const details::operator_type o0, 38116 | const details::operator_type o1, 38117 | const details::operator_type o2) 38118 | { 38119 | return details::build_string() 38120 | << "(t" << expr_gen.to_str(o0) 38121 | << "t)" << expr_gen.to_str(o1) 38122 | << "(t" << expr_gen.to_str(o2) 38123 | << "t)" 38124 | } 38125 | }; 38126 | 38127 | struct synthesize_vocovoc_expression0 38128 | { 38129 | typedef typename vocovoc_t::type0 node_type; 38130 | typedef typename vocovoc_t::sf4_type sf4_type; 38131 | typedef typename node_type::T0 T0; 38132 | typedef typename node_type::T1 T1; 38133 | typedef typename node_type::T2 T2; 38134 | typedef typename node_type::T3 T3; 38135 | 38136 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38137 | const details::operator_type& operation, 38138 | expression_node_ptr (&branch)[2]) 38139 | { 38140 | // (v0 o0 c0) o1 (v1 o2 c1) 38141 | const details::voc_base_node<Type>* voc0 = static_cast<details::voc_base_node<Type>*>(branch[0]); 38142 | const details::voc_base_node<Type>* voc1 = static_cast<details::voc_base_node<Type>*>(branch[1]); 38143 | const Type c0 = voc0->c(); 38144 | const Type& v0 = voc0->v(); 38145 | const Type c1 = voc1->c(); 38146 | const Type& v1 = voc1->v(); 38147 | const details::operator_type o0 = voc0->operation(); 38148 | const details::operator_type o1 = operation; 38149 | const details::operator_type o2 = voc1->operation(); 38150 | 38151 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 38152 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38153 | 38154 | expression_node_ptr result = error_node(); 38155 | 38156 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 38157 | { 38158 | // (v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1 38159 | if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2)) 38160 | { 38161 | const bool synthesis_result = 38162 | synthesize_sf3ext_expression:: 38163 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result); 38164 | 38165 | exprtk_debug(("(v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n")); 38166 | 38167 | return (synthesis_result) ? result : error_node(); 38168 | } 38169 | // (v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1 38170 | else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2)) 38171 | { 38172 | const bool synthesis_result = 38173 | synthesize_sf3ext_expression:: 38174 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result); 38175 | 38176 | exprtk_debug(("(v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n")); 38177 | 38178 | return (synthesis_result) ? result : error_node(); 38179 | } 38180 | // (v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1 38181 | else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2)) 38182 | { 38183 | const bool synthesis_result = 38184 | synthesize_sf3ext_expression:: 38185 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c1 - c0), v0, v1, result); 38186 | 38187 | exprtk_debug(("(v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1\n")); 38188 | 38189 | return (synthesis_result) ? result : error_node(); 38190 | } 38191 | // (v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1 38192 | else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2)) 38193 | { 38194 | const bool synthesis_result = 38195 | synthesize_sf3ext_expression:: 38196 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result); 38197 | 38198 | exprtk_debug(("(v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n")); 38199 | 38200 | return (synthesis_result) ? result : error_node(); 38201 | } 38202 | // (v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1) 38203 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38204 | { 38205 | const bool synthesis_result = 38206 | synthesize_sf3ext_expression:: 38207 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result); 38208 | 38209 | exprtk_debug(("(v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n")); 38210 | 38211 | return (synthesis_result) ? result : error_node(); 38212 | } 38213 | // (v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1 38214 | else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 38215 | { 38216 | const bool synthesis_result = 38217 | synthesize_sf3ext_expression:: 38218 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", Type(1) / (c0 * c1), v0, v1, result); 38219 | 38220 | exprtk_debug(("(v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1\n")); 38221 | 38222 | return (synthesis_result) ? result : error_node(); 38223 | } 38224 | // (v0 / c0) / (v1 / c1) --> (covov) ((c1 / c0) * v0) / v1 38225 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 38226 | { 38227 | const bool synthesis_result = 38228 | synthesize_sf3ext_expression:: 38229 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c1 / c0), v0, v1, result); 38230 | 38231 | exprtk_debug(("(v0 / c0) / (v1 / c1) --> (covov) ((c1 / c0) * v0) / v1\n")); 38232 | 38233 | return (synthesis_result) ? result : error_node(); 38234 | } 38235 | // (v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1) 38236 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) 38237 | { 38238 | const bool synthesis_result = 38239 | synthesize_sf3ext_expression:: 38240 | template compile<ctype, vtype, vtype>(expr_gen, "t*(t/t)", (c0 * c1), v0, v1, result); 38241 | 38242 | exprtk_debug(("(v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n")); 38243 | 38244 | return (synthesis_result) ? result : error_node(); 38245 | } 38246 | // (v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1 38247 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38248 | { 38249 | const bool synthesis_result = 38250 | synthesize_sf3ext_expression:: 38251 | template compile<ctype, vtype, vtype>(expr_gen, "t*(t/t)", Type(1) / (c0 * c1), v0, v1, result); 38252 | 38253 | exprtk_debug(("(v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1\n")); 38254 | 38255 | return (synthesis_result) ? result : error_node(); 38256 | } 38257 | // (v0 / c0) * (v1 + c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 + c1) 38258 | else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_add == o2)) 38259 | { 38260 | const bool synthesis_result = 38261 | synthesize_sf4ext_expression:: 38262 | template compile<vtype, ctype, vtype, ctype>(expr_gen, "(t*t)*(t+t)", v0, T(1) / c0, v1, c1, result); 38263 | 38264 | exprtk_debug(("(v0 / c0) * (v1 + c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 + c1)\n")); 38265 | 38266 | return (synthesis_result) ? result : error_node(); 38267 | } 38268 | // (v0 / c0) * (v1 - c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 - c1) 38269 | else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_sub == o2)) 38270 | { 38271 | const bool synthesis_result = 38272 | synthesize_sf4ext_expression:: 38273 | template compile<vtype, ctype, vtype, ctype>(expr_gen, "(t*t)*(t-t)", v0, T(1) / c0, v1, c1, result); 38274 | 38275 | exprtk_debug(("(v0 / c0) * (v1 - c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 - c1)\n")); 38276 | 38277 | return (synthesis_result) ? result : error_node(); 38278 | } 38279 | // (v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1) 38280 | else if ( 38281 | (std::equal_to<T>()(c0,c1)) && 38282 | (details::e_mul == o0) && 38283 | (details::e_mul == o2) && 38284 | ( 38285 | (details::e_add == o1) || 38286 | (details::e_sub == o1) 38287 | ) 38288 | ) 38289 | { 38290 | std::string specfunc; 38291 | 38292 | switch (o1) 38293 | { 38294 | case details::e_add : specfunc = "t*(t+t)" break; 38295 | case details::e_sub : specfunc = "t*(t-t)" break; 38296 | default : return error_node(); 38297 | } 38298 | 38299 | const bool synthesis_result = 38300 | synthesize_sf3ext_expression:: 38301 | template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result); 38302 | 38303 | exprtk_debug(("(v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n")); 38304 | 38305 | return (synthesis_result) ? result : error_node(); 38306 | } 38307 | // (v0 / c) +/- (v1 / c) --> (vovoc) (v0 +/- v1) / c 38308 | else if ( 38309 | (std::equal_to<T>()(c0,c1)) && 38310 | (details::e_div == o0) && 38311 | (details::e_div == o2) && 38312 | ( 38313 | (details::e_add == o1) || 38314 | (details::e_sub == o1) 38315 | ) 38316 | ) 38317 | { 38318 | std::string specfunc; 38319 | 38320 | switch (o1) 38321 | { 38322 | case details::e_add : specfunc = "(t+t)/t" break; 38323 | case details::e_sub : specfunc = "(t-t)/t" break; 38324 | default : return error_node(); 38325 | } 38326 | 38327 | const bool synthesis_result = 38328 | synthesize_sf3ext_expression:: 38329 | template compile<vtype, vtype, ctype>(expr_gen, specfunc, v0, v1, c0, result); 38330 | 38331 | exprtk_debug(("(v0 / c) +/- (v1 / c) --> (vovoc) (v0 +/- v1) / c\n")); 38332 | 38333 | return (synthesis_result) ? result : error_node(); 38334 | } 38335 | } 38336 | 38337 | const bool synthesis_result = 38338 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38339 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result); 38340 | 38341 | if (synthesis_result) 38342 | return result; 38343 | 38344 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38345 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 38346 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 38347 | 38348 | if (!expr_gen.valid_operator(o0,f0)) 38349 | return error_node(); 38350 | else if (!expr_gen.valid_operator(o1,f1)) 38351 | return error_node(); 38352 | else if (!expr_gen.valid_operator(o2,f2)) 38353 | return error_node(); 38354 | else 38355 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2); 38356 | } 38357 | 38358 | static inline std::string id(expression_generator<Type>& expr_gen, 38359 | const details::operator_type o0, 38360 | const details::operator_type o1, 38361 | const details::operator_type o2) 38362 | { 38363 | return details::build_string() 38364 | << "(t" << expr_gen.to_str(o0) 38365 | << "t)" << expr_gen.to_str(o1) 38366 | << "(t" << expr_gen.to_str(o2) 38367 | << "t)" 38368 | } 38369 | }; 38370 | 38371 | struct synthesize_covovoc_expression0 38372 | { 38373 | typedef typename covovoc_t::type0 node_type; 38374 | typedef typename covovoc_t::sf4_type sf4_type; 38375 | typedef typename node_type::T0 T0; 38376 | typedef typename node_type::T1 T1; 38377 | typedef typename node_type::T2 T2; 38378 | typedef typename node_type::T3 T3; 38379 | 38380 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38381 | const details::operator_type& operation, 38382 | expression_node_ptr (&branch)[2]) 38383 | { 38384 | // (c0 o0 v0) o1 (v1 o2 c1) 38385 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]); 38386 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]); 38387 | const Type c0 = cov->c(); 38388 | const Type& v0 = cov->v(); 38389 | const Type c1 = voc->c(); 38390 | const Type& v1 = voc->v(); 38391 | const details::operator_type o0 = cov->operation(); 38392 | const details::operator_type o1 = operation; 38393 | const details::operator_type o2 = voc->operation(); 38394 | 38395 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 38396 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38397 | 38398 | expression_node_ptr result = error_node(); 38399 | 38400 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 38401 | { 38402 | // (c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1 38403 | if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2)) 38404 | { 38405 | const bool synthesis_result = 38406 | synthesize_sf3ext_expression:: 38407 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result); 38408 | 38409 | exprtk_debug(("(c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n")); 38410 | 38411 | return (synthesis_result) ? result : error_node(); 38412 | } 38413 | // (c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1 38414 | else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2)) 38415 | { 38416 | const bool synthesis_result = 38417 | synthesize_sf3ext_expression:: 38418 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result); 38419 | 38420 | exprtk_debug(("(c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n")); 38421 | 38422 | return (synthesis_result) ? result : error_node(); 38423 | } 38424 | // (c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1 38425 | else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2)) 38426 | { 38427 | const bool synthesis_result = 38428 | synthesize_sf3ext_expression:: 38429 | template compile<ctype, vtype, vtype>(expr_gen, "t-(t+t)", (c0 + c1), v0, v1, result); 38430 | 38431 | exprtk_debug(("(c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1\n")); 38432 | 38433 | return (synthesis_result) ? result : error_node(); 38434 | } 38435 | // (c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1 38436 | else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2)) 38437 | { 38438 | const bool synthesis_result = 38439 | synthesize_sf3ext_expression:: 38440 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result); 38441 | 38442 | exprtk_debug(("(c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n")); 38443 | 38444 | return (synthesis_result) ? result : error_node(); 38445 | } 38446 | // (c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1) 38447 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38448 | { 38449 | const bool synthesis_result = 38450 | synthesize_sf3ext_expression:: 38451 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result); 38452 | 38453 | exprtk_debug(("(c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n")); 38454 | 38455 | return (synthesis_result) ? result : error_node(); 38456 | } 38457 | // (c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0) 38458 | else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 38459 | { 38460 | const bool synthesis_result = 38461 | synthesize_sf3ext_expression:: 38462 | template compile<ctype, vtype, vtype>(expr_gen, "t*(t/t)", (c0 / c1), v1, v0, result); 38463 | 38464 | exprtk_debug(("(c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0)\n")); 38465 | 38466 | return (synthesis_result) ? result : error_node(); 38467 | } 38468 | // (c0 / v0) / (v1 / c1) --> (covov) (c0 * c1) / (v0 * v1) 38469 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 38470 | { 38471 | const bool synthesis_result = 38472 | synthesize_sf3ext_expression:: 38473 | template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", (c0 * c1), v0, v1, result); 38474 | 38475 | exprtk_debug(("(c0 / v0) / (v1 / c1) --> (covov) (c0 * c1) / (v0 * v1)\n")); 38476 | 38477 | return (synthesis_result) ? result : error_node(); 38478 | } 38479 | // (c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1) 38480 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) 38481 | { 38482 | const bool synthesis_result = 38483 | synthesize_sf3ext_expression:: 38484 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 * c1), v0, v1, result); 38485 | 38486 | exprtk_debug(("(c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n")); 38487 | 38488 | return (synthesis_result) ? result : error_node(); 38489 | } 38490 | // (c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1) 38491 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38492 | { 38493 | const bool synthesis_result = 38494 | synthesize_sf3ext_expression:: 38495 | template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", (c0 / c1), v0, v1, result); 38496 | 38497 | exprtk_debug(("(c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1)\n")); 38498 | 38499 | return (synthesis_result) ? result : error_node(); 38500 | } 38501 | // (c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1) 38502 | else if ( 38503 | (std::equal_to<T>()(c0,c1)) && 38504 | (details::e_mul == o0) && 38505 | (details::e_mul == o2) && 38506 | ( 38507 | (details::e_add == o1) || 38508 | (details::e_sub == o1) 38509 | ) 38510 | ) 38511 | { 38512 | std::string specfunc; 38513 | 38514 | switch (o1) 38515 | { 38516 | case details::e_add : specfunc = "t*(t+t)" break; 38517 | case details::e_sub : specfunc = "t*(t-t)" break; 38518 | default : return error_node(); 38519 | } 38520 | 38521 | const bool synthesis_result = 38522 | synthesize_sf3ext_expression:: 38523 | template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result); 38524 | 38525 | exprtk_debug(("(c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n")); 38526 | 38527 | return (synthesis_result) ? result : error_node(); 38528 | } 38529 | } 38530 | 38531 | const bool synthesis_result = 38532 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38533 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result); 38534 | 38535 | if (synthesis_result) 38536 | return result; 38537 | 38538 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38539 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 38540 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 38541 | 38542 | if (!expr_gen.valid_operator(o0,f0)) 38543 | return error_node(); 38544 | else if (!expr_gen.valid_operator(o1,f1)) 38545 | return error_node(); 38546 | else if (!expr_gen.valid_operator(o2,f2)) 38547 | return error_node(); 38548 | else 38549 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2); 38550 | } 38551 | 38552 | static inline std::string id(expression_generator<Type>& expr_gen, 38553 | const details::operator_type o0, 38554 | const details::operator_type o1, 38555 | const details::operator_type o2) 38556 | { 38557 | return details::build_string() 38558 | << "(t" << expr_gen.to_str(o0) 38559 | << "t)" << expr_gen.to_str(o1) 38560 | << "(t" << expr_gen.to_str(o2) 38561 | << "t)" 38562 | } 38563 | }; 38564 | 38565 | struct synthesize_vococov_expression0 38566 | { 38567 | typedef typename vococov_t::type0 node_type; 38568 | typedef typename vococov_t::sf4_type sf4_type; 38569 | typedef typename node_type::T0 T0; 38570 | typedef typename node_type::T1 T1; 38571 | typedef typename node_type::T2 T2; 38572 | typedef typename node_type::T3 T3; 38573 | 38574 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38575 | const details::operator_type& operation, 38576 | expression_node_ptr (&branch)[2]) 38577 | { 38578 | // (v0 o0 c0) o1 (c1 o2 v1) 38579 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]); 38580 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]); 38581 | const Type c0 = voc->c(); 38582 | const Type& v0 = voc->v(); 38583 | const Type c1 = cov->c(); 38584 | const Type& v1 = cov->v(); 38585 | const details::operator_type o0 = voc->operation(); 38586 | const details::operator_type o1 = operation; 38587 | const details::operator_type o2 = cov->operation(); 38588 | 38589 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 38590 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38591 | 38592 | expression_node_ptr result = error_node(); 38593 | 38594 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 38595 | { 38596 | // (v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1 38597 | if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2)) 38598 | { 38599 | const bool synthesis_result = 38600 | synthesize_sf3ext_expression:: 38601 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result); 38602 | 38603 | exprtk_debug(("(v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n")); 38604 | 38605 | return (synthesis_result) ? result : error_node(); 38606 | } 38607 | // (v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1 38608 | else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2)) 38609 | { 38610 | const bool synthesis_result = 38611 | synthesize_sf3ext_expression:: 38612 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result); 38613 | 38614 | exprtk_debug(("(v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n")); 38615 | 38616 | return (synthesis_result) ? result : error_node(); 38617 | } 38618 | // (v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0) 38619 | else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2)) 38620 | { 38621 | const bool synthesis_result = 38622 | synthesize_sf3ext_expression:: 38623 | template compile<vtype, vtype, ctype>(expr_gen, "(t+t)-t", v0, v1, (c1 + c0), result); 38624 | 38625 | exprtk_debug(("(v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0)\n")); 38626 | 38627 | return (synthesis_result) ? result : error_node(); 38628 | } 38629 | // (v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1 38630 | else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2)) 38631 | { 38632 | const bool synthesis_result = 38633 | synthesize_sf3ext_expression:: 38634 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result); 38635 | 38636 | exprtk_debug(("(v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n")); 38637 | 38638 | return (synthesis_result) ? result : error_node(); 38639 | } 38640 | // (v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1) 38641 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38642 | { 38643 | const bool synthesis_result = 38644 | synthesize_sf3ext_expression:: 38645 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result); 38646 | 38647 | exprtk_debug(("(v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1)\n")); 38648 | 38649 | return (synthesis_result) ? result : error_node(); 38650 | } 38651 | // (v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1) 38652 | else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 38653 | { 38654 | const bool synthesis_result = 38655 | synthesize_sf3ext_expression:: 38656 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c1 / c0), v0, v1, result); 38657 | 38658 | exprtk_debug(("(v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1)\n")); 38659 | 38660 | return (synthesis_result) ? result : error_node(); 38661 | } 38662 | // (v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1) 38663 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) 38664 | { 38665 | const bool synthesis_result = 38666 | synthesize_sf3ext_expression:: 38667 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 / c1), v0, v1, result); 38668 | 38669 | exprtk_debug(("(v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n")); 38670 | 38671 | return (synthesis_result) ? result : error_node(); 38672 | } 38673 | // (v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1) 38674 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38675 | { 38676 | const bool synthesis_result = 38677 | synthesize_sf3ext_expression:: 38678 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", Type(1) / (c0 * c1), v0, v1, result); 38679 | 38680 | exprtk_debug(("(v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1)\n")); 38681 | 38682 | return (synthesis_result) ? result : error_node(); 38683 | } 38684 | // (v0 / c0) / (c1 / v1) --> (vovoc) (v0 * v1) * (1 / (c0 * c1)) 38685 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 38686 | { 38687 | const bool synthesis_result = 38688 | synthesize_sf3ext_expression:: 38689 | template compile<vtype, vtype, ctype>(expr_gen, "(t*t)*t", v0, v1, Type(1) / (c0 * c1), result); 38690 | 38691 | exprtk_debug(("(v0 / c0) / (c1 / v1) --> (vovoc) (v0 * v1) * (1 / (c0 * c1))\n")); 38692 | 38693 | return (synthesis_result) ? result : error_node(); 38694 | } 38695 | // (v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1) 38696 | else if ( 38697 | (std::equal_to<T>()(c0,c1)) && 38698 | (details::e_mul == o0) && 38699 | (details::e_mul == o2) && 38700 | ( 38701 | (details::e_add == o1) || (details::e_sub == o1) 38702 | ) 38703 | ) 38704 | { 38705 | std::string specfunc; 38706 | 38707 | switch (o1) 38708 | { 38709 | case details::e_add : specfunc = "t*(t+t)" break; 38710 | case details::e_sub : specfunc = "t*(t-t)" break; 38711 | default : return error_node(); 38712 | } 38713 | 38714 | const bool synthesis_result = 38715 | synthesize_sf3ext_expression:: 38716 | template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result); 38717 | 38718 | exprtk_debug(("(v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1)\n")); 38719 | 38720 | return (synthesis_result) ? result : error_node(); 38721 | } 38722 | } 38723 | 38724 | const bool synthesis_result = 38725 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38726 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result); 38727 | 38728 | if (synthesis_result) 38729 | return result; 38730 | 38731 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38732 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 38733 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 38734 | 38735 | if (!expr_gen.valid_operator(o0,f0)) 38736 | return error_node(); 38737 | else if (!expr_gen.valid_operator(o1,f1)) 38738 | return error_node(); 38739 | else if (!expr_gen.valid_operator(o2,f2)) 38740 | return error_node(); 38741 | else 38742 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2); 38743 | } 38744 | 38745 | static inline std::string id(expression_generator<Type>& expr_gen, 38746 | const details::operator_type o0, 38747 | const details::operator_type o1, 38748 | const details::operator_type o2) 38749 | { 38750 | return details::build_string() 38751 | << "(t" << expr_gen.to_str(o0) 38752 | << "t)" << expr_gen.to_str(o1) 38753 | << "(t" << expr_gen.to_str(o2) 38754 | << "t)" 38755 | } 38756 | }; 38757 | 38758 | struct synthesize_vovovov_expression1 38759 | { 38760 | typedef typename vovovov_t::type1 node_type; 38761 | typedef typename vovovov_t::sf4_type sf4_type; 38762 | typedef typename node_type::T0 T0; 38763 | typedef typename node_type::T1 T1; 38764 | typedef typename node_type::T2 T2; 38765 | typedef typename node_type::T3 T3; 38766 | 38767 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38768 | const details::operator_type& operation, 38769 | expression_node_ptr (&branch)[2]) 38770 | { 38771 | // v0 o0 (v1 o1 (v2 o2 v3)) 38772 | typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t; 38773 | 38774 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]); 38775 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 38776 | const Type& v1 = vovov->t0(); 38777 | const Type& v2 = vovov->t1(); 38778 | const Type& v3 = vovov->t2(); 38779 | const details::operator_type o0 = operation; 38780 | const details::operator_type o1 = expr_gen.get_operator(vovov->f0()); 38781 | const details::operator_type o2 = expr_gen.get_operator(vovov->f1()); 38782 | 38783 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38784 | binary_functor_t f1 = vovov->f0(); 38785 | binary_functor_t f2 = vovov->f1(); 38786 | 38787 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38788 | 38789 | expression_node_ptr result = error_node(); 38790 | 38791 | const bool synthesis_result = 38792 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38793 | (expr_gen,id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result); 38794 | 38795 | if (synthesis_result) 38796 | return result; 38797 | else if (!expr_gen.valid_operator(o0,f0)) 38798 | return error_node(); 38799 | 38800 | exprtk_debug(("v0 o0 (v1 o1 (v2 o2 v3))\n")); 38801 | 38802 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2); 38803 | } 38804 | 38805 | static inline std::string id(expression_generator<Type>& expr_gen, 38806 | const details::operator_type o0, 38807 | const details::operator_type o1, 38808 | const details::operator_type o2) 38809 | { 38810 | return details::build_string() 38811 | << "t" << expr_gen.to_str(o0) 38812 | << "(t" << expr_gen.to_str(o1) 38813 | << "(t" << expr_gen.to_str(o2) 38814 | << "t))" 38815 | } 38816 | }; 38817 | 38818 | struct synthesize_vovovoc_expression1 38819 | { 38820 | typedef typename vovovoc_t::type1 node_type; 38821 | typedef typename vovovoc_t::sf4_type sf4_type; 38822 | typedef typename node_type::T0 T0; 38823 | typedef typename node_type::T1 T1; 38824 | typedef typename node_type::T2 T2; 38825 | typedef typename node_type::T3 T3; 38826 | 38827 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38828 | const details::operator_type& operation, 38829 | expression_node_ptr (&branch)[2]) 38830 | { 38831 | // v0 o0 (v1 o1 (v2 o2 c)) 38832 | typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t; 38833 | 38834 | const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]); 38835 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 38836 | const Type& v1 = vovoc->t0(); 38837 | const Type& v2 = vovoc->t1(); 38838 | const Type c = vovoc->t2(); 38839 | const details::operator_type o0 = operation; 38840 | const details::operator_type o1 = expr_gen.get_operator(vovoc->f0()); 38841 | const details::operator_type o2 = expr_gen.get_operator(vovoc->f1()); 38842 | 38843 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38844 | binary_functor_t f1 = vovoc->f0(); 38845 | binary_functor_t f2 = vovoc->f1(); 38846 | 38847 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38848 | 38849 | expression_node_ptr result = error_node(); 38850 | 38851 | const bool synthesis_result = 38852 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38853 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result); 38854 | 38855 | if (synthesis_result) 38856 | return result; 38857 | else if (!expr_gen.valid_operator(o0,f0)) 38858 | return error_node(); 38859 | 38860 | exprtk_debug(("v0 o0 (v1 o1 (v2 o2 c))\n")); 38861 | 38862 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2); 38863 | } 38864 | 38865 | static inline std::string id(expression_generator<Type>& expr_gen, 38866 | const details::operator_type o0, 38867 | const details::operator_type o1, 38868 | const details::operator_type o2) 38869 | { 38870 | return details::build_string() 38871 | << "t" << expr_gen.to_str(o0) 38872 | << "(t" << expr_gen.to_str(o1) 38873 | << "(t" << expr_gen.to_str(o2) 38874 | << "t))" 38875 | } 38876 | }; 38877 | 38878 | struct synthesize_vovocov_expression1 38879 | { 38880 | typedef typename vovocov_t::type1 node_type; 38881 | typedef typename vovocov_t::sf4_type sf4_type; 38882 | typedef typename node_type::T0 T0; 38883 | typedef typename node_type::T1 T1; 38884 | typedef typename node_type::T2 T2; 38885 | typedef typename node_type::T3 T3; 38886 | 38887 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38888 | const details::operator_type& operation, 38889 | expression_node_ptr (&branch)[2]) 38890 | { 38891 | // v0 o0 (v1 o1 (c o2 v2)) 38892 | typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t; 38893 | 38894 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]); 38895 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 38896 | const Type& v1 = vocov->t0(); 38897 | const Type c = vocov->t1(); 38898 | const Type& v2 = vocov->t2(); 38899 | const details::operator_type o0 = operation; 38900 | const details::operator_type o1 = expr_gen.get_operator(vocov->f0()); 38901 | const details::operator_type o2 = expr_gen.get_operator(vocov->f1()); 38902 | 38903 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38904 | binary_functor_t f1 = vocov->f0(); 38905 | binary_functor_t f2 = vocov->f1(); 38906 | 38907 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38908 | 38909 | expression_node_ptr result = error_node(); 38910 | 38911 | const bool synthesis_result = 38912 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38913 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result); 38914 | 38915 | if (synthesis_result) 38916 | return result; 38917 | if (!expr_gen.valid_operator(o0,f0)) 38918 | return error_node(); 38919 | 38920 | exprtk_debug(("v0 o0 (v1 o1 (c o2 v2))\n")); 38921 | 38922 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2); 38923 | } 38924 | 38925 | static inline std::string id(expression_generator<Type>& expr_gen, 38926 | const details::operator_type o0, 38927 | const details::operator_type o1, 38928 | const details::operator_type o2) 38929 | { 38930 | return details::build_string() 38931 | << "t" << expr_gen.to_str(o0) 38932 | << "(t" << expr_gen.to_str(o1) 38933 | << "(t" << expr_gen.to_str(o2) 38934 | << "t))" 38935 | } 38936 | }; 38937 | 38938 | struct synthesize_vocovov_expression1 38939 | { 38940 | typedef typename vocovov_t::type1 node_type; 38941 | typedef typename vocovov_t::sf4_type sf4_type; 38942 | typedef typename node_type::T0 T0; 38943 | typedef typename node_type::T1 T1; 38944 | typedef typename node_type::T2 T2; 38945 | typedef typename node_type::T3 T3; 38946 | 38947 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38948 | const details::operator_type& operation, 38949 | expression_node_ptr (&branch)[2]) 38950 | { 38951 | // v0 o0 (c o1 (v1 o2 v2)) 38952 | typedef typename synthesize_covov_expression1::node_type lcl_covov_t; 38953 | 38954 | const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[1]); 38955 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 38956 | const Type c = covov->t0(); 38957 | const Type& v1 = covov->t1(); 38958 | const Type& v2 = covov->t2(); 38959 | const details::operator_type o0 = operation; 38960 | const details::operator_type o1 = expr_gen.get_operator(covov->f0()); 38961 | const details::operator_type o2 = expr_gen.get_operator(covov->f1()); 38962 | 38963 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38964 | binary_functor_t f1 = covov->f0(); 38965 | binary_functor_t f2 = covov->f1(); 38966 | 38967 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38968 | 38969 | expression_node_ptr result = error_node(); 38970 | 38971 | const bool synthesis_result = 38972 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38973 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result); 38974 | 38975 | if (synthesis_result) 38976 | return result; 38977 | else if (!expr_gen.valid_operator(o0,f0)) 38978 | return error_node(); 38979 | 38980 | exprtk_debug(("v0 o0 (c o1 (v1 o2 v2))\n")); 38981 | 38982 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2); 38983 | } 38984 | 38985 | static inline std::string id(expression_generator<Type>& expr_gen, 38986 | const details::operator_type o0, 38987 | const details::operator_type o1, 38988 | const details::operator_type o2) 38989 | { 38990 | return details::build_string() 38991 | << "t" << expr_gen.to_str(o0) 38992 | << "(t" << expr_gen.to_str(o1) 38993 | << "(t" << expr_gen.to_str(o2) 38994 | << "t))" 38995 | } 38996 | }; 38997 | 38998 | struct synthesize_covovov_expression1 38999 | { 39000 | typedef typename covovov_t::type1 node_type; 39001 | typedef typename covovov_t::sf4_type sf4_type; 39002 | typedef typename node_type::T0 T0; 39003 | typedef typename node_type::T1 T1; 39004 | typedef typename node_type::T2 T2; 39005 | typedef typename node_type::T3 T3; 39006 | 39007 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39008 | const details::operator_type& operation, 39009 | expression_node_ptr (&branch)[2]) 39010 | { 39011 | // c o0 (v0 o1 (v1 o2 v2)) 39012 | typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t; 39013 | 39014 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]); 39015 | const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); 39016 | const Type& v0 = vovov->t0(); 39017 | const Type& v1 = vovov->t1(); 39018 | const Type& v2 = vovov->t2(); 39019 | const details::operator_type o0 = operation; 39020 | const details::operator_type o1 = expr_gen.get_operator(vovov->f0()); 39021 | const details::operator_type o2 = expr_gen.get_operator(vovov->f1()); 39022 | 39023 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39024 | binary_functor_t f1 = vovov->f0(); 39025 | binary_functor_t f2 = vovov->f1(); 39026 | 39027 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39028 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39029 | 39030 | expression_node_ptr result = error_node(); 39031 | 39032 | const bool synthesis_result = 39033 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39034 | (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result); 39035 | 39036 | if (synthesis_result) 39037 | return result; 39038 | if (!expr_gen.valid_operator(o0,f0)) 39039 | return error_node(); 39040 | 39041 | exprtk_debug(("c o0 (v0 o1 (v1 o2 v2))\n")); 39042 | 39043 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2); 39044 | } 39045 | 39046 | static inline std::string id(expression_generator<Type>& expr_gen, 39047 | const details::operator_type o0, 39048 | const details::operator_type o1, 39049 | const details::operator_type o2) 39050 | { 39051 | return details::build_string() 39052 | << "t" << expr_gen.to_str(o0) 39053 | << "(t" << expr_gen.to_str(o1) 39054 | << "(t" << expr_gen.to_str(o2) 39055 | << "t))" 39056 | } 39057 | }; 39058 | 39059 | struct synthesize_covocov_expression1 39060 | { 39061 | typedef typename covocov_t::type1 node_type; 39062 | typedef typename covocov_t::sf4_type sf4_type; 39063 | typedef typename node_type::T0 T0; 39064 | typedef typename node_type::T1 T1; 39065 | typedef typename node_type::T2 T2; 39066 | typedef typename node_type::T3 T3; 39067 | 39068 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39069 | const details::operator_type& operation, 39070 | expression_node_ptr (&branch)[2]) 39071 | { 39072 | // c0 o0 (v0 o1 (c1 o2 v1)) 39073 | typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t; 39074 | 39075 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]); 39076 | const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); 39077 | const Type& v0 = vocov->t0(); 39078 | const Type c1 = vocov->t1(); 39079 | const Type& v1 = vocov->t2(); 39080 | const details::operator_type o0 = operation; 39081 | const details::operator_type o1 = expr_gen.get_operator(vocov->f0()); 39082 | const details::operator_type o2 = expr_gen.get_operator(vocov->f1()); 39083 | 39084 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39085 | binary_functor_t f1 = vocov->f0(); 39086 | binary_functor_t f2 = vocov->f1(); 39087 | 39088 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39089 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39090 | 39091 | expression_node_ptr result = error_node(); 39092 | 39093 | const bool synthesis_result = 39094 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39095 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result); 39096 | 39097 | if (synthesis_result) 39098 | return result; 39099 | else if (!expr_gen.valid_operator(o0,f0)) 39100 | return error_node(); 39101 | 39102 | exprtk_debug(("c0 o0 (v0 o1 (c1 o2 v1))\n")); 39103 | 39104 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2); 39105 | } 39106 | 39107 | static inline std::string id(expression_generator<Type>& expr_gen, 39108 | const details::operator_type o0, 39109 | const details::operator_type o1, 39110 | const details::operator_type o2) 39111 | { 39112 | return details::build_string() 39113 | << "t" << expr_gen.to_str(o0) 39114 | << "(t" << expr_gen.to_str(o1) 39115 | << "(t" << expr_gen.to_str(o2) 39116 | << "t))" 39117 | } 39118 | }; 39119 | 39120 | struct synthesize_vocovoc_expression1 39121 | { 39122 | typedef typename vocovoc_t::type1 node_type; 39123 | typedef typename vocovoc_t::sf4_type sf4_type; 39124 | typedef typename node_type::T0 T0; 39125 | typedef typename node_type::T1 T1; 39126 | typedef typename node_type::T2 T2; 39127 | typedef typename node_type::T3 T3; 39128 | 39129 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39130 | const details::operator_type& operation, 39131 | expression_node_ptr (&branch)[2]) 39132 | { 39133 | // v0 o0 (c0 o1 (v1 o2 c2)) 39134 | typedef typename synthesize_covoc_expression1::node_type lcl_covoc_t; 39135 | 39136 | const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[1]); 39137 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39138 | const Type c0 = covoc->t0(); 39139 | const Type& v1 = covoc->t1(); 39140 | const Type c1 = covoc->t2(); 39141 | const details::operator_type o0 = operation; 39142 | const details::operator_type o1 = expr_gen.get_operator(covoc->f0()); 39143 | const details::operator_type o2 = expr_gen.get_operator(covoc->f1()); 39144 | 39145 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39146 | binary_functor_t f1 = covoc->f0(); 39147 | binary_functor_t f2 = covoc->f1(); 39148 | 39149 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39150 | 39151 | expression_node_ptr result = error_node(); 39152 | 39153 | const bool synthesis_result = 39154 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39155 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result); 39156 | 39157 | if (synthesis_result) 39158 | return result; 39159 | else if (!expr_gen.valid_operator(o0,f0)) 39160 | return error_node(); 39161 | 39162 | exprtk_debug(("v0 o0 (c0 o1 (v1 o2 c2))\n")); 39163 | 39164 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2); 39165 | } 39166 | 39167 | static inline std::string id(expression_generator<Type>& expr_gen, 39168 | const details::operator_type o0, 39169 | const details::operator_type o1, 39170 | const details::operator_type o2) 39171 | { 39172 | return details::build_string() 39173 | << "t" << expr_gen.to_str(o0) 39174 | << "(t" << expr_gen.to_str(o1) 39175 | << "(t" << expr_gen.to_str(o2) 39176 | << "t))" 39177 | } 39178 | }; 39179 | 39180 | struct synthesize_covovoc_expression1 39181 | { 39182 | typedef typename covovoc_t::type1 node_type; 39183 | typedef typename covovoc_t::sf4_type sf4_type; 39184 | typedef typename node_type::T0 T0; 39185 | typedef typename node_type::T1 T1; 39186 | typedef typename node_type::T2 T2; 39187 | typedef typename node_type::T3 T3; 39188 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39189 | const details::operator_type& operation, 39190 | expression_node_ptr (&branch)[2]) 39191 | { 39192 | // c0 o0 (v0 o1 (v1 o2 c1)) 39193 | typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t; 39194 | 39195 | const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]); 39196 | const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); 39197 | const Type& v0 = vovoc->t0(); 39198 | const Type& v1 = vovoc->t1(); 39199 | const Type c1 = vovoc->t2(); 39200 | const details::operator_type o0 = operation; 39201 | const details::operator_type o1 = expr_gen.get_operator(vovoc->f0()); 39202 | const details::operator_type o2 = expr_gen.get_operator(vovoc->f1()); 39203 | 39204 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39205 | binary_functor_t f1 = vovoc->f0(); 39206 | binary_functor_t f2 = vovoc->f1(); 39207 | 39208 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39209 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39210 | 39211 | expression_node_ptr result = error_node(); 39212 | 39213 | const bool synthesis_result = 39214 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39215 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result); 39216 | 39217 | if (synthesis_result) 39218 | return result; 39219 | else if (!expr_gen.valid_operator(o0,f0)) 39220 | return error_node(); 39221 | 39222 | exprtk_debug(("c0 o0 (v0 o1 (v1 o2 c1))\n")); 39223 | 39224 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2); 39225 | } 39226 | 39227 | static inline std::string id(expression_generator<Type>& expr_gen, 39228 | const details::operator_type o0, 39229 | const details::operator_type o1, 39230 | const details::operator_type o2) 39231 | { 39232 | return details::build_string() 39233 | << "t" << expr_gen.to_str(o0) 39234 | << "(t" << expr_gen.to_str(o1) 39235 | << "(t" << expr_gen.to_str(o2) 39236 | << "t))" 39237 | } 39238 | }; 39239 | 39240 | struct synthesize_vococov_expression1 39241 | { 39242 | typedef typename vococov_t::type1 node_type; 39243 | typedef typename vococov_t::sf4_type sf4_type; 39244 | typedef typename node_type::T0 T0; 39245 | typedef typename node_type::T1 T1; 39246 | typedef typename node_type::T2 T2; 39247 | typedef typename node_type::T3 T3; 39248 | 39249 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39250 | const details::operator_type& operation, 39251 | expression_node_ptr (&branch)[2]) 39252 | { 39253 | // v0 o0 (c0 o1 (c1 o2 v1)) 39254 | typedef typename synthesize_cocov_expression1::node_type lcl_cocov_t; 39255 | 39256 | const lcl_cocov_t* cocov = static_cast<const lcl_cocov_t*>(branch[1]); 39257 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39258 | const Type c0 = cocov->t0(); 39259 | const Type c1 = cocov->t1(); 39260 | const Type& v1 = cocov->t2(); 39261 | const details::operator_type o0 = operation; 39262 | const details::operator_type o1 = expr_gen.get_operator(cocov->f0()); 39263 | const details::operator_type o2 = expr_gen.get_operator(cocov->f1()); 39264 | 39265 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39266 | binary_functor_t f1 = cocov->f0(); 39267 | binary_functor_t f2 = cocov->f1(); 39268 | 39269 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39270 | 39271 | expression_node_ptr result = error_node(); 39272 | 39273 | const bool synthesis_result = 39274 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39275 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result); 39276 | 39277 | if (synthesis_result) 39278 | return result; 39279 | else if (!expr_gen.valid_operator(o0,f0)) 39280 | return error_node(); 39281 | 39282 | exprtk_debug(("v0 o0 (c0 o1 (c1 o2 v1))\n")); 39283 | 39284 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2); 39285 | } 39286 | 39287 | static inline std::string id(expression_generator<Type>& expr_gen, 39288 | const details::operator_type o0, 39289 | const details::operator_type o1, 39290 | const details::operator_type o2) 39291 | { 39292 | return details::build_string() 39293 | << "t" << expr_gen.to_str(o0) 39294 | << "(t" << expr_gen.to_str(o1) 39295 | << "(t" << expr_gen.to_str(o2) 39296 | << "t))" 39297 | } 39298 | }; 39299 | 39300 | struct synthesize_vovovov_expression2 39301 | { 39302 | typedef typename vovovov_t::type2 node_type; 39303 | typedef typename vovovov_t::sf4_type sf4_type; 39304 | typedef typename node_type::T0 T0; 39305 | typedef typename node_type::T1 T1; 39306 | typedef typename node_type::T2 T2; 39307 | typedef typename node_type::T3 T3; 39308 | 39309 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39310 | const details::operator_type& operation, 39311 | expression_node_ptr (&branch)[2]) 39312 | { 39313 | // v0 o0 ((v1 o1 v2) o2 v3) 39314 | typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t; 39315 | 39316 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]); 39317 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39318 | const Type& v1 = vovov->t0(); 39319 | const Type& v2 = vovov->t1(); 39320 | const Type& v3 = vovov->t2(); 39321 | const details::operator_type o0 = operation; 39322 | const details::operator_type o1 = expr_gen.get_operator(vovov->f0()); 39323 | const details::operator_type o2 = expr_gen.get_operator(vovov->f1()); 39324 | 39325 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39326 | binary_functor_t f1 = vovov->f0(); 39327 | binary_functor_t f2 = vovov->f1(); 39328 | 39329 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39330 | 39331 | expression_node_ptr result = error_node(); 39332 | 39333 | const bool synthesis_result = 39334 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39335 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result); 39336 | 39337 | if (synthesis_result) 39338 | return result; 39339 | else if (!expr_gen.valid_operator(o0,f0)) 39340 | return error_node(); 39341 | 39342 | exprtk_debug(("v0 o0 ((v1 o1 v2) o2 v3)\n")); 39343 | 39344 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2); 39345 | } 39346 | 39347 | static inline std::string id(expression_generator<Type>& expr_gen, 39348 | const details::operator_type o0, 39349 | const details::operator_type o1, 39350 | const details::operator_type o2) 39351 | { 39352 | return details::build_string() 39353 | << "t" << expr_gen.to_str(o0) 39354 | << "((t" << expr_gen.to_str(o1) 39355 | << "t)" << expr_gen.to_str(o2) 39356 | << "t)" 39357 | } 39358 | }; 39359 | 39360 | struct synthesize_vovovoc_expression2 39361 | { 39362 | typedef typename vovovoc_t::type2 node_type; 39363 | typedef typename vovovoc_t::sf4_type sf4_type; 39364 | typedef typename node_type::T0 T0; 39365 | typedef typename node_type::T1 T1; 39366 | typedef typename node_type::T2 T2; 39367 | typedef typename node_type::T3 T3; 39368 | 39369 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39370 | const details::operator_type& operation, 39371 | expression_node_ptr (&branch)[2]) 39372 | { 39373 | // v0 o0 ((v1 o1 v2) o2 c) 39374 | typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t; 39375 | 39376 | const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]); 39377 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39378 | const Type& v1 = vovoc->t0(); 39379 | const Type& v2 = vovoc->t1(); 39380 | const Type c = vovoc->t2(); 39381 | const details::operator_type o0 = operation; 39382 | const details::operator_type o1 = expr_gen.get_operator(vovoc->f0()); 39383 | const details::operator_type o2 = expr_gen.get_operator(vovoc->f1()); 39384 | 39385 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39386 | binary_functor_t f1 = vovoc->f0(); 39387 | binary_functor_t f2 = vovoc->f1(); 39388 | 39389 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39390 | 39391 | expression_node_ptr result = error_node(); 39392 | 39393 | const bool synthesis_result = 39394 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39395 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result); 39396 | 39397 | if (synthesis_result) 39398 | return result; 39399 | else if (!expr_gen.valid_operator(o0,f0)) 39400 | return error_node(); 39401 | 39402 | exprtk_debug(("v0 o0 ((v1 o1 v2) o2 c)\n")); 39403 | 39404 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2); 39405 | } 39406 | 39407 | static inline std::string id(expression_generator<Type>& expr_gen, 39408 | const details::operator_type o0, 39409 | const details::operator_type o1, 39410 | const details::operator_type o2) 39411 | { 39412 | return details::build_string() 39413 | << "t" << expr_gen.to_str(o0) 39414 | << "((t" << expr_gen.to_str(o1) 39415 | << "t)" << expr_gen.to_str(o2) 39416 | << "t)" 39417 | } 39418 | }; 39419 | 39420 | struct synthesize_vovocov_expression2 39421 | { 39422 | typedef typename vovocov_t::type2 node_type; 39423 | typedef typename vovocov_t::sf4_type sf4_type; 39424 | typedef typename node_type::T0 T0; 39425 | typedef typename node_type::T1 T1; 39426 | typedef typename node_type::T2 T2; 39427 | typedef typename node_type::T3 T3; 39428 | 39429 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39430 | const details::operator_type& operation, 39431 | expression_node_ptr (&branch)[2]) 39432 | { 39433 | // v0 o0 ((v1 o1 c) o2 v2) 39434 | typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t; 39435 | 39436 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]); 39437 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39438 | const Type& v1 = vocov->t0(); 39439 | const Type c = vocov->t1(); 39440 | const Type& v2 = vocov->t2(); 39441 | const details::operator_type o0 = operation; 39442 | const details::operator_type o1 = expr_gen.get_operator(vocov->f0()); 39443 | const details::operator_type o2 = expr_gen.get_operator(vocov->f1()); 39444 | 39445 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39446 | binary_functor_t f1 = vocov->f0(); 39447 | binary_functor_t f2 = vocov->f1(); 39448 | 39449 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39450 | 39451 | expression_node_ptr result = error_node(); 39452 | 39453 | const bool synthesis_result = 39454 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39455 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result); 39456 | 39457 | if (synthesis_result) 39458 | return result; 39459 | else if (!expr_gen.valid_operator(o0,f0)) 39460 | return error_node(); 39461 | 39462 | exprtk_debug(("v0 o0 ((v1 o1 c) o2 v2)\n")); 39463 | 39464 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2); 39465 | } 39466 | 39467 | static inline std::string id(expression_generator<Type>& expr_gen, 39468 | const details::operator_type o0, 39469 | const details::operator_type o1, 39470 | const details::operator_type o2) 39471 | { 39472 | return details::build_string() 39473 | << "t" << expr_gen.to_str(o0) 39474 | << "((t" << expr_gen.to_str(o1) 39475 | << "t)" << expr_gen.to_str(o2) 39476 | << "t)" 39477 | } 39478 | }; 39479 | 39480 | struct synthesize_vocovov_expression2 39481 | { 39482 | typedef typename vocovov_t::type2 node_type; 39483 | typedef typename vocovov_t::sf4_type sf4_type; 39484 | typedef typename node_type::T0 T0; 39485 | typedef typename node_type::T1 T1; 39486 | typedef typename node_type::T2 T2; 39487 | typedef typename node_type::T3 T3; 39488 | 39489 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39490 | const details::operator_type& operation, 39491 | expression_node_ptr (&branch)[2]) 39492 | { 39493 | // v0 o0 ((c o1 v1) o2 v2) 39494 | typedef typename synthesize_covov_expression0::node_type lcl_covov_t; 39495 | 39496 | const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[1]); 39497 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39498 | const Type c = covov->t0(); 39499 | const Type& v1 = covov->t1(); 39500 | const Type& v2 = covov->t2(); 39501 | const details::operator_type o0 = operation; 39502 | const details::operator_type o1 = expr_gen.get_operator(covov->f0()); 39503 | const details::operator_type o2 = expr_gen.get_operator(covov->f1()); 39504 | 39505 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39506 | binary_functor_t f1 = covov->f0(); 39507 | binary_functor_t f2 = covov->f1(); 39508 | 39509 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39510 | 39511 | expression_node_ptr result = error_node(); 39512 | 39513 | const bool synthesis_result = 39514 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39515 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result); 39516 | 39517 | if (synthesis_result) 39518 | return result; 39519 | else if (!expr_gen.valid_operator(o0,f0)) 39520 | return error_node(); 39521 | 39522 | exprtk_debug(("v0 o0 ((c o1 v1) o2 v2)\n")); 39523 | 39524 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2); 39525 | } 39526 | 39527 | static inline std::string id(expression_generator<Type>& expr_gen, 39528 | const details::operator_type o0, 39529 | const details::operator_type o1, 39530 | const details::operator_type o2) 39531 | { 39532 | return details::build_string() 39533 | << "t" << expr_gen.to_str(o0) 39534 | << "((t" << expr_gen.to_str(o1) 39535 | << "t)" << expr_gen.to_str(o2) 39536 | << "t)" 39537 | } 39538 | }; 39539 | 39540 | struct synthesize_covovov_expression2 39541 | { 39542 | typedef typename covovov_t::type2 node_type; 39543 | typedef typename covovov_t::sf4_type sf4_type; 39544 | typedef typename node_type::T0 T0; 39545 | typedef typename node_type::T1 T1; 39546 | typedef typename node_type::T2 T2; 39547 | typedef typename node_type::T3 T3; 39548 | 39549 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39550 | const details::operator_type& operation, 39551 | expression_node_ptr (&branch)[2]) 39552 | { 39553 | // c o0 ((v1 o1 v2) o2 v3) 39554 | typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t; 39555 | 39556 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]); 39557 | const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); 39558 | const Type& v0 = vovov->t0(); 39559 | const Type& v1 = vovov->t1(); 39560 | const Type& v2 = vovov->t2(); 39561 | const details::operator_type o0 = operation; 39562 | const details::operator_type o1 = expr_gen.get_operator(vovov->f0()); 39563 | const details::operator_type o2 = expr_gen.get_operator(vovov->f1()); 39564 | 39565 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39566 | binary_functor_t f1 = vovov->f0(); 39567 | binary_functor_t f2 = vovov->f1(); 39568 | 39569 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39570 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39571 | 39572 | expression_node_ptr result = error_node(); 39573 | 39574 | const bool synthesis_result = 39575 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39576 | (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result); 39577 | 39578 | if (synthesis_result) 39579 | return result; 39580 | else if (!expr_gen.valid_operator(o0,f0)) 39581 | return error_node(); 39582 | 39583 | exprtk_debug(("c o0 ((v1 o1 v2) o2 v3)\n")); 39584 | 39585 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2); 39586 | } 39587 | 39588 | static inline std::string id(expression_generator<Type>& expr_gen, 39589 | const details::operator_type o0, 39590 | const details::operator_type o1, 39591 | const details::operator_type o2) 39592 | { 39593 | return details::build_string() 39594 | << "t" << expr_gen.to_str(o0) 39595 | << "((t" << expr_gen.to_str(o1) 39596 | << "t)" << expr_gen.to_str(o2) 39597 | << "t)" 39598 | } 39599 | }; 39600 | 39601 | struct synthesize_covocov_expression2 39602 | { 39603 | typedef typename covocov_t::type2 node_type; 39604 | typedef typename covocov_t::sf4_type sf4_type; 39605 | typedef typename node_type::T0 T0; 39606 | typedef typename node_type::T1 T1; 39607 | typedef typename node_type::T2 T2; 39608 | typedef typename node_type::T3 T3; 39609 | 39610 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39611 | const details::operator_type& operation, 39612 | expression_node_ptr (&branch)[2]) 39613 | { 39614 | // c0 o0 ((v0 o1 c1) o2 v1) 39615 | typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t; 39616 | 39617 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]); 39618 | const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); 39619 | const Type& v0 = vocov->t0(); 39620 | const Type c1 = vocov->t1(); 39621 | const Type& v1 = vocov->t2(); 39622 | const details::operator_type o0 = operation; 39623 | const details::operator_type o1 = expr_gen.get_operator(vocov->f0()); 39624 | const details::operator_type o2 = expr_gen.get_operator(vocov->f1()); 39625 | 39626 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39627 | binary_functor_t f1 = vocov->f0(); 39628 | binary_functor_t f2 = vocov->f1(); 39629 | 39630 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39631 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39632 | 39633 | expression_node_ptr result = error_node(); 39634 | 39635 | const bool synthesis_result = 39636 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39637 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result); 39638 | 39639 | if (synthesis_result) 39640 | return result; 39641 | else if (!expr_gen.valid_operator(o0,f0)) 39642 | return error_node(); 39643 | 39644 | exprtk_debug(("c0 o0 ((v0 o1 c1) o2 v1)\n")); 39645 | 39646 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2); 39647 | } 39648 | 39649 | static inline std::string id(expression_generator<Type>& expr_gen, 39650 | const details::operator_type o0, 39651 | const details::operator_type o1, 39652 | const details::operator_type o2) 39653 | { 39654 | return details::build_string() 39655 | << "t" << expr_gen.to_str(o0) 39656 | << "((t" << expr_gen.to_str(o1) 39657 | << "t)" << expr_gen.to_str(o2) 39658 | << "t)" 39659 | } 39660 | }; 39661 | 39662 | struct synthesize_vocovoc_expression2 39663 | { 39664 | typedef typename vocovoc_t::type2 node_type; 39665 | typedef typename vocovoc_t::sf4_type sf4_type; 39666 | typedef typename node_type::T0 T0; 39667 | typedef typename node_type::T1 T1; 39668 | typedef typename node_type::T2 T2; 39669 | typedef typename node_type::T3 T3; 39670 | 39671 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39672 | const details::operator_type& operation, 39673 | expression_node_ptr (&branch)[2]) 39674 | { 39675 | // v0 o0 ((c0 o1 v1) o2 c1) 39676 | typedef typename synthesize_covoc_expression0::node_type lcl_covoc_t; 39677 | 39678 | const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[1]); 39679 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39680 | const Type c0 = covoc->t0(); 39681 | const Type& v1 = covoc->t1(); 39682 | const Type c1 = covoc->t2(); 39683 | const details::operator_type o0 = operation; 39684 | const details::operator_type o1 = expr_gen.get_operator(covoc->f0()); 39685 | const details::operator_type o2 = expr_gen.get_operator(covoc->f1()); 39686 | 39687 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39688 | binary_functor_t f1 = covoc->f0(); 39689 | binary_functor_t f2 = covoc->f1(); 39690 | 39691 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39692 | 39693 | expression_node_ptr result = error_node(); 39694 | 39695 | const bool synthesis_result = 39696 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39697 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result); 39698 | 39699 | if (synthesis_result) 39700 | return result; 39701 | else if (!expr_gen.valid_operator(o0,f0)) 39702 | return error_node(); 39703 | 39704 | exprtk_debug(("v0 o0 ((c0 o1 v1) o2 c1)\n")); 39705 | 39706 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2); 39707 | } 39708 | 39709 | static inline std::string id(expression_generator<Type>& expr_gen, 39710 | const details::operator_type o0, 39711 | const details::operator_type o1, 39712 | const details::operator_type o2) 39713 | { 39714 | return details::build_string() 39715 | << "t" << expr_gen.to_str(o0) 39716 | << "((t" << expr_gen.to_str(o1) 39717 | << "t)" << expr_gen.to_str(o2) 39718 | << "t)" 39719 | } 39720 | }; 39721 | 39722 | struct synthesize_covovoc_expression2 39723 | { 39724 | typedef typename covovoc_t::type2 node_type; 39725 | typedef typename covovoc_t::sf4_type sf4_type; 39726 | typedef typename node_type::T0 T0; 39727 | typedef typename node_type::T1 T1; 39728 | typedef typename node_type::T2 T2; 39729 | typedef typename node_type::T3 T3; 39730 | 39731 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39732 | const details::operator_type& operation, 39733 | expression_node_ptr (&branch)[2]) 39734 | { 39735 | // c0 o0 ((v0 o1 v1) o2 c1) 39736 | typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t; 39737 | 39738 | const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]); 39739 | const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); 39740 | const Type& v0 = vovoc->t0(); 39741 | const Type& v1 = vovoc->t1(); 39742 | const Type c1 = vovoc->t2(); 39743 | const details::operator_type o0 = operation; 39744 | const details::operator_type o1 = expr_gen.get_operator(vovoc->f0()); 39745 | const details::operator_type o2 = expr_gen.get_operator(vovoc->f1()); 39746 | 39747 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39748 | binary_functor_t f1 = vovoc->f0(); 39749 | binary_functor_t f2 = vovoc->f1(); 39750 | 39751 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39752 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39753 | 39754 | expression_node_ptr result = error_node(); 39755 | 39756 | const bool synthesis_result = 39757 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39758 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result); 39759 | 39760 | if (synthesis_result) 39761 | return result; 39762 | else if (!expr_gen.valid_operator(o0,f0)) 39763 | return error_node(); 39764 | 39765 | exprtk_debug(("c0 o0 ((v0 o1 v1) o2 c1)\n")); 39766 | 39767 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2); 39768 | } 39769 | 39770 | static inline std::string id(expression_generator<Type>& expr_gen, 39771 | const details::operator_type o0, 39772 | const details::operator_type o1, 39773 | const details::operator_type o2) 39774 | { 39775 | return details::build_string() 39776 | << "t" << expr_gen.to_str(o0) 39777 | << "((t" << expr_gen.to_str(o1) 39778 | << "t)" << expr_gen.to_str(o2) 39779 | << "t)" 39780 | } 39781 | }; 39782 | 39783 | struct synthesize_vococov_expression2 39784 | { 39785 | typedef typename vococov_t::type2 node_type; 39786 | static inline expression_node_ptr process(expression_generator<Type>&, 39787 | const details::operator_type&, 39788 | expression_node_ptr (&)[2]) 39789 | { 39790 | // v0 o0 ((c0 o1 c1) o2 v1) - Not possible 39791 | exprtk_debug(("v0 o0 ((c0 o1 c1) o2 v1) - Not possible\n")); 39792 | return error_node(); 39793 | } 39794 | 39795 | static inline std::string id(expression_generator<Type>&, 39796 | const details::operator_type, 39797 | const details::operator_type, 39798 | const details::operator_type) 39799 | { 39800 | return "INVALID" 39801 | } 39802 | }; 39803 | 39804 | struct synthesize_vovovov_expression3 39805 | { 39806 | typedef typename vovovov_t::type3 node_type; 39807 | typedef typename vovovov_t::sf4_type sf4_type; 39808 | typedef typename node_type::T0 T0; 39809 | typedef typename node_type::T1 T1; 39810 | typedef typename node_type::T2 T2; 39811 | typedef typename node_type::T3 T3; 39812 | 39813 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39814 | const details::operator_type& operation, 39815 | expression_node_ptr (&branch)[2]) 39816 | { 39817 | // ((v0 o0 v1) o1 v2) o2 v3 39818 | typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t; 39819 | 39820 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]); 39821 | const Type& v0 = vovov->t0(); 39822 | const Type& v1 = vovov->t1(); 39823 | const Type& v2 = vovov->t2(); 39824 | const Type& v3 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 39825 | const details::operator_type o0 = expr_gen.get_operator(vovov->f0()); 39826 | const details::operator_type o1 = expr_gen.get_operator(vovov->f1()); 39827 | const details::operator_type o2 = operation; 39828 | 39829 | binary_functor_t f0 = vovov->f0(); 39830 | binary_functor_t f1 = vovov->f1(); 39831 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 39832 | 39833 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39834 | 39835 | expression_node_ptr result = error_node(); 39836 | 39837 | const bool synthesis_result = 39838 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39839 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result); 39840 | 39841 | if (synthesis_result) 39842 | return result; 39843 | else if (!expr_gen.valid_operator(o2,f2)) 39844 | return error_node(); 39845 | 39846 | exprtk_debug(("((v0 o0 v1) o1 v2) o2 v3\n")); 39847 | 39848 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2); 39849 | } 39850 | 39851 | static inline std::string id(expression_generator<Type>& expr_gen, 39852 | const details::operator_type o0, 39853 | const details::operator_type o1, 39854 | const details::operator_type o2) 39855 | { 39856 | return details::build_string() 39857 | << "((t" << expr_gen.to_str(o0) 39858 | << "t)" << expr_gen.to_str(o1) 39859 | << "t)" << expr_gen.to_str(o2) 39860 | << "t" 39861 | } 39862 | }; 39863 | 39864 | struct synthesize_vovovoc_expression3 39865 | { 39866 | typedef typename vovovoc_t::type3 node_type; 39867 | typedef typename vovovoc_t::sf4_type sf4_type; 39868 | typedef typename node_type::T0 T0; 39869 | typedef typename node_type::T1 T1; 39870 | typedef typename node_type::T2 T2; 39871 | typedef typename node_type::T3 T3; 39872 | 39873 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39874 | const details::operator_type& operation, 39875 | expression_node_ptr (&branch)[2]) 39876 | { 39877 | // ((v0 o0 v1) o1 v2) o2 c 39878 | typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t; 39879 | 39880 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]); 39881 | const Type& v0 = vovov->t0(); 39882 | const Type& v1 = vovov->t1(); 39883 | const Type& v2 = vovov->t2(); 39884 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 39885 | const details::operator_type o0 = expr_gen.get_operator(vovov->f0()); 39886 | const details::operator_type o1 = expr_gen.get_operator(vovov->f1()); 39887 | const details::operator_type o2 = operation; 39888 | 39889 | binary_functor_t f0 = vovov->f0(); 39890 | binary_functor_t f1 = vovov->f1(); 39891 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 39892 | 39893 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39894 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39895 | 39896 | expression_node_ptr result = error_node(); 39897 | 39898 | const bool synthesis_result = 39899 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39900 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result); 39901 | 39902 | if (synthesis_result) 39903 | return result; 39904 | else if (!expr_gen.valid_operator(o2,f2)) 39905 | return error_node(); 39906 | 39907 | exprtk_debug(("((v0 o0 v1) o1 v2) o2 c\n")); 39908 | 39909 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2); 39910 | } 39911 | 39912 | static inline std::string id(expression_generator<Type>& expr_gen, 39913 | const details::operator_type o0, 39914 | const details::operator_type o1, 39915 | const details::operator_type o2) 39916 | { 39917 | return details::build_string() 39918 | << "((t" << expr_gen.to_str(o0) 39919 | << "t)" << expr_gen.to_str(o1) 39920 | << "t)" << expr_gen.to_str(o2) 39921 | << "t" 39922 | } 39923 | }; 39924 | 39925 | struct synthesize_vovocov_expression3 39926 | { 39927 | typedef typename vovocov_t::type3 node_type; 39928 | typedef typename vovocov_t::sf4_type sf4_type; 39929 | typedef typename node_type::T0 T0; 39930 | typedef typename node_type::T1 T1; 39931 | typedef typename node_type::T2 T2; 39932 | typedef typename node_type::T3 T3; 39933 | 39934 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39935 | const details::operator_type& operation, 39936 | expression_node_ptr (&branch)[2]) 39937 | { 39938 | // ((v0 o0 v1) o1 c) o2 v2 39939 | typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t; 39940 | 39941 | const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[0]); 39942 | const Type& v0 = vovoc->t0(); 39943 | const Type& v1 = vovoc->t1(); 39944 | const Type c = vovoc->t2(); 39945 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 39946 | const details::operator_type o0 = expr_gen.get_operator(vovoc->f0()); 39947 | const details::operator_type o1 = expr_gen.get_operator(vovoc->f1()); 39948 | const details::operator_type o2 = operation; 39949 | 39950 | binary_functor_t f0 = vovoc->f0(); 39951 | binary_functor_t f1 = vovoc->f1(); 39952 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 39953 | 39954 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39955 | 39956 | expression_node_ptr result = error_node(); 39957 | 39958 | const bool synthesis_result = 39959 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39960 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result); 39961 | 39962 | if (synthesis_result) 39963 | return result; 39964 | else if (!expr_gen.valid_operator(o2,f2)) 39965 | return error_node(); 39966 | 39967 | exprtk_debug(("((v0 o0 v1) o1 c) o2 v2\n")); 39968 | 39969 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2); 39970 | } 39971 | 39972 | static inline std::string id(expression_generator<Type>& expr_gen, 39973 | const details::operator_type o0, 39974 | const details::operator_type o1, 39975 | const details::operator_type o2) 39976 | { 39977 | return details::build_string() 39978 | << "((t" << expr_gen.to_str(o0) 39979 | << "t)" << expr_gen.to_str(o1) 39980 | << "t)" << expr_gen.to_str(o2) 39981 | << "t" 39982 | } 39983 | }; 39984 | 39985 | struct synthesize_vocovov_expression3 39986 | { 39987 | typedef typename vocovov_t::type3 node_type; 39988 | typedef typename vocovov_t::sf4_type sf4_type; 39989 | typedef typename node_type::T0 T0; 39990 | typedef typename node_type::T1 T1; 39991 | typedef typename node_type::T2 T2; 39992 | typedef typename node_type::T3 T3; 39993 | 39994 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39995 | const details::operator_type& operation, 39996 | expression_node_ptr (&branch)[2]) 39997 | { 39998 | // ((v0 o0 c) o1 v1) o2 v2 39999 | typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t; 40000 | 40001 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]); 40002 | const Type& v0 = vocov->t0(); 40003 | const Type c = vocov->t1(); 40004 | const Type& v1 = vocov->t2(); 40005 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40006 | const details::operator_type o0 = expr_gen.get_operator(vocov->f0()); 40007 | const details::operator_type o1 = expr_gen.get_operator(vocov->f1()); 40008 | const details::operator_type o2 = operation; 40009 | 40010 | binary_functor_t f0 = vocov->f0(); 40011 | binary_functor_t f1 = vocov->f1(); 40012 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40013 | 40014 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40015 | 40016 | expression_node_ptr result = error_node(); 40017 | 40018 | const bool synthesis_result = 40019 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40020 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result); 40021 | 40022 | if (synthesis_result) 40023 | return result; 40024 | else if (!expr_gen.valid_operator(o2,f2)) 40025 | return error_node(); 40026 | 40027 | exprtk_debug(("((v0 o0 c) o1 v1) o2 v2\n")); 40028 | 40029 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2); 40030 | } 40031 | 40032 | static inline std::string id(expression_generator<Type>& expr_gen, 40033 | const details::operator_type o0, 40034 | const details::operator_type o1, 40035 | const details::operator_type o2) 40036 | { 40037 | return details::build_string() 40038 | << "((t" << expr_gen.to_str(o0) 40039 | << "t)" << expr_gen.to_str(o1) 40040 | << "t)" << expr_gen.to_str(o2) 40041 | << "t" 40042 | } 40043 | }; 40044 | 40045 | struct synthesize_covovov_expression3 40046 | { 40047 | typedef typename covovov_t::type3 node_type; 40048 | typedef typename covovov_t::sf4_type sf4_type; 40049 | typedef typename node_type::T0 T0; 40050 | typedef typename node_type::T1 T1; 40051 | typedef typename node_type::T2 T2; 40052 | typedef typename node_type::T3 T3; 40053 | 40054 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40055 | const details::operator_type& operation, 40056 | expression_node_ptr (&branch)[2]) 40057 | { 40058 | // ((c o0 v0) o1 v1) o2 v2 40059 | typedef typename synthesize_covov_expression0::node_type lcl_covov_t; 40060 | 40061 | const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]); 40062 | const Type c = covov->t0(); 40063 | const Type& v0 = covov->t1(); 40064 | const Type& v1 = covov->t2(); 40065 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40066 | const details::operator_type o0 = expr_gen.get_operator(covov->f0()); 40067 | const details::operator_type o1 = expr_gen.get_operator(covov->f1()); 40068 | const details::operator_type o2 = operation; 40069 | 40070 | binary_functor_t f0 = covov->f0(); 40071 | binary_functor_t f1 = covov->f1(); 40072 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40073 | 40074 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40075 | 40076 | expression_node_ptr result = error_node(); 40077 | 40078 | const bool synthesis_result = 40079 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40080 | (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result); 40081 | 40082 | if (synthesis_result) 40083 | return result; 40084 | else if (!expr_gen.valid_operator(o2,f2)) 40085 | return error_node(); 40086 | 40087 | exprtk_debug(("((c o0 v0) o1 v1) o2 v2\n")); 40088 | 40089 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2); 40090 | } 40091 | 40092 | static inline std::string id(expression_generator<Type>& expr_gen, 40093 | const details::operator_type o0, 40094 | const details::operator_type o1, 40095 | const details::operator_type o2) 40096 | { 40097 | return details::build_string() 40098 | << "((t" << expr_gen.to_str(o0) 40099 | << "t)" << expr_gen.to_str(o1) 40100 | << "t)" << expr_gen.to_str(o2) 40101 | << "t" 40102 | } 40103 | }; 40104 | 40105 | struct synthesize_covocov_expression3 40106 | { 40107 | typedef typename covocov_t::type3 node_type; 40108 | typedef typename covocov_t::sf4_type sf4_type; 40109 | typedef typename node_type::T0 T0; 40110 | typedef typename node_type::T1 T1; 40111 | typedef typename node_type::T2 T2; 40112 | typedef typename node_type::T3 T3; 40113 | 40114 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40115 | const details::operator_type& operation, 40116 | expression_node_ptr (&branch)[2]) 40117 | { 40118 | // ((c0 o0 v0) o1 c1) o2 v1 40119 | typedef typename synthesize_covoc_expression0::node_type lcl_covoc_t; 40120 | 40121 | const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[0]); 40122 | const Type c0 = covoc->t0(); 40123 | const Type& v0 = covoc->t1(); 40124 | const Type c1 = covoc->t2(); 40125 | const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40126 | const details::operator_type o0 = expr_gen.get_operator(covoc->f0()); 40127 | const details::operator_type o1 = expr_gen.get_operator(covoc->f1()); 40128 | const details::operator_type o2 = operation; 40129 | 40130 | binary_functor_t f0 = covoc->f0(); 40131 | binary_functor_t f1 = covoc->f1(); 40132 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40133 | 40134 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40135 | 40136 | expression_node_ptr result = error_node(); 40137 | 40138 | const bool synthesis_result = 40139 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40140 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result); 40141 | 40142 | if (synthesis_result) 40143 | return result; 40144 | else if (!expr_gen.valid_operator(o2,f2)) 40145 | return error_node(); 40146 | 40147 | exprtk_debug(("((c0 o0 v0) o1 c1) o2 v1\n")); 40148 | 40149 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2); 40150 | } 40151 | 40152 | static inline std::string id(expression_generator<Type>& expr_gen, 40153 | const details::operator_type o0, 40154 | const details::operator_type o1, 40155 | const details::operator_type o2) 40156 | { 40157 | return details::build_string() 40158 | << "((t" << expr_gen.to_str(o0) 40159 | << "t)" << expr_gen.to_str(o1) 40160 | << "t)" << expr_gen.to_str(o2) 40161 | << "t" 40162 | } 40163 | }; 40164 | 40165 | struct synthesize_vocovoc_expression3 40166 | { 40167 | typedef typename vocovoc_t::type3 node_type; 40168 | typedef typename vocovoc_t::sf4_type sf4_type; 40169 | typedef typename node_type::T0 T0; 40170 | typedef typename node_type::T1 T1; 40171 | typedef typename node_type::T2 T2; 40172 | typedef typename node_type::T3 T3; 40173 | 40174 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40175 | const details::operator_type& operation, 40176 | expression_node_ptr (&branch)[2]) 40177 | { 40178 | // ((v0 o0 c0) o1 v1) o2 c1 40179 | typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t; 40180 | 40181 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]); 40182 | const Type& v0 = vocov->t0(); 40183 | const Type c0 = vocov->t1(); 40184 | const Type& v1 = vocov->t2(); 40185 | const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); 40186 | const details::operator_type o0 = expr_gen.get_operator(vocov->f0()); 40187 | const details::operator_type o1 = expr_gen.get_operator(vocov->f1()); 40188 | const details::operator_type o2 = operation; 40189 | 40190 | binary_functor_t f0 = vocov->f0(); 40191 | binary_functor_t f1 = vocov->f1(); 40192 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40193 | 40194 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40195 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 40196 | 40197 | expression_node_ptr result = error_node(); 40198 | 40199 | const bool synthesis_result = 40200 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40201 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result); 40202 | 40203 | if (synthesis_result) 40204 | return result; 40205 | else if (!expr_gen.valid_operator(o2,f2)) 40206 | return error_node(); 40207 | 40208 | exprtk_debug(("((v0 o0 c0) o1 v1) o2 c1\n")); 40209 | 40210 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2); 40211 | } 40212 | 40213 | static inline std::string id(expression_generator<Type>& expr_gen, 40214 | const details::operator_type o0, 40215 | const details::operator_type o1, 40216 | const details::operator_type o2) 40217 | { 40218 | return details::build_string() 40219 | << "((t" << expr_gen.to_str(o0) 40220 | << "t)" << expr_gen.to_str(o1) 40221 | << "t)" << expr_gen.to_str(o2) 40222 | << "t" 40223 | } 40224 | }; 40225 | 40226 | struct synthesize_covovoc_expression3 40227 | { 40228 | typedef typename covovoc_t::type3 node_type; 40229 | typedef typename covovoc_t::sf4_type sf4_type; 40230 | typedef typename node_type::T0 T0; 40231 | typedef typename node_type::T1 T1; 40232 | typedef typename node_type::T2 T2; 40233 | typedef typename node_type::T3 T3; 40234 | 40235 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40236 | const details::operator_type& operation, 40237 | expression_node_ptr (&branch)[2]) 40238 | { 40239 | // ((c0 o0 v0) o1 v1) o2 c1 40240 | typedef typename synthesize_covov_expression0::node_type lcl_covov_t; 40241 | 40242 | const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]); 40243 | const Type c0 = covov->t0(); 40244 | const Type& v0 = covov->t1(); 40245 | const Type& v1 = covov->t2(); 40246 | const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); 40247 | const details::operator_type o0 = expr_gen.get_operator(covov->f0()); 40248 | const details::operator_type o1 = expr_gen.get_operator(covov->f1()); 40249 | const details::operator_type o2 = operation; 40250 | 40251 | binary_functor_t f0 = covov->f0(); 40252 | binary_functor_t f1 = covov->f1(); 40253 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40254 | 40255 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40256 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 40257 | 40258 | expression_node_ptr result = error_node(); 40259 | 40260 | const bool synthesis_result = 40261 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40262 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result); 40263 | 40264 | if (synthesis_result) 40265 | return result; 40266 | else if (!expr_gen.valid_operator(o2,f2)) 40267 | return error_node(); 40268 | 40269 | exprtk_debug(("((c0 o0 v0) o1 v1) o2 c1\n")); 40270 | 40271 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2); 40272 | } 40273 | 40274 | static inline std::string id(expression_generator<Type>& expr_gen, 40275 | const details::operator_type o0, 40276 | const details::operator_type o1, 40277 | const details::operator_type o2) 40278 | { 40279 | return details::build_string() 40280 | << "((t" << expr_gen.to_str(o0) 40281 | << "t)" << expr_gen.to_str(o1) 40282 | << "t)" << expr_gen.to_str(o2) 40283 | << "t" 40284 | } 40285 | }; 40286 | 40287 | struct synthesize_vococov_expression3 40288 | { 40289 | typedef typename vococov_t::type3 node_type; 40290 | typedef typename vococov_t::sf4_type sf4_type; 40291 | typedef typename node_type::T0 T0; 40292 | typedef typename node_type::T1 T1; 40293 | typedef typename node_type::T2 T2; 40294 | typedef typename node_type::T3 T3; 40295 | 40296 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40297 | const details::operator_type& operation, 40298 | expression_node_ptr (&branch)[2]) 40299 | { 40300 | // ((v0 o0 c0) o1 c1) o2 v1 40301 | typedef typename synthesize_vococ_expression0::node_type lcl_vococ_t; 40302 | 40303 | const lcl_vococ_t* vococ = static_cast<const lcl_vococ_t*>(branch[0]); 40304 | const Type& v0 = vococ->t0(); 40305 | const Type c0 = vococ->t1(); 40306 | const Type c1 = vococ->t2(); 40307 | const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40308 | const details::operator_type o0 = expr_gen.get_operator(vococ->f0()); 40309 | const details::operator_type o1 = expr_gen.get_operator(vococ->f1()); 40310 | const details::operator_type o2 = operation; 40311 | 40312 | binary_functor_t f0 = vococ->f0(); 40313 | binary_functor_t f1 = vococ->f1(); 40314 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40315 | 40316 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40317 | 40318 | expression_node_ptr result = error_node(); 40319 | 40320 | const bool synthesis_result = 40321 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40322 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result); 40323 | 40324 | if (synthesis_result) 40325 | return result; 40326 | else if (!expr_gen.valid_operator(o2,f2)) 40327 | return error_node(); 40328 | 40329 | exprtk_debug(("((v0 o0 c0) o1 c1) o2 v1\n")); 40330 | 40331 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2); 40332 | } 40333 | 40334 | static inline std::string id(expression_generator<Type>& expr_gen, 40335 | const details::operator_type o0, 40336 | const details::operator_type o1, 40337 | const details::operator_type o2) 40338 | { 40339 | return details::build_string() 40340 | << "((t" << expr_gen.to_str(o0) 40341 | << "t)" << expr_gen.to_str(o1) 40342 | << "t)" << expr_gen.to_str(o2) 40343 | << "t" 40344 | } 40345 | }; 40346 | 40347 | struct synthesize_vovovov_expression4 40348 | { 40349 | typedef typename vovovov_t::type4 node_type; 40350 | typedef typename vovovov_t::sf4_type sf4_type; 40351 | typedef typename node_type::T0 T0; 40352 | typedef typename node_type::T1 T1; 40353 | typedef typename node_type::T2 T2; 40354 | typedef typename node_type::T3 T3; 40355 | 40356 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40357 | const details::operator_type& operation, 40358 | expression_node_ptr (&branch)[2]) 40359 | { 40360 | // (v0 o0 (v1 o1 v2)) o2 v3 40361 | typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t; 40362 | 40363 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]); 40364 | const Type& v0 = vovov->t0(); 40365 | const Type& v1 = vovov->t1(); 40366 | const Type& v2 = vovov->t2(); 40367 | const Type& v3 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40368 | const details::operator_type o0 = expr_gen.get_operator(vovov->f0()); 40369 | const details::operator_type o1 = expr_gen.get_operator(vovov->f1()); 40370 | const details::operator_type o2 = operation; 40371 | 40372 | binary_functor_t f0 = vovov->f0(); 40373 | binary_functor_t f1 = vovov->f1(); 40374 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40375 | 40376 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40377 | 40378 | expression_node_ptr result = error_node(); 40379 | 40380 | const bool synthesis_result = 40381 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40382 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result); 40383 | 40384 | if (synthesis_result) 40385 | return result; 40386 | else if (!expr_gen.valid_operator(o2,f2)) 40387 | return error_node(); 40388 | 40389 | exprtk_debug(("(v0 o0 (v1 o1 v2)) o2 v3\n")); 40390 | 40391 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2); 40392 | } 40393 | 40394 | static inline std::string id(expression_generator<Type>& expr_gen, 40395 | const details::operator_type o0, 40396 | const details::operator_type o1, 40397 | const details::operator_type o2) 40398 | { 40399 | return details::build_string() 40400 | << "(t" << expr_gen.to_str(o0) 40401 | << "(t" << expr_gen.to_str(o1) 40402 | << "t)" << expr_gen.to_str(o2) 40403 | << "t" 40404 | } 40405 | }; 40406 | 40407 | struct synthesize_vovovoc_expression4 40408 | { 40409 | typedef typename vovovoc_t::type4 node_type; 40410 | typedef typename vovovoc_t::sf4_type sf4_type; 40411 | typedef typename node_type::T0 T0; 40412 | typedef typename node_type::T1 T1; 40413 | typedef typename node_type::T2 T2; 40414 | typedef typename node_type::T3 T3; 40415 | 40416 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40417 | const details::operator_type& operation, 40418 | expression_node_ptr (&branch)[2]) 40419 | { 40420 | // ((v0 o0 (v1 o1 v2)) o2 c) 40421 | typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t; 40422 | 40423 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]); 40424 | const Type& v0 = vovov->t0(); 40425 | const Type& v1 = vovov->t1(); 40426 | const Type& v2 = vovov->t2(); 40427 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 40428 | const details::operator_type o0 = expr_gen.get_operator(vovov->f0()); 40429 | const details::operator_type o1 = expr_gen.get_operator(vovov->f1()); 40430 | const details::operator_type o2 = operation; 40431 | 40432 | binary_functor_t f0 = vovov->f0(); 40433 | binary_functor_t f1 = vovov->f1(); 40434 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40435 | 40436 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40437 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 40438 | 40439 | expression_node_ptr result = error_node(); 40440 | 40441 | const bool synthesis_result = 40442 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40443 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result); 40444 | 40445 | if (synthesis_result) 40446 | return result; 40447 | else if (!expr_gen.valid_operator(o2,f2)) 40448 | return error_node(); 40449 | 40450 | exprtk_debug(("((v0 o0 (v1 o1 v2)) o2 c)\n")); 40451 | 40452 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2); 40453 | } 40454 | 40455 | static inline std::string id(expression_generator<Type>& expr_gen, 40456 | const details::operator_type o0, 40457 | const details::operator_type o1, 40458 | const details::operator_type o2) 40459 | { 40460 | return details::build_string() 40461 | << "(t" << expr_gen.to_str(o0) 40462 | << "(t" << expr_gen.to_str(o1) 40463 | << "t)" << expr_gen.to_str(o2) 40464 | << "t" 40465 | } 40466 | }; 40467 | 40468 | struct synthesize_vovocov_expression4 40469 | { 40470 | typedef typename vovocov_t::type4 node_type; 40471 | typedef typename vovocov_t::sf4_type sf4_type; 40472 | typedef typename node_type::T0 T0; 40473 | typedef typename node_type::T1 T1; 40474 | typedef typename node_type::T2 T2; 40475 | typedef typename node_type::T3 T3; 40476 | 40477 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40478 | const details::operator_type& operation, 40479 | expression_node_ptr (&branch)[2]) 40480 | { 40481 | // ((v0 o0 (v1 o1 c)) o2 v1) 40482 | typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t; 40483 | 40484 | const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[0]); 40485 | const Type& v0 = vovoc->t0(); 40486 | const Type& v1 = vovoc->t1(); 40487 | const Type c = vovoc->t2(); 40488 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40489 | const details::operator_type o0 = expr_gen.get_operator(vovoc->f0()); 40490 | const details::operator_type o1 = expr_gen.get_operator(vovoc->f1()); 40491 | const details::operator_type o2 = operation; 40492 | 40493 | binary_functor_t f0 = vovoc->f0(); 40494 | binary_functor_t f1 = vovoc->f1(); 40495 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40496 | 40497 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40498 | 40499 | expression_node_ptr result = error_node(); 40500 | 40501 | const bool synthesis_result = 40502 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40503 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result); 40504 | 40505 | if (synthesis_result) 40506 | return result; 40507 | else if (!expr_gen.valid_operator(o2,f2)) 40508 | return error_node(); 40509 | 40510 | exprtk_debug(("((v0 o0 (v1 o1 c)) o2 v1)\n")); 40511 | 40512 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2); 40513 | } 40514 | 40515 | static inline std::string id(expression_generator<Type>& expr_gen, 40516 | const details::operator_type o0, 40517 | const details::operator_type o1, 40518 | const details::operator_type o2) 40519 | { 40520 | return details::build_string() 40521 | << "(t" << expr_gen.to_str(o0) 40522 | << "(t" << expr_gen.to_str(o1) 40523 | << "t)" << expr_gen.to_str(o2) 40524 | << "t" 40525 | } 40526 | }; 40527 | 40528 | struct synthesize_vocovov_expression4 40529 | { 40530 | typedef typename vocovov_t::type4 node_type; 40531 | typedef typename vocovov_t::sf4_type sf4_type; 40532 | typedef typename node_type::T0 T0; 40533 | typedef typename node_type::T1 T1; 40534 | typedef typename node_type::T2 T2; 40535 | typedef typename node_type::T3 T3; 40536 | 40537 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40538 | const details::operator_type& operation, 40539 | expression_node_ptr (&branch)[2]) 40540 | { 40541 | // ((v0 o0 (c o1 v1)) o2 v2) 40542 | typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t; 40543 | 40544 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]); 40545 | const Type& v0 = vocov->t0(); 40546 | const Type c = vocov->t1(); 40547 | const Type& v1 = vocov->t2(); 40548 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40549 | const details::operator_type o0 = expr_gen.get_operator(vocov->f0()); 40550 | const details::operator_type o1 = expr_gen.get_operator(vocov->f1()); 40551 | const details::operator_type o2 = operation; 40552 | 40553 | binary_functor_t f0 = vocov->f0(); 40554 | binary_functor_t f1 = vocov->f1(); 40555 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40556 | 40557 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40558 | expression_node_ptr result = error_node(); 40559 | 40560 | const bool synthesis_result = 40561 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40562 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result); 40563 | 40564 | if (synthesis_result) 40565 | return result; 40566 | else if (!expr_gen.valid_operator(o2,f2)) 40567 | return error_node(); 40568 | 40569 | exprtk_debug(("((v0 o0 (c o1 v1)) o2 v2)\n")); 40570 | 40571 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2); 40572 | } 40573 | 40574 | static inline std::string id(expression_generator<Type>& expr_gen, 40575 | const details::operator_type o0, 40576 | const details::operator_type o1, 40577 | const details::operator_type o2) 40578 | { 40579 | return details::build_string() 40580 | << "(t" << expr_gen.to_str(o0) 40581 | << "(t" << expr_gen.to_str(o1) 40582 | << "t)" << expr_gen.to_str(o2) 40583 | << "t" 40584 | } 40585 | }; 40586 | 40587 | struct synthesize_covovov_expression4 40588 | { 40589 | typedef typename covovov_t::type4 node_type; 40590 | typedef typename covovov_t::sf4_type sf4_type; 40591 | typedef typename node_type::T0 T0; 40592 | typedef typename node_type::T1 T1; 40593 | typedef typename node_type::T2 T2; 40594 | typedef typename node_type::T3 T3; 40595 | 40596 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40597 | const details::operator_type& operation, 40598 | expression_node_ptr (&branch)[2]) 40599 | { 40600 | // ((c o0 (v0 o1 v1)) o2 v2) 40601 | typedef typename synthesize_covov_expression1::node_type lcl_covov_t; 40602 | 40603 | const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]); 40604 | const Type c = covov->t0(); 40605 | const Type& v0 = covov->t1(); 40606 | const Type& v1 = covov->t2(); 40607 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40608 | const details::operator_type o0 = expr_gen.get_operator(covov->f0()); 40609 | const details::operator_type o1 = expr_gen.get_operator(covov->f1()); 40610 | const details::operator_type o2 = operation; 40611 | 40612 | binary_functor_t f0 = covov->f0(); 40613 | binary_functor_t f1 = covov->f1(); 40614 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40615 | 40616 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40617 | 40618 | expression_node_ptr result = error_node(); 40619 | 40620 | const bool synthesis_result = 40621 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40622 | (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result); 40623 | 40624 | if (synthesis_result) 40625 | return result; 40626 | else if (!expr_gen.valid_operator(o2,f2)) 40627 | return error_node(); 40628 | 40629 | exprtk_debug(("((c o0 (v0 o1 v1)) o2 v2)\n")); 40630 | 40631 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2); 40632 | } 40633 | 40634 | static inline std::string id(expression_generator<Type>& expr_gen, 40635 | const details::operator_type o0, 40636 | const details::operator_type o1, 40637 | const details::operator_type o2) 40638 | { 40639 | return details::build_string() 40640 | << "(t" << expr_gen.to_str(o0) 40641 | << "(t" << expr_gen.to_str(o1) 40642 | << "t)" << expr_gen.to_str(o2) 40643 | << "t" 40644 | } 40645 | }; 40646 | 40647 | struct synthesize_covocov_expression4 40648 | { 40649 | typedef typename covocov_t::type4 node_type; 40650 | typedef typename covocov_t::sf4_type sf4_type; 40651 | typedef typename node_type::T0 T0; 40652 | typedef typename node_type::T1 T1; 40653 | typedef typename node_type::T2 T2; 40654 | typedef typename node_type::T3 T3; 40655 | 40656 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40657 | const details::operator_type& operation, 40658 | expression_node_ptr (&branch)[2]) 40659 | { 40660 | // ((c0 o0 (v0 o1 c1)) o2 v1) 40661 | typedef typename synthesize_covoc_expression1::node_type lcl_covoc_t; 40662 | 40663 | const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[0]); 40664 | const Type c0 = covoc->t0(); 40665 | const Type& v0 = covoc->t1(); 40666 | const Type c1 = covoc->t2(); 40667 | const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40668 | const details::operator_type o0 = expr_gen.get_operator(covoc->f0()); 40669 | const details::operator_type o1 = expr_gen.get_operator(covoc->f1()); 40670 | const details::operator_type o2 = operation; 40671 | 40672 | binary_functor_t f0 = covoc->f0(); 40673 | binary_functor_t f1 = covoc->f1(); 40674 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40675 | 40676 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40677 | 40678 | expression_node_ptr result = error_node(); 40679 | 40680 | const bool synthesis_result = 40681 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40682 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result); 40683 | 40684 | if (synthesis_result) 40685 | return result; 40686 | else if (!expr_gen.valid_operator(o2,f2)) 40687 | return error_node(); 40688 | 40689 | exprtk_debug(("((c0 o0 (v0 o1 c1)) o2 v1)\n")); 40690 | 40691 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2); 40692 | } 40693 | 40694 | static inline std::string id(expression_generator<Type>& expr_gen, 40695 | const details::operator_type o0, 40696 | const details::operator_type o1, 40697 | const details::operator_type o2) 40698 | { 40699 | return details::build_string() 40700 | << "(t" << expr_gen.to_str(o0) 40701 | << "(t" << expr_gen.to_str(o1) 40702 | << "t)" << expr_gen.to_str(o2) 40703 | << "t" 40704 | } 40705 | }; 40706 | 40707 | struct synthesize_vocovoc_expression4 40708 | { 40709 | typedef typename vocovoc_t::type4 node_type; 40710 | typedef typename vocovoc_t::sf4_type sf4_type; 40711 | typedef typename node_type::T0 T0; 40712 | typedef typename node_type::T1 T1; 40713 | typedef typename node_type::T2 T2; 40714 | typedef typename node_type::T3 T3; 40715 | 40716 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40717 | const details::operator_type& operation, 40718 | expression_node_ptr (&branch)[2]) 40719 | { 40720 | // ((v0 o0 (c0 o1 v1)) o2 c1) 40721 | typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t; 40722 | 40723 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]); 40724 | const Type& v0 = vocov->t0(); 40725 | const Type c0 = vocov->t1(); 40726 | const Type& v1 = vocov->t2(); 40727 | const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); 40728 | const details::operator_type o0 = expr_gen.get_operator(vocov->f0()); 40729 | const details::operator_type o1 = expr_gen.get_operator(vocov->f1()); 40730 | const details::operator_type o2 = operation; 40731 | 40732 | binary_functor_t f0 = vocov->f0(); 40733 | binary_functor_t f1 = vocov->f1(); 40734 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40735 | 40736 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40737 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 40738 | 40739 | expression_node_ptr result = error_node(); 40740 | 40741 | const bool synthesis_result = 40742 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40743 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result); 40744 | 40745 | if (synthesis_result) 40746 | return result; 40747 | else if (!expr_gen.valid_operator(o2,f2)) 40748 | return error_node(); 40749 | 40750 | exprtk_debug(("((v0 o0 (c0 o1 v1)) o2 c1)\n")); 40751 | 40752 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2); 40753 | } 40754 | 40755 | static inline std::string id(expression_generator<Type>& expr_gen, 40756 | const details::operator_type o0, 40757 | const details::operator_type o1, 40758 | const details::operator_type o2) 40759 | { 40760 | return details::build_string() 40761 | << "(t" << expr_gen.to_str(o0) 40762 | << "(t" << expr_gen.to_str(o1) 40763 | << "t)" << expr_gen.to_str(o2) 40764 | << "t" 40765 | } 40766 | }; 40767 | 40768 | struct synthesize_covovoc_expression4 40769 | { 40770 | typedef typename covovoc_t::type4 node_type; 40771 | typedef typename covovoc_t::sf4_type sf4_type; 40772 | typedef typename node_type::T0 T0; 40773 | typedef typename node_type::T1 T1; 40774 | typedef typename node_type::T2 T2; 40775 | typedef typename node_type::T3 T3; 40776 | 40777 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40778 | const details::operator_type& operation, 40779 | expression_node_ptr (&branch)[2]) 40780 | { 40781 | // ((c0 o0 (v0 o1 v1)) o2 c1) 40782 | typedef typename synthesize_covov_expression1::node_type lcl_covov_t; 40783 | 40784 | const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]); 40785 | const Type c0 = covov->t0(); 40786 | const Type& v0 = covov->t1(); 40787 | const Type& v1 = covov->t2(); 40788 | const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); 40789 | const details::operator_type o0 = expr_gen.get_operator(covov->f0()); 40790 | const details::operator_type o1 = expr_gen.get_operator(covov->f1()); 40791 | const details::operator_type o2 = operation; 40792 | 40793 | binary_functor_t f0 = covov->f0(); 40794 | binary_functor_t f1 = covov->f1(); 40795 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40796 | 40797 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40798 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 40799 | 40800 | expression_node_ptr result = error_node(); 40801 | 40802 | const bool synthesis_result = 40803 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40804 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result); 40805 | 40806 | if (synthesis_result) 40807 | return result; 40808 | else if (!expr_gen.valid_operator(o2,f2)) 40809 | return error_node(); 40810 | 40811 | exprtk_debug(("((c0 o0 (v0 o1 v1)) o2 c1)\n")); 40812 | 40813 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2); 40814 | } 40815 | 40816 | static inline std::string id(expression_generator<Type>& expr_gen, 40817 | const details::operator_type o0, 40818 | const details::operator_type o1, 40819 | const details::operator_type o2) 40820 | { 40821 | return details::build_string() 40822 | << "(t" << expr_gen.to_str(o0) 40823 | << "(t" << expr_gen.to_str(o1) 40824 | << "t)" << expr_gen.to_str(o2) 40825 | << "t" 40826 | } 40827 | }; 40828 | 40829 | struct synthesize_vococov_expression4 40830 | { 40831 | typedef typename vococov_t::type4 node_type; 40832 | static inline expression_node_ptr process(expression_generator<Type>&, 40833 | const details::operator_type&, 40834 | expression_node_ptr (&)[2]) 40835 | { 40836 | // ((v0 o0 (c0 o1 c1)) o2 v1) - Not possible 40837 | exprtk_debug(("((v0 o0 (c0 o1 c1)) o2 v1) - Not possible\n")); 40838 | return error_node(); 40839 | } 40840 | 40841 | static inline std::string id(expression_generator<Type>&, 40842 | const details::operator_type, 40843 | const details::operator_type, 40844 | const details::operator_type) 40845 | { 40846 | return "INVALID" 40847 | } 40848 | }; 40849 | #endif 40850 | 40851 | inline expression_node_ptr synthesize_uvouv_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2]) 40852 | { 40853 | // Definition: uv o uv 40854 | details::operator_type o0 = static_cast<details::uv_base_node<Type>*>(branch[0])->operation(); 40855 | details::operator_type o1 = static_cast<details::uv_base_node<Type>*>(branch[1])->operation(); 40856 | const Type& v0 = static_cast<details::uv_base_node<Type>*>(branch[0])->v(); 40857 | const Type& v1 = static_cast<details::uv_base_node<Type>*>(branch[1])->v(); 40858 | unary_functor_t u0 = reinterpret_cast<unary_functor_t> (0); 40859 | unary_functor_t u1 = reinterpret_cast<unary_functor_t> (0); 40860 | binary_functor_t f = reinterpret_cast<binary_functor_t>(0); 40861 | 40862 | if (!valid_operator(o0,u0)) 40863 | return error_node(); 40864 | else if (!valid_operator(o1,u1)) 40865 | return error_node(); 40866 | else if (!valid_operator(operation,f)) 40867 | return error_node(); 40868 | 40869 | expression_node_ptr result = error_node(); 40870 | 40871 | if ( 40872 | (details::e_neg == o0) && 40873 | (details::e_neg == o1) 40874 | ) 40875 | { 40876 | switch (operation) 40877 | { 40878 | // (-v0 + -v1) --> -(v0 + v1) 40879 | case details::e_add : result = (*this)(details::e_neg, 40880 | node_allocator_-> 40881 | allocate_rr<typename details:: 40882 | vov_node<Type,details::add_op<Type> > >(v0, v1)); 40883 | exprtk_debug(("(-v0 + -v1) --> -(v0 + v1)\n")); 40884 | break; 40885 | 40886 | // (-v0 - -v1) --> (v1 - v0) 40887 | case details::e_sub : result = node_allocator_-> 40888 | allocate_rr<typename details:: 40889 | vov_node<Type,details::sub_op<Type> > >(v1, v0); 40890 | exprtk_debug(("(-v0 - -v1) --> (v1 - v0)\n")); 40891 | break; 40892 | 40893 | // (-v0 * -v1) --> (v0 * v1) 40894 | case details::e_mul : result = node_allocator_-> 40895 | allocate_rr<typename details:: 40896 | vov_node<Type,details::mul_op<Type> > >(v0, v1); 40897 | exprtk_debug(("(-v0 * -v1) --> (v0 * v1)\n")); 40898 | break; 40899 | 40900 | // (-v0 / -v1) --> (v0 / v1) 40901 | case details::e_div : result = node_allocator_-> 40902 | allocate_rr<typename details:: 40903 | vov_node<Type,details::div_op<Type> > >(v0, v1); 40904 | exprtk_debug(("(-v0 / -v1) --> (v0 / v1)\n")); 40905 | break; 40906 | 40907 | default : break; 40908 | } 40909 | } 40910 | 40911 | if (0 == result) 40912 | { 40913 | result = node_allocator_-> 40914 | allocate_rrrrr<typename details::uvouv_node<Type> >(v0, v1, u0, u1, f); 40915 | } 40916 | 40917 | details::free_all_nodes(*node_allocator_,branch); 40918 | return result; 40919 | } 40920 | 40921 | #undef basic_opr_switch_statements 40922 | #undef extended_opr_switch_statements 40923 | #undef unary_opr_switch_statements 40924 | 40925 | #ifndef exprtk_disable_string_capabilities 40926 | 40927 | #define string_opr_switch_statements \ 40928 | case_stmt(details::e_lt , details::lt_op ) \ 40929 | case_stmt(details::e_lte , details::lte_op ) \ 40930 | case_stmt(details::e_gt , details::gt_op ) \ 40931 | case_stmt(details::e_gte , details::gte_op ) \ 40932 | case_stmt(details::e_eq , details::eq_op ) \ 40933 | case_stmt(details::e_ne , details::ne_op ) \ 40934 | case_stmt(details::e_in , details::in_op ) \ 40935 | case_stmt(details::e_like , details::like_op ) \ 40936 | case_stmt(details::e_ilike , details::ilike_op) \ 40937 | 40938 | template <typename T0, typename T1> 40939 | inline expression_node_ptr synthesize_str_xrox_expression_impl(const details::operator_type& opr, 40940 | T0 s0, T1 s1, 40941 | range_t rp0) 40942 | { 40943 | switch (opr) 40944 | { 40945 | #define case_stmt(op0, op1) \ 40946 | case op0 : return node_allocator_-> \ 40947 | allocate_ttt<typename details::str_xrox_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \ 40948 | (s0, s1, rp0); \ 40949 | 40950 | string_opr_switch_statements 40951 | #undef case_stmt 40952 | default : return error_node(); 40953 | } 40954 | } 40955 | 40956 | template <typename T0, typename T1> 40957 | inline expression_node_ptr synthesize_str_xoxr_expression_impl(const details::operator_type& opr, 40958 | T0 s0, T1 s1, 40959 | range_t rp1) 40960 | { 40961 | switch (opr) 40962 | { 40963 | #define case_stmt(op0, op1) \ 40964 | case op0 : return node_allocator_-> \ 40965 | allocate_ttt<typename details::str_xoxr_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \ 40966 | (s0, s1, rp1); \ 40967 | 40968 | string_opr_switch_statements 40969 | #undef case_stmt 40970 | default : return error_node(); 40971 | } 40972 | } 40973 | 40974 | template <typename T0, typename T1> 40975 | inline expression_node_ptr synthesize_str_xroxr_expression_impl(const details::operator_type& opr, 40976 | T0 s0, T1 s1, 40977 | range_t rp0, range_t rp1) 40978 | { 40979 | switch (opr) 40980 | { 40981 | #define case_stmt(op0, op1) \ 40982 | case op0 : return node_allocator_-> \ 40983 | allocate_tttt<typename details::str_xroxr_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \ 40984 | (s0, s1, rp0, rp1); \ 40985 | 40986 | string_opr_switch_statements 40987 | #undef case_stmt 40988 | default : return error_node(); 40989 | } 40990 | } 40991 | 40992 | template <typename T0, typename T1> 40993 | inline expression_node_ptr synthesize_sos_expression_impl(const details::operator_type& opr, T0 s0, T1 s1) 40994 | { 40995 | switch (opr) 40996 | { 40997 | #define case_stmt(op0, op1) \ 40998 | case op0 : return node_allocator_-> \ 40999 | allocate_tt<typename details::sos_node<Type,T0,T1,op1<Type> >,T0,T1>(s0, s1); \ 41000 | 41001 | string_opr_switch_statements 41002 | #undef case_stmt 41003 | default : return error_node(); 41004 | } 41005 | } 41006 | 41007 | inline expression_node_ptr synthesize_sos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41008 | { 41009 | std::string& s0 = static_cast<details::stringvar_node<Type>*>(branch[0])->ref(); 41010 | std::string& s1 = static_cast<details::stringvar_node<Type>*>(branch[1])->ref(); 41011 | 41012 | return synthesize_sos_expression_impl<std::string&,std::string&>(opr, s0, s1); 41013 | } 41014 | 41015 | inline expression_node_ptr synthesize_sros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41016 | { 41017 | std::string& s0 = static_cast<details::string_range_node<Type>*>(branch[0])->ref (); 41018 | std::string& s1 = static_cast<details::stringvar_node<Type>*> (branch[1])->ref (); 41019 | range_t rp0 = static_cast<details::string_range_node<Type>*>(branch[0])->range(); 41020 | 41021 | static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear(); 41022 | 41023 | details::free_node(*node_allocator_,branch[0]); 41024 | 41025 | return synthesize_str_xrox_expression_impl<std::string&,std::string&>(opr, s0, s1, rp0); 41026 | } 41027 | 41028 | inline expression_node_ptr synthesize_sosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41029 | { 41030 | std::string& s0 = static_cast<details::stringvar_node<Type>*> (branch[0])->ref (); 41031 | std::string& s1 = static_cast<details::string_range_node<Type>*>(branch[1])->ref (); 41032 | range_t rp1 = static_cast<details::string_range_node<Type>*>(branch[1])->range(); 41033 | 41034 | static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear(); 41035 | 41036 | details::free_node(*node_allocator_,branch[1]); 41037 | 41038 | return synthesize_str_xoxr_expression_impl<std::string&,std::string&>(opr, s0, s1, rp1); 41039 | } 41040 | 41041 | inline expression_node_ptr synthesize_socsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41042 | { 41043 | std::string& s0 = static_cast<details::stringvar_node<Type>*> (branch[0])->ref (); 41044 | std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str (); 41045 | range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range(); 41046 | 41047 | static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear(); 41048 | 41049 | details::free_node(*node_allocator_,branch[1]); 41050 | 41051 | return synthesize_str_xoxr_expression_impl<std::string&, const std::string>(opr, s0, s1, rp1); 41052 | } 41053 | 41054 | inline expression_node_ptr synthesize_srosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41055 | { 41056 | std::string& s0 = static_cast<details::string_range_node<Type>*>(branch[0])->ref (); 41057 | std::string& s1 = static_cast<details::string_range_node<Type>*>(branch[1])->ref (); 41058 | range_t rp0 = static_cast<details::string_range_node<Type>*>(branch[0])->range(); 41059 | range_t rp1 = static_cast<details::string_range_node<Type>*>(branch[1])->range(); 41060 | 41061 | static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear(); 41062 | static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear(); 41063 | 41064 | details::free_node(*node_allocator_,branch[0]); 41065 | details::free_node(*node_allocator_,branch[1]); 41066 | 41067 | return synthesize_str_xroxr_expression_impl<std::string&,std::string&>(opr, s0, s1, rp0, rp1); 41068 | } 41069 | 41070 | inline expression_node_ptr synthesize_socs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41071 | { 41072 | std::string& s0 = static_cast< details::stringvar_node<Type>*>(branch[0])->ref(); 41073 | std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str(); 41074 | 41075 | details::free_node(*node_allocator_,branch[1]); 41076 | 41077 | return synthesize_sos_expression_impl<std::string&, const std::string>(opr, s0, s1); 41078 | } 41079 | 41080 | inline expression_node_ptr synthesize_csos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41081 | { 41082 | std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str(); 41083 | std::string& s1 = static_cast<details::stringvar_node<Type>* >(branch[1])->ref(); 41084 | 41085 | details::free_node(*node_allocator_,branch[0]); 41086 | 41087 | return synthesize_sos_expression_impl<const std::string,std::string&>(opr, s0, s1); 41088 | } 41089 | 41090 | inline expression_node_ptr synthesize_csosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41091 | { 41092 | std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str (); 41093 | std::string& s1 = static_cast<details::string_range_node<Type>* >(branch[1])->ref (); 41094 | range_t rp1 = static_cast<details::string_range_node<Type>* >(branch[1])->range(); 41095 | 41096 | static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear(); 41097 | 41098 | details::free_node(*node_allocator_,branch[0]); 41099 | details::free_node(*node_allocator_,branch[1]); 41100 | 41101 | return synthesize_str_xoxr_expression_impl<const std::string,std::string&>(opr, s0, s1, rp1); 41102 | } 41103 | 41104 | inline expression_node_ptr synthesize_srocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41105 | { 41106 | std::string& s0 = static_cast<details::string_range_node<Type>* >(branch[0])->ref (); 41107 | std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str (); 41108 | range_t rp0 = static_cast<details::string_range_node<Type>* >(branch[0])->range(); 41109 | 41110 | static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear(); 41111 | 41112 | details::free_node(*node_allocator_,branch[0]); 41113 | details::free_node(*node_allocator_,branch[1]); 41114 | 41115 | return synthesize_str_xrox_expression_impl<std::string&, const std::string>(opr, s0, s1, rp0); 41116 | } 41117 | 41118 | inline expression_node_ptr synthesize_srocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41119 | { 41120 | std::string& s0 = static_cast<details::string_range_node<Type>* >(branch[0])->ref (); 41121 | std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str (); 41122 | range_t rp0 = static_cast<details::string_range_node<Type>* >(branch[0])->range(); 41123 | range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range(); 41124 | 41125 | static_cast<details::string_range_node<Type>*> (branch[0])->range_ref().clear(); 41126 | static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear(); 41127 | 41128 | details::free_node(*node_allocator_,branch[0]); 41129 | details::free_node(*node_allocator_,branch[1]); 41130 | 41131 | return synthesize_str_xroxr_expression_impl<std::string&, const std::string>(opr, s0, s1, rp0, rp1); 41132 | } 41133 | 41134 | inline expression_node_ptr synthesize_csocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41135 | { 41136 | const std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str(); 41137 | const std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str(); 41138 | 41139 | expression_node_ptr result = error_node(); 41140 | 41141 | if (details::e_add == opr) 41142 | result = node_allocator_->allocate_c<details::string_literal_node<Type> >(s0 + s1); 41143 | else if (details::e_in == opr) 41144 | result = node_allocator_->allocate_c<details::literal_node<Type> >(details::in_op <Type>::process(s0,s1)); 41145 | else if (details::e_like == opr) 41146 | result = node_allocator_->allocate_c<details::literal_node<Type> >(details::like_op <Type>::process(s0,s1)); 41147 | else if (details::e_ilike == opr) 41148 | result = node_allocator_->allocate_c<details::literal_node<Type> >(details::ilike_op<Type>::process(s0,s1)); 41149 | else 41150 | { 41151 | expression_node_ptr temp = synthesize_sos_expression_impl<const std::string, const std::string>(opr, s0, s1); 41152 | 41153 | const Type v = temp->value(); 41154 | 41155 | details::free_node(*node_allocator_,temp); 41156 | 41157 | result = node_allocator_->allocate<literal_node_t>(v); 41158 | } 41159 | 41160 | details::free_all_nodes(*node_allocator_,branch); 41161 | 41162 | return result; 41163 | } 41164 | 41165 | inline expression_node_ptr synthesize_csocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41166 | { 41167 | const std::string s0 = static_cast<details::string_literal_node<Type>* >(branch[0])->str (); 41168 | std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str (); 41169 | range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range(); 41170 | 41171 | static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear(); 41172 | 41173 | details::free_node(*node_allocator_,branch[0]); 41174 | details::free_node(*node_allocator_,branch[1]); 41175 | 41176 | return synthesize_str_xoxr_expression_impl<const std::string, const std::string>(opr, s0, s1, rp1); 41177 | } 41178 | 41179 | inline expression_node_ptr synthesize_csros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41180 | { 41181 | std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str (); 41182 | std::string& s1 = static_cast<details::stringvar_node<Type>* >(branch[1])->ref (); 41183 | range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range(); 41184 | 41185 | static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear(); 41186 | 41187 | details::free_node(*node_allocator_,branch[0]); 41188 | 41189 | return synthesize_str_xrox_expression_impl<const std::string,std::string&>(opr, s0, s1, rp0); 41190 | } 41191 | 41192 | inline expression_node_ptr synthesize_csrosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41193 | { 41194 | const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str (); 41195 | std::string& s1 = static_cast<details::string_range_node<Type>* >(branch[1])->ref (); 41196 | const range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range(); 41197 | const range_t rp1 = static_cast<details::string_range_node<Type>* >(branch[1])->range(); 41198 | 41199 | static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear(); 41200 | static_cast<details::string_range_node<Type>*> (branch[1])->range_ref().clear(); 41201 | 41202 | details::free_node(*node_allocator_,branch[0]); 41203 | details::free_node(*node_allocator_,branch[1]); 41204 | 41205 | return synthesize_str_xroxr_expression_impl<const std::string,std::string&>(opr, s0, s1, rp0, rp1); 41206 | } 41207 | 41208 | inline expression_node_ptr synthesize_csrocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41209 | { 41210 | const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str (); 41211 | const std::string s1 = static_cast<details::string_literal_node<Type>* >(branch[1])->str (); 41212 | const range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range(); 41213 | 41214 | static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear(); 41215 | 41216 | details::free_all_nodes(*node_allocator_,branch); 41217 | 41218 | return synthesize_str_xrox_expression_impl<const std::string,std::string>(opr, s0, s1, rp0); 41219 | } 41220 | 41221 | inline expression_node_ptr synthesize_csrocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41222 | { 41223 | const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str (); 41224 | const std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str (); 41225 | const range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range(); 41226 | const range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range(); 41227 | 41228 | static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear(); 41229 | static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear(); 41230 | 41231 | details::free_all_nodes(*node_allocator_,branch); 41232 | 41233 | return synthesize_str_xroxr_expression_impl<const std::string, const std::string>(opr, s0, s1, rp0, rp1); 41234 | } 41235 | 41236 | inline expression_node_ptr synthesize_strogen_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41237 | { 41238 | switch (opr) 41239 | { 41240 | #define case_stmt(op0, op1) \ 41241 | case op0 : return node_allocator_-> \ 41242 | allocate_ttt<typename details::str_sogens_node<Type,op1<Type> > > \ 41243 | (opr, branch[0], branch[1]); \ 41244 | 41245 | string_opr_switch_statements 41246 | #undef case_stmt 41247 | default : return error_node(); 41248 | } 41249 | } 41250 | 41251 | #undef string_opr_switch_statements 41252 | #endif 41253 | 41254 | #ifndef exprtk_disable_string_capabilities 41255 | inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41256 | { 41257 | if ((0 == branch[0]) || (0 == branch[1])) 41258 | { 41259 | details::free_all_nodes(*node_allocator_,branch); 41260 | 41261 | return error_node(); 41262 | } 41263 | 41264 | const bool b0_is_s = details::is_string_node (branch[0]); 41265 | const bool b0_is_cs = details::is_const_string_node (branch[0]); 41266 | const bool b0_is_sr = details::is_string_range_node (branch[0]); 41267 | const bool b0_is_csr = details::is_const_string_range_node(branch[0]); 41268 | 41269 | const bool b1_is_s = details::is_string_node (branch[1]); 41270 | const bool b1_is_cs = details::is_const_string_node (branch[1]); 41271 | const bool b1_is_sr = details::is_string_range_node (branch[1]); 41272 | const bool b1_is_csr = details::is_const_string_range_node(branch[1]); 41273 | 41274 | const bool b0_is_gen = details::is_string_assignment_node (branch[0]) || 41275 | details::is_genricstring_range_node(branch[0]) || 41276 | details::is_string_concat_node (branch[0]) || 41277 | details::is_string_function_node (branch[0]) || 41278 | details::is_string_condition_node (branch[0]) || 41279 | details::is_string_ccondition_node (branch[0]) || 41280 | details::is_string_vararg_node (branch[0]) ; 41281 | 41282 | const bool b1_is_gen = details::is_string_assignment_node (branch[1]) || 41283 | details::is_genricstring_range_node(branch[1]) || 41284 | details::is_string_concat_node (branch[1]) || 41285 | details::is_string_function_node (branch[1]) || 41286 | details::is_string_condition_node (branch[1]) || 41287 | details::is_string_ccondition_node (branch[1]) || 41288 | details::is_string_vararg_node (branch[1]) ; 41289 | 41290 | if (details::e_add == opr) 41291 | { 41292 | if (!b0_is_cs || !b1_is_cs) 41293 | { 41294 | return synthesize_expression<string_concat_node_t,2>(opr,branch); 41295 | } 41296 | } 41297 | 41298 | if (b0_is_gen || b1_is_gen) 41299 | { 41300 | return synthesize_strogen_expression(opr,branch); 41301 | } 41302 | else if (b0_is_s) 41303 | { 41304 | if (b1_is_s ) return synthesize_sos_expression (opr,branch); 41305 | else if (b1_is_cs ) return synthesize_socs_expression (opr,branch); 41306 | else if (b1_is_sr ) return synthesize_sosr_expression (opr,branch); 41307 | else if (b1_is_csr) return synthesize_socsr_expression (opr,branch); 41308 | } 41309 | else if (b0_is_cs) 41310 | { 41311 | if (b1_is_s ) return synthesize_csos_expression (opr,branch); 41312 | else if (b1_is_cs ) return synthesize_csocs_expression (opr,branch); 41313 | else if (b1_is_sr ) return synthesize_csosr_expression (opr,branch); 41314 | else if (b1_is_csr) return synthesize_csocsr_expression(opr,branch); 41315 | } 41316 | else if (b0_is_sr) 41317 | { 41318 | if (b1_is_s ) return synthesize_sros_expression (opr,branch); 41319 | else if (b1_is_sr ) return synthesize_srosr_expression (opr,branch); 41320 | else if (b1_is_cs ) return synthesize_srocs_expression (opr,branch); 41321 | else if (b1_is_csr) return synthesize_srocsr_expression(opr,branch); 41322 | } 41323 | else if (b0_is_csr) 41324 | { 41325 | if (b1_is_s ) return synthesize_csros_expression (opr,branch); 41326 | else if (b1_is_sr ) return synthesize_csrosr_expression (opr,branch); 41327 | else if (b1_is_cs ) return synthesize_csrocs_expression (opr,branch); 41328 | else if (b1_is_csr) return synthesize_csrocsr_expression(opr,branch); 41329 | } 41330 | 41331 | return error_node(); 41332 | } 41333 | #else 41334 | inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&branch)[2]) 41335 | { 41336 | details::free_all_nodes(*node_allocator_,branch); 41337 | return error_node(); 41338 | } 41339 | #endif 41340 | 41341 | #ifndef exprtk_disable_string_capabilities 41342 | inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[3]) 41343 | { 41344 | if (details::e_inrange != opr) 41345 | return error_node(); 41346 | else if ((0 == branch[0]) || (0 == branch[1]) || (0 == branch[2])) 41347 | { 41348 | details::free_all_nodes(*node_allocator_,branch); 41349 | 41350 | return error_node(); 41351 | } 41352 | else if ( 41353 | details::is_const_string_node(branch[0]) && 41354 | details::is_const_string_node(branch[1]) && 41355 | details::is_const_string_node(branch[2]) 41356 | ) 41357 | { 41358 | const std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str(); 41359 | const std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str(); 41360 | const std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str(); 41361 | 41362 | const Type v = (((s0 <= s1) && (s1 <= s2)) ? Type(1) : Type(0)); 41363 | 41364 | details::free_all_nodes(*node_allocator_,branch); 41365 | 41366 | return node_allocator_->allocate_c<details::literal_node<Type> >(v); 41367 | } 41368 | else if ( 41369 | details::is_string_node(branch[0]) && 41370 | details::is_string_node(branch[1]) && 41371 | details::is_string_node(branch[2]) 41372 | ) 41373 | { 41374 | std::string& s0 = static_cast<details::stringvar_node<Type>*>(branch[0])->ref(); 41375 | std::string& s1 = static_cast<details::stringvar_node<Type>*>(branch[1])->ref(); 41376 | std::string& s2 = static_cast<details::stringvar_node<Type>*>(branch[2])->ref(); 41377 | 41378 | typedef typename details::sosos_node<Type, std::string&, std::string&, std::string&, details::inrange_op<Type> > inrange_t; 41379 | 41380 | return node_allocator_->allocate_type<inrange_t, std::string&, std::string&, std::string&>(s0, s1, s2); 41381 | } 41382 | else if ( 41383 | details::is_const_string_node(branch[0]) && 41384 | details::is_string_node(branch[1]) && 41385 | details::is_const_string_node(branch[2]) 41386 | ) 41387 | { 41388 | std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str(); 41389 | std::string& s1 = static_cast<details::stringvar_node<Type>* >(branch[1])->ref(); 41390 | std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str(); 41391 | 41392 | typedef typename details::sosos_node<Type, std::string, std::string&, std::string, details::inrange_op<Type> > inrange_t; 41393 | 41394 | details::free_node(*node_allocator_,branch[0]); 41395 | details::free_node(*node_allocator_,branch[2]); 41396 | 41397 | return node_allocator_->allocate_type<inrange_t, std::string, std::string&, std::string>(s0, s1, s2); 41398 | } 41399 | else if ( 41400 | details::is_string_node(branch[0]) && 41401 | details::is_const_string_node(branch[1]) && 41402 | details::is_string_node(branch[2]) 41403 | ) 41404 | { 41405 | std::string& s0 = static_cast<details::stringvar_node<Type>* >(branch[0])->ref(); 41406 | std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str(); 41407 | std::string& s2 = static_cast<details::stringvar_node<Type>* >(branch[2])->ref(); 41408 | 41409 | typedef typename details::sosos_node<Type, std::string&, std::string, std::string&, details::inrange_op<Type> > inrange_t; 41410 | 41411 | details::free_node(*node_allocator_,branch[1]); 41412 | 41413 | return node_allocator_->allocate_type<inrange_t, std::string&, std::string, std::string&>(s0, s1, s2); 41414 | } 41415 | else if ( 41416 | details::is_string_node(branch[0]) && 41417 | details::is_string_node(branch[1]) && 41418 | details::is_const_string_node(branch[2]) 41419 | ) 41420 | { 41421 | std::string& s0 = static_cast<details::stringvar_node<Type>* >(branch[0])->ref(); 41422 | std::string& s1 = static_cast<details::stringvar_node<Type>* >(branch[1])->ref(); 41423 | std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str(); 41424 | 41425 | typedef typename details::sosos_node<Type, std::string&, std::string&, std::string, details::inrange_op<Type> > inrange_t; 41426 | 41427 | details::free_node(*node_allocator_,branch[2]); 41428 | 41429 | return node_allocator_->allocate_type<inrange_t, std::string&, std::string&, std::string>(s0, s1, s2); 41430 | } 41431 | else if ( 41432 | details::is_const_string_node(branch[0]) && 41433 | details:: is_string_node(branch[1]) && 41434 | details:: is_string_node(branch[2]) 41435 | ) 41436 | { 41437 | std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str(); 41438 | std::string& s1 = static_cast<details::stringvar_node<Type>* >(branch[1])->ref(); 41439 | std::string& s2 = static_cast<details::stringvar_node<Type>* >(branch[2])->ref(); 41440 | 41441 | typedef typename details::sosos_node<Type, std::string, std::string&, std::string&, details::inrange_op<Type> > inrange_t; 41442 | 41443 | details::free_node(*node_allocator_,branch[0]); 41444 | 41445 | return node_allocator_->allocate_type<inrange_t, std::string, std::string&, std::string&>(s0, s1, s2); 41446 | } 41447 | else 41448 | return error_node(); 41449 | } 41450 | #else 41451 | inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&branch)[3]) 41452 | { 41453 | details::free_all_nodes(*node_allocator_,branch); 41454 | return error_node(); 41455 | } 41456 | #endif 41457 | 41458 | inline expression_node_ptr synthesize_null_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2]) 41459 | { 41460 | /* 41461 | Note: The following are the type promotion rules 41462 | that relate to operations that include 'null': 41463 | 0. null ==/!= null --> true false 41464 | 1. null operation null --> null 41465 | 2. x ==/!= null --> true/false 41466 | 3. null ==/!= x --> true/false 41467 | 4. x operation null --> x 41468 | 5. null operation x --> x 41469 | */ 41470 | 41471 | typedef typename details::null_eq_node<T> nulleq_node_t; 41472 | 41473 | const bool b0_null = details::is_null_node(branch[0]); 41474 | const bool b1_null = details::is_null_node(branch[1]); 41475 | 41476 | if (b0_null && b1_null) 41477 | { 41478 | expression_node_ptr result = error_node(); 41479 | 41480 | if (details::e_eq == operation) 41481 | result = node_allocator_->allocate_c<literal_node_t>(T(1)); 41482 | else if (details::e_ne == operation) 41483 | result = node_allocator_->allocate_c<literal_node_t>(T(0)); 41484 | 41485 | if (result) 41486 | { 41487 | details::free_node(*node_allocator_,branch[0]); 41488 | details::free_node(*node_allocator_,branch[1]); 41489 | 41490 | return result; 41491 | } 41492 | 41493 | details::free_node(*node_allocator_,branch[1]); 41494 | 41495 | return branch[0]; 41496 | } 41497 | else if (details::e_eq == operation) 41498 | { 41499 | expression_node_ptr result = node_allocator_-> 41500 | allocate_rc<nulleq_node_t>(branch[b0_null ? 0 : 1],true); 41501 | 41502 | details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]); 41503 | 41504 | return result; 41505 | } 41506 | else if (details::e_ne == operation) 41507 | { 41508 | expression_node_ptr result = node_allocator_-> 41509 | allocate_rc<nulleq_node_t>(branch[b0_null ? 0 : 1],false); 41510 | 41511 | details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]); 41512 | 41513 | return result; 41514 | } 41515 | else if (b0_null) 41516 | { 41517 | details::free_node(*node_allocator_,branch[0]); 41518 | branch[0] = branch[1]; 41519 | branch[1] = error_node(); 41520 | } 41521 | else if (b1_null) 41522 | { 41523 | details::free_node(*node_allocator_,branch[1]); 41524 | branch[1] = error_node(); 41525 | } 41526 | 41527 | if ( 41528 | (details::e_add == operation) || (details::e_sub == operation) || 41529 | (details::e_mul == operation) || (details::e_div == operation) || 41530 | (details::e_mod == operation) || (details::e_pow == operation) 41531 | ) 41532 | { 41533 | return branch[0]; 41534 | } 41535 | 41536 | details::free_node(*node_allocator_, branch[0]); 41537 | 41538 | if ( 41539 | (details::e_lt == operation) || (details::e_lte == operation) || 41540 | (details::e_gt == operation) || (details::e_gte == operation) || 41541 | (details::e_and == operation) || (details::e_nand == operation) || 41542 | (details::e_or == operation) || (details::e_nor == operation) || 41543 | (details::e_xor == operation) || (details::e_xnor == operation) || 41544 | (details::e_in == operation) || (details::e_like == operation) || 41545 | (details::e_ilike == operation) 41546 | ) 41547 | { 41548 | return node_allocator_->allocate_c<literal_node_t>(T(0)); 41549 | } 41550 | 41551 | return node_allocator_->allocate<details::null_node<Type> >(); 41552 | } 41553 | 41554 | template <typename NodeType, std::size_t N> 41555 | inline expression_node_ptr synthesize_expression(const details::operator_type& operation, expression_node_ptr (&branch)[N]) 41556 | { 41557 | if ( 41558 | (details::e_in == operation) || 41559 | (details::e_like == operation) || 41560 | (details::e_ilike == operation) 41561 | ) 41562 | { 41563 | free_all_nodes(*node_allocator_,branch); 41564 | 41565 | return error_node(); 41566 | } 41567 | else if (!details::all_nodes_valid<N>(branch)) 41568 | { 41569 | free_all_nodes(*node_allocator_,branch); 41570 | 41571 | return error_node(); 41572 | } 41573 | else if ((details::e_default != operation)) 41574 | { 41575 | // Attempt simple constant folding optimisation. 41576 | expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(operation,branch); 41577 | 41578 | if (is_constant_foldable<N>(branch)) 41579 | { 41580 | const Type v = expression_point->value(); 41581 | details::free_node(*node_allocator_,expression_point); 41582 | 41583 | return node_allocator_->allocate<literal_node_t>(v); 41584 | } 41585 | 41586 | if (expression_point && expression_point->valid()) 41587 | { 41588 | return expression_point; 41589 | } 41590 | 41591 | parser_->set_error(parser_error::make_error( 41592 | parser_error::e_parser, 41593 | token_t(), 41594 | "ERR281 - Failed to synthesize node: NodeType", 41595 | exprtk_error_location)); 41596 | 41597 | details::free_node(*node_allocator_, expression_point); 41598 | } 41599 | 41600 | return error_node(); 41601 | } 41602 | 41603 | template <typename NodeType, std::size_t N> 41604 | inline expression_node_ptr synthesize_expression(F* f, expression_node_ptr (&branch)[N]) 41605 | { 41606 | if (!details::all_nodes_valid<N>(branch)) 41607 | { 41608 | free_all_nodes(*node_allocator_,branch); 41609 | 41610 | return error_node(); 41611 | } 41612 | 41613 | typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t; 41614 | 41615 | // Attempt simple constant folding optimisation. 41616 | 41617 | expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(f); 41618 | function_N_node_t* func_node_ptr = dynamic_cast<function_N_node_t*>(expression_point); 41619 | 41620 | if (0 == func_node_ptr) 41621 | { 41622 | free_all_nodes(*node_allocator_,branch); 41623 | 41624 | return error_node(); 41625 | } 41626 | else 41627 | func_node_ptr->init_branches(branch); 41628 | 41629 | if (is_constant_foldable<N>(branch) && !f->has_side_effects()) 41630 | { 41631 | Type v = expression_point->value(); 41632 | details::free_node(*node_allocator_,expression_point); 41633 | 41634 | return node_allocator_->allocate<literal_node_t>(v); 41635 | } 41636 | 41637 | parser_->state_.activate_side_effect("synthesize_expression(function<NT,N>)"); 41638 | 41639 | return expression_point; 41640 | } 41641 | 41642 | bool strength_reduction_enabled_; 41643 | details::node_allocator* node_allocator_; 41644 | synthesize_map_t synthesize_map_; 41645 | unary_op_map_t* unary_op_map_; 41646 | binary_op_map_t* binary_op_map_; 41647 | inv_binary_op_map_t* inv_binary_op_map_; 41648 | sf3_map_t* sf3_map_; 41649 | sf4_map_t* sf4_map_; 41650 | parser_t* parser_; 41651 | }; // class expression_generator 41652 | 41653 | inline void set_error(const parser_error::type& error_type) 41654 | { 41655 | error_list_.push_back(error_type); 41656 | } 41657 | 41658 | inline void remove_last_error() 41659 | { 41660 | if (!error_list_.empty()) 41661 | { 41662 | error_list_.pop_back(); 41663 | } 41664 | } 41665 | 41666 | inline void set_synthesis_error(const std::string& synthesis_error_message) 41667 | { 41668 | if (synthesis_error_.empty()) 41669 | { 41670 | synthesis_error_ = synthesis_error_message; 41671 | } 41672 | } 41673 | 41674 | inline void register_local_vars(expression<T>& e) 41675 | { 41676 | for (std::size_t i = 0; i < sem_.size(); ++i) 41677 | { 41678 | scope_element& se = sem_.get_element(i); 41679 | 41680 | exprtk_debug(("register_local_vars() - se[%s]\n", se.name.c_str())); 41681 | 41682 | if ( 41683 | (scope_element::e_variable == se.type) || 41684 | (scope_element::e_literal == se.type) || 41685 | (scope_element::e_vecelem == se.type) 41686 | ) 41687 | { 41688 | if (se.var_node) 41689 | { 41690 | e.register_local_var(se.var_node); 41691 | } 41692 | 41693 | if (se.data) 41694 | { 41695 | e.register_local_data(se.data, 1, 0); 41696 | } 41697 | } 41698 | else if (scope_element::e_vector == se.type) 41699 | { 41700 | if (se.vec_node) 41701 | { 41702 | e.register_local_var(se.vec_node); 41703 | } 41704 | 41705 | if (se.data) 41706 | { 41707 | e.register_local_data(se.data, se.size, 1); 41708 | } 41709 | } 41710 | #ifndef exprtk_disable_string_capabilities 41711 | else if (scope_element::e_string == se.type) 41712 | { 41713 | if (se.str_node) 41714 | { 41715 | e.register_local_var(se.str_node); 41716 | } 41717 | 41718 | if (se.data) 41719 | { 41720 | e.register_local_data(se.data, se.size, 2); 41721 | } 41722 | } 41723 | #endif 41724 | 41725 | se.var_node = 0; 41726 | se.vec_node = 0; 41727 | #ifndef exprtk_disable_string_capabilities 41728 | se.str_node = 0; 41729 | #endif 41730 | se.data = 0; 41731 | se.ref_count = 0; 41732 | se.active = false; 41733 | } 41734 | } 41735 | 41736 | inline void register_return_results(expression<T>& e) 41737 | { 41738 | e.register_return_results(results_context_); 41739 | results_context_ = 0; 41740 | } 41741 | 41742 | inline void load_unary_operations_map(unary_op_map_t& m) 41743 | { 41744 | #define register_unary_op(Op, UnaryFunctor) \ 41745 | m.insert(std::make_pair(Op,UnaryFunctor<T>::process)); \ 41746 | 41747 | register_unary_op(details::e_abs , details::abs_op ) 41748 | register_unary_op(details::e_acos , details::acos_op ) 41749 | register_unary_op(details::e_acosh , details::acosh_op) 41750 | register_unary_op(details::e_asin , details::asin_op ) 41751 | register_unary_op(details::e_asinh , details::asinh_op) 41752 | register_unary_op(details::e_atanh , details::atanh_op) 41753 | register_unary_op(details::e_ceil , details::ceil_op ) 41754 | register_unary_op(details::e_cos , details::cos_op ) 41755 | register_unary_op(details::e_cosh , details::cosh_op ) 41756 | register_unary_op(details::e_exp , details::exp_op ) 41757 | register_unary_op(details::e_expm1 , details::expm1_op) 41758 | register_unary_op(details::e_floor , details::floor_op) 41759 | register_unary_op(details::e_log , details::log_op ) 41760 | register_unary_op(details::e_log10 , details::log10_op) 41761 | register_unary_op(details::e_log2 , details::log2_op ) 41762 | register_unary_op(details::e_log1p , details::log1p_op) 41763 | register_unary_op(details::e_neg , details::neg_op ) 41764 | register_unary_op(details::e_pos , details::pos_op ) 41765 | register_unary_op(details::e_round , details::round_op) 41766 | register_unary_op(details::e_sin , details::sin_op ) 41767 | register_unary_op(details::e_sinc , details::sinc_op ) 41768 | register_unary_op(details::e_sinh , details::sinh_op ) 41769 | register_unary_op(details::e_sqrt , details::sqrt_op ) 41770 | register_unary_op(details::e_tan , details::tan_op ) 41771 | register_unary_op(details::e_tanh , details::tanh_op ) 41772 | register_unary_op(details::e_cot , details::cot_op ) 41773 | register_unary_op(details::e_sec , details::sec_op ) 41774 | register_unary_op(details::e_csc , details::csc_op ) 41775 | register_unary_op(details::e_r2d , details::r2d_op ) 41776 | register_unary_op(details::e_d2r , details::d2r_op ) 41777 | register_unary_op(details::e_d2g , details::d2g_op ) 41778 | register_unary_op(details::e_g2d , details::g2d_op ) 41779 | register_unary_op(details::e_notl , details::notl_op ) 41780 | register_unary_op(details::e_sgn , details::sgn_op ) 41781 | register_unary_op(details::e_erf , details::erf_op ) 41782 | register_unary_op(details::e_erfc , details::erfc_op ) 41783 | register_unary_op(details::e_ncdf , details::ncdf_op ) 41784 | register_unary_op(details::e_frac , details::frac_op ) 41785 | register_unary_op(details::e_trunc , details::trunc_op) 41786 | #undef register_unary_op 41787 | } 41788 | 41789 | inline void load_binary_operations_map(binary_op_map_t& m) 41790 | { 41791 | typedef typename binary_op_map_t::value_type value_type; 41792 | 41793 | #define register_binary_op(Op, BinaryFunctor) \ 41794 | m.insert(value_type(Op,BinaryFunctor<T>::process)); \ 41795 | 41796 | register_binary_op(details::e_add , details::add_op ) 41797 | register_binary_op(details::e_sub , details::sub_op ) 41798 | register_binary_op(details::e_mul , details::mul_op ) 41799 | register_binary_op(details::e_div , details::div_op ) 41800 | register_binary_op(details::e_mod , details::mod_op ) 41801 | register_binary_op(details::e_pow , details::pow_op ) 41802 | register_binary_op(details::e_lt , details::lt_op ) 41803 | register_binary_op(details::e_lte , details::lte_op ) 41804 | register_binary_op(details::e_gt , details::gt_op ) 41805 | register_binary_op(details::e_gte , details::gte_op ) 41806 | register_binary_op(details::e_eq , details::eq_op ) 41807 | register_binary_op(details::e_ne , details::ne_op ) 41808 | register_binary_op(details::e_and , details::and_op ) 41809 | register_binary_op(details::e_nand , details::nand_op) 41810 | register_binary_op(details::e_or , details::or_op ) 41811 | register_binary_op(details::e_nor , details::nor_op ) 41812 | register_binary_op(details::e_xor , details::xor_op ) 41813 | register_binary_op(details::e_xnor , details::xnor_op) 41814 | #undef register_binary_op 41815 | } 41816 | 41817 | inline void load_inv_binary_operations_map(inv_binary_op_map_t& m) 41818 | { 41819 | typedef typename inv_binary_op_map_t::value_type value_type; 41820 | 41821 | #define register_binary_op(Op, BinaryFunctor) \ 41822 | m.insert(value_type(BinaryFunctor<T>::process,Op)); \ 41823 | 41824 | register_binary_op(details::e_add , details::add_op ) 41825 | register_binary_op(details::e_sub , details::sub_op ) 41826 | register_binary_op(details::e_mul , details::mul_op ) 41827 | register_binary_op(details::e_div , details::div_op ) 41828 | register_binary_op(details::e_mod , details::mod_op ) 41829 | register_binary_op(details::e_pow , details::pow_op ) 41830 | register_binary_op(details::e_lt , details::lt_op ) 41831 | register_binary_op(details::e_lte , details::lte_op ) 41832 | register_binary_op(details::e_gt , details::gt_op ) 41833 | register_binary_op(details::e_gte , details::gte_op ) 41834 | register_binary_op(details::e_eq , details::eq_op ) 41835 | register_binary_op(details::e_ne , details::ne_op ) 41836 | register_binary_op(details::e_and , details::and_op ) 41837 | register_binary_op(details::e_nand , details::nand_op) 41838 | register_binary_op(details::e_or , details::or_op ) 41839 | register_binary_op(details::e_nor , details::nor_op ) 41840 | register_binary_op(details::e_xor , details::xor_op ) 41841 | register_binary_op(details::e_xnor , details::xnor_op) 41842 | #undef register_binary_op 41843 | } 41844 | 41845 | inline void load_sf3_map(sf3_map_t& sf3_map) 41846 | { 41847 | typedef std::pair<trinary_functor_t,details::operator_type> pair_t; 41848 | 41849 | #define register_sf3(Op) \ 41850 | sf3_map[details::sf##Op##_op<T>::id()] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \ 41851 | 41852 | register_sf3(00) register_sf3(01) register_sf3(02) register_sf3(03) 41853 | register_sf3(04) register_sf3(05) register_sf3(06) register_sf3(07) 41854 | register_sf3(08) register_sf3(09) register_sf3(10) register_sf3(11) 41855 | register_sf3(12) register_sf3(13) register_sf3(14) register_sf3(15) 41856 | register_sf3(16) register_sf3(17) register_sf3(18) register_sf3(19) 41857 | register_sf3(20) register_sf3(21) register_sf3(22) register_sf3(23) 41858 | register_sf3(24) register_sf3(25) register_sf3(26) register_sf3(27) 41859 | register_sf3(28) register_sf3(29) register_sf3(30) 41860 | #undef register_sf3 41861 | 41862 | #define register_sf3_extid(Id, Op) \ 41863 | sf3_map[Id] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \ 41864 | 41865 | register_sf3_extid("(t-t)-t",23) // (t-t)-t --> t-(t+t) 41866 | #undef register_sf3_extid 41867 | } 41868 | 41869 | inline void load_sf4_map(sf4_map_t& sf4_map) 41870 | { 41871 | typedef std::pair<quaternary_functor_t,details::operator_type> pair_t; 41872 | 41873 | #define register_sf4(Op) \ 41874 | sf4_map[details::sf##Op##_op<T>::id()] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \ 41875 | 41876 | register_sf4(48) register_sf4(49) register_sf4(50) register_sf4(51) 41877 | register_sf4(52) register_sf4(53) register_sf4(54) register_sf4(55) 41878 | register_sf4(56) register_sf4(57) register_sf4(58) register_sf4(59) 41879 | register_sf4(60) register_sf4(61) register_sf4(62) register_sf4(63) 41880 | register_sf4(64) register_sf4(65) register_sf4(66) register_sf4(67) 41881 | register_sf4(68) register_sf4(69) register_sf4(70) register_sf4(71) 41882 | register_sf4(72) register_sf4(73) register_sf4(74) register_sf4(75) 41883 | register_sf4(76) register_sf4(77) register_sf4(78) register_sf4(79) 41884 | register_sf4(80) register_sf4(81) register_sf4(82) register_sf4(83) 41885 | #undef register_sf4 41886 | 41887 | #define register_sf4ext(Op) \ 41888 | sf4_map[details::sfext##Op##_op<T>::id()] = pair_t(details::sfext##Op##_op<T>::process,details::e_sf4ext##Op); \ 41889 | 41890 | register_sf4ext(00) register_sf4ext(01) register_sf4ext(02) register_sf4ext(03) 41891 | register_sf4ext(04) register_sf4ext(05) register_sf4ext(06) register_sf4ext(07) 41892 | register_sf4ext(08) register_sf4ext(09) register_sf4ext(10) register_sf4ext(11) 41893 | register_sf4ext(12) register_sf4ext(13) register_sf4ext(14) register_sf4ext(15) 41894 | register_sf4ext(16) register_sf4ext(17) register_sf4ext(18) register_sf4ext(19) 41895 | register_sf4ext(20) register_sf4ext(21) register_sf4ext(22) register_sf4ext(23) 41896 | register_sf4ext(24) register_sf4ext(25) register_sf4ext(26) register_sf4ext(27) 41897 | register_sf4ext(28) register_sf4ext(29) register_sf4ext(30) register_sf4ext(31) 41898 | register_sf4ext(32) register_sf4ext(33) register_sf4ext(34) register_sf4ext(35) 41899 | register_sf4ext(36) register_sf4ext(36) register_sf4ext(38) register_sf4ext(39) 41900 | register_sf4ext(40) register_sf4ext(41) register_sf4ext(42) register_sf4ext(43) 41901 | register_sf4ext(44) register_sf4ext(45) register_sf4ext(46) register_sf4ext(47) 41902 | register_sf4ext(48) register_sf4ext(49) register_sf4ext(50) register_sf4ext(51) 41903 | register_sf4ext(52) register_sf4ext(53) register_sf4ext(54) register_sf4ext(55) 41904 | register_sf4ext(56) register_sf4ext(57) register_sf4ext(58) register_sf4ext(59) 41905 | register_sf4ext(60) register_sf4ext(61) 41906 | #undef register_sf4ext 41907 | } 41908 | 41909 | inline results_context_t& results_ctx() 41910 | { 41911 | if (0 == results_context_) 41912 | { 41913 | results_context_ = new results_context_t(); 41914 | } 41915 | 41916 | return (*results_context_); 41917 | } 41918 | 41919 | inline void return_cleanup() 41920 | { 41921 | #ifndef exprtk_disable_return_statement 41922 | if (results_context_) 41923 | { 41924 | delete results_context_; 41925 | results_context_ = 0; 41926 | } 41927 | 41928 | state_.return_stmt_present = false; 41929 | #endif 41930 | } 41931 | 41932 | inline bool valid_settings() 41933 | { 41934 | const std::size_t max_local_vector_size_bytes = sizeof(T) * settings_.max_local_vector_size(); 41935 | 41936 | if (max_local_vector_size_bytes > settings_.max_total_local_symbol_size_bytes()) 41937 | { 41938 | set_error(make_error( 41939 | parser_error::e_parser, 41940 | "ERR282 - Max local vector size of " + details::to_str(max_local_vector_size_bytes) + " bytes " 41941 | "is larger than max total local symbol size of " + details::to_str(settings_.max_total_local_symbol_size_bytes()) + " bytes", 41942 | exprtk_error_location)); 41943 | 41944 | return false; 41945 | } 41946 | 41947 | return true; 41948 | } 41949 | 41950 | private: 41951 | 41952 | parser(const parser<T>&) exprtk_delete; 41953 | parser<T>& operator=(const parser<T>&) exprtk_delete; 41954 | 41955 | settings_store settings_; 41956 | expression_generator<T> expression_generator_; 41957 | details::node_allocator node_allocator_; 41958 | symtab_store symtab_store_; 41959 | dependent_entity_collector dec_; 41960 | std::deque<parser_error::type> error_list_; 41961 | std::deque<bool> brkcnt_list_; 41962 | parser_state state_; 41963 | bool resolve_unknown_symbol_; 41964 | results_context_t* results_context_; 41965 | unknown_symbol_resolver* unknown_symbol_resolver_; 41966 | unknown_symbol_resolver default_usr_; 41967 | base_ops_map_t base_ops_map_; 41968 | unary_op_map_t unary_op_map_; 41969 | binary_op_map_t binary_op_map_; 41970 | inv_binary_op_map_t inv_binary_op_map_; 41971 | sf3_map_t sf3_map_; 41972 | sf4_map_t sf4_map_; 41973 | std::string synthesis_error_; 41974 | scope_element_manager sem_; 41975 | std::vector<state_t> current_state_stack_; 41976 | 41977 | immutable_memory_map_t immutable_memory_map_; 41978 | immutable_symtok_map_t immutable_symtok_map_; 41979 | 41980 | lexer::helper::helper_assembly helper_assembly_; 41981 | 41982 | lexer::helper::commutative_inserter commutative_inserter_; 41983 | lexer::helper::operator_joiner operator_joiner_2_; 41984 | lexer::helper::operator_joiner operator_joiner_3_; 41985 | lexer::helper::symbol_replacer symbol_replacer_; 41986 | lexer::helper::bracket_checker bracket_checker_; 41987 | lexer::helper::numeric_checker<T> numeric_checker_; 41988 | lexer::helper::sequence_validator sequence_validator_; 41989 | lexer::helper::sequence_validator_3tokens sequence_validator_3tkns_; 41990 | 41991 | loop_runtime_check_ptr loop_runtime_check_; 41992 | vector_access_runtime_check_ptr vector_access_runtime_check_; 41993 | compilation_check_ptr compilation_check_ptr_; 41994 | assert_check_ptr assert_check_; 41995 | std::set<std::string> assert_ids_; 41996 | 41997 | template <typename ParserType> 41998 | friend void details::disable_type_checking(ParserType& p); 41999 | }; // class parser 42000 | 42001 | namespace details 42002 | { 42003 | template <typename T> 42004 | struct collector_helper 42005 | { 42006 | typedef exprtk::symbol_table<T> symbol_table_t; 42007 | typedef exprtk::expression<T> expression_t; 42008 | typedef exprtk::parser<T> parser_t; 42009 | typedef typename parser_t::dependent_entity_collector::symbol_t symbol_t; 42010 | typedef typename parser_t::unknown_symbol_resolver usr_t; 42011 | 42012 | struct resolve_as_vector : public usr_t 42013 | { 42014 | typedef exprtk::parser<T> parser_t; 42015 | 42016 | using usr_t::process; 42017 | 42018 | resolve_as_vector() 42019 | : usr_t(usr_t::e_usrmode_extended) 42020 | {} 42021 | 42022 | virtual bool process(const std::string& unknown_symbol, 42023 | symbol_table_t& symbol_table, 42024 | std::string&) exprtk_override 42025 | { 42026 | static T v[1]; 42027 | symbol_table.add_vector(unknown_symbol,v); 42028 | return true; 42029 | } 42030 | }; 42031 | 42032 | static inline bool collection_pass(const std::string& expression_string, 42033 | std::set<std::string>& symbol_set, 42034 | const bool collect_variables, 42035 | const bool collect_functions, 42036 | const bool vector_pass, 42037 | symbol_table_t& ext_symbol_table) 42038 | { 42039 | symbol_table_t symbol_table; 42040 | expression_t expression; 42041 | parser_t parser; 42042 | 42043 | resolve_as_vector vect_resolver; 42044 | 42045 | expression.register_symbol_table(symbol_table ); 42046 | expression.register_symbol_table(ext_symbol_table); 42047 | 42048 | if (vector_pass) 42049 | parser.enable_unknown_symbol_resolver(&vect_resolver); 42050 | else 42051 | parser.enable_unknown_symbol_resolver(); 42052 | 42053 | if (collect_variables) 42054 | parser.dec().collect_variables() = true; 42055 | 42056 | if (collect_functions) 42057 | parser.dec().collect_functions() = true; 42058 | 42059 | bool pass_result = false; 42060 | 42061 | details::disable_type_checking(parser); 42062 | 42063 | if (parser.compile(expression_string, expression)) 42064 | { 42065 | pass_result = true; 42066 | 42067 | std::deque<symbol_t> symb_list; 42068 | parser.dec().symbols(symb_list); 42069 | 42070 | for (std::size_t i = 0; i < symb_list.size(); ++i) 42071 | { 42072 | symbol_set.insert(symb_list[i].first); 42073 | } 42074 | } 42075 | 42076 | return pass_result; 42077 | } 42078 | }; 42079 | } 42080 | 42081 | template <typename Allocator, 42082 | template <typename, typename> class Sequence> 42083 | inline bool collect_variables(const std::string& expression, 42084 | Sequence<std::string, Allocator>& symbol_list) 42085 | { 42086 | typedef double T; 42087 | typedef details::collector_helper<T> collect_t; 42088 | 42089 | collect_t::symbol_table_t null_symbol_table; 42090 | 42091 | std::set<std::string> symbol_set; 42092 | 42093 | const bool variable_pass = collect_t::collection_pass 42094 | (expression, symbol_set, true, false, false, null_symbol_table); 42095 | const bool vector_pass = collect_t::collection_pass 42096 | (expression, symbol_set, true, false, true, null_symbol_table); 42097 | 42098 | if (!variable_pass && !vector_pass) 42099 | return false; 42100 | 42101 | std::set<std::string>::iterator itr = symbol_set.begin(); 42102 | 42103 | while (symbol_set.end() != itr) 42104 | { 42105 | symbol_list.push_back(*itr); 42106 | ++itr; 42107 | } 42108 | 42109 | return true; 42110 | } 42111 | 42112 | template <typename T, 42113 | typename Allocator, 42114 | template <typename, typename> class Sequence> 42115 | inline bool collect_variables(const std::string& expression, 42116 | exprtk::symbol_table<T>& extrnl_symbol_table, 42117 | Sequence<std::string, Allocator>& symbol_list) 42118 | { 42119 | typedef details::collector_helper<T> collect_t; 42120 | 42121 | std::set<std::string> symbol_set; 42122 | 42123 | const bool variable_pass = collect_t::collection_pass 42124 | (expression, symbol_set, true, false, false, extrnl_symbol_table); 42125 | const bool vector_pass = collect_t::collection_pass 42126 | (expression, symbol_set, true, false, true, extrnl_symbol_table); 42127 | 42128 | if (!variable_pass && !vector_pass) 42129 | return false; 42130 | 42131 | std::set<std::string>::iterator itr = symbol_set.begin(); 42132 | 42133 | while (symbol_set.end() != itr) 42134 | { 42135 | symbol_list.push_back(*itr); 42136 | ++itr; 42137 | } 42138 | 42139 | return true; 42140 | } 42141 | 42142 | template <typename Allocator, 42143 | template <typename, typename> class Sequence> 42144 | inline bool collect_functions(const std::string& expression, 42145 | Sequence<std::string, Allocator>& symbol_list) 42146 | { 42147 | typedef double T; 42148 | typedef details::collector_helper<T> collect_t; 42149 | 42150 | collect_t::symbol_table_t null_symbol_table; 42151 | 42152 | std::set<std::string> symbol_set; 42153 | 42154 | const bool variable_pass = collect_t::collection_pass 42155 | (expression, symbol_set, false, true, false, null_symbol_table); 42156 | const bool vector_pass = collect_t::collection_pass 42157 | (expression, symbol_set, false, true, true, null_symbol_table); 42158 | 42159 | if (!variable_pass && !vector_pass) 42160 | return false; 42161 | 42162 | std::set<std::string>::iterator itr = symbol_set.begin(); 42163 | 42164 | while (symbol_set.end() != itr) 42165 | { 42166 | symbol_list.push_back(*itr); 42167 | ++itr; 42168 | } 42169 | 42170 | return true; 42171 | } 42172 | 42173 | template <typename T, 42174 | typename Allocator, 42175 | template <typename, typename> class Sequence> 42176 | inline bool collect_functions(const std::string& expression, 42177 | exprtk::symbol_table<T>& extrnl_symbol_table, 42178 | Sequence<std::string, Allocator>& symbol_list) 42179 | { 42180 | typedef details::collector_helper<T> collect_t; 42181 | 42182 | std::set<std::string> symbol_set; 42183 | 42184 | const bool variable_pass = collect_t::collection_pass 42185 | (expression, symbol_set, false, true, false, extrnl_symbol_table); 42186 | const bool vector_pass = collect_t::collection_pass 42187 | (expression, symbol_set, false, true, true, extrnl_symbol_table); 42188 | 42189 | if (!variable_pass && !vector_pass) 42190 | return false; 42191 | 42192 | std::set<std::string>::iterator itr = symbol_set.begin(); 42193 | 42194 | while (symbol_set.end() != itr) 42195 | { 42196 | symbol_list.push_back(*itr); 42197 | ++itr; 42198 | } 42199 | 42200 | return true; 42201 | } 42202 | 42203 | template <typename T> 42204 | inline T integrate(const expression<T>& e, 42205 | T& x, 42206 | const T& r0, const T& r1, 42207 | const std::size_t number_of_intervals = 1000000) 42208 | { 42209 | if (r0 > r1) 42210 | return T(0); 42211 | 42212 | const T h = (r1 - r0) / (T(2) * number_of_intervals); 42213 | T total_area = T(0); 42214 | 42215 | for (std::size_t i = 0; i < number_of_intervals; ++i) 42216 | { 42217 | x = r0 + T(2) * i * h; 42218 | const T y0 = e.value(); x += h; 42219 | const T y1 = e.value(); x += h; 42220 | const T y2 = e.value(); x += h; 42221 | total_area += h * (y0 + T(4) * y1 + y2) / T(3); 42222 | } 42223 | 42224 | return total_area; 42225 | } 42226 | 42227 | template <typename T> 42228 | inline T integrate(const expression<T>& e, 42229 | const std::string& variable_name, 42230 | const T& r0, const T& r1, 42231 | const std::size_t number_of_intervals = 1000000) 42232 | { 42233 | const symbol_table<T>& sym_table = e.get_symbol_table(); 42234 | 42235 | if (!sym_table.valid()) 42236 | { 42237 | return std::numeric_limits<T>::quiet_NaN(); 42238 | } 42239 | 42240 | details::variable_node<T>* var = sym_table.get_variable(variable_name); 42241 | 42242 | if (var) 42243 | { 42244 | T& x = var->ref(); 42245 | const T x_original = x; 42246 | const T result = integrate(e, x, r0, r1, number_of_intervals); 42247 | x = x_original; 42248 | 42249 | return result; 42250 | } 42251 | 42252 | return std::numeric_limits<T>::quiet_NaN(); 42253 | } 42254 | 42255 | template <typename T> 42256 | inline T derivative(const expression<T>& e, 42257 | T& x, 42258 | const T& h = T(0.00000001)) 42259 | { 42260 | const T x_init = x; 42261 | const T _2h = T(2) * h; 42262 | 42263 | x = x_init + _2h; 42264 | const T y0 = e.value(); 42265 | x = x_init + h; 42266 | const T y1 = e.value(); 42267 | x = x_init - h; 42268 | const T y2 = e.value(); 42269 | x = x_init - _2h; 42270 | const T y3 = e.value(); 42271 | x = x_init; 42272 | 42273 | return (-y0 + T(8) * (y1 - y2) + y3) / (T(12) * h); 42274 | } 42275 | 42276 | template <typename T> 42277 | inline T second_derivative(const expression<T>& e, 42278 | T& x, 42279 | const T& h = T(0.00001)) 42280 | { 42281 | const T x_init = x; 42282 | const T _2h = T(2) * h; 42283 | 42284 | const T y = e.value(); 42285 | x = x_init + _2h; 42286 | const T y0 = e.value(); 42287 | x = x_init + h; 42288 | const T y1 = e.value(); 42289 | x = x_init - h; 42290 | const T y2 = e.value(); 42291 | x = x_init - _2h; 42292 | const T y3 = e.value(); 42293 | x = x_init; 42294 | 42295 | return (-y0 + T(16) * (y1 + y2) - T(30) * y - y3) / (T(12) * h * h); 42296 | } 42297 | 42298 | template <typename T> 42299 | inline T third_derivative(const expression<T>& e, 42300 | T& x, 42301 | const T& h = T(0.0001)) 42302 | { 42303 | const T x_init = x; 42304 | const T _2h = T(2) * h; 42305 | 42306 | x = x_init + _2h; 42307 | const T y0 = e.value(); 42308 | x = x_init + h; 42309 | const T y1 = e.value(); 42310 | x = x_init - h; 42311 | const T y2 = e.value(); 42312 | x = x_init - _2h; 42313 | const T y3 = e.value(); 42314 | x = x_init; 42315 | 42316 | return (y0 + T(2) * (y2 - y1) - y3) / (T(2) * h * h * h); 42317 | } 42318 | 42319 | template <typename T> 42320 | inline T derivative(const expression<T>& e, 42321 | const std::string& variable_name, 42322 | const T& h = T(0.00000001)) 42323 | { 42324 | const symbol_table<T>& sym_table = e.get_symbol_table(); 42325 | 42326 | if (!sym_table.valid()) 42327 | { 42328 | return std::numeric_limits<T>::quiet_NaN(); 42329 | } 42330 | 42331 | details::variable_node<T>* var = sym_table.get_variable(variable_name); 42332 | 42333 | if (var) 42334 | { 42335 | T& x = var->ref(); 42336 | const T x_original = x; 42337 | const T result = derivative(e, x, h); 42338 | x = x_original; 42339 | 42340 | return result; 42341 | } 42342 | 42343 | return std::numeric_limits<T>::quiet_NaN(); 42344 | } 42345 | 42346 | template <typename T> 42347 | inline T second_derivative(const expression<T>& e, 42348 | const std::string& variable_name, 42349 | const T& h = T(0.00001)) 42350 | { 42351 | const symbol_table<T>& sym_table = e.get_symbol_table(); 42352 | 42353 | if (!sym_table.valid()) 42354 | { 42355 | return std::numeric_limits<T>::quiet_NaN(); 42356 | } 42357 | 42358 | details::variable_node<T>* var = sym_table.get_variable(variable_name); 42359 | 42360 | if (var) 42361 | { 42362 | T& x = var->ref(); 42363 | const T x_original = x; 42364 | const T result = second_derivative(e, x, h); 42365 | x = x_original; 42366 | 42367 | return result; 42368 | } 42369 | 42370 | return std::numeric_limits<T>::quiet_NaN(); 42371 | } 42372 | 42373 | template <typename T> 42374 | inline T third_derivative(const expression<T>& e, 42375 | const std::string& variable_name, 42376 | const T& h = T(0.0001)) 42377 | { 42378 | const symbol_table<T>& sym_table = e.get_symbol_table(); 42379 | 42380 | if (!sym_table.valid()) 42381 | { 42382 | return std::numeric_limits<T>::quiet_NaN(); 42383 | } 42384 | 42385 | details::variable_node<T>* var = sym_table.get_variable(variable_name); 42386 | 42387 | if (var) 42388 | { 42389 | T& x = var->ref(); 42390 | const T x_original = x; 42391 | const T result = third_derivative(e, x, h); 42392 | x = x_original; 42393 | 42394 | return result; 42395 | } 42396 | 42397 | return std::numeric_limits<T>::quiet_NaN(); 42398 | } 42399 | 42400 | /* 42401 | Note: The following 'compute' routines are simple helpers, 42402 | for quickly setting up the required pieces of code in order 42403 | to evaluate an expression. By virtue of how they operate 42404 | there will be an overhead with regards to their setup and 42405 | teardown and hence should not be used in time critical 42406 | sections of code. 42407 | Furthermore they only assume a small sub set of variables, 42408 | no string variables or user defined functions. 42409 | */ 42410 | template <typename T> 42411 | inline bool compute(const std::string& expression_string, T& result) 42412 | { 42413 | // No variables 42414 | symbol_table<T> symbol_table; 42415 | symbol_table.add_constants(); 42416 | 42417 | expression<T> expression; 42418 | expression.register_symbol_table(symbol_table); 42419 | 42420 | parser<T> parser; 42421 | 42422 | if (parser.compile(expression_string,expression)) 42423 | { 42424 | result = expression.value(); 42425 | 42426 | return true; 42427 | } 42428 | else 42429 | return false; 42430 | } 42431 | 42432 | template <typename T> 42433 | inline bool compute(const std::string& expression_string, 42434 | const T& x, 42435 | T& result) 42436 | { 42437 | // Only 'x' 42438 | static const std::string x_var("x"); 42439 | 42440 | symbol_table<T> symbol_table; 42441 | symbol_table.add_constants(); 42442 | symbol_table.add_constant(x_var,x); 42443 | 42444 | expression<T> expression; 42445 | expression.register_symbol_table(symbol_table); 42446 | 42447 | parser<T> parser; 42448 | 42449 | if (parser.compile(expression_string,expression)) 42450 | { 42451 | result = expression.value(); 42452 | 42453 | return true; 42454 | } 42455 | else 42456 | return false; 42457 | } 42458 | 42459 | template <typename T> 42460 | inline bool compute(const std::string& expression_string, 42461 | const T&x, const T& y, 42462 | T& result) 42463 | { 42464 | // Only 'x' and 'y' 42465 | static const std::string x_var("x"); 42466 | static const std::string y_var("y"); 42467 | 42468 | symbol_table<T> symbol_table; 42469 | symbol_table.add_constants(); 42470 | symbol_table.add_constant(x_var,x); 42471 | symbol_table.add_constant(y_var,y); 42472 | 42473 | expression<T> expression; 42474 | expression.register_symbol_table(symbol_table); 42475 | 42476 | parser<T> parser; 42477 | 42478 | if (parser.compile(expression_string,expression)) 42479 | { 42480 | result = expression.value(); 42481 | 42482 | return true; 42483 | } 42484 | else 42485 | return false; 42486 | } 42487 | 42488 | template <typename T> 42489 | inline bool compute(const std::string& expression_string, 42490 | const T& x, const T& y, const T& z, 42491 | T& result) 42492 | { 42493 | // Only 'x', 'y' or 'z' 42494 | static const std::string x_var("x"); 42495 | static const std::string y_var("y"); 42496 | static const std::string z_var("z"); 42497 | 42498 | symbol_table<T> symbol_table; 42499 | symbol_table.add_constants(); 42500 | symbol_table.add_constant(x_var,x); 42501 | symbol_table.add_constant(y_var,y); 42502 | symbol_table.add_constant(z_var,z); 42503 | 42504 | expression<T> expression; 42505 | expression.register_symbol_table(symbol_table); 42506 | 42507 | parser<T> parser; 42508 | 42509 | if (parser.compile(expression_string,expression)) 42510 | { 42511 | result = expression.value(); 42512 | 42513 | return true; 42514 | } 42515 | else 42516 | return false; 42517 | } 42518 | 42519 | template <typename T, std::size_t N> 42520 | class polynomial : public ifunction<T> 42521 | { 42522 | private: 42523 | 42524 | template <typename Type, std::size_t NumberOfCoefficients> 42525 | struct poly_impl { }; 42526 | 42527 | template <typename Type> 42528 | struct poly_impl <Type,12> 42529 | { 42530 | static inline T evaluate(const Type x, 42531 | const Type c12, const Type c11, const Type c10, const Type c9, const Type c8, 42532 | const Type c7, const Type c6, const Type c5, const Type c4, const Type c3, 42533 | const Type c2, const Type c1, const Type c0) 42534 | { 42535 | // 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 42536 | 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); 42537 | } 42538 | }; 42539 | 42540 | template <typename Type> 42541 | struct poly_impl <Type,11> 42542 | { 42543 | static inline T evaluate(const Type x, 42544 | const Type c11, const Type c10, const Type c9, const Type c8, const Type c7, 42545 | const Type c6, const Type c5, const Type c4, const Type c3, const Type c2, 42546 | const Type c1, const Type c0) 42547 | { 42548 | // 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 42549 | return (((((((((((c11 * x + c10) * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42550 | } 42551 | }; 42552 | 42553 | template <typename Type> 42554 | struct poly_impl <Type,10> 42555 | { 42556 | static inline T evaluate(const Type x, 42557 | const Type c10, const Type c9, const Type c8, const Type c7, const Type c6, 42558 | const Type c5, const Type c4, const Type c3, const Type c2, const Type c1, 42559 | const Type c0) 42560 | { 42561 | // 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 42562 | return ((((((((((c10 * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42563 | } 42564 | }; 42565 | 42566 | template <typename Type> 42567 | struct poly_impl <Type,9> 42568 | { 42569 | static inline T evaluate(const Type x, 42570 | const Type c9, const Type c8, const Type c7, const Type c6, const Type c5, 42571 | const Type c4, const Type c3, const Type c2, const Type c1, const Type c0) 42572 | { 42573 | // 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 42574 | return (((((((((c9 * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42575 | } 42576 | }; 42577 | 42578 | template <typename Type> 42579 | struct poly_impl <Type,8> 42580 | { 42581 | static inline T evaluate(const Type x, 42582 | const Type c8, const Type c7, const Type c6, const Type c5, const Type c4, 42583 | const Type c3, const Type c2, const Type c1, const Type c0) 42584 | { 42585 | // 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 42586 | return ((((((((c8 * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42587 | } 42588 | }; 42589 | 42590 | template <typename Type> 42591 | struct poly_impl <Type,7> 42592 | { 42593 | static inline T evaluate(const Type x, 42594 | const Type c7, const Type c6, const Type c5, const Type c4, const Type c3, 42595 | const Type c2, const Type c1, const Type c0) 42596 | { 42597 | // 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 42598 | return (((((((c7 * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42599 | } 42600 | }; 42601 | 42602 | template <typename Type> 42603 | struct poly_impl <Type,6> 42604 | { 42605 | static inline T evaluate(const Type x, 42606 | const Type c6, const Type c5, const Type c4, const Type c3, const Type c2, 42607 | const Type c1, const Type c0) 42608 | { 42609 | // p(x) = c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 42610 | return ((((((c6 * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42611 | } 42612 | }; 42613 | 42614 | template <typename Type> 42615 | struct poly_impl <Type,5> 42616 | { 42617 | static inline T evaluate(const Type x, 42618 | const Type c5, const Type c4, const Type c3, const Type c2, 42619 | const Type c1, const Type c0) 42620 | { 42621 | // p(x) = c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 42622 | return (((((c5 * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42623 | } 42624 | }; 42625 | 42626 | template <typename Type> 42627 | struct poly_impl <Type,4> 42628 | { 42629 | static inline T evaluate(const Type x, const Type c4, const Type c3, const Type c2, const Type c1, const Type c0) 42630 | { 42631 | // p(x) = c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 42632 | return ((((c4 * x + c3) * x + c2) * x + c1) * x + c0); 42633 | } 42634 | }; 42635 | 42636 | template <typename Type> 42637 | struct poly_impl <Type,3> 42638 | { 42639 | static inline T evaluate(const Type x, const Type c3, const Type c2, const Type c1, const Type c0) 42640 | { 42641 | // p(x) = c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 42642 | return (((c3 * x + c2) * x + c1) * x + c0); 42643 | } 42644 | }; 42645 | 42646 | template <typename Type> 42647 | struct poly_impl <Type,2> 42648 | { 42649 | static inline T evaluate(const Type x, const Type c2, const Type c1, const Type c0) 42650 | { 42651 | // p(x) = c_2x^2 + c_1x^1 + c_0x^0 42652 | return ((c2 * x + c1) * x + c0); 42653 | } 42654 | }; 42655 | 42656 | template <typename Type> 42657 | struct poly_impl <Type,1> 42658 | { 42659 | static inline T evaluate(const Type x, const Type c1, const Type c0) 42660 | { 42661 | // p(x) = c_1x^1 + c_0x^0 42662 | return (c1 * x + c0); 42663 | } 42664 | }; 42665 | 42666 | public: 42667 | 42668 | using ifunction<T>::operator(); 42669 | 42670 | polynomial() 42671 | : ifunction<T>((N+2 <= 20) ? (N + 2) : std::numeric_limits<std::size_t>::max()) 42672 | { 42673 | disable_has_side_effects(*this); 42674 | } 42675 | 42676 | virtual ~polynomial() exprtk_override 42677 | {} 42678 | 42679 | #define poly_rtrn(NN) \ 42680 | return (NN != N) ? std::numeric_limits<T>::quiet_NaN() : 42681 | 42682 | inline virtual T operator() (const T& x, const T& c1, const T& c0) exprtk_override 42683 | { 42684 | poly_rtrn(1) (poly_impl<T,1>::evaluate(x, c1, c0)); 42685 | } 42686 | 42687 | inline virtual T operator() (const T& x, const T& c2, const T& c1, const T& c0) exprtk_override 42688 | { 42689 | poly_rtrn(2) (poly_impl<T,2>::evaluate(x, c2, c1, c0)); 42690 | } 42691 | 42692 | inline virtual T operator() (const T& x, const T& c3, const T& c2, const T& c1, const T& c0) exprtk_override 42693 | { 42694 | poly_rtrn(3) (poly_impl<T,3>::evaluate(x, c3, c2, c1, c0)); 42695 | } 42696 | 42697 | inline virtual T operator() (const T& x, const T& c4, const T& c3, const T& c2, const T& c1, 42698 | const T& c0) exprtk_override 42699 | { 42700 | poly_rtrn(4) (poly_impl<T,4>::evaluate(x, c4, c3, c2, c1, c0)); 42701 | } 42702 | 42703 | inline virtual T operator() (const T& x, const T& c5, const T& c4, const T& c3, const T& c2, 42704 | const T& c1, const T& c0) exprtk_override 42705 | { 42706 | poly_rtrn(5) (poly_impl<T,5>::evaluate(x, c5, c4, c3, c2, c1, c0)); 42707 | } 42708 | 42709 | inline virtual T operator() (const T& x, const T& c6, const T& c5, const T& c4, const T& c3, 42710 | const T& c2, const T& c1, const T& c0) exprtk_override 42711 | { 42712 | poly_rtrn(6) (poly_impl<T,6>::evaluate(x, c6, c5, c4, c3, c2, c1, c0)); 42713 | } 42714 | 42715 | inline virtual T operator() (const T& x, const T& c7, const T& c6, const T& c5, const T& c4, 42716 | const T& c3, const T& c2, const T& c1, const T& c0) exprtk_override 42717 | { 42718 | poly_rtrn(7) (poly_impl<T,7>::evaluate(x, c7, c6, c5, c4, c3, c2, c1, c0)); 42719 | } 42720 | 42721 | inline virtual T operator() (const T& x, const T& c8, const T& c7, const T& c6, const T& c5, 42722 | const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) exprtk_override 42723 | { 42724 | poly_rtrn(8) (poly_impl<T,8>::evaluate(x, c8, c7, c6, c5, c4, c3, c2, c1, c0)); 42725 | } 42726 | 42727 | inline virtual T operator() (const T& x, const T& c9, const T& c8, const T& c7, const T& c6, 42728 | const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, 42729 | const T& c0) exprtk_override 42730 | { 42731 | poly_rtrn(9) (poly_impl<T,9>::evaluate(x, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0)); 42732 | } 42733 | 42734 | inline virtual T operator() (const T& x, const T& c10, const T& c9, const T& c8, const T& c7, 42735 | const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, 42736 | const T& c1, const T& c0) exprtk_override 42737 | { 42738 | poly_rtrn(10) (poly_impl<T,10>::evaluate(x, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0)); 42739 | } 42740 | 42741 | inline virtual T operator() (const T& x, const T& c11, const T& c10, const T& c9, const T& c8, 42742 | const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, 42743 | const T& c2, const T& c1, const T& c0) exprtk_override 42744 | { 42745 | poly_rtrn(11) (poly_impl<T,11>::evaluate(x, c11, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0)); 42746 | } 42747 | 42748 | inline virtual T operator() (const T& x, const T& c12, const T& c11, const T& c10, const T& c9, 42749 | const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, 42750 | const T& c3, const T& c2, const T& c1, const T& c0) exprtk_override 42751 | { 42752 | poly_rtrn(12) (poly_impl<T,12>::evaluate(x, c12, c11, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0)); 42753 | } 42754 | 42755 | #undef poly_rtrn 42756 | 42757 | inline virtual T operator() () exprtk_override 42758 | { 42759 | return std::numeric_limits<T>::quiet_NaN(); 42760 | } 42761 | 42762 | inline virtual T operator() (const T&) exprtk_override 42763 | { 42764 | return std::numeric_limits<T>::quiet_NaN(); 42765 | } 42766 | 42767 | inline virtual T operator() (const T&, const T&) exprtk_override 42768 | { 42769 | return std::numeric_limits<T>::quiet_NaN(); 42770 | } 42771 | }; 42772 | 42773 | template <typename T> 42774 | class function_compositor 42775 | { 42776 | public: 42777 | 42778 | typedef exprtk::expression<T> expression_t; 42779 | typedef exprtk::symbol_table<T> symbol_table_t; 42780 | typedef exprtk::parser<T> parser_t; 42781 | typedef typename parser_t::settings_store settings_t; 42782 | 42783 | struct function 42784 | { 42785 | function() 42786 | {} 42787 | 42788 | explicit function(const std::string& n) 42789 | : name_(n) 42790 | {} 42791 | 42792 | function(const std::string& name, 42793 | const std::string& expression) 42794 | : name_(name) 42795 | , expression_(expression) 42796 | {} 42797 | 42798 | function(const std::string& name, 42799 | const std::string& expression, 42800 | const std::string& v0) 42801 | : name_(name) 42802 | , expression_(expression) 42803 | { 42804 | v_.push_back(v0); 42805 | } 42806 | 42807 | function(const std::string& name, 42808 | const std::string& expression, 42809 | const std::string& v0, const std::string& v1) 42810 | : name_(name) 42811 | , expression_(expression) 42812 | { 42813 | v_.push_back(v0); v_.push_back(v1); 42814 | } 42815 | 42816 | function(const std::string& name, 42817 | const std::string& expression, 42818 | const std::string& v0, const std::string& v1, 42819 | const std::string& v2) 42820 | : name_(name) 42821 | , expression_(expression) 42822 | { 42823 | v_.push_back(v0); v_.push_back(v1); 42824 | v_.push_back(v2); 42825 | } 42826 | 42827 | function(const std::string& name, 42828 | const std::string& expression, 42829 | const std::string& v0, const std::string& v1, 42830 | const std::string& v2, const std::string& v3) 42831 | : name_(name) 42832 | , expression_(expression) 42833 | { 42834 | v_.push_back(v0); v_.push_back(v1); 42835 | v_.push_back(v2); v_.push_back(v3); 42836 | } 42837 | 42838 | function(const std::string& name, 42839 | const std::string& expression, 42840 | const std::string& v0, const std::string& v1, 42841 | const std::string& v2, const std::string& v3, 42842 | const std::string& v4) 42843 | : name_(name) 42844 | , expression_(expression) 42845 | { 42846 | v_.push_back(v0); v_.push_back(v1); 42847 | v_.push_back(v2); v_.push_back(v3); 42848 | v_.push_back(v4); 42849 | } 42850 | 42851 | inline function& name(const std::string& n) 42852 | { 42853 | name_ = n; 42854 | return (*this); 42855 | } 42856 | 42857 | inline function& expression(const std::string& e) 42858 | { 42859 | expression_ = e; 42860 | return (*this); 42861 | } 42862 | 42863 | inline function& var(const std::string& v) 42864 | { 42865 | v_.push_back(v); 42866 | return (*this); 42867 | } 42868 | 42869 | inline function& vars(const std::string& v0, 42870 | const std::string& v1) 42871 | { 42872 | v_.push_back(v0); 42873 | v_.push_back(v1); 42874 | return (*this); 42875 | } 42876 | 42877 | inline function& vars(const std::string& v0, 42878 | const std::string& v1, 42879 | const std::string& v2) 42880 | { 42881 | v_.push_back(v0); 42882 | v_.push_back(v1); 42883 | v_.push_back(v2); 42884 | return (*this); 42885 | } 42886 | 42887 | inline function& vars(const std::string& v0, 42888 | const std::string& v1, 42889 | const std::string& v2, 42890 | const std::string& v3) 42891 | { 42892 | v_.push_back(v0); 42893 | v_.push_back(v1); 42894 | v_.push_back(v2); 42895 | v_.push_back(v3); 42896 | return (*this); 42897 | } 42898 | 42899 | inline function& vars(const std::string& v0, 42900 | const std::string& v1, 42901 | const std::string& v2, 42902 | const std::string& v3, 42903 | const std::string& v4) 42904 | { 42905 | v_.push_back(v0); 42906 | v_.push_back(v1); 42907 | v_.push_back(v2); 42908 | v_.push_back(v3); 42909 | v_.push_back(v4); 42910 | return (*this); 42911 | } 42912 | 42913 | std::string name_; 42914 | std::string expression_; 42915 | std::deque<std::string> v_; 42916 | }; 42917 | 42918 | private: 42919 | 42920 | struct base_func : public exprtk::ifunction<T> 42921 | { 42922 | typedef const T& type; 42923 | typedef exprtk::ifunction<T> function_t; 42924 | typedef std::vector<T*> varref_t; 42925 | typedef std::vector<T> var_t; 42926 | typedef std::vector<std::string> str_t; 42927 | typedef std::pair<T*,std::size_t> lvarref_t; 42928 | typedef std::vector<lvarref_t> lvr_vec_t; 42929 | typedef std::vector<std::string*> lstr_vec_t; 42930 | 42931 | using exprtk::ifunction<T>::operator(); 42932 | 42933 | explicit base_func(const std::size_t& pc = 0) 42934 | : exprtk::ifunction<T>(pc) 42935 | , local_var_stack_size(0) 42936 | , stack_depth(0) 42937 | { 42938 | v.resize(pc); 42939 | } 42940 | 42941 | virtual ~base_func() 42942 | {} 42943 | 42944 | #define exprtk_assign(Index) \ 42945 | (*v[Index]) = v##Index; \ 42946 | 42947 | inline void update(const T& v0) 42948 | { 42949 | exprtk_assign(0) 42950 | } 42951 | 42952 | inline void update(const T& v0, const T& v1) 42953 | { 42954 | exprtk_assign(0) exprtk_assign(1) 42955 | } 42956 | 42957 | inline void update(const T& v0, const T& v1, const T& v2) 42958 | { 42959 | exprtk_assign(0) exprtk_assign(1) 42960 | exprtk_assign(2) 42961 | } 42962 | 42963 | inline void update(const T& v0, const T& v1, const T& v2, const T& v3) 42964 | { 42965 | exprtk_assign(0) exprtk_assign(1) 42966 | exprtk_assign(2) exprtk_assign(3) 42967 | } 42968 | 42969 | inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4) 42970 | { 42971 | exprtk_assign(0) exprtk_assign(1) 42972 | exprtk_assign(2) exprtk_assign(3) 42973 | exprtk_assign(4) 42974 | } 42975 | 42976 | inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5) 42977 | { 42978 | exprtk_assign(0) exprtk_assign(1) 42979 | exprtk_assign(2) exprtk_assign(3) 42980 | exprtk_assign(4) exprtk_assign(5) 42981 | } 42982 | 42983 | #ifdef exprtk_assign 42984 | #undef exprtk_assign 42985 | #endif 42986 | 42987 | inline function_t& setup(expression_t& expr) 42988 | { 42989 | expression = expr; 42990 | 42991 | typedef typename expression_t::control_block ctrlblk_t; 42992 | typedef typename ctrlblk_t::local_data_list_t ldl_t; 42993 | typedef typename ctrlblk_t::data_type data_t; 42994 | typedef typename ldl_t::value_type ldl_value_type; 42995 | 42996 | const ldl_t ldl = expr.local_data_list(); 42997 | 42998 | std::vector<std::pair<std::size_t,data_t> > index_list; 42999 | 43000 | for (std::size_t i = 0; i < ldl.size(); ++i) 43001 | { 43002 | exprtk_debug(("base_func::setup() - element[%02d] type: %s size: %d\n", 43003 | static_cast<int>(i), 43004 | expression_t::control_block::to_str(ldl[i].type).c_str(), 43005 | static_cast<int>(ldl[i].size))); 43006 | 43007 | switch (ldl[i].type) 43008 | { 43009 | case ctrlblk_t::e_unknown : continue; 43010 | case ctrlblk_t::e_expr : continue; 43011 | case ctrlblk_t::e_vecholder : continue; 43012 | default : break; 43013 | } 43014 | 43015 | if (ldl[i].size) 43016 | { 43017 | index_list.push_back(std::make_pair(i,ldl[i].type)); 43018 | } 43019 | } 43020 | 43021 | std::size_t input_param_count = 0; 43022 | 43023 | for (std::size_t i = 0; i < index_list.size(); ++i) 43024 | { 43025 | const std::size_t index = index_list[i].first; 43026 | const ldl_value_type& local_var = ldl[index]; 43027 | 43028 | assert(local_var.pointer); 43029 | 43030 | if (i < (index_list.size() - v.size())) 43031 | { 43032 | if (local_var.type == ctrlblk_t::e_string) 43033 | { 43034 | local_str_vars.push_back( 43035 | reinterpret_cast<std::string*>(local_var.pointer)); 43036 | } 43037 | else if ( 43038 | (local_var.type == ctrlblk_t::e_data ) || 43039 | (local_var.type == ctrlblk_t::e_vecdata) 43040 | ) 43041 | { 43042 | local_vars.push_back(std::make_pair( 43043 | reinterpret_cast<T*>(local_var.pointer), 43044 | local_var.size)); 43045 | 43046 | local_var_stack_size += local_var.size; 43047 | } 43048 | } 43049 | else 43050 | { 43051 | v[input_param_count++] = reinterpret_cast<T*>(local_var.pointer); 43052 | } 43053 | } 43054 | 43055 | clear_stack(); 43056 | 43057 | return (*this); 43058 | } 43059 | 43060 | inline void pre() 43061 | { 43062 | if (stack_depth++) 43063 | { 43064 | if (!v.empty()) 43065 | { 43066 | var_t var_stack(v.size(),T(0)); 43067 | copy(v,var_stack); 43068 | input_params_stack.push_back(var_stack); 43069 | } 43070 | 43071 | if (!local_vars.empty()) 43072 | { 43073 | var_t local_vec_frame(local_var_stack_size,T(0)); 43074 | copy(local_vars,local_vec_frame); 43075 | local_var_stack.push_back(local_vec_frame); 43076 | } 43077 | 43078 | if (!local_str_vars.empty()) 43079 | { 43080 | str_t local_str_frame(local_str_vars.size()); 43081 | copy(local_str_vars,local_str_frame); 43082 | local_str_stack.push_back(local_str_frame); 43083 | } 43084 | } 43085 | } 43086 | 43087 | inline void post() 43088 | { 43089 | if (--stack_depth) 43090 | { 43091 | if (!v.empty()) 43092 | { 43093 | copy(input_params_stack.back(), v); 43094 | input_params_stack.pop_back(); 43095 | } 43096 | 43097 | if (!local_vars.empty()) 43098 | { 43099 | copy(local_var_stack.back(), local_vars); 43100 | local_var_stack.pop_back(); 43101 | } 43102 | 43103 | if (!local_str_vars.empty()) 43104 | { 43105 | copy(local_str_stack.back(), local_str_vars); 43106 | local_str_stack.pop_back(); 43107 | } 43108 | } 43109 | } 43110 | 43111 | void copy(const varref_t& src_v, var_t& dest_v) 43112 | { 43113 | for (std::size_t i = 0; i < src_v.size(); ++i) 43114 | { 43115 | dest_v[i] = (*src_v[i]); 43116 | } 43117 | } 43118 | 43119 | void copy(const lstr_vec_t& src_v, str_t& dest_v) 43120 | { 43121 | for (std::size_t i = 0; i < src_v.size(); ++i) 43122 | { 43123 | dest_v[i] = (*src_v[i]); 43124 | } 43125 | } 43126 | 43127 | void copy(const var_t& src_v, varref_t& dest_v) 43128 | { 43129 | for (std::size_t i = 0; i < src_v.size(); ++i) 43130 | { 43131 | (*dest_v[i]) = src_v[i]; 43132 | } 43133 | } 43134 | 43135 | void copy(const lvr_vec_t& src_v, var_t& dest_v) 43136 | { 43137 | typename var_t::iterator itr = dest_v.begin(); 43138 | typedef typename std::iterator_traits<typename var_t::iterator>::difference_type diff_t; 43139 | 43140 | for (std::size_t i = 0; i < src_v.size(); ++i) 43141 | { 43142 | lvarref_t vr = src_v[i]; 43143 | 43144 | if (1 == vr.second) 43145 | *itr++ = (*vr.first); 43146 | else 43147 | { 43148 | std::copy(vr.first, vr.first + vr.second, itr); 43149 | itr += static_cast<diff_t>(vr.second); 43150 | } 43151 | } 43152 | } 43153 | 43154 | void copy(const var_t& src_v, lvr_vec_t& dest_v) 43155 | { 43156 | typename var_t::const_iterator itr = src_v.begin(); 43157 | typedef typename std::iterator_traits<typename var_t::iterator>::difference_type diff_t; 43158 | 43159 | for (std::size_t i = 0; i < dest_v.size(); ++i) 43160 | { 43161 | lvarref_t& vr = dest_v[i]; 43162 | 43163 | assert(vr.first != 0); 43164 | assert(vr.second > 0); 43165 | 43166 | if (1 == vr.second) 43167 | (*vr.first) = *itr++; 43168 | else 43169 | { 43170 | std::copy(itr, itr + static_cast<diff_t>(vr.second), vr.first); 43171 | itr += static_cast<diff_t>(vr.second); 43172 | } 43173 | } 43174 | } 43175 | 43176 | void copy(const str_t& src_str, lstr_vec_t& dest_str) 43177 | { 43178 | assert(src_str.size() == dest_str.size()); 43179 | 43180 | for (std::size_t i = 0; i < dest_str.size(); ++i) 43181 | { 43182 | *dest_str[i] = src_str[i]; 43183 | } 43184 | } 43185 | 43186 | inline void clear_stack() 43187 | { 43188 | for (std::size_t i = 0; i < v.size(); ++i) 43189 | { 43190 | (*v[i]) = 0; 43191 | } 43192 | } 43193 | 43194 | inline virtual T value(expression_t& e) 43195 | { 43196 | return e.value(); 43197 | } 43198 | 43199 | expression_t expression; 43200 | varref_t v; 43201 | lvr_vec_t local_vars; 43202 | lstr_vec_t local_str_vars; 43203 | std::size_t local_var_stack_size; 43204 | std::size_t stack_depth; 43205 | std::deque<var_t> input_params_stack; 43206 | std::deque<var_t> local_var_stack; 43207 | std::deque<str_t> local_str_stack; 43208 | }; 43209 | 43210 | typedef std::map<std::string,base_func*> funcparam_t; 43211 | 43212 | typedef const T& type; 43213 | 43214 | template <typename BaseFuncType> 43215 | struct scoped_bft 43216 | { 43217 | explicit scoped_bft(BaseFuncType& bft) 43218 | : bft_(bft) 43219 | { 43220 | bft_.pre (); 43221 | } 43222 | 43223 | ~scoped_bft() 43224 | { 43225 | bft_.post(); 43226 | } 43227 | 43228 | BaseFuncType& bft_; 43229 | 43230 | private: 43231 | 43232 | scoped_bft(const scoped_bft&) exprtk_delete; 43233 | scoped_bft& operator=(const scoped_bft&) exprtk_delete; 43234 | }; 43235 | 43236 | struct func_0param : public base_func 43237 | { 43238 | using exprtk::ifunction<T>::operator(); 43239 | 43240 | func_0param() : base_func(0) {} 43241 | 43242 | inline T operator() () exprtk_override 43243 | { 43244 | scoped_bft<func_0param> sb(*this); 43245 | return this->value(base_func::expression); 43246 | } 43247 | }; 43248 | 43249 | struct func_1param : public base_func 43250 | { 43251 | using exprtk::ifunction<T>::operator(); 43252 | 43253 | func_1param() : base_func(1) {} 43254 | 43255 | inline T operator() (type v0) exprtk_override 43256 | { 43257 | scoped_bft<func_1param> sb(*this); 43258 | base_func::update(v0); 43259 | return this->value(base_func::expression); 43260 | } 43261 | }; 43262 | 43263 | struct func_2param : public base_func 43264 | { 43265 | using exprtk::ifunction<T>::operator(); 43266 | 43267 | func_2param() : base_func(2) {} 43268 | 43269 | inline T operator() (type v0, type v1) exprtk_override 43270 | { 43271 | scoped_bft<func_2param> sb(*this); 43272 | base_func::update(v0, v1); 43273 | return this->value(base_func::expression); 43274 | } 43275 | }; 43276 | 43277 | struct func_3param : public base_func 43278 | { 43279 | using exprtk::ifunction<T>::operator(); 43280 | 43281 | func_3param() : base_func(3) {} 43282 | 43283 | inline T operator() (type v0, type v1, type v2) exprtk_override 43284 | { 43285 | scoped_bft<func_3param> sb(*this); 43286 | base_func::update(v0, v1, v2); 43287 | return this->value(base_func::expression); 43288 | } 43289 | }; 43290 | 43291 | struct func_4param : public base_func 43292 | { 43293 | using exprtk::ifunction<T>::operator(); 43294 | 43295 | func_4param() : base_func(4) {} 43296 | 43297 | inline T operator() (type v0, type v1, type v2, type v3) exprtk_override 43298 | { 43299 | scoped_bft<func_4param> sb(*this); 43300 | base_func::update(v0, v1, v2, v3); 43301 | return this->value(base_func::expression); 43302 | } 43303 | }; 43304 | 43305 | struct func_5param : public base_func 43306 | { 43307 | using exprtk::ifunction<T>::operator(); 43308 | 43309 | func_5param() : base_func(5) {} 43310 | 43311 | inline T operator() (type v0, type v1, type v2, type v3, type v4) exprtk_override 43312 | { 43313 | scoped_bft<func_5param> sb(*this); 43314 | base_func::update(v0, v1, v2, v3, v4); 43315 | return this->value(base_func::expression); 43316 | } 43317 | }; 43318 | 43319 | struct func_6param : public base_func 43320 | { 43321 | using exprtk::ifunction<T>::operator(); 43322 | 43323 | func_6param() : base_func(6) {} 43324 | 43325 | inline T operator() (type v0, type v1, type v2, type v3, type v4, type v5) exprtk_override 43326 | { 43327 | scoped_bft<func_6param> sb(*this); 43328 | base_func::update(v0, v1, v2, v3, v4, v5); 43329 | return this->value(base_func::expression); 43330 | } 43331 | }; 43332 | 43333 | static T return_value(expression_t& e) 43334 | { 43335 | typedef exprtk::results_context<T> results_context_t; 43336 | typedef typename results_context_t::type_store_t type_t; 43337 | typedef typename type_t::scalar_view scalar_t; 43338 | 43339 | const T result = e.value(); 43340 | 43341 | if (e.return_invoked()) 43342 | { 43343 | // Due to the post compilation checks, it can be safely 43344 | // assumed that there will be at least one parameter 43345 | // and that the first parameter will always be scalar. 43346 | return scalar_t(e.results()[0])(); 43347 | } 43348 | 43349 | return result; 43350 | } 43351 | 43352 | #define def_fp_retval(N) \ 43353 | struct func_##N##param_retval exprtk_final : public func_##N##param \ 43354 | { \ 43355 | inline T value(expression_t& e) exprtk_override \ 43356 | { \ 43357 | return return_value(e); \ 43358 | } \ 43359 | }; \ 43360 | 43361 | def_fp_retval(0) 43362 | def_fp_retval(1) 43363 | def_fp_retval(2) 43364 | def_fp_retval(3) 43365 | def_fp_retval(4) 43366 | def_fp_retval(5) 43367 | def_fp_retval(6) 43368 | 43369 | #undef def_fp_retval 43370 | 43371 | template <typename Allocator, 43372 | template <typename, typename> class Sequence> 43373 | inline bool add(const std::string& name, 43374 | const std::string& expression, 43375 | const Sequence<std::string,Allocator>& var_list, 43376 | const bool override = false) 43377 | { 43378 | const typename std::map<std::string,expression_t>::iterator itr = expr_map_.find(name); 43379 | 43380 | if (expr_map_.end() != itr) 43381 | { 43382 | if (!override) 43383 | { 43384 | exprtk_debug(("Compositor error(add): function '%s' already defined\n", 43385 | name.c_str())); 43386 | 43387 | return false; 43388 | } 43389 | 43390 | remove(name, var_list.size()); 43391 | } 43392 | 43393 | if (compile_expression(name, expression, var_list)) 43394 | { 43395 | const std::size_t n = var_list.size(); 43396 | 43397 | fp_map_[n][name]->setup(expr_map_[name]); 43398 | 43399 | return true; 43400 | } 43401 | else 43402 | { 43403 | exprtk_debug(("Compositor error(add): Failed to compile function '%s'\n", 43404 | name.c_str())); 43405 | 43406 | return false; 43407 | } 43408 | } 43409 | 43410 | public: 43411 | 43412 | function_compositor() 43413 | : parser_(settings_t::default_compile_all_opts + 43414 | settings_t::e_disable_zero_return) 43415 | , fp_map_(7) 43416 | , load_variables_(false) 43417 | , load_vectors_(false) 43418 | {} 43419 | 43420 | explicit function_compositor(const symbol_table_t& st) 43421 | : symbol_table_(st) 43422 | , parser_(settings_t::default_compile_all_opts + 43423 | settings_t::e_disable_zero_return) 43424 | , fp_map_(7) 43425 | , load_variables_(false) 43426 | , load_vectors_(false) 43427 | {} 43428 | 43429 | ~function_compositor() 43430 | { 43431 | clear(); 43432 | } 43433 | 43434 | inline symbol_table_t& symbol_table() 43435 | { 43436 | return symbol_table_; 43437 | } 43438 | 43439 | inline const symbol_table_t& symbol_table() const 43440 | { 43441 | return symbol_table_; 43442 | } 43443 | 43444 | inline void add_auxiliary_symtab(symbol_table_t& symtab) 43445 | { 43446 | auxiliary_symtab_list_.push_back(&symtab); 43447 | } 43448 | 43449 | void load_variables(const bool load = true) 43450 | { 43451 | load_variables_ = load; 43452 | } 43453 | 43454 | void load_vectors(const bool load = true) 43455 | { 43456 | load_vectors_ = load; 43457 | } 43458 | 43459 | inline void register_loop_runtime_check(loop_runtime_check& lrtchk) 43460 | { 43461 | parser_.register_loop_runtime_check(lrtchk); 43462 | } 43463 | 43464 | inline void register_vector_access_runtime_check(vector_access_runtime_check& vartchk) 43465 | { 43466 | parser_.register_vector_access_runtime_check(vartchk); 43467 | } 43468 | 43469 | inline void register_compilation_timeout_check(compilation_check& compchk) 43470 | { 43471 | parser_.register_compilation_timeout_check(compchk); 43472 | } 43473 | 43474 | inline void clear_loop_runtime_check() 43475 | { 43476 | parser_.clear_loop_runtime_check(); 43477 | } 43478 | 43479 | inline void clear_vector_access_runtime_check() 43480 | { 43481 | parser_.clear_vector_access_runtime_check(); 43482 | } 43483 | 43484 | inline void clear_compilation_timeout_check() 43485 | { 43486 | parser_.clear_compilation_timeout_check(); 43487 | } 43488 | 43489 | void clear() 43490 | { 43491 | symbol_table_.clear(); 43492 | expr_map_ .clear(); 43493 | 43494 | for (std::size_t i = 0; i < fp_map_.size(); ++i) 43495 | { 43496 | typename funcparam_t::iterator itr = fp_map_[i].begin(); 43497 | typename funcparam_t::iterator end = fp_map_[i].end (); 43498 | 43499 | while (itr != end) 43500 | { 43501 | delete itr->second; 43502 | ++itr; 43503 | } 43504 | 43505 | fp_map_[i].clear(); 43506 | } 43507 | 43508 | clear_loop_runtime_check (); 43509 | clear_vector_access_runtime_check(); 43510 | clear_compilation_timeout_check (); 43511 | } 43512 | 43513 | inline bool add(const function& f, const bool override = false) 43514 | { 43515 | return add(f.name_, f.expression_, f.v_,override); 43516 | } 43517 | 43518 | inline std::string error() const 43519 | { 43520 | if (!error_list_.empty()) 43521 | { 43522 | return error_list_[0].diagnostic; 43523 | } 43524 | else 43525 | return std::string("No Error"); 43526 | } 43527 | 43528 | inline std::size_t error_count() const 43529 | { 43530 | return error_list_.size(); 43531 | } 43532 | 43533 | inline parser_error::type get_error(const std::size_t& index) const 43534 | { 43535 | if (index < error_list_.size()) 43536 | { 43537 | return error_list_[index]; 43538 | } 43539 | 43540 | throw std::invalid_argument("compositor::get_error() - Invalid error index specified"); 43541 | } 43542 | 43543 | private: 43544 | 43545 | template <typename Allocator, 43546 | template <typename, typename> class Sequence> 43547 | bool compile_expression(const std::string& name, 43548 | const std::string& expression, 43549 | const Sequence<std::string,Allocator>& input_var_list, 43550 | bool return_present = false) 43551 | { 43552 | expression_t compiled_expression; 43553 | symbol_table_t local_symbol_table; 43554 | 43555 | local_symbol_table.load_from(symbol_table_); 43556 | local_symbol_table.add_constants(); 43557 | 43558 | if (load_variables_) 43559 | { 43560 | local_symbol_table.load_variables_from(symbol_table_); 43561 | } 43562 | 43563 | if (load_vectors_) 43564 | { 43565 | local_symbol_table.load_vectors_from(symbol_table_); 43566 | } 43567 | 43568 | error_list_.clear(); 43569 | 43570 | if (!valid(name,input_var_list.size())) 43571 | { 43572 | parser_error::type error = 43573 | parser_error::make_error( 43574 | parser_error::e_parser, 43575 | lexer::token(), 43576 | "ERR283 - Function '" + name + "' is an invalid overload", 43577 | exprtk_error_location); 43578 | 43579 | error_list_.push_back(error); 43580 | return false; 43581 | } 43582 | 43583 | if (!forward(name, 43584 | input_var_list.size(), 43585 | local_symbol_table, 43586 | return_present)) 43587 | return false; 43588 | 43589 | compiled_expression.register_symbol_table(local_symbol_table); 43590 | 43591 | for (std::size_t i = 0; i < auxiliary_symtab_list_.size(); ++i) 43592 | { 43593 | compiled_expression.register_symbol_table((*auxiliary_symtab_list_[i])); 43594 | } 43595 | 43596 | std::string mod_expression; 43597 | 43598 | for (std::size_t i = 0; i < input_var_list.size(); ++i) 43599 | { 43600 | mod_expression += " var " + input_var_list[i] + "{};\n" 43601 | } 43602 | 43603 | if ( 43604 | ('{' == details::front(expression)) && 43605 | ('}' == details::back (expression)) 43606 | ) 43607 | mod_expression += "~" + expression + "" 43608 | else 43609 | mod_expression += "~{" + expression + "};" 43610 | 43611 | if (!parser_.compile(mod_expression,compiled_expression)) 43612 | { 43613 | exprtk_debug(("Compositor Error: %s\n", parser_.error().c_str())); 43614 | exprtk_debug(("Compositor modified expression: \n%s\n", mod_expression.c_str())); 43615 | 43616 | remove(name,input_var_list.size()); 43617 | 43618 | for (std::size_t err_index = 0; err_index < parser_.error_count(); ++err_index) 43619 | { 43620 | error_list_.push_back(parser_.get_error(err_index)); 43621 | } 43622 | 43623 | return false; 43624 | } 43625 | 43626 | if (!return_present && parser_.dec().return_present()) 43627 | { 43628 | remove(name,input_var_list.size()); 43629 | return compile_expression(name, expression, input_var_list, true); 43630 | } 43631 | 43632 | // Make sure every return point has a scalar as its first parameter 43633 | if (parser_.dec().return_present()) 43634 | { 43635 | typedef std::vector<std::string> str_list_t; 43636 | 43637 | str_list_t ret_param_list = parser_.dec().return_param_type_list(); 43638 | 43639 | for (std::size_t i = 0; i < ret_param_list.size(); ++i) 43640 | { 43641 | const std::string& params = ret_param_list[i]; 43642 | 43643 | if (params.empty() || ('T' != params[0])) 43644 | { 43645 | exprtk_debug(("Compositor Error: Return statement in function '%s' is invalid\n", 43646 | name.c_str())); 43647 | 43648 | remove(name,input_var_list.size()); 43649 | 43650 | return false; 43651 | } 43652 | } 43653 | } 43654 | 43655 | expr_map_[name] = compiled_expression; 43656 | 43657 | exprtk::ifunction<T>& ifunc = (*(fp_map_[input_var_list.size()])[name]); 43658 | 43659 | if (symbol_table_.add_function(name,ifunc)) 43660 | return true; 43661 | else 43662 | { 43663 | exprtk_debug(("Compositor Error: Failed to add function '%s' to symbol table\n", 43664 | name.c_str())); 43665 | return false; 43666 | } 43667 | } 43668 | 43669 | inline bool symbol_used(const std::string& symbol) const 43670 | { 43671 | return ( 43672 | symbol_table_.is_variable (symbol) || 43673 | symbol_table_.is_stringvar (symbol) || 43674 | symbol_table_.is_function (symbol) || 43675 | symbol_table_.is_vector (symbol) || 43676 | symbol_table_.is_vararg_function(symbol) 43677 | ); 43678 | } 43679 | 43680 | inline bool valid(const std::string& name, 43681 | const std::size_t& arg_count) const 43682 | { 43683 | if (arg_count > 6) 43684 | return false; 43685 | else if (symbol_used(name)) 43686 | return false; 43687 | else if (fp_map_[arg_count].end() != fp_map_[arg_count].find(name)) 43688 | return false; 43689 | else 43690 | return true; 43691 | } 43692 | 43693 | inline bool forward(const std::string& name, 43694 | const std::size_t& arg_count, 43695 | symbol_table_t& sym_table, 43696 | const bool ret_present = false) 43697 | { 43698 | switch (arg_count) 43699 | { 43700 | #define case_stmt(N) \ 43701 | case N : (fp_map_[arg_count])[name] = \ 43702 | (!ret_present) ? static_cast<base_func*> \ 43703 | (new func_##N##param) : \ 43704 | static_cast<base_func*> \ 43705 | (new func_##N##param_retval) ; \ 43706 | break; \ 43707 | 43708 | case_stmt(0) case_stmt(1) case_stmt(2) 43709 | case_stmt(3) case_stmt(4) case_stmt(5) 43710 | case_stmt(6) 43711 | #undef case_stmt 43712 | } 43713 | 43714 | exprtk::ifunction<T>& ifunc = (*(fp_map_[arg_count])[name]); 43715 | 43716 | return sym_table.add_function(name,ifunc); 43717 | } 43718 | 43719 | inline void remove(const std::string& name, const std::size_t& arg_count) 43720 | { 43721 | if (arg_count > 6) 43722 | return; 43723 | 43724 | const typename std::map<std::string,expression_t>::iterator em_itr = expr_map_.find(name); 43725 | 43726 | if (expr_map_.end() != em_itr) 43727 | { 43728 | expr_map_.erase(em_itr); 43729 | } 43730 | 43731 | const typename funcparam_t::iterator fp_itr = fp_map_[arg_count].find(name); 43732 | 43733 | if (fp_map_[arg_count].end() != fp_itr) 43734 | { 43735 | delete fp_itr->second; 43736 | fp_map_[arg_count].erase(fp_itr); 43737 | } 43738 | 43739 | symbol_table_.remove_function(name); 43740 | } 43741 | 43742 | private: 43743 | 43744 | symbol_table_t symbol_table_; 43745 | parser_t parser_; 43746 | std::map<std::string,expression_t> expr_map_; 43747 | std::vector<funcparam_t> fp_map_; 43748 | std::vector<symbol_table_t*> auxiliary_symtab_list_; 43749 | std::deque<parser_error::type> error_list_; 43750 | bool load_variables_; 43751 | bool load_vectors_; 43752 | }; // class function_compositor 43753 | 43754 | } // namespace exprtk 43755 | 43756 | #if defined(_MSC_VER) || defined(_WIN32) || defined(__WIN32__) || defined(WIN32) 43757 | # ifndef NOMINMAX 43758 | # define NOMINMAX 43759 | # endif 43760 | # ifndef WIN32_LEAN_AND_MEAN 43761 | # define WIN32_LEAN_AND_MEAN 43762 | # endif 43763 | # include43764 | # include 43765 | #else 43766 | # include 43767 | # include 43768 | # include 43769 | #endif 43770 | 43771 | namespace exprtk 43772 | { 43773 | class timer 43774 | { 43775 | public: 43776 | 43777 | #if defined(_MSC_VER) || defined(_WIN32) || defined(__WIN32__) || defined(WIN32) 43778 | timer() 43779 | : in_use_(false) 43780 | , start_time_{ {0, 0} } 43781 | , stop_time_ { {0, 0} } 43782 | { 43783 | QueryPerformanceFrequency(&clock_frequency_); 43784 | } 43785 | 43786 | inline void start() 43787 | { 43788 | in_use_ = true; 43789 | QueryPerformanceCounter(&start_time_); 43790 | } 43791 | 43792 | inline void stop() 43793 | { 43794 | QueryPerformanceCounter(&stop_time_); 43795 | in_use_ = false; 43796 | } 43797 | 43798 | inline double time() const 43799 | { 43800 | return (1.0 * (stop_time_.QuadPart - start_time_.QuadPart)) / (1.0 * clock_frequency_.QuadPart); 43801 | } 43802 | 43803 | #else 43804 | 43805 | timer() 43806 | : in_use_(false) 43807 | { 43808 | start_time_.tv_sec = 0; 43809 | start_time_.tv_usec = 0; 43810 | 43811 | stop_time_.tv_sec = 0; 43812 | stop_time_.tv_usec = 0; 43813 | } 43814 | 43815 | inline void start() 43816 | { 43817 | in_use_ = true; 43818 | gettimeofday(&start_time_,0); 43819 | } 43820 | 43821 | inline void stop() 43822 | { 43823 | gettimeofday(&stop_time_, 0); 43824 | in_use_ = false; 43825 | } 43826 | 43827 | inline unsigned long long int usec_time() const 43828 | { 43829 | if (!in_use_) 43830 | { 43831 | if (stop_time_.tv_sec >= start_time_.tv_sec) 43832 | { 43833 | return 1000000LLU * static_cast<details::_uint64_t>(stop_time_.tv_sec - start_time_.tv_sec ) + 43834 | static_cast<details::_uint64_t>(stop_time_.tv_usec - start_time_.tv_usec) ; 43835 | } 43836 | else 43837 | return std::numeric_limits<details::_uint64_t>::max(); 43838 | } 43839 | else 43840 | return std::numeric_limits<details::_uint64_t>::max(); 43841 | } 43842 | 43843 | inline double time() const 43844 | { 43845 | return usec_time() * 0.000001; 43846 | } 43847 | 43848 | #endif 43849 | 43850 | inline bool in_use() const 43851 | { 43852 | return in_use_; 43853 | } 43854 | 43855 | private: 43856 | 43857 | bool in_use_; 43858 | 43859 | #if defined(_MSC_VER) || defined(_WIN32) || defined(__WIN32__) || defined(WIN32) 43860 | LARGE_INTEGER start_time_; 43861 | LARGE_INTEGER stop_time_; 43862 | LARGE_INTEGER clock_frequency_; 43863 | #else 43864 | struct timeval start_time_; 43865 | struct timeval stop_time_; 43866 | #endif 43867 | }; 43868 | 43869 | template <typename T> 43870 | struct type_defs 43871 | { 43872 | typedef symbol_table<T> symbol_table_t; 43873 | typedef expression<T> expression_t; 43874 | typedef parser<T> parser_t; 43875 | typedef parser_error::type error_t; 43876 | typedef function_compositor<T> compositor_t; 43877 | typedef typename compositor_t::function function_t; 43878 | }; 43879 | 43880 | } // namespace exprtk 43881 | 43882 | #ifndef exprtk_disable_rtl_io 43883 | namespace exprtk 43884 | { 43885 | namespace rtl { namespace io { namespace details 43886 | { 43887 | template <typename T> 43888 | inline void print_type(const std::string& fmt, 43889 | const T v, 43890 | exprtk::details::numeric::details::real_type_tag) 43891 | { 43892 | #if defined(__clang__) 43893 | #pragma clang diagnostic push 43894 | #pragma clang diagnostic ignored "-Wformat-nonliteral" 43895 | #elif defined(__GNUC__) || defined(__GNUG__) 43896 | #pragma GCC diagnostic push 43897 | #pragma GCC diagnostic ignored "-Wformat-nonliteral" 43898 | #elif defined(_MSC_VER) 43899 | #endif 43900 | 43901 | printf(fmt.c_str(), v); 43902 | 43903 | #if defined(__clang__) 43904 | #pragma clang diagnostic pop 43905 | #elif defined(__GNUC__) || defined(__GNUG__) 43906 | #pragma GCC diagnostic pop 43907 | #elif defined(_MSC_VER) 43908 | #endif 43909 | } 43910 | 43911 | template <typename T> 43912 | struct print_impl 43913 | { 43914 | typedef typename igeneric_function<T>::generic_type generic_type; 43915 | typedef typename igeneric_function<T>::parameter_list_t parameter_list_t; 43916 | typedef typename generic_type::scalar_view scalar_t; 43917 | typedef typename generic_type::vector_view vector_t; 43918 | typedef typename generic_type::string_view string_t; 43919 | typedef typename exprtk::details::numeric::details::number_type<T>::type num_type; 43920 | 43921 | static void process(const std::string& scalar_format, parameter_list_t parameters) 43922 | { 43923 | for (std::size_t i = 0; i < parameters.size(); ++i) 43924 | { 43925 | generic_type& gt = parameters[i]; 43926 | 43927 | switch (gt.type) 43928 | { 43929 | case generic_type::e_scalar : print(scalar_format,scalar_t(gt)); 43930 | break; 43931 | 43932 | case generic_type::e_vector : print(scalar_format,vector_t(gt)); 43933 | break; 43934 | 43935 | case generic_type::e_string : print(string_t(gt)); 43936 | break; 43937 | 43938 | default : continue; 43939 | } 43940 | } 43941 | } 43942 | 43943 | static inline void print(const std::string& scalar_format, const scalar_t& s) 43944 | { 43945 | print_type(scalar_format,s(),num_type()); 43946 | } 43947 | 43948 | static inline void print(const std::string& scalar_format, const vector_t& v) 43949 | { 43950 | for (std::size_t i = 0; i < v.size(); ++i) 43951 | { 43952 | print_type(scalar_format,v[i],num_type()); 43953 | 43954 | if ((i + 1) < v.size()) 43955 | printf(" "); 43956 | } 43957 | } 43958 | 43959 | static inline void print(const string_t& s) 43960 | { 43961 | printf("%s",to_str(s).c_str()); 43962 | } 43963 | }; 43964 | 43965 | } // namespace exprtk::rtl::io::details 43966 | 43967 | template <typename T> 43968 | struct print exprtk_final : public exprtk::igeneric_function<T> 43969 | { 43970 | typedef typename igeneric_function<T>::parameter_list_t parameter_list_t; 43971 | 43972 | using exprtk::igeneric_function<T>::operator(); 43973 | 43974 | explicit print(const std::string& scalar_format = "%10.5f") 43975 | : scalar_format_(scalar_format) 43976 | { 43977 | exprtk::enable_zero_parameters(*this); 43978 | } 43979 | 43980 | inline T operator() (parameter_list_t parameters) exprtk_override 43981 | { 43982 | details::print_impl<T>::process(scalar_format_,parameters); 43983 | return T(0); 43984 | } 43985 | 43986 | std::string scalar_format_; 43987 | }; 43988 | 43989 | template <typename T> 43990 | struct println exprtk_final : public exprtk::igeneric_function<T> 43991 | { 43992 | typedef typename igeneric_function<T>::parameter_list_t parameter_list_t; 43993 | 43994 | using exprtk::igeneric_function<T>::operator(); 43995 | 43996 | explicit println(const std::string& scalar_format = "%10.5f") 43997 | : scalar_format_(scalar_format) 43998 | { 43999 | exprtk::enable_zero_parameters(*this); 44000 | } 44001 | 44002 | inline T operator() (parameter_list_t parameters) exprtk_override 44003 | { 44004 | details::print_impl<T>::process(scalar_format_,parameters); 44005 | printf("\n"); 44006 | return T(0); 44007 | } 44008 | 44009 | std::string scalar_format_; 44010 | }; 44011 | 44012 | template <typename T> 44013 | struct package 44014 | { 44015 | print <T> p; 44016 | println<T> pl; 44017 | 44018 | bool register_package(exprtk::symbol_table<T>& symtab) 44019 | { 44020 | #define exprtk_register_function(FunctionName, FunctionType) \ 44021 | if (!symtab.add_function(FunctionName,FunctionType)) \ 44022 | { \ 44023 | exprtk_debug(( \ 44024 | "exprtk::rtl::io::register_package - Failed to add function: %s\n", \ 44025 | FunctionName)); \ 44026 | return false; \ 44027 | } \ 44028 | 44029 | exprtk_register_function("print" , p ) 44030 | exprtk_register_function("println", pl) 44031 | #undef exprtk_register_function 44032 | 44033 | return true; 44034 | } 44035 | }; 44036 | 44037 | } // namespace exprtk::rtl::io 44038 | } // namespace exprtk::rtl 44039 | } // namespace exprtk 44040 | #endif 44041 | 44042 | #ifndef exprtk_disable_rtl_io_file 44043 | #include 44044 | namespace exprtk 44045 | { 44046 | namespace rtl { namespace io { namespace file { namespace details 44047 | { 44048 | using ::exprtk::details::char_ptr; 44049 | using ::exprtk::details::char_cptr; 44050 | 44051 | enum file_mode 44052 | { 44053 | e_error = 0, 44054 | e_read = 1, 44055 | e_write = 2, 44056 | e_rdwrt = 4 44057 | }; 44058 | 44059 | struct file_descriptor 44060 | { 44061 | file_descriptor(const std::string& fname, const std::string& access) 44062 | : stream_ptr(0) 44063 | , mode(get_file_mode(access)) 44064 | , file_name(fname) 44065 | {} 44066 | 44067 | void* stream_ptr; 44068 | file_mode mode; 44069 | std::string file_name; 44070 | 44071 | bool open() 44072 | { 44073 | if (e_read == mode) 44074 | { 44075 | std::ifstream* stream = new std::ifstream(file_name.c_str(),std::ios::binary); 44076 | 44077 | if (!(*stream)) 44078 | { 44079 | file_name.clear(); 44080 | delete stream; 44081 | 44082 | return false; 44083 | } 44084 | 44085 | stream_ptr = stream; 44086 | 44087 | return true; 44088 | } 44089 | else if (e_write == mode) 44090 | { 44091 | std::ofstream* stream = new std::ofstream(file_name.c_str(),std::ios::binary); 44092 | 44093 | if (!(*stream)) 44094 | { 44095 | file_name.clear(); 44096 | delete stream; 44097 | 44098 | return false; 44099 | } 44100 | 44101 | stream_ptr = stream; 44102 | 44103 | return true; 44104 | } 44105 | else if (e_rdwrt == mode) 44106 | { 44107 | std::fstream* stream = new std::fstream(file_name.c_str(),std::ios::binary); 44108 | 44109 | if (!(*stream)) 44110 | { 44111 | file_name.clear(); 44112 | delete stream; 44113 | 44114 | return false; 44115 | } 44116 | 44117 | stream_ptr = stream; 44118 | 44119 | return true; 44120 | } 44121 | 44122 | return false; 44123 | } 44124 | 44125 | template <typename Stream, typename Ptr> 44126 | void close(Ptr& p) 44127 | { 44128 | Stream* stream = reinterpret_cast<Stream*>(p); 44129 | stream->close(); 44130 | delete stream; 44131 | p = reinterpret_cast<Ptr>(0); 44132 | } 44133 | 44134 | bool close() 44135 | { 44136 | switch (mode) 44137 | { 44138 | case e_read : close<std::ifstream>(stream_ptr); 44139 | break; 44140 | 44141 | case e_write : close<std::ofstream>(stream_ptr); 44142 | break; 44143 | 44144 | case e_rdwrt : close<std::fstream> (stream_ptr); 44145 | break; 44146 | 44147 | default : return false; 44148 | } 44149 | 44150 | return true; 44151 | } 44152 | 44153 | template <typename View> 44154 | bool write(const View& view, const std::size_t amount, const std::size_t offset = 0) 44155 | { 44156 | switch (mode) 44157 | { 44158 | case e_write : reinterpret_cast<std::ofstream*>(stream_ptr)-> 44159 | write(reinterpret_cast<char_cptr>(view.begin() + offset), amount * sizeof(typename View::value_t)); 44160 | break; 44161 | 44162 | case e_rdwrt : reinterpret_cast<std::fstream*>(stream_ptr)-> 44163 | write(reinterpret_cast<char_cptr>(view.begin() + offset) , amount * sizeof(typename View::value_t)); 44164 | break; 44165 | 44166 | default : return false; 44167 | } 44168 | 44169 | return true; 44170 | } 44171 | 44172 | template <typename View> 44173 | bool read(View& view, const std::size_t amount, const std::size_t offset = 0) 44174 | { 44175 | switch (mode) 44176 | { 44177 | case e_read : reinterpret_cast<std::ifstream*>(stream_ptr)-> 44178 | read(reinterpret_cast<char_ptr>(view.begin() + offset), amount * sizeof(typename View::value_t)); 44179 | break; 44180 | 44181 | case e_rdwrt : reinterpret_cast<std::fstream*>(stream_ptr)-> 44182 | read(reinterpret_cast<char_ptr>(view.begin() + offset) , amount * sizeof(typename View::value_t)); 44183 | break; 44184 | 44185 | default : return false; 44186 | } 44187 | 44188 | return true; 44189 | } 44190 | 44191 | bool getline(std::string& s) 44192 | { 44193 | switch (mode) 44194 | { 44195 | case e_read : return (!!std::getline(*reinterpret_cast<std::ifstream*>(stream_ptr),s)); 44196 | case e_rdwrt : return (!!std::getline(*reinterpret_cast<std::fstream* >(stream_ptr),s)); 44197 | default : return false; 44198 | } 44199 | } 44200 | 44201 | bool eof() const 44202 | { 44203 | switch (mode) 44204 | { 44205 | case e_read : return reinterpret_cast<std::ifstream*>(stream_ptr)->eof(); 44206 | case e_write : return reinterpret_cast<std::ofstream*>(stream_ptr)->eof(); 44207 | case e_rdwrt : return reinterpret_cast<std::fstream* >(stream_ptr)->eof(); 44208 | default : return true; 44209 | } 44210 | } 44211 | 44212 | file_mode get_file_mode(const std::string& access) const 44213 | { 44214 | if (access.empty() || access.size() > 2) 44215 | return e_error; 44216 | 44217 | std::size_t w_cnt = 0; 44218 | std::size_t r_cnt = 0; 44219 | 44220 | for (std::size_t i = 0; i < access.size(); ++i) 44221 | { 44222 | switch (std::tolower(access[i])) 44223 | { 44224 | case 'r' : r_cnt++; break; 44225 | case 'w' : w_cnt++; break; 44226 | default : return e_error; 44227 | } 44228 | } 44229 | 44230 | if ((0 == r_cnt) && (0 == w_cnt)) 44231 | return e_error; 44232 | else if ((r_cnt > 1) || (w_cnt > 1)) 44233 | return e_error; 44234 | else if ((1 == r_cnt) && (1 == w_cnt)) 44235 | return e_rdwrt; 44236 | else if (1 == r_cnt) 44237 | return e_read; 44238 | else 44239 | return e_write; 44240 | } 44241 | }; 44242 | 44243 | template <typename T> 44244 | file_descriptor* make_handle(T v) 44245 | { 44246 | const std::size_t fd_size = sizeof(details::file_descriptor*); 44247 | details::file_descriptor* fd = reinterpret_cast<file_descriptor*>(0); 44248 | 44249 | std::memcpy(reinterpret_cast<char_ptr >(&fd), 44250 | reinterpret_cast<char_cptr>(&v ), 44251 | fd_size); 44252 | return fd; 44253 | } 44254 | 44255 | template <typename T> 44256 | void perform_check() 44257 | { 44258 | #ifdef _MSC_VER 44259 | #pragma warning(push) 44260 | #pragma warning(disable: 4127) 44261 | #endif 44262 | if (sizeof(T) < sizeof(void*)) 44263 | { 44264 | throw std::runtime_error("exprtk::rtl::io::file - Error - pointer size larger than holder."); 44265 | } 44266 | #ifdef _MSC_VER 44267 | #pragma warning(pop) 44268 | #endif 44269 | assert(sizeof(T) <= sizeof(void*)); 44270 | } 44271 | 44272 | } // namespace exprtk::rtl::io::file::details 44273 | 44274 | template <typename T> 44275 | class open exprtk_final : public exprtk::igeneric_function<T> 44276 | { 44277 | public: 44278 | 44279 | typedef typename exprtk::igeneric_function<T> igfun_t; 44280 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44281 | typedef typename igfun_t::generic_type generic_type; 44282 | typedef typename generic_type::string_view string_t; 44283 | 44284 | using igfun_t::operator(); 44285 | 44286 | open() 44287 | : exprtk::igeneric_function<T>("S|SS") 44288 | { details::perform_check<T>(); } 44289 | 44290 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44291 | { 44292 | const std::string file_name = to_str(string_t(parameters[0])); 44293 | 44294 | if (file_name.empty()) 44295 | { 44296 | return T(0); 44297 | } 44298 | 44299 | if ((1 == ps_index) && (0 == string_t(parameters[1]).size())) 44300 | { 44301 | return T(0); 44302 | } 44303 | 44304 | const std::string access = 44305 | (0 == ps_index) ? "r" : to_str(string_t(parameters[1])); 44306 | 44307 | details::file_descriptor* fd = new details::file_descriptor(file_name,access); 44308 | 44309 | if (fd->open()) 44310 | { 44311 | T t = T(0); 44312 | 44313 | const std::size_t fd_size = sizeof(details::file_descriptor*); 44314 | 44315 | std::memcpy(reinterpret_cast<char*>(&t ), 44316 | reinterpret_cast<char*>(&fd), 44317 | fd_size); 44318 | return t; 44319 | } 44320 | else 44321 | { 44322 | delete fd; 44323 | return T(0); 44324 | } 44325 | } 44326 | }; 44327 | 44328 | template <typename T> 44329 | struct close exprtk_final : public exprtk::ifunction<T> 44330 | { 44331 | using exprtk::ifunction<T>::operator(); 44332 | 44333 | close() 44334 | : exprtk::ifunction<T>(1) 44335 | { details::perform_check<T>(); } 44336 | 44337 | inline T operator() (const T& v) exprtk_override 44338 | { 44339 | details::file_descriptor* fd = details::make_handle(v); 44340 | 44341 | if (!fd->close()) 44342 | return T(0); 44343 | 44344 | delete fd; 44345 | 44346 | return T(1); 44347 | } 44348 | }; 44349 | 44350 | template <typename T> 44351 | class write exprtk_final : public exprtk::igeneric_function<T> 44352 | { 44353 | public: 44354 | 44355 | typedef typename exprtk::igeneric_function<T> igfun_t; 44356 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44357 | typedef typename igfun_t::generic_type generic_type; 44358 | typedef typename generic_type::string_view string_t; 44359 | typedef typename generic_type::scalar_view scalar_t; 44360 | typedef typename generic_type::vector_view vector_t; 44361 | 44362 | using igfun_t::operator(); 44363 | 44364 | write() 44365 | : igfun_t("TS|TST|TV|TVT") 44366 | { details::perform_check<T>(); } 44367 | 44368 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44369 | { 44370 | details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])()); 44371 | 44372 | switch (ps_index) 44373 | { 44374 | case 0 : { 44375 | const string_t buffer(parameters[1]); 44376 | const std::size_t amount = buffer.size(); 44377 | return T(fd->write(buffer, amount) ? 1 : 0); 44378 | } 44379 | 44380 | case 1 : { 44381 | const string_t buffer(parameters[1]); 44382 | const std::size_t amount = 44383 | std::min(buffer.size(), 44384 | static_cast<std::size_t>(scalar_t(parameters[2])())); 44385 | return T(fd->write(buffer, amount) ? 1 : 0); 44386 | } 44387 | 44388 | case 2 : { 44389 | const vector_t vec(parameters[1]); 44390 | const std::size_t amount = vec.size(); 44391 | return T(fd->write(vec, amount) ? 1 : 0); 44392 | } 44393 | 44394 | case 3 : { 44395 | const vector_t vec(parameters[1]); 44396 | const std::size_t amount = 44397 | std::min(vec.size(), 44398 | static_cast<std::size_t>(scalar_t(parameters[2])())); 44399 | return T(fd->write(vec, amount) ? 1 : 0); 44400 | } 44401 | } 44402 | 44403 | return T(0); 44404 | } 44405 | }; 44406 | 44407 | template <typename T> 44408 | class read exprtk_final : public exprtk::igeneric_function<T> 44409 | { 44410 | public: 44411 | 44412 | typedef typename exprtk::igeneric_function<T> igfun_t; 44413 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44414 | typedef typename igfun_t::generic_type generic_type; 44415 | typedef typename generic_type::string_view string_t; 44416 | typedef typename generic_type::scalar_view scalar_t; 44417 | typedef typename generic_type::vector_view vector_t; 44418 | 44419 | using igfun_t::operator(); 44420 | 44421 | read() 44422 | : igfun_t("TS|TST|TV|TVT") 44423 | { details::perform_check<T>(); } 44424 | 44425 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44426 | { 44427 | details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])()); 44428 | 44429 | switch (ps_index) 44430 | { 44431 | case 0 : { 44432 | string_t buffer(parameters[1]); 44433 | const std::size_t amount = buffer.size(); 44434 | return T(fd->read(buffer,amount) ? 1 : 0); 44435 | } 44436 | 44437 | case 1 : { 44438 | string_t buffer(parameters[1]); 44439 | const std::size_t amount = 44440 | std::min(buffer.size(), 44441 | static_cast<std::size_t>(scalar_t(parameters[2])())); 44442 | return T(fd->read(buffer,amount) ? 1 : 0); 44443 | } 44444 | 44445 | case 2 : { 44446 | vector_t vec(parameters[1]); 44447 | const std::size_t amount = vec.size(); 44448 | return T(fd->read(vec,amount) ? 1 : 0); 44449 | } 44450 | 44451 | case 3 : { 44452 | vector_t vec(parameters[1]); 44453 | const std::size_t amount = 44454 | std::min(vec.size(), 44455 | static_cast<std::size_t>(scalar_t(parameters[2])())); 44456 | return T(fd->read(vec,amount) ? 1 : 0); 44457 | } 44458 | } 44459 | 44460 | return T(0); 44461 | } 44462 | }; 44463 | 44464 | template <typename T> 44465 | class getline exprtk_final : public exprtk::igeneric_function<T> 44466 | { 44467 | public: 44468 | 44469 | typedef typename exprtk::igeneric_function<T> igfun_t; 44470 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44471 | typedef typename igfun_t::generic_type generic_type; 44472 | typedef typename generic_type::string_view string_t; 44473 | typedef typename generic_type::scalar_view scalar_t; 44474 | 44475 | using igfun_t::operator(); 44476 | 44477 | getline() 44478 | : igfun_t("T",igfun_t::e_rtrn_string) 44479 | { details::perform_check<T>(); } 44480 | 44481 | inline T operator() (std::string& result, parameter_list_t parameters) exprtk_override 44482 | { 44483 | details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])()); 44484 | return T(fd->getline(result) ? 1 : 0); 44485 | } 44486 | }; 44487 | 44488 | template <typename T> 44489 | struct eof exprtk_final : public exprtk::ifunction<T> 44490 | { 44491 | using exprtk::ifunction<T>::operator(); 44492 | 44493 | eof() 44494 | : exprtk::ifunction<T>(1) 44495 | { details::perform_check<T>(); } 44496 | 44497 | inline T operator() (const T& v) exprtk_override 44498 | { 44499 | details::file_descriptor* fd = details::make_handle(v); 44500 | return (fd->eof() ? T(1) : T(0)); 44501 | } 44502 | }; 44503 | 44504 | template <typename T> 44505 | struct package 44506 | { 44507 | open <T> o; 44508 | close <T> c; 44509 | write <T> w; 44510 | read <T> r; 44511 | getline<T> g; 44512 | eof <T> e; 44513 | 44514 | bool register_package(exprtk::symbol_table<T>& symtab) 44515 | { 44516 | #define exprtk_register_function(FunctionName, FunctionType) \ 44517 | if (!symtab.add_function(FunctionName,FunctionType)) \ 44518 | { \ 44519 | exprtk_debug(( \ 44520 | "exprtk::rtl::io::file::register_package - Failed to add function: %s\n", \ 44521 | FunctionName)); \ 44522 | return false; \ 44523 | } \ 44524 | 44525 | exprtk_register_function("open" , o) 44526 | exprtk_register_function("close" , c) 44527 | exprtk_register_function("write" , w) 44528 | exprtk_register_function("read" , r) 44529 | exprtk_register_function("getline" , g) 44530 | exprtk_register_function("eof" , e) 44531 | #undef exprtk_register_function 44532 | 44533 | return true; 44534 | } 44535 | }; 44536 | 44537 | } // namespace exprtk::rtl::io::file 44538 | } // namespace exprtk::rtl::io 44539 | } // namespace exprtk::rtl 44540 | } // namespace exprtk 44541 | #endif 44542 | 44543 | #ifndef exprtk_disable_rtl_vecops 44544 | namespace exprtk 44545 | { 44546 | namespace rtl { namespace vecops { 44547 | 44548 | namespace helper 44549 | { 44550 | template <typename Vector> 44551 | inline bool invalid_range(const Vector& v, const std::size_t r0, const std::size_t r1) 44552 | { 44553 | if (r0 > (v.size() - 1)) 44554 | return true; 44555 | else if (r1 > (v.size() - 1)) 44556 | return true; 44557 | else if (r1 < r0) 44558 | return true; 44559 | else 44560 | return false; 44561 | } 44562 | 44563 | template <typename T> 44564 | struct load_vector_range 44565 | { 44566 | typedef typename exprtk::igeneric_function<T> igfun_t; 44567 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44568 | typedef typename igfun_t::generic_type generic_type; 44569 | typedef typename generic_type::scalar_view scalar_t; 44570 | typedef typename generic_type::vector_view vector_t; 44571 | 44572 | static inline bool process(parameter_list_t& parameters, 44573 | std::size_t& r0, std::size_t& r1, 44574 | const std::size_t& r0_prmidx, 44575 | const std::size_t& r1_prmidx, 44576 | const std::size_t vec_idx = 0) 44577 | { 44578 | if (r0_prmidx >= parameters.size()) 44579 | return false; 44580 | 44581 | if (r1_prmidx >= parameters.size()) 44582 | return false; 44583 | 44584 | if (!scalar_t(parameters[r0_prmidx]).to_uint(r0)) 44585 | return false; 44586 | 44587 | if (!scalar_t(parameters[r1_prmidx]).to_uint(r1)) 44588 | return false; 44589 | 44590 | return !invalid_range(vector_t(parameters[vec_idx]), r0, r1); 44591 | } 44592 | }; 44593 | } 44594 | 44595 | namespace details 44596 | { 44597 | template <typename T> 44598 | inline void kahan_sum(T& sum, T& error, const T v) 44599 | { 44600 | const T x = v - error; 44601 | const T y = sum + x; 44602 | error = (y - sum) - x; 44603 | sum = y; 44604 | } 44605 | 44606 | } // namespace exprtk::rtl::details 44607 | 44608 | template <typename T> 44609 | class all_true exprtk_final : public exprtk::igeneric_function<T> 44610 | { 44611 | public: 44612 | 44613 | typedef typename exprtk::igeneric_function<T> igfun_t; 44614 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44615 | typedef typename igfun_t::generic_type generic_type; 44616 | typedef typename generic_type::scalar_view scalar_t; 44617 | typedef typename generic_type::vector_view vector_t; 44618 | 44619 | using igfun_t::operator(); 44620 | 44621 | all_true() 44622 | : exprtk::igeneric_function<T>("V|VTT|T*") 44623 | /* 44624 | Overloads: 44625 | 0. V - vector 44626 | 1. VTT - vector, r0, r1 44627 | 2. T* - T....T 44628 | */ 44629 | {} 44630 | 44631 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44632 | { 44633 | if (2 == ps_index) 44634 | { 44635 | for (std::size_t i = 0; i < parameters.size(); ++i) 44636 | { 44637 | if (scalar_t(parameters[i])() == T(0)) 44638 | { 44639 | return T(0); 44640 | } 44641 | } 44642 | } 44643 | else 44644 | { 44645 | const vector_t vec(parameters[0]); 44646 | 44647 | std::size_t r0 = 0; 44648 | std::size_t r1 = vec.size() - 1; 44649 | 44650 | if ( 44651 | (1 == ps_index) && 44652 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 44653 | ) 44654 | { 44655 | return std::numeric_limits<T>::quiet_NaN(); 44656 | } 44657 | 44658 | for (std::size_t i = r0; i <= r1; ++i) 44659 | { 44660 | if (vec[i] == T(0)) 44661 | { 44662 | return T(0); 44663 | } 44664 | } 44665 | } 44666 | 44667 | return T(1); 44668 | } 44669 | }; 44670 | 44671 | template <typename T> 44672 | class all_false exprtk_final : public exprtk::igeneric_function<T> 44673 | { 44674 | public: 44675 | 44676 | typedef typename exprtk::igeneric_function<T> igfun_t; 44677 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44678 | typedef typename igfun_t::generic_type generic_type; 44679 | typedef typename generic_type::scalar_view scalar_t; 44680 | typedef typename generic_type::vector_view vector_t; 44681 | 44682 | using igfun_t::operator(); 44683 | 44684 | all_false() 44685 | : exprtk::igeneric_function<T>("V|VTT|T*") 44686 | /* 44687 | Overloads: 44688 | 0. V - vector 44689 | 1. VTT - vector, r0, r1 44690 | 2. T* - T....T 44691 | */ 44692 | {} 44693 | 44694 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44695 | { 44696 | if (2 == ps_index) 44697 | { 44698 | for (std::size_t i = 0; i < parameters.size(); ++i) 44699 | { 44700 | if (scalar_t(parameters[i])() != T(0)) 44701 | { 44702 | return T(0); 44703 | } 44704 | } 44705 | } 44706 | else 44707 | { 44708 | const vector_t vec(parameters[0]); 44709 | 44710 | std::size_t r0 = 0; 44711 | std::size_t r1 = vec.size() - 1; 44712 | 44713 | if ( 44714 | (1 == ps_index) && 44715 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 44716 | ) 44717 | { 44718 | return std::numeric_limits<T>::quiet_NaN(); 44719 | } 44720 | 44721 | for (std::size_t i = r0; i <= r1; ++i) 44722 | { 44723 | if (vec[i] != T(0)) 44724 | { 44725 | return T(0); 44726 | } 44727 | } 44728 | } 44729 | 44730 | return T(1); 44731 | } 44732 | }; 44733 | 44734 | template <typename T> 44735 | class any_true exprtk_final : public exprtk::igeneric_function<T> 44736 | { 44737 | public: 44738 | 44739 | typedef typename exprtk::igeneric_function<T> igfun_t; 44740 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44741 | typedef typename igfun_t::generic_type generic_type; 44742 | typedef typename generic_type::scalar_view scalar_t; 44743 | typedef typename generic_type::vector_view vector_t; 44744 | 44745 | using igfun_t::operator(); 44746 | 44747 | any_true() 44748 | : exprtk::igeneric_function<T>("V|VTT|T*") 44749 | /* 44750 | Overloads: 44751 | 0. V - vector 44752 | 1. VTT - vector, r0, r1 44753 | 2. T* - T....T 44754 | */ 44755 | {} 44756 | 44757 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44758 | { 44759 | if (2 == ps_index) 44760 | { 44761 | for (std::size_t i = 0; i < parameters.size(); ++i) 44762 | { 44763 | if (scalar_t(parameters[i])() != T(0)) 44764 | { 44765 | return T(1); 44766 | } 44767 | } 44768 | } 44769 | else 44770 | { 44771 | const vector_t vec(parameters[0]); 44772 | 44773 | std::size_t r0 = 0; 44774 | std::size_t r1 = vec.size() - 1; 44775 | 44776 | if ( 44777 | (1 == ps_index) && 44778 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 44779 | ) 44780 | { 44781 | return std::numeric_limits<T>::quiet_NaN(); 44782 | } 44783 | 44784 | for (std::size_t i = r0; i <= r1; ++i) 44785 | { 44786 | if (vec[i] != T(0)) 44787 | { 44788 | return T(1); 44789 | } 44790 | } 44791 | } 44792 | 44793 | return T(0); 44794 | } 44795 | }; 44796 | 44797 | template <typename T> 44798 | class any_false exprtk_final : public exprtk::igeneric_function<T> 44799 | { 44800 | public: 44801 | 44802 | typedef typename exprtk::igeneric_function<T> igfun_t; 44803 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44804 | typedef typename igfun_t::generic_type generic_type; 44805 | typedef typename generic_type::scalar_view scalar_t; 44806 | typedef typename generic_type::vector_view vector_t; 44807 | 44808 | using igfun_t::operator(); 44809 | 44810 | any_false() 44811 | : exprtk::igeneric_function<T>("V|VTT|T*") 44812 | /* 44813 | Overloads: 44814 | 0. V - vector 44815 | 1. VTT - vector, r0, r1 44816 | 2. T* - T....T 44817 | */ 44818 | {} 44819 | 44820 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44821 | { 44822 | if (2 == ps_index) 44823 | { 44824 | for (std::size_t i = 0; i < parameters.size(); ++i) 44825 | { 44826 | if (scalar_t(parameters[i])() == T(0)) 44827 | { 44828 | return T(1); 44829 | } 44830 | } 44831 | } 44832 | else 44833 | { 44834 | const vector_t vec(parameters[0]); 44835 | 44836 | std::size_t r0 = 0; 44837 | std::size_t r1 = vec.size() - 1; 44838 | 44839 | if ( 44840 | (1 == ps_index) && 44841 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 44842 | ) 44843 | { 44844 | return std::numeric_limits<T>::quiet_NaN(); 44845 | } 44846 | 44847 | for (std::size_t i = r0; i <= r1; ++i) 44848 | { 44849 | if (vec[i] == T(0)) 44850 | { 44851 | return T(1); 44852 | } 44853 | } 44854 | } 44855 | 44856 | return T(0); 44857 | } 44858 | }; 44859 | 44860 | template <typename T> 44861 | class count exprtk_final : public exprtk::igeneric_function<T> 44862 | { 44863 | public: 44864 | 44865 | typedef typename exprtk::igeneric_function<T> igfun_t; 44866 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44867 | typedef typename igfun_t::generic_type generic_type; 44868 | typedef typename generic_type::scalar_view scalar_t; 44869 | typedef typename generic_type::vector_view vector_t; 44870 | 44871 | using igfun_t::operator(); 44872 | 44873 | count() 44874 | : exprtk::igeneric_function<T>("V|VTT|T*") 44875 | /* 44876 | Overloads: 44877 | 0. V - vector 44878 | 1. VTT - vector, r0, r1 44879 | 2. T* - T....T 44880 | */ 44881 | {} 44882 | 44883 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44884 | { 44885 | std::size_t cnt = 0; 44886 | 44887 | if (2 == ps_index) 44888 | { 44889 | for (std::size_t i = 0; i < parameters.size(); ++i) 44890 | { 44891 | if (scalar_t(parameters[i])() != T(0)) ++cnt; 44892 | } 44893 | } 44894 | else 44895 | { 44896 | const vector_t vec(parameters[0]); 44897 | 44898 | std::size_t r0 = 0; 44899 | std::size_t r1 = vec.size() - 1; 44900 | 44901 | if ( 44902 | (1 == ps_index) && 44903 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 44904 | ) 44905 | { 44906 | return std::numeric_limits<T>::quiet_NaN(); 44907 | } 44908 | 44909 | for (std::size_t i = r0; i <= r1; ++i) 44910 | { 44911 | if (vec[i] != T(0)) ++cnt; 44912 | } 44913 | } 44914 | 44915 | return T(cnt); 44916 | } 44917 | }; 44918 | 44919 | template <typename T> 44920 | class copy exprtk_final : public exprtk::igeneric_function<T> 44921 | { 44922 | public: 44923 | 44924 | typedef typename exprtk::igeneric_function<T> igfun_t; 44925 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44926 | typedef typename igfun_t::generic_type generic_type; 44927 | typedef typename generic_type::scalar_view scalar_t; 44928 | typedef typename generic_type::vector_view vector_t; 44929 | 44930 | using igfun_t::operator(); 44931 | 44932 | copy() 44933 | : exprtk::igeneric_function<T>("VV|VTTVTT") 44934 | /* 44935 | Overloads: 44936 | 0. VV - x(vector), y(vector) 44937 | 1. VTTVTT - x(vector), xr0, xr1, y(vector), yr0, yr1, 44938 | */ 44939 | {} 44940 | 44941 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44942 | { 44943 | const vector_t x(parameters[0]); 44944 | vector_t y(parameters[(0 == ps_index) ? 1 : 3]); 44945 | 44946 | std::size_t xr0 = 0; 44947 | std::size_t xr1 = x.size() - 1; 44948 | 44949 | std::size_t yr0 = 0; 44950 | std::size_t yr1 = y.size() - 1; 44951 | 44952 | if (1 == ps_index) 44953 | { 44954 | if ( 44955 | !helper::load_vector_range<T>::process(parameters, xr0, xr1, 1, 2, 0) || 44956 | !helper::load_vector_range<T>::process(parameters, yr0, yr1, 4, 5, 3) 44957 | ) 44958 | return T(0); 44959 | } 44960 | 44961 | const std::size_t n = std::min(xr1 - xr0 + 1, yr1 - yr0 + 1); 44962 | 44963 | std::copy( 44964 | x.begin() + xr0, 44965 | x.begin() + xr0 + n, 44966 | y.begin() + yr0); 44967 | 44968 | return T(n); 44969 | } 44970 | }; 44971 | 44972 | template <typename T> 44973 | class rol exprtk_final : public exprtk::igeneric_function<T> 44974 | { 44975 | public: 44976 | 44977 | typedef typename exprtk::igeneric_function<T> igfun_t; 44978 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44979 | typedef typename igfun_t::generic_type generic_type; 44980 | typedef typename generic_type::scalar_view scalar_t; 44981 | typedef typename generic_type::vector_view vector_t; 44982 | 44983 | using igfun_t::operator(); 44984 | 44985 | rol() 44986 | : exprtk::igeneric_function<T>("VT|VTTT") 44987 | /* 44988 | Overloads: 44989 | 0. VT - vector, N 44990 | 1. VTTT - vector, N, r0, r1 44991 | */ 44992 | {} 44993 | 44994 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44995 | { 44996 | vector_t vec(parameters[0]); 44997 | 44998 | std::size_t n = 0; 44999 | std::size_t r0 = 0; 45000 | std::size_t r1 = vec.size() - 1; 45001 | 45002 | if (!scalar_t(parameters[1]).to_uint(n)) 45003 | return T(0); 45004 | 45005 | if ( 45006 | (1 == ps_index) && 45007 | !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0) 45008 | ) 45009 | return T(0); 45010 | 45011 | const std::size_t dist = r1 - r0 + 1; 45012 | const std::size_t shift = n % dist; 45013 | 45014 | std::rotate( 45015 | vec.begin() + r0, 45016 | vec.begin() + r0 + shift, 45017 | vec.begin() + r1 + 1); 45018 | 45019 | return T(1); 45020 | } 45021 | }; 45022 | 45023 | template <typename T> 45024 | class ror exprtk_final : public exprtk::igeneric_function<T> 45025 | { 45026 | public: 45027 | 45028 | typedef typename exprtk::igeneric_function<T> igfun_t; 45029 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45030 | typedef typename igfun_t::generic_type generic_type; 45031 | typedef typename generic_type::scalar_view scalar_t; 45032 | typedef typename generic_type::vector_view vector_t; 45033 | 45034 | using igfun_t::operator(); 45035 | 45036 | ror() 45037 | : exprtk::igeneric_function<T>("VT|VTTT") 45038 | /* 45039 | Overloads: 45040 | 0. VT - vector, N 45041 | 1. VTTT - vector, N, r0, r1 45042 | */ 45043 | {} 45044 | 45045 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45046 | { 45047 | vector_t vec(parameters[0]); 45048 | 45049 | std::size_t n = 0; 45050 | std::size_t r0 = 0; 45051 | std::size_t r1 = vec.size() - 1; 45052 | 45053 | if (!scalar_t(parameters[1]).to_uint(n)) 45054 | return T(0); 45055 | 45056 | if ( 45057 | (1 == ps_index) && 45058 | !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0) 45059 | ) 45060 | return T(0); 45061 | 45062 | const std::size_t dist = r1 - r0 + 1; 45063 | const std::size_t shift = (dist - (n % dist)) % dist; 45064 | 45065 | std::rotate( 45066 | vec.begin() + r0, 45067 | vec.begin() + r0 + shift, 45068 | vec.begin() + r1 + 1); 45069 | 45070 | return T(1); 45071 | } 45072 | }; 45073 | 45074 | template <typename T> 45075 | class reverse exprtk_final : public exprtk::igeneric_function<T> 45076 | { 45077 | public: 45078 | 45079 | typedef typename exprtk::igeneric_function<T> igfun_t; 45080 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45081 | typedef typename igfun_t::generic_type generic_type; 45082 | typedef typename generic_type::scalar_view scalar_t; 45083 | typedef typename generic_type::vector_view vector_t; 45084 | 45085 | using igfun_t::operator(); 45086 | 45087 | reverse() 45088 | : exprtk::igeneric_function<T>("V|VTT") 45089 | /* 45090 | Overloads: 45091 | 0. V - vector 45092 | 1. VTT - vector, r0, r1 45093 | */ 45094 | {} 45095 | 45096 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45097 | { 45098 | vector_t vec(parameters[0]); 45099 | 45100 | std::size_t r0 = 0; 45101 | std::size_t r1 = vec.size() - 1; 45102 | 45103 | if ( 45104 | (1 == ps_index) && 45105 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 45106 | ) 45107 | return T(0); 45108 | 45109 | std::reverse(vec.begin() + r0, vec.begin() + r1 + 1); 45110 | 45111 | return T(1); 45112 | } 45113 | }; 45114 | 45115 | template <typename T> 45116 | class shift_left exprtk_final : public exprtk::igeneric_function<T> 45117 | { 45118 | public: 45119 | 45120 | typedef typename exprtk::igeneric_function<T> igfun_t; 45121 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45122 | typedef typename igfun_t::generic_type generic_type; 45123 | typedef typename generic_type::scalar_view scalar_t; 45124 | typedef typename generic_type::vector_view vector_t; 45125 | 45126 | using igfun_t::operator(); 45127 | 45128 | shift_left() 45129 | : exprtk::igeneric_function<T>("VT|VTTT") 45130 | /* 45131 | Overloads: 45132 | 0. VT - vector, N 45133 | 1. VTTT - vector, N, r0, r1 45134 | */ 45135 | {} 45136 | 45137 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45138 | { 45139 | vector_t vec(parameters[0]); 45140 | 45141 | std::size_t n = 0; 45142 | std::size_t r0 = 0; 45143 | std::size_t r1 = vec.size() - 1; 45144 | 45145 | if (!scalar_t(parameters[1]).to_uint(n)) 45146 | return T(0); 45147 | 45148 | if ( 45149 | (1 == ps_index) && 45150 | !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0) 45151 | ) 45152 | return T(0); 45153 | 45154 | const std::size_t dist = r1 - r0 + 1; 45155 | 45156 | if (n > dist) 45157 | return T(0); 45158 | 45159 | std::rotate( 45160 | vec.begin() + r0, 45161 | vec.begin() + r0 + n, 45162 | vec.begin() + r1 + 1); 45163 | 45164 | for (std::size_t i = r1 - n + 1ULL; i <= r1; ++i) 45165 | { 45166 | vec[i] = T(0); 45167 | } 45168 | 45169 | return T(1); 45170 | } 45171 | }; 45172 | 45173 | template <typename T> 45174 | class shift_right exprtk_final : public exprtk::igeneric_function<T> 45175 | { 45176 | public: 45177 | 45178 | typedef typename exprtk::igeneric_function<T> igfun_t; 45179 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45180 | typedef typename igfun_t::generic_type generic_type; 45181 | typedef typename generic_type::scalar_view scalar_t; 45182 | typedef typename generic_type::vector_view vector_t; 45183 | 45184 | using igfun_t::operator(); 45185 | 45186 | shift_right() 45187 | : exprtk::igeneric_function<T>("VT|VTTT") 45188 | /* 45189 | Overloads: 45190 | 0. VT - vector, N 45191 | 1. VTTT - vector, N, r0, r1 45192 | */ 45193 | {} 45194 | 45195 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45196 | { 45197 | vector_t vec(parameters[0]); 45198 | 45199 | std::size_t n = 0; 45200 | std::size_t r0 = 0; 45201 | std::size_t r1 = vec.size() - 1; 45202 | 45203 | if (!scalar_t(parameters[1]).to_uint(n)) 45204 | return T(0); 45205 | 45206 | if ( 45207 | (1 == ps_index) && 45208 | !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0) 45209 | ) 45210 | return T(0); 45211 | 45212 | const std::size_t dist = r1 - r0 + 1; 45213 | 45214 | if (n > dist) 45215 | return T(0); 45216 | 45217 | const std::size_t shift = (dist - (n % dist)) % dist; 45218 | 45219 | std::rotate( 45220 | vec.begin() + r0, 45221 | vec.begin() + r0 + shift, 45222 | vec.begin() + r1 + 1); 45223 | 45224 | for (std::size_t i = r0; i < r0 + n; ++i) 45225 | { 45226 | vec[i] = T(0); 45227 | } 45228 | 45229 | return T(1); 45230 | } 45231 | }; 45232 | 45233 | template <typename T> 45234 | class sort exprtk_final : public exprtk::igeneric_function<T> 45235 | { 45236 | public: 45237 | 45238 | typedef typename exprtk::igeneric_function<T> igfun_t; 45239 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45240 | typedef typename igfun_t::generic_type generic_type; 45241 | typedef typename generic_type::string_view string_t; 45242 | typedef typename generic_type::vector_view vector_t; 45243 | 45244 | using igfun_t::operator(); 45245 | 45246 | sort() 45247 | : exprtk::igeneric_function<T>("V|VTT|VS|VSTT") 45248 | /* 45249 | Overloads: 45250 | 0. V - vector 45251 | 1. VTT - vector, r0, r1 45252 | 2. VS - vector, string 45253 | 3. VSTT - vector, string, r0, r1 45254 | */ 45255 | {} 45256 | 45257 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45258 | { 45259 | vector_t vec(parameters[0]); 45260 | 45261 | std::size_t r0 = 0; 45262 | std::size_t r1 = vec.size() - 1; 45263 | 45264 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)) 45265 | return T(0); 45266 | if ((3 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)) 45267 | return T(0); 45268 | 45269 | bool ascending = true; 45270 | 45271 | if ((2 == ps_index) || (3 == ps_index)) 45272 | { 45273 | if (exprtk::details::imatch(to_str(string_t(parameters[1])),"ascending")) 45274 | ascending = true; 45275 | else if (exprtk::details::imatch(to_str(string_t(parameters[1])),"descending")) 45276 | ascending = false; 45277 | else 45278 | return T(0); 45279 | } 45280 | 45281 | if (ascending) 45282 | std::sort( 45283 | vec.begin() + r0, 45284 | vec.begin() + r1 + 1, 45285 | std::less<T>()); 45286 | else 45287 | std::sort( 45288 | vec.begin() + r0, 45289 | vec.begin() + r1 + 1, 45290 | std::greater<T>()); 45291 | 45292 | return T(1); 45293 | } 45294 | }; 45295 | 45296 | template <typename T> 45297 | class nthelement exprtk_final : public exprtk::igeneric_function<T> 45298 | { 45299 | public: 45300 | 45301 | typedef typename exprtk::igeneric_function<T> igfun_t; 45302 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45303 | typedef typename igfun_t::generic_type generic_type; 45304 | typedef typename generic_type::scalar_view scalar_t; 45305 | typedef typename generic_type::vector_view vector_t; 45306 | 45307 | using igfun_t::operator(); 45308 | 45309 | nthelement() 45310 | : exprtk::igeneric_function<T>("VT|VTTT") 45311 | /* 45312 | Overloads: 45313 | 0. VT - vector, nth-element 45314 | 1. VTTT - vector, nth-element, r0, r1 45315 | */ 45316 | {} 45317 | 45318 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45319 | { 45320 | vector_t vec(parameters[0]); 45321 | 45322 | std::size_t n = 0; 45323 | std::size_t r0 = 0; 45324 | std::size_t r1 = vec.size() - 1; 45325 | 45326 | if (!scalar_t(parameters[1]).to_uint(n)) 45327 | return T(0); 45328 | 45329 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)) 45330 | { 45331 | return std::numeric_limits<T>::quiet_NaN(); 45332 | } 45333 | 45334 | std::nth_element( 45335 | vec.begin() + r0, 45336 | vec.begin() + r0 + n , 45337 | vec.begin() + r1 + 1); 45338 | 45339 | return T(1); 45340 | } 45341 | }; 45342 | 45343 | template <typename T> 45344 | class assign exprtk_final : public exprtk::igeneric_function<T> 45345 | { 45346 | public: 45347 | 45348 | typedef typename exprtk::igeneric_function<T> igfun_t; 45349 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45350 | typedef typename igfun_t::generic_type generic_type; 45351 | typedef typename generic_type::scalar_view scalar_t; 45352 | typedef typename generic_type::vector_view vector_t; 45353 | 45354 | using igfun_t::operator(); 45355 | 45356 | assign() 45357 | : exprtk::igeneric_function<T>("VT|VTTT|VTTTT") 45358 | /* 45359 | Overloads: 45360 | 0. VT - vector, V 45361 | 1. VTTT - vector, V, r0, r1 45362 | 2. VTTTT - vector, V, r0, r1, SS 45363 | */ 45364 | {} 45365 | 45366 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45367 | { 45368 | vector_t vec(parameters[0]); 45369 | 45370 | const T assign_value = scalar_t(parameters[1]); 45371 | 45372 | const std::size_t step_size = (2 != ps_index) ? 1 : 45373 | static_cast<std::size_t>(scalar_t(parameters.back())()); 45374 | 45375 | std::size_t r0 = 0; 45376 | std::size_t r1 = vec.size() - 1; 45377 | 45378 | if ( 45379 | ((ps_index == 1) || (ps_index == 2)) && 45380 | !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0) 45381 | ) 45382 | { 45383 | return T(0); 45384 | } 45385 | 45386 | for (std::size_t i = r0; i <= r1; i += step_size) 45387 | { 45388 | vec[i] = assign_value; 45389 | } 45390 | 45391 | return T(1); 45392 | } 45393 | }; 45394 | 45395 | template <typename T> 45396 | class iota exprtk_final : public exprtk::igeneric_function<T> 45397 | { 45398 | public: 45399 | 45400 | typedef typename exprtk::igeneric_function<T> igfun_t; 45401 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45402 | typedef typename igfun_t::generic_type generic_type; 45403 | typedef typename generic_type::scalar_view scalar_t; 45404 | typedef typename generic_type::vector_view vector_t; 45405 | 45406 | using igfun_t::operator(); 45407 | 45408 | iota() 45409 | : exprtk::igeneric_function<T>("VTT|VT|VTTTT|VTTT") 45410 | /* 45411 | Overloads: 45412 | 0. VTT - vector, SV, SS 45413 | 1. VT - vector, SV, SS (+1) 45414 | 2. VTTT - vector, r0, r1, SV, SS 45415 | 3. VTT - vector, r0, r1, SV, SS (+1) 45416 | 45417 | Where: 45418 | 1. SV - Start value 45419 | 2. SS - Step size 45420 | */ 45421 | {} 45422 | 45423 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45424 | { 45425 | vector_t vec(parameters[0]); 45426 | 45427 | const T start_value = (ps_index <= 1) ? 45428 | scalar_t(parameters[1]) : 45429 | scalar_t(parameters[3]) ; 45430 | 45431 | const T step_size = ((0 == ps_index) || (2 == ps_index)) ? 45432 | scalar_t(parameters.back())() : 45433 | T(1) ; 45434 | 45435 | std::size_t r0 = 0; 45436 | std::size_t r1 = vec.size() - 1; 45437 | 45438 | if ( 45439 | ((ps_index == 2) || (ps_index == 3)) && 45440 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 45441 | ) 45442 | { 45443 | return T(0); 45444 | } 45445 | 45446 | for (std::size_t i = r0; i <= r1; ++i) 45447 | { 45448 | vec[i] = start_value + ((i - r0) * step_size); 45449 | } 45450 | 45451 | return T(1); 45452 | } 45453 | }; 45454 | 45455 | template <typename T> 45456 | class sumk exprtk_final : public exprtk::igeneric_function<T> 45457 | { 45458 | public: 45459 | 45460 | typedef typename exprtk::igeneric_function<T> igfun_t; 45461 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45462 | typedef typename igfun_t::generic_type generic_type; 45463 | typedef typename generic_type::scalar_view scalar_t; 45464 | typedef typename generic_type::vector_view vector_t; 45465 | 45466 | using igfun_t::operator(); 45467 | 45468 | sumk() 45469 | : exprtk::igeneric_function<T>("V|VTT|VTTT") 45470 | /* 45471 | Overloads: 45472 | 0. V - vector 45473 | 1. VTT - vector, r0, r1 45474 | 2. VTTT - vector, r0, r1, stride 45475 | */ 45476 | {} 45477 | 45478 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45479 | { 45480 | const vector_t vec(parameters[0]); 45481 | 45482 | const std::size_t stride = (2 != ps_index) ? 1 : 45483 | static_cast<std::size_t>(scalar_t(parameters[3])()); 45484 | 45485 | std::size_t r0 = 0; 45486 | std::size_t r1 = vec.size() - 1; 45487 | 45488 | if ( 45489 | ((1 == ps_index) || (2 == ps_index)) && 45490 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 45491 | ) 45492 | { 45493 | return std::numeric_limits<T>::quiet_NaN(); 45494 | } 45495 | 45496 | T result = T(0); 45497 | T error = T(0); 45498 | 45499 | for (std::size_t i = r0; i <= r1; i += stride) 45500 | { 45501 | details::kahan_sum(result, error, vec[i]); 45502 | } 45503 | 45504 | return result; 45505 | } 45506 | }; 45507 | 45508 | template <typename T> 45509 | class axpy exprtk_final : public exprtk::igeneric_function<T> 45510 | { 45511 | public: 45512 | 45513 | typedef typename exprtk::igeneric_function<T> igfun_t; 45514 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45515 | typedef typename igfun_t::generic_type generic_type; 45516 | typedef typename generic_type::scalar_view scalar_t; 45517 | typedef typename generic_type::vector_view vector_t; 45518 | 45519 | using igfun_t::operator(); 45520 | 45521 | axpy() 45522 | : exprtk::igeneric_function<T>("TVV|TVVTT") 45523 | /* 45524 | y <- ax + y 45525 | Overloads: 45526 | 0. TVV - a, x(vector), y(vector) 45527 | 1. TVVTT - a, x(vector), y(vector), r0, r1 45528 | */ 45529 | {} 45530 | 45531 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45532 | { 45533 | const vector_t x(parameters[1]); 45534 | vector_t y(parameters[2]); 45535 | 45536 | std::size_t r0 = 0; 45537 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 45538 | 45539 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 3, 4, 1)) 45540 | return std::numeric_limits<T>::quiet_NaN(); 45541 | else if (helper::invalid_range(y, r0, r1)) 45542 | return std::numeric_limits<T>::quiet_NaN(); 45543 | 45544 | const T a = scalar_t(parameters[0])(); 45545 | 45546 | for (std::size_t i = r0; i <= r1; ++i) 45547 | { 45548 | y[i] = (a * x[i]) + y[i]; 45549 | } 45550 | 45551 | return T(1); 45552 | } 45553 | }; 45554 | 45555 | template <typename T> 45556 | class axpby exprtk_final : public exprtk::igeneric_function<T> 45557 | { 45558 | public: 45559 | 45560 | typedef typename exprtk::igeneric_function<T> igfun_t; 45561 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45562 | typedef typename igfun_t::generic_type generic_type; 45563 | typedef typename generic_type::scalar_view scalar_t; 45564 | typedef typename generic_type::vector_view vector_t; 45565 | 45566 | using igfun_t::operator(); 45567 | 45568 | axpby() 45569 | : exprtk::igeneric_function<T>("TVTV|TVTVTT") 45570 | /* 45571 | y <- ax + by 45572 | Overloads: 45573 | 0. TVTV - a, x(vector), b, y(vector) 45574 | 1. TVTVTT - a, x(vector), b, y(vector), r0, r1 45575 | */ 45576 | {} 45577 | 45578 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45579 | { 45580 | const vector_t x(parameters[1]); 45581 | vector_t y(parameters[3]); 45582 | 45583 | std::size_t r0 = 0; 45584 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 45585 | 45586 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1)) 45587 | return std::numeric_limits<T>::quiet_NaN(); 45588 | else if (helper::invalid_range(y, r0, r1)) 45589 | return std::numeric_limits<T>::quiet_NaN(); 45590 | 45591 | const T a = scalar_t(parameters[0])(); 45592 | const T b = scalar_t(parameters[2])(); 45593 | 45594 | for (std::size_t i = r0; i <= r1; ++i) 45595 | { 45596 | y[i] = (a * x[i]) + (b * y[i]); 45597 | } 45598 | 45599 | return T(1); 45600 | } 45601 | }; 45602 | 45603 | template <typename T> 45604 | class axpyz exprtk_final : public exprtk::igeneric_function<T> 45605 | { 45606 | public: 45607 | 45608 | typedef typename exprtk::igeneric_function<T> igfun_t; 45609 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45610 | typedef typename igfun_t::generic_type generic_type; 45611 | typedef typename generic_type::scalar_view scalar_t; 45612 | typedef typename generic_type::vector_view vector_t; 45613 | 45614 | using igfun_t::operator(); 45615 | 45616 | axpyz() 45617 | : exprtk::igeneric_function<T>("TVVV|TVVVTT") 45618 | /* 45619 | z <- ax + y 45620 | Overloads: 45621 | 0. TVVV - a, x(vector), y(vector), z(vector) 45622 | 1. TVVVTT - a, x(vector), y(vector), z(vector), r0, r1 45623 | */ 45624 | {} 45625 | 45626 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45627 | { 45628 | const vector_t x(parameters[1]); 45629 | const vector_t y(parameters[2]); 45630 | vector_t z(parameters[3]); 45631 | 45632 | std::size_t r0 = 0; 45633 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 45634 | 45635 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1)) 45636 | return std::numeric_limits<T>::quiet_NaN(); 45637 | else if (helper::invalid_range(y, r0, r1)) 45638 | return std::numeric_limits<T>::quiet_NaN(); 45639 | else if (helper::invalid_range(z, r0, r1)) 45640 | return std::numeric_limits<T>::quiet_NaN(); 45641 | 45642 | const T a = scalar_t(parameters[0])(); 45643 | 45644 | for (std::size_t i = r0; i <= r1; ++i) 45645 | { 45646 | z[i] = (a * x[i]) + y[i]; 45647 | } 45648 | 45649 | return T(1); 45650 | } 45651 | }; 45652 | 45653 | template <typename T> 45654 | class axpbyz exprtk_final : public exprtk::igeneric_function<T> 45655 | { 45656 | public: 45657 | 45658 | typedef typename exprtk::igeneric_function<T> igfun_t; 45659 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45660 | typedef typename igfun_t::generic_type generic_type; 45661 | typedef typename generic_type::scalar_view scalar_t; 45662 | typedef typename generic_type::vector_view vector_t; 45663 | 45664 | using igfun_t::operator(); 45665 | 45666 | axpbyz() 45667 | : exprtk::igeneric_function<T>("TVTVV|TVTVVTT") 45668 | /* 45669 | z <- ax + by 45670 | Overloads: 45671 | 0. TVTVV - a, x(vector), b, y(vector), z(vector) 45672 | 1. TVTVVTT - a, x(vector), b, y(vector), z(vector), r0, r1 45673 | */ 45674 | {} 45675 | 45676 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45677 | { 45678 | const vector_t x(parameters[1]); 45679 | const vector_t y(parameters[3]); 45680 | vector_t z(parameters[4]); 45681 | 45682 | std::size_t r0 = 0; 45683 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 45684 | 45685 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 5, 6, 1)) 45686 | return std::numeric_limits<T>::quiet_NaN(); 45687 | else if (helper::invalid_range(y, r0, r1)) 45688 | return std::numeric_limits<T>::quiet_NaN(); 45689 | else if (helper::invalid_range(z, r0, r1)) 45690 | return std::numeric_limits<T>::quiet_NaN(); 45691 | 45692 | const T a = scalar_t(parameters[0])(); 45693 | const T b = scalar_t(parameters[2])(); 45694 | 45695 | for (std::size_t i = r0; i <= r1; ++i) 45696 | { 45697 | z[i] = (a * x[i]) + (b * y[i]); 45698 | } 45699 | 45700 | return T(1); 45701 | } 45702 | }; 45703 | 45704 | template <typename T> 45705 | class axpbsy exprtk_final : public exprtk::igeneric_function<T> 45706 | { 45707 | public: 45708 | 45709 | typedef typename exprtk::igeneric_function<T> igfun_t; 45710 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45711 | typedef typename igfun_t::generic_type generic_type; 45712 | typedef typename generic_type::scalar_view scalar_t; 45713 | typedef typename generic_type::vector_view vector_t; 45714 | 45715 | using igfun_t::operator(); 45716 | 45717 | axpbsy() 45718 | : exprtk::igeneric_function<T>("TVTTV|TVTTVTT") 45719 | /* 45720 | y <- ax + by 45721 | Overloads: 45722 | 0. TVTVV - a, x(vector), b, shift, y(vector), z(vector) 45723 | 1. TVTVVTT - a, x(vector), b, shift, y(vector), z(vector), r0, r1 45724 | */ 45725 | {} 45726 | 45727 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45728 | { 45729 | const vector_t x(parameters[1]); 45730 | vector_t y(parameters[4]); 45731 | 45732 | std::size_t r0 = 0; 45733 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 45734 | 45735 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 5, 6, 1)) 45736 | return std::numeric_limits<T>::quiet_NaN(); 45737 | else if (helper::invalid_range(y, r0, r1)) 45738 | return std::numeric_limits<T>::quiet_NaN(); 45739 | 45740 | const T a = scalar_t(parameters[0])(); 45741 | const T b = scalar_t(parameters[2])(); 45742 | 45743 | const std::size_t s = static_cast<std::size_t>(scalar_t(parameters[3])()); 45744 | 45745 | for (std::size_t i = r0; i <= r1; ++i) 45746 | { 45747 | y[i] = (a * x[i]) + (b * y[i + s]); 45748 | } 45749 | 45750 | return T(1); 45751 | } 45752 | }; 45753 | 45754 | template <typename T> 45755 | class axpbsyz 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 | axpbsyz() 45768 | : exprtk::igeneric_function<T>("TVTTVV|TVTTVVTT") 45769 | /* 45770 | z <- ax + by 45771 | Overloads: 45772 | 0. TVTVV - a, x(vector), b, shift, y(vector), z(vector) 45773 | 1. TVTVVTT - a, x(vector), b, shift, 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[4]); 45781 | vector_t z(parameters[5]); 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, 6, 7, 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 | const T b = scalar_t(parameters[2])(); 45795 | 45796 | const std::size_t s = static_cast<std::size_t>(scalar_t(parameters[3])()); 45797 | 45798 | for (std::size_t i = r0; i <= r1; ++i) 45799 | { 45800 | z[i] = (a * x[i]) + (b * y[i + s]); 45801 | } 45802 | 45803 | return T(1); 45804 | } 45805 | }; 45806 | 45807 | template <typename T> 45808 | class axpbz exprtk_final : public exprtk::igeneric_function<T> 45809 | { 45810 | public: 45811 | 45812 | typedef typename exprtk::igeneric_function<T> igfun_t; 45813 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45814 | typedef typename igfun_t::generic_type generic_type; 45815 | typedef typename generic_type::scalar_view scalar_t; 45816 | typedef typename generic_type::vector_view vector_t; 45817 | 45818 | using igfun_t::operator(); 45819 | 45820 | axpbz() 45821 | : exprtk::igeneric_function<T>("TVTV|TVTVTT") 45822 | /* 45823 | z <- ax + b 45824 | Overloads: 45825 | 0. TVTV - a, x(vector), b, z(vector) 45826 | 1. TVTVTT - a, x(vector), b, z(vector), r0, r1 45827 | */ 45828 | {} 45829 | 45830 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45831 | { 45832 | const vector_t x(parameters[1]); 45833 | vector_t z(parameters[3]); 45834 | 45835 | std::size_t r0 = 0; 45836 | std::size_t r1 = x.size() - 1; 45837 | 45838 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1)) 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; 45849 | } 45850 | 45851 | return T(1); 45852 | } 45853 | }; 45854 | 45855 | template <typename T> 45856 | class diff 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 | diff() 45869 | : exprtk::igeneric_function<T>("VV|VVT") 45870 | /* 45871 | x_(i - stride) - x_i 45872 | Overloads: 45873 | 0. VV - x(vector), y(vector) 45874 | 1. VVT - x(vector), y(vector), stride 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[0]); 45881 | vector_t y(parameters[1]); 45882 | 45883 | const std::size_t r0 = 0; 45884 | const std::size_t r1 = std::min(x.size(),y.size()) - 1; 45885 | 45886 | const std::size_t stride = (1 != ps_index) ? 1 : 45887 | std::min(r1,static_cast<std::size_t>(scalar_t(parameters[2])())); 45888 | 45889 | for (std::size_t i = 0; i < stride; ++i) 45890 | { 45891 | y[i] = std::numeric_limits<T>::quiet_NaN(); 45892 | } 45893 | 45894 | for (std::size_t i = (r0 + stride); i <= r1; ++i) 45895 | { 45896 | y[i] = x[i] - x[i - stride]; 45897 | } 45898 | 45899 | return T(1); 45900 | } 45901 | }; 45902 | 45903 | template <typename T> 45904 | class dot exprtk_final : public exprtk::igeneric_function<T> 45905 | { 45906 | public: 45907 | 45908 | typedef typename exprtk::igeneric_function<T> igfun_t; 45909 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45910 | typedef typename igfun_t::generic_type generic_type; 45911 | typedef typename generic_type::scalar_view scalar_t; 45912 | typedef typename generic_type::vector_view vector_t; 45913 | 45914 | using igfun_t::operator(); 45915 | 45916 | dot() 45917 | : exprtk::igeneric_function<T>("VV|VVTT") 45918 | /* 45919 | Overloads: 45920 | 0. VV - x(vector), y(vector) 45921 | 1. VVTT - x(vector), y(vector), r0, r1 45922 | */ 45923 | {} 45924 | 45925 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45926 | { 45927 | const vector_t x(parameters[0]); 45928 | const vector_t y(parameters[1]); 45929 | 45930 | std::size_t r0 = 0; 45931 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 45932 | 45933 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)) 45934 | return std::numeric_limits<T>::quiet_NaN(); 45935 | else if (helper::invalid_range(y, r0, r1)) 45936 | return std::numeric_limits<T>::quiet_NaN(); 45937 | 45938 | T result = T(0); 45939 | 45940 | for (std::size_t i = r0; i <= r1; ++i) 45941 | { 45942 | result += (x[i] * y[i]); 45943 | } 45944 | 45945 | return result; 45946 | } 45947 | }; 45948 | 45949 | template <typename T> 45950 | class dotk exprtk_final : public exprtk::igeneric_function<T> 45951 | { 45952 | public: 45953 | 45954 | typedef typename exprtk::igeneric_function<T> igfun_t; 45955 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45956 | typedef typename igfun_t::generic_type generic_type; 45957 | typedef typename generic_type::scalar_view scalar_t; 45958 | typedef typename generic_type::vector_view vector_t; 45959 | 45960 | using igfun_t::operator(); 45961 | 45962 | dotk() 45963 | : exprtk::igeneric_function<T>("VV|VVTT") 45964 | /* 45965 | Overloads: 45966 | 0. VV - x(vector), y(vector) 45967 | 1. VVTT - x(vector), y(vector), r0, r1 45968 | */ 45969 | {} 45970 | 45971 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45972 | { 45973 | const vector_t x(parameters[0]); 45974 | const vector_t y(parameters[1]); 45975 | 45976 | std::size_t r0 = 0; 45977 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 45978 | 45979 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)) 45980 | return std::numeric_limits<T>::quiet_NaN(); 45981 | else if (helper::invalid_range(y, r0, r1)) 45982 | return std::numeric_limits<T>::quiet_NaN(); 45983 | 45984 | T result = T(0); 45985 | T error = T(0); 45986 | 45987 | for (std::size_t i = r0; i <= r1; ++i) 45988 | { 45989 | details::kahan_sum(result, error, (x[i] * y[i])); 45990 | } 45991 | 45992 | return result; 45993 | } 45994 | }; 45995 | 45996 | template <typename T> 45997 | class threshold_below exprtk_final : public exprtk::igeneric_function<T> 45998 | { 45999 | public: 46000 | 46001 | typedef typename exprtk::igeneric_function<T> igfun_t; 46002 | typedef typename igfun_t::parameter_list_t parameter_list_t; 46003 | typedef typename igfun_t::generic_type generic_type; 46004 | typedef typename generic_type::scalar_view scalar_t; 46005 | typedef typename generic_type::vector_view vector_t; 46006 | 46007 | using igfun_t::operator(); 46008 | 46009 | threshold_below() 46010 | : exprtk::igeneric_function<T>("VTT|VTTTT") 46011 | /* 46012 | Overloads: 46013 | 0. VTT - vector, TV, SV 46014 | 1. VTTTT - vector, r0, r1, TV, SV 46015 | 46016 | Where: 46017 | TV - Threshold value 46018 | SV - Snap-to value 46019 | */ 46020 | {} 46021 | 46022 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 46023 | { 46024 | vector_t vec(parameters[0]); 46025 | 46026 | const T threshold_value = (0 == ps_index) ? 46027 | scalar_t(parameters[1]) : 46028 | scalar_t(parameters[3]) ; 46029 | 46030 | const T snap_value = scalar_t(parameters.back()); 46031 | 46032 | std::size_t r0 = 0; 46033 | std::size_t r1 = vec.size() - 1; 46034 | 46035 | if ( 46036 | (1 == ps_index) && 46037 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 46038 | ) 46039 | { 46040 | return T(0); 46041 | } 46042 | 46043 | for (std::size_t i = r0; i <= r1; ++i) 46044 | { 46045 | if (vec[i] < threshold_value) 46046 | { 46047 | vec[i] = snap_value; 46048 | } 46049 | } 46050 | 46051 | return T(1); 46052 | } 46053 | }; 46054 | 46055 | template <typename T> 46056 | class threshold_above exprtk_final : public exprtk::igeneric_function<T> 46057 | { 46058 | public: 46059 | 46060 | typedef typename exprtk::igeneric_function<T> igfun_t; 46061 | typedef typename igfun_t::parameter_list_t parameter_list_t; 46062 | typedef typename igfun_t::generic_type generic_type; 46063 | typedef typename generic_type::scalar_view scalar_t; 46064 | typedef typename generic_type::vector_view vector_t; 46065 | 46066 | using igfun_t::operator(); 46067 | 46068 | threshold_above() 46069 | : exprtk::igeneric_function<T>("VTT|VTTTT") 46070 | /* 46071 | Overloads: 46072 | 0. VTT - vector, TV, SV 46073 | 1. VTTTT - vector, r0, r1, TV, SV 46074 | 46075 | Where: 46076 | TV - Threshold value 46077 | SV - Snap-to value 46078 | */ 46079 | {} 46080 | 46081 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 46082 | { 46083 | vector_t vec(parameters[0]); 46084 | 46085 | const T threshold_value = (0 == ps_index) ? 46086 | scalar_t(parameters[1]) : 46087 | scalar_t(parameters[3]) ; 46088 | 46089 | const T snap_value = scalar_t(parameters.back()); 46090 | 46091 | std::size_t r0 = 0; 46092 | std::size_t r1 = vec.size() - 1; 46093 | 46094 | if ( 46095 | (1 == ps_index) && 46096 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 46097 | ) 46098 | { 46099 | return T(0); 46100 | } 46101 | 46102 | for (std::size_t i = r0; i <= r1; ++i) 46103 | { 46104 | if (vec[i] > threshold_value) 46105 | { 46106 | vec[i] = snap_value; 46107 | } 46108 | } 46109 | 46110 | return T(1); 46111 | } 46112 | }; 46113 | 46114 | template <typename T> 46115 | struct package 46116 | { 46117 | all_true <T> at; 46118 | all_false <T> af; 46119 | any_true <T> nt; 46120 | any_false <T> nf; 46121 | count <T> c; 46122 | copy <T> cp; 46123 | rol <T> rl; 46124 | ror <T> rr; 46125 | reverse <T> rev; 46126 | shift_left <T> sl; 46127 | shift_right <T> sr; 46128 | sort <T> st; 46129 | nthelement <T> ne; 46130 | assign <T> an; 46131 | iota <T> ia; 46132 | sumk <T> sk; 46133 | axpy <T> b1_axpy; 46134 | axpby <T> b1_axpby; 46135 | axpyz <T> b1_axpyz; 46136 | axpbyz <T> b1_axpbyz; 46137 | axpbsy <T> b1_axpbsy; 46138 | axpbsyz <T> b1_axpbsyz; 46139 | axpbz <T> b1_axpbz; 46140 | diff <T> df; 46141 | dot <T> dt; 46142 | dotk <T> dtk; 46143 | threshold_above<T> ta; 46144 | threshold_below<T> tb; 46145 | 46146 | bool register_package(exprtk::symbol_table<T>& symtab) 46147 | { 46148 | #define exprtk_register_function(FunctionName, FunctionType) \ 46149 | if (!symtab.add_function(FunctionName,FunctionType)) \ 46150 | { \ 46151 | exprtk_debug(( \ 46152 | "exprtk::rtl::vecops::register_package - Failed to add function: %s\n", \ 46153 | FunctionName)); \ 46154 | return false; \ 46155 | } \ 46156 | 46157 | exprtk_register_function("all_true" , at ) 46158 | exprtk_register_function("all_false" , af ) 46159 | exprtk_register_function("any_true" , nt ) 46160 | exprtk_register_function("any_false" , nf ) 46161 | exprtk_register_function("count" , c ) 46162 | exprtk_register_function("copy" , cp ) 46163 | exprtk_register_function("rotate_left" , rl ) 46164 | exprtk_register_function("rol" , rl ) 46165 | exprtk_register_function("rotate_right" , rr ) 46166 | exprtk_register_function("ror" , rr ) 46167 | exprtk_register_function("reverse" , rev ) 46168 | exprtk_register_function("shftl" , sl ) 46169 | exprtk_register_function("shftr" , sr ) 46170 | exprtk_register_function("sort" , st ) 46171 | exprtk_register_function("nth_element" , ne ) 46172 | exprtk_register_function("assign" , an ) 46173 | exprtk_register_function("iota" , ia ) 46174 | exprtk_register_function("sumk" , sk ) 46175 | exprtk_register_function("axpy" , b1_axpy ) 46176 | exprtk_register_function("axpby" , b1_axpby ) 46177 | exprtk_register_function("axpyz" , b1_axpyz ) 46178 | exprtk_register_function("axpbyz" , b1_axpbyz ) 46179 | exprtk_register_function("axpbsy" , b1_axpbsy ) 46180 | exprtk_register_function("axpbsyz" , b1_axpbsyz) 46181 | exprtk_register_function("axpbz" , b1_axpbz ) 46182 | exprtk_register_function("diff" , df ) 46183 | exprtk_register_function("dot" , dt ) 46184 | exprtk_register_function("dotk" , dtk ) 46185 | exprtk_register_function("threshold_above" , ta ) 46186 | exprtk_register_function("threshold_below" , tb ) 46187 | #undef exprtk_register_function 46188 | 46189 | return true; 46190 | } 46191 | }; 46192 | 46193 | } // namespace exprtk::rtl::vecops 46194 | } // namespace exprtk::rtl 46195 | } // namespace exprtk 46196 | #endif 46197 | 46198 | namespace exprtk 46199 | { 46200 | namespace information 46201 | { 46202 | using ::exprtk::details::char_cptr; 46203 | 46204 | static char_cptr library = "Mathematical Expression Toolkit" 46205 | static char_cptr version = "2.718281828459045235360287471352662497757" 46206 | "24709369995957496696762772407663035354759" 46207 | "45713821785251664274274663919320030599218" 46208 | "17413596629043572900334295260595630738132" 46209 | static char_cptr date = "20240101" 46210 | static char_cptr min_cpp = "199711L" 46211 | 46212 | static inline std::string data() 46213 | { 46214 | static const std::string info_str = std::string(library) + 46215 | std::string(" v") + std::string(version) + 46216 | std::string(" (") + date + std::string(")") + 46217 | std::string(" (") + min_cpp + std::string(")"); 46218 | return info_str; 46219 | } 46220 | 46221 | } // namespace information 46222 | 46223 | #ifdef exprtk_debug 46224 | #undef exprtk_debug 46225 | #endif 46226 | 46227 | #ifdef exprtk_error_location 46228 | #undef exprtk_error_location 46229 | #endif 46230 | 46231 | #ifdef exprtk_fallthrough 46232 | #undef exprtk_fallthrough 46233 | #endif 46234 | 46235 | #ifdef exprtk_override 46236 | #undef exprtk_override 46237 | #endif 46238 | 46239 | #ifdef exprtk_final 46240 | #undef exprtk_final 46241 | #endif 46242 | 46243 | #ifdef exprtk_delete 46244 | #undef exprtk_delete 46245 | #endif 46246 | 46247 | } // namespace exprtk 46248 | 46249 | #endif