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 expm1_impl(const T v, real_type_tag) 00958 | { 00959 | // return std::expm1<T>(v); 00960 | if (abs_impl(v,real_type_tag()) < T(0.00001)) 00961 | return v + (T(0.5) * v * v); 00962 | else 00963 | return std::exp(v) - T(1); 00964 | } 00965 | 00966 | template <typename T> 00967 | inline T expm1_impl(const T v, int_type_tag) 00968 | { 00969 | return T(std::exp<double>(v)) - T(1); 00970 | } 00971 | 00972 | template <typename T> 00973 | inline T nequal_impl(const T v0, const T v1, real_type_tag) 00974 | { 00975 | typedef real_type_tag rtg; 00976 | const T epsilon = epsilon_type<T>::value(); 00977 | 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); 00978 | } 00979 | 00980 | inline float nequal_impl(const float v0, const float v1, real_type_tag) 00981 | { 00982 | typedef real_type_tag rtg; 00983 | const float epsilon = epsilon_type<float>::value(); 00984 | 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; 00985 | } 00986 | 00987 | template <typename T> 00988 | inline T nequal_impl(const T v0, const T v1, int_type_tag) 00989 | { 00990 | return (v0 != v1) ? 1 : 0; 00991 | } 00992 | 00993 | template <typename T> 00994 | inline T modulus_impl(const T v0, const T v1, real_type_tag) 00995 | { 00996 | return std::fmod(v0,v1); 00997 | } 00998 | 00999 | template <typename T> 01000 | inline T modulus_impl(const T v0, const T v1, int_type_tag) 01001 | { 01002 | return v0 % v1; 01003 | } 01004 | 01005 | template <typename T> 01006 | inline T pow_impl(const T v0, const T v1, real_type_tag) 01007 | { 01008 | return std::pow(v0,v1); 01009 | } 01010 | 01011 | template <typename T> 01012 | inline T pow_impl(const T v0, const T v1, int_type_tag) 01013 | { 01014 | return std::pow(static_cast<double>(v0),static_cast<double>(v1)); 01015 | } 01016 | 01017 | template <typename T> 01018 | inline T logn_impl(const T v0, const T v1, real_type_tag) 01019 | { 01020 | return std::log(v0) / std::log(v1); 01021 | } 01022 | 01023 | template <typename T> 01024 | inline T logn_impl(const T v0, const T v1, int_type_tag) 01025 | { 01026 | return static_cast<T>(logn_impl<double>(static_cast<double>(v0),static_cast<double>(v1),real_type_tag())); 01027 | } 01028 | 01029 | template <typename T> 01030 | inline T log1p_impl(const T v, real_type_tag) 01031 | { 01032 | if (v > T(-1)) 01033 | { 01034 | if (abs_impl(v,real_type_tag()) > T(0.0001)) 01035 | { 01036 | return std::log(T(1) + v); 01037 | } 01038 | else 01039 | return (T(-0.5) * v + T(1)) * v; 01040 | } 01041 | 01042 | return std::numeric_limits<T>::quiet_NaN(); 01043 | } 01044 | 01045 | template <typename T> 01046 | inline T log1p_impl(const T v, int_type_tag) 01047 | { 01048 | if (v > T(-1)) 01049 | { 01050 | return std::log(T(1) + v); 01051 | } 01052 | 01053 | return std::numeric_limits<T>::quiet_NaN(); 01054 | } 01055 | 01056 | template <typename T> 01057 | inline T root_impl(const T v0, const T v1, real_type_tag) 01058 | { 01059 | if (v0 < T(0)) 01060 | { 01061 | return (v1 == trunc_impl(v1, real_type_tag())) && 01062 | (modulus_impl(v1, T(2), real_type_tag()) != T(0)) ? 01063 | -std::pow(abs_impl(v0, real_type_tag()), T(1) / v1) : 01064 | std::numeric_limits<double>::quiet_NaN(); 01065 | } 01066 | 01067 | return std::pow(v0, T(1) / v1); 01068 | } 01069 | 01070 | template <typename T> 01071 | inline T root_impl(const T v0, const T v1, int_type_tag) 01072 | { 01073 | return root_impl<double>(static_cast<double>(v0),static_cast<double>(v1),real_type_tag()); 01074 | } 01075 | 01076 | template <typename T> 01077 | inline T round_impl(const T v, real_type_tag) 01078 | { 01079 | return ((v < T(0)) ? std::ceil(v - T(0.5)) : std::floor(v + T(0.5))); 01080 | } 01081 | 01082 | template <typename T> 01083 | inline T roundn_impl(const T v0, const T v1, real_type_tag) 01084 | { 01085 | const int index = std::max<int>(0, std::min<int>(pow10_size - 1, static_cast<int>(std::floor(v1)))); 01086 | const T p10 = T(pow10[index]); 01087 | 01088 | if (v0 < T(0)) 01089 | return T(std::ceil ((v0 * p10) - T(0.5)) / p10); 01090 | else 01091 | return T(std::floor((v0 * p10) + T(0.5)) / p10); 01092 | } 01093 | 01094 | template <typename T> 01095 | inline T roundn_impl(const T v0, const T, int_type_tag) 01096 | { 01097 | return v0; 01098 | } 01099 | 01100 | template <typename T> 01101 | inline T hypot_impl(const T v0, const T v1, real_type_tag) 01102 | { 01103 | return std::sqrt((v0 * v0) + (v1 * v1)); 01104 | } 01105 | 01106 | template <typename T> 01107 | inline T hypot_impl(const T v0, const T v1, int_type_tag) 01108 | { 01109 | return static_cast<T>(std::sqrt(static_cast<double>((v0 * v0) + (v1 * v1)))); 01110 | } 01111 | 01112 | template <typename T> 01113 | inline T atan2_impl(const T v0, const T v1, real_type_tag) 01114 | { 01115 | return std::atan2(v0,v1); 01116 | } 01117 | 01118 | template <typename T> 01119 | inline T atan2_impl(const T, const T, int_type_tag) 01120 | { 01121 | return 0; 01122 | } 01123 | 01124 | template <typename T> 01125 | inline T shr_impl(const T v0, const T v1, real_type_tag) 01126 | { 01127 | return v0 * (T(1) / std::pow(T(2),static_cast<T>(static_cast<int>(v1)))); 01128 | } 01129 | 01130 | template <typename T> 01131 | inline T shr_impl(const T v0, const T v1, int_type_tag) 01132 | { 01133 | return v0 >> v1; 01134 | } 01135 | 01136 | template <typename T> 01137 | inline T shl_impl(const T v0, const T v1, real_type_tag) 01138 | { 01139 | return v0 * std::pow(T(2),static_cast<T>(static_cast<int>(v1))); 01140 | } 01141 | 01142 | template <typename T> 01143 | inline T shl_impl(const T v0, const T v1, int_type_tag) 01144 | { 01145 | return v0 << v1; 01146 | } 01147 | 01148 | template <typename T> 01149 | inline T sgn_impl(const T v, real_type_tag) 01150 | { 01151 | if (v > T(0)) return T(+1); 01152 | else if (v < T(0)) return T(-1); 01153 | else return T( 0); 01154 | } 01155 | 01156 | template <typename T> 01157 | inline T sgn_impl(const T v, int_type_tag) 01158 | { 01159 | if (v > T(0)) return T(+1); 01160 | else if (v < T(0)) return T(-1); 01161 | else return T( 0); 01162 | } 01163 | 01164 | template <typename T> 01165 | inline T and_impl(const T v0, const T v1, real_type_tag) 01166 | { 01167 | return (is_true_impl(v0) && is_true_impl(v1)) ? T(1) : T(0); 01168 | } 01169 | 01170 | template <typename T> 01171 | inline T and_impl(const T v0, const T v1, int_type_tag) 01172 | { 01173 | return v0 && v1; 01174 | } 01175 | 01176 | template <typename T> 01177 | inline T nand_impl(const T v0, const T v1, real_type_tag) 01178 | { 01179 | return (is_false_impl(v0) || is_false_impl(v1)) ? T(1) : T(0); 01180 | } 01181 | 01182 | template <typename T> 01183 | inline T nand_impl(const T v0, const T v1, int_type_tag) 01184 | { 01185 | return !(v0 && v1); 01186 | } 01187 | 01188 | template <typename T> 01189 | inline T or_impl(const T v0, const T v1, real_type_tag) 01190 | { 01191 | return (is_true_impl(v0) || is_true_impl(v1)) ? T(1) : T(0); 01192 | } 01193 | 01194 | template <typename T> 01195 | inline T or_impl(const T v0, const T v1, int_type_tag) 01196 | { 01197 | return (v0 || v1); 01198 | } 01199 | 01200 | template <typename T> 01201 | inline T nor_impl(const T v0, const T v1, real_type_tag) 01202 | { 01203 | return (is_false_impl(v0) && is_false_impl(v1)) ? T(1) : T(0); 01204 | } 01205 | 01206 | template <typename T> 01207 | inline T nor_impl(const T v0, const T v1, int_type_tag) 01208 | { 01209 | return !(v0 || v1); 01210 | } 01211 | 01212 | template <typename T> 01213 | inline T xor_impl(const T v0, const T v1, real_type_tag) 01214 | { 01215 | return (is_false_impl(v0) != is_false_impl(v1)) ? T(1) : T(0); 01216 | } 01217 | 01218 | template <typename T> 01219 | inline T xor_impl(const T v0, const T v1, int_type_tag) 01220 | { 01221 | return v0 ^ v1; 01222 | } 01223 | 01224 | template <typename T> 01225 | inline T xnor_impl(const T v0, const T v1, real_type_tag) 01226 | { 01227 | const bool v0_true = is_true_impl(v0); 01228 | const bool v1_true = is_true_impl(v1); 01229 | 01230 | if ((v0_true && v1_true) || (!v0_true && !v1_true)) 01231 | return T(1); 01232 | else 01233 | return T(0); 01234 | } 01235 | 01236 | template <typename T> 01237 | inline T xnor_impl(const T v0, const T v1, int_type_tag) 01238 | { 01239 | const bool v0_true = is_true_impl(v0); 01240 | const bool v1_true = is_true_impl(v1); 01241 | 01242 | if ((v0_true && v1_true) || (!v0_true && !v1_true)) 01243 | return T(1); 01244 | else 01245 | return T(0); 01246 | } 01247 | 01248 | #if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || !defined(_MSC_VER) 01249 | #define exprtk_define_erf(TT, impl) \ 01250 | inline TT erf_impl(const TT v) { return impl(v); } \ 01251 | 01252 | exprtk_define_erf(float , ::erff) 01253 | exprtk_define_erf(double , ::erf ) 01254 | exprtk_define_erf(long double, ::erfl) 01255 | #undef exprtk_define_erf 01256 | #endif 01257 | 01258 | template <typename T> 01259 | inline T erf_impl(const T v, real_type_tag) 01260 | { 01261 | #if defined(_MSC_VER) && (_MSC_VER < 1900) 01262 | // Credits: Abramowitz & Stegun Equations 7.1.25-28 01263 | static const T c[] = 01264 | { 01265 | T( 1.26551223), T(1.00002368), 01266 | T( 0.37409196), T(0.09678418), 01267 | T(-0.18628806), T(0.27886807), 01268 | T(-1.13520398), T(1.48851587), 01269 | T(-0.82215223), T(0.17087277) 01270 | }; 01271 | 01272 | const T t = T(1) / (T(1) + T(0.5) * abs_impl(v,real_type_tag())); 01273 | 01274 | const T result = T(1) - t * std::exp((-v * v) - 01275 | c[0] + t * (c[1] + t * 01276 | (c[2] + t * (c[3] + t * 01277 | (c[4] + t * (c[5] + t * 01278 | (c[6] + t * (c[7] + t * 01279 | (c[8] + t * (c[9])))))))))); 01280 | 01281 | return (v >= T(0)) ? result : -result; 01282 | #else 01283 | return erf_impl(v); 01284 | #endif 01285 | } 01286 | 01287 | template <typename T> 01288 | inline T erf_impl(const T v, int_type_tag) 01289 | { 01290 | return erf_impl(static_cast<double>(v),real_type_tag()); 01291 | } 01292 | 01293 | #if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || !defined(_MSC_VER) 01294 | #define exprtk_define_erfc(TT, impl) \ 01295 | inline TT erfc_impl(const TT v) { return impl(v); } \ 01296 | 01297 | exprtk_define_erfc(float ,::erfcf) 01298 | exprtk_define_erfc(double ,::erfc ) 01299 | exprtk_define_erfc(long double,::erfcl) 01300 | #undef exprtk_define_erfc 01301 | #endif 01302 | 01303 | template <typename T> 01304 | inline T erfc_impl(const T v, real_type_tag) 01305 | { 01306 | #if defined(_MSC_VER) && (_MSC_VER < 1900) 01307 | return T(1) - erf_impl(v,real_type_tag()); 01308 | #else 01309 | return erfc_impl(v); 01310 | #endif 01311 | } 01312 | 01313 | template <typename T> 01314 | inline T erfc_impl(const T v, int_type_tag) 01315 | { 01316 | return erfc_impl(static_cast<double>(v),real_type_tag()); 01317 | } 01318 | 01319 | template <typename T> 01320 | inline T ncdf_impl(const T v, real_type_tag) 01321 | { 01322 | return T(0.5) * erfc_impl(-(v / T(numeric::constant::sqrt2)),real_type_tag()); 01323 | } 01324 | 01325 | template <typename T> 01326 | inline T ncdf_impl(const T v, int_type_tag) 01327 | { 01328 | return ncdf_impl(static_cast<double>(v),real_type_tag()); 01329 | } 01330 | 01331 | template <typename T> 01332 | inline T sinc_impl(const T v, real_type_tag) 01333 | { 01334 | if (std::abs(v) >= std::numeric_limits<T>::epsilon()) 01335 | return(std::sin(v) / v); 01336 | else 01337 | return T(1); 01338 | } 01339 | 01340 | template <typename T> 01341 | inline T sinc_impl(const T v, int_type_tag) 01342 | { 01343 | return sinc_impl(static_cast<double>(v),real_type_tag()); 01344 | } 01345 | 01346 | #if __cplusplus >= 201103L 01347 | template <typename T> 01348 | inline T acosh_impl(const T v, real_type_tag) 01349 | { 01350 | return std::acosh(v); 01351 | } 01352 | 01353 | template <typename T> 01354 | inline T asinh_impl(const T v, real_type_tag) 01355 | { 01356 | return std::asinh(v); 01357 | } 01358 | 01359 | template <typename T> 01360 | inline T atanh_impl(const T v, real_type_tag) 01361 | { 01362 | return std::atanh(v); 01363 | } 01364 | 01365 | template <typename T> 01366 | inline T trunc_impl(const T v, real_type_tag) 01367 | { 01368 | return std::trunc(v); 01369 | } 01370 | #else 01371 | template <typename T> 01372 | inline T acosh_impl(const T v, real_type_tag) 01373 | { 01374 | return std::log(v + std::sqrt((v * v) - T(1))); 01375 | } 01376 | 01377 | template <typename T> 01378 | inline T asinh_impl(const T v, real_type_tag) 01379 | { 01380 | return std::log(v + std::sqrt((v * v) + T(1))); 01381 | } 01382 | 01383 | template <typename T> 01384 | inline T atanh_impl(const T v, real_type_tag) 01385 | { 01386 | return (std::log(T(1) + v) - std::log(T(1) - v)) / T(2); 01387 | } 01388 | 01389 | template <typename T> 01390 | inline T trunc_impl(const T v, real_type_tag) 01391 | { 01392 | return T(static_cast<long long>(v)); 01393 | } 01394 | #endif 01395 | 01396 | template <typename T> inline T acos_impl(const T v, real_type_tag) { return std::acos (v); } 01397 | template <typename T> inline T asin_impl(const T v, real_type_tag) { return std::asin (v); } 01398 | template <typename T> inline T atan_impl(const T v, real_type_tag) { return std::atan (v); } 01399 | template <typename T> inline T ceil_impl(const T v, real_type_tag) { return std::ceil (v); } 01400 | template <typename T> inline T cos_impl(const T v, real_type_tag) { return std::cos (v); } 01401 | template <typename T> inline T cosh_impl(const T v, real_type_tag) { return std::cosh (v); } 01402 | template <typename T> inline T exp_impl(const T v, real_type_tag) { return std::exp (v); } 01403 | template <typename T> inline T floor_impl(const T v, real_type_tag) { return std::floor(v); } 01404 | template <typename T> inline T log_impl(const T v, real_type_tag) { return std::log (v); } 01405 | template <typename T> inline T log10_impl(const T v, real_type_tag) { return std::log10(v); } 01406 | template <typename T> inline T log2_impl(const T v, real_type_tag) { return std::log(v)/T(numeric::constant::log2); } 01407 | template <typename T> inline T neg_impl(const T v, real_type_tag) { return -v; } 01408 | template <typename T> inline T pos_impl(const T v, real_type_tag) { return +v; } 01409 | template <typename T> inline T sin_impl(const T v, real_type_tag) { return std::sin (v); } 01410 | template <typename T> inline T sinh_impl(const T v, real_type_tag) { return std::sinh (v); } 01411 | template <typename T> inline T sqrt_impl(const T v, real_type_tag) { return std::sqrt (v); } 01412 | template <typename T> inline T tan_impl(const T v, real_type_tag) { return std::tan (v); } 01413 | template <typename T> inline T tanh_impl(const T v, real_type_tag) { return std::tanh (v); } 01414 | template <typename T> inline T cot_impl(const T v, real_type_tag) { return T(1) / std::tan(v); } 01415 | template <typename T> inline T sec_impl(const T v, real_type_tag) { return T(1) / std::cos(v); } 01416 | template <typename T> inline T csc_impl(const T v, real_type_tag) { return T(1) / std::sin(v); } 01417 | template <typename T> inline T r2d_impl(const T v, real_type_tag) { return (v * T(numeric::constant::_180_pi)); } 01418 | template <typename T> inline T d2r_impl(const T v, real_type_tag) { return (v * T(numeric::constant::pi_180)); } 01419 | template <typename T> inline T d2g_impl(const T v, real_type_tag) { return (v * T(10.0/9.0)); } 01420 | template <typename T> inline T g2d_impl(const T v, real_type_tag) { return (v * T(9.0/10.0)); } 01421 | 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)); } 01422 | template <typename T> inline T frac_impl(const T v, real_type_tag) { return (v - trunc_impl(v,real_type_tag())); } 01423 | 01424 | template <typename T> inline T const_pi_impl(real_type_tag) { return T(numeric::constant::pi); } 01425 | template <typename T> inline T const_e_impl(real_type_tag) { return T(numeric::constant::e); } 01426 | template <typename T> inline T const_qnan_impl(real_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01427 | 01428 | template <typename T> inline T abs_impl(const T v, int_type_tag) { return ((v >= T(0)) ? v : -v); } 01429 | template <typename T> inline T exp_impl(const T v, int_type_tag) { return std::exp (v); } 01430 | template <typename T> inline T log_impl(const T v, int_type_tag) { return std::log (v); } 01431 | template <typename T> inline T log10_impl(const T v, int_type_tag) { return std::log10(v); } 01432 | template <typename T> inline T log2_impl(const T v, int_type_tag) { return std::log(v)/T(numeric::constant::log2); } 01433 | template <typename T> inline T neg_impl(const T v, int_type_tag) { return -v; } 01434 | template <typename T> inline T pos_impl(const T v, int_type_tag) { return +v; } 01435 | template <typename T> inline T ceil_impl(const T v, int_type_tag) { return v; } 01436 | template <typename T> inline T floor_impl(const T v, int_type_tag) { return v; } 01437 | template <typename T> inline T round_impl(const T v, int_type_tag) { return v; } 01438 | template <typename T> inline T notl_impl(const T v, int_type_tag) { return !v; } 01439 | template <typename T> inline T sqrt_impl(const T v, int_type_tag) { return std::sqrt (v); } 01440 | template <typename T> inline T frac_impl(const T , int_type_tag) { return T(0); } 01441 | template <typename T> inline T trunc_impl(const T v, int_type_tag) { return v; } 01442 | template <typename T> inline T acos_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01443 | template <typename T> inline T acosh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01444 | template <typename T> inline T asin_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01445 | template <typename T> inline T asinh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01446 | template <typename T> inline T atan_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01447 | template <typename T> inline T atanh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01448 | template <typename T> inline T cos_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01449 | template <typename T> inline T cosh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01450 | template <typename T> inline T sin_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01451 | template <typename T> inline T sinh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01452 | template <typename T> inline T tan_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01453 | template <typename T> inline T tanh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01454 | template <typename T> inline T cot_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01455 | template <typename T> inline T sec_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01456 | template <typename T> inline T csc_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } 01457 | 01458 | template <typename T> 01459 | inline bool is_integer_impl(const T& v, real_type_tag) 01460 | { 01461 | return std::equal_to<T>()(T(0),std::fmod(v,T(1))); 01462 | } 01463 | 01464 | template <typename T> 01465 | inline bool is_integer_impl(const T&, int_type_tag) 01466 | { 01467 | return true; 01468 | } 01469 | } 01470 | 01471 | template <typename Type> 01472 | struct numeric_info { enum { length = 0, size = 32, bound_length = 0, min_exp = 0, max_exp = 0 }; }; 01473 | 01474 | template <> struct numeric_info<int > { enum { length = 10, size = 16, bound_length = 9 }; }; 01475 | template <> struct numeric_info<float > { enum { min_exp = -38, max_exp = +38 }; }; 01476 | template <> struct numeric_info<double > { enum { min_exp = -308, max_exp = +308 }; }; 01477 | template <> struct numeric_info<long double> { enum { min_exp = -308, max_exp = +308 }; }; 01478 | 01479 | template <typename T> 01480 | inline int to_int32(const T v) 01481 | { 01482 | const typename details::number_type<T>::type num_type; 01483 | return to_int32_impl(v, num_type); 01484 | } 01485 | 01486 | template <typename T> 01487 | inline _int64_t to_int64(const T v) 01488 | { 01489 | const typename details::number_type<T>::type num_type; 01490 | return to_int64_impl(v, num_type); 01491 | } 01492 | 01493 | template <typename T> 01494 | inline _uint64_t to_uint64(const T v) 01495 | { 01496 | const typename details::number_type<T>::type num_type; 01497 | return to_uint64_impl(v, num_type); 01498 | } 01499 | 01500 | template <typename T> 01501 | inline bool is_nan(const T v) 01502 | { 01503 | const typename details::number_type<T>::type num_type; 01504 | return is_nan_impl(v, num_type); 01505 | } 01506 | 01507 | template <typename T> 01508 | inline T min(const T v0, const T v1) 01509 | { 01510 | const typename details::number_type<T>::type num_type; 01511 | return min_impl(v0, v1, num_type); 01512 | } 01513 | 01514 | template <typename T> 01515 | inline T max(const T v0, const T v1) 01516 | { 01517 | const typename details::number_type<T>::type num_type; 01518 | return max_impl(v0, v1, num_type); 01519 | } 01520 | 01521 | template <typename T> 01522 | inline T equal(const T v0, const T v1) 01523 | { 01524 | const typename details::number_type<T>::type num_type; 01525 | return equal_impl(v0, v1, num_type); 01526 | } 01527 | 01528 | template <typename T> 01529 | inline T nequal(const T v0, const T v1) 01530 | { 01531 | const typename details::number_type<T>::type num_type; 01532 | return nequal_impl(v0, v1, num_type); 01533 | } 01534 | 01535 | template <typename T> 01536 | inline T modulus(const T v0, const T v1) 01537 | { 01538 | const typename details::number_type<T>::type num_type; 01539 | return modulus_impl(v0, v1, num_type); 01540 | } 01541 | 01542 | template <typename T> 01543 | inline T pow(const T v0, const T v1) 01544 | { 01545 | const typename details::number_type<T>::type num_type; 01546 | return pow_impl(v0, v1, num_type); 01547 | } 01548 | 01549 | template <typename T> 01550 | inline T logn(const T v0, const T v1) 01551 | { 01552 | const typename details::number_type<T>::type num_type; 01553 | return logn_impl(v0, v1, num_type); 01554 | } 01555 | 01556 | template <typename T> 01557 | inline T root(const T v0, const T v1) 01558 | { 01559 | const typename details::number_type<T>::type num_type; 01560 | return root_impl(v0, v1, num_type); 01561 | } 01562 | 01563 | template <typename T> 01564 | inline T roundn(const T v0, const T v1) 01565 | { 01566 | const typename details::number_type<T>::type num_type; 01567 | return roundn_impl(v0, v1, num_type); 01568 | } 01569 | 01570 | template <typename T> 01571 | inline T hypot(const T v0, const T v1) 01572 | { 01573 | const typename details::number_type<T>::type num_type; 01574 | return hypot_impl(v0, v1, num_type); 01575 | } 01576 | 01577 | template <typename T> 01578 | inline T atan2(const T v0, const T v1) 01579 | { 01580 | const typename details::number_type<T>::type num_type; 01581 | return atan2_impl(v0, v1, num_type); 01582 | } 01583 | 01584 | template <typename T> 01585 | inline T shr(const T v0, const T v1) 01586 | { 01587 | const typename details::number_type<T>::type num_type; 01588 | return shr_impl(v0, v1, num_type); 01589 | } 01590 | 01591 | template <typename T> 01592 | inline T shl(const T v0, const T v1) 01593 | { 01594 | const typename details::number_type<T>::type num_type; 01595 | return shl_impl(v0, v1, num_type); 01596 | } 01597 | 01598 | template <typename T> 01599 | inline T and_opr(const T v0, const T v1) 01600 | { 01601 | const typename details::number_type<T>::type num_type; 01602 | return and_impl(v0, v1, num_type); 01603 | } 01604 | 01605 | template <typename T> 01606 | inline T nand_opr(const T v0, const T v1) 01607 | { 01608 | const typename details::number_type<T>::type num_type; 01609 | return nand_impl(v0, v1, num_type); 01610 | } 01611 | 01612 | template <typename T> 01613 | inline T or_opr(const T v0, const T v1) 01614 | { 01615 | const typename details::number_type<T>::type num_type; 01616 | return or_impl(v0, v1, num_type); 01617 | } 01618 | 01619 | template <typename T> 01620 | inline T nor_opr(const T v0, const T v1) 01621 | { 01622 | const typename details::number_type<T>::type num_type; 01623 | return nor_impl(v0, v1, num_type); 01624 | } 01625 | 01626 | template <typename T> 01627 | inline T xor_opr(const T v0, const T v1) 01628 | { 01629 | const typename details::number_type<T>::type num_type; 01630 | return xor_impl(v0, v1, num_type); 01631 | } 01632 | 01633 | template <typename T> 01634 | inline T xnor_opr(const T v0, const T v1) 01635 | { 01636 | const typename details::number_type<T>::type num_type; 01637 | return xnor_impl(v0, v1, num_type); 01638 | } 01639 | 01640 | template <typename T> 01641 | inline bool is_integer(const T v) 01642 | { 01643 | const typename details::number_type<T>::type num_type; 01644 | return is_integer_impl(v, num_type); 01645 | } 01646 | 01647 | template <typename T, unsigned int N> 01648 | struct fast_exp 01649 | { 01650 | static inline T result(T v) 01651 | { 01652 | unsigned int k = N; 01653 | T l = T(1); 01654 | 01655 | while (k) 01656 | { 01657 | if (1 == (k % 2)) 01658 | { 01659 | l *= v; 01660 | --k; 01661 | } 01662 | 01663 | v *= v; 01664 | k /= 2; 01665 | } 01666 | 01667 | return l; 01668 | } 01669 | }; 01670 | 01671 | 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; } }; 01672 | template <typename T> struct fast_exp<T, 9> { static inline T result(const T v) { return fast_exp<T,8>::result(v) * v; } }; 01673 | 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; } }; 01674 | template <typename T> struct fast_exp<T, 7> { static inline T result(const T v) { return fast_exp<T,6>::result(v) * v; } }; 01675 | 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; } }; 01676 | template <typename T> struct fast_exp<T, 5> { static inline T result(const T v) { return fast_exp<T,4>::result(v) * v; } }; 01677 | 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; } }; 01678 | template <typename T> struct fast_exp<T, 3> { static inline T result(const T v) { return v * v * v; } }; 01679 | template <typename T> struct fast_exp<T, 2> { static inline T result(const T v) { return v * v; } }; 01680 | template <typename T> struct fast_exp<T, 1> { static inline T result(const T v) { return v; } }; 01681 | template <typename T> struct fast_exp<T, 0> { static inline T result(const T ) { return T(1); } }; 01682 | 01683 | #define exprtk_define_unary_function(FunctionName) \ 01684 | template <typename T> \ 01685 | inline T FunctionName (const T v) \ 01686 | { \ 01687 | const typename details::number_type<T>::type num_type; \ 01688 | return FunctionName##_impl(v,num_type); \ 01689 | } \ 01690 | 01691 | exprtk_define_unary_function(abs ) 01692 | exprtk_define_unary_function(acos ) 01693 | exprtk_define_unary_function(acosh) 01694 | exprtk_define_unary_function(asin ) 01695 | exprtk_define_unary_function(asinh) 01696 | exprtk_define_unary_function(atan ) 01697 | exprtk_define_unary_function(atanh) 01698 | exprtk_define_unary_function(ceil ) 01699 | exprtk_define_unary_function(cos ) 01700 | exprtk_define_unary_function(cosh ) 01701 | exprtk_define_unary_function(exp ) 01702 | exprtk_define_unary_function(expm1) 01703 | exprtk_define_unary_function(floor) 01704 | exprtk_define_unary_function(log ) 01705 | exprtk_define_unary_function(log10) 01706 | exprtk_define_unary_function(log2 ) 01707 | exprtk_define_unary_function(log1p) 01708 | exprtk_define_unary_function(neg ) 01709 | exprtk_define_unary_function(pos ) 01710 | exprtk_define_unary_function(round) 01711 | exprtk_define_unary_function(sin ) 01712 | exprtk_define_unary_function(sinc ) 01713 | exprtk_define_unary_function(sinh ) 01714 | exprtk_define_unary_function(sqrt ) 01715 | exprtk_define_unary_function(tan ) 01716 | exprtk_define_unary_function(tanh ) 01717 | exprtk_define_unary_function(cot ) 01718 | exprtk_define_unary_function(sec ) 01719 | exprtk_define_unary_function(csc ) 01720 | exprtk_define_unary_function(r2d ) 01721 | exprtk_define_unary_function(d2r ) 01722 | exprtk_define_unary_function(d2g ) 01723 | exprtk_define_unary_function(g2d ) 01724 | exprtk_define_unary_function(notl ) 01725 | exprtk_define_unary_function(sgn ) 01726 | exprtk_define_unary_function(erf ) 01727 | exprtk_define_unary_function(erfc ) 01728 | exprtk_define_unary_function(ncdf ) 01729 | exprtk_define_unary_function(frac ) 01730 | exprtk_define_unary_function(trunc) 01731 | #undef exprtk_define_unary_function 01732 | } 01733 | 01734 | template <typename T> 01735 | inline T compute_pow10(T d, const int exponent) 01736 | { 01737 | static const double fract10[] = 01738 | { 01739 | 0.0, 01740 | 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, 01741 | 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, 01742 | 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, 01743 | 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, 01744 | 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, 01745 | 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, 01746 | 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, 01747 | 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, 01748 | 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, 01749 | 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, 01750 | 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, 01751 | 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, 01752 | 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, 01753 | 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, 01754 | 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, 01755 | 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, 01756 | 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, 01757 | 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, 01758 | 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, 01759 | 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, 01760 | 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, 01761 | 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, 01762 | 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, 01763 | 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, 01764 | 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, 01765 | 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, 01766 | 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, 01767 | 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, 01768 | 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, 01769 | 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, 01770 | 1.0E+301, 1.0E+302, 1.0E+303, 1.0E+304, 1.0E+305, 1.0E+306, 1.0E+307, 1.0E+308 01771 | }; 01772 | 01773 | static const int fract10_size = static_cast<int>(sizeof(fract10) / sizeof(double)); 01774 | 01775 | const int e = std::abs(exponent); 01776 | 01777 | if (exponent >= std::numeric_limits<T>::min_exponent10) 01778 | { 01779 | if (e < fract10_size) 01780 | { 01781 | if (exponent > 0) 01782 | return T(d * fract10[e]); 01783 | else 01784 | return T(d / fract10[e]); 01785 | } 01786 | else 01787 | return T(d * std::pow(10.0, 10.0 * exponent)); 01788 | } 01789 | else 01790 | { 01791 | d /= T(fract10[ -std::numeric_limits<T>::min_exponent10]); 01792 | return T(d / fract10[-exponent + std::numeric_limits<T>::min_exponent10]); 01793 | } 01794 | } 01795 | 01796 | template <typename Iterator, typename T> 01797 | inline bool string_to_type_converter_impl_ref(Iterator& itr, const Iterator end, T& result) 01798 | { 01799 | if (itr == end) 01800 | return false; 01801 | 01802 | const bool negative = ('-' == (*itr)); 01803 | 01804 | if (negative || ('+' == (*itr))) 01805 | { 01806 | if (end == ++itr) 01807 | return false; 01808 | } 01809 | 01810 | static const uchar_t zero = static_cast<uchar_t>('0'); 01811 | 01812 | while ((end != itr) && (zero == (*itr))) ++itr; 01813 | 01814 | bool return_result = true; 01815 | unsigned int digit = 0; 01816 | const std::size_t length = static_cast<std::size_t>(std::distance(itr,end)); 01817 | 01818 | if (length <= 4) 01819 | { 01820 | switch (length) 01821 | { 01822 | #ifdef exprtk_use_lut 01823 | 01824 | #define exprtk_process_digit \ 01825 | if ((digit = details::digit_table[(int)*itr++]) < 10) \ 01826 | result = result * 10 + (digit); \ 01827 | else \ 01828 | { \ 01829 | return_result = false; \ 01830 | break; \ 01831 | } \ 01832 | exprtk_fallthrough \ 01833 | 01834 | #else 01835 | 01836 | #define exprtk_process_digit \ 01837 | if ((digit = (*itr++ - zero)) < 10) \ 01838 | result = result * T(10) + digit; \ 01839 | else \ 01840 | { \ 01841 | return_result = false; \ 01842 | break; \ 01843 | } \ 01844 | exprtk_fallthrough \ 01845 | 01846 | #endif 01847 | 01848 | case 4 : exprtk_process_digit 01849 | case 3 : exprtk_process_digit 01850 | case 2 : exprtk_process_digit 01851 | case 1 : if ((digit = (*itr - zero))>= 10) 01852 | { 01853 | digit = 0; 01854 | return_result = false; 01855 | } 01856 | 01857 | #undef exprtk_process_digit 01858 | } 01859 | } 01860 | else 01861 | return_result = false; 01862 | 01863 | if (length && return_result) 01864 | { 01865 | result = result * 10 + static_cast<T>(digit); 01866 | ++itr; 01867 | } 01868 | 01869 | result = negative ? -result : result; 01870 | return return_result; 01871 | } 01872 | 01873 | template <typename Iterator, typename T> 01874 | static inline bool parse_nan(Iterator& itr, const Iterator end, T& t) 01875 | { 01876 | typedef typename std::iterator_traits<Iterator>::value_type type; 01877 | 01878 | static const std::size_t nan_length = 3; 01879 | 01880 | if (std::distance(itr,end) != static_cast<int>(nan_length)) 01881 | return false; 01882 | 01883 | if (static_cast<type>('n') == (*itr)) 01884 | { 01885 | if ( 01886 | (static_cast<type>('a') != *(itr + 1)) || 01887 | (static_cast<type>('n') != *(itr + 2)) 01888 | ) 01889 | { 01890 | return false; 01891 | } 01892 | } 01893 | else if ( 01894 | (static_cast<type>('A') != *(itr + 1)) || 01895 | (static_cast<type>('N') != *(itr + 2)) 01896 | ) 01897 | { 01898 | return false; 01899 | } 01900 | 01901 | t = std::numeric_limits<T>::quiet_NaN(); 01902 | 01903 | return true; 01904 | } 01905 | 01906 | template <typename Iterator, typename T> 01907 | static inline bool parse_inf(Iterator& itr, const Iterator end, T& t, const bool negative) 01908 | { 01909 | static const char_t inf_uc[] = "INFINITY" 01910 | static const char_t inf_lc[] = "infinity" 01911 | static const std::size_t inf_length = 8; 01912 | 01913 | const std::size_t length = static_cast<std::size_t>(std::distance(itr,end)); 01914 | 01915 | if ((3 != length) && (inf_length != length)) 01916 | return false; 01917 | 01918 | char_cptr inf_itr = ('i' == (*itr)) ? inf_lc : inf_uc; 01919 | 01920 | while (end != itr) 01921 | { 01922 | if (*inf_itr == static_cast<char_t>(*itr)) 01923 | { 01924 | ++itr; 01925 | ++inf_itr; 01926 | continue; 01927 | } 01928 | else 01929 | return false; 01930 | } 01931 | 01932 | if (negative) 01933 | t = -std::numeric_limits<T>::infinity(); 01934 | else 01935 | t = std::numeric_limits<T>::infinity(); 01936 | 01937 | return true; 01938 | } 01939 | 01940 | template <typename T> 01941 | inline bool valid_exponent(const int exponent, numeric::details::real_type_tag) 01942 | { 01943 | using namespace details::numeric; 01944 | return (numeric_info<T>::min_exp <= exponent) && (exponent <= numeric_info<T>::max_exp); 01945 | } 01946 | 01947 | template <typename Iterator, typename T> 01948 | inline bool string_to_real(Iterator& itr_external, const Iterator end, T& t, numeric::details::real_type_tag) 01949 | { 01950 | if (end == itr_external) return false; 01951 | 01952 | Iterator itr = itr_external; 01953 | 01954 | T d = T(0); 01955 | 01956 | const bool negative = ('-' == (*itr)); 01957 | 01958 | if (negative || '+' == (*itr)) 01959 | { 01960 | if (end == ++itr) 01961 | return false; 01962 | } 01963 | 01964 | bool instate = false; 01965 | 01966 | static const char_t zero = static_cast<uchar_t>('0'); 01967 | 01968 | #define parse_digit_1(d) \ 01969 | if ((digit = (*itr - zero)) < 10) \ 01970 | { d = d * T(10) + digit; } \ 01971 | else \ 01972 | { break; } \ 01973 | if (end == ++itr) break; \ 01974 | 01975 | #define parse_digit_2(d) \ 01976 | if ((digit = (*itr - zero)) < 10) \ 01977 | { d = d * T(10) + digit; } \ 01978 | else \ 01979 | { break; } \ 01980 | ++itr; \ 01981 | 01982 | if ('.' != (*itr)) 01983 | { 01984 | const Iterator curr = itr; 01985 | 01986 | while ((end != itr) && (zero == (*itr))) ++itr; 01987 | 01988 | while (end != itr) 01989 | { 01990 | unsigned int digit; 01991 | parse_digit_1(d) 01992 | parse_digit_1(d) 01993 | parse_digit_2(d) 01994 | } 01995 | 01996 | if (curr != itr) instate = true; 01997 | } 01998 | 01999 | int exponent = 0; 02000 | 02001 | if (end != itr) 02002 | { 02003 | if ('.' == (*itr)) 02004 | { 02005 | const Iterator curr = ++itr; 02006 | T tmp_d = T(0); 02007 | 02008 | while (end != itr) 02009 | { 02010 | unsigned int digit; 02011 | parse_digit_1(tmp_d) 02012 | parse_digit_1(tmp_d) 02013 | parse_digit_2(tmp_d) 02014 | } 02015 | 02016 | if (curr != itr) 02017 | { 02018 | instate = true; 02019 | 02020 | const int frac_exponent = static_cast<int>(-std::distance(curr, itr)); 02021 | 02022 | if (!valid_exponent<T>(frac_exponent, numeric::details::real_type_tag())) 02023 | return false; 02024 | 02025 | d += compute_pow10(tmp_d, frac_exponent); 02026 | } 02027 | 02028 | #undef parse_digit_1 02029 | #undef parse_digit_2 02030 | } 02031 | 02032 | if (end != itr) 02033 | { 02034 | typename std::iterator_traits<Iterator>::value_type c = (*itr); 02035 | 02036 | if (('e' == c) || ('E' == c)) 02037 | { 02038 | int exp = 0; 02039 | 02040 | if (!details::string_to_type_converter_impl_ref(++itr, end, exp)) 02041 | { 02042 | if (end == itr) 02043 | return false; 02044 | else 02045 | c = (*itr); 02046 | } 02047 | 02048 | exponent += exp; 02049 | } 02050 | 02051 | if (end != itr) 02052 | { 02053 | if (('f' == c) || ('F' == c) || ('l' == c) || ('L' == c)) 02054 | ++itr; 02055 | else if ('#' == c) 02056 | { 02057 | if (end == ++itr) 02058 | return false; 02059 | else if (('I' <= (*itr)) && ((*itr) <= 'n')) 02060 | { 02061 | if (('i' == (*itr)) || ('I' == (*itr))) 02062 | { 02063 | return parse_inf(itr, end, t, negative); 02064 | } 02065 | else if (('n' == (*itr)) || ('N' == (*itr))) 02066 | { 02067 | return parse_nan(itr, end, t); 02068 | } 02069 | else 02070 | return false; 02071 | } 02072 | else 02073 | return false; 02074 | } 02075 | else if (('I' <= (*itr)) && ((*itr) <= 'n')) 02076 | { 02077 | if (('i' == (*itr)) || ('I' == (*itr))) 02078 | { 02079 | return parse_inf(itr, end, t, negative); 02080 | } 02081 | else if (('n' == (*itr)) || ('N' == (*itr))) 02082 | { 02083 | return parse_nan(itr, end, t); 02084 | } 02085 | else 02086 | return false; 02087 | } 02088 | else 02089 | return false; 02090 | } 02091 | } 02092 | } 02093 | 02094 | if ((end != itr) || (!instate)) 02095 | return false; 02096 | else if (!valid_exponent<T>(exponent, numeric::details::real_type_tag())) 02097 | return false; 02098 | else if (exponent) 02099 | d = compute_pow10(d,exponent); 02100 | 02101 | t = static_cast<T>((negative) ? -d : d); 02102 | return true; 02103 | } 02104 | 02105 | template <typename T> 02106 | inline bool string_to_real(const std::string& s, T& t) 02107 | { 02108 | const typename numeric::details::number_type<T>::type num_type; 02109 | 02110 | char_cptr begin = s.data(); 02111 | char_cptr end = s.data() + s.size(); 02112 | 02113 | return string_to_real(begin, end, t, num_type); 02114 | } 02115 | 02116 | template <typename T> 02117 | struct functor_t 02118 | { 02119 | /* 02120 | Note: The following definitions for Type, may require tweaking 02121 | based on the compiler and target architecture. The benchmark 02122 | should provide enough information to make the right choice. 02123 | */ 02124 | //typedef T Type; 02125 | //typedef const T Type; 02126 | typedef const T& Type; 02127 | typedef T& RefType; 02128 | typedef T (*qfunc_t)(Type t0, Type t1, Type t2, Type t3); 02129 | typedef T (*tfunc_t)(Type t0, Type t1, Type t2); 02130 | typedef T (*bfunc_t)(Type t0, Type t1); 02131 | typedef T (*ufunc_t)(Type t0); 02132 | }; 02133 | 02134 | } // namespace details 02135 | 02136 | struct loop_runtime_check 02137 | { 02138 | enum loop_types 02139 | { 02140 | e_invalid = 0, 02141 | e_for_loop = 1, 02142 | e_while_loop = 2, 02143 | e_repeat_until_loop = 4, 02144 | e_all_loops = 7 02145 | }; 02146 | 02147 | enum violation_type 02148 | { 02149 | e_unknown = 0, 02150 | e_iteration_count = 1, 02151 | e_timeout = 2 02152 | }; 02153 | 02154 | loop_types loop_set; 02155 | 02156 | loop_runtime_check() 02157 | : loop_set(e_invalid) 02158 | , max_loop_iterations(0) 02159 | {} 02160 | 02161 | details::_uint64_t max_loop_iterations; 02162 | 02163 | struct violation_context 02164 | { 02165 | loop_types loop; 02166 | violation_type violation; 02167 | details::_uint64_t iteration_count; 02168 | }; 02169 | 02170 | virtual bool check() 02171 | { 02172 | return true; 02173 | } 02174 | 02175 | virtual void handle_runtime_violation(const violation_context&) 02176 | { 02177 | throw std::runtime_error("ExprTk Loop runtime violation."); 02178 | } 02179 | 02180 | virtual ~loop_runtime_check() 02181 | {} 02182 | }; 02183 | 02184 | typedef loop_runtime_check* loop_runtime_check_ptr; 02185 | 02186 | struct vector_access_runtime_check 02187 | { 02188 | struct violation_context 02189 | { 02190 | void* base_ptr; 02191 | void* end_ptr; 02192 | void* access_ptr; 02193 | std::size_t type_size; 02194 | }; 02195 | 02196 | virtual ~vector_access_runtime_check() 02197 | {} 02198 | 02199 | virtual bool handle_runtime_violation(violation_context& /*context*/) 02200 | { 02201 | throw std::runtime_error("ExprTk runtime vector access violation."); 02202 | #if !defined(_MSC_VER) && !defined(__NVCOMPILER) 02203 | return false; 02204 | #endif 02205 | } 02206 | }; 02207 | 02208 | typedef vector_access_runtime_check* vector_access_runtime_check_ptr; 02209 | 02210 | struct assert_check 02211 | { 02212 | struct assert_context 02213 | { 02214 | std::string condition; 02215 | std::string message; 02216 | std::string id; 02217 | std::size_t offet; 02218 | }; 02219 | 02220 | virtual ~assert_check() 02221 | {} 02222 | 02223 | virtual void handle_assert(const assert_context& /*context*/) 02224 | { 02225 | } 02226 | }; 02227 | 02228 | typedef assert_check* assert_check_ptr; 02229 | 02230 | struct compilation_check 02231 | { 02232 | struct compilation_context 02233 | { 02234 | std::string error_message; 02235 | }; 02236 | 02237 | virtual bool continue_compilation(compilation_context& /*context*/) = 0; 02238 | 02239 | virtual ~compilation_check() 02240 | {} 02241 | }; 02242 | 02243 | typedef compilation_check* compilation_check_ptr; 02244 | 02245 | namespace lexer 02246 | { 02247 | struct token 02248 | { 02249 | enum token_type 02250 | { 02251 | e_none = 0, e_error = 1, e_err_symbol = 2, 02252 | e_err_number = 3, e_err_string = 4, e_err_sfunc = 5, 02253 | e_eof = 6, e_number = 7, e_symbol = 8, 02254 | e_string = 9, e_assign = 10, e_addass = 11, 02255 | e_subass = 12, e_mulass = 13, e_divass = 14, 02256 | e_modass = 15, e_shr = 16, e_shl = 17, 02257 | e_lte = 18, e_ne = 19, e_gte = 20, 02258 | e_swap = 21, e_lt = '<', e_gt = '>', 02259 | e_eq = '=', e_rbracket = ')', e_lbracket = '(', 02260 | e_rsqrbracket = ']', e_lsqrbracket = '[', e_rcrlbracket = '}', 02261 | e_lcrlbracket = '{', e_comma = ',', e_add = '+', 02262 | e_sub = '-', e_div = '/', e_mul = '*', 02263 | e_mod = '%', e_pow = '^', e_colon = ':', 02264 | e_ternary = '?' 02265 | }; 02266 | 02267 | token() 02268 | : type(e_none) 02269 | , value("") 02270 | , position(std::numeric_limits<std::size_t>::max()) 02271 | {} 02272 | 02273 | void clear() 02274 | { 02275 | type = e_none; 02276 | value = "" 02277 | position = std::numeric_limits<std::size_t>::max(); 02278 | } 02279 | 02280 | template <typename Iterator> 02281 | inline token& set_operator(const token_type tt, 02282 | const Iterator begin, const Iterator end, 02283 | const Iterator base_begin = Iterator(0)) 02284 | { 02285 | type = tt; 02286 | value.assign(begin,end); 02287 | if (base_begin) 02288 | position = static_cast<std::size_t>(std::distance(base_begin,begin)); 02289 | return (*this); 02290 | } 02291 | 02292 | template <typename Iterator> 02293 | inline token& set_symbol(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0)) 02294 | { 02295 | type = e_symbol; 02296 | value.assign(begin,end); 02297 | if (base_begin) 02298 | position = static_cast<std::size_t>(std::distance(base_begin,begin)); 02299 | return (*this); 02300 | } 02301 | 02302 | template <typename Iterator> 02303 | inline token& set_numeric(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0)) 02304 | { 02305 | type = e_number; 02306 | value.assign(begin,end); 02307 | if (base_begin) 02308 | position = static_cast<std::size_t>(std::distance(base_begin,begin)); 02309 | return (*this); 02310 | } 02311 | 02312 | template <typename Iterator> 02313 | inline token& set_string(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0)) 02314 | { 02315 | type = e_string; 02316 | value.assign(begin,end); 02317 | if (base_begin) 02318 | position = static_cast<std::size_t>(std::distance(base_begin,begin)); 02319 | return (*this); 02320 | } 02321 | 02322 | inline token& set_string(const std::string& s, const std::size_t p) 02323 | { 02324 | type = e_string; 02325 | value = s; 02326 | position = p; 02327 | return (*this); 02328 | } 02329 | 02330 | template <typename Iterator> 02331 | inline token& set_error(const token_type et, 02332 | const Iterator begin, const Iterator end, 02333 | const Iterator base_begin = Iterator(0)) 02334 | { 02335 | if ( 02336 | (e_error == et) || 02337 | (e_err_symbol == et) || 02338 | (e_err_number == et) || 02339 | (e_err_string == et) || 02340 | (e_err_sfunc == et) 02341 | ) 02342 | { 02343 | type = et; 02344 | } 02345 | else 02346 | type = e_error; 02347 | 02348 | value.assign(begin,end); 02349 | 02350 | if (base_begin) 02351 | position = static_cast<std::size_t>(std::distance(base_begin,begin)); 02352 | 02353 | return (*this); 02354 | } 02355 | 02356 | static inline std::string to_str(token_type t) 02357 | { 02358 | switch (t) 02359 | { 02360 | case e_none : return "NONE" 02361 | case e_error : return "ERROR" 02362 | case e_err_symbol : return "ERROR_SYMBOL" 02363 | case e_err_number : return "ERROR_NUMBER" 02364 | case e_err_string : return "ERROR_STRING" 02365 | case e_eof : return "EOF" 02366 | case e_number : return "NUMBER" 02367 | case e_symbol : return "SYMBOL" 02368 | case e_string : return "STRING" 02369 | case e_assign : return ":=" 02370 | case e_addass : return "+=" 02371 | case e_subass : return "-=" 02372 | case e_mulass : return "*=" 02373 | case e_divass : return "/=" 02374 | case e_modass : return "%=" 02375 | case e_shr : return ">>" 02376 | case e_shl : return "<<" 02377 | case e_lte : return "<=" 02378 | case e_ne : return "!=" 02379 | case e_gte : return ">=" 02380 | case e_lt : return "<" 02381 | case e_gt : return ">" 02382 | case e_eq : return "=" 02383 | case e_rbracket : return ")" 02384 | case e_lbracket : return "(" 02385 | case e_rsqrbracket : return "]" 02386 | case e_lsqrbracket : return "[" 02387 | case e_rcrlbracket : return "}" 02388 | case e_lcrlbracket : return "{" 02389 | case e_comma : return "," 02390 | case e_add : return "+" 02391 | case e_sub : return "-" 02392 | case e_div : return "/" 02393 | case e_mul : return "*" 02394 | case e_mod : return "%" 02395 | case e_pow : return "^" 02396 | case e_colon : return ":" 02397 | case e_ternary : return "?" 02398 | case e_swap : return "<=>" 02399 | default : return "UNKNOWN" 02400 | } 02401 | } 02402 | 02403 | static inline std::string seperator_to_str(const token_type t) 02404 | { 02405 | switch (t) 02406 | { 02407 | case e_comma : return "," 02408 | case e_colon : return ":" 02409 | case e_eof : return "" 02410 | default : return "UNKNOWN" 02411 | } 02412 | 02413 | #if !defined(_MSC_VER) && !defined(__NVCOMPILER) 02414 | return "UNKNOWN" 02415 | #endif 02416 | } 02417 | 02418 | inline bool is_error() const 02419 | { 02420 | return ( 02421 | (e_error == type) || 02422 | (e_err_symbol == type) || 02423 | (e_err_number == type) || 02424 | (e_err_string == type) || 02425 | (e_err_sfunc == type) 02426 | ); 02427 | } 02428 | 02429 | token_type type; 02430 | std::string value; 02431 | std::size_t position; 02432 | }; 02433 | 02434 | class generator 02435 | { 02436 | public: 02437 | 02438 | typedef token token_t; 02439 | typedef std::vector<token_t> token_list_t; 02440 | typedef token_list_t::iterator token_list_itr_t; 02441 | typedef details::char_t char_t; 02442 | 02443 | generator() 02444 | : base_itr_(0) 02445 | , s_itr_ (0) 02446 | , s_end_ (0) 02447 | { 02448 | clear(); 02449 | } 02450 | 02451 | inline void clear() 02452 | { 02453 | base_itr_ = 0; 02454 | s_itr_ = 0; 02455 | s_end_ = 0; 02456 | token_list_.clear(); 02457 | token_itr_ = token_list_.end(); 02458 | store_token_itr_ = token_list_.end(); 02459 | } 02460 | 02461 | inline bool process(const std::string& str) 02462 | { 02463 | base_itr_ = str.data(); 02464 | s_itr_ = str.data(); 02465 | s_end_ = str.data() + str.size(); 02466 | 02467 | eof_token_.set_operator(token_t::e_eof, s_end_, s_end_, base_itr_); 02468 | token_list_.clear(); 02469 | 02470 | while (!is_end(s_itr_)) 02471 | { 02472 | scan_token(); 02473 | 02474 | if (!token_list_.empty() && token_list_.back().is_error()) 02475 | return false; 02476 | } 02477 | 02478 | return true; 02479 | } 02480 | 02481 | inline bool empty() const 02482 | { 02483 | return token_list_.empty(); 02484 | } 02485 | 02486 | inline std::size_t size() const 02487 | { 02488 | return token_list_.size(); 02489 | } 02490 | 02491 | inline void begin() 02492 | { 02493 | token_itr_ = token_list_.begin(); 02494 | store_token_itr_ = token_list_.begin(); 02495 | } 02496 | 02497 | inline void store() 02498 | { 02499 | store_token_itr_ = token_itr_; 02500 | } 02501 | 02502 | inline void restore() 02503 | { 02504 | token_itr_ = store_token_itr_; 02505 | } 02506 | 02507 | inline token_t& next_token() 02508 | { 02509 | if (token_list_.end() != token_itr_) 02510 | { 02511 | return *token_itr_++; 02512 | } 02513 | else 02514 | return eof_token_; 02515 | } 02516 | 02517 | inline token_t& peek_next_token() 02518 | { 02519 | if (token_list_.end() != token_itr_) 02520 | { 02521 | return *token_itr_; 02522 | } 02523 | else 02524 | return eof_token_; 02525 | } 02526 | 02527 | inline token_t& operator[](const std::size_t& index) 02528 | { 02529 | if (index < token_list_.size()) 02530 | { 02531 | return token_list_[index]; 02532 | } 02533 | else 02534 | return eof_token_; 02535 | } 02536 | 02537 | inline token_t operator[](const std::size_t& index) const 02538 | { 02539 | if (index < token_list_.size()) 02540 | { 02541 | return token_list_[index]; 02542 | } 02543 | else 02544 | return eof_token_; 02545 | } 02546 | 02547 | inline bool finished() const 02548 | { 02549 | return (token_list_.end() == token_itr_); 02550 | } 02551 | 02552 | inline void insert_front(token_t::token_type tk_type) 02553 | { 02554 | if ( 02555 | !token_list_.empty() && 02556 | (token_list_.end() != token_itr_) 02557 | ) 02558 | { 02559 | token_t t = *token_itr_; 02560 | 02561 | t.type = tk_type; 02562 | token_itr_ = token_list_.insert(token_itr_,t); 02563 | } 02564 | } 02565 | 02566 | inline std::string substr(const std::size_t& begin, const std::size_t& end) const 02567 | { 02568 | const details::char_cptr begin_itr = ((base_itr_ + begin) < s_end_) ? (base_itr_ + begin) : s_end_; 02569 | const details::char_cptr end_itr = ((base_itr_ + end ) < s_end_) ? (base_itr_ + end ) : s_end_; 02570 | 02571 | return std::string(begin_itr,end_itr); 02572 | } 02573 | 02574 | inline std::string remaining() const 02575 | { 02576 | if (finished()) 02577 | return "" 02578 | else if (token_list_.begin() != token_itr_) 02579 | return std::string(base_itr_ + (token_itr_ - 1)->position, s_end_); 02580 | else 02581 | return std::string(base_itr_ + token_itr_->position, s_end_); 02582 | } 02583 | 02584 | private: 02585 | 02586 | inline bool is_end(details::char_cptr itr) const 02587 | { 02588 | return (s_end_ == itr); 02589 | } 02590 | 02591 | #ifndef exprtk_disable_comments 02592 | inline bool is_comment_start(details::char_cptr itr) const 02593 | { 02594 | const char_t c0 = *(itr + 0); 02595 | const char_t c1 = *(itr + 1); 02596 | 02597 | if ('#' == c0) 02598 | return true; 02599 | else if (!is_end(itr + 1)) 02600 | { 02601 | if (('/' == c0) && ('/' == c1)) return true; 02602 | if (('/' == c0) && ('*' == c1)) return true; 02603 | } 02604 | return false; 02605 | } 02606 | #else 02607 | inline bool is_comment_start(details::char_cptr) const 02608 | { 02609 | return false; 02610 | } 02611 | #endif 02612 | 02613 | inline void skip_whitespace() 02614 | { 02615 | while (!is_end(s_itr_) && details::is_whitespace(*s_itr_)) 02616 | { 02617 | ++s_itr_; 02618 | } 02619 | } 02620 | 02621 | inline void skip_comments() 02622 | { 02623 | #ifndef exprtk_disable_comments 02624 | // The following comment styles are supported: 02625 | // 1. // .... \n 02626 | // 2. # .... \n 02627 | // 3. /* .... */ 02628 | struct test 02629 | { 02630 | static inline bool comment_start(const char_t c0, const char_t c1, int& mode, int& incr) 02631 | { 02632 | mode = 0; 02633 | if ('#' == c0) { mode = 1; incr = 1; } 02634 | else if ('/' == c0) 02635 | { 02636 | if ('/' == c1) { mode = 1; incr = 2; } 02637 | else if ('*' == c1) { mode = 2; incr = 2; } 02638 | } 02639 | return (0 != mode); 02640 | } 02641 | 02642 | static inline bool comment_end(const char_t c0, const char_t c1, int& mode) 02643 | { 02644 | if ( 02645 | ((1 == mode) && ('\n' == c0)) || 02646 | ((2 == mode) && ( '*' == c0) && ('/' == c1)) 02647 | ) 02648 | { 02649 | mode = 0; 02650 | return true; 02651 | } 02652 | else 02653 | return false; 02654 | } 02655 | }; 02656 | 02657 | int mode = 0; 02658 | int increment = 0; 02659 | 02660 | if (is_end(s_itr_)) 02661 | return; 02662 | else if (!test::comment_start(*s_itr_, *(s_itr_ + 1), mode, increment)) 02663 | return; 02664 | 02665 | details::char_cptr cmt_start = s_itr_; 02666 | 02667 | s_itr_ += increment; 02668 | 02669 | while (!is_end(s_itr_)) 02670 | { 02671 | if ((1 == mode) && test::comment_end(*s_itr_, 0, mode)) 02672 | { 02673 | ++s_itr_; 02674 | return; 02675 | } 02676 | 02677 | if ((2 == mode)) 02678 | { 02679 | if (!is_end((s_itr_ + 1)) && test::comment_end(*s_itr_, *(s_itr_ + 1), mode)) 02680 | { 02681 | s_itr_ += 2; 02682 | return; 02683 | } 02684 | } 02685 | 02686 | ++s_itr_; 02687 | } 02688 | 02689 | if (2 == mode) 02690 | { 02691 | token_t t; 02692 | t.set_error(token::e_error, cmt_start, cmt_start + mode, base_itr_); 02693 | token_list_.push_back(t); 02694 | } 02695 | #endif 02696 | } 02697 | 02698 | inline bool next_is_digit(const details::char_cptr itr) const 02699 | { 02700 | return ((itr + 1) != s_end_) && 02701 | details::is_digit(*(itr + 1)); 02702 | } 02703 | 02704 | inline void scan_token() 02705 | { 02706 | const char_t c = *s_itr_; 02707 | 02708 | if (details::is_whitespace(c)) 02709 | { 02710 | skip_whitespace(); 02711 | return; 02712 | } 02713 | else if (is_comment_start(s_itr_)) 02714 | { 02715 | skip_comments(); 02716 | return; 02717 | } 02718 | else if (details::is_operator_char(c)) 02719 | { 02720 | scan_operator(); 02721 | return; 02722 | } 02723 | else if (details::is_letter(c)) 02724 | { 02725 | scan_symbol(); 02726 | return; 02727 | } 02728 | else if (('.' == c) && !next_is_digit(s_itr_)) 02729 | { 02730 | scan_operator(); 02731 | return; 02732 | } 02733 | else if (details::is_digit(c) || ('.' == c)) 02734 | { 02735 | scan_number(); 02736 | return; 02737 | } 02738 | else if ('$' == c) 02739 | { 02740 | scan_special_function(); 02741 | return; 02742 | } 02743 | #ifndef exprtk_disable_string_capabilities 02744 | else if ('\'' == c) 02745 | { 02746 | scan_string(); 02747 | return; 02748 | } 02749 | #endif 02750 | else if ('~' == c) 02751 | { 02752 | token_t t; 02753 | t.set_symbol(s_itr_, s_itr_ + 1, base_itr_); 02754 | token_list_.push_back(t); 02755 | ++s_itr_; 02756 | return; 02757 | } 02758 | else 02759 | { 02760 | token_t t; 02761 | t.set_error(token::e_error, s_itr_, s_itr_ + 2, base_itr_); 02762 | token_list_.push_back(t); 02763 | ++s_itr_; 02764 | } 02765 | } 02766 | 02767 | inline void scan_operator() 02768 | { 02769 | token_t t; 02770 | 02771 | const char_t c0 = s_itr_[0]; 02772 | 02773 | if (!is_end(s_itr_ + 1)) 02774 | { 02775 | const char_t c1 = s_itr_[1]; 02776 | 02777 | if (!is_end(s_itr_ + 2)) 02778 | { 02779 | const char_t c2 = s_itr_[2]; 02780 | 02781 | if ((c0 == '<') && (c1 == '=') && (c2 == '>')) 02782 | { 02783 | t.set_operator(token_t::e_swap, s_itr_, s_itr_ + 3, base_itr_); 02784 | token_list_.push_back(t); 02785 | s_itr_ += 3; 02786 | return; 02787 | } 02788 | } 02789 | 02790 | token_t::token_type ttype = token_t::e_none; 02791 | 02792 | if ((c0 == '<') && (c1 == '=')) ttype = token_t::e_lte; 02793 | else if ((c0 == '>') && (c1 == '=')) ttype = token_t::e_gte; 02794 | else if ((c0 == '<') && (c1 == '>')) ttype = token_t::e_ne; 02795 | else if ((c0 == '!') && (c1 == '=')) ttype = token_t::e_ne; 02796 | else if ((c0 == '=') && (c1 == '=')) ttype = token_t::e_eq; 02797 | else if ((c0 == ':') && (c1 == '=')) ttype = token_t::e_assign; 02798 | else if ((c0 == '<') && (c1 == '<')) ttype = token_t::e_shl; 02799 | else if ((c0 == '>') && (c1 == '>')) ttype = token_t::e_shr; 02800 | else if ((c0 == '+') && (c1 == '=')) ttype = token_t::e_addass; 02801 | else if ((c0 == '-') && (c1 == '=')) ttype = token_t::e_subass; 02802 | else if ((c0 == '*') && (c1 == '=')) ttype = token_t::e_mulass; 02803 | else if ((c0 == '/') && (c1 == '=')) ttype = token_t::e_divass; 02804 | else if ((c0 == '%') && (c1 == '=')) ttype = token_t::e_modass; 02805 | 02806 | if (token_t::e_none != ttype) 02807 | { 02808 | t.set_operator(ttype, s_itr_, s_itr_ + 2, base_itr_); 02809 | token_list_.push_back(t); 02810 | s_itr_ += 2; 02811 | return; 02812 | } 02813 | } 02814 | 02815 | if ('<' == c0) 02816 | t.set_operator(token_t::e_lt , s_itr_, s_itr_ + 1, base_itr_); 02817 | else if ('>' == c0) 02818 | t.set_operator(token_t::e_gt , s_itr_, s_itr_ + 1, base_itr_); 02819 | else if (';' == c0) 02820 | t.set_operator(token_t::e_eof, s_itr_, s_itr_ + 1, base_itr_); 02821 | else if ('&' == c0) 02822 | t.set_symbol(s_itr_, s_itr_ + 1, base_itr_); 02823 | else if ('|' == c0) 02824 | t.set_symbol(s_itr_, s_itr_ + 1, base_itr_); 02825 | else 02826 | t.set_operator(token_t::token_type(c0), s_itr_, s_itr_ + 1, base_itr_); 02827 | 02828 | token_list_.push_back(t); 02829 | ++s_itr_; 02830 | } 02831 | 02832 | inline void scan_symbol() 02833 | { 02834 | details::char_cptr initial_itr = s_itr_; 02835 | 02836 | while (!is_end(s_itr_)) 02837 | { 02838 | if (!details::is_letter_or_digit(*s_itr_) && ('_' != (*s_itr_))) 02839 | { 02840 | if ('.' != (*s_itr_)) 02841 | break; 02842 | /* 02843 | Permit symbols that contain a 'dot' 02844 | Allowed : abc.xyz, a123.xyz, abc.123, abc_.xyz a123_.xyz abc._123 02845 | Disallowed: .abc, abc.<white-space>, abc.<eof>, abc.<operator +,-,*,/...> 02846 | */ 02847 | if ( 02848 | (s_itr_ != initial_itr) && 02849 | !is_end(s_itr_ + 1) && 02850 | !details::is_letter_or_digit(*(s_itr_ + 1)) && 02851 | ('_' != (*(s_itr_ + 1))) 02852 | ) 02853 | break; 02854 | } 02855 | 02856 | ++s_itr_; 02857 | } 02858 | 02859 | token_t t; 02860 | t.set_symbol(initial_itr, s_itr_, base_itr_); 02861 | token_list_.push_back(t); 02862 | } 02863 | 02864 | inline void scan_number() 02865 | { 02866 | /* 02867 | Attempt to match a valid numeric value in one of the following formats: 02868 | (01) 123456 02869 | (02) 123456. 02870 | (03) 123.456 02871 | (04) 123.456e3 02872 | (05) 123.456E3 02873 | (06) 123.456e+3 02874 | (07) 123.456E+3 02875 | (08) 123.456e-3 02876 | (09) 123.456E-3 02877 | (00) .1234 02878 | (11) .1234e3 02879 | (12) .1234E+3 02880 | (13) .1234e+3 02881 | (14) .1234E-3 02882 | (15) .1234e-3 02883 | */ 02884 | 02885 | details::char_cptr initial_itr = s_itr_; 02886 | bool dot_found = false; 02887 | bool e_found = false; 02888 | bool post_e_sign_found = false; 02889 | bool post_e_digit_found = false; 02890 | token_t t; 02891 | 02892 | while (!is_end(s_itr_)) 02893 | { 02894 | if ('.' == (*s_itr_)) 02895 | { 02896 | if (dot_found) 02897 | { 02898 | t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_); 02899 | token_list_.push_back(t); 02900 | 02901 | return; 02902 | } 02903 | 02904 | dot_found = true; 02905 | ++s_itr_; 02906 | 02907 | continue; 02908 | } 02909 | else if ('e' == std::tolower(*s_itr_)) 02910 | { 02911 | const char_t& c = *(s_itr_ + 1); 02912 | 02913 | if (is_end(s_itr_ + 1)) 02914 | { 02915 | t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_); 02916 | token_list_.push_back(t); 02917 | 02918 | return; 02919 | } 02920 | else if ( 02921 | ('+' != c) && 02922 | ('-' != c) && 02923 | !details::is_digit(c) 02924 | ) 02925 | { 02926 | t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_); 02927 | token_list_.push_back(t); 02928 | 02929 | return; 02930 | } 02931 | 02932 | e_found = true; 02933 | ++s_itr_; 02934 | 02935 | continue; 02936 | } 02937 | else if (e_found && details::is_sign(*s_itr_) && !post_e_digit_found) 02938 | { 02939 | if (post_e_sign_found) 02940 | { 02941 | t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_); 02942 | token_list_.push_back(t); 02943 | 02944 | return; 02945 | } 02946 | 02947 | post_e_sign_found = true; 02948 | ++s_itr_; 02949 | 02950 | continue; 02951 | } 02952 | else if (e_found && details::is_digit(*s_itr_)) 02953 | { 02954 | post_e_digit_found = true; 02955 | ++s_itr_; 02956 | 02957 | continue; 02958 | } 02959 | else if (('.' != (*s_itr_)) && !details::is_digit(*s_itr_)) 02960 | break; 02961 | else 02962 | ++s_itr_; 02963 | } 02964 | 02965 | t.set_numeric(initial_itr, s_itr_, base_itr_); 02966 | token_list_.push_back(t); 02967 | 02968 | return; 02969 | } 02970 | 02971 | inline void scan_special_function() 02972 | { 02973 | details::char_cptr initial_itr = s_itr_; 02974 | token_t t; 02975 | 02976 | // $fdd(x,x,x) = at least 11 chars 02977 | if (std::distance(s_itr_,s_end_) < 11) 02978 | { 02979 | t.set_error( 02980 | token::e_err_sfunc, 02981 | initial_itr, std::min(initial_itr + 11, s_end_), 02982 | base_itr_); 02983 | token_list_.push_back(t); 02984 | 02985 | return; 02986 | } 02987 | 02988 | if ( 02989 | !(('$' == *s_itr_) && 02990 | (details::imatch ('f',*(s_itr_ + 1))) && 02991 | (details::is_digit(*(s_itr_ + 2))) && 02992 | (details::is_digit(*(s_itr_ + 3)))) 02993 | ) 02994 | { 02995 | t.set_error( 02996 | token::e_err_sfunc, 02997 | initial_itr, std::min(initial_itr + 4, s_end_), 02998 | base_itr_); 02999 | token_list_.push_back(t); 03000 | 03001 | return; 03002 | } 03003 | 03004 | s_itr_ += 4; // $fdd = 4chars 03005 | 03006 | t.set_symbol(initial_itr, s_itr_, base_itr_); 03007 | token_list_.push_back(t); 03008 | 03009 | return; 03010 | } 03011 | 03012 | #ifndef exprtk_disable_string_capabilities 03013 | inline void scan_string() 03014 | { 03015 | details::char_cptr initial_itr = s_itr_ + 1; 03016 | token_t t; 03017 | 03018 | if (std::distance(s_itr_,s_end_) < 2) 03019 | { 03020 | t.set_error(token::e_err_string, s_itr_, s_end_, base_itr_); 03021 | token_list_.push_back(t); 03022 | 03023 | return; 03024 | } 03025 | 03026 | ++s_itr_; 03027 | 03028 | bool escaped_found = false; 03029 | bool escaped = false; 03030 | 03031 | while (!is_end(s_itr_)) 03032 | { 03033 | if (!details::is_valid_string_char(*s_itr_)) 03034 | { 03035 | t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_); 03036 | token_list_.push_back(t); 03037 | 03038 | return; 03039 | } 03040 | else if (!escaped && ('\\' == *s_itr_)) 03041 | { 03042 | escaped_found = true; 03043 | escaped = true; 03044 | ++s_itr_; 03045 | 03046 | continue; 03047 | } 03048 | else if (!escaped) 03049 | { 03050 | if ('\'' == *s_itr_) 03051 | break; 03052 | } 03053 | else if (escaped) 03054 | { 03055 | if ( 03056 | !is_end(s_itr_) && ('0' == *(s_itr_)) && 03057 | ((s_itr_ + 4) <= s_end_) 03058 | ) 03059 | { 03060 | const bool x_separator = ('X' == std::toupper(*(s_itr_ + 1))); 03061 | 03062 | const bool both_digits = details::is_hex_digit(*(s_itr_ + 2)) && 03063 | details::is_hex_digit(*(s_itr_ + 3)) ; 03064 | 03065 | if (!(x_separator && both_digits)) 03066 | { 03067 | t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_); 03068 | token_list_.push_back(t); 03069 | 03070 | return; 03071 | } 03072 | else 03073 | s_itr_ += 3; 03074 | } 03075 | 03076 | escaped = false; 03077 | } 03078 | 03079 | ++s_itr_; 03080 | } 03081 | 03082 | if (is_end(s_itr_)) 03083 | { 03084 | t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_); 03085 | token_list_.push_back(t); 03086 | 03087 | return; 03088 | } 03089 | 03090 | if (!escaped_found) 03091 | t.set_string(initial_itr, s_itr_, base_itr_); 03092 | else 03093 | { 03094 | std::string parsed_string(initial_itr,s_itr_); 03095 | 03096 | if (!details::cleanup_escapes(parsed_string)) 03097 | { 03098 | t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_); 03099 | token_list_.push_back(t); 03100 | 03101 | return; 03102 | } 03103 | 03104 | t.set_string( 03105 | parsed_string, 03106 | static_cast<std::size_t>(std::distance(base_itr_,initial_itr))); 03107 | } 03108 | 03109 | token_list_.push_back(t); 03110 | ++s_itr_; 03111 | 03112 | return; 03113 | } 03114 | #endif 03115 | 03116 | private: 03117 | 03118 | token_list_t token_list_; 03119 | token_list_itr_t token_itr_; 03120 | token_list_itr_t store_token_itr_; 03121 | token_t eof_token_; 03122 | details::char_cptr base_itr_; 03123 | details::char_cptr s_itr_; 03124 | details::char_cptr s_end_; 03125 | 03126 | friend class token_scanner; 03127 | friend class token_modifier; 03128 | friend class token_inserter; 03129 | friend class token_joiner; 03130 | }; // class generator 03131 | 03132 | class helper_interface 03133 | { 03134 | public: 03135 | 03136 | virtual void init() { } 03137 | virtual void reset() { } 03138 | virtual bool result() { return true; } 03139 | virtual std::size_t process(generator&) { return 0; } 03140 | virtual ~helper_interface() { } 03141 | }; 03142 | 03143 | class token_scanner : public helper_interface 03144 | { 03145 | public: 03146 | 03147 | virtual ~token_scanner() exprtk_override 03148 | {} 03149 | 03150 | explicit token_scanner(const std::size_t& stride) 03151 | : stride_(stride) 03152 | { 03153 | if (stride > 4) 03154 | { 03155 | throw std::invalid_argument("token_scanner() - Invalid stride value"); 03156 | } 03157 | } 03158 | 03159 | inline std::size_t process(generator& g) exprtk_override 03160 | { 03161 | if (g.token_list_.size() >= stride_) 03162 | { 03163 | for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i) 03164 | { 03165 | token t; 03166 | 03167 | switch (stride_) 03168 | { 03169 | case 1 : 03170 | { 03171 | const token& t0 = g.token_list_[i]; 03172 | 03173 | if (!operator()(t0)) 03174 | { 03175 | return 0; 03176 | } 03177 | } 03178 | break; 03179 | 03180 | case 2 : 03181 | { 03182 | const token& t0 = g.token_list_[i ]; 03183 | const token& t1 = g.token_list_[i + 1]; 03184 | 03185 | if (!operator()(t0, t1)) 03186 | { 03187 | return 0; 03188 | } 03189 | } 03190 | break; 03191 | 03192 | case 3 : 03193 | { 03194 | const token& t0 = g.token_list_[i ]; 03195 | const token& t1 = g.token_list_[i + 1]; 03196 | const token& t2 = g.token_list_[i + 2]; 03197 | 03198 | if (!operator()(t0, t1, t2)) 03199 | { 03200 | return 0; 03201 | } 03202 | } 03203 | break; 03204 | 03205 | case 4 : 03206 | { 03207 | const token& t0 = g.token_list_[i ]; 03208 | const token& t1 = g.token_list_[i + 1]; 03209 | const token& t2 = g.token_list_[i + 2]; 03210 | const token& t3 = g.token_list_[i + 3]; 03211 | 03212 | if (!operator()(t0, t1, t2, t3)) 03213 | { 03214 | return 0; 03215 | } 03216 | } 03217 | break; 03218 | } 03219 | } 03220 | } 03221 | 03222 | return 0; 03223 | } 03224 | 03225 | virtual bool operator() (const token&) 03226 | { 03227 | return false; 03228 | } 03229 | 03230 | virtual bool operator() (const token&, const token&) 03231 | { 03232 | return false; 03233 | } 03234 | 03235 | virtual bool operator() (const token&, const token&, const token&) 03236 | { 03237 | return false; 03238 | } 03239 | 03240 | virtual bool operator() (const token&, const token&, const token&, const token&) 03241 | { 03242 | return false; 03243 | } 03244 | 03245 | private: 03246 | 03247 | const std::size_t stride_; 03248 | }; // class token_scanner 03249 | 03250 | class token_modifier : public helper_interface 03251 | { 03252 | public: 03253 | 03254 | inline std::size_t process(generator& g) exprtk_override 03255 | { 03256 | std::size_t changes = 0; 03257 | 03258 | for (std::size_t i = 0; i < g.token_list_.size(); ++i) 03259 | { 03260 | if (modify(g.token_list_[i])) changes++; 03261 | } 03262 | 03263 | return changes; 03264 | } 03265 | 03266 | virtual bool modify(token& t) = 0; 03267 | }; 03268 | 03269 | class token_inserter : public helper_interface 03270 | { 03271 | public: 03272 | 03273 | explicit token_inserter(const std::size_t& stride) 03274 | : stride_(stride) 03275 | { 03276 | if (stride > 5) 03277 | { 03278 | throw std::invalid_argument("token_inserter() - Invalid stride value"); 03279 | } 03280 | } 03281 | 03282 | inline std::size_t process(generator& g) exprtk_override 03283 | { 03284 | if (g.token_list_.empty()) 03285 | return 0; 03286 | else if (g.token_list_.size() < stride_) 03287 | return 0; 03288 | 03289 | std::size_t changes = 0; 03290 | 03291 | typedef std::pair<std::size_t, token> insert_t; 03292 | std::vector<insert_t> insert_list; 03293 | insert_list.reserve(10000); 03294 | 03295 | for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i) 03296 | { 03297 | int insert_index = -1; 03298 | token t; 03299 | 03300 | switch (stride_) 03301 | { 03302 | case 1 : insert_index = insert(g.token_list_[i],t); 03303 | break; 03304 | 03305 | case 2 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], t); 03306 | break; 03307 | 03308 | case 3 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], g.token_list_[i + 2], t); 03309 | break; 03310 | 03311 | 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); 03312 | break; 03313 | 03314 | 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); 03315 | break; 03316 | } 03317 | 03318 | if ((insert_index >= 0) && (insert_index <= (static_cast<int>(stride_) + 1))) 03319 | { 03320 | insert_list.push_back(insert_t(i, t)); 03321 | changes++; 03322 | } 03323 | } 03324 | 03325 | if (!insert_list.empty()) 03326 | { 03327 | generator::token_list_t token_list; 03328 | 03329 | std::size_t insert_index = 0; 03330 | 03331 | for (std::size_t i = 0; i < g.token_list_.size(); ++i) 03332 | { 03333 | token_list.push_back(g.token_list_[i]); 03334 | 03335 | if ( 03336 | (insert_index < insert_list.size()) && 03337 | (insert_list[insert_index].first == i) 03338 | ) 03339 | { 03340 | token_list.push_back(insert_list[insert_index].second); 03341 | insert_index++; 03342 | } 03343 | } 03344 | 03345 | std::swap(g.token_list_,token_list); 03346 | } 03347 | 03348 | return changes; 03349 | } 03350 | 03351 | #define token_inserter_empty_body \ 03352 | { \ 03353 | return -1; \ 03354 | } \ 03355 | 03356 | inline virtual int insert(const token&, token&) 03357 | token_inserter_empty_body 03358 | 03359 | inline virtual int insert(const token&, const token&, token&) 03360 | token_inserter_empty_body 03361 | 03362 | inline virtual int insert(const token&, const token&, const token&, token&) 03363 | token_inserter_empty_body 03364 | 03365 | inline virtual int insert(const token&, const token&, const token&, const token&, token&) 03366 | token_inserter_empty_body 03367 | 03368 | inline virtual int insert(const token&, const token&, const token&, const token&, const token&, token&) 03369 | token_inserter_empty_body 03370 | 03371 | #undef token_inserter_empty_body 03372 | 03373 | private: 03374 | 03375 | const std::size_t stride_; 03376 | }; 03377 | 03378 | class token_joiner : public helper_interface 03379 | { 03380 | public: 03381 | 03382 | explicit token_joiner(const std::size_t& stride) 03383 | : stride_(stride) 03384 | {} 03385 | 03386 | inline std::size_t process(generator& g) exprtk_override 03387 | { 03388 | if (g.token_list_.empty()) 03389 | return 0; 03390 | 03391 | switch (stride_) 03392 | { 03393 | case 2 : return process_stride_2(g); 03394 | case 3 : return process_stride_3(g); 03395 | default : return 0; 03396 | } 03397 | } 03398 | 03399 | virtual bool join(const token&, const token&, token&) { return false; } 03400 | virtual bool join(const token&, const token&, const token&, token&) { return false; } 03401 | 03402 | private: 03403 | 03404 | inline std::size_t process_stride_2(generator& g) 03405 | { 03406 | if (g.token_list_.size() < 2) 03407 | return 0; 03408 | 03409 | std::size_t changes = 0; 03410 | 03411 | generator::token_list_t token_list; 03412 | token_list.reserve(10000); 03413 | 03414 | for (int i = 0; i < static_cast<int>(g.token_list_.size() - 1); ++i) 03415 | { 03416 | token t; 03417 | 03418 | for ( ; ; ) 03419 | { 03420 | if (!join(g[i], g[i + 1], t)) 03421 | { 03422 | token_list.push_back(g[i]); 03423 | break; 03424 | } 03425 | 03426 | token_list.push_back(t); 03427 | 03428 | ++changes; 03429 | 03430 | i += 2; 03431 | 03432 | if (static_cast<std::size_t>(i) >= (g.token_list_.size() - 1)) 03433 | break; 03434 | } 03435 | } 03436 | 03437 | token_list.push_back(g.token_list_.back()); 03438 | 03439 | assert(token_list.size() <= g.token_list_.size()); 03440 | 03441 | std::swap(token_list, g.token_list_); 03442 | 03443 | return changes; 03444 | } 03445 | 03446 | inline std::size_t process_stride_3(generator& g) 03447 | { 03448 | if (g.token_list_.size() < 3) 03449 | return 0; 03450 | 03451 | std::size_t changes = 0; 03452 | 03453 | generator::token_list_t token_list; 03454 | token_list.reserve(10000); 03455 | 03456 | for (int i = 0; i < static_cast<int>(g.token_list_.size() - 2); ++i) 03457 | { 03458 | token t; 03459 | 03460 | for ( ; ; ) 03461 | { 03462 | if (!join(g[i], g[i + 1], g[i + 2], t)) 03463 | { 03464 | token_list.push_back(g[i]); 03465 | break; 03466 | } 03467 | 03468 | token_list.push_back(t); 03469 | 03470 | ++changes; 03471 | 03472 | i += 3; 03473 | 03474 | if (static_cast<std::size_t>(i) >= (g.token_list_.size() - 2)) 03475 | break; 03476 | } 03477 | } 03478 | 03479 | token_list.push_back(*(g.token_list_.begin() + g.token_list_.size() - 2)); 03480 | token_list.push_back(*(g.token_list_.begin() + g.token_list_.size() - 1)); 03481 | 03482 | assert(token_list.size() <= g.token_list_.size()); 03483 | 03484 | std::swap(token_list, g.token_list_); 03485 | 03486 | return changes; 03487 | } 03488 | 03489 | const std::size_t stride_; 03490 | }; 03491 | 03492 | namespace helper 03493 | { 03494 | 03495 | inline void dump(const lexer::generator& generator) 03496 | { 03497 | for (std::size_t i = 0; i < generator.size(); ++i) 03498 | { 03499 | const lexer::token& t = generator[i]; 03500 | printf("Token[%02d] @ %03d %6s --> '%s'\n", 03501 | static_cast<int>(i), 03502 | static_cast<int>(t.position), 03503 | t.to_str(t.type).c_str(), 03504 | t.value.c_str()); 03505 | } 03506 | } 03507 | 03508 | class commutative_inserter : public lexer::token_inserter 03509 | { 03510 | public: 03511 | 03512 | using lexer::token_inserter::insert; 03513 | 03514 | commutative_inserter() 03515 | : lexer::token_inserter(2) 03516 | {} 03517 | 03518 | inline void ignore_symbol(const std::string& symbol) 03519 | { 03520 | ignore_set_.insert(symbol); 03521 | } 03522 | 03523 | inline int insert(const lexer::token& t0, const lexer::token& t1, lexer::token& new_token) exprtk_override 03524 | { 03525 | bool match = false; 03526 | new_token.type = lexer::token::e_mul; 03527 | new_token.value = "*" 03528 | new_token.position = t1.position; 03529 | 03530 | if (t0.type == lexer::token::e_symbol) 03531 | { 03532 | if (ignore_set_.end() != ignore_set_.find(t0.value)) 03533 | { 03534 | return -1; 03535 | } 03536 | else if (!t0.value.empty() && ('$' == t0.value[0])) 03537 | { 03538 | return -1; 03539 | } 03540 | } 03541 | 03542 | if (t1.type == lexer::token::e_symbol) 03543 | { 03544 | if (ignore_set_.end() != ignore_set_.find(t1.value)) 03545 | { 03546 | return -1; 03547 | } 03548 | } 03549 | if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_symbol )) match = true; 03550 | else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lbracket )) match = true; 03551 | else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lcrlbracket)) match = true; 03552 | else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lsqrbracket)) match = true; 03553 | else if ((t0.type == lexer::token::e_symbol ) && (t1.type == lexer::token::e_number )) match = true; 03554 | else if ((t0.type == lexer::token::e_rbracket ) && (t1.type == lexer::token::e_number )) match = true; 03555 | else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_number )) match = true; 03556 | else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_number )) match = true; 03557 | else if ((t0.type == lexer::token::e_rbracket ) && (t1.type == lexer::token::e_symbol )) match = true; 03558 | else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_symbol )) match = true; 03559 | else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_symbol )) match = true; 03560 | else if ((t0.type == lexer::token::e_symbol ) && (t1.type == lexer::token::e_symbol )) match = true; 03561 | 03562 | return (match) ? 1 : -1; 03563 | } 03564 | 03565 | private: 03566 | 03567 | std::set<std::string,details::ilesscompare> ignore_set_; 03568 | }; 03569 | 03570 | class operator_joiner exprtk_final : public token_joiner 03571 | { 03572 | public: 03573 | 03574 | explicit operator_joiner(const std::size_t& stride) 03575 | : token_joiner(stride) 03576 | {} 03577 | 03578 | inline bool join(const lexer::token& t0, const lexer::token& t1, lexer::token& t) exprtk_override 03579 | { 03580 | // ': =' --> ':=' 03581 | if ((t0.type == lexer::token::e_colon) && (t1.type == lexer::token::e_eq)) 03582 | { 03583 | t.type = lexer::token::e_assign; 03584 | t.value = ":=" 03585 | t.position = t0.position; 03586 | 03587 | return true; 03588 | } 03589 | // '+ =' --> '+=' 03590 | else if ((t0.type == lexer::token::e_add) && (t1.type == lexer::token::e_eq)) 03591 | { 03592 | t.type = lexer::token::e_addass; 03593 | t.value = "+=" 03594 | t.position = t0.position; 03595 | 03596 | return true; 03597 | } 03598 | // '- =' --> '-=' 03599 | else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_eq)) 03600 | { 03601 | t.type = lexer::token::e_subass; 03602 | t.value = "-=" 03603 | t.position = t0.position; 03604 | 03605 | return true; 03606 | } 03607 | // '* =' --> '*=' 03608 | else if ((t0.type == lexer::token::e_mul) && (t1.type == lexer::token::e_eq)) 03609 | { 03610 | t.type = lexer::token::e_mulass; 03611 | t.value = "*=" 03612 | t.position = t0.position; 03613 | 03614 | return true; 03615 | } 03616 | // '/ =' --> '/=' 03617 | else if ((t0.type == lexer::token::e_div) && (t1.type == lexer::token::e_eq)) 03618 | { 03619 | t.type = lexer::token::e_divass; 03620 | t.value = "/=" 03621 | t.position = t0.position; 03622 | 03623 | return true; 03624 | } 03625 | // '% =' --> '%=' 03626 | else if ((t0.type == lexer::token::e_mod) && (t1.type == lexer::token::e_eq)) 03627 | { 03628 | t.type = lexer::token::e_modass; 03629 | t.value = "%=" 03630 | t.position = t0.position; 03631 | 03632 | return true; 03633 | } 03634 | // '> =' --> '>=' 03635 | else if ((t0.type == lexer::token::e_gt) && (t1.type == lexer::token::e_eq)) 03636 | { 03637 | t.type = lexer::token::e_gte; 03638 | t.value = ">=" 03639 | t.position = t0.position; 03640 | 03641 | return true; 03642 | } 03643 | // '< =' --> '<=' 03644 | else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_eq)) 03645 | { 03646 | t.type = lexer::token::e_lte; 03647 | t.value = "<=" 03648 | t.position = t0.position; 03649 | 03650 | return true; 03651 | } 03652 | // '= =' --> '==' 03653 | else if ((t0.type == lexer::token::e_eq) && (t1.type == lexer::token::e_eq)) 03654 | { 03655 | t.type = lexer::token::e_eq; 03656 | t.value = "==" 03657 | t.position = t0.position; 03658 | 03659 | return true; 03660 | } 03661 | // '! =' --> '!=' 03662 | else if ((static_cast<details::char_t>(t0.type) == '!') && (t1.type == lexer::token::e_eq)) 03663 | { 03664 | t.type = lexer::token::e_ne; 03665 | t.value = "!=" 03666 | t.position = t0.position; 03667 | 03668 | return true; 03669 | } 03670 | // '< >' --> '<>' 03671 | else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_gt)) 03672 | { 03673 | t.type = lexer::token::e_ne; 03674 | t.value = "<>" 03675 | t.position = t0.position; 03676 | 03677 | return true; 03678 | } 03679 | // '<= >' --> '<=>' 03680 | else if ((t0.type == lexer::token::e_lte) && (t1.type == lexer::token::e_gt)) 03681 | { 03682 | t.type = lexer::token::e_swap; 03683 | t.value = "<=>" 03684 | t.position = t0.position; 03685 | 03686 | return true; 03687 | } 03688 | // '+ -' --> '-' 03689 | else if ((t0.type == lexer::token::e_add) && (t1.type == lexer::token::e_sub)) 03690 | { 03691 | t.type = lexer::token::e_sub; 03692 | t.value = "-" 03693 | t.position = t0.position; 03694 | 03695 | return true; 03696 | } 03697 | // '- +' --> '-' 03698 | else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_add)) 03699 | { 03700 | t.type = lexer::token::e_sub; 03701 | t.value = "-" 03702 | t.position = t0.position; 03703 | 03704 | return true; 03705 | } 03706 | // '- -' --> '+' 03707 | else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_sub)) 03708 | { 03709 | /* 03710 | Note: May need to reconsider this when wanting to implement 03711 | pre/postfix decrement operator 03712 | */ 03713 | t.type = lexer::token::e_add; 03714 | t.value = "+" 03715 | t.position = t0.position; 03716 | 03717 | return true; 03718 | } 03719 | else 03720 | return false; 03721 | } 03722 | 03723 | inline bool join(const lexer::token& t0, 03724 | const lexer::token& t1, 03725 | const lexer::token& t2, 03726 | lexer::token& t) exprtk_override 03727 | { 03728 | // '[ * ]' --> '[*]' 03729 | if ( 03730 | (t0.type == lexer::token::e_lsqrbracket) && 03731 | (t1.type == lexer::token::e_mul ) && 03732 | (t2.type == lexer::token::e_rsqrbracket) 03733 | ) 03734 | { 03735 | t.type = lexer::token::e_symbol; 03736 | t.value = "[*]" 03737 | t.position = t0.position; 03738 | 03739 | return true; 03740 | } 03741 | else 03742 | return false; 03743 | } 03744 | }; 03745 | 03746 | class bracket_checker exprtk_final : public lexer::token_scanner 03747 | { 03748 | public: 03749 | 03750 | using lexer::token_scanner::operator(); 03751 | 03752 | bracket_checker() 03753 | : token_scanner(1) 03754 | , state_(true) 03755 | {} 03756 | 03757 | bool result() exprtk_override 03758 | { 03759 | if (!stack_.empty()) 03760 | { 03761 | lexer::token t; 03762 | t.value = stack_.top().first; 03763 | t.position = stack_.top().second; 03764 | error_token_ = t; 03765 | state_ = false; 03766 | 03767 | return false; 03768 | } 03769 | else 03770 | return state_; 03771 | } 03772 | 03773 | lexer::token error_token() const 03774 | { 03775 | return error_token_; 03776 | } 03777 | 03778 | void reset() exprtk_override 03779 | { 03780 | // Why? because msvc doesn't support swap properly. 03781 | stack_ = std::stack<std::pair<char,std::size_t> >(); 03782 | state_ = true; 03783 | error_token_.clear(); 03784 | } 03785 | 03786 | bool operator() (const lexer::token& t) exprtk_override 03787 | { 03788 | if ( 03789 | !t.value.empty() && 03790 | (lexer::token::e_string != t.type) && 03791 | (lexer::token::e_symbol != t.type) && 03792 | exprtk::details::is_bracket(t.value[0]) 03793 | ) 03794 | { 03795 | details::char_t c = t.value[0]; 03796 | 03797 | if (t.type == lexer::token::e_lbracket ) stack_.push(std::make_pair(')',t.position)); 03798 | else if (t.type == lexer::token::e_lcrlbracket) stack_.push(std::make_pair('}',t.position)); 03799 | else if (t.type == lexer::token::e_lsqrbracket) stack_.push(std::make_pair(']',t.position)); 03800 | else if (exprtk::details::is_right_bracket(c)) 03801 | { 03802 | if (stack_.empty()) 03803 | { 03804 | state_ = false; 03805 | error_token_ = t; 03806 | 03807 | return false; 03808 | } 03809 | else if (c != stack_.top().first) 03810 | { 03811 | state_ = false; 03812 | error_token_ = t; 03813 | 03814 | return false; 03815 | } 03816 | else 03817 | stack_.pop(); 03818 | } 03819 | } 03820 | 03821 | return true; 03822 | } 03823 | 03824 | private: 03825 | 03826 | bool state_; 03827 | std::stack<std::pair<char,std::size_t> > stack_; 03828 | lexer::token error_token_; 03829 | }; 03830 | 03831 | template <typename T> 03832 | class numeric_checker exprtk_final : public lexer::token_scanner 03833 | { 03834 | public: 03835 | 03836 | using lexer::token_scanner::operator(); 03837 | 03838 | numeric_checker() 03839 | : token_scanner (1) 03840 | , current_index_(0) 03841 | {} 03842 | 03843 | bool result() exprtk_override 03844 | { 03845 | return error_list_.empty(); 03846 | } 03847 | 03848 | void reset() exprtk_override 03849 | { 03850 | error_list_.clear(); 03851 | current_index_ = 0; 03852 | } 03853 | 03854 | bool operator() (const lexer::token& t) exprtk_override 03855 | { 03856 | if (token::e_number == t.type) 03857 | { 03858 | T v; 03859 | 03860 | if (!exprtk::details::string_to_real(t.value,v)) 03861 | { 03862 | error_list_.push_back(current_index_); 03863 | } 03864 | } 03865 | 03866 | ++current_index_; 03867 | 03868 | return true; 03869 | } 03870 | 03871 | std::size_t error_count() const 03872 | { 03873 | return error_list_.size(); 03874 | } 03875 | 03876 | std::size_t error_index(const std::size_t& i) const 03877 | { 03878 | if (i < error_list_.size()) 03879 | return error_list_[i]; 03880 | else 03881 | return std::numeric_limits<std::size_t>::max(); 03882 | } 03883 | 03884 | void clear_errors() 03885 | { 03886 | error_list_.clear(); 03887 | } 03888 | 03889 | private: 03890 | 03891 | std::size_t current_index_; 03892 | std::vector<std::size_t> error_list_; 03893 | }; 03894 | 03895 | class symbol_replacer exprtk_final : public lexer::token_modifier 03896 | { 03897 | private: 03898 | 03899 | typedef std::map<std::string,std::pair<std::string,token::token_type>,details::ilesscompare> replace_map_t; 03900 | 03901 | public: 03902 | 03903 | bool remove(const std::string& target_symbol) 03904 | { 03905 | const replace_map_t::iterator itr = replace_map_.find(target_symbol); 03906 | 03907 | if (replace_map_.end() == itr) 03908 | return false; 03909 | 03910 | replace_map_.erase(itr); 03911 | 03912 | return true; 03913 | } 03914 | 03915 | bool add_replace(const std::string& target_symbol, 03916 | const std::string& replace_symbol, 03917 | const lexer::token::token_type token_type = lexer::token::e_symbol) 03918 | { 03919 | const replace_map_t::iterator itr = replace_map_.find(target_symbol); 03920 | 03921 | if (replace_map_.end() != itr) 03922 | { 03923 | return false; 03924 | } 03925 | 03926 | replace_map_[target_symbol] = std::make_pair(replace_symbol,token_type); 03927 | 03928 | return true; 03929 | } 03930 | 03931 | void clear() 03932 | { 03933 | replace_map_.clear(); 03934 | } 03935 | 03936 | private: 03937 | 03938 | bool modify(lexer::token& t) exprtk_override 03939 | { 03940 | if (lexer::token::e_symbol == t.type) 03941 | { 03942 | if (replace_map_.empty()) 03943 | return false; 03944 | 03945 | const replace_map_t::iterator itr = replace_map_.find(t.value); 03946 | 03947 | if (replace_map_.end() != itr) 03948 | { 03949 | t.value = itr->second.first; 03950 | t.type = itr->second.second; 03951 | 03952 | return true; 03953 | } 03954 | } 03955 | 03956 | return false; 03957 | } 03958 | 03959 | replace_map_t replace_map_; 03960 | }; 03961 | 03962 | class sequence_validator exprtk_final : public lexer::token_scanner 03963 | { 03964 | private: 03965 | 03966 | typedef std::pair<lexer::token::token_type,lexer::token::token_type> token_pair_t; 03967 | typedef std::set<token_pair_t> set_t; 03968 | 03969 | public: 03970 | 03971 | using lexer::token_scanner::operator(); 03972 | 03973 | sequence_validator() 03974 | : lexer::token_scanner(2) 03975 | { 03976 | add_invalid(lexer::token::e_number, lexer::token::e_number); 03977 | add_invalid(lexer::token::e_string, lexer::token::e_string); 03978 | add_invalid(lexer::token::e_number, lexer::token::e_string); 03979 | add_invalid(lexer::token::e_string, lexer::token::e_number); 03980 | 03981 | add_invalid_set1(lexer::token::e_assign ); 03982 | add_invalid_set1(lexer::token::e_shr ); 03983 | add_invalid_set1(lexer::token::e_shl ); 03984 | add_invalid_set1(lexer::token::e_lte ); 03985 | add_invalid_set1(lexer::token::e_ne ); 03986 | add_invalid_set1(lexer::token::e_gte ); 03987 | add_invalid_set1(lexer::token::e_lt ); 03988 | add_invalid_set1(lexer::token::e_gt ); 03989 | add_invalid_set1(lexer::token::e_eq ); 03990 | add_invalid_set1(lexer::token::e_comma ); 03991 | add_invalid_set1(lexer::token::e_add ); 03992 | add_invalid_set1(lexer::token::e_sub ); 03993 | add_invalid_set1(lexer::token::e_div ); 03994 | add_invalid_set1(lexer::token::e_mul ); 03995 | add_invalid_set1(lexer::token::e_mod ); 03996 | add_invalid_set1(lexer::token::e_pow ); 03997 | add_invalid_set1(lexer::token::e_colon ); 03998 | add_invalid_set1(lexer::token::e_ternary); 03999 | } 04000 | 04001 | bool result() exprtk_override 04002 | { 04003 | return error_list_.empty(); 04004 | } 04005 | 04006 | bool operator() (const lexer::token& t0, const lexer::token& t1) exprtk_override 04007 | { 04008 | const set_t::value_type p = std::make_pair(t0.type,t1.type); 04009 | 04010 | if (invalid_bracket_check(t0.type,t1.type)) 04011 | { 04012 | error_list_.push_back(std::make_pair(t0,t1)); 04013 | } 04014 | else if (invalid_comb_.find(p) != invalid_comb_.end()) 04015 | { 04016 | error_list_.push_back(std::make_pair(t0,t1)); 04017 | } 04018 | 04019 | return true; 04020 | } 04021 | 04022 | std::size_t error_count() const 04023 | { 04024 | return error_list_.size(); 04025 | } 04026 | 04027 | std::pair<lexer::token,lexer::token> error(const std::size_t index) 04028 | { 04029 | if (index < error_list_.size()) 04030 | { 04031 | return error_list_[index]; 04032 | } 04033 | else 04034 | { 04035 | static const lexer::token error_token; 04036 | return std::make_pair(error_token,error_token); 04037 | } 04038 | } 04039 | 04040 | void clear_errors() 04041 | { 04042 | error_list_.clear(); 04043 | } 04044 | 04045 | private: 04046 | 04047 | void add_invalid(const lexer::token::token_type base, const lexer::token::token_type t) 04048 | { 04049 | invalid_comb_.insert(std::make_pair(base,t)); 04050 | } 04051 | 04052 | void add_invalid_set1(const lexer::token::token_type t) 04053 | { 04054 | add_invalid(t, lexer::token::e_assign); 04055 | add_invalid(t, lexer::token::e_shr ); 04056 | add_invalid(t, lexer::token::e_shl ); 04057 | add_invalid(t, lexer::token::e_lte ); 04058 | add_invalid(t, lexer::token::e_ne ); 04059 | add_invalid(t, lexer::token::e_gte ); 04060 | add_invalid(t, lexer::token::e_lt ); 04061 | add_invalid(t, lexer::token::e_gt ); 04062 | add_invalid(t, lexer::token::e_eq ); 04063 | add_invalid(t, lexer::token::e_comma ); 04064 | add_invalid(t, lexer::token::e_div ); 04065 | add_invalid(t, lexer::token::e_mul ); 04066 | add_invalid(t, lexer::token::e_mod ); 04067 | add_invalid(t, lexer::token::e_pow ); 04068 | add_invalid(t, lexer::token::e_colon ); 04069 | } 04070 | 04071 | bool invalid_bracket_check(const lexer::token::token_type base, const lexer::token::token_type t) 04072 | { 04073 | if (details::is_right_bracket(static_cast<details::char_t>(base))) 04074 | { 04075 | switch (t) 04076 | { 04077 | case lexer::token::e_assign : return (']' != base); 04078 | case lexer::token::e_string : return (')' != base); 04079 | default : return false; 04080 | } 04081 | } 04082 | else if (details::is_left_bracket(static_cast<details::char_t>(base))) 04083 | { 04084 | if (details::is_right_bracket(static_cast<details::char_t>(t))) 04085 | return false; 04086 | else if (details::is_left_bracket(static_cast<details::char_t>(t))) 04087 | return false; 04088 | else 04089 | { 04090 | switch (t) 04091 | { 04092 | case lexer::token::e_number : return false; 04093 | case lexer::token::e_symbol : return false; 04094 | case lexer::token::e_string : return false; 04095 | case lexer::token::e_add : return false; 04096 | case lexer::token::e_sub : return false; 04097 | case lexer::token::e_colon : return false; 04098 | case lexer::token::e_ternary : return false; 04099 | default : return true ; 04100 | } 04101 | } 04102 | } 04103 | else if (details::is_right_bracket(static_cast<details::char_t>(t))) 04104 | { 04105 | switch (base) 04106 | { 04107 | case lexer::token::e_number : return false; 04108 | case lexer::token::e_symbol : return false; 04109 | case lexer::token::e_string : return false; 04110 | case lexer::token::e_eof : return false; 04111 | case lexer::token::e_colon : return false; 04112 | case lexer::token::e_ternary : return false; 04113 | default : return true ; 04114 | } 04115 | } 04116 | else if (details::is_left_bracket(static_cast<details::char_t>(t))) 04117 | { 04118 | switch (base) 04119 | { 04120 | case lexer::token::e_rbracket : return true; 04121 | case lexer::token::e_rsqrbracket : return true; 04122 | case lexer::token::e_rcrlbracket : return true; 04123 | default : return false; 04124 | } 04125 | } 04126 | 04127 | return false; 04128 | } 04129 | 04130 | set_t invalid_comb_; 04131 | std::vector<std::pair<lexer::token,lexer::token> > error_list_; 04132 | }; 04133 | 04134 | class sequence_validator_3tokens exprtk_final : public lexer::token_scanner 04135 | { 04136 | private: 04137 | 04138 | typedef lexer::token::token_type token_t; 04139 | typedef std::pair<token_t,std::pair<token_t,token_t> > token_triplet_t; 04140 | typedef std::set<token_triplet_t> set_t; 04141 | 04142 | public: 04143 | 04144 | using lexer::token_scanner::operator(); 04145 | 04146 | sequence_validator_3tokens() 04147 | : lexer::token_scanner(3) 04148 | { 04149 | add_invalid(lexer::token::e_number , lexer::token::e_number , lexer::token::e_number); 04150 | add_invalid(lexer::token::e_string , lexer::token::e_string , lexer::token::e_string); 04151 | add_invalid(lexer::token::e_comma , lexer::token::e_comma , lexer::token::e_comma ); 04152 | 04153 | add_invalid(lexer::token::e_add , lexer::token::e_add , lexer::token::e_add ); 04154 | add_invalid(lexer::token::e_sub , lexer::token::e_sub , lexer::token::e_sub ); 04155 | add_invalid(lexer::token::e_div , lexer::token::e_div , lexer::token::e_div ); 04156 | add_invalid(lexer::token::e_mul , lexer::token::e_mul , lexer::token::e_mul ); 04157 | add_invalid(lexer::token::e_mod , lexer::token::e_mod , lexer::token::e_mod ); 04158 | add_invalid(lexer::token::e_pow , lexer::token::e_pow , lexer::token::e_pow ); 04159 | 04160 | add_invalid(lexer::token::e_add , lexer::token::e_sub , lexer::token::e_add ); 04161 | add_invalid(lexer::token::e_sub , lexer::token::e_add , lexer::token::e_sub ); 04162 | add_invalid(lexer::token::e_div , lexer::token::e_mul , lexer::token::e_div ); 04163 | add_invalid(lexer::token::e_mul , lexer::token::e_div , lexer::token::e_mul ); 04164 | add_invalid(lexer::token::e_mod , lexer::token::e_pow , lexer::token::e_mod ); 04165 | add_invalid(lexer::token::e_pow , lexer::token::e_mod , lexer::token::e_pow ); 04166 | } 04167 | 04168 | bool result() exprtk_override 04169 | { 04170 | return error_list_.empty(); 04171 | } 04172 | 04173 | bool operator() (const lexer::token& t0, const lexer::token& t1, const lexer::token& t2) exprtk_override 04174 | { 04175 | const set_t::value_type p = std::make_pair(t0.type,std::make_pair(t1.type,t2.type)); 04176 | 04177 | if (invalid_comb_.find(p) != invalid_comb_.end()) 04178 | { 04179 | error_list_.push_back(std::make_pair(t0,t1)); 04180 | } 04181 | 04182 | return true; 04183 | } 04184 | 04185 | std::size_t error_count() const 04186 | { 04187 | return error_list_.size(); 04188 | } 04189 | 04190 | std::pair<lexer::token,lexer::token> error(const std::size_t index) 04191 | { 04192 | if (index < error_list_.size()) 04193 | { 04194 | return error_list_[index]; 04195 | } 04196 | else 04197 | { 04198 | static const lexer::token error_token; 04199 | return std::make_pair(error_token,error_token); 04200 | } 04201 | } 04202 | 04203 | void clear_errors() 04204 | { 04205 | error_list_.clear(); 04206 | } 04207 | 04208 | private: 04209 | 04210 | void add_invalid(const token_t t0, const token_t t1, const token_t t2) 04211 | { 04212 | invalid_comb_.insert(std::make_pair(t0,std::make_pair(t1,t2))); 04213 | } 04214 | 04215 | set_t invalid_comb_; 04216 | std::vector<std::pair<lexer::token,lexer::token> > error_list_; 04217 | }; 04218 | 04219 | struct helper_assembly 04220 | { 04221 | inline bool register_scanner(lexer::token_scanner* scanner) 04222 | { 04223 | if (token_scanner_list.end() != std::find(token_scanner_list.begin(), 04224 | token_scanner_list.end (), 04225 | scanner)) 04226 | { 04227 | return false; 04228 | } 04229 | 04230 | token_scanner_list.push_back(scanner); 04231 | 04232 | return true; 04233 | } 04234 | 04235 | inline bool register_modifier(lexer::token_modifier* modifier) 04236 | { 04237 | if (token_modifier_list.end() != std::find(token_modifier_list.begin(), 04238 | token_modifier_list.end (), 04239 | modifier)) 04240 | { 04241 | return false; 04242 | } 04243 | 04244 | token_modifier_list.push_back(modifier); 04245 | 04246 | return true; 04247 | } 04248 | 04249 | inline bool register_joiner(lexer::token_joiner* joiner) 04250 | { 04251 | if (token_joiner_list.end() != std::find(token_joiner_list.begin(), 04252 | token_joiner_list.end (), 04253 | joiner)) 04254 | { 04255 | return false; 04256 | } 04257 | 04258 | token_joiner_list.push_back(joiner); 04259 | 04260 | return true; 04261 | } 04262 | 04263 | inline bool register_inserter(lexer::token_inserter* inserter) 04264 | { 04265 | if (token_inserter_list.end() != std::find(token_inserter_list.begin(), 04266 | token_inserter_list.end (), 04267 | inserter)) 04268 | { 04269 | return false; 04270 | } 04271 | 04272 | token_inserter_list.push_back(inserter); 04273 | 04274 | return true; 04275 | } 04276 | 04277 | inline bool run_modifiers(lexer::generator& g) 04278 | { 04279 | error_token_modifier = reinterpret_cast<lexer::token_modifier*>(0); 04280 | 04281 | for (std::size_t i = 0; i < token_modifier_list.size(); ++i) 04282 | { 04283 | lexer::token_modifier& modifier = (*token_modifier_list[i]); 04284 | 04285 | modifier.reset(); 04286 | modifier.process(g); 04287 | 04288 | if (!modifier.result()) 04289 | { 04290 | error_token_modifier = token_modifier_list[i]; 04291 | 04292 | return false; 04293 | } 04294 | } 04295 | 04296 | return true; 04297 | } 04298 | 04299 | inline bool run_joiners(lexer::generator& g) 04300 | { 04301 | error_token_joiner = reinterpret_cast<lexer::token_joiner*>(0); 04302 | 04303 | for (std::size_t i = 0; i < token_joiner_list.size(); ++i) 04304 | { 04305 | lexer::token_joiner& joiner = (*token_joiner_list[i]); 04306 | 04307 | joiner.reset(); 04308 | joiner.process(g); 04309 | 04310 | if (!joiner.result()) 04311 | { 04312 | error_token_joiner = token_joiner_list[i]; 04313 | 04314 | return false; 04315 | } 04316 | } 04317 | 04318 | return true; 04319 | } 04320 | 04321 | inline bool run_inserters(lexer::generator& g) 04322 | { 04323 | error_token_inserter = reinterpret_cast<lexer::token_inserter*>(0); 04324 | 04325 | for (std::size_t i = 0; i < token_inserter_list.size(); ++i) 04326 | { 04327 | lexer::token_inserter& inserter = (*token_inserter_list[i]); 04328 | 04329 | inserter.reset(); 04330 | inserter.process(g); 04331 | 04332 | if (!inserter.result()) 04333 | { 04334 | error_token_inserter = token_inserter_list[i]; 04335 | 04336 | return false; 04337 | } 04338 | } 04339 | 04340 | return true; 04341 | } 04342 | 04343 | inline bool run_scanners(lexer::generator& g) 04344 | { 04345 | error_token_scanner = reinterpret_cast<lexer::token_scanner*>(0); 04346 | 04347 | for (std::size_t i = 0; i < token_scanner_list.size(); ++i) 04348 | { 04349 | lexer::token_scanner& scanner = (*token_scanner_list[i]); 04350 | 04351 | scanner.reset(); 04352 | scanner.process(g); 04353 | 04354 | if (!scanner.result()) 04355 | { 04356 | error_token_scanner = token_scanner_list[i]; 04357 | 04358 | return false; 04359 | } 04360 | } 04361 | 04362 | return true; 04363 | } 04364 | 04365 | std::vector<lexer::token_scanner*> token_scanner_list; 04366 | std::vector<lexer::token_modifier*> token_modifier_list; 04367 | std::vector<lexer::token_joiner*> token_joiner_list; 04368 | std::vector<lexer::token_inserter*> token_inserter_list; 04369 | 04370 | lexer::token_scanner* error_token_scanner; 04371 | lexer::token_modifier* error_token_modifier; 04372 | lexer::token_joiner* error_token_joiner; 04373 | lexer::token_inserter* error_token_inserter; 04374 | }; 04375 | } 04376 | 04377 | class parser_helper 04378 | { 04379 | public: 04380 | 04381 | typedef token token_t; 04382 | typedef generator generator_t; 04383 | 04384 | inline bool init(const std::string& str) 04385 | { 04386 | if (!lexer_.process(str)) 04387 | { 04388 | return false; 04389 | } 04390 | 04391 | lexer_.begin(); 04392 | 04393 | next_token(); 04394 | 04395 | return true; 04396 | } 04397 | 04398 | inline generator_t& lexer() 04399 | { 04400 | return lexer_; 04401 | } 04402 | 04403 | inline const generator_t& lexer() const 04404 | { 04405 | return lexer_; 04406 | } 04407 | 04408 | inline void store_token() 04409 | { 04410 | lexer_.store(); 04411 | store_current_token_ = current_token_; 04412 | } 04413 | 04414 | inline void restore_token() 04415 | { 04416 | lexer_.restore(); 04417 | current_token_ = store_current_token_; 04418 | } 04419 | 04420 | inline void next_token() 04421 | { 04422 | current_token_ = lexer_.next_token(); 04423 | } 04424 | 04425 | inline const token_t& current_token() const 04426 | { 04427 | return current_token_; 04428 | } 04429 | 04430 | inline const token_t& peek_next_token() 04431 | { 04432 | return lexer_.peek_next_token(); 04433 | } 04434 | 04435 | enum token_advance_mode 04436 | { 04437 | e_hold = 0, 04438 | e_advance = 1 04439 | }; 04440 | 04441 | inline void advance_token(const token_advance_mode mode) 04442 | { 04443 | if (e_advance == mode) 04444 | { 04445 | next_token(); 04446 | } 04447 | } 04448 | 04449 | inline bool token_is(const token_t::token_type& ttype, const token_advance_mode mode = e_advance) 04450 | { 04451 | if (current_token().type != ttype) 04452 | { 04453 | return false; 04454 | } 04455 | 04456 | advance_token(mode); 04457 | 04458 | return true; 04459 | } 04460 | 04461 | inline bool token_is(const token_t::token_type& ttype, 04462 | const std::string& value, 04463 | const token_advance_mode mode = e_advance) 04464 | { 04465 | if ( 04466 | (current_token().type != ttype) || 04467 | !exprtk::details::imatch(value,current_token().value) 04468 | ) 04469 | { 04470 | return false; 04471 | } 04472 | 04473 | advance_token(mode); 04474 | 04475 | return true; 04476 | } 04477 | 04478 | inline bool token_is(const std::string& value, 04479 | const token_advance_mode mode = e_advance) 04480 | { 04481 | if (!exprtk::details::imatch(value,current_token().value)) 04482 | { 04483 | return false; 04484 | } 04485 | 04486 | advance_token(mode); 04487 | 04488 | return true; 04489 | } 04490 | 04491 | inline bool token_is_arithmetic_opr(const token_advance_mode mode = e_advance) 04492 | { 04493 | switch (current_token().type) 04494 | { 04495 | case token_t::e_add : 04496 | case token_t::e_sub : 04497 | case token_t::e_div : 04498 | case token_t::e_mul : 04499 | case token_t::e_mod : 04500 | case token_t::e_pow : break; 04501 | default : return false; 04502 | } 04503 | 04504 | advance_token(mode); 04505 | 04506 | return true; 04507 | } 04508 | 04509 | inline bool token_is_ineq_opr(const token_advance_mode mode = e_advance) 04510 | { 04511 | switch (current_token().type) 04512 | { 04513 | case token_t::e_eq : 04514 | case token_t::e_lte : 04515 | case token_t::e_ne : 04516 | case token_t::e_gte : 04517 | case token_t::e_lt : 04518 | case token_t::e_gt : break; 04519 | default : return false; 04520 | } 04521 | 04522 | advance_token(mode); 04523 | 04524 | return true; 04525 | } 04526 | 04527 | inline bool token_is_left_bracket(const token_advance_mode mode = e_advance) 04528 | { 04529 | switch (current_token().type) 04530 | { 04531 | case token_t::e_lbracket : 04532 | case token_t::e_lcrlbracket : 04533 | case token_t::e_lsqrbracket : break; 04534 | default : return false; 04535 | } 04536 | 04537 | advance_token(mode); 04538 | 04539 | return true; 04540 | } 04541 | 04542 | inline bool token_is_right_bracket(const token_advance_mode mode = e_advance) 04543 | { 04544 | switch (current_token().type) 04545 | { 04546 | case token_t::e_rbracket : 04547 | case token_t::e_rcrlbracket : 04548 | case token_t::e_rsqrbracket : break; 04549 | default : return false; 04550 | } 04551 | 04552 | advance_token(mode); 04553 | 04554 | return true; 04555 | } 04556 | 04557 | inline bool token_is_bracket(const token_advance_mode mode = e_advance) 04558 | { 04559 | switch (current_token().type) 04560 | { 04561 | case token_t::e_rbracket : 04562 | case token_t::e_rcrlbracket : 04563 | case token_t::e_rsqrbracket : 04564 | case token_t::e_lbracket : 04565 | case token_t::e_lcrlbracket : 04566 | case token_t::e_lsqrbracket : break; 04567 | default : return false; 04568 | } 04569 | 04570 | advance_token(mode); 04571 | 04572 | return true; 04573 | } 04574 | 04575 | inline bool token_is_loop(const token_advance_mode mode = e_advance) 04576 | { 04577 | return token_is("for" , mode) || 04578 | token_is("while" , mode) || 04579 | token_is("repeat", mode) ; 04580 | } 04581 | 04582 | inline bool peek_token_is(const token_t::token_type& ttype) 04583 | { 04584 | return (lexer_.peek_next_token().type == ttype); 04585 | } 04586 | 04587 | inline bool peek_token_is(const std::string& s) 04588 | { 04589 | return (exprtk::details::imatch(lexer_.peek_next_token().value,s)); 04590 | } 04591 | 04592 | private: 04593 | 04594 | generator_t lexer_; 04595 | token_t current_token_; 04596 | token_t store_current_token_; 04597 | }; 04598 | } 04599 | 04600 | template <typename T> 04601 | class vector_view 04602 | { 04603 | public: 04604 | 04605 | typedef T* data_ptr_t; 04606 | 04607 | vector_view(data_ptr_t data, const std::size_t& size) 04608 | : base_size_(size) 04609 | , size_(size) 04610 | , data_(data) 04611 | , data_ref_(0) 04612 | { 04613 | assert(size_ > 0); 04614 | } 04615 | 04616 | vector_view(const vector_view<T>& vv) 04617 | : base_size_(vv.base_size_) 04618 | , size_(vv.size_) 04619 | , data_(vv.data_) 04620 | , data_ref_(0) 04621 | { 04622 | assert(size_ > 0); 04623 | } 04624 | 04625 | inline void rebase(data_ptr_t data) 04626 | { 04627 | data_ = data; 04628 | 04629 | if (!data_ref_.empty()) 04630 | { 04631 | for (std::size_t i = 0; i < data_ref_.size(); ++i) 04632 | { 04633 | (*data_ref_[i]) = data; 04634 | } 04635 | } 04636 | } 04637 | 04638 | inline data_ptr_t data() const 04639 | { 04640 | return data_; 04641 | } 04642 | 04643 | inline std::size_t base_size() const 04644 | { 04645 | return base_size_; 04646 | } 04647 | 04648 | inline std::size_t size() const 04649 | { 04650 | return size_; 04651 | } 04652 | 04653 | inline const T& operator[](const std::size_t index) const 04654 | { 04655 | assert(index < size_); 04656 | return data_[index]; 04657 | } 04658 | 04659 | inline T& operator[](const std::size_t index) 04660 | { 04661 | assert(index < size_); 04662 | return data_[index]; 04663 | } 04664 | 04665 | void set_ref(data_ptr_t* data_ref) 04666 | { 04667 | data_ref_.push_back(data_ref); 04668 | exprtk_debug(("vector_view::set_ref() - data_ref: %p data_ref_.size(): %d\n", 04669 | reinterpret_cast<void*>(data_ref), 04670 | static_cast<int>(data_ref_.size()))); 04671 | } 04672 | 04673 | void remove_ref(data_ptr_t* data_ref) 04674 | { 04675 | data_ref_.erase( 04676 | std::remove(data_ref_.begin(), data_ref_.end(), data_ref), 04677 | data_ref_.end()); 04678 | exprtk_debug(("vector_view::remove_ref() - data_ref: %p data_ref_.size(): %d\n", 04679 | reinterpret_cast<void*>(data_ref), 04680 | static_cast<int>(data_ref_.size()))); 04681 | } 04682 | 04683 | bool set_size(const std::size_t new_size) 04684 | { 04685 | if ((new_size > 0) && (new_size <= base_size_)) 04686 | { 04687 | size_ = new_size; 04688 | exprtk_debug(("vector_view::set_size() - data_: %p size: %lu\n", 04689 | reinterpret_cast<void*>(data_), 04690 | size_)); 04691 | return true; 04692 | } 04693 | 04694 | exprtk_debug(("vector_view::set_size() - error invalid new_size: %lu base_size: %lu\n", 04695 | new_size, 04696 | base_size_)); 04697 | return false; 04698 | } 04699 | 04700 | private: 04701 | 04702 | const std::size_t base_size_; 04703 | std::size_t size_; 04704 | data_ptr_t data_; 04705 | std::vector<data_ptr_t*> data_ref_; 04706 | }; 04707 | 04708 | template <typename T> 04709 | inline vector_view<T> make_vector_view(T* data, 04710 | const std::size_t size, const std::size_t offset = 0) 04711 | { 04712 | return vector_view<T>(data + offset, size); 04713 | } 04714 | 04715 | template <typename T> 04716 | inline vector_view<T> make_vector_view(std::vector<T>& v, 04717 | const std::size_t size, const std::size_t offset = 0) 04718 | { 04719 | return vector_view<T>(v.data() + offset, size); 04720 | } 04721 | 04722 | template <typename T> class results_context; 04723 | 04724 | template <typename T> 04725 | struct type_store 04726 | { 04727 | enum store_type 04728 | { 04729 | e_unknown, 04730 | e_scalar , 04731 | e_vector , 04732 | e_string 04733 | }; 04734 | 04735 | type_store() 04736 | : data(0) 04737 | , size(0) 04738 | , type(e_unknown) 04739 | {} 04740 | 04741 | union 04742 | { 04743 | void* data; 04744 | T* vec_data; 04745 | }; 04746 | 04747 | std::size_t size; 04748 | store_type type; 04749 | 04750 | class parameter_list 04751 | { 04752 | public: 04753 | 04754 | explicit parameter_list(std::vector<type_store>& pl) 04755 | : parameter_list_(pl) 04756 | {} 04757 | 04758 | inline bool empty() const 04759 | { 04760 | return parameter_list_.empty(); 04761 | } 04762 | 04763 | inline std::size_t size() const 04764 | { 04765 | return parameter_list_.size(); 04766 | } 04767 | 04768 | inline type_store& operator[](const std::size_t& index) 04769 | { 04770 | return parameter_list_[index]; 04771 | } 04772 | 04773 | inline const type_store& operator[](const std::size_t& index) const 04774 | { 04775 | return parameter_list_[index]; 04776 | } 04777 | 04778 | inline type_store& front() 04779 | { 04780 | return parameter_list_[0]; 04781 | } 04782 | 04783 | inline const type_store& front() const 04784 | { 04785 | return parameter_list_[0]; 04786 | } 04787 | 04788 | inline type_store& back() 04789 | { 04790 | return parameter_list_.back(); 04791 | } 04792 | 04793 | inline const type_store& back() const 04794 | { 04795 | return parameter_list_.back(); 04796 | } 04797 | 04798 | private: 04799 | 04800 | std::vector<type_store>& parameter_list_; 04801 | 04802 | friend class results_context<T>; 04803 | }; 04804 | 04805 | template <typename ViewType> 04806 | struct type_view 04807 | { 04808 | typedef type_store<T> type_store_t; 04809 | typedef ViewType value_t; 04810 | 04811 | explicit type_view(type_store_t& ts) 04812 | : ts_(ts) 04813 | , data_(reinterpret_cast<value_t*>(ts_.data)) 04814 | {} 04815 | 04816 | explicit type_view(const type_store_t& ts) 04817 | : ts_(const_cast<type_store_t&>(ts)) 04818 | , data_(reinterpret_cast<value_t*>(ts_.data)) 04819 | {} 04820 | 04821 | inline std::size_t size() const 04822 | { 04823 | return ts_.size; 04824 | } 04825 | 04826 | inline value_t& operator[](const std::size_t& i) 04827 | { 04828 | return data_[i]; 04829 | } 04830 | 04831 | inline const value_t& operator[](const std::size_t& i) const 04832 | { 04833 | return data_[i]; 04834 | } 04835 | 04836 | inline const value_t* begin() const { return data_; } 04837 | inline value_t* begin() { return data_; } 04838 | 04839 | inline const value_t* end() const 04840 | { 04841 | return static_cast<value_t*>(data_ + ts_.size); 04842 | } 04843 | 04844 | inline value_t* end() 04845 | { 04846 | return static_cast<value_t*>(data_ + ts_.size); 04847 | } 04848 | 04849 | type_store_t& ts_; 04850 | value_t* data_; 04851 | }; 04852 | 04853 | typedef type_view<T> vector_view; 04854 | typedef type_view<char> string_view; 04855 | 04856 | struct scalar_view 04857 | { 04858 | typedef type_store<T> type_store_t; 04859 | typedef T value_t; 04860 | 04861 | explicit scalar_view(type_store_t& ts) 04862 | : v_(*reinterpret_cast<value_t*>(ts.data)) 04863 | {} 04864 | 04865 | explicit scalar_view(const type_store_t& ts) 04866 | : v_(*reinterpret_cast<value_t*>(const_cast<type_store_t&>(ts).data)) 04867 | {} 04868 | 04869 | inline value_t& operator() () 04870 | { 04871 | return v_; 04872 | } 04873 | 04874 | inline const value_t& operator() () const 04875 | { 04876 | return v_; 04877 | } 04878 | 04879 | inline operator value_t() const 04880 | { 04881 | return v_; 04882 | } 04883 | 04884 | inline operator value_t() 04885 | { 04886 | return v_; 04887 | } 04888 | 04889 | template <typename IntType> 04890 | inline bool to_int(IntType& i) const 04891 | { 04892 | if (!exprtk::details::numeric::is_integer(v_)) 04893 | return false; 04894 | 04895 | i = static_cast<IntType>(v_); 04896 | 04897 | return true; 04898 | } 04899 | 04900 | template <typename UIntType> 04901 | inline bool to_uint(UIntType& u) const 04902 | { 04903 | if (v_ < T(0)) 04904 | return false; 04905 | else if (!exprtk::details::numeric::is_integer(v_)) 04906 | return false; 04907 | 04908 | u = static_cast<UIntType>(v_); 04909 | 04910 | return true; 04911 | } 04912 | 04913 | T& v_; 04914 | }; 04915 | }; 04916 | 04917 | template <typename StringView> 04918 | inline std::string to_str(const StringView& view) 04919 | { 04920 | return std::string(view.begin(),view.size()); 04921 | } 04922 | 04923 | #ifndef exprtk_disable_return_statement 04924 | namespace details 04925 | { 04926 | template <typename T> class return_node; 04927 | template <typename T> class return_envelope_node; 04928 | } 04929 | #endif 04930 | 04931 | template <typename T> 04932 | class results_context 04933 | { 04934 | public: 04935 | 04936 | typedef type_store<T> type_store_t; 04937 | typedef typename type_store_t::scalar_view scalar_t; 04938 | typedef typename type_store_t::vector_view vector_t; 04939 | typedef typename type_store_t::string_view string_t; 04940 | 04941 | results_context() 04942 | : results_available_(false) 04943 | {} 04944 | 04945 | inline std::size_t count() const 04946 | { 04947 | if (results_available_) 04948 | return parameter_list_.size(); 04949 | else 04950 | return 0; 04951 | } 04952 | 04953 | inline type_store_t& operator[](const std::size_t& index) 04954 | { 04955 | return parameter_list_[index]; 04956 | } 04957 | 04958 | inline const type_store_t& operator[](const std::size_t& index) const 04959 | { 04960 | return parameter_list_[index]; 04961 | } 04962 | 04963 | inline bool get_scalar(const std::size_t& index, T& out) const 04964 | { 04965 | if ( 04966 | (index < parameter_list_.size()) && 04967 | (parameter_list_[index].type == type_store_t::e_scalar) 04968 | ) 04969 | { 04970 | const scalar_t scalar(parameter_list_[index]); 04971 | out = scalar(); 04972 | return true; 04973 | } 04974 | 04975 | return false; 04976 | } 04977 | 04978 | template <typename OutputIterator> 04979 | inline bool get_vector(const std::size_t& index, OutputIterator out_itr) const 04980 | { 04981 | if ( 04982 | (index < parameter_list_.size()) && 04983 | (parameter_list_[index].type == type_store_t::e_vector) 04984 | ) 04985 | { 04986 | const vector_t vector(parameter_list_[index]); 04987 | for (std::size_t i = 0; i < vector.size(); ++i) 04988 | { 04989 | *(out_itr++) = vector[i]; 04990 | } 04991 | 04992 | return true; 04993 | } 04994 | 04995 | return false; 04996 | } 04997 | 04998 | inline bool get_vector(const std::size_t& index, std::vector<T>& out) const 04999 | { 05000 | return get_vector(index,std::back_inserter(out)); 05001 | } 05002 | 05003 | inline bool get_string(const std::size_t& index, std::string& out) const 05004 | { 05005 | if ( 05006 | (index < parameter_list_.size()) && 05007 | (parameter_list_[index].type == type_store_t::e_string) 05008 | ) 05009 | { 05010 | const string_t str(parameter_list_[index]); 05011 | out.assign(str.begin(),str.size()); 05012 | return true; 05013 | } 05014 | 05015 | return false; 05016 | } 05017 | 05018 | private: 05019 | 05020 | inline void clear() 05021 | { 05022 | results_available_ = false; 05023 | } 05024 | 05025 | typedef std::vector<type_store_t> ts_list_t; 05026 | typedef typename type_store_t::parameter_list parameter_list_t; 05027 | 05028 | inline void assign(const parameter_list_t& pl) 05029 | { 05030 | parameter_list_ = pl.parameter_list_; 05031 | results_available_ = true; 05032 | } 05033 | 05034 | bool results_available_; 05035 | ts_list_t parameter_list_; 05036 | 05037 | #ifndef exprtk_disable_return_statement 05038 | friend class details::return_node<T>; 05039 | friend class details::return_envelope_node<T>; 05040 | #endif 05041 | }; 05042 | 05043 | namespace details 05044 | { 05045 | enum operator_type 05046 | { 05047 | e_default , e_null , e_add , e_sub , 05048 | e_mul , e_div , e_mod , e_pow , 05049 | e_atan2 , e_min , e_max , e_avg , 05050 | e_sum , e_prod , e_lt , e_lte , 05051 | e_eq , e_equal , e_ne , e_nequal , 05052 | e_gte , e_gt , e_and , e_nand , 05053 | e_or , e_nor , e_xor , e_xnor , 05054 | e_mand , e_mor , e_scand , e_scor , 05055 | e_shr , e_shl , e_abs , e_acos , 05056 | e_acosh , e_asin , e_asinh , e_atan , 05057 | e_atanh , e_ceil , e_cos , e_cosh , 05058 | e_exp , e_expm1 , e_floor , e_log , 05059 | e_log10 , e_log2 , e_log1p , e_logn , 05060 | e_neg , e_pos , e_round , e_roundn , 05061 | e_root , e_sqrt , e_sin , e_sinc , 05062 | e_sinh , e_sec , e_csc , e_tan , 05063 | e_tanh , e_cot , e_clamp , e_iclamp , 05064 | e_inrange , e_sgn , e_r2d , e_d2r , 05065 | e_d2g , e_g2d , e_hypot , e_notl , 05066 | e_erf , e_erfc , e_ncdf , e_frac , 05067 | e_trunc , e_assign , e_addass , e_subass , 05068 | e_mulass , e_divass , e_modass , e_in , 05069 | e_like , e_ilike , e_multi , e_smulti , 05070 | e_swap , 05071 | 05072 | // Do not add new functions/operators after this point. 05073 | e_sf00 = 1000, e_sf01 = 1001, e_sf02 = 1002, e_sf03 = 1003, 05074 | e_sf04 = 1004, e_sf05 = 1005, e_sf06 = 1006, e_sf07 = 1007, 05075 | e_sf08 = 1008, e_sf09 = 1009, e_sf10 = 1010, e_sf11 = 1011, 05076 | e_sf12 = 1012, e_sf13 = 1013, e_sf14 = 1014, e_sf15 = 1015, 05077 | e_sf16 = 1016, e_sf17 = 1017, e_sf18 = 1018, e_sf19 = 1019, 05078 | e_sf20 = 1020, e_sf21 = 1021, e_sf22 = 1022, e_sf23 = 1023, 05079 | e_sf24 = 1024, e_sf25 = 1025, e_sf26 = 1026, e_sf27 = 1027, 05080 | e_sf28 = 1028, e_sf29 = 1029, e_sf30 = 1030, e_sf31 = 1031, 05081 | e_sf32 = 1032, e_sf33 = 1033, e_sf34 = 1034, e_sf35 = 1035, 05082 | e_sf36 = 1036, e_sf37 = 1037, e_sf38 = 1038, e_sf39 = 1039, 05083 | e_sf40 = 1040, e_sf41 = 1041, e_sf42 = 1042, e_sf43 = 1043, 05084 | e_sf44 = 1044, e_sf45 = 1045, e_sf46 = 1046, e_sf47 = 1047, 05085 | e_sf48 = 1048, e_sf49 = 1049, e_sf50 = 1050, e_sf51 = 1051, 05086 | e_sf52 = 1052, e_sf53 = 1053, e_sf54 = 1054, e_sf55 = 1055, 05087 | e_sf56 = 1056, e_sf57 = 1057, e_sf58 = 1058, e_sf59 = 1059, 05088 | e_sf60 = 1060, e_sf61 = 1061, e_sf62 = 1062, e_sf63 = 1063, 05089 | e_sf64 = 1064, e_sf65 = 1065, e_sf66 = 1066, e_sf67 = 1067, 05090 | e_sf68 = 1068, e_sf69 = 1069, e_sf70 = 1070, e_sf71 = 1071, 05091 | e_sf72 = 1072, e_sf73 = 1073, e_sf74 = 1074, e_sf75 = 1075, 05092 | e_sf76 = 1076, e_sf77 = 1077, e_sf78 = 1078, e_sf79 = 1079, 05093 | e_sf80 = 1080, e_sf81 = 1081, e_sf82 = 1082, e_sf83 = 1083, 05094 | e_sf84 = 1084, e_sf85 = 1085, e_sf86 = 1086, e_sf87 = 1087, 05095 | e_sf88 = 1088, e_sf89 = 1089, e_sf90 = 1090, e_sf91 = 1091, 05096 | e_sf92 = 1092, e_sf93 = 1093, e_sf94 = 1094, e_sf95 = 1095, 05097 | e_sf96 = 1096, e_sf97 = 1097, e_sf98 = 1098, e_sf99 = 1099, 05098 | e_sffinal = 1100, 05099 | e_sf4ext00 = 2000, e_sf4ext01 = 2001, e_sf4ext02 = 2002, e_sf4ext03 = 2003, 05100 | e_sf4ext04 = 2004, e_sf4ext05 = 2005, e_sf4ext06 = 2006, e_sf4ext07 = 2007, 05101 | e_sf4ext08 = 2008, e_sf4ext09 = 2009, e_sf4ext10 = 2010, e_sf4ext11 = 2011, 05102 | e_sf4ext12 = 2012, e_sf4ext13 = 2013, e_sf4ext14 = 2014, e_sf4ext15 = 2015, 05103 | e_sf4ext16 = 2016, e_sf4ext17 = 2017, e_sf4ext18 = 2018, e_sf4ext19 = 2019, 05104 | e_sf4ext20 = 2020, e_sf4ext21 = 2021, e_sf4ext22 = 2022, e_sf4ext23 = 2023, 05105 | e_sf4ext24 = 2024, e_sf4ext25 = 2025, e_sf4ext26 = 2026, e_sf4ext27 = 2027, 05106 | e_sf4ext28 = 2028, e_sf4ext29 = 2029, e_sf4ext30 = 2030, e_sf4ext31 = 2031, 05107 | e_sf4ext32 = 2032, e_sf4ext33 = 2033, e_sf4ext34 = 2034, e_sf4ext35 = 2035, 05108 | e_sf4ext36 = 2036, e_sf4ext37 = 2037, e_sf4ext38 = 2038, e_sf4ext39 = 2039, 05109 | e_sf4ext40 = 2040, e_sf4ext41 = 2041, e_sf4ext42 = 2042, e_sf4ext43 = 2043, 05110 | e_sf4ext44 = 2044, e_sf4ext45 = 2045, e_sf4ext46 = 2046, e_sf4ext47 = 2047, 05111 | e_sf4ext48 = 2048, e_sf4ext49 = 2049, e_sf4ext50 = 2050, e_sf4ext51 = 2051, 05112 | e_sf4ext52 = 2052, e_sf4ext53 = 2053, e_sf4ext54 = 2054, e_sf4ext55 = 2055, 05113 | e_sf4ext56 = 2056, e_sf4ext57 = 2057, e_sf4ext58 = 2058, e_sf4ext59 = 2059, 05114 | e_sf4ext60 = 2060, e_sf4ext61 = 2061 05115 | }; 05116 | 05117 | inline std::string to_str(const operator_type opr) 05118 | { 05119 | switch (opr) 05120 | { 05121 | case e_add : return "+" ; 05122 | case e_sub : return "-" ; 05123 | case e_mul : return "*" ; 05124 | case e_div : return "/" ; 05125 | case e_mod : return "%" ; 05126 | case e_pow : return "^" ; 05127 | case e_assign : return ":=" ; 05128 | case e_addass : return "+=" ; 05129 | case e_subass : return "-=" ; 05130 | case e_mulass : return "*=" ; 05131 | case e_divass : return "/=" ; 05132 | case e_modass : return "%=" ; 05133 | case e_lt : return "<" ; 05134 | case e_lte : return "<=" ; 05135 | case e_eq : return "==" ; 05136 | case e_equal : return "=" ; 05137 | case e_ne : return "!=" ; 05138 | case e_nequal : return "<>" ; 05139 | case e_gte : return ">=" ; 05140 | case e_gt : return ">" ; 05141 | case e_and : return "and" ; 05142 | case e_or : return "or" ; 05143 | case e_xor : return "xor" ; 05144 | case e_nand : return "nand" 05145 | case e_nor : return "nor" ; 05146 | case e_xnor : return "xnor" 05147 | default : return "N/A" ; 05148 | } 05149 | } 05150 | 05151 | struct base_operation_t 05152 | { 05153 | base_operation_t(const operator_type t, const unsigned int& np) 05154 | : type(t) 05155 | , num_params(np) 05156 | {} 05157 | 05158 | operator_type type; 05159 | unsigned int num_params; 05160 | }; 05161 | 05162 | namespace loop_unroll 05163 | { 05164 | const unsigned int global_loop_batch_size = 05165 | #ifndef exprtk_disable_superscalar_unroll 05166 | 16; 05167 | #else 05168 | 4; 05169 | #endif 05170 | 05171 | struct details 05172 | { 05173 | explicit details(const std::size_t& vsize, 05174 | const unsigned int loop_batch_size = global_loop_batch_size) 05175 | : batch_size(loop_batch_size ) 05176 | , remainder (vsize % batch_size) 05177 | , upper_bound(static_cast<int>(vsize - (remainder ? loop_batch_size : 0))) 05178 | {} 05179 | 05180 | unsigned int batch_size; 05181 | int remainder; 05182 | int upper_bound; 05183 | }; 05184 | } 05185 | 05186 | #ifdef exprtk_enable_debugging 05187 | inline void dump_ptr(const std::string& s, const void* ptr, const std::size_t size = 0) 05188 | { 05189 | if (size) 05190 | exprtk_debug(("%s - addr: %p size: %d\n", 05191 | s.c_str(), 05192 | ptr, 05193 | static_cast<unsigned int>(size))); 05194 | else 05195 | exprtk_debug(("%s - addr: %p\n", s.c_str(), ptr)); 05196 | } 05197 | 05198 | template <typename T> 05199 | inline void dump_vector(const std::string& vec_name, const T* data, const std::size_t size) 05200 | { 05201 | printf("----- %s (%p) -----\n", 05202 | vec_name.c_str(), 05203 | static_cast<const void*>(data)); 05204 | printf("[ "); 05205 | for (std::size_t i = 0; i < size; ++i) 05206 | { 05207 | printf("%8.3f\t", data[i]); 05208 | } 05209 | printf(" ]\n"); 05210 | printf("---------------------\n"); 05211 | } 05212 | #else 05213 | inline void dump_ptr(const std::string&, const void*) {} 05214 | inline void dump_ptr(const std::string&, const void*, const std::size_t) {} 05215 | template <typename T> 05216 | inline void dump_vector(const std::string&, const T*, const std::size_t) {} 05217 | #endif 05218 | 05219 | template <typename T> 05220 | class vec_data_store 05221 | { 05222 | public: 05223 | 05224 | typedef vec_data_store<T> type; 05225 | typedef T* data_t; 05226 | 05227 | private: 05228 | 05229 | struct control_block 05230 | { 05231 | control_block() 05232 | : ref_count(1) 05233 | , size (0) 05234 | , data (0) 05235 | , destruct (true) 05236 | {} 05237 | 05238 | explicit control_block(const std::size_t& dsize) 05239 | : ref_count(1 ) 05240 | , size (dsize) 05241 | , data (0 ) 05242 | , destruct (true ) 05243 | { create_data(); } 05244 | 05245 | control_block(const std::size_t& dsize, data_t dptr, bool dstrct = false) 05246 | : ref_count(1 ) 05247 | , size (dsize ) 05248 | , data (dptr ) 05249 | , destruct (dstrct) 05250 | {} 05251 | 05252 | ~control_block() 05253 | { 05254 | if (data && destruct && (0 == ref_count)) 05255 | { 05256 | dump_ptr("~vec_data_store::control_block() data",data); 05257 | delete[] data; 05258 | data = reinterpret_cast<data_t>(0); 05259 | } 05260 | } 05261 | 05262 | static inline control_block* create(const std::size_t& dsize, data_t data_ptr = data_t(0), bool dstrct = false) 05263 | { 05264 | if (dsize) 05265 | { 05266 | if (0 == data_ptr) 05267 | return (new control_block(dsize)); 05268 | else 05269 | return (new control_block(dsize, data_ptr, dstrct)); 05270 | } 05271 | else 05272 | return (new control_block); 05273 | } 05274 | 05275 | static inline void destroy(control_block*& cntrl_blck) 05276 | { 05277 | if (cntrl_blck) 05278 | { 05279 | if ( 05280 | (0 != cntrl_blck->ref_count) && 05281 | (0 == --cntrl_blck->ref_count) 05282 | ) 05283 | { 05284 | delete cntrl_blck; 05285 | } 05286 | 05287 | cntrl_blck = 0; 05288 | } 05289 | } 05290 | 05291 | std::size_t ref_count; 05292 | std::size_t size; 05293 | data_t data; 05294 | bool destruct; 05295 | 05296 | private: 05297 | 05298 | control_block(const control_block&) exprtk_delete; 05299 | control_block& operator=(const control_block&) exprtk_delete; 05300 | 05301 | inline void create_data() 05302 | { 05303 | destruct = true; 05304 | data = new T[size]; 05305 | std::fill_n(data, size, T(0)); 05306 | dump_ptr("control_block::create_data() - data", data, size); 05307 | } 05308 | }; 05309 | 05310 | public: 05311 | 05312 | vec_data_store() 05313 | : control_block_(control_block::create(0)) 05314 | {} 05315 | 05316 | explicit vec_data_store(const std::size_t& size) 05317 | : control_block_(control_block::create(size,reinterpret_cast<data_t>(0),true)) 05318 | {} 05319 | 05320 | vec_data_store(const std::size_t& size, data_t data, bool dstrct = false) 05321 | : control_block_(control_block::create(size, data, dstrct)) 05322 | {} 05323 | 05324 | vec_data_store(const type& vds) 05325 | { 05326 | control_block_ = vds.control_block_; 05327 | control_block_->ref_count++; 05328 | } 05329 | 05330 | ~vec_data_store() 05331 | { 05332 | control_block::destroy(control_block_); 05333 | } 05334 | 05335 | type& operator=(const type& vds) 05336 | { 05337 | if (this != &vds) 05338 | { 05339 | const std::size_t final_size = min_size(control_block_, vds.control_block_); 05340 | 05341 | vds.control_block_->size = final_size; 05342 | control_block_->size = final_size; 05343 | 05344 | if (control_block_->destruct || (0 == control_block_->data)) 05345 | { 05346 | control_block::destroy(control_block_); 05347 | 05348 | control_block_ = vds.control_block_; 05349 | control_block_->ref_count++; 05350 | } 05351 | } 05352 | 05353 | return (*this); 05354 | } 05355 | 05356 | inline data_t data() 05357 | { 05358 | return control_block_->data; 05359 | } 05360 | 05361 | inline data_t data() const 05362 | { 05363 | return control_block_->data; 05364 | } 05365 | 05366 | inline std::size_t size() const 05367 | { 05368 | return control_block_->size; 05369 | } 05370 | 05371 | inline data_t& ref() 05372 | { 05373 | return control_block_->data; 05374 | } 05375 | 05376 | inline void dump() const 05377 | { 05378 | #ifdef exprtk_enable_debugging 05379 | exprtk_debug(("size: %d\taddress:%p\tdestruct:%c\n", 05380 | size(), 05381 | data(), 05382 | (control_block_->destruct ? 'T' : 'F'))); 05383 | 05384 | for (std::size_t i = 0; i < size(); ++i) 05385 | { 05386 | if (5 == i) 05387 | exprtk_debug(("\n")); 05388 | 05389 | exprtk_debug(("%15.10f ", data()[i])); 05390 | } 05391 | exprtk_debug(("\n")); 05392 | #endif 05393 | } 05394 | 05395 | static inline void match_sizes(type& vds0, type& vds1) 05396 | { 05397 | const std::size_t size = min_size(vds0.control_block_,vds1.control_block_); 05398 | vds0.control_block_->size = size; 05399 | vds1.control_block_->size = size; 05400 | } 05401 | 05402 | private: 05403 | 05404 | static inline std::size_t min_size(const control_block* cb0, const control_block* cb1) 05405 | { 05406 | const std::size_t size0 = cb0->size; 05407 | const std::size_t size1 = cb1->size; 05408 | 05409 | if (size0 && size1) 05410 | return std::min(size0,size1); 05411 | else 05412 | return (size0) ? size0 : size1; 05413 | } 05414 | 05415 | control_block* control_block_; 05416 | }; 05417 | 05418 | namespace numeric 05419 | { 05420 | namespace details 05421 | { 05422 | template <typename T> 05423 | inline T process_impl(const operator_type operation, const T arg) 05424 | { 05425 | switch (operation) 05426 | { 05427 | case e_abs : return numeric::abs (arg); 05428 | case e_acos : return numeric::acos (arg); 05429 | case e_acosh : return numeric::acosh(arg); 05430 | case e_asin : return numeric::asin (arg); 05431 | case e_asinh : return numeric::asinh(arg); 05432 | case e_atan : return numeric::atan (arg); 05433 | case e_atanh : return numeric::atanh(arg); 05434 | case e_ceil : return numeric::ceil (arg); 05435 | case e_cos : return numeric::cos (arg); 05436 | case e_cosh : return numeric::cosh (arg); 05437 | case e_exp : return numeric::exp (arg); 05438 | case e_expm1 : return numeric::expm1(arg); 05439 | case e_floor : return numeric::floor(arg); 05440 | case e_log : return numeric::log (arg); 05441 | case e_log10 : return numeric::log10(arg); 05442 | case e_log2 : return numeric::log2 (arg); 05443 | case e_log1p : return numeric::log1p(arg); 05444 | case e_neg : return numeric::neg (arg); 05445 | case e_pos : return numeric::pos (arg); 05446 | case e_round : return numeric::round(arg); 05447 | case e_sin : return numeric::sin (arg); 05448 | case e_sinc : return numeric::sinc (arg); 05449 | case e_sinh : return numeric::sinh (arg); 05450 | case e_sqrt : return numeric::sqrt (arg); 05451 | case e_tan : return numeric::tan (arg); 05452 | case e_tanh : return numeric::tanh (arg); 05453 | case e_cot : return numeric::cot (arg); 05454 | case e_sec : return numeric::sec (arg); 05455 | case e_csc : return numeric::csc (arg); 05456 | case e_r2d : return numeric::r2d (arg); 05457 | case e_d2r : return numeric::d2r (arg); 05458 | case e_d2g : return numeric::d2g (arg); 05459 | case e_g2d : return numeric::g2d (arg); 05460 | case e_notl : return numeric::notl (arg); 05461 | case e_sgn : return numeric::sgn (arg); 05462 | case e_erf : return numeric::erf (arg); 05463 | case e_erfc : return numeric::erfc (arg); 05464 | case e_ncdf : return numeric::ncdf (arg); 05465 | case e_frac : return numeric::frac (arg); 05466 | case e_trunc : return numeric::trunc(arg); 05467 | 05468 | default : exprtk_debug(("numeric::details::process_impl<T> - Invalid unary operation.\n")); 05469 | return std::numeric_limits<T>::quiet_NaN(); 05470 | } 05471 | } 05472 | 05473 | template <typename T> 05474 | inline T process_impl(const operator_type operation, const T arg0, const T arg1) 05475 | { 05476 | switch (operation) 05477 | { 05478 | case e_add : return (arg0 + arg1); 05479 | case e_sub : return (arg0 - arg1); 05480 | case e_mul : return (arg0 * arg1); 05481 | case e_div : return (arg0 / arg1); 05482 | case e_mod : return modulus<T>(arg0,arg1); 05483 | case e_pow : return pow<T>(arg0,arg1); 05484 | case e_atan2 : return atan2<T>(arg0,arg1); 05485 | case e_min : return std::min<T>(arg0,arg1); 05486 | case e_max : return std::max<T>(arg0,arg1); 05487 | case e_logn : return logn<T>(arg0,arg1); 05488 | case e_lt : return (arg0 < arg1) ? T(1) : T(0); 05489 | case e_lte : return (arg0 <= arg1) ? T(1) : T(0); 05490 | case e_eq : return std::equal_to<T>()(arg0,arg1) ? T(1) : T(0); 05491 | case e_ne : return std::not_equal_to<T>()(arg0,arg1) ? T(1) : T(0); 05492 | case e_gte : return (arg0 >= arg1) ? T(1) : T(0); 05493 | case e_gt : return (arg0 > arg1) ? T(1) : T(0); 05494 | case e_and : return and_opr <T>(arg0,arg1); 05495 | case e_nand : return nand_opr<T>(arg0,arg1); 05496 | case e_or : return or_opr <T>(arg0,arg1); 05497 | case e_nor : return nor_opr <T>(arg0,arg1); 05498 | case e_xor : return xor_opr <T>(arg0,arg1); 05499 | case e_xnor : return xnor_opr<T>(arg0,arg1); 05500 | case e_root : return root <T>(arg0,arg1); 05501 | case e_roundn : return roundn <T>(arg0,arg1); 05502 | case e_equal : return equal <T>(arg0,arg1); 05503 | case e_nequal : return nequal <T>(arg0,arg1); 05504 | case e_hypot : return hypot <T>(arg0,arg1); 05505 | case e_shr : return shr <T>(arg0,arg1); 05506 | case e_shl : return shl <T>(arg0,arg1); 05507 | 05508 | default : exprtk_debug(("numeric::details::process_impl<T> - Invalid binary operation.\n")); 05509 | return std::numeric_limits<T>::quiet_NaN(); 05510 | } 05511 | } 05512 | 05513 | template <typename T> 05514 | inline T process_impl(const operator_type operation, const T arg0, const T arg1, int_type_tag) 05515 | { 05516 | switch (operation) 05517 | { 05518 | case e_add : return (arg0 + arg1); 05519 | case e_sub : return (arg0 - arg1); 05520 | case e_mul : return (arg0 * arg1); 05521 | case e_div : return (arg0 / arg1); 05522 | case e_mod : return arg0 % arg1; 05523 | case e_pow : return pow<T>(arg0,arg1); 05524 | case e_min : return std::min<T>(arg0,arg1); 05525 | case e_max : return std::max<T>(arg0,arg1); 05526 | case e_logn : return logn<T>(arg0,arg1); 05527 | case e_lt : return (arg0 < arg1) ? T(1) : T(0); 05528 | case e_lte : return (arg0 <= arg1) ? T(1) : T(0); 05529 | case e_eq : return (arg0 == arg1) ? T(1) : T(0); 05530 | case e_ne : return (arg0 != arg1) ? T(1) : T(0); 05531 | case e_gte : return (arg0 >= arg1) ? T(1) : T(0); 05532 | case e_gt : return (arg0 > arg1) ? T(1) : T(0); 05533 | case e_and : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(1) : T(0); 05534 | case e_nand : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(0) : T(1); 05535 | case e_or : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(1) : T(0); 05536 | case e_nor : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(0) : T(1); 05537 | case e_xor : return arg0 ^ arg1; 05538 | case e_xnor : return !(arg0 ^ arg1); 05539 | case e_root : return root<T>(arg0,arg1); 05540 | case e_equal : return arg0 == arg1; 05541 | case e_nequal : return arg0 != arg1; 05542 | case e_hypot : return hypot<T>(arg0,arg1); 05543 | case e_shr : return arg0 >> arg1; 05544 | case e_shl : return arg0 << arg1; 05545 | 05546 | default : exprtk_debug(("numeric::details::process_impl<IntType> - Invalid binary operation.\n")); 05547 | return std::numeric_limits<T>::quiet_NaN(); 05548 | } 05549 | } 05550 | } 05551 | 05552 | template <typename T> 05553 | inline T process(const operator_type operation, const T arg) 05554 | { 05555 | return exprtk::details::numeric::details::process_impl(operation,arg); 05556 | } 05557 | 05558 | template <typename T> 05559 | inline T process(const operator_type operation, const T arg0, const T arg1) 05560 | { 05561 | return exprtk::details::numeric::details::process_impl(operation, arg0, arg1); 05562 | } 05563 | } 05564 | 05565 | template <typename Node> 05566 | struct node_collector_interface 05567 | { 05568 | typedef Node* node_ptr_t; 05569 | typedef Node** node_pp_t; 05570 | typedef std::vector<node_pp_t> noderef_list_t; 05571 | 05572 | virtual ~node_collector_interface() 05573 | {} 05574 | 05575 | virtual void collect_nodes(noderef_list_t&) 05576 | {} 05577 | }; 05578 | 05579 | template <typename Node> 05580 | struct node_depth_base; 05581 | 05582 | template <typename T> 05583 | class expression_node : public node_collector_interface<expression_node<T> > 05584 | , public node_depth_base<expression_node<T> > 05585 | { 05586 | public: 05587 | 05588 | enum node_type 05589 | { 05590 | e_none , e_null , e_constant , e_unary , 05591 | e_binary , e_binary_ext , e_trinary , e_quaternary , 05592 | e_vararg , e_conditional , e_while , e_repeat , 05593 | e_for , e_switch , e_mswitch , e_return , 05594 | e_retenv , e_variable , e_stringvar , e_stringconst , 05595 | e_stringvarrng , e_cstringvarrng , e_strgenrange , e_strconcat , 05596 | e_stringvarsize , e_strswap , e_stringsize , e_stringvararg , 05597 | e_function , e_vafunction , e_genfunction , e_strfunction , 05598 | e_strcondition , e_strccondition , e_add , e_sub , 05599 | e_mul , e_div , e_mod , e_pow , 05600 | e_lt , e_lte , e_gt , e_gte , 05601 | e_eq , e_ne , e_and , e_nand , 05602 | e_or , e_nor , e_xor , e_xnor , 05603 | e_in , e_like , e_ilike , e_inranges , 05604 | e_ipow , e_ipowinv , e_abs , e_acos , 05605 | e_acosh , e_asin , e_asinh , e_atan , 05606 | e_atanh , e_ceil , e_cos , e_cosh , 05607 | e_exp , e_expm1 , e_floor , e_log , 05608 | e_log10 , e_log2 , e_log1p , e_neg , 05609 | e_pos , e_round , e_sin , e_sinc , 05610 | e_sinh , e_sqrt , e_tan , e_tanh , 05611 | e_cot , e_sec , e_csc , e_r2d , 05612 | e_d2r , e_d2g , e_g2d , e_notl , 05613 | e_sgn , e_erf , e_erfc , e_ncdf , 05614 | e_frac , e_trunc , e_uvouv , e_vov , 05615 | e_cov , e_voc , e_vob , e_bov , 05616 | e_cob , e_boc , e_vovov , e_vovoc , 05617 | e_vocov , e_covov , e_covoc , e_vovovov , 05618 | e_vovovoc , e_vovocov , e_vocovov , e_covovov , 05619 | e_covocov , e_vocovoc , e_covovoc , e_vococov , 05620 | e_sf3ext , e_sf4ext , e_nulleq , e_strass , 05621 | e_vector , e_vecsize , e_vecelem , e_veccelem , 05622 | e_vecelemrtc , e_veccelemrtc , e_rbvecelem , e_rbvecelemrtc , 05623 | e_rbveccelem , e_rbveccelemrtc , e_vecinit , e_vecvalass , 05624 | e_vecvecass , e_vecopvalass , e_vecopvecass , e_vecfunc , 05625 | e_vecvecswap , e_vecvecineq , e_vecvalineq , e_valvecineq , 05626 | e_vecvecarith , e_vecvalarith , e_valvecarith , e_vecunaryop , 05627 | e_vecondition , e_break , e_continue , e_swap , 05628 | e_assert 05629 | }; 05630 | 05631 | typedef T value_type; 05632 | typedef expression_node<T>* expression_ptr; 05633 | typedef node_collector_interface<expression_node<T> > nci_t; 05634 | typedef typename nci_t::noderef_list_t noderef_list_t; 05635 | typedef node_depth_base<expression_node<T> > ndb_t; 05636 | 05637 | virtual ~expression_node() 05638 | {} 05639 | 05640 | inline virtual T value() const 05641 | { 05642 | return std::numeric_limits<T>::quiet_NaN(); 05643 | } 05644 | 05645 | inline virtual expression_node<T>* branch(const std::size_t& index = 0) const 05646 | { 05647 | return reinterpret_cast<expression_ptr>(index * 0); 05648 | } 05649 | 05650 | inline virtual node_type type() const 05651 | { 05652 | return e_none; 05653 | } 05654 | 05655 | inline virtual bool valid() const 05656 | { 05657 | return true; 05658 | } 05659 | }; // class expression_node 05660 | 05661 | template <typename T> 05662 | inline bool is_generally_string_node(const expression_node<T>* node); 05663 | 05664 | inline bool is_true(const double v) 05665 | { 05666 | return std::not_equal_to<double>()(0.0,v); 05667 | } 05668 | 05669 | inline bool is_true(const long double v) 05670 | { 05671 | return std::not_equal_to<long double>()(0.0L,v); 05672 | } 05673 | 05674 | inline bool is_true(const float v) 05675 | { 05676 | return std::not_equal_to<float>()(0.0f,v); 05677 | } 05678 | 05679 | template <typename T> 05680 | inline bool is_true(const expression_node<T>* node) 05681 | { 05682 | return std::not_equal_to<T>()(T(0),node->value()); 05683 | } 05684 | 05685 | template <typename T> 05686 | inline bool is_true(const std::pair<expression_node<T>*,bool>& node) 05687 | { 05688 | return std::not_equal_to<T>()(T(0),node.first->value()); 05689 | } 05690 | 05691 | template <typename T> 05692 | inline bool is_false(const expression_node<T>* node) 05693 | { 05694 | return std::equal_to<T>()(T(0),node->value()); 05695 | } 05696 | 05697 | template <typename T> 05698 | inline bool is_false(const std::pair<expression_node<T>*,bool>& node) 05699 | { 05700 | return std::equal_to<T>()(T(0),node.first->value()); 05701 | } 05702 | 05703 | template <typename T> 05704 | inline bool is_literal_node(const expression_node<T>* node) 05705 | { 05706 | return node && (details::expression_node<T>::e_constant == node->type()); 05707 | } 05708 | 05709 | template <typename T> 05710 | inline bool is_unary_node(const expression_node<T>* node) 05711 | { 05712 | return node && (details::expression_node<T>::e_unary == node->type()); 05713 | } 05714 | 05715 | template <typename T> 05716 | inline bool is_neg_unary_node(const expression_node<T>* node) 05717 | { 05718 | return node && (details::expression_node<T>::e_neg == node->type()); 05719 | } 05720 | 05721 | template <typename T> 05722 | inline bool is_binary_node(const expression_node<T>* node) 05723 | { 05724 | return node && (details::expression_node<T>::e_binary == node->type()); 05725 | } 05726 | 05727 | template <typename T> 05728 | inline bool is_variable_node(const expression_node<T>* node) 05729 | { 05730 | return node && (details::expression_node<T>::e_variable == node->type()); 05731 | } 05732 | 05733 | template <typename T> 05734 | inline bool is_ivariable_node(const expression_node<T>* node) 05735 | { 05736 | return node && 05737 | ( 05738 | details::expression_node<T>::e_variable == node->type() || 05739 | details::expression_node<T>::e_vecelem == node->type() || 05740 | details::expression_node<T>::e_veccelem == node->type() || 05741 | details::expression_node<T>::e_vecelemrtc == node->type() || 05742 | details::expression_node<T>::e_veccelemrtc == node->type() || 05743 | details::expression_node<T>::e_rbvecelem == node->type() || 05744 | details::expression_node<T>::e_rbveccelem == node->type() || 05745 | details::expression_node<T>::e_rbvecelemrtc == node->type() || 05746 | details::expression_node<T>::e_rbveccelemrtc == node->type() 05747 | ); 05748 | } 05749 | 05750 | template <typename T> 05751 | inline bool is_vector_elem_node(const expression_node<T>* node) 05752 | { 05753 | return node && (details::expression_node<T>::e_vecelem == node->type()); 05754 | } 05755 | 05756 | template <typename T> 05757 | inline bool is_vector_celem_node(const expression_node<T>* node) 05758 | { 05759 | return node && (details::expression_node<T>::e_veccelem == node->type()); 05760 | } 05761 | 05762 | template <typename T> 05763 | inline bool is_vector_elem_rtc_node(const expression_node<T>* node) 05764 | { 05765 | return node && (details::expression_node<T>::e_vecelemrtc == node->type()); 05766 | } 05767 | 05768 | template <typename T> 05769 | inline bool is_vector_celem_rtc_node(const expression_node<T>* node) 05770 | { 05771 | return node && (details::expression_node<T>::e_veccelemrtc == node->type()); 05772 | } 05773 | 05774 | template <typename T> 05775 | inline bool is_rebasevector_elem_node(const expression_node<T>* node) 05776 | { 05777 | return node && (details::expression_node<T>::e_rbvecelem == node->type()); 05778 | } 05779 | 05780 | template <typename T> 05781 | inline bool is_rebasevector_elem_rtc_node(const expression_node<T>* node) 05782 | { 05783 | return node && (details::expression_node<T>::e_rbvecelemrtc == node->type()); 05784 | } 05785 | 05786 | template <typename T> 05787 | inline bool is_rebasevector_celem_rtc_node(const expression_node<T>* node) 05788 | { 05789 | return node && (details::expression_node<T>::e_rbveccelemrtc == node->type()); 05790 | } 05791 | 05792 | template <typename T> 05793 | inline bool is_rebasevector_celem_node(const expression_node<T>* node) 05794 | { 05795 | return node && (details::expression_node<T>::e_rbveccelem == node->type()); 05796 | } 05797 | 05798 | template <typename T> 05799 | inline bool is_vector_node(const expression_node<T>* node) 05800 | { 05801 | return node && (details::expression_node<T>::e_vector == node->type()); 05802 | } 05803 | 05804 | template <typename T> 05805 | inline bool is_ivector_node(const expression_node<T>* node) 05806 | { 05807 | if (node) 05808 | { 05809 | switch (node->type()) 05810 | { 05811 | case details::expression_node<T>::e_vector : 05812 | case details::expression_node<T>::e_vecvalass : 05813 | case details::expression_node<T>::e_vecvecass : 05814 | case details::expression_node<T>::e_vecopvalass : 05815 | case details::expression_node<T>::e_vecopvecass : 05816 | case details::expression_node<T>::e_vecvecswap : 05817 | case details::expression_node<T>::e_vecvecarith : 05818 | case details::expression_node<T>::e_vecvalarith : 05819 | case details::expression_node<T>::e_valvecarith : 05820 | case details::expression_node<T>::e_vecunaryop : 05821 | case details::expression_node<T>::e_vecondition : return true; 05822 | default : return false; 05823 | } 05824 | } 05825 | else 05826 | return false; 05827 | } 05828 | 05829 | template <typename T> 05830 | inline bool is_constant_node(const expression_node<T>* node) 05831 | { 05832 | return node && 05833 | ( 05834 | details::expression_node<T>::e_constant == node->type() || 05835 | details::expression_node<T>::e_stringconst == node->type() 05836 | ); 05837 | } 05838 | 05839 | template <typename T> 05840 | inline bool is_null_node(const expression_node<T>* node) 05841 | { 05842 | return node && (details::expression_node<T>::e_null == node->type()); 05843 | } 05844 | 05845 | template <typename T> 05846 | inline bool is_break_node(const expression_node<T>* node) 05847 | { 05848 | return node && (details::expression_node<T>::e_break == node->type()); 05849 | } 05850 | 05851 | template <typename T> 05852 | inline bool is_continue_node(const expression_node<T>* node) 05853 | { 05854 | return node && (details::expression_node<T>::e_continue == node->type()); 05855 | } 05856 | 05857 | template <typename T> 05858 | inline bool is_swap_node(const expression_node<T>* node) 05859 | { 05860 | return node && (details::expression_node<T>::e_swap == node->type()); 05861 | } 05862 | 05863 | template <typename T> 05864 | inline bool is_function(const expression_node<T>* node) 05865 | { 05866 | return node && (details::expression_node<T>::e_function == node->type()); 05867 | } 05868 | 05869 | template <typename T> 05870 | inline bool is_vararg_node(const expression_node<T>* node) 05871 | { 05872 | return node && (details::expression_node<T>::e_vararg == node->type()); 05873 | } 05874 | 05875 | template <typename T> 05876 | inline bool is_return_node(const expression_node<T>* node) 05877 | { 05878 | return node && (details::expression_node<T>::e_return == node->type()); 05879 | } 05880 | 05881 | template <typename T> class unary_node; 05882 | 05883 | template <typename T> 05884 | inline bool is_negate_node(const expression_node<T>* node) 05885 | { 05886 | if (node && is_unary_node(node)) 05887 | { 05888 | return (details::e_neg == static_cast<const unary_node<T>*>(node)->operation()); 05889 | } 05890 | else 05891 | return false; 05892 | } 05893 | 05894 | template <typename T> 05895 | inline bool is_assert_node(const expression_node<T>* node) 05896 | { 05897 | return node && (details::expression_node<T>::e_assert == node->type()); 05898 | } 05899 | 05900 | template <typename T> 05901 | inline bool branch_deletable(const expression_node<T>* node) 05902 | { 05903 | return (0 != node) && 05904 | !is_variable_node(node) && 05905 | !is_string_node (node) ; 05906 | } 05907 | 05908 | template <std::size_t N, typename T> 05909 | inline bool all_nodes_valid(expression_node<T>* const (&b)[N]) 05910 | { 05911 | for (std::size_t i = 0; i < N; ++i) 05912 | { 05913 | if (0 == b[i]) return false; 05914 | } 05915 | 05916 | return true; 05917 | } 05918 | 05919 | template <typename T, 05920 | typename Allocator, 05921 | template <typename, typename> class Sequence> 05922 | inline bool all_nodes_valid(const Sequence<expression_node<T>*,Allocator>& b) 05923 | { 05924 | for (std::size_t i = 0; i < b.size(); ++i) 05925 | { 05926 | if (0 == b[i]) return false; 05927 | } 05928 | 05929 | return true; 05930 | } 05931 | 05932 | template <std::size_t N, typename T> 05933 | inline bool all_nodes_variables(expression_node<T>* const (&b)[N]) 05934 | { 05935 | for (std::size_t i = 0; i < N; ++i) 05936 | { 05937 | if (0 == b[i]) 05938 | return false; 05939 | else if (!is_variable_node(b[i])) 05940 | return false; 05941 | } 05942 | 05943 | return true; 05944 | } 05945 | 05946 | template <typename T, 05947 | typename Allocator, 05948 | template <typename, typename> class Sequence> 05949 | inline bool all_nodes_variables(const Sequence<expression_node<T>*,Allocator>& b) 05950 | { 05951 | for (std::size_t i = 0; i < b.size(); ++i) 05952 | { 05953 | if (0 == b[i]) 05954 | return false; 05955 | else if (!is_variable_node(b[i])) 05956 | return false; 05957 | } 05958 | 05959 | return true; 05960 | } 05961 | 05962 | template <typename Node> 05963 | class node_collection_destructor 05964 | { 05965 | public: 05966 | 05967 | typedef node_collector_interface<Node> nci_t; 05968 | 05969 | typedef typename nci_t::node_ptr_t node_ptr_t; 05970 | typedef typename nci_t::node_pp_t node_pp_t; 05971 | typedef typename nci_t::noderef_list_t noderef_list_t; 05972 | 05973 | static void delete_nodes(node_ptr_t& root) 05974 | { 05975 | std::vector<node_pp_t> node_delete_list; 05976 | node_delete_list.reserve(1000); 05977 | 05978 | collect_nodes(root, node_delete_list); 05979 | 05980 | for (std::size_t i = 0; i < node_delete_list.size(); ++i) 05981 | { 05982 | node_ptr_t& node = *node_delete_list[i]; 05983 | exprtk_debug(("ncd::delete_nodes() - deleting: %p\n", reinterpret_cast<void*>(node))); 05984 | delete node; 05985 | node = reinterpret_cast<node_ptr_t>(0); 05986 | } 05987 | } 05988 | 05989 | private: 05990 | 05991 | static void collect_nodes(node_ptr_t& root, noderef_list_t& node_delete_list) 05992 | { 05993 | std::deque<node_ptr_t> node_list; 05994 | node_list.push_back(root); 05995 | node_delete_list.push_back(&root); 05996 | 05997 | noderef_list_t child_node_delete_list; 05998 | child_node_delete_list.reserve(1000); 05999 | 06000 | while (!node_list.empty()) 06001 | { 06002 | node_list.front()->collect_nodes(child_node_delete_list); 06003 | 06004 | if (!child_node_delete_list.empty()) 06005 | { 06006 | for (std::size_t i = 0; i < child_node_delete_list.size(); ++i) 06007 | { 06008 | node_pp_t& node = child_node_delete_list[i]; 06009 | 06010 | if (0 == (*node)) 06011 | { 06012 | exprtk_debug(("ncd::collect_nodes() - null node encountered.\n")); 06013 | } 06014 | 06015 | node_list.push_back(*node); 06016 | } 06017 | 06018 | node_delete_list.insert( 06019 | node_delete_list.end(), 06020 | child_node_delete_list.begin(), child_node_delete_list.end()); 06021 | 06022 | child_node_delete_list.clear(); 06023 | } 06024 | 06025 | node_list.pop_front(); 06026 | } 06027 | 06028 | std::reverse(node_delete_list.begin(), node_delete_list.end()); 06029 | } 06030 | }; 06031 | 06032 | template <typename NodeAllocator, typename T, std::size_t N> 06033 | inline void free_all_nodes(NodeAllocator& node_allocator, expression_node<T>* (&b)[N]) 06034 | { 06035 | for (std::size_t i = 0; i < N; ++i) 06036 | { 06037 | free_node(node_allocator,b[i]); 06038 | } 06039 | } 06040 | 06041 | template <typename NodeAllocator, 06042 | typename T, 06043 | typename Allocator, 06044 | template <typename, typename> class Sequence> 06045 | inline void free_all_nodes(NodeAllocator& node_allocator, Sequence<expression_node<T>*,Allocator>& b) 06046 | { 06047 | for (std::size_t i = 0; i < b.size(); ++i) 06048 | { 06049 | free_node(node_allocator,b[i]); 06050 | } 06051 | 06052 | b.clear(); 06053 | } 06054 | 06055 | template <typename NodeAllocator, typename T> 06056 | inline void free_node(NodeAllocator&, expression_node<T>*& node) 06057 | { 06058 | if ((0 == node) || is_variable_node(node) || is_string_node(node)) 06059 | { 06060 | return; 06061 | } 06062 | 06063 | node_collection_destructor<expression_node<T> > 06064 | ::delete_nodes(node); 06065 | } 06066 | 06067 | template <typename T> 06068 | inline void destroy_node(expression_node<T>*& node) 06069 | { 06070 | if (0 != node) 06071 | { 06072 | node_collection_destructor<expression_node<T> > 06073 | ::delete_nodes(node); 06074 | } 06075 | } 06076 | 06077 | template <typename Node> 06078 | struct node_depth_base 06079 | { 06080 | typedef Node* node_ptr_t; 06081 | typedef std::pair<node_ptr_t,bool> nb_pair_t; 06082 | 06083 | node_depth_base() 06084 | : depth_set(false) 06085 | , depth(0) 06086 | {} 06087 | 06088 | virtual ~node_depth_base() 06089 | {} 06090 | 06091 | virtual std::size_t node_depth() const { return 1; } 06092 | 06093 | std::size_t compute_node_depth(const Node* const& node) const 06094 | { 06095 | if (!depth_set) 06096 | { 06097 | depth = 1 + (node ? node->node_depth() : 0); 06098 | depth_set = true; 06099 | } 06100 | 06101 | return depth; 06102 | } 06103 | 06104 | std::size_t compute_node_depth(const nb_pair_t& branch) const 06105 | { 06106 | if (!depth_set) 06107 | { 06108 | depth = 1 + (branch.first ? branch.first->node_depth() : 0); 06109 | depth_set = true; 06110 | } 06111 | 06112 | return depth; 06113 | } 06114 | 06115 | template <std::size_t N> 06116 | std::size_t compute_node_depth(const nb_pair_t (&branch)[N]) const 06117 | { 06118 | if (!depth_set) 06119 | { 06120 | depth = 0; 06121 | 06122 | for (std::size_t i = 0; i < N; ++i) 06123 | { 06124 | if (branch[i].first) 06125 | { 06126 | depth = std::max(depth,branch[i].first->node_depth()); 06127 | } 06128 | } 06129 | 06130 | depth += 1; 06131 | depth_set = true; 06132 | } 06133 | 06134 | return depth; 06135 | } 06136 | 06137 | template <typename BranchType> 06138 | std::size_t max_node_depth(const BranchType& n0, const BranchType& n1) const 06139 | { 06140 | return std::max(compute_node_depth(n0), compute_node_depth(n1)); 06141 | } 06142 | 06143 | template <typename BranchType> 06144 | std::size_t max_node_depth(const BranchType& n0, const BranchType& n1, const BranchType& n2) const 06145 | { 06146 | return std::max(compute_node_depth(n0), 06147 | std::max(compute_node_depth(n1), compute_node_depth(n2))); 06148 | } 06149 | 06150 | template <typename BranchType> 06151 | std::size_t max_node_depth(const BranchType& n0, const BranchType& n1, 06152 | const BranchType& n2, const BranchType& n3) const 06153 | { 06154 | return std::max( 06155 | std::max(compute_node_depth(n0), compute_node_depth(n1)), 06156 | std::max(compute_node_depth(n2), compute_node_depth(n3))); 06157 | } 06158 | 06159 | template <typename BranchType> 06160 | std::size_t compute_node_depth(const BranchType& n0, const BranchType& n1) const 06161 | { 06162 | if (!depth_set) 06163 | { 06164 | depth = 1 + max_node_depth(n0, n1); 06165 | depth_set = true; 06166 | } 06167 | 06168 | return depth; 06169 | } 06170 | 06171 | template <typename BranchType> 06172 | std::size_t compute_node_depth(const BranchType& n0, const BranchType& n1, 06173 | const BranchType& n2) const 06174 | { 06175 | if (!depth_set) 06176 | { 06177 | depth = 1 + max_node_depth(n0, n1, n2); 06178 | depth_set = true; 06179 | } 06180 | 06181 | return depth; 06182 | } 06183 | 06184 | template <typename BranchType> 06185 | std::size_t compute_node_depth(const BranchType& n0, const BranchType& n1, 06186 | const BranchType& n2, const BranchType& n3) const 06187 | { 06188 | if (!depth_set) 06189 | { 06190 | depth = 1 + max_node_depth(n0, n1, n2, n3); 06191 | depth_set = true; 06192 | } 06193 | 06194 | return depth; 06195 | } 06196 | 06197 | template <typename Allocator, 06198 | template <typename, typename> class Sequence> 06199 | std::size_t compute_node_depth(const Sequence<node_ptr_t, Allocator>& branch_list) const 06200 | { 06201 | if (!depth_set) 06202 | { 06203 | for (std::size_t i = 0; i < branch_list.size(); ++i) 06204 | { 06205 | if (branch_list[i]) 06206 | { 06207 | depth = std::max(depth, compute_node_depth(branch_list[i])); 06208 | } 06209 | } 06210 | 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<nb_pair_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].first) 06226 | { 06227 | depth = std::max(depth, compute_node_depth(branch_list[i].first)); 06228 | } 06229 | } 06230 | 06231 | depth_set = true; 06232 | } 06233 | 06234 | return depth; 06235 | } 06236 | 06237 | mutable bool depth_set; 06238 | mutable std::size_t depth; 06239 | 06240 | template <typename NodeSequence> 06241 | void collect(node_ptr_t const& node, 06242 | const bool deletable, 06243 | NodeSequence& delete_node_list) const 06244 | { 06245 | if ((0 != node) && deletable) 06246 | { 06247 | delete_node_list.push_back(const_cast<node_ptr_t*>(&node)); 06248 | } 06249 | } 06250 | 06251 | template <typename NodeSequence> 06252 | void collect(const nb_pair_t& branch, 06253 | NodeSequence& delete_node_list) const 06254 | { 06255 | collect(branch.first, branch.second, delete_node_list); 06256 | } 06257 | 06258 | template <typename NodeSequence> 06259 | void collect(Node*& node, 06260 | NodeSequence& delete_node_list) const 06261 | { 06262 | collect(node, branch_deletable(node), delete_node_list); 06263 | } 06264 | 06265 | template <std::size_t N, typename NodeSequence> 06266 | void collect(const nb_pair_t(&branch)[N], 06267 | NodeSequence& delete_node_list) const 06268 | { 06269 | for (std::size_t i = 0; i < N; ++i) 06270 | { 06271 | collect(branch[i].first, branch[i].second, delete_node_list); 06272 | } 06273 | } 06274 | 06275 | template <typename Allocator, 06276 | template <typename, typename> class Sequence, 06277 | typename NodeSequence> 06278 | void collect(const Sequence<nb_pair_t, Allocator>& branch, 06279 | NodeSequence& delete_node_list) const 06280 | { 06281 | for (std::size_t i = 0; i < branch.size(); ++i) 06282 | { 06283 | collect(branch[i].first, branch[i].second, delete_node_list); 06284 | } 06285 | } 06286 | 06287 | template <typename Allocator, 06288 | template <typename, typename> class Sequence, 06289 | typename NodeSequence> 06290 | void collect(const Sequence<node_ptr_t, Allocator>& branch_list, 06291 | NodeSequence& delete_node_list) const 06292 | { 06293 | for (std::size_t i = 0; i < branch_list.size(); ++i) 06294 | { 06295 | collect(branch_list[i], branch_deletable(branch_list[i]), delete_node_list); 06296 | } 06297 | } 06298 | 06299 | template <typename Boolean, 06300 | typename AllocatorT, 06301 | typename AllocatorB, 06302 | template <typename, typename> class Sequence, 06303 | typename NodeSequence> 06304 | void collect(const Sequence<node_ptr_t, AllocatorT>& branch_list, 06305 | const Sequence<Boolean, AllocatorB>& branch_deletable_list, 06306 | NodeSequence& delete_node_list) const 06307 | { 06308 | for (std::size_t i = 0; i < branch_list.size(); ++i) 06309 | { 06310 | collect(branch_list[i], branch_deletable_list[i], delete_node_list); 06311 | } 06312 | } 06313 | }; 06314 | 06315 | template <typename Type> 06316 | class vector_holder 06317 | { 06318 | private: 06319 | 06320 | typedef Type value_type; 06321 | typedef value_type* value_ptr; 06322 | typedef const value_ptr const_value_ptr; 06323 | typedef vector_holder<Type> vector_holder_t; 06324 | 06325 | class vector_holder_base 06326 | { 06327 | public: 06328 | 06329 | virtual ~vector_holder_base() 06330 | {} 06331 | 06332 | inline value_ptr operator[](const std::size_t& index) const 06333 | { 06334 | return value_at(index); 06335 | } 06336 | 06337 | inline std::size_t size() const 06338 | { 06339 | return vector_size(); 06340 | } 06341 | 06342 | inline std::size_t base_size() const 06343 | { 06344 | return vector_base_size(); 06345 | } 06346 | 06347 | inline value_ptr data() const 06348 | { 06349 | return value_at(0); 06350 | } 06351 | 06352 | virtual inline bool rebaseable() const 06353 | { 06354 | return false; 06355 | } 06356 | 06357 | virtual void set_ref(value_ptr*) 06358 | {} 06359 | 06360 | virtual void remove_ref(value_ptr*) 06361 | {} 06362 | 06363 | virtual vector_view<Type>* rebaseable_instance() 06364 | { 06365 | return reinterpret_cast<vector_view<Type>*>(0); 06366 | } 06367 | 06368 | protected: 06369 | 06370 | virtual value_ptr value_at(const std::size_t&) const = 0; 06371 | virtual std::size_t vector_size() const = 0; 06372 | virtual std::size_t vector_base_size() const = 0; 06373 | }; 06374 | 06375 | class array_vector_impl exprtk_final : public vector_holder_base 06376 | { 06377 | public: 06378 | 06379 | array_vector_impl(const Type* vec, const std::size_t& vec_size) 06380 | : vec_(vec) 06381 | , size_(vec_size) 06382 | {} 06383 | 06384 | protected: 06385 | 06386 | value_ptr value_at(const std::size_t& index) const exprtk_override 06387 | { 06388 | assert(index < size_); 06389 | return const_cast<const_value_ptr>(vec_ + index); 06390 | } 06391 | 06392 | std::size_t vector_size() const exprtk_override 06393 | { 06394 | return size_; 06395 | } 06396 | 06397 | std::size_t vector_base_size() const exprtk_override 06398 | { 06399 | return vector_size(); 06400 | } 06401 | 06402 | private: 06403 | 06404 | array_vector_impl(const array_vector_impl&) exprtk_delete; 06405 | array_vector_impl& operator=(const array_vector_impl&) exprtk_delete; 06406 | 06407 | const Type* vec_; 06408 | const std::size_t size_; 06409 | }; 06410 | 06411 | template <typename Allocator, 06412 | template <typename, typename> class Sequence> 06413 | class sequence_vector_impl exprtk_final : public vector_holder_base 06414 | { 06415 | public: 06416 | 06417 | typedef Sequence<Type,Allocator> sequence_t; 06418 | 06419 | explicit sequence_vector_impl(sequence_t& seq) 06420 | : sequence_(seq) 06421 | {} 06422 | 06423 | protected: 06424 | 06425 | value_ptr value_at(const std::size_t& index) const exprtk_override 06426 | { 06427 | assert(index < sequence_.size()); 06428 | return (&sequence_[index]); 06429 | } 06430 | 06431 | std::size_t vector_size() const exprtk_override 06432 | { 06433 | return sequence_.size(); 06434 | } 06435 | 06436 | std::size_t vector_base_size() const exprtk_override 06437 | { 06438 | return vector_size(); 06439 | } 06440 | 06441 | private: 06442 | 06443 | sequence_vector_impl(const sequence_vector_impl&) exprtk_delete; 06444 | sequence_vector_impl& operator=(const sequence_vector_impl&) exprtk_delete; 06445 | 06446 | sequence_t& sequence_; 06447 | }; 06448 | 06449 | class vector_view_impl exprtk_final : public vector_holder_base 06450 | { 06451 | public: 06452 | 06453 | typedef exprtk::vector_view<Type> vector_view_t; 06454 | 06455 | explicit vector_view_impl(vector_view_t& vec_view) 06456 | : vec_view_(vec_view) 06457 | { 06458 | assert(vec_view_.size() > 0); 06459 | } 06460 | 06461 | void set_ref(value_ptr* ref) exprtk_override 06462 | { 06463 | vec_view_.set_ref(ref); 06464 | } 06465 | 06466 | void remove_ref(value_ptr* ref) exprtk_override 06467 | { 06468 | vec_view_.remove_ref(ref); 06469 | } 06470 | 06471 | bool rebaseable() const exprtk_override 06472 | { 06473 | return true; 06474 | } 06475 | 06476 | vector_view<Type>* rebaseable_instance() exprtk_override 06477 | { 06478 | return &vec_view_; 06479 | } 06480 | 06481 | protected: 06482 | 06483 | value_ptr value_at(const std::size_t& index) const exprtk_override 06484 | { 06485 | assert(index < vec_view_.size()); 06486 | return (&vec_view_[index]); 06487 | } 06488 | 06489 | std::size_t vector_size() const exprtk_override 06490 | { 06491 | return vec_view_.size(); 06492 | } 06493 | 06494 | std::size_t vector_base_size() const exprtk_override 06495 | { 06496 | return vec_view_.base_size(); 06497 | } 06498 | 06499 | private: 06500 | 06501 | vector_view_impl(const vector_view_impl&) exprtk_delete; 06502 | vector_view_impl& operator=(const vector_view_impl&) exprtk_delete; 06503 | 06504 | vector_view_t& vec_view_; 06505 | }; 06506 | 06507 | class resizable_vector_impl exprtk_final : public vector_holder_base 06508 | { 06509 | public: 06510 | 06511 | resizable_vector_impl(vector_holder& vec_view_holder, 06512 | const Type* vec, 06513 | const std::size_t& vec_size) 06514 | : vec_(vec) 06515 | , size_(vec_size) 06516 | , vec_view_holder_(*vec_view_holder.rebaseable_instance()) 06517 | { 06518 | assert(vec_view_holder.rebaseable_instance()); 06519 | assert(size_ <= vector_base_size()); 06520 | } 06521 | 06522 | virtual ~resizable_vector_impl() exprtk_override 06523 | {} 06524 | 06525 | protected: 06526 | 06527 | value_ptr value_at(const std::size_t& index) const exprtk_override 06528 | { 06529 | assert(index < vector_size()); 06530 | return const_cast<const_value_ptr>(vec_ + index); 06531 | } 06532 | 06533 | std::size_t vector_size() const exprtk_override 06534 | { 06535 | return vec_view_holder_.size(); 06536 | } 06537 | 06538 | std::size_t vector_base_size() const exprtk_override 06539 | { 06540 | return vec_view_holder_.base_size(); 06541 | } 06542 | 06543 | bool rebaseable() const exprtk_override 06544 | { 06545 | return true; 06546 | } 06547 | 06548 | virtual vector_view<Type>* rebaseable_instance() exprtk_override 06549 | { 06550 | return &vec_view_holder_; 06551 | } 06552 | 06553 | private: 06554 | 06555 | resizable_vector_impl(const resizable_vector_impl&) exprtk_delete; 06556 | resizable_vector_impl& operator=(const resizable_vector_impl&) exprtk_delete; 06557 | 06558 | const Type* vec_; 06559 | const std::size_t size_; 06560 | vector_view<Type>& vec_view_holder_; 06561 | }; 06562 | 06563 | public: 06564 | 06565 | typedef typename details::vec_data_store<Type> vds_t; 06566 | 06567 | vector_holder(Type* vec, const std::size_t& vec_size) 06568 | : vector_holder_base_(new(buffer)array_vector_impl(vec,vec_size)) 06569 | {} 06570 | 06571 | explicit vector_holder(const vds_t& vds) 06572 | : vector_holder_base_(new(buffer)array_vector_impl(vds.data(),vds.size())) 06573 | {} 06574 | 06575 | template <typename Allocator> 06576 | explicit vector_holder(std::vector<Type,Allocator>& vec) 06577 | : vector_holder_base_(new(buffer)sequence_vector_impl<Allocator,std::vector>(vec)) 06578 | {} 06579 | 06580 | explicit vector_holder(exprtk::vector_view<Type>& vec) 06581 | : vector_holder_base_(new(buffer)vector_view_impl(vec)) 06582 | {} 06583 | 06584 | explicit vector_holder(vector_holder_t& vec_holder, const vds_t& vds) 06585 | : vector_holder_base_(new(buffer)resizable_vector_impl(vec_holder, vds.data(), vds.size())) 06586 | {} 06587 | 06588 | inline value_ptr operator[](const std::size_t& index) const 06589 | { 06590 | return (*vector_holder_base_)[index]; 06591 | } 06592 | 06593 | inline std::size_t size() const 06594 | { 06595 | return vector_holder_base_->size(); 06596 | } 06597 | 06598 | inline std::size_t base_size() const 06599 | { 06600 | return vector_holder_base_->base_size(); 06601 | } 06602 | 06603 | inline value_ptr data() const 06604 | { 06605 | return vector_holder_base_->data(); 06606 | } 06607 | 06608 | void set_ref(value_ptr* ref) 06609 | { 06610 | if (rebaseable()) 06611 | { 06612 | vector_holder_base_->set_ref(ref); 06613 | } 06614 | } 06615 | 06616 | void remove_ref(value_ptr* ref) 06617 | { 06618 | if (rebaseable()) 06619 | { 06620 | vector_holder_base_->remove_ref(ref); 06621 | } 06622 | } 06623 | 06624 | bool rebaseable() const 06625 | { 06626 | return vector_holder_base_->rebaseable(); 06627 | } 06628 | 06629 | vector_view<Type>* rebaseable_instance() 06630 | { 06631 | return vector_holder_base_->rebaseable_instance(); 06632 | } 06633 | 06634 | private: 06635 | 06636 | vector_holder(const vector_holder<Type>&) exprtk_delete; 06637 | vector_holder<Type>& operator=(const vector_holder<Type>&) exprtk_delete; 06638 | 06639 | mutable vector_holder_base* vector_holder_base_; 06640 | uchar_t buffer[64]; 06641 | }; 06642 | 06643 | template <typename T> 06644 | class null_node exprtk_final : public expression_node<T> 06645 | { 06646 | public: 06647 | 06648 | inline T value() const exprtk_override 06649 | { 06650 | return std::numeric_limits<T>::quiet_NaN(); 06651 | } 06652 | 06653 | inline typename expression_node<T>::node_type type() const exprtk_override 06654 | { 06655 | return expression_node<T>::e_null; 06656 | } 06657 | }; 06658 | 06659 | template <typename T, std::size_t N> 06660 | inline void construct_branch_pair(std::pair<expression_node<T>*,bool> (&branch)[N], 06661 | expression_node<T>* b, 06662 | const std::size_t& index) 06663 | { 06664 | if (b && (index < N)) 06665 | { 06666 | branch[index] = std::make_pair(b,branch_deletable(b)); 06667 | } 06668 | } 06669 | 06670 | template <typename T> 06671 | inline void construct_branch_pair(std::pair<expression_node<T>*,bool>& branch, expression_node<T>* b) 06672 | { 06673 | if (b) 06674 | { 06675 | branch = std::make_pair(b,branch_deletable(b)); 06676 | } 06677 | } 06678 | 06679 | template <std::size_t N, typename T> 06680 | inline void init_branches(std::pair<expression_node<T>*,bool> (&branch)[N], 06681 | expression_node<T>* b0, 06682 | expression_node<T>* b1 = reinterpret_cast<expression_node<T>*>(0), 06683 | expression_node<T>* b2 = reinterpret_cast<expression_node<T>*>(0), 06684 | expression_node<T>* b3 = reinterpret_cast<expression_node<T>*>(0), 06685 | expression_node<T>* b4 = reinterpret_cast<expression_node<T>*>(0), 06686 | expression_node<T>* b5 = reinterpret_cast<expression_node<T>*>(0), 06687 | expression_node<T>* b6 = reinterpret_cast<expression_node<T>*>(0), 06688 | expression_node<T>* b7 = reinterpret_cast<expression_node<T>*>(0), 06689 | expression_node<T>* b8 = reinterpret_cast<expression_node<T>*>(0), 06690 | expression_node<T>* b9 = reinterpret_cast<expression_node<T>*>(0)) 06691 | { 06692 | construct_branch_pair(branch, b0, 0); 06693 | construct_branch_pair(branch, b1, 1); 06694 | construct_branch_pair(branch, b2, 2); 06695 | construct_branch_pair(branch, b3, 3); 06696 | construct_branch_pair(branch, b4, 4); 06697 | construct_branch_pair(branch, b5, 5); 06698 | construct_branch_pair(branch, b6, 6); 06699 | construct_branch_pair(branch, b7, 7); 06700 | construct_branch_pair(branch, b8, 8); 06701 | construct_branch_pair(branch, b9, 9); 06702 | } 06703 | 06704 | template <typename T> 06705 | class null_eq_node exprtk_final : public expression_node<T> 06706 | { 06707 | public: 06708 | 06709 | typedef expression_node<T>* expression_ptr; 06710 | typedef std::pair<expression_ptr,bool> branch_t; 06711 | 06712 | explicit null_eq_node(expression_ptr branch, const bool equality = true) 06713 | : equality_(equality) 06714 | { 06715 | construct_branch_pair(branch_, branch); 06716 | assert(valid()); 06717 | } 06718 | 06719 | inline T value() const exprtk_override 06720 | { 06721 | const T v = branch_.first->value(); 06722 | const bool result = details::numeric::is_nan(v); 06723 | 06724 | if (result) 06725 | return equality_ ? T(1) : T(0); 06726 | else 06727 | return equality_ ? T(0) : T(1); 06728 | } 06729 | 06730 | inline typename expression_node<T>::node_type type() const exprtk_override 06731 | { 06732 | return expression_node<T>::e_nulleq; 06733 | } 06734 | 06735 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 06736 | { 06737 | return branch_.first; 06738 | } 06739 | 06740 | inline bool valid() const exprtk_override 06741 | { 06742 | return branch_.first; 06743 | } 06744 | 06745 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 06746 | { 06747 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 06748 | } 06749 | 06750 | std::size_t node_depth() const exprtk_override 06751 | { 06752 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 06753 | } 06754 | 06755 | private: 06756 | 06757 | bool equality_; 06758 | branch_t branch_; 06759 | }; 06760 | 06761 | template <typename T> 06762 | class literal_node exprtk_final : public expression_node<T> 06763 | { 06764 | public: 06765 | 06766 | explicit literal_node(const T& v) 06767 | : value_(v) 06768 | {} 06769 | 06770 | inline T value() const exprtk_override 06771 | { 06772 | return value_; 06773 | } 06774 | 06775 | inline typename expression_node<T>::node_type type() const exprtk_override 06776 | { 06777 | return expression_node<T>::e_constant; 06778 | } 06779 | 06780 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 06781 | { 06782 | return reinterpret_cast<expression_node<T>*>(0); 06783 | } 06784 | 06785 | private: 06786 | 06787 | literal_node(const literal_node<T>&) exprtk_delete; 06788 | literal_node<T>& operator=(const literal_node<T>&) exprtk_delete; 06789 | 06790 | const T value_; 06791 | }; 06792 | 06793 | template <typename T> 06794 | struct range_pack; 06795 | 06796 | template <typename T> 06797 | struct range_data_type; 06798 | 06799 | template <typename T> 06800 | class range_interface 06801 | { 06802 | public: 06803 | 06804 | typedef range_pack<T> range_t; 06805 | 06806 | virtual ~range_interface() 06807 | {} 06808 | 06809 | virtual range_t& range_ref() = 0; 06810 | 06811 | virtual const range_t& range_ref() const = 0; 06812 | }; 06813 | 06814 | #ifndef exprtk_disable_string_capabilities 06815 | template <typename T> 06816 | class string_base_node 06817 | { 06818 | public: 06819 | 06820 | typedef range_data_type<T> range_data_type_t; 06821 | 06822 | virtual ~string_base_node() 06823 | {} 06824 | 06825 | virtual std::string str () const = 0; 06826 | 06827 | virtual char_cptr base() const = 0; 06828 | 06829 | virtual std::size_t size() const = 0; 06830 | }; 06831 | 06832 | template <typename T> 06833 | class string_literal_node exprtk_final 06834 | : public expression_node <T> 06835 | , public string_base_node<T> 06836 | , public range_interface <T> 06837 | { 06838 | public: 06839 | 06840 | typedef range_pack<T> range_t; 06841 | 06842 | explicit string_literal_node(const std::string& v) 06843 | : value_(v) 06844 | { 06845 | rp_.n0_c = std::make_pair<bool,std::size_t>(true, 0); 06846 | rp_.n1_c = std::make_pair<bool,std::size_t>(true, v.size()); 06847 | rp_.cache.first = rp_.n0_c.second; 06848 | rp_.cache.second = rp_.n1_c.second; 06849 | } 06850 | 06851 | inline T value() const exprtk_override 06852 | { 06853 | return std::numeric_limits<T>::quiet_NaN(); 06854 | } 06855 | 06856 | inline typename expression_node<T>::node_type type() const exprtk_override 06857 | { 06858 | return expression_node<T>::e_stringconst; 06859 | } 06860 | 06861 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 06862 | { 06863 | return reinterpret_cast<expression_node<T>*>(0); 06864 | } 06865 | 06866 | std::string str() const exprtk_override 06867 | { 06868 | return value_; 06869 | } 06870 | 06871 | char_cptr base() const exprtk_override 06872 | { 06873 | return value_.data(); 06874 | } 06875 | 06876 | std::size_t size() const exprtk_override 06877 | { 06878 | return value_.size(); 06879 | } 06880 | 06881 | range_t& range_ref() exprtk_override 06882 | { 06883 | return rp_; 06884 | } 06885 | 06886 | const range_t& range_ref() const exprtk_override 06887 | { 06888 | return rp_; 06889 | } 06890 | 06891 | private: 06892 | 06893 | string_literal_node(const string_literal_node<T>&) exprtk_delete; 06894 | string_literal_node<T>& operator=(const string_literal_node<T>&) exprtk_delete; 06895 | 06896 | const std::string value_; 06897 | range_t rp_; 06898 | }; 06899 | #endif 06900 | 06901 | template <typename T> 06902 | class unary_node : public expression_node<T> 06903 | { 06904 | public: 06905 | 06906 | typedef expression_node<T>* expression_ptr; 06907 | typedef std::pair<expression_ptr,bool> branch_t; 06908 | 06909 | unary_node(const operator_type& opr, expression_ptr branch) 06910 | : operation_(opr) 06911 | { 06912 | construct_branch_pair(branch_,branch); 06913 | assert(valid()); 06914 | } 06915 | 06916 | inline T value() const exprtk_override 06917 | { 06918 | return numeric::process<T> 06919 | (operation_,branch_.first->value()); 06920 | } 06921 | 06922 | inline typename expression_node<T>::node_type type() const exprtk_override 06923 | { 06924 | return expression_node<T>::e_unary; 06925 | } 06926 | 06927 | inline operator_type operation() 06928 | { 06929 | return operation_; 06930 | } 06931 | 06932 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 06933 | { 06934 | return branch_.first; 06935 | } 06936 | 06937 | inline bool valid() const exprtk_override 06938 | { 06939 | return branch_.first && branch_.first->valid(); 06940 | } 06941 | 06942 | inline void release() 06943 | { 06944 | branch_.second = false; 06945 | } 06946 | 06947 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 06948 | { 06949 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 06950 | } 06951 | 06952 | std::size_t node_depth() const exprtk_final 06953 | { 06954 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 06955 | } 06956 | 06957 | private: 06958 | 06959 | operator_type operation_; 06960 | branch_t branch_; 06961 | }; 06962 | 06963 | template <typename T> 06964 | class binary_node : public expression_node<T> 06965 | { 06966 | public: 06967 | 06968 | typedef expression_node<T>* expression_ptr; 06969 | typedef std::pair<expression_ptr,bool> branch_t; 06970 | 06971 | binary_node(const operator_type& opr, 06972 | expression_ptr branch0, 06973 | expression_ptr branch1) 06974 | : operation_(opr) 06975 | { 06976 | init_branches<2>(branch_, branch0, branch1); 06977 | assert(valid()); 06978 | } 06979 | 06980 | inline T value() const exprtk_override 06981 | { 06982 | return numeric::process<T> 06983 | ( 06984 | operation_, 06985 | branch_[0].first->value(), 06986 | branch_[1].first->value() 06987 | ); 06988 | } 06989 | 06990 | inline typename expression_node<T>::node_type type() const exprtk_override 06991 | { 06992 | return expression_node<T>::e_binary; 06993 | } 06994 | 06995 | inline operator_type operation() 06996 | { 06997 | return operation_; 06998 | } 06999 | 07000 | inline expression_node<T>* branch(const std::size_t& index = 0) const exprtk_override 07001 | { 07002 | assert(index < 2); 07003 | return branch_[index].first; 07004 | } 07005 | 07006 | inline bool valid() const exprtk_override 07007 | { 07008 | return 07009 | branch_[0].first && branch_[0].first->valid() && 07010 | branch_[1].first && branch_[1].first->valid() ; 07011 | } 07012 | 07013 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07014 | { 07015 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 07016 | } 07017 | 07018 | std::size_t node_depth() const exprtk_final 07019 | { 07020 | return expression_node<T>::ndb_t::template compute_node_depth<2>(branch_); 07021 | } 07022 | 07023 | private: 07024 | 07025 | operator_type operation_; 07026 | branch_t branch_[2]; 07027 | }; 07028 | 07029 | template <typename T, typename Operation> 07030 | class binary_ext_node exprtk_final : public expression_node<T> 07031 | { 07032 | public: 07033 | 07034 | typedef expression_node<T>* expression_ptr; 07035 | typedef std::pair<expression_ptr,bool> branch_t; 07036 | 07037 | binary_ext_node(expression_ptr branch0, expression_ptr branch1) 07038 | { 07039 | init_branches<2>(branch_, branch0, branch1); 07040 | assert(valid()); 07041 | } 07042 | 07043 | inline T value() const exprtk_override 07044 | { 07045 | const T arg0 = branch_[0].first->value(); 07046 | const T arg1 = branch_[1].first->value(); 07047 | return Operation::process(arg0,arg1); 07048 | } 07049 | 07050 | inline typename expression_node<T>::node_type type() const exprtk_override 07051 | { 07052 | return expression_node<T>::e_binary_ext; 07053 | } 07054 | 07055 | inline operator_type operation() 07056 | { 07057 | return Operation::operation(); 07058 | } 07059 | 07060 | inline expression_node<T>* branch(const std::size_t& index = 0) const exprtk_override 07061 | { 07062 | assert(index < 2); 07063 | return branch_[index].first; 07064 | } 07065 | 07066 | inline bool valid() const exprtk_override 07067 | { 07068 | return 07069 | branch_[0].first && branch_[0].first->valid() && 07070 | branch_[1].first && branch_[1].first->valid() ; 07071 | } 07072 | 07073 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07074 | { 07075 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 07076 | } 07077 | 07078 | std::size_t node_depth() const exprtk_override 07079 | { 07080 | return expression_node<T>::ndb_t::template compute_node_depth<2>(branch_); 07081 | } 07082 | 07083 | protected: 07084 | 07085 | branch_t branch_[2]; 07086 | }; 07087 | 07088 | template <typename T> 07089 | class trinary_node : public expression_node<T> 07090 | { 07091 | public: 07092 | 07093 | typedef expression_node<T>* expression_ptr; 07094 | typedef std::pair<expression_ptr,bool> branch_t; 07095 | 07096 | trinary_node(const operator_type& opr, 07097 | expression_ptr branch0, 07098 | expression_ptr branch1, 07099 | expression_ptr branch2) 07100 | : operation_(opr) 07101 | { 07102 | init_branches<3>(branch_, branch0, branch1, branch2); 07103 | assert(valid()); 07104 | } 07105 | 07106 | inline T value() const exprtk_override 07107 | { 07108 | const T arg0 = branch_[0].first->value(); 07109 | const T arg1 = branch_[1].first->value(); 07110 | const T arg2 = branch_[2].first->value(); 07111 | 07112 | switch (operation_) 07113 | { 07114 | case e_inrange : return (arg1 < arg0) ? T(0) : ((arg1 > arg2) ? T(0) : T(1)); 07115 | 07116 | case e_clamp : return (arg1 < arg0) ? arg0 : (arg1 > arg2 ? arg2 : arg1); 07117 | 07118 | case e_iclamp : if ((arg1 <= arg0) || (arg1 >= arg2)) 07119 | return arg1; 07120 | else 07121 | return ((T(2) * arg1 <= (arg2 + arg0)) ? arg0 : arg2); 07122 | 07123 | default : exprtk_debug(("trinary_node::value() - Error: Invalid operation\n")); 07124 | return std::numeric_limits<T>::quiet_NaN(); 07125 | } 07126 | } 07127 | 07128 | inline typename expression_node<T>::node_type type() const exprtk_override 07129 | { 07130 | return expression_node<T>::e_trinary; 07131 | } 07132 | 07133 | inline bool valid() const exprtk_override 07134 | { 07135 | return 07136 | branch_[0].first && branch_[0].first->valid() && 07137 | branch_[1].first && branch_[1].first->valid() && 07138 | branch_[2].first && branch_[2].first->valid() ; 07139 | } 07140 | 07141 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07142 | { 07143 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 07144 | } 07145 | 07146 | std::size_t node_depth() const exprtk_override exprtk_final 07147 | { 07148 | return expression_node<T>::ndb_t::template compute_node_depth<3>(branch_); 07149 | } 07150 | 07151 | protected: 07152 | 07153 | operator_type operation_; 07154 | branch_t branch_[3]; 07155 | }; 07156 | 07157 | template <typename T> 07158 | class quaternary_node : public expression_node<T> 07159 | { 07160 | public: 07161 | 07162 | typedef expression_node<T>* expression_ptr; 07163 | typedef std::pair<expression_ptr,bool> branch_t; 07164 | 07165 | quaternary_node(const operator_type& opr, 07166 | expression_ptr branch0, 07167 | expression_ptr branch1, 07168 | expression_ptr branch2, 07169 | expression_ptr branch3) 07170 | : operation_(opr) 07171 | { 07172 | init_branches<4>(branch_, branch0, branch1, branch2, branch3); 07173 | } 07174 | 07175 | inline T value() const exprtk_override 07176 | { 07177 | return std::numeric_limits<T>::quiet_NaN(); 07178 | } 07179 | 07180 | inline typename expression_node<T>::node_type type() const exprtk_override 07181 | { 07182 | return expression_node<T>::e_quaternary; 07183 | } 07184 | 07185 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07186 | { 07187 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 07188 | } 07189 | 07190 | std::size_t node_depth() const exprtk_override exprtk_final 07191 | { 07192 | return expression_node<T>::ndb_t::template compute_node_depth<4>(branch_); 07193 | } 07194 | 07195 | inline bool valid() const exprtk_override 07196 | { 07197 | return 07198 | branch_[0].first && branch_[0].first->valid() && 07199 | branch_[1].first && branch_[1].first->valid() && 07200 | branch_[2].first && branch_[2].first->valid() && 07201 | branch_[3].first && branch_[3].first->valid() ; 07202 | } 07203 | 07204 | protected: 07205 | 07206 | operator_type operation_; 07207 | branch_t branch_[4]; 07208 | }; 07209 | 07210 | template <typename T> 07211 | class conditional_node exprtk_final : public expression_node<T> 07212 | { 07213 | public: 07214 | 07215 | typedef expression_node<T>* expression_ptr; 07216 | typedef std::pair<expression_ptr,bool> branch_t; 07217 | 07218 | conditional_node(expression_ptr condition, 07219 | expression_ptr consequent, 07220 | expression_ptr alternative) 07221 | { 07222 | construct_branch_pair(condition_ , condition ); 07223 | construct_branch_pair(consequent_ , consequent ); 07224 | construct_branch_pair(alternative_, alternative); 07225 | assert(valid()); 07226 | } 07227 | 07228 | inline T value() const exprtk_override 07229 | { 07230 | if (is_true(condition_)) 07231 | return consequent_.first->value(); 07232 | else 07233 | return alternative_.first->value(); 07234 | } 07235 | 07236 | inline typename expression_node<T>::node_type type() const exprtk_override 07237 | { 07238 | return expression_node<T>::e_conditional; 07239 | } 07240 | 07241 | inline bool valid() const exprtk_override 07242 | { 07243 | return 07244 | condition_ .first && condition_ .first->valid() && 07245 | consequent_ .first && consequent_ .first->valid() && 07246 | alternative_.first && alternative_.first->valid() ; 07247 | } 07248 | 07249 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07250 | { 07251 | expression_node<T>::ndb_t::collect(condition_ , node_delete_list); 07252 | expression_node<T>::ndb_t::collect(consequent_ , node_delete_list); 07253 | expression_node<T>::ndb_t::collect(alternative_ , node_delete_list); 07254 | } 07255 | 07256 | std::size_t node_depth() const exprtk_override 07257 | { 07258 | return expression_node<T>::ndb_t::compute_node_depth 07259 | (condition_, consequent_, alternative_); 07260 | } 07261 | 07262 | private: 07263 | 07264 | branch_t condition_; 07265 | branch_t consequent_; 07266 | branch_t alternative_; 07267 | }; 07268 | 07269 | template <typename T> 07270 | class cons_conditional_node exprtk_final : public expression_node<T> 07271 | { 07272 | public: 07273 | 07274 | // Consequent only conditional statement node 07275 | typedef expression_node<T>* expression_ptr; 07276 | typedef std::pair<expression_ptr,bool> branch_t; 07277 | 07278 | cons_conditional_node(expression_ptr condition, 07279 | expression_ptr consequent) 07280 | { 07281 | construct_branch_pair(condition_ , condition ); 07282 | construct_branch_pair(consequent_, consequent); 07283 | assert(valid()); 07284 | } 07285 | 07286 | inline T value() const exprtk_override 07287 | { 07288 | if (is_true(condition_)) 07289 | return consequent_.first->value(); 07290 | else 07291 | return std::numeric_limits<T>::quiet_NaN(); 07292 | } 07293 | 07294 | inline typename expression_node<T>::node_type type() const exprtk_override 07295 | { 07296 | return expression_node<T>::e_conditional; 07297 | } 07298 | 07299 | inline bool valid() const exprtk_override 07300 | { 07301 | return 07302 | condition_ .first && condition_ .first->valid() && 07303 | consequent_.first && consequent_.first->valid() ; 07304 | } 07305 | 07306 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07307 | { 07308 | expression_node<T>::ndb_t::collect(condition_ , node_delete_list); 07309 | expression_node<T>::ndb_t::collect(consequent_ , node_delete_list); 07310 | } 07311 | 07312 | std::size_t node_depth() const exprtk_override 07313 | { 07314 | return expression_node<T>::ndb_t:: 07315 | compute_node_depth(condition_, consequent_); 07316 | } 07317 | 07318 | private: 07319 | 07320 | branch_t condition_; 07321 | branch_t consequent_; 07322 | }; 07323 | 07324 | #ifndef exprtk_disable_break_continue 07325 | template <typename T> 07326 | class break_exception 07327 | { 07328 | public: 07329 | 07330 | explicit break_exception(const T& v) 07331 | : value(v) 07332 | {} 07333 | 07334 | T value; 07335 | }; 07336 | 07337 | class continue_exception {}; 07338 | 07339 | template <typename T> 07340 | class break_node exprtk_final : public expression_node<T> 07341 | { 07342 | public: 07343 | 07344 | typedef expression_node<T>* expression_ptr; 07345 | typedef std::pair<expression_ptr,bool> branch_t; 07346 | 07347 | explicit break_node(expression_ptr ret = expression_ptr(0)) 07348 | { 07349 | construct_branch_pair(return_, ret); 07350 | } 07351 | 07352 | inline T value() const exprtk_override 07353 | { 07354 | const T result = return_.first ? 07355 | return_.first->value() : 07356 | std::numeric_limits<T>::quiet_NaN(); 07357 | 07358 | throw break_exception<T>(result); 07359 | 07360 | #if !defined(_MSC_VER) && !defined(__NVCOMPILER) 07361 | return std::numeric_limits<T>::quiet_NaN(); 07362 | #endif 07363 | } 07364 | 07365 | inline typename expression_node<T>::node_type type() const exprtk_override 07366 | { 07367 | return expression_node<T>::e_break; 07368 | } 07369 | 07370 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07371 | { 07372 | expression_node<T>::ndb_t::collect(return_, node_delete_list); 07373 | } 07374 | 07375 | std::size_t node_depth() const exprtk_override 07376 | { 07377 | return expression_node<T>::ndb_t::compute_node_depth(return_); 07378 | } 07379 | 07380 | private: 07381 | 07382 | branch_t return_; 07383 | }; 07384 | 07385 | template <typename T> 07386 | class continue_node exprtk_final : public expression_node<T> 07387 | { 07388 | public: 07389 | 07390 | inline T value() const exprtk_override 07391 | { 07392 | throw continue_exception(); 07393 | #if !defined(_MSC_VER) && !defined(__NVCOMPILER) 07394 | return std::numeric_limits<T>::quiet_NaN(); 07395 | #endif 07396 | } 07397 | 07398 | inline typename expression_node<T>::node_type type() const exprtk_override 07399 | { 07400 | return expression_node<T>::e_break; 07401 | } 07402 | }; 07403 | #endif 07404 | 07405 | struct loop_runtime_checker 07406 | { 07407 | loop_runtime_checker(loop_runtime_check_ptr loop_runtime_check, 07408 | loop_runtime_check::loop_types lp_typ = loop_runtime_check::e_invalid) 07409 | : iteration_count_(0) 07410 | , loop_runtime_check_(loop_runtime_check) 07411 | , max_loop_iterations_(loop_runtime_check_->max_loop_iterations) 07412 | , loop_type_(lp_typ) 07413 | { 07414 | assert(loop_runtime_check_); 07415 | } 07416 | 07417 | inline void reset(const _uint64_t initial_value = 0) const 07418 | { 07419 | iteration_count_ = initial_value; 07420 | } 07421 | 07422 | inline bool check() const 07423 | { 07424 | assert(loop_runtime_check_); 07425 | 07426 | if ( 07427 | (++iteration_count_ <= max_loop_iterations_) && 07428 | loop_runtime_check_->check() 07429 | ) 07430 | { 07431 | return true; 07432 | } 07433 | 07434 | loop_runtime_check::violation_context ctxt; 07435 | ctxt.loop = loop_type_; 07436 | ctxt.violation = loop_runtime_check::e_iteration_count; 07437 | 07438 | loop_runtime_check_->handle_runtime_violation(ctxt); 07439 | 07440 | return false; 07441 | } 07442 | 07443 | bool valid() const 07444 | { 07445 | return 0 != loop_runtime_check_; 07446 | } 07447 | 07448 | mutable _uint64_t iteration_count_; 07449 | mutable loop_runtime_check_ptr loop_runtime_check_; 07450 | const details::_uint64_t& max_loop_iterations_; 07451 | loop_runtime_check::loop_types loop_type_; 07452 | }; 07453 | 07454 | template <typename T> 07455 | class while_loop_node : public expression_node<T> 07456 | { 07457 | public: 07458 | 07459 | typedef expression_node<T>* expression_ptr; 07460 | typedef std::pair<expression_ptr,bool> branch_t; 07461 | 07462 | while_loop_node(expression_ptr condition, 07463 | expression_ptr loop_body) 07464 | { 07465 | construct_branch_pair(condition_, condition); 07466 | construct_branch_pair(loop_body_, loop_body); 07467 | assert(valid()); 07468 | } 07469 | 07470 | inline T value() const exprtk_override 07471 | { 07472 | T result = T(0); 07473 | 07474 | while (is_true(condition_)) 07475 | { 07476 | result = loop_body_.first->value(); 07477 | } 07478 | 07479 | return result; 07480 | } 07481 | 07482 | inline typename expression_node<T>::node_type type() const exprtk_override 07483 | { 07484 | return expression_node<T>::e_while; 07485 | } 07486 | 07487 | inline bool valid() const exprtk_override 07488 | { 07489 | return 07490 | condition_.first && condition_.first->valid() && 07491 | loop_body_.first && loop_body_.first->valid() ; 07492 | } 07493 | 07494 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07495 | { 07496 | expression_node<T>::ndb_t::collect(condition_ , node_delete_list); 07497 | expression_node<T>::ndb_t::collect(loop_body_ , node_delete_list); 07498 | } 07499 | 07500 | std::size_t node_depth() const exprtk_override 07501 | { 07502 | return expression_node<T>::ndb_t::compute_node_depth(condition_, loop_body_); 07503 | } 07504 | 07505 | protected: 07506 | 07507 | branch_t condition_; 07508 | branch_t loop_body_; 07509 | }; 07510 | 07511 | template <typename T> 07512 | class while_loop_rtc_node exprtk_final 07513 | : public while_loop_node<T> 07514 | , public loop_runtime_checker 07515 | { 07516 | public: 07517 | 07518 | typedef while_loop_node<T> parent_t; 07519 | typedef expression_node<T>* expression_ptr; 07520 | 07521 | while_loop_rtc_node(expression_ptr condition, 07522 | expression_ptr loop_body, 07523 | loop_runtime_check_ptr loop_rt_chk) 07524 | : parent_t(condition, loop_body) 07525 | , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_while_loop) 07526 | { 07527 | assert(valid()); 07528 | } 07529 | 07530 | inline T value() const exprtk_override 07531 | { 07532 | 07533 | T result = T(0); 07534 | 07535 | loop_runtime_checker::reset(); 07536 | 07537 | while (is_true(parent_t::condition_) && loop_runtime_checker::check()) 07538 | { 07539 | result = parent_t::loop_body_.first->value(); 07540 | } 07541 | 07542 | return result; 07543 | } 07544 | 07545 | using parent_t::valid; 07546 | 07547 | bool valid() const exprtk_override exprtk_final 07548 | { 07549 | return parent_t::valid() && 07550 | loop_runtime_checker::valid(); 07551 | } 07552 | }; 07553 | 07554 | template <typename T> 07555 | class repeat_until_loop_node : public expression_node<T> 07556 | { 07557 | public: 07558 | 07559 | typedef expression_node<T>* expression_ptr; 07560 | typedef std::pair<expression_ptr,bool> branch_t; 07561 | 07562 | repeat_until_loop_node(expression_ptr condition, 07563 | expression_ptr loop_body) 07564 | { 07565 | construct_branch_pair(condition_, condition); 07566 | construct_branch_pair(loop_body_, loop_body); 07567 | assert(valid()); 07568 | } 07569 | 07570 | inline T value() const exprtk_override 07571 | { 07572 | T result = T(0); 07573 | 07574 | do 07575 | { 07576 | result = loop_body_.first->value(); 07577 | } 07578 | while (is_false(condition_.first)); 07579 | 07580 | return result; 07581 | } 07582 | 07583 | inline typename expression_node<T>::node_type type() const exprtk_override 07584 | { 07585 | return expression_node<T>::e_repeat; 07586 | } 07587 | 07588 | inline bool valid() const exprtk_override 07589 | { 07590 | return 07591 | condition_.first && condition_.first->valid() && 07592 | loop_body_.first && loop_body_.first->valid() ; 07593 | } 07594 | 07595 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07596 | { 07597 | expression_node<T>::ndb_t::collect(condition_ , node_delete_list); 07598 | expression_node<T>::ndb_t::collect(loop_body_ , node_delete_list); 07599 | } 07600 | 07601 | std::size_t node_depth() const exprtk_override 07602 | { 07603 | return expression_node<T>::ndb_t::compute_node_depth(condition_, loop_body_); 07604 | } 07605 | 07606 | protected: 07607 | 07608 | branch_t condition_; 07609 | branch_t loop_body_; 07610 | }; 07611 | 07612 | template <typename T> 07613 | class repeat_until_loop_rtc_node exprtk_final 07614 | : public repeat_until_loop_node<T> 07615 | , public loop_runtime_checker 07616 | { 07617 | public: 07618 | 07619 | typedef repeat_until_loop_node<T> parent_t; 07620 | typedef expression_node<T>* expression_ptr; 07621 | 07622 | repeat_until_loop_rtc_node(expression_ptr condition, 07623 | expression_ptr loop_body, 07624 | loop_runtime_check_ptr loop_rt_chk) 07625 | : parent_t(condition, loop_body) 07626 | , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_repeat_until_loop) 07627 | { 07628 | assert(valid()); 07629 | } 07630 | 07631 | inline T value() const exprtk_override 07632 | { 07633 | T result = T(0); 07634 | 07635 | loop_runtime_checker::reset(1); 07636 | 07637 | do 07638 | { 07639 | result = parent_t::loop_body_.first->value(); 07640 | } 07641 | while (is_false(parent_t::condition_.first) && loop_runtime_checker::check()); 07642 | 07643 | return result; 07644 | } 07645 | 07646 | using parent_t::valid; 07647 | 07648 | inline bool valid() const exprtk_override exprtk_final 07649 | { 07650 | return parent_t::valid() && 07651 | loop_runtime_checker::valid(); 07652 | } 07653 | }; 07654 | 07655 | template <typename T> 07656 | class for_loop_node : public expression_node<T> 07657 | { 07658 | public: 07659 | 07660 | typedef expression_node<T>* expression_ptr; 07661 | typedef std::pair<expression_ptr,bool> branch_t; 07662 | 07663 | for_loop_node(expression_ptr initialiser, 07664 | expression_ptr condition, 07665 | expression_ptr incrementor, 07666 | expression_ptr loop_body) 07667 | { 07668 | construct_branch_pair(initialiser_, initialiser); 07669 | construct_branch_pair(condition_ , condition ); 07670 | construct_branch_pair(incrementor_, incrementor); 07671 | construct_branch_pair(loop_body_ , loop_body ); 07672 | assert(valid()); 07673 | } 07674 | 07675 | inline T value() const exprtk_override 07676 | { 07677 | T result = T(0); 07678 | 07679 | if (initialiser_.first) 07680 | initialiser_.first->value(); 07681 | 07682 | if (incrementor_.first) 07683 | { 07684 | while (is_true(condition_)) 07685 | { 07686 | result = loop_body_.first->value(); 07687 | incrementor_.first->value(); 07688 | } 07689 | } 07690 | else 07691 | { 07692 | while (is_true(condition_)) 07693 | { 07694 | result = loop_body_.first->value(); 07695 | } 07696 | } 07697 | 07698 | return result; 07699 | } 07700 | 07701 | inline typename expression_node<T>::node_type type() const exprtk_override 07702 | { 07703 | return expression_node<T>::e_for; 07704 | } 07705 | 07706 | inline bool valid() const exprtk_override 07707 | { 07708 | return condition_.first && loop_body_.first; 07709 | } 07710 | 07711 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 07712 | { 07713 | expression_node<T>::ndb_t::collect(initialiser_ , node_delete_list); 07714 | expression_node<T>::ndb_t::collect(condition_ , node_delete_list); 07715 | expression_node<T>::ndb_t::collect(incrementor_ , node_delete_list); 07716 | expression_node<T>::ndb_t::collect(loop_body_ , node_delete_list); 07717 | } 07718 | 07719 | std::size_t node_depth() const exprtk_override 07720 | { 07721 | return expression_node<T>::ndb_t::compute_node_depth 07722 | (initialiser_, condition_, incrementor_, loop_body_); 07723 | } 07724 | 07725 | protected: 07726 | 07727 | branch_t initialiser_; 07728 | branch_t condition_ ; 07729 | branch_t incrementor_; 07730 | branch_t loop_body_ ; 07731 | }; 07732 | 07733 | template <typename T> 07734 | class for_loop_rtc_node exprtk_final 07735 | : public for_loop_node<T> 07736 | , public loop_runtime_checker 07737 | { 07738 | public: 07739 | 07740 | typedef for_loop_node<T> parent_t; 07741 | typedef expression_node<T>* expression_ptr; 07742 | 07743 | for_loop_rtc_node(expression_ptr initialiser, 07744 | expression_ptr condition, 07745 | expression_ptr incrementor, 07746 | expression_ptr loop_body, 07747 | loop_runtime_check_ptr loop_rt_chk) 07748 | : parent_t(initialiser, condition, incrementor, loop_body) 07749 | , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_for_loop) 07750 | { 07751 | assert(valid()); 07752 | } 07753 | 07754 | inline T value() const exprtk_override 07755 | { 07756 | T result = T(0); 07757 | 07758 | loop_runtime_checker::reset(); 07759 | 07760 | if (parent_t::initialiser_.first) 07761 | parent_t::initialiser_.first->value(); 07762 | 07763 | if (parent_t::incrementor_.first) 07764 | { 07765 | while (is_true(parent_t::condition_) && loop_runtime_checker::check()) 07766 | { 07767 | result = parent_t::loop_body_.first->value(); 07768 | parent_t::incrementor_.first->value(); 07769 | } 07770 | } 07771 | else 07772 | { 07773 | while (is_true(parent_t::condition_) && loop_runtime_checker::check()) 07774 | { 07775 | result = parent_t::loop_body_.first->value(); 07776 | } 07777 | } 07778 | 07779 | return result; 07780 | } 07781 | 07782 | using parent_t::valid; 07783 | 07784 | inline bool valid() const exprtk_override exprtk_final 07785 | { 07786 | return parent_t::valid() && 07787 | loop_runtime_checker::valid(); 07788 | } 07789 | }; 07790 | 07791 | #ifndef exprtk_disable_break_continue 07792 | template <typename T> 07793 | class while_loop_bc_node : public while_loop_node<T> 07794 | { 07795 | public: 07796 | 07797 | typedef while_loop_node<T> parent_t; 07798 | typedef expression_node<T>* expression_ptr; 07799 | 07800 | while_loop_bc_node(expression_ptr condition, 07801 | expression_ptr loop_body) 07802 | : parent_t(condition, loop_body) 07803 | { 07804 | assert(parent_t::valid()); 07805 | } 07806 | 07807 | inline T value() const exprtk_override 07808 | { 07809 | T result = T(0); 07810 | 07811 | while (is_true(parent_t::condition_)) 07812 | { 07813 | try 07814 | { 07815 | result = parent_t::loop_body_.first->value(); 07816 | } 07817 | catch(const break_exception<T>& e) 07818 | { 07819 | return e.value; 07820 | } 07821 | catch(const continue_exception&) 07822 | {} 07823 | } 07824 | 07825 | return result; 07826 | } 07827 | }; 07828 | 07829 | template <typename T> 07830 | class while_loop_bc_rtc_node exprtk_final 07831 | : public while_loop_bc_node<T> 07832 | , public loop_runtime_checker 07833 | { 07834 | public: 07835 | 07836 | typedef while_loop_bc_node<T> parent_t; 07837 | typedef expression_node<T>* expression_ptr; 07838 | 07839 | while_loop_bc_rtc_node(expression_ptr condition, 07840 | expression_ptr loop_body, 07841 | loop_runtime_check_ptr loop_rt_chk) 07842 | : parent_t(condition, loop_body) 07843 | , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_while_loop) 07844 | { 07845 | assert(valid()); 07846 | } 07847 | 07848 | inline T value() const exprtk_override 07849 | { 07850 | T result = T(0); 07851 | 07852 | loop_runtime_checker::reset(); 07853 | 07854 | while (is_true(parent_t::condition_) && loop_runtime_checker::check()) 07855 | { 07856 | try 07857 | { 07858 | result = parent_t::loop_body_.first->value(); 07859 | } 07860 | catch(const break_exception<T>& e) 07861 | { 07862 | return e.value; 07863 | } 07864 | catch(const continue_exception&) 07865 | {} 07866 | } 07867 | 07868 | return result; 07869 | } 07870 | 07871 | using parent_t::valid; 07872 | 07873 | inline bool valid() const exprtk_override exprtk_final 07874 | { 07875 | return parent_t::valid() && 07876 | loop_runtime_checker::valid(); 07877 | } 07878 | }; 07879 | 07880 | template <typename T> 07881 | class repeat_until_loop_bc_node : public repeat_until_loop_node<T> 07882 | { 07883 | public: 07884 | 07885 | typedef repeat_until_loop_node<T> parent_t; 07886 | typedef expression_node<T>* expression_ptr; 07887 | 07888 | repeat_until_loop_bc_node(expression_ptr condition, 07889 | expression_ptr loop_body) 07890 | : parent_t(condition, loop_body) 07891 | { 07892 | assert(parent_t::valid()); 07893 | } 07894 | 07895 | inline T value() const exprtk_override 07896 | { 07897 | T result = T(0); 07898 | 07899 | do 07900 | { 07901 | try 07902 | { 07903 | result = parent_t::loop_body_.first->value(); 07904 | } 07905 | catch(const break_exception<T>& e) 07906 | { 07907 | return e.value; 07908 | } 07909 | catch(const continue_exception&) 07910 | {} 07911 | } 07912 | while (is_false(parent_t::condition_.first)); 07913 | 07914 | return result; 07915 | } 07916 | }; 07917 | 07918 | template <typename T> 07919 | class repeat_until_loop_bc_rtc_node exprtk_final 07920 | : public repeat_until_loop_bc_node<T> 07921 | , public loop_runtime_checker 07922 | { 07923 | public: 07924 | 07925 | typedef repeat_until_loop_bc_node<T> parent_t; 07926 | typedef expression_node<T>* expression_ptr; 07927 | 07928 | repeat_until_loop_bc_rtc_node(expression_ptr condition, 07929 | expression_ptr loop_body, 07930 | loop_runtime_check_ptr loop_rt_chk) 07931 | : parent_t(condition, loop_body) 07932 | , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_repeat_until_loop) 07933 | { 07934 | assert(valid()); 07935 | } 07936 | 07937 | inline T value() const exprtk_override 07938 | { 07939 | T result = T(0); 07940 | 07941 | loop_runtime_checker::reset(); 07942 | 07943 | do 07944 | { 07945 | try 07946 | { 07947 | result = parent_t::loop_body_.first->value(); 07948 | } 07949 | catch(const break_exception<T>& e) 07950 | { 07951 | return e.value; 07952 | } 07953 | catch(const continue_exception&) 07954 | {} 07955 | } 07956 | while (is_false(parent_t::condition_.first) && loop_runtime_checker::check()); 07957 | 07958 | return result; 07959 | } 07960 | 07961 | using parent_t::valid; 07962 | 07963 | inline bool valid() const exprtk_override exprtk_final 07964 | { 07965 | return parent_t::valid() && 07966 | loop_runtime_checker::valid(); 07967 | } 07968 | }; 07969 | 07970 | template <typename T> 07971 | class for_loop_bc_node : public for_loop_node<T> 07972 | { 07973 | public: 07974 | 07975 | typedef for_loop_node<T> parent_t; 07976 | typedef expression_node<T>* expression_ptr; 07977 | 07978 | for_loop_bc_node(expression_ptr initialiser, 07979 | expression_ptr condition, 07980 | expression_ptr incrementor, 07981 | expression_ptr loop_body) 07982 | : parent_t(initialiser, condition, incrementor, loop_body) 07983 | { 07984 | assert(parent_t::valid()); 07985 | } 07986 | 07987 | inline T value() const exprtk_override 07988 | { 07989 | T result = T(0); 07990 | 07991 | if (parent_t::initialiser_.first) 07992 | parent_t::initialiser_.first->value(); 07993 | 07994 | if (parent_t::incrementor_.first) 07995 | { 07996 | while (is_true(parent_t::condition_)) 07997 | { 07998 | try 07999 | { 08000 | result = parent_t::loop_body_.first->value(); 08001 | } 08002 | catch(const break_exception<T>& e) 08003 | { 08004 | return e.value; 08005 | } 08006 | catch(const continue_exception&) 08007 | {} 08008 | 08009 | parent_t::incrementor_.first->value(); 08010 | } 08011 | } 08012 | else 08013 | { 08014 | while (is_true(parent_t::condition_)) 08015 | { 08016 | try 08017 | { 08018 | result = parent_t::loop_body_.first->value(); 08019 | } 08020 | catch(const break_exception<T>& e) 08021 | { 08022 | return e.value; 08023 | } 08024 | catch(const continue_exception&) 08025 | {} 08026 | } 08027 | } 08028 | 08029 | return result; 08030 | } 08031 | }; 08032 | 08033 | template <typename T> 08034 | class for_loop_bc_rtc_node exprtk_final 08035 | : public for_loop_bc_node<T> 08036 | , public loop_runtime_checker 08037 | { 08038 | public: 08039 | 08040 | typedef for_loop_bc_node<T> parent_t; 08041 | typedef expression_node<T>* expression_ptr; 08042 | 08043 | for_loop_bc_rtc_node(expression_ptr initialiser, 08044 | expression_ptr condition, 08045 | expression_ptr incrementor, 08046 | expression_ptr loop_body, 08047 | loop_runtime_check_ptr loop_rt_chk) 08048 | : parent_t(initialiser, condition, incrementor, loop_body) 08049 | , loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_for_loop) 08050 | { 08051 | assert(valid()); 08052 | } 08053 | 08054 | inline T value() const exprtk_override 08055 | { 08056 | T result = T(0); 08057 | 08058 | loop_runtime_checker::reset(); 08059 | 08060 | if (parent_t::initialiser_.first) 08061 | parent_t::initialiser_.first->value(); 08062 | 08063 | if (parent_t::incrementor_.first) 08064 | { 08065 | while (is_true(parent_t::condition_) && loop_runtime_checker::check()) 08066 | { 08067 | try 08068 | { 08069 | result = parent_t::loop_body_.first->value(); 08070 | } 08071 | catch(const break_exception<T>& e) 08072 | { 08073 | return e.value; 08074 | } 08075 | catch(const continue_exception&) 08076 | {} 08077 | 08078 | parent_t::incrementor_.first->value(); 08079 | } 08080 | } 08081 | else 08082 | { 08083 | while (is_true(parent_t::condition_) && loop_runtime_checker::check()) 08084 | { 08085 | try 08086 | { 08087 | result = parent_t::loop_body_.first->value(); 08088 | } 08089 | catch(const break_exception<T>& e) 08090 | { 08091 | return e.value; 08092 | } 08093 | catch(const continue_exception&) 08094 | {} 08095 | } 08096 | } 08097 | 08098 | return result; 08099 | } 08100 | 08101 | using parent_t::valid; 08102 | 08103 | inline bool valid() const exprtk_override exprtk_final 08104 | { 08105 | return parent_t::valid() && 08106 | loop_runtime_checker::valid(); 08107 | } 08108 | }; 08109 | #endif 08110 | 08111 | template <typename T> 08112 | class switch_node : public expression_node<T> 08113 | { 08114 | public: 08115 | 08116 | typedef expression_node<T>* expression_ptr; 08117 | typedef std::pair<expression_ptr,bool> branch_t; 08118 | 08119 | template <typename Allocator, 08120 | template <typename, typename> class Sequence> 08121 | explicit switch_node(const Sequence<expression_ptr,Allocator>& arg_list) 08122 | { 08123 | if (1 != (arg_list.size() & 1)) 08124 | return; 08125 | 08126 | arg_list_.resize(arg_list.size()); 08127 | 08128 | for (std::size_t i = 0; i < arg_list.size(); ++i) 08129 | { 08130 | if (arg_list[i] && arg_list[i]->valid()) 08131 | { 08132 | construct_branch_pair(arg_list_[i], arg_list[i]); 08133 | } 08134 | else 08135 | { 08136 | arg_list_.clear(); 08137 | return; 08138 | } 08139 | } 08140 | 08141 | assert(valid()); 08142 | } 08143 | 08144 | inline T value() const exprtk_override 08145 | { 08146 | const std::size_t upper_bound = (arg_list_.size() - 1); 08147 | 08148 | for (std::size_t i = 0; i < upper_bound; i += 2) 08149 | { 08150 | expression_ptr condition = arg_list_[i ].first; 08151 | expression_ptr consequent = arg_list_[i + 1].first; 08152 | 08153 | if (is_true(condition)) 08154 | { 08155 | return consequent->value(); 08156 | } 08157 | } 08158 | 08159 | return arg_list_[upper_bound].first->value(); 08160 | } 08161 | 08162 | inline typename expression_node<T>::node_type type() const exprtk_override exprtk_final 08163 | { 08164 | return expression_node<T>::e_switch; 08165 | } 08166 | 08167 | inline bool valid() const exprtk_override 08168 | { 08169 | return !arg_list_.empty(); 08170 | } 08171 | 08172 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 08173 | { 08174 | expression_node<T>::ndb_t::collect(arg_list_, node_delete_list); 08175 | } 08176 | 08177 | std::size_t node_depth() const exprtk_override exprtk_final 08178 | { 08179 | return expression_node<T>::ndb_t::compute_node_depth(arg_list_); 08180 | } 08181 | 08182 | protected: 08183 | 08184 | std::vector<branch_t> arg_list_; 08185 | }; 08186 | 08187 | template <typename T, typename Switch_N> 08188 | class switch_n_node exprtk_final : public switch_node<T> 08189 | { 08190 | public: 08191 | 08192 | typedef expression_node<T>* expression_ptr; 08193 | 08194 | template <typename Allocator, 08195 | template <typename, typename> class Sequence> 08196 | explicit switch_n_node(const Sequence<expression_ptr,Allocator>& arg_list) 08197 | : switch_node<T>(arg_list) 08198 | {} 08199 | 08200 | inline T value() const exprtk_override 08201 | { 08202 | return Switch_N::process(switch_node<T>::arg_list_); 08203 | } 08204 | }; 08205 | 08206 | template <typename T> 08207 | class multi_switch_node exprtk_final : public expression_node<T> 08208 | { 08209 | public: 08210 | 08211 | typedef expression_node<T>* expression_ptr; 08212 | typedef std::pair<expression_ptr,bool> branch_t; 08213 | 08214 | template <typename Allocator, 08215 | template <typename, typename> class Sequence> 08216 | explicit multi_switch_node(const Sequence<expression_ptr,Allocator>& arg_list) 08217 | { 08218 | if (0 != (arg_list.size() & 1)) 08219 | return; 08220 | 08221 | arg_list_.resize(arg_list.size()); 08222 | 08223 | for (std::size_t i = 0; i < arg_list.size(); ++i) 08224 | { 08225 | if (arg_list[i] && arg_list[i]->valid()) 08226 | { 08227 | construct_branch_pair(arg_list_[i], arg_list[i]); 08228 | } 08229 | else 08230 | { 08231 | arg_list_.clear(); 08232 | return; 08233 | } 08234 | } 08235 | 08236 | assert(valid()); 08237 | } 08238 | 08239 | inline T value() const exprtk_override 08240 | { 08241 | const std::size_t upper_bound = (arg_list_.size() - 1); 08242 | 08243 | T result = T(0); 08244 | 08245 | for (std::size_t i = 0; i < upper_bound; i += 2) 08246 | { 08247 | expression_ptr condition = arg_list_[i ].first; 08248 | expression_ptr consequent = arg_list_[i + 1].first; 08249 | 08250 | if (is_true(condition)) 08251 | { 08252 | result = consequent->value(); 08253 | } 08254 | } 08255 | 08256 | return result; 08257 | } 08258 | 08259 | inline typename expression_node<T>::node_type type() const exprtk_override 08260 | { 08261 | return expression_node<T>::e_mswitch; 08262 | } 08263 | 08264 | inline bool valid() const exprtk_override 08265 | { 08266 | return !arg_list_.empty() && (0 == (arg_list_.size() % 2)); 08267 | } 08268 | 08269 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 08270 | { 08271 | expression_node<T>::ndb_t::collect(arg_list_, node_delete_list); 08272 | } 08273 | 08274 | std::size_t node_depth() const exprtk_override exprtk_final 08275 | { 08276 | return expression_node<T>::ndb_t::compute_node_depth(arg_list_); 08277 | } 08278 | 08279 | private: 08280 | 08281 | std::vector<branch_t> arg_list_; 08282 | }; 08283 | 08284 | template <typename T> 08285 | class ivariable 08286 | { 08287 | public: 08288 | 08289 | virtual ~ivariable() 08290 | {} 08291 | 08292 | virtual T& ref() = 0; 08293 | virtual const T& ref() const = 0; 08294 | }; 08295 | 08296 | template <typename T> 08297 | class variable_node exprtk_final 08298 | : public expression_node<T> 08299 | , public ivariable <T> 08300 | { 08301 | public: 08302 | 08303 | static T null_value; 08304 | 08305 | explicit variable_node() 08306 | : value_(&null_value) 08307 | {} 08308 | 08309 | explicit variable_node(T& v) 08310 | : value_(&v) 08311 | {} 08312 | 08313 | inline bool operator <(const variable_node<T>& v) const 08314 | { 08315 | return this < (&v); 08316 | } 08317 | 08318 | inline T value() const exprtk_override 08319 | { 08320 | return (*value_); 08321 | } 08322 | 08323 | inline T& ref() exprtk_override 08324 | { 08325 | return (*value_); 08326 | } 08327 | 08328 | inline const T& ref() const exprtk_override 08329 | { 08330 | return (*value_); 08331 | } 08332 | 08333 | inline typename expression_node<T>::node_type type() const exprtk_override 08334 | { 08335 | return expression_node<T>::e_variable; 08336 | } 08337 | 08338 | private: 08339 | 08340 | T* value_; 08341 | }; 08342 | 08343 | template <typename T> 08344 | T variable_node<T>::null_value = T(std::numeric_limits<T>::quiet_NaN()); 08345 | 08346 | template <typename T> 08347 | struct range_pack 08348 | { 08349 | typedef expression_node<T>* expression_node_ptr; 08350 | typedef std::pair<std::size_t,std::size_t> cached_range_t; 08351 | 08352 | range_pack() 08353 | : n0_e (std::make_pair(false,expression_node_ptr(0))) 08354 | , n1_e (std::make_pair(false,expression_node_ptr(0))) 08355 | , n0_c (std::make_pair(false,0)) 08356 | , n1_c (std::make_pair(false,0)) 08357 | , cache(std::make_pair(0,0)) 08358 | {} 08359 | 08360 | void clear() 08361 | { 08362 | n0_e = std::make_pair(false,expression_node_ptr(0)); 08363 | n1_e = std::make_pair(false,expression_node_ptr(0)); 08364 | n0_c = std::make_pair(false,0); 08365 | n1_c = std::make_pair(false,0); 08366 | cache = std::make_pair(0,0); 08367 | } 08368 | 08369 | void free() 08370 | { 08371 | if (n0_e.first && n0_e.second) 08372 | { 08373 | n0_e.first = false; 08374 | 08375 | if ( 08376 | !is_variable_node(n0_e.second) && 08377 | !is_string_node (n0_e.second) 08378 | ) 08379 | { 08380 | destroy_node(n0_e.second); 08381 | } 08382 | } 08383 | 08384 | if (n1_e.first && n1_e.second) 08385 | { 08386 | n1_e.first = false; 08387 | 08388 | if ( 08389 | !is_variable_node(n1_e.second) && 08390 | !is_string_node (n1_e.second) 08391 | ) 08392 | { 08393 | destroy_node(n1_e.second); 08394 | } 08395 | } 08396 | } 08397 | 08398 | bool const_range() const 08399 | { 08400 | return ( n0_c.first && n1_c.first) && 08401 | (!n0_e.first && !n1_e.first); 08402 | } 08403 | 08404 | bool var_range() const 08405 | { 08406 | return ( n0_e.first && n1_e.first) && 08407 | (!n0_c.first && !n1_c.first); 08408 | } 08409 | 08410 | bool operator() (std::size_t& r0, std::size_t& r1, 08411 | const std::size_t& size = std::numeric_limits<std::size_t>::max()) const 08412 | { 08413 | if (n0_c.first) 08414 | r0 = n0_c.second; 08415 | else if (n0_e.first) 08416 | { 08417 | r0 = static_cast<std::size_t>(details::numeric::to_int64(n0_e.second->value())); 08418 | } 08419 | else 08420 | return false; 08421 | 08422 | if (n1_c.first) 08423 | r1 = n1_c.second; 08424 | else if (n1_e.first) 08425 | { 08426 | r1 = static_cast<std::size_t>(details::numeric::to_int64(n1_e.second->value())); 08427 | } 08428 | else 08429 | return false; 08430 | 08431 | if ( 08432 | (std::numeric_limits<std::size_t>::max() != size) && 08433 | (std::numeric_limits<std::size_t>::max() == r1 ) 08434 | ) 08435 | { 08436 | r1 = size; 08437 | } 08438 | 08439 | cache.first = r0; 08440 | cache.second = r1; 08441 | 08442 | #ifndef exprtk_enable_range_runtime_checks 08443 | return (r0 <= r1); 08444 | #else 08445 | return range_runtime_check(r0, r1, size); 08446 | #endif 08447 | } 08448 | 08449 | inline std::size_t const_size() const 08450 | { 08451 | return (n1_c.second - n0_c.second); 08452 | } 08453 | 08454 | inline std::size_t cache_size() const 08455 | { 08456 | return (cache.second - cache.first); 08457 | } 08458 | 08459 | std::pair<bool,expression_node_ptr> n0_e; 08460 | std::pair<bool,expression_node_ptr> n1_e; 08461 | std::pair<bool,std::size_t > n0_c; 08462 | std::pair<bool,std::size_t > n1_c; 08463 | mutable cached_range_t cache; 08464 | 08465 | #ifdef exprtk_enable_range_runtime_checks 08466 | bool range_runtime_check(const std::size_t r0, 08467 | const std::size_t r1, 08468 | const std::size_t size) const 08469 | { 08470 | if (r0 > size) 08471 | { 08472 | throw std::runtime_error("range error: (r0 < 0) || (r0 > size)"); 08473 | #if !defined(_MSC_VER) && !defined(__NVCOMPILER) 08474 | return false; 08475 | #endif 08476 | } 08477 | 08478 | if (r1 > size) 08479 | { 08480 | throw std::runtime_error("range error: (r1 < 0) || (r1 > size)"); 08481 | #if !defined(_MSC_VER) && !defined(__NVCOMPILER) 08482 | return false; 08483 | #endif 08484 | } 08485 | 08486 | return (r0 <= r1); 08487 | } 08488 | #endif 08489 | }; 08490 | 08491 | template <typename T> 08492 | class string_base_node; 08493 | 08494 | template <typename T> 08495 | struct range_data_type 08496 | { 08497 | typedef range_pack<T> range_t; 08498 | typedef string_base_node<T>* strbase_ptr_t; 08499 | 08500 | range_data_type() 08501 | : range(0) 08502 | , data (0) 08503 | , size (0) 08504 | , type_size(0) 08505 | , str_node (0) 08506 | {} 08507 | 08508 | range_t* range; 08509 | void* data; 08510 | std::size_t size; 08511 | std::size_t type_size; 08512 | strbase_ptr_t str_node; 08513 | }; 08514 | 08515 | template <typename T> class vector_node; 08516 | 08517 | template <typename T> 08518 | class vector_interface 08519 | { 08520 | public: 08521 | 08522 | typedef vector_node<T>* vector_node_ptr; 08523 | typedef vec_data_store<T> vds_t; 08524 | 08525 | virtual ~vector_interface() 08526 | {} 08527 | 08528 | virtual std::size_t size () const = 0; 08529 | 08530 | virtual std::size_t base_size() const = 0; 08531 | 08532 | virtual vector_node_ptr vec () const = 0; 08533 | 08534 | virtual vector_node_ptr vec () = 0; 08535 | 08536 | virtual vds_t& vds () = 0; 08537 | 08538 | virtual const vds_t& vds () const = 0; 08539 | 08540 | virtual bool side_effect () const { return false; } 08541 | }; 08542 | 08543 | template <typename T> 08544 | class vector_node exprtk_final 08545 | : public expression_node <T> 08546 | , public vector_interface<T> 08547 | { 08548 | public: 08549 | 08550 | typedef expression_node<T>* expression_ptr; 08551 | typedef vector_holder<T> vector_holder_t; 08552 | typedef vector_node<T>* vector_node_ptr; 08553 | typedef vec_data_store<T> vds_t; 08554 | 08555 | explicit vector_node(vector_holder_t* vh) 08556 | : vector_holder_(vh) 08557 | , vds_((*vector_holder_).size(),(*vector_holder_)[0]) 08558 | { 08559 | vector_holder_->set_ref(&vds_.ref()); 08560 | } 08561 | 08562 | vector_node(const vds_t& vds, vector_holder_t* vh) 08563 | : vector_holder_(vh) 08564 | , vds_(vds) 08565 | {} 08566 | 08567 | ~vector_node() exprtk_override 08568 | { 08569 | assert(valid()); 08570 | vector_holder_->remove_ref(&vds_.ref()); 08571 | } 08572 | 08573 | inline T value() const exprtk_override 08574 | { 08575 | return vds().data()[0]; 08576 | } 08577 | 08578 | vector_node_ptr vec() const exprtk_override 08579 | { 08580 | return const_cast<vector_node_ptr>(this); 08581 | } 08582 | 08583 | vector_node_ptr vec() exprtk_override 08584 | { 08585 | return this; 08586 | } 08587 | 08588 | inline typename expression_node<T>::node_type type() const exprtk_override 08589 | { 08590 | return expression_node<T>::e_vector; 08591 | } 08592 | 08593 | inline bool valid() const exprtk_override 08594 | { 08595 | return vector_holder_; 08596 | } 08597 | 08598 | std::size_t size() const exprtk_override 08599 | { 08600 | return vec_holder().size(); 08601 | } 08602 | 08603 | std::size_t base_size() const exprtk_override 08604 | { 08605 | return vec_holder().base_size(); 08606 | } 08607 | 08608 | vds_t& vds() exprtk_override 08609 | { 08610 | return vds_; 08611 | } 08612 | 08613 | const vds_t& vds() const exprtk_override 08614 | { 08615 | return vds_; 08616 | } 08617 | 08618 | inline vector_holder_t& vec_holder() 08619 | { 08620 | return (*vector_holder_); 08621 | } 08622 | 08623 | inline vector_holder_t& vec_holder() const 08624 | { 08625 | return (*vector_holder_); 08626 | } 08627 | 08628 | private: 08629 | 08630 | vector_holder_t* vector_holder_; 08631 | vds_t vds_; 08632 | }; 08633 | 08634 | template <typename T> 08635 | class vector_size_node exprtk_final 08636 | : public expression_node <T> 08637 | { 08638 | public: 08639 | 08640 | typedef expression_node<T>* expression_ptr; 08641 | typedef vector_holder<T> vector_holder_t; 08642 | 08643 | explicit vector_size_node(vector_holder_t* vh) 08644 | : vector_holder_(vh) 08645 | {} 08646 | 08647 | ~vector_size_node() exprtk_override 08648 | { 08649 | assert(valid()); 08650 | } 08651 | 08652 | inline T value() const exprtk_override 08653 | { 08654 | assert(vector_holder_); 08655 | return static_cast<T>(vector_holder_->size()); 08656 | } 08657 | 08658 | inline typename expression_node<T>::node_type type() const exprtk_override 08659 | { 08660 | return expression_node<T>::e_vecsize; 08661 | } 08662 | 08663 | inline bool valid() const exprtk_override 08664 | { 08665 | return vector_holder_ && vector_holder_->size(); 08666 | } 08667 | 08668 | inline vector_holder_t* vec_holder() 08669 | { 08670 | return vector_holder_; 08671 | } 08672 | 08673 | private: 08674 | 08675 | vector_holder_t* vector_holder_; 08676 | }; 08677 | 08678 | template <typename T> 08679 | class vector_elem_node exprtk_final 08680 | : public expression_node<T> 08681 | , public ivariable <T> 08682 | { 08683 | public: 08684 | 08685 | typedef expression_node<T>* expression_ptr; 08686 | typedef vector_holder<T> vector_holder_t; 08687 | typedef vector_holder_t* vector_holder_ptr; 08688 | typedef std::pair<expression_ptr,bool> branch_t; 08689 | 08690 | vector_elem_node(expression_ptr vec_node, 08691 | expression_ptr index, 08692 | vector_holder_ptr vec_holder) 08693 | : vector_holder_(vec_holder) 08694 | , vector_base_((*vec_holder)[0]) 08695 | { 08696 | construct_branch_pair(vector_node_, vec_node); 08697 | construct_branch_pair(index_ , index ); 08698 | assert(valid()); 08699 | } 08700 | 08701 | inline T value() const exprtk_override 08702 | { 08703 | return *access_vector(); 08704 | } 08705 | 08706 | inline T& ref() exprtk_override 08707 | { 08708 | return *access_vector(); 08709 | } 08710 | 08711 | inline const T& ref() const exprtk_override 08712 | { 08713 | return *access_vector(); 08714 | } 08715 | 08716 | inline typename expression_node<T>::node_type type() const exprtk_override 08717 | { 08718 | return expression_node<T>::e_vecelem; 08719 | } 08720 | 08721 | inline bool valid() const exprtk_override 08722 | { 08723 | return 08724 | vector_holder_ && 08725 | index_.first && 08726 | vector_node_.first && 08727 | index_.first->valid() && 08728 | vector_node_.first->valid(); 08729 | } 08730 | 08731 | inline vector_holder_t& vec_holder() 08732 | { 08733 | return (*vector_holder_); 08734 | } 08735 | 08736 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 08737 | { 08738 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 08739 | expression_node<T>::ndb_t::collect(index_ , node_delete_list); 08740 | } 08741 | 08742 | std::size_t node_depth() const exprtk_override 08743 | { 08744 | return expression_node<T>::ndb_t::compute_node_depth 08745 | (vector_node_, index_); 08746 | } 08747 | 08748 | private: 08749 | 08750 | inline T* access_vector() const 08751 | { 08752 | vector_node_.first->value(); 08753 | return (vector_base_ + details::numeric::to_uint64(index_.first->value())); 08754 | } 08755 | 08756 | vector_holder_ptr vector_holder_; 08757 | T* vector_base_; 08758 | branch_t vector_node_; 08759 | branch_t index_; 08760 | }; 08761 | 08762 | template <typename T> 08763 | class vector_celem_node exprtk_final 08764 | : public expression_node<T> 08765 | , public ivariable <T> 08766 | { 08767 | public: 08768 | 08769 | typedef expression_node<T>* expression_ptr; 08770 | typedef vector_holder<T> vector_holder_t; 08771 | typedef vector_holder_t* vector_holder_ptr; 08772 | typedef std::pair<expression_ptr,bool> branch_t; 08773 | 08774 | vector_celem_node(expression_ptr vec_node, 08775 | const std::size_t index, 08776 | vector_holder_ptr vec_holder) 08777 | : index_(index) 08778 | , vector_holder_(vec_holder) 08779 | , vector_base_((*vec_holder)[0]) 08780 | { 08781 | construct_branch_pair(vector_node_, vec_node); 08782 | assert(valid()); 08783 | } 08784 | 08785 | inline T value() const exprtk_override 08786 | { 08787 | return *access_vector(); 08788 | } 08789 | 08790 | inline T& ref() exprtk_override 08791 | { 08792 | return *access_vector(); 08793 | } 08794 | 08795 | inline const T& ref() const exprtk_override 08796 | { 08797 | return *access_vector(); 08798 | } 08799 | 08800 | inline typename expression_node<T>::node_type type() const exprtk_override 08801 | { 08802 | return expression_node<T>::e_veccelem; 08803 | } 08804 | 08805 | inline bool valid() const exprtk_override 08806 | { 08807 | return 08808 | vector_holder_ && 08809 | vector_node_.first && 08810 | vector_node_.first->valid(); 08811 | } 08812 | 08813 | inline vector_holder_t& vec_holder() 08814 | { 08815 | return (*vector_holder_); 08816 | } 08817 | 08818 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 08819 | { 08820 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 08821 | } 08822 | 08823 | std::size_t node_depth() const exprtk_override 08824 | { 08825 | return expression_node<T>::ndb_t::compute_node_depth(vector_node_); 08826 | } 08827 | 08828 | private: 08829 | 08830 | inline T* access_vector() const 08831 | { 08832 | vector_node_.first->value(); 08833 | return (vector_base_ + index_); 08834 | } 08835 | 08836 | const std::size_t index_; 08837 | vector_holder_ptr vector_holder_; 08838 | T* vector_base_; 08839 | branch_t vector_node_; 08840 | }; 08841 | 08842 | template <typename T> 08843 | class vector_elem_rtc_node exprtk_final 08844 | : public expression_node<T> 08845 | , public ivariable <T> 08846 | { 08847 | public: 08848 | 08849 | typedef expression_node<T>* expression_ptr; 08850 | typedef vector_holder<T> vector_holder_t; 08851 | typedef vector_holder_t* vector_holder_ptr; 08852 | typedef std::pair<expression_ptr,bool> branch_t; 08853 | 08854 | vector_elem_rtc_node(expression_ptr vec_node, 08855 | expression_ptr index, 08856 | vector_holder_ptr vec_holder, 08857 | vector_access_runtime_check_ptr vec_rt_chk) 08858 | : vector_holder_(vec_holder) 08859 | , vector_base_((*vec_holder)[0]) 08860 | , vec_rt_chk_(vec_rt_chk) 08861 | , max_vector_index_(vector_holder_->size() - 1) 08862 | { 08863 | construct_branch_pair(vector_node_, vec_node); 08864 | construct_branch_pair(index_ , index ); 08865 | assert(valid()); 08866 | } 08867 | 08868 | inline T value() const exprtk_override 08869 | { 08870 | return *access_vector(); 08871 | } 08872 | 08873 | inline T& ref() exprtk_override 08874 | { 08875 | return *access_vector(); 08876 | } 08877 | 08878 | inline const T& ref() const exprtk_override 08879 | { 08880 | return *access_vector(); 08881 | } 08882 | 08883 | inline typename expression_node<T>::node_type type() const exprtk_override 08884 | { 08885 | return expression_node<T>::e_vecelemrtc; 08886 | } 08887 | 08888 | inline bool valid() const exprtk_override 08889 | { 08890 | return 08891 | vector_holder_ && 08892 | index_.first && 08893 | vector_node_.first && 08894 | index_.first->valid() && 08895 | vector_node_.first->valid(); 08896 | } 08897 | 08898 | inline vector_holder_t& vec_holder() 08899 | { 08900 | return (*vector_holder_); 08901 | } 08902 | 08903 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 08904 | { 08905 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 08906 | expression_node<T>::ndb_t::collect(index_, node_delete_list); 08907 | } 08908 | 08909 | std::size_t node_depth() const exprtk_override 08910 | { 08911 | return expression_node<T>::ndb_t::compute_node_depth 08912 | (vector_node_, index_); 08913 | } 08914 | 08915 | private: 08916 | 08917 | inline T* access_vector() const 08918 | { 08919 | const _uint64_t index = details::numeric::to_uint64(index_.first->value()); 08920 | vector_node_.first->value(); 08921 | 08922 | if (index <= max_vector_index_) 08923 | { 08924 | return (vector_holder_->data() + index); 08925 | } 08926 | 08927 | assert(vec_rt_chk_); 08928 | 08929 | vector_access_runtime_check::violation_context context; 08930 | context.base_ptr = reinterpret_cast<void*>(vector_base_); 08931 | context.end_ptr = reinterpret_cast<void*>(vector_base_ + vector_holder_->size()); 08932 | context.access_ptr = reinterpret_cast<void*>(vector_base_ + index); 08933 | context.type_size = sizeof(T); 08934 | 08935 | return vec_rt_chk_->handle_runtime_violation(context) ? 08936 | reinterpret_cast<T*>(context.access_ptr) : 08937 | vector_base_ ; 08938 | } 08939 | 08940 | vector_holder_ptr vector_holder_; 08941 | T* vector_base_; 08942 | branch_t vector_node_; 08943 | branch_t index_; 08944 | vector_access_runtime_check_ptr vec_rt_chk_; 08945 | const std::size_t max_vector_index_; 08946 | }; 08947 | 08948 | template <typename T> 08949 | class vector_celem_rtc_node exprtk_final 08950 | : public expression_node<T> 08951 | , public ivariable <T> 08952 | { 08953 | public: 08954 | 08955 | typedef expression_node<T>* expression_ptr; 08956 | typedef vector_holder<T> vector_holder_t; 08957 | typedef vector_holder_t* vector_holder_ptr; 08958 | typedef std::pair<expression_ptr,bool> branch_t; 08959 | 08960 | vector_celem_rtc_node(expression_ptr vec_node, 08961 | const std::size_t index, 08962 | vector_holder_ptr vec_holder, 08963 | vector_access_runtime_check_ptr vec_rt_chk) 08964 | : index_(index) 08965 | , max_vector_index_(vec_holder->size() - 1) 08966 | , vector_holder_(vec_holder) 08967 | , vector_base_((*vec_holder)[0]) 08968 | , vec_rt_chk_(vec_rt_chk) 08969 | { 08970 | construct_branch_pair(vector_node_, vec_node); 08971 | assert(valid()); 08972 | } 08973 | 08974 | inline T value() const exprtk_override 08975 | { 08976 | return *access_vector(); 08977 | } 08978 | 08979 | inline T& ref() exprtk_override 08980 | { 08981 | return *access_vector(); 08982 | } 08983 | 08984 | inline const T& ref() const exprtk_override 08985 | { 08986 | return *access_vector(); 08987 | } 08988 | 08989 | inline typename expression_node<T>::node_type type() const exprtk_override 08990 | { 08991 | return expression_node<T>::e_veccelemrtc; 08992 | } 08993 | 08994 | inline bool valid() const exprtk_override 08995 | { 08996 | return 08997 | vector_holder_ && 08998 | vector_node_.first && 08999 | vector_node_.first->valid(); 09000 | } 09001 | 09002 | inline vector_holder_t& vec_holder() 09003 | { 09004 | return (*vector_holder_); 09005 | } 09006 | 09007 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09008 | { 09009 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 09010 | } 09011 | 09012 | std::size_t node_depth() const exprtk_override 09013 | { 09014 | return expression_node<T>::ndb_t::compute_node_depth(vector_node_); 09015 | } 09016 | 09017 | private: 09018 | 09019 | inline T* access_vector() const 09020 | { 09021 | vector_node_.first->value(); 09022 | 09023 | if (index_ <= max_vector_index_) 09024 | { 09025 | return (vector_holder_->data() + index_); 09026 | } 09027 | 09028 | assert(vec_rt_chk_); 09029 | 09030 | vector_access_runtime_check::violation_context context; 09031 | context.base_ptr = reinterpret_cast<void*>(vector_base_); 09032 | context.end_ptr = reinterpret_cast<void*>(vector_base_ + vector_holder_->size()); 09033 | context.access_ptr = reinterpret_cast<void*>(vector_base_ + index_); 09034 | context.type_size = sizeof(T); 09035 | 09036 | return vec_rt_chk_->handle_runtime_violation(context) ? 09037 | reinterpret_cast<T*>(context.access_ptr) : 09038 | vector_base_ ; 09039 | } 09040 | 09041 | const std::size_t index_; 09042 | const std::size_t max_vector_index_; 09043 | vector_holder_ptr vector_holder_; 09044 | T* vector_base_; 09045 | branch_t vector_node_; 09046 | vector_access_runtime_check_ptr vec_rt_chk_; 09047 | }; 09048 | 09049 | template <typename T> 09050 | class rebasevector_elem_node exprtk_final 09051 | : public expression_node<T> 09052 | , public ivariable <T> 09053 | { 09054 | public: 09055 | 09056 | typedef expression_node<T>* expression_ptr; 09057 | typedef vector_holder<T> vector_holder_t; 09058 | typedef vector_holder_t* vector_holder_ptr; 09059 | typedef vec_data_store<T> vds_t; 09060 | typedef std::pair<expression_ptr,bool> branch_t; 09061 | 09062 | rebasevector_elem_node(expression_ptr vec_node, 09063 | expression_ptr index, 09064 | vector_holder_ptr vec_holder) 09065 | : vector_holder_(vec_holder) 09066 | { 09067 | construct_branch_pair(vector_node_, vec_node); 09068 | construct_branch_pair(index_ , index ); 09069 | assert(valid()); 09070 | } 09071 | 09072 | inline T value() const exprtk_override 09073 | { 09074 | return *access_vector(); 09075 | } 09076 | 09077 | inline T& ref() exprtk_override 09078 | { 09079 | return *access_vector(); 09080 | } 09081 | 09082 | inline const T& ref() const exprtk_override 09083 | { 09084 | return *access_vector(); 09085 | } 09086 | 09087 | inline typename expression_node<T>::node_type type() const exprtk_override 09088 | { 09089 | return expression_node<T>::e_rbvecelem; 09090 | } 09091 | 09092 | inline bool valid() const exprtk_override 09093 | { 09094 | return 09095 | vector_holder_ && 09096 | index_.first && 09097 | vector_node_.first && 09098 | index_.first->valid() && 09099 | vector_node_.first->valid(); 09100 | } 09101 | 09102 | inline vector_holder_t& vec_holder() 09103 | { 09104 | return (*vector_holder_); 09105 | } 09106 | 09107 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09108 | { 09109 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 09110 | expression_node<T>::ndb_t::collect(index_, node_delete_list); 09111 | } 09112 | 09113 | std::size_t node_depth() const exprtk_override 09114 | { 09115 | return expression_node<T>::ndb_t::compute_node_depth 09116 | (vector_node_, index_); 09117 | } 09118 | 09119 | private: 09120 | 09121 | inline T* access_vector() const 09122 | { 09123 | vector_node_.first->value(); 09124 | return (vector_holder_->data() + details::numeric::to_uint64(index_.first->value())); 09125 | } 09126 | 09127 | vector_holder_ptr vector_holder_; 09128 | branch_t vector_node_; 09129 | branch_t index_; 09130 | }; 09131 | 09132 | template <typename T> 09133 | class rebasevector_celem_node exprtk_final 09134 | : public expression_node<T> 09135 | , public ivariable <T> 09136 | { 09137 | public: 09138 | 09139 | typedef expression_node<T>* expression_ptr; 09140 | typedef vector_holder<T> vector_holder_t; 09141 | typedef vector_holder_t* vector_holder_ptr; 09142 | typedef std::pair<expression_ptr,bool> branch_t; 09143 | 09144 | rebasevector_celem_node(expression_ptr vec_node, 09145 | const std::size_t index, 09146 | vector_holder_ptr vec_holder) 09147 | : index_(index) 09148 | , vector_holder_(vec_holder) 09149 | { 09150 | construct_branch_pair(vector_node_, vec_node); 09151 | assert(valid()); 09152 | } 09153 | 09154 | inline T value() const exprtk_override 09155 | { 09156 | vector_node_.first->value(); 09157 | return ref();; 09158 | } 09159 | 09160 | inline T& ref() exprtk_override 09161 | { 09162 | return *(vector_holder_->data() + index_); 09163 | } 09164 | 09165 | inline const T& ref() const exprtk_override 09166 | { 09167 | return *(vector_holder_->data() + index_); 09168 | } 09169 | 09170 | inline typename expression_node<T>::node_type type() const exprtk_override 09171 | { 09172 | return expression_node<T>::e_rbveccelem; 09173 | } 09174 | 09175 | inline bool valid() const exprtk_override 09176 | { 09177 | return 09178 | vector_holder_ && 09179 | vector_node_.first && 09180 | vector_node_.first->valid(); 09181 | } 09182 | 09183 | inline vector_holder_t& vec_holder() 09184 | { 09185 | return (*vector_holder_); 09186 | } 09187 | 09188 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09189 | { 09190 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 09191 | } 09192 | 09193 | std::size_t node_depth() const exprtk_override 09194 | { 09195 | return expression_node<T>::ndb_t::compute_node_depth(vector_node_); 09196 | } 09197 | 09198 | private: 09199 | 09200 | const std::size_t index_; 09201 | vector_holder_ptr vector_holder_; 09202 | branch_t vector_node_; 09203 | }; 09204 | 09205 | template <typename T> 09206 | class rebasevector_elem_rtc_node exprtk_final 09207 | : public expression_node<T> 09208 | , public ivariable <T> 09209 | { 09210 | public: 09211 | 09212 | typedef expression_node<T>* expression_ptr; 09213 | typedef vector_holder<T> vector_holder_t; 09214 | typedef vector_holder_t* vector_holder_ptr; 09215 | typedef std::pair<expression_ptr,bool> branch_t; 09216 | 09217 | rebasevector_elem_rtc_node(expression_ptr vec_node, 09218 | expression_ptr index, 09219 | vector_holder_ptr vec_holder, 09220 | vector_access_runtime_check_ptr vec_rt_chk) 09221 | : vector_holder_(vec_holder) 09222 | , vec_rt_chk_(vec_rt_chk) 09223 | { 09224 | construct_branch_pair(vector_node_, vec_node); 09225 | construct_branch_pair(index_ , index ); 09226 | assert(valid()); 09227 | } 09228 | 09229 | inline T value() const exprtk_override 09230 | { 09231 | return *access_vector(); 09232 | } 09233 | 09234 | inline T& ref() exprtk_override 09235 | { 09236 | return *access_vector(); 09237 | } 09238 | 09239 | inline const T& ref() const exprtk_override 09240 | { 09241 | return *access_vector(); 09242 | } 09243 | 09244 | inline typename expression_node<T>::node_type type() const exprtk_override 09245 | { 09246 | return expression_node<T>::e_rbvecelemrtc; 09247 | } 09248 | 09249 | inline bool valid() const exprtk_override 09250 | { 09251 | return 09252 | vector_holder_ && 09253 | index_.first && 09254 | vector_node_.first && 09255 | index_.first->valid() && 09256 | vector_node_.first->valid(); 09257 | } 09258 | 09259 | inline vector_holder_t& vec_holder() 09260 | { 09261 | return (*vector_holder_); 09262 | } 09263 | 09264 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09265 | { 09266 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 09267 | expression_node<T>::ndb_t::collect(index_ , node_delete_list); 09268 | } 09269 | 09270 | std::size_t node_depth() const exprtk_override 09271 | { 09272 | return expression_node<T>::ndb_t::compute_node_depth 09273 | (vector_node_, index_); 09274 | } 09275 | 09276 | private: 09277 | 09278 | inline T* access_vector() const 09279 | { 09280 | vector_node_.first->value(); 09281 | const _uint64_t index = details::numeric::to_uint64(index_.first->value()); 09282 | 09283 | if (index <= (vector_holder_->size() - 1)) 09284 | { 09285 | return (vector_holder_->data() + index); 09286 | } 09287 | 09288 | assert(vec_rt_chk_); 09289 | 09290 | vector_access_runtime_check::violation_context context; 09291 | context.base_ptr = reinterpret_cast<void*>(vector_holder_->data()); 09292 | context.end_ptr = reinterpret_cast<void*>(vector_holder_->data() + vector_holder_->size()); 09293 | context.access_ptr = reinterpret_cast<void*>(vector_holder_->data() + index); 09294 | context.type_size = sizeof(T); 09295 | 09296 | return vec_rt_chk_->handle_runtime_violation(context) ? 09297 | reinterpret_cast<T*>(context.access_ptr) : 09298 | vector_holder_->data() ; 09299 | } 09300 | 09301 | vector_holder_ptr vector_holder_; 09302 | branch_t vector_node_; 09303 | branch_t index_; 09304 | vector_access_runtime_check_ptr vec_rt_chk_; 09305 | }; 09306 | 09307 | template <typename T> 09308 | class rebasevector_celem_rtc_node exprtk_final 09309 | : public expression_node<T> 09310 | , public ivariable <T> 09311 | { 09312 | public: 09313 | 09314 | typedef expression_node<T>* expression_ptr; 09315 | typedef vector_holder<T> vector_holder_t; 09316 | typedef vector_holder_t* vector_holder_ptr; 09317 | typedef std::pair<expression_ptr,bool> branch_t; 09318 | 09319 | rebasevector_celem_rtc_node(expression_ptr vec_node, 09320 | const std::size_t index, 09321 | vector_holder_ptr vec_holder, 09322 | vector_access_runtime_check_ptr vec_rt_chk) 09323 | : index_(index) 09324 | , vector_holder_(vec_holder) 09325 | , vector_base_((*vec_holder)[0]) 09326 | , vec_rt_chk_(vec_rt_chk) 09327 | { 09328 | construct_branch_pair(vector_node_, vec_node); 09329 | assert(valid()); 09330 | } 09331 | 09332 | inline T value() const exprtk_override 09333 | { 09334 | return *access_vector(); 09335 | } 09336 | 09337 | inline T& ref() exprtk_override 09338 | { 09339 | return *access_vector(); 09340 | } 09341 | 09342 | inline const T& ref() const exprtk_override 09343 | { 09344 | return *access_vector(); 09345 | } 09346 | 09347 | inline typename expression_node<T>::node_type type() const exprtk_override 09348 | { 09349 | return expression_node<T>::e_rbveccelemrtc; 09350 | } 09351 | 09352 | inline bool valid() const exprtk_override 09353 | { 09354 | return 09355 | vector_holder_ && 09356 | vector_node_.first && 09357 | vector_node_.first->valid(); 09358 | } 09359 | 09360 | inline vector_holder_t& vec_holder() 09361 | { 09362 | return (*vector_holder_); 09363 | } 09364 | 09365 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09366 | { 09367 | expression_node<T>::ndb_t::collect(vector_node_, node_delete_list); 09368 | } 09369 | 09370 | std::size_t node_depth() const exprtk_override 09371 | { 09372 | return expression_node<T>::ndb_t::compute_node_depth(vector_node_); 09373 | } 09374 | 09375 | private: 09376 | 09377 | inline T* access_vector() const 09378 | { 09379 | vector_node_.first->value(); 09380 | 09381 | if (index_ <= vector_holder_->size() - 1) 09382 | { 09383 | return (vector_holder_->data() + index_); 09384 | } 09385 | 09386 | assert(vec_rt_chk_); 09387 | 09388 | vector_access_runtime_check::violation_context context; 09389 | context.base_ptr = reinterpret_cast<void*>(vector_base_); 09390 | context.end_ptr = reinterpret_cast<void*>(vector_base_ + vector_holder_->size()); 09391 | context.access_ptr = reinterpret_cast<void*>(vector_base_ + index_); 09392 | context.type_size = sizeof(T); 09393 | 09394 | return vec_rt_chk_->handle_runtime_violation(context) ? 09395 | reinterpret_cast<T*>(context.access_ptr) : 09396 | vector_base_ ; 09397 | } 09398 | 09399 | const std::size_t index_; 09400 | vector_holder_ptr vector_holder_; 09401 | T* vector_base_; 09402 | branch_t vector_node_; 09403 | vector_access_runtime_check_ptr vec_rt_chk_; 09404 | }; 09405 | 09406 | template <typename T> 09407 | class vector_initialisation_node exprtk_final : public expression_node<T> 09408 | { 09409 | public: 09410 | 09411 | typedef expression_node<T>* expression_ptr; 09412 | 09413 | vector_initialisation_node(T* vector_base, 09414 | const std::size_t& size, 09415 | const std::vector<expression_ptr>& initialiser_list, 09416 | const bool single_value_initialse) 09417 | : vector_base_(vector_base) 09418 | , initialiser_list_(initialiser_list) 09419 | , size_(size) 09420 | , single_value_initialse_(single_value_initialse) 09421 | , zero_value_initialse_(false) 09422 | , const_nonzero_literal_value_initialse_(false) 09423 | , single_initialiser_value_(T(0)) 09424 | { 09425 | if (single_value_initialse_) 09426 | { 09427 | if (initialiser_list_.empty()) 09428 | zero_value_initialse_ = true; 09429 | else if ( 09430 | (initialiser_list_.size() == 1) && 09431 | details::is_constant_node(initialiser_list_[0]) && 09432 | (T(0) == initialiser_list_[0]->value()) 09433 | ) 09434 | { 09435 | zero_value_initialse_ = true; 09436 | } 09437 | else 09438 | { 09439 | assert(initialiser_list_.size() == 1); 09440 | 09441 | if (details::is_constant_node(initialiser_list_[0])) 09442 | { 09443 | const_nonzero_literal_value_initialse_ = true; 09444 | single_initialiser_value_ = initialiser_list_[0]->value(); 09445 | assert(T(0) != single_initialiser_value_); 09446 | } 09447 | } 09448 | } 09449 | } 09450 | 09451 | inline T value() const exprtk_override 09452 | { 09453 | if (single_value_initialse_) 09454 | { 09455 | if (zero_value_initialse_) 09456 | { 09457 | details::set_zero_value(vector_base_, size_); 09458 | } 09459 | else if (const_nonzero_literal_value_initialse_) 09460 | { 09461 | for (std::size_t i = 0; i < size_; ++i) 09462 | { 09463 | *(vector_base_ + i) = single_initialiser_value_; 09464 | } 09465 | } 09466 | else 09467 | { 09468 | for (std::size_t i = 0; i < size_; ++i) 09469 | { 09470 | *(vector_base_ + i) = initialiser_list_[0]->value(); 09471 | } 09472 | } 09473 | } 09474 | else 09475 | { 09476 | const std::size_t initialiser_list_size = initialiser_list_.size(); 09477 | 09478 | for (std::size_t i = 0; i < initialiser_list_size; ++i) 09479 | { 09480 | *(vector_base_ + i) = initialiser_list_[i]->value(); 09481 | } 09482 | 09483 | if (initialiser_list_size < size_) 09484 | { 09485 | details::set_zero_value( 09486 | vector_base_ + initialiser_list_size, 09487 | (size_ - initialiser_list_size)); 09488 | } 09489 | } 09490 | 09491 | return *(vector_base_); 09492 | } 09493 | 09494 | inline typename expression_node<T>::node_type type() const exprtk_override 09495 | { 09496 | return expression_node<T>::e_vecinit; 09497 | } 09498 | 09499 | inline bool valid() const exprtk_override 09500 | { 09501 | return vector_base_; 09502 | } 09503 | 09504 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09505 | { 09506 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09507 | } 09508 | 09509 | std::size_t node_depth() const exprtk_override 09510 | { 09511 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09512 | } 09513 | 09514 | private: 09515 | 09516 | vector_initialisation_node(const vector_initialisation_node<T>&) exprtk_delete; 09517 | vector_initialisation_node<T>& operator=(const vector_initialisation_node<T>&) exprtk_delete; 09518 | 09519 | mutable T* vector_base_; 09520 | std::vector<expression_ptr> initialiser_list_; 09521 | const std::size_t size_; 09522 | const bool single_value_initialse_; 09523 | bool zero_value_initialse_; 09524 | bool const_nonzero_literal_value_initialse_; 09525 | T single_initialiser_value_; 09526 | }; 09527 | 09528 | template <typename T> 09529 | class vector_init_zero_value_node exprtk_final : public expression_node<T> 09530 | { 09531 | public: 09532 | 09533 | typedef expression_node<T>* expression_ptr; 09534 | 09535 | vector_init_zero_value_node(T* vector_base, 09536 | const std::size_t& size, 09537 | const std::vector<expression_ptr>& initialiser_list) 09538 | : vector_base_(vector_base) 09539 | , size_(size) 09540 | , initialiser_list_(initialiser_list) 09541 | {} 09542 | 09543 | inline T value() const exprtk_override 09544 | { 09545 | details::set_zero_value(vector_base_, size_); 09546 | return *(vector_base_); 09547 | } 09548 | 09549 | inline typename expression_node<T>::node_type type() const exprtk_override 09550 | { 09551 | return expression_node<T>::e_vecinit; 09552 | } 09553 | 09554 | inline bool valid() const exprtk_override 09555 | { 09556 | return vector_base_; 09557 | } 09558 | 09559 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09560 | { 09561 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09562 | } 09563 | 09564 | std::size_t node_depth() const exprtk_override 09565 | { 09566 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09567 | } 09568 | 09569 | private: 09570 | 09571 | vector_init_zero_value_node(const vector_init_zero_value_node<T>&) exprtk_delete; 09572 | vector_init_zero_value_node<T>& operator=(const vector_init_zero_value_node<T>&) exprtk_delete; 09573 | 09574 | mutable T* vector_base_; 09575 | const std::size_t size_; 09576 | std::vector<expression_ptr> initialiser_list_; 09577 | }; 09578 | 09579 | template <typename T> 09580 | class vector_init_single_constvalue_node exprtk_final : public expression_node<T> 09581 | { 09582 | public: 09583 | 09584 | typedef expression_node<T>* expression_ptr; 09585 | 09586 | vector_init_single_constvalue_node(T* vector_base, 09587 | const std::size_t& size, 09588 | const std::vector<expression_ptr>& initialiser_list) 09589 | : vector_base_(vector_base) 09590 | , size_(size) 09591 | , initialiser_list_(initialiser_list) 09592 | { 09593 | single_initialiser_value_ = initialiser_list_[0]->value(); 09594 | assert(valid()); 09595 | } 09596 | 09597 | inline T value() const exprtk_override 09598 | { 09599 | for (std::size_t i = 0; i < size_; ++i) 09600 | { 09601 | *(vector_base_ + i) = single_initialiser_value_; 09602 | } 09603 | 09604 | return *(vector_base_); 09605 | } 09606 | 09607 | inline typename expression_node<T>::node_type type() const exprtk_override 09608 | { 09609 | return expression_node<T>::e_vecinit; 09610 | } 09611 | 09612 | inline bool valid() const exprtk_override 09613 | { 09614 | return vector_base_ && 09615 | (initialiser_list_.size() == 1) && 09616 | (details::is_constant_node(initialiser_list_[0])) && 09617 | (single_initialiser_value_ != T(0)); 09618 | } 09619 | 09620 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09621 | { 09622 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09623 | } 09624 | 09625 | std::size_t node_depth() const exprtk_override 09626 | { 09627 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09628 | } 09629 | 09630 | private: 09631 | 09632 | vector_init_single_constvalue_node(const vector_init_single_constvalue_node<T>&) exprtk_delete; 09633 | vector_init_single_constvalue_node<T>& operator=(const vector_init_single_constvalue_node<T>&) exprtk_delete; 09634 | 09635 | mutable T* vector_base_; 09636 | const std::size_t size_; 09637 | std::vector<expression_ptr> initialiser_list_; 09638 | T single_initialiser_value_; 09639 | }; 09640 | 09641 | template <typename T> 09642 | class vector_init_single_value_node exprtk_final : public expression_node<T> 09643 | { 09644 | public: 09645 | 09646 | typedef expression_node<T>* expression_ptr; 09647 | 09648 | vector_init_single_value_node(T* vector_base, 09649 | const std::size_t& size, 09650 | const std::vector<expression_ptr>& initialiser_list) 09651 | : vector_base_(vector_base) 09652 | , size_(size) 09653 | , initialiser_list_(initialiser_list) 09654 | { 09655 | assert(valid()); 09656 | } 09657 | 09658 | inline T value() const exprtk_override 09659 | { 09660 | expression_node<T>& node = *initialiser_list_[0]; 09661 | 09662 | for (std::size_t i = 0; i < size_; ++i) 09663 | { 09664 | *(vector_base_ + i) = node.value(); 09665 | } 09666 | 09667 | return *(vector_base_); 09668 | } 09669 | 09670 | inline typename expression_node<T>::node_type type() const exprtk_override 09671 | { 09672 | return expression_node<T>::e_vecinit; 09673 | } 09674 | 09675 | inline bool valid() const exprtk_override 09676 | { 09677 | return vector_base_ && 09678 | (initialiser_list_.size() == 1) && 09679 | !details::is_constant_node(initialiser_list_[0]); 09680 | } 09681 | 09682 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09683 | { 09684 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09685 | } 09686 | 09687 | std::size_t node_depth() const exprtk_override 09688 | { 09689 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09690 | } 09691 | 09692 | private: 09693 | 09694 | vector_init_single_value_node(const vector_init_single_value_node<T>&) exprtk_delete; 09695 | vector_init_single_value_node<T>& operator=(const vector_init_single_value_node<T>&) exprtk_delete; 09696 | 09697 | mutable T* vector_base_; 09698 | const std::size_t size_; 09699 | std::vector<expression_ptr> initialiser_list_; 09700 | }; 09701 | 09702 | template <typename T> 09703 | class vector_init_iota_constconst_node exprtk_final : public expression_node<T> 09704 | { 09705 | public: 09706 | 09707 | typedef expression_node<T>* expression_ptr; 09708 | 09709 | vector_init_iota_constconst_node(T* vector_base, 09710 | const std::size_t& size, 09711 | const std::vector<expression_ptr>& initialiser_list) 09712 | : vector_base_(vector_base) 09713 | , size_(size) 09714 | , initialiser_list_(initialiser_list) 09715 | { 09716 | base_value_ = initialiser_list_[0]->value(); 09717 | increment_value_ = initialiser_list_[1]->value(); 09718 | 09719 | assert(valid()); 09720 | } 09721 | 09722 | inline T value() const exprtk_override 09723 | { 09724 | T value = base_value_; 09725 | 09726 | for (std::size_t i = 0; i < size_; ++i, value += increment_value_) 09727 | { 09728 | *(vector_base_ + i) = value; 09729 | } 09730 | 09731 | return *(vector_base_); 09732 | } 09733 | 09734 | inline typename expression_node<T>::node_type type() const exprtk_override 09735 | { 09736 | return expression_node<T>::e_vecinit; 09737 | } 09738 | 09739 | inline bool valid() const exprtk_override 09740 | { 09741 | return vector_base_ && 09742 | (initialiser_list_.size() == 2) && 09743 | (details::is_constant_node(initialiser_list_[0])) && 09744 | (details::is_constant_node(initialiser_list_[1])) ; 09745 | } 09746 | 09747 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09748 | { 09749 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09750 | } 09751 | 09752 | std::size_t node_depth() const exprtk_override 09753 | { 09754 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09755 | } 09756 | 09757 | private: 09758 | 09759 | vector_init_iota_constconst_node(const vector_init_iota_constconst_node<T>&) exprtk_delete; 09760 | vector_init_iota_constconst_node<T>& operator=(const vector_init_iota_constconst_node<T>&) exprtk_delete; 09761 | 09762 | mutable T* vector_base_; 09763 | const std::size_t size_; 09764 | std::vector<expression_ptr> initialiser_list_; 09765 | T base_value_; 09766 | T increment_value_; 09767 | }; 09768 | 09769 | template <typename T> 09770 | class vector_init_iota_constnconst_node exprtk_final : public expression_node<T> 09771 | { 09772 | public: 09773 | 09774 | typedef expression_node<T>* expression_ptr; 09775 | 09776 | vector_init_iota_constnconst_node(T* vector_base, 09777 | const std::size_t& size, 09778 | const std::vector<expression_ptr>& initialiser_list) 09779 | : vector_base_(vector_base) 09780 | , size_(size) 09781 | , initialiser_list_(initialiser_list) 09782 | { 09783 | assert(valid()); 09784 | base_value_ = initialiser_list_[0]->value(); 09785 | } 09786 | 09787 | inline T value() const exprtk_override 09788 | { 09789 | T value = base_value_; 09790 | expression_node<T>& increment = *initialiser_list_[1]; 09791 | 09792 | for (std::size_t i = 0; i < size_; ++i, value += increment.value()) 09793 | { 09794 | *(vector_base_ + i) = value; 09795 | } 09796 | 09797 | return *(vector_base_); 09798 | } 09799 | 09800 | inline typename expression_node<T>::node_type type() const exprtk_override 09801 | { 09802 | return expression_node<T>::e_vecinit; 09803 | } 09804 | 09805 | inline bool valid() const exprtk_override 09806 | { 09807 | return vector_base_ && 09808 | (initialiser_list_.size() == 2) && 09809 | ( details::is_constant_node(initialiser_list_[0])) && 09810 | (!details::is_constant_node(initialiser_list_[1])); 09811 | } 09812 | 09813 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09814 | { 09815 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09816 | } 09817 | 09818 | std::size_t node_depth() const exprtk_override 09819 | { 09820 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09821 | } 09822 | 09823 | private: 09824 | 09825 | vector_init_iota_constnconst_node(const vector_init_iota_constnconst_node<T>&) exprtk_delete; 09826 | vector_init_iota_constnconst_node<T>& operator=(const vector_init_iota_constnconst_node<T>&) exprtk_delete; 09827 | 09828 | mutable T* vector_base_; 09829 | const std::size_t size_; 09830 | std::vector<expression_ptr> initialiser_list_; 09831 | T base_value_; 09832 | }; 09833 | 09834 | template <typename T> 09835 | class vector_init_iota_nconstconst_node exprtk_final : public expression_node<T> 09836 | { 09837 | public: 09838 | 09839 | typedef expression_node<T>* expression_ptr; 09840 | 09841 | vector_init_iota_nconstconst_node(T* vector_base, 09842 | const std::size_t& size, 09843 | const std::vector<expression_ptr>& initialiser_list) 09844 | : vector_base_(vector_base) 09845 | , size_(size) 09846 | , initialiser_list_(initialiser_list) 09847 | { 09848 | assert(valid()); 09849 | } 09850 | 09851 | inline T value() const exprtk_override 09852 | { 09853 | T value = initialiser_list_[0]->value(); 09854 | const T increment = initialiser_list_[1]->value(); 09855 | 09856 | for (std::size_t i = 0; i < size_; ++i, value += increment) 09857 | { 09858 | *(vector_base_ + i) = value; 09859 | } 09860 | 09861 | return *(vector_base_); 09862 | } 09863 | 09864 | inline typename expression_node<T>::node_type type() const exprtk_override 09865 | { 09866 | return expression_node<T>::e_vecinit; 09867 | } 09868 | 09869 | inline bool valid() const exprtk_override 09870 | { 09871 | return vector_base_ && 09872 | (initialiser_list_.size() == 2) && 09873 | (!details::is_constant_node(initialiser_list_[0])) && 09874 | (details::is_constant_node(initialiser_list_[1])); 09875 | } 09876 | 09877 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09878 | { 09879 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09880 | } 09881 | 09882 | std::size_t node_depth() const exprtk_override 09883 | { 09884 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09885 | } 09886 | 09887 | private: 09888 | 09889 | vector_init_iota_nconstconst_node(const vector_init_iota_nconstconst_node<T>&) exprtk_delete; 09890 | vector_init_iota_nconstconst_node<T>& operator=(const vector_init_iota_nconstconst_node<T>&) exprtk_delete; 09891 | 09892 | mutable T* vector_base_; 09893 | const std::size_t size_; 09894 | std::vector<expression_ptr> initialiser_list_; 09895 | }; 09896 | 09897 | template <typename T> 09898 | class vector_init_iota_nconstnconst_node exprtk_final : public expression_node<T> 09899 | { 09900 | public: 09901 | 09902 | typedef expression_node<T>* expression_ptr; 09903 | 09904 | vector_init_iota_nconstnconst_node(T* vector_base, 09905 | const std::size_t& size, 09906 | const std::vector<expression_ptr>& initialiser_list) 09907 | : vector_base_(vector_base) 09908 | , size_(size) 09909 | , initialiser_list_(initialiser_list) 09910 | { 09911 | assert(valid()); 09912 | } 09913 | 09914 | inline T value() const exprtk_override 09915 | { 09916 | T value = initialiser_list_[0]->value(); 09917 | expression_node<T>& increment = *initialiser_list_[1]; 09918 | 09919 | for (std::size_t i = 0; i < size_; ++i, value += increment.value()) 09920 | { 09921 | *(vector_base_ + i) = value; 09922 | } 09923 | 09924 | return *(vector_base_); 09925 | } 09926 | 09927 | inline typename expression_node<T>::node_type type() const exprtk_override 09928 | { 09929 | return expression_node<T>::e_vecinit; 09930 | } 09931 | 09932 | inline bool valid() const exprtk_override 09933 | { 09934 | return vector_base_ && 09935 | (initialiser_list_.size() == 2) && 09936 | (!details::is_constant_node(initialiser_list_[0])) && 09937 | (!details::is_constant_node(initialiser_list_[1])); 09938 | } 09939 | 09940 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 09941 | { 09942 | expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); 09943 | } 09944 | 09945 | std::size_t node_depth() const exprtk_override 09946 | { 09947 | return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); 09948 | } 09949 | 09950 | private: 09951 | 09952 | vector_init_iota_nconstnconst_node(const vector_init_iota_nconstnconst_node<T>&) exprtk_delete; 09953 | vector_init_iota_nconstnconst_node<T>& operator=(const vector_init_iota_nconstnconst_node<T>&) exprtk_delete; 09954 | 09955 | mutable T* vector_base_; 09956 | const std::size_t size_; 09957 | std::vector<expression_ptr> initialiser_list_; 09958 | }; 09959 | 09960 | template <typename T> 09961 | class swap_node exprtk_final : public expression_node<T> 09962 | { 09963 | public: 09964 | 09965 | typedef expression_node<T>* expression_ptr; 09966 | typedef variable_node<T>* variable_node_ptr; 09967 | 09968 | swap_node(variable_node_ptr var0, variable_node_ptr var1) 09969 | : var0_(var0) 09970 | , var1_(var1) 09971 | {} 09972 | 09973 | inline T value() const exprtk_override 09974 | { 09975 | std::swap(var0_->ref(),var1_->ref()); 09976 | return var1_->ref(); 09977 | } 09978 | 09979 | inline typename expression_node<T>::node_type type() const exprtk_override 09980 | { 09981 | return expression_node<T>::e_swap; 09982 | } 09983 | 09984 | private: 09985 | 09986 | variable_node_ptr var0_; 09987 | variable_node_ptr var1_; 09988 | }; 09989 | 09990 | template <typename T> 09991 | class swap_generic_node exprtk_final : public binary_node<T> 09992 | { 09993 | public: 09994 | 09995 | typedef expression_node<T>* expression_ptr; 09996 | typedef ivariable<T>* ivariable_ptr; 09997 | 09998 | swap_generic_node(expression_ptr var0, expression_ptr var1) 09999 | : binary_node<T>(details::e_swap, var0, var1) 10000 | , var0_(dynamic_cast<ivariable_ptr>(var0)) 10001 | , var1_(dynamic_cast<ivariable_ptr>(var1)) 10002 | {} 10003 | 10004 | inline T value() const exprtk_override 10005 | { 10006 | std::swap(var0_->ref(),var1_->ref()); 10007 | return var1_->ref(); 10008 | } 10009 | 10010 | inline typename expression_node<T>::node_type type() const exprtk_override 10011 | { 10012 | return expression_node<T>::e_swap; 10013 | } 10014 | 10015 | private: 10016 | 10017 | ivariable_ptr var0_; 10018 | ivariable_ptr var1_; 10019 | }; 10020 | 10021 | template <typename T> 10022 | class swap_vecvec_node exprtk_final 10023 | : public binary_node <T> 10024 | , public vector_interface<T> 10025 | { 10026 | public: 10027 | 10028 | typedef expression_node<T>* expression_ptr; 10029 | typedef vector_node <T>* vector_node_ptr; 10030 | typedef vec_data_store <T> vds_t; 10031 | 10032 | using binary_node<T>::branch; 10033 | 10034 | swap_vecvec_node(expression_ptr branch0, 10035 | expression_ptr branch1) 10036 | : binary_node<T>(details::e_swap, branch0, branch1) 10037 | , vec0_node_ptr_(0) 10038 | , vec1_node_ptr_(0) 10039 | , initialised_ (false) 10040 | { 10041 | if (is_ivector_node(branch(0))) 10042 | { 10043 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 10044 | 10045 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(0)))) 10046 | { 10047 | vec0_node_ptr_ = vi->vec(); 10048 | vds() = vi->vds(); 10049 | } 10050 | } 10051 | 10052 | if (is_ivector_node(branch(1))) 10053 | { 10054 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 10055 | 10056 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1)))) 10057 | { 10058 | vec1_node_ptr_ = vi->vec(); 10059 | } 10060 | } 10061 | 10062 | if (vec0_node_ptr_ && vec1_node_ptr_) 10063 | { 10064 | initialised_ = size() <= base_size(); 10065 | } 10066 | 10067 | assert(valid()); 10068 | } 10069 | 10070 | inline T value() const exprtk_override 10071 | { 10072 | binary_node<T>::branch(0)->value(); 10073 | binary_node<T>::branch(1)->value(); 10074 | 10075 | T* vec0 = vec0_node_ptr_->vds().data(); 10076 | T* vec1 = vec1_node_ptr_->vds().data(); 10077 | 10078 | assert(size() <= base_size()); 10079 | const std::size_t n = size(); 10080 | 10081 | for (std::size_t i = 0; i < n; ++i) 10082 | { 10083 | std::swap(vec0[i],vec1[i]); 10084 | } 10085 | 10086 | return vec1_node_ptr_->value(); 10087 | } 10088 | 10089 | vector_node_ptr vec() const exprtk_override 10090 | { 10091 | return vec0_node_ptr_; 10092 | } 10093 | 10094 | vector_node_ptr vec() exprtk_override 10095 | { 10096 | return vec0_node_ptr_; 10097 | } 10098 | 10099 | inline typename expression_node<T>::node_type type() const exprtk_override 10100 | { 10101 | return expression_node<T>::e_vecvecswap; 10102 | } 10103 | 10104 | inline bool valid() const exprtk_override 10105 | { 10106 | return initialised_ && binary_node<T>::valid(); 10107 | } 10108 | 10109 | std::size_t size() const exprtk_override 10110 | { 10111 | return std::min( 10112 | vec0_node_ptr_->vec_holder().size(), 10113 | vec1_node_ptr_->vec_holder().size()); 10114 | } 10115 | 10116 | std::size_t base_size() const exprtk_override 10117 | { 10118 | return std::min( 10119 | vec0_node_ptr_->vec_holder().base_size(), 10120 | vec1_node_ptr_->vec_holder().base_size()); 10121 | } 10122 | 10123 | vds_t& vds() exprtk_override 10124 | { 10125 | return vds_; 10126 | } 10127 | 10128 | const vds_t& vds() const exprtk_override 10129 | { 10130 | return vds_; 10131 | } 10132 | 10133 | private: 10134 | 10135 | vector_node<T>* vec0_node_ptr_; 10136 | vector_node<T>* vec1_node_ptr_; 10137 | bool initialised_; 10138 | vds_t vds_; 10139 | }; 10140 | 10141 | #ifndef exprtk_disable_string_capabilities 10142 | template <typename T> 10143 | class stringvar_node exprtk_final 10144 | : public expression_node <T> 10145 | , public string_base_node<T> 10146 | , public range_interface <T> 10147 | { 10148 | public: 10149 | 10150 | typedef typename range_interface<T>::range_t range_t; 10151 | 10152 | static std::string null_value; 10153 | 10154 | explicit stringvar_node() 10155 | : value_(&null_value) 10156 | {} 10157 | 10158 | explicit stringvar_node(std::string& v) 10159 | : value_(&v) 10160 | { 10161 | rp_.n0_c = std::make_pair<bool,std::size_t>(true,0); 10162 | rp_.n1_c = std::make_pair<bool,std::size_t>(true,v.size()); 10163 | rp_.cache.first = rp_.n0_c.second; 10164 | rp_.cache.second = rp_.n1_c.second; 10165 | } 10166 | 10167 | inline bool operator <(const stringvar_node<T>& v) const 10168 | { 10169 | return this < (&v); 10170 | } 10171 | 10172 | inline T value() const exprtk_override 10173 | { 10174 | rp_.n1_c.second = (*value_).size(); 10175 | rp_.cache.second = rp_.n1_c.second; 10176 | 10177 | return std::numeric_limits<T>::quiet_NaN(); 10178 | } 10179 | 10180 | std::string str() const exprtk_override 10181 | { 10182 | return ref(); 10183 | } 10184 | 10185 | char_cptr base() const exprtk_override 10186 | { 10187 | return &(*value_)[0]; 10188 | } 10189 | 10190 | std::size_t size() const exprtk_override 10191 | { 10192 | return ref().size(); 10193 | } 10194 | 10195 | std::string& ref() 10196 | { 10197 | return (*value_); 10198 | } 10199 | 10200 | const std::string& ref() const 10201 | { 10202 | return (*value_); 10203 | } 10204 | 10205 | range_t& range_ref() exprtk_override 10206 | { 10207 | return rp_; 10208 | } 10209 | 10210 | const range_t& range_ref() const exprtk_override 10211 | { 10212 | return rp_; 10213 | } 10214 | 10215 | inline typename expression_node<T>::node_type type() const exprtk_override 10216 | { 10217 | return expression_node<T>::e_stringvar; 10218 | } 10219 | 10220 | void rebase(std::string& s) 10221 | { 10222 | value_ = &s; 10223 | rp_.n0_c = std::make_pair<bool,std::size_t>(true,0); 10224 | rp_.n1_c = std::make_pair<bool,std::size_t>(true,value_->size() - 1); 10225 | rp_.cache.first = rp_.n0_c.second; 10226 | rp_.cache.second = rp_.n1_c.second; 10227 | } 10228 | 10229 | private: 10230 | 10231 | std::string* value_; 10232 | mutable range_t rp_; 10233 | }; 10234 | 10235 | template <typename T> 10236 | std::string stringvar_node<T>::null_value = std::string(""); 10237 | 10238 | template <typename T> 10239 | class string_range_node exprtk_final 10240 | : public expression_node <T> 10241 | , public string_base_node<T> 10242 | , public range_interface <T> 10243 | { 10244 | public: 10245 | 10246 | typedef typename range_interface<T>::range_t range_t; 10247 | 10248 | static std::string null_value; 10249 | 10250 | explicit string_range_node(std::string& v, const range_t& rp) 10251 | : value_(&v) 10252 | , rp_(rp) 10253 | {} 10254 | 10255 | virtual ~string_range_node() 10256 | { 10257 | rp_.free(); 10258 | } 10259 | 10260 | inline bool operator <(const string_range_node<T>& v) const 10261 | { 10262 | return this < (&v); 10263 | } 10264 | 10265 | inline T value() const exprtk_override 10266 | { 10267 | return std::numeric_limits<T>::quiet_NaN(); 10268 | } 10269 | 10270 | inline std::string str() const exprtk_override 10271 | { 10272 | return (*value_); 10273 | } 10274 | 10275 | char_cptr base() const exprtk_override 10276 | { 10277 | return &(*value_)[0]; 10278 | } 10279 | 10280 | std::size_t size() const exprtk_override 10281 | { 10282 | return ref().size(); 10283 | } 10284 | 10285 | inline range_t range() const 10286 | { 10287 | return rp_; 10288 | } 10289 | 10290 | inline virtual std::string& ref() 10291 | { 10292 | return (*value_); 10293 | } 10294 | 10295 | inline virtual const std::string& ref() const 10296 | { 10297 | return (*value_); 10298 | } 10299 | 10300 | inline range_t& range_ref() exprtk_override 10301 | { 10302 | return rp_; 10303 | } 10304 | 10305 | inline const range_t& range_ref() const exprtk_override 10306 | { 10307 | return rp_; 10308 | } 10309 | 10310 | inline typename expression_node<T>::node_type type() const exprtk_override 10311 | { 10312 | return expression_node<T>::e_stringvarrng; 10313 | } 10314 | 10315 | private: 10316 | 10317 | std::string* value_; 10318 | range_t rp_; 10319 | }; 10320 | 10321 | template <typename T> 10322 | std::string string_range_node<T>::null_value = std::string(""); 10323 | 10324 | template <typename T> 10325 | class const_string_range_node exprtk_final 10326 | : public expression_node <T> 10327 | , public string_base_node<T> 10328 | , public range_interface <T> 10329 | { 10330 | public: 10331 | 10332 | typedef typename range_interface<T>::range_t range_t; 10333 | 10334 | explicit const_string_range_node(const std::string& v, const range_t& rp) 10335 | : value_(v) 10336 | , rp_(rp) 10337 | {} 10338 | 10339 | ~const_string_range_node() exprtk_override 10340 | { 10341 | rp_.free(); 10342 | } 10343 | 10344 | inline T value() const exprtk_override 10345 | { 10346 | return std::numeric_limits<T>::quiet_NaN(); 10347 | } 10348 | 10349 | std::string str() const exprtk_override 10350 | { 10351 | return value_; 10352 | } 10353 | 10354 | char_cptr base() const exprtk_override 10355 | { 10356 | return value_.data(); 10357 | } 10358 | 10359 | std::size_t size() const exprtk_override 10360 | { 10361 | return value_.size(); 10362 | } 10363 | 10364 | range_t range() const 10365 | { 10366 | return rp_; 10367 | } 10368 | 10369 | range_t& range_ref() exprtk_override 10370 | { 10371 | return rp_; 10372 | } 10373 | 10374 | const range_t& range_ref() const exprtk_override 10375 | { 10376 | return rp_; 10377 | } 10378 | 10379 | inline typename expression_node<T>::node_type type() const exprtk_override 10380 | { 10381 | return expression_node<T>::e_cstringvarrng; 10382 | } 10383 | 10384 | private: 10385 | 10386 | const_string_range_node(const const_string_range_node<T>&) exprtk_delete; 10387 | const_string_range_node<T>& operator=(const const_string_range_node<T>&) exprtk_delete; 10388 | 10389 | const std::string value_; 10390 | range_t rp_; 10391 | }; 10392 | 10393 | template <typename T> 10394 | class generic_string_range_node exprtk_final 10395 | : public expression_node <T> 10396 | , public string_base_node<T> 10397 | , public range_interface <T> 10398 | { 10399 | public: 10400 | 10401 | typedef expression_node <T>* expression_ptr; 10402 | typedef stringvar_node <T>* strvar_node_ptr; 10403 | typedef string_base_node<T>* str_base_ptr; 10404 | typedef typename range_interface<T>::range_t range_t; 10405 | typedef range_t* range_ptr; 10406 | typedef range_interface<T> irange_t; 10407 | typedef irange_t* irange_ptr; 10408 | typedef std::pair<expression_ptr,bool> branch_t; 10409 | 10410 | generic_string_range_node(expression_ptr str_branch, const range_t& brange) 10411 | : initialised_(false) 10412 | , str_base_ptr_ (0) 10413 | , str_range_ptr_(0) 10414 | , base_range_(brange) 10415 | { 10416 | range_.n0_c = std::make_pair<bool,std::size_t>(true,0); 10417 | range_.n1_c = std::make_pair<bool,std::size_t>(true,0); 10418 | range_.cache.first = range_.n0_c.second; 10419 | range_.cache.second = range_.n1_c.second; 10420 | 10421 | construct_branch_pair(branch_, str_branch); 10422 | 10423 | if (is_generally_string_node(branch_.first)) 10424 | { 10425 | str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_.first); 10426 | 10427 | if (0 == str_base_ptr_) 10428 | return; 10429 | 10430 | str_range_ptr_ = dynamic_cast<irange_ptr>(branch_.first); 10431 | 10432 | if (0 == str_range_ptr_) 10433 | return; 10434 | } 10435 | 10436 | initialised_ = (str_base_ptr_ && str_range_ptr_); 10437 | assert(valid()); 10438 | } 10439 | 10440 | ~generic_string_range_node() exprtk_override 10441 | { 10442 | base_range_.free(); 10443 | } 10444 | 10445 | inline T value() const exprtk_override 10446 | { 10447 | branch_.first->value(); 10448 | 10449 | std::size_t str_r0 = 0; 10450 | std::size_t str_r1 = 0; 10451 | 10452 | std::size_t r0 = 0; 10453 | std::size_t r1 = 0; 10454 | 10455 | const range_t& range = str_range_ptr_->range_ref(); 10456 | 10457 | const std::size_t base_str_size = str_base_ptr_->size(); 10458 | 10459 | if ( 10460 | range (str_r0, str_r1, base_str_size ) && 10461 | base_range_(r0 , r1 , base_str_size - str_r0) 10462 | ) 10463 | { 10464 | const std::size_t size = r1 - r0; 10465 | 10466 | range_.n1_c.second = size; 10467 | range_.cache.second = range_.n1_c.second; 10468 | 10469 | value_.assign(str_base_ptr_->base() + str_r0 + r0, size); 10470 | } 10471 | 10472 | return std::numeric_limits<T>::quiet_NaN(); 10473 | } 10474 | 10475 | std::string str() const exprtk_override 10476 | { 10477 | return value_; 10478 | } 10479 | 10480 | char_cptr base() const exprtk_override 10481 | { 10482 | return &value_[0]; 10483 | } 10484 | 10485 | std::size_t size() const exprtk_override 10486 | { 10487 | return value_.size(); 10488 | } 10489 | 10490 | range_t& range_ref() exprtk_override 10491 | { 10492 | return range_; 10493 | } 10494 | 10495 | const range_t& range_ref() const exprtk_override 10496 | { 10497 | return range_; 10498 | } 10499 | 10500 | inline typename expression_node<T>::node_type type() const exprtk_override 10501 | { 10502 | return expression_node<T>::e_strgenrange; 10503 | } 10504 | 10505 | inline bool valid() const exprtk_override 10506 | { 10507 | return initialised_ && branch_.first; 10508 | } 10509 | 10510 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 10511 | { 10512 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 10513 | } 10514 | 10515 | std::size_t node_depth() const exprtk_override 10516 | { 10517 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 10518 | } 10519 | 10520 | private: 10521 | 10522 | bool initialised_; 10523 | branch_t branch_; 10524 | str_base_ptr str_base_ptr_; 10525 | irange_ptr str_range_ptr_; 10526 | mutable range_t base_range_; 10527 | mutable range_t range_; 10528 | mutable std::string value_; 10529 | }; 10530 | 10531 | template <typename T> 10532 | class string_concat_node exprtk_final 10533 | : public binary_node <T> 10534 | , public string_base_node<T> 10535 | , public range_interface <T> 10536 | { 10537 | public: 10538 | 10539 | typedef typename range_interface<T>::range_t range_t; 10540 | typedef range_interface<T> irange_t; 10541 | typedef irange_t* irange_ptr; 10542 | typedef range_t* range_ptr; 10543 | typedef expression_node <T>* expression_ptr; 10544 | typedef string_base_node<T>* str_base_ptr; 10545 | 10546 | using binary_node<T>::branch; 10547 | 10548 | string_concat_node(const operator_type& opr, 10549 | expression_ptr branch0, 10550 | expression_ptr branch1) 10551 | : binary_node<T>(opr, branch0, branch1) 10552 | , initialised_(false) 10553 | , str0_base_ptr_ (0) 10554 | , str1_base_ptr_ (0) 10555 | , str0_range_ptr_(0) 10556 | , str1_range_ptr_(0) 10557 | { 10558 | range_.n0_c = std::make_pair<bool,std::size_t>(true,0); 10559 | range_.n1_c = std::make_pair<bool,std::size_t>(true,0); 10560 | 10561 | range_.cache.first = range_.n0_c.second; 10562 | range_.cache.second = range_.n1_c.second; 10563 | 10564 | if (is_generally_string_node(branch(0))) 10565 | { 10566 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0)); 10567 | 10568 | if (0 == str0_base_ptr_) 10569 | return; 10570 | 10571 | str0_range_ptr_ = dynamic_cast<irange_ptr>(branch(0)); 10572 | 10573 | if (0 == str0_range_ptr_) 10574 | return; 10575 | } 10576 | 10577 | if (is_generally_string_node(branch(1))) 10578 | { 10579 | str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1)); 10580 | 10581 | if (0 == str1_base_ptr_) 10582 | return; 10583 | 10584 | str1_range_ptr_ = dynamic_cast<irange_ptr>(branch(1)); 10585 | 10586 | if (0 == str1_range_ptr_) 10587 | return; 10588 | } 10589 | 10590 | initialised_ = str0_base_ptr_ && 10591 | str1_base_ptr_ && 10592 | str0_range_ptr_ && 10593 | str1_range_ptr_ ; 10594 | 10595 | assert(valid()); 10596 | } 10597 | 10598 | inline T value() const exprtk_override 10599 | { 10600 | branch(0)->value(); 10601 | branch(1)->value(); 10602 | 10603 | std::size_t str0_r0 = 0; 10604 | std::size_t str0_r1 = 0; 10605 | 10606 | std::size_t str1_r0 = 0; 10607 | std::size_t str1_r1 = 0; 10608 | 10609 | const range_t& range0 = str0_range_ptr_->range_ref(); 10610 | const range_t& range1 = str1_range_ptr_->range_ref(); 10611 | 10612 | if ( 10613 | range0(str0_r0, str0_r1, str0_base_ptr_->size()) && 10614 | range1(str1_r0, str1_r1, str1_base_ptr_->size()) 10615 | ) 10616 | { 10617 | const std::size_t size0 = (str0_r1 - str0_r0); 10618 | const std::size_t size1 = (str1_r1 - str1_r0); 10619 | 10620 | value_.assign(str0_base_ptr_->base() + str0_r0, size0); 10621 | value_.append(str1_base_ptr_->base() + str1_r0, size1); 10622 | 10623 | range_.n1_c.second = value_.size(); 10624 | range_.cache.second = range_.n1_c.second; 10625 | } 10626 | 10627 | return std::numeric_limits<T>::quiet_NaN(); 10628 | } 10629 | 10630 | std::string str() const exprtk_override 10631 | { 10632 | return value_; 10633 | } 10634 | 10635 | char_cptr base() const exprtk_override 10636 | { 10637 | return &value_[0]; 10638 | } 10639 | 10640 | std::size_t size() const exprtk_override 10641 | { 10642 | return value_.size(); 10643 | } 10644 | 10645 | range_t& range_ref() exprtk_override 10646 | { 10647 | return range_; 10648 | } 10649 | 10650 | const range_t& range_ref() const exprtk_override 10651 | { 10652 | return range_; 10653 | } 10654 | 10655 | inline typename expression_node<T>::node_type type() const exprtk_override 10656 | { 10657 | return expression_node<T>::e_strconcat; 10658 | } 10659 | 10660 | inline bool valid() const exprtk_override 10661 | { 10662 | return initialised_ && binary_node<T>::valid(); 10663 | } 10664 | 10665 | private: 10666 | 10667 | bool initialised_; 10668 | str_base_ptr str0_base_ptr_; 10669 | str_base_ptr str1_base_ptr_; 10670 | irange_ptr str0_range_ptr_; 10671 | irange_ptr str1_range_ptr_; 10672 | mutable range_t range_; 10673 | mutable std::string value_; 10674 | }; 10675 | 10676 | template <typename T> 10677 | class swap_string_node exprtk_final 10678 | : public binary_node <T> 10679 | , public string_base_node<T> 10680 | , public range_interface <T> 10681 | { 10682 | public: 10683 | 10684 | typedef typename range_interface<T>::range_t range_t; 10685 | typedef range_t* range_ptr; 10686 | typedef range_interface<T> irange_t; 10687 | typedef irange_t* irange_ptr; 10688 | typedef expression_node <T>* expression_ptr; 10689 | typedef stringvar_node <T>* strvar_node_ptr; 10690 | typedef string_base_node<T>* str_base_ptr; 10691 | 10692 | using binary_node<T>::branch; 10693 | 10694 | swap_string_node(expression_ptr branch0, expression_ptr branch1) 10695 | : binary_node<T>(details::e_swap, branch0, branch1) 10696 | , initialised_(false) 10697 | , str0_node_ptr_(0) 10698 | , str1_node_ptr_(0) 10699 | { 10700 | if (is_string_node(branch(0))) 10701 | { 10702 | str0_node_ptr_ = static_cast<strvar_node_ptr>(branch(0)); 10703 | } 10704 | 10705 | if (is_string_node(branch(1))) 10706 | { 10707 | str1_node_ptr_ = static_cast<strvar_node_ptr>(branch(1)); 10708 | } 10709 | 10710 | initialised_ = (str0_node_ptr_ && str1_node_ptr_); 10711 | assert(valid()); 10712 | } 10713 | 10714 | inline T value() const exprtk_override 10715 | { 10716 | branch(0)->value(); 10717 | branch(1)->value(); 10718 | 10719 | std::swap(str0_node_ptr_->ref(), str1_node_ptr_->ref()); 10720 | 10721 | return std::numeric_limits<T>::quiet_NaN(); 10722 | } 10723 | 10724 | std::string str() const exprtk_override 10725 | { 10726 | return str0_node_ptr_->str(); 10727 | } 10728 | 10729 | char_cptr base() const exprtk_override 10730 | { 10731 | return str0_node_ptr_->base(); 10732 | } 10733 | 10734 | std::size_t size() const exprtk_override 10735 | { 10736 | return str0_node_ptr_->size(); 10737 | } 10738 | 10739 | range_t& range_ref() exprtk_override 10740 | { 10741 | return str0_node_ptr_->range_ref(); 10742 | } 10743 | 10744 | const range_t& range_ref() const exprtk_override 10745 | { 10746 | return str0_node_ptr_->range_ref(); 10747 | } 10748 | 10749 | inline typename expression_node<T>::node_type type() const exprtk_override 10750 | { 10751 | return expression_node<T>::e_strswap; 10752 | } 10753 | 10754 | inline bool valid() const exprtk_override 10755 | { 10756 | return initialised_ && binary_node<T>::valid(); 10757 | } 10758 | 10759 | private: 10760 | 10761 | bool initialised_; 10762 | strvar_node_ptr str0_node_ptr_; 10763 | strvar_node_ptr str1_node_ptr_; 10764 | }; 10765 | 10766 | template <typename T> 10767 | class swap_genstrings_node exprtk_final : public binary_node<T> 10768 | { 10769 | public: 10770 | 10771 | typedef typename range_interface<T>::range_t range_t; 10772 | typedef range_t* range_ptr; 10773 | typedef range_interface<T> irange_t; 10774 | typedef irange_t* irange_ptr; 10775 | typedef expression_node <T>* expression_ptr; 10776 | typedef string_base_node<T>* str_base_ptr; 10777 | 10778 | using binary_node<T>::branch; 10779 | 10780 | swap_genstrings_node(expression_ptr branch0, 10781 | expression_ptr branch1) 10782 | : binary_node<T>(details::e_default, branch0, branch1) 10783 | , str0_base_ptr_ (0) 10784 | , str1_base_ptr_ (0) 10785 | , str0_range_ptr_(0) 10786 | , str1_range_ptr_(0) 10787 | , initialised_(false) 10788 | { 10789 | if (is_generally_string_node(branch(0))) 10790 | { 10791 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0)); 10792 | 10793 | if (0 == str0_base_ptr_) 10794 | return; 10795 | 10796 | irange_ptr range = dynamic_cast<irange_ptr>(branch(0)); 10797 | 10798 | if (0 == range) 10799 | return; 10800 | 10801 | str0_range_ptr_ = &(range->range_ref()); 10802 | } 10803 | 10804 | if (is_generally_string_node(branch(1))) 10805 | { 10806 | str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1)); 10807 | 10808 | if (0 == str1_base_ptr_) 10809 | return; 10810 | 10811 | irange_ptr range = dynamic_cast<irange_ptr>(branch(1)); 10812 | 10813 | if (0 == range) 10814 | return; 10815 | 10816 | str1_range_ptr_ = &(range->range_ref()); 10817 | } 10818 | 10819 | initialised_ = str0_base_ptr_ && 10820 | str1_base_ptr_ && 10821 | str0_range_ptr_ && 10822 | str1_range_ptr_ ; 10823 | 10824 | assert(valid()); 10825 | } 10826 | 10827 | inline T value() const exprtk_override 10828 | { 10829 | branch(0)->value(); 10830 | branch(1)->value(); 10831 | 10832 | std::size_t str0_r0 = 0; 10833 | std::size_t str0_r1 = 0; 10834 | 10835 | std::size_t str1_r0 = 0; 10836 | std::size_t str1_r1 = 0; 10837 | 10838 | const range_t& range0 = (*str0_range_ptr_); 10839 | const range_t& range1 = (*str1_range_ptr_); 10840 | 10841 | if ( 10842 | range0(str0_r0, str0_r1, str0_base_ptr_->size()) && 10843 | range1(str1_r0, str1_r1, str1_base_ptr_->size()) 10844 | ) 10845 | { 10846 | const std::size_t size0 = range0.cache_size(); 10847 | const std::size_t size1 = range1.cache_size(); 10848 | const std::size_t max_size = std::min(size0,size1); 10849 | 10850 | char_ptr s0 = const_cast<char_ptr>(str0_base_ptr_->base() + str0_r0); 10851 | char_ptr s1 = const_cast<char_ptr>(str1_base_ptr_->base() + str1_r0); 10852 | 10853 | loop_unroll::details lud(max_size); 10854 | char_cptr upper_bound = s0 + lud.upper_bound; 10855 | 10856 | while (s0 < upper_bound) 10857 | { 10858 | #define exprtk_loop(N) \ 10859 | std::swap(s0[N], s1[N]); \ 10860 | 10861 | exprtk_loop( 0) exprtk_loop( 1) 10862 | exprtk_loop( 2) exprtk_loop( 3) 10863 | #ifndef exprtk_disable_superscalar_unroll 10864 | exprtk_loop( 4) exprtk_loop( 5) 10865 | exprtk_loop( 6) exprtk_loop( 7) 10866 | exprtk_loop( 8) exprtk_loop( 9) 10867 | exprtk_loop(10) exprtk_loop(11) 10868 | exprtk_loop(12) exprtk_loop(13) 10869 | exprtk_loop(14) exprtk_loop(15) 10870 | #endif 10871 | 10872 | s0 += lud.batch_size; 10873 | s1 += lud.batch_size; 10874 | } 10875 | 10876 | int i = 0; 10877 | 10878 | switch (lud.remainder) 10879 | { 10880 | #define case_stmt(N) \ 10881 | case N : { std::swap(s0[i], s1[i]); ++i; } \ 10882 | exprtk_fallthrough \ 10883 | 10884 | #ifndef exprtk_disable_superscalar_unroll 10885 | case_stmt(15) case_stmt(14) 10886 | case_stmt(13) case_stmt(12) 10887 | case_stmt(11) case_stmt(10) 10888 | case_stmt( 9) case_stmt( 8) 10889 | case_stmt( 7) case_stmt( 6) 10890 | case_stmt( 5) case_stmt( 4) 10891 | #endif 10892 | case_stmt( 3) case_stmt( 2) 10893 | case_stmt( 1) 10894 | default: break; 10895 | } 10896 | 10897 | #undef exprtk_loop 10898 | #undef case_stmt 10899 | } 10900 | 10901 | return std::numeric_limits<T>::quiet_NaN(); 10902 | } 10903 | 10904 | inline typename expression_node<T>::node_type type() const exprtk_override 10905 | { 10906 | return expression_node<T>::e_strswap; 10907 | } 10908 | 10909 | inline bool valid() const exprtk_override 10910 | { 10911 | return initialised_ && binary_node<T>::valid(); 10912 | } 10913 | 10914 | private: 10915 | 10916 | swap_genstrings_node(const swap_genstrings_node<T>&) exprtk_delete; 10917 | swap_genstrings_node<T>& operator=(const swap_genstrings_node<T>&) exprtk_delete; 10918 | 10919 | str_base_ptr str0_base_ptr_; 10920 | str_base_ptr str1_base_ptr_; 10921 | range_ptr str0_range_ptr_; 10922 | range_ptr str1_range_ptr_; 10923 | bool initialised_; 10924 | }; 10925 | 10926 | template <typename T> 10927 | class stringvar_size_node exprtk_final : public expression_node<T> 10928 | { 10929 | public: 10930 | 10931 | static const std::string null_value; 10932 | 10933 | explicit stringvar_size_node() 10934 | : value_(&null_value) 10935 | {} 10936 | 10937 | explicit stringvar_size_node(std::string& v) 10938 | : value_(&v) 10939 | {} 10940 | 10941 | inline T value() const exprtk_override 10942 | { 10943 | return T((*value_).size()); 10944 | } 10945 | 10946 | inline typename expression_node<T>::node_type type() const exprtk_override 10947 | { 10948 | return expression_node<T>::e_stringvarsize; 10949 | } 10950 | 10951 | private: 10952 | 10953 | const std::string* value_; 10954 | }; 10955 | 10956 | template <typename T> 10957 | const std::string stringvar_size_node<T>::null_value = std::string(""); 10958 | 10959 | template <typename T> 10960 | class string_size_node exprtk_final : public expression_node<T> 10961 | { 10962 | public: 10963 | 10964 | typedef expression_node <T>* expression_ptr; 10965 | typedef string_base_node<T>* str_base_ptr; 10966 | typedef std::pair<expression_ptr,bool> branch_t; 10967 | 10968 | explicit string_size_node(expression_ptr branch) 10969 | : str_base_ptr_(0) 10970 | { 10971 | construct_branch_pair(branch_, branch); 10972 | 10973 | if (is_generally_string_node(branch_.first)) 10974 | { 10975 | str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_.first); 10976 | } 10977 | 10978 | assert(valid()); 10979 | } 10980 | 10981 | inline T value() const exprtk_override 10982 | { 10983 | branch_.first->value(); 10984 | return T(str_base_ptr_->size()); 10985 | } 10986 | 10987 | inline typename expression_node<T>::node_type type() const exprtk_override 10988 | { 10989 | return expression_node<T>::e_stringsize; 10990 | } 10991 | 10992 | inline bool valid() const exprtk_override 10993 | { 10994 | return str_base_ptr_; 10995 | } 10996 | 10997 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 10998 | { 10999 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 11000 | } 11001 | 11002 | std::size_t node_depth() const exprtk_override 11003 | { 11004 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 11005 | } 11006 | 11007 | private: 11008 | 11009 | branch_t branch_; 11010 | str_base_ptr str_base_ptr_; 11011 | }; 11012 | 11013 | struct asn_assignment 11014 | { 11015 | static inline void execute(std::string& s, char_cptr data, const std::size_t size) 11016 | { s.assign(data,size); } 11017 | }; 11018 | 11019 | struct asn_addassignment 11020 | { 11021 | static inline void execute(std::string& s, char_cptr data, const std::size_t size) 11022 | { s.append(data,size); } 11023 | }; 11024 | 11025 | template <typename T, typename AssignmentProcess = asn_assignment> 11026 | class assignment_string_node exprtk_final 11027 | : public binary_node <T> 11028 | , public string_base_node<T> 11029 | , public range_interface <T> 11030 | { 11031 | public: 11032 | 11033 | typedef typename range_interface<T>::range_t range_t; 11034 | typedef range_t* range_ptr; 11035 | typedef range_interface <T> irange_t; 11036 | typedef irange_t* irange_ptr; 11037 | typedef expression_node <T>* expression_ptr; 11038 | typedef stringvar_node <T>* strvar_node_ptr; 11039 | typedef string_base_node<T>* str_base_ptr; 11040 | 11041 | using binary_node<T>::branch; 11042 | 11043 | assignment_string_node(const operator_type& opr, 11044 | expression_ptr branch0, 11045 | expression_ptr branch1) 11046 | : binary_node<T>(opr, branch0, branch1) 11047 | , initialised_(false) 11048 | , str0_base_ptr_ (0) 11049 | , str1_base_ptr_ (0) 11050 | , str0_node_ptr_ (0) 11051 | , str1_range_ptr_(0) 11052 | { 11053 | if (is_string_node(branch(0))) 11054 | { 11055 | str0_node_ptr_ = static_cast<strvar_node_ptr>(branch(0)); 11056 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0)); 11057 | } 11058 | 11059 | if (is_generally_string_node(branch(1))) 11060 | { 11061 | str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1)); 11062 | 11063 | if (0 == str1_base_ptr_) 11064 | return; 11065 | 11066 | irange_ptr range = dynamic_cast<irange_ptr>(branch(1)); 11067 | 11068 | if (0 == range) 11069 | return; 11070 | 11071 | str1_range_ptr_ = &(range->range_ref()); 11072 | } 11073 | 11074 | initialised_ = str0_base_ptr_ && 11075 | str1_base_ptr_ && 11076 | str0_node_ptr_ && 11077 | str1_range_ptr_ ; 11078 | 11079 | assert(valid()); 11080 | } 11081 | 11082 | inline T value() const exprtk_override 11083 | { 11084 | branch(1)->value(); 11085 | 11086 | std::size_t r0 = 0; 11087 | std::size_t r1 = 0; 11088 | 11089 | const range_t& range = (*str1_range_ptr_); 11090 | 11091 | if (range(r0, r1, str1_base_ptr_->size())) 11092 | { 11093 | AssignmentProcess::execute( 11094 | str0_node_ptr_->ref(), 11095 | str1_base_ptr_->base() + r0, (r1 - r0)); 11096 | 11097 | branch(0)->value(); 11098 | } 11099 | 11100 | return std::numeric_limits<T>::quiet_NaN(); 11101 | } 11102 | 11103 | std::string str() const exprtk_override 11104 | { 11105 | return str0_node_ptr_->str(); 11106 | } 11107 | 11108 | char_cptr base() const exprtk_override 11109 | { 11110 | return str0_node_ptr_->base(); 11111 | } 11112 | 11113 | std::size_t size() const exprtk_override 11114 | { 11115 | return str0_node_ptr_->size(); 11116 | } 11117 | 11118 | range_t& range_ref() exprtk_override 11119 | { 11120 | return str0_node_ptr_->range_ref(); 11121 | } 11122 | 11123 | const range_t& range_ref() const exprtk_override 11124 | { 11125 | return str0_node_ptr_->range_ref(); 11126 | } 11127 | 11128 | inline typename expression_node<T>::node_type type() const exprtk_override 11129 | { 11130 | return expression_node<T>::e_strass; 11131 | } 11132 | 11133 | inline bool valid() const exprtk_override 11134 | { 11135 | return initialised_ && binary_node<T>::valid(); 11136 | } 11137 | 11138 | private: 11139 | 11140 | bool initialised_; 11141 | str_base_ptr str0_base_ptr_; 11142 | str_base_ptr str1_base_ptr_; 11143 | strvar_node_ptr str0_node_ptr_; 11144 | range_ptr str1_range_ptr_; 11145 | }; 11146 | 11147 | template <typename T, typename AssignmentProcess = asn_assignment> 11148 | class assignment_string_range_node exprtk_final 11149 | : public binary_node <T> 11150 | , public string_base_node<T> 11151 | , public range_interface <T> 11152 | { 11153 | public: 11154 | 11155 | typedef typename range_interface<T>::range_t range_t; 11156 | typedef range_t* range_ptr; 11157 | typedef range_interface <T> irange_t; 11158 | typedef irange_t* irange_ptr; 11159 | typedef expression_node <T>* expression_ptr; 11160 | typedef stringvar_node <T>* strvar_node_ptr; 11161 | typedef string_range_node<T>* str_rng_node_ptr; 11162 | typedef string_base_node <T>* str_base_ptr; 11163 | 11164 | using binary_node<T>::branch; 11165 | 11166 | assignment_string_range_node(const operator_type& opr, 11167 | expression_ptr branch0, 11168 | expression_ptr branch1) 11169 | : binary_node<T>(opr, branch0, branch1) 11170 | , initialised_(false) 11171 | , str0_base_ptr_ (0) 11172 | , str1_base_ptr_ (0) 11173 | , str0_rng_node_ptr_(0) 11174 | , str0_range_ptr_ (0) 11175 | , str1_range_ptr_ (0) 11176 | { 11177 | if (is_string_range_node(branch(0))) 11178 | { 11179 | str0_rng_node_ptr_ = static_cast<str_rng_node_ptr>(branch(0)); 11180 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0)); 11181 | irange_ptr range = dynamic_cast<irange_ptr>(branch(0)); 11182 | 11183 | if (0 == range) 11184 | return; 11185 | 11186 | str0_range_ptr_ = &(range->range_ref()); 11187 | } 11188 | 11189 | if (is_generally_string_node(branch(1))) 11190 | { 11191 | str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1)); 11192 | 11193 | if (0 == str1_base_ptr_) 11194 | return; 11195 | 11196 | irange_ptr range = dynamic_cast<irange_ptr>(branch(1)); 11197 | 11198 | if (0 == range) 11199 | return; 11200 | 11201 | str1_range_ptr_ = &(range->range_ref()); 11202 | } 11203 | 11204 | initialised_ = str0_base_ptr_ && 11205 | str1_base_ptr_ && 11206 | str0_rng_node_ptr_ && 11207 | str0_range_ptr_ && 11208 | str1_range_ptr_ ; 11209 | 11210 | assert(valid()); 11211 | } 11212 | 11213 | inline T value() const exprtk_override 11214 | { 11215 | branch(0)->value(); 11216 | branch(1)->value(); 11217 | 11218 | std::size_t s0_r0 = 0; 11219 | std::size_t s0_r1 = 0; 11220 | 11221 | std::size_t s1_r0 = 0; 11222 | std::size_t s1_r1 = 0; 11223 | 11224 | const range_t& range0 = (*str0_range_ptr_); 11225 | const range_t& range1 = (*str1_range_ptr_); 11226 | 11227 | if ( 11228 | range0(s0_r0, s0_r1, str0_base_ptr_->size()) && 11229 | range1(s1_r0, s1_r1, str1_base_ptr_->size()) 11230 | ) 11231 | { 11232 | const std::size_t size = std::min((s0_r1 - s0_r0), (s1_r1 - s1_r0)); 11233 | 11234 | std::copy( 11235 | str1_base_ptr_->base() + s1_r0, 11236 | str1_base_ptr_->base() + s1_r0 + size, 11237 | const_cast<char_ptr>(base() + s0_r0)); 11238 | } 11239 | 11240 | return std::numeric_limits<T>::quiet_NaN(); 11241 | } 11242 | 11243 | std::string str() const exprtk_override 11244 | { 11245 | return str0_base_ptr_->str(); 11246 | } 11247 | 11248 | char_cptr base() const exprtk_override 11249 | { 11250 | return str0_base_ptr_->base(); 11251 | } 11252 | 11253 | std::size_t size() const exprtk_override 11254 | { 11255 | return str0_base_ptr_->size(); 11256 | } 11257 | 11258 | range_t& range_ref() exprtk_override 11259 | { 11260 | return str0_rng_node_ptr_->range_ref(); 11261 | } 11262 | 11263 | const range_t& range_ref() const exprtk_override 11264 | { 11265 | return str0_rng_node_ptr_->range_ref(); 11266 | } 11267 | 11268 | inline typename expression_node<T>::node_type type() const exprtk_override 11269 | { 11270 | return expression_node<T>::e_strass; 11271 | } 11272 | 11273 | inline bool valid() const exprtk_override 11274 | { 11275 | return initialised_ && binary_node<T>::valid(); 11276 | } 11277 | 11278 | private: 11279 | 11280 | bool initialised_; 11281 | str_base_ptr str0_base_ptr_; 11282 | str_base_ptr str1_base_ptr_; 11283 | str_rng_node_ptr str0_rng_node_ptr_; 11284 | range_ptr str0_range_ptr_; 11285 | range_ptr str1_range_ptr_; 11286 | }; 11287 | 11288 | template <typename T> 11289 | class conditional_string_node exprtk_final 11290 | : public trinary_node <T> 11291 | , public string_base_node<T> 11292 | , public range_interface <T> 11293 | { 11294 | public: 11295 | 11296 | typedef typename range_interface<T>::range_t range_t; 11297 | typedef range_t* range_ptr; 11298 | typedef range_interface <T> irange_t; 11299 | typedef irange_t* irange_ptr; 11300 | typedef expression_node <T>* expression_ptr; 11301 | typedef string_base_node<T>* str_base_ptr; 11302 | 11303 | conditional_string_node(expression_ptr condition, 11304 | expression_ptr consequent, 11305 | expression_ptr alternative) 11306 | : trinary_node<T>(details::e_default, consequent, alternative, condition) 11307 | , initialised_(false) 11308 | , str0_base_ptr_ (0) 11309 | , str1_base_ptr_ (0) 11310 | , str0_range_ptr_(0) 11311 | , str1_range_ptr_(0) 11312 | , condition_ (condition ) 11313 | , consequent_ (consequent ) 11314 | , alternative_(alternative) 11315 | { 11316 | range_.n0_c = std::make_pair<bool,std::size_t>(true,0); 11317 | range_.n1_c = std::make_pair<bool,std::size_t>(true,0); 11318 | 11319 | range_.cache.first = range_.n0_c.second; 11320 | range_.cache.second = range_.n1_c.second; 11321 | 11322 | if (is_generally_string_node(trinary_node<T>::branch_[0].first)) 11323 | { 11324 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(trinary_node<T>::branch_[0].first); 11325 | 11326 | if (0 == str0_base_ptr_) 11327 | return; 11328 | 11329 | str0_range_ptr_ = dynamic_cast<irange_ptr>(trinary_node<T>::branch_[0].first); 11330 | 11331 | if (0 == str0_range_ptr_) 11332 | return; 11333 | } 11334 | 11335 | if (is_generally_string_node(trinary_node<T>::branch_[1].first)) 11336 | { 11337 | str1_base_ptr_ = dynamic_cast<str_base_ptr>(trinary_node<T>::branch_[1].first); 11338 | 11339 | if (0 == str1_base_ptr_) 11340 | return; 11341 | 11342 | str1_range_ptr_ = dynamic_cast<irange_ptr>(trinary_node<T>::branch_[1].first); 11343 | 11344 | if (0 == str1_range_ptr_) 11345 | return; 11346 | } 11347 | 11348 | initialised_ = str0_base_ptr_ && 11349 | str1_base_ptr_ && 11350 | str0_range_ptr_ && 11351 | str1_range_ptr_ ; 11352 | 11353 | assert(valid()); 11354 | } 11355 | 11356 | inline T value() const exprtk_override 11357 | { 11358 | std::size_t r0 = 0; 11359 | std::size_t r1 = 0; 11360 | 11361 | if (is_true(condition_)) 11362 | { 11363 | consequent_->value(); 11364 | 11365 | const range_t& range = str0_range_ptr_->range_ref(); 11366 | 11367 | if (range(r0, r1, str0_base_ptr_->size())) 11368 | { 11369 | const std::size_t size = (r1 - r0); 11370 | 11371 | value_.assign(str0_base_ptr_->base() + r0, size); 11372 | 11373 | range_.n1_c.second = value_.size(); 11374 | range_.cache.second = range_.n1_c.second; 11375 | 11376 | return T(1); 11377 | } 11378 | } 11379 | else 11380 | { 11381 | alternative_->value(); 11382 | 11383 | const range_t& range = str1_range_ptr_->range_ref(); 11384 | 11385 | if (range(r0, r1, str1_base_ptr_->size())) 11386 | { 11387 | const std::size_t size = (r1 - r0); 11388 | 11389 | value_.assign(str1_base_ptr_->base() + r0, size); 11390 | 11391 | range_.n1_c.second = value_.size(); 11392 | range_.cache.second = range_.n1_c.second; 11393 | 11394 | return T(0); 11395 | } 11396 | } 11397 | 11398 | return std::numeric_limits<T>::quiet_NaN(); 11399 | } 11400 | 11401 | std::string str() const exprtk_override 11402 | { 11403 | return value_; 11404 | } 11405 | 11406 | char_cptr base() const exprtk_override 11407 | { 11408 | return &value_[0]; 11409 | } 11410 | 11411 | std::size_t size() const exprtk_override 11412 | { 11413 | return value_.size(); 11414 | } 11415 | 11416 | range_t& range_ref() exprtk_override 11417 | { 11418 | return range_; 11419 | } 11420 | 11421 | const range_t& range_ref() const exprtk_override 11422 | { 11423 | return range_; 11424 | } 11425 | 11426 | inline typename expression_node<T>::node_type type() const exprtk_override 11427 | { 11428 | return expression_node<T>::e_strcondition; 11429 | } 11430 | 11431 | inline bool valid() const exprtk_override 11432 | { 11433 | return 11434 | initialised_ && 11435 | condition_ && condition_ ->valid() && 11436 | consequent_ && consequent_ ->valid() && 11437 | alternative_&& alternative_->valid() ; 11438 | } 11439 | 11440 | private: 11441 | 11442 | bool initialised_; 11443 | str_base_ptr str0_base_ptr_; 11444 | str_base_ptr str1_base_ptr_; 11445 | irange_ptr str0_range_ptr_; 11446 | irange_ptr str1_range_ptr_; 11447 | mutable range_t range_; 11448 | mutable std::string value_; 11449 | 11450 | expression_ptr condition_; 11451 | expression_ptr consequent_; 11452 | expression_ptr alternative_; 11453 | }; 11454 | 11455 | template <typename T> 11456 | class cons_conditional_str_node exprtk_final 11457 | : public binary_node <T> 11458 | , public string_base_node<T> 11459 | , public range_interface <T> 11460 | { 11461 | public: 11462 | 11463 | typedef typename range_interface<T>::range_t range_t; 11464 | typedef range_t* range_ptr; 11465 | typedef range_interface <T> irange_t; 11466 | typedef irange_t* irange_ptr; 11467 | typedef expression_node <T>* expression_ptr; 11468 | typedef string_base_node<T>* str_base_ptr; 11469 | 11470 | using binary_node<T>::branch; 11471 | 11472 | cons_conditional_str_node(expression_ptr condition, 11473 | expression_ptr consequent) 11474 | : binary_node<T>(details::e_default, consequent, condition) 11475 | , initialised_(false) 11476 | , str0_base_ptr_ (0) 11477 | , str0_range_ptr_(0) 11478 | , condition_ (condition ) 11479 | , consequent_(consequent) 11480 | { 11481 | range_.n0_c = std::make_pair<bool,std::size_t>(true,0); 11482 | range_.n1_c = std::make_pair<bool,std::size_t>(true,0); 11483 | 11484 | range_.cache.first = range_.n0_c.second; 11485 | range_.cache.second = range_.n1_c.second; 11486 | 11487 | if (is_generally_string_node(branch(0))) 11488 | { 11489 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0)); 11490 | 11491 | if (0 == str0_base_ptr_) 11492 | return; 11493 | 11494 | str0_range_ptr_ = dynamic_cast<irange_ptr>(branch(0)); 11495 | 11496 | if (0 == str0_range_ptr_) 11497 | return; 11498 | } 11499 | 11500 | initialised_ = str0_base_ptr_ && str0_range_ptr_ ; 11501 | assert(valid()); 11502 | } 11503 | 11504 | inline T value() const exprtk_override 11505 | { 11506 | if (is_true(condition_)) 11507 | { 11508 | consequent_->value(); 11509 | 11510 | const range_t& range = str0_range_ptr_->range_ref(); 11511 | 11512 | std::size_t r0 = 0; 11513 | std::size_t r1 = 0; 11514 | 11515 | if (range(r0, r1, str0_base_ptr_->size())) 11516 | { 11517 | const std::size_t size = (r1 - r0); 11518 | 11519 | value_.assign(str0_base_ptr_->base() + r0, size); 11520 | 11521 | range_.n1_c.second = value_.size(); 11522 | range_.cache.second = range_.n1_c.second; 11523 | 11524 | return T(1); 11525 | } 11526 | } 11527 | 11528 | return std::numeric_limits<T>::quiet_NaN(); 11529 | } 11530 | 11531 | std::string str() const 11532 | { 11533 | return value_; 11534 | } 11535 | 11536 | char_cptr base() const 11537 | { 11538 | return &value_[0]; 11539 | } 11540 | 11541 | std::size_t size() const 11542 | { 11543 | return value_.size(); 11544 | } 11545 | 11546 | range_t& range_ref() 11547 | { 11548 | return range_; 11549 | } 11550 | 11551 | const range_t& range_ref() const 11552 | { 11553 | return range_; 11554 | } 11555 | 11556 | inline typename expression_node<T>::node_type type() const exprtk_override 11557 | { 11558 | return expression_node<T>::e_strccondition; 11559 | } 11560 | 11561 | inline bool valid() const exprtk_override 11562 | { 11563 | return 11564 | initialised_ && 11565 | condition_ && condition_ ->valid() && 11566 | consequent_ && consequent_ ->valid() ; 11567 | } 11568 | 11569 | private: 11570 | 11571 | bool initialised_; 11572 | str_base_ptr str0_base_ptr_; 11573 | irange_ptr str0_range_ptr_; 11574 | mutable range_t range_; 11575 | mutable std::string value_; 11576 | 11577 | expression_ptr condition_; 11578 | expression_ptr consequent_; 11579 | }; 11580 | 11581 | template <typename T, typename VarArgFunction> 11582 | class str_vararg_node exprtk_final 11583 | : public expression_node <T> 11584 | , public string_base_node<T> 11585 | , public range_interface <T> 11586 | { 11587 | public: 11588 | 11589 | typedef typename range_interface<T>::range_t range_t; 11590 | typedef range_t* range_ptr; 11591 | typedef range_interface <T> irange_t; 11592 | typedef irange_t* irange_ptr; 11593 | typedef expression_node <T>* expression_ptr; 11594 | typedef string_base_node<T>* str_base_ptr; 11595 | typedef std::pair<expression_ptr,bool> branch_t; 11596 | 11597 | template <typename Allocator, 11598 | template <typename, typename> class Sequence> 11599 | explicit str_vararg_node(const Sequence<expression_ptr,Allocator>& arg_list) 11600 | : initialised_(false) 11601 | , str_base_ptr_ (0) 11602 | , str_range_ptr_(0) 11603 | { 11604 | construct_branch_pair(final_node_, const_cast<expression_ptr>(arg_list.back())); 11605 | 11606 | if (0 == final_node_.first) 11607 | return; 11608 | else if (!is_generally_string_node(final_node_.first)) 11609 | return; 11610 | 11611 | str_base_ptr_ = dynamic_cast<str_base_ptr>(final_node_.first); 11612 | 11613 | if (0 == str_base_ptr_) 11614 | return; 11615 | 11616 | str_range_ptr_ = dynamic_cast<irange_ptr>(final_node_.first); 11617 | 11618 | if (0 == str_range_ptr_) 11619 | return; 11620 | 11621 | if (arg_list.size() > 1) 11622 | { 11623 | const std::size_t arg_list_size = arg_list.size() - 1; 11624 | 11625 | arg_list_.resize(arg_list_size); 11626 | 11627 | for (std::size_t i = 0; i < arg_list_size; ++i) 11628 | { 11629 | if (arg_list[i] && arg_list[i]->valid()) 11630 | { 11631 | construct_branch_pair(arg_list_[i], arg_list[i]); 11632 | } 11633 | else 11634 | { 11635 | arg_list_.clear(); 11636 | return; 11637 | } 11638 | } 11639 | 11640 | initialised_ = true; 11641 | } 11642 | 11643 | initialised_ &= str_base_ptr_ && str_range_ptr_; 11644 | assert(valid()); 11645 | } 11646 | 11647 | inline T value() const exprtk_override 11648 | { 11649 | if (!arg_list_.empty()) 11650 | { 11651 | VarArgFunction::process(arg_list_); 11652 | } 11653 | 11654 | final_node_.first->value(); 11655 | 11656 | return std::numeric_limits<T>::quiet_NaN(); 11657 | } 11658 | 11659 | std::string str() const exprtk_override 11660 | { 11661 | return str_base_ptr_->str(); 11662 | } 11663 | 11664 | char_cptr base() const exprtk_override 11665 | { 11666 | return str_base_ptr_->base(); 11667 | } 11668 | 11669 | std::size_t size() const exprtk_override 11670 | { 11671 | return str_base_ptr_->size(); 11672 | } 11673 | 11674 | range_t& range_ref() exprtk_override 11675 | { 11676 | return str_range_ptr_->range_ref(); 11677 | } 11678 | 11679 | const range_t& range_ref() const exprtk_override 11680 | { 11681 | return str_range_ptr_->range_ref(); 11682 | } 11683 | 11684 | inline typename expression_node<T>::node_type type() const exprtk_override 11685 | { 11686 | return expression_node<T>::e_stringvararg; 11687 | } 11688 | 11689 | inline bool valid() const exprtk_override 11690 | { 11691 | return 11692 | initialised_ && 11693 | final_node_.first && final_node_.first->valid(); 11694 | } 11695 | 11696 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 11697 | { 11698 | expression_node<T>::ndb_t::collect(final_node_ , node_delete_list); 11699 | expression_node<T>::ndb_t::collect(arg_list_ , node_delete_list); 11700 | } 11701 | 11702 | std::size_t node_depth() const exprtk_override 11703 | { 11704 | return std::max( 11705 | expression_node<T>::ndb_t::compute_node_depth(final_node_), 11706 | expression_node<T>::ndb_t::compute_node_depth(arg_list_ )); 11707 | } 11708 | 11709 | private: 11710 | 11711 | bool initialised_; 11712 | branch_t final_node_; 11713 | str_base_ptr str_base_ptr_; 11714 | irange_ptr str_range_ptr_; 11715 | std::vector<branch_t> arg_list_; 11716 | }; 11717 | #endif 11718 | 11719 | template <typename T> 11720 | class assert_node exprtk_final : public expression_node<T> 11721 | { 11722 | public: 11723 | 11724 | typedef expression_node<T>* expression_ptr; 11725 | typedef std::pair<expression_ptr,bool> branch_t; 11726 | typedef string_base_node<T>* str_base_ptr; 11727 | typedef assert_check::assert_context assert_context_t; 11728 | 11729 | assert_node(expression_ptr assert_condition_node, 11730 | expression_ptr assert_message_node, 11731 | assert_check_ptr assert_check, 11732 | assert_context_t context) 11733 | : assert_message_str_base_(0) 11734 | , assert_check_(assert_check) 11735 | , context_(context) 11736 | { 11737 | construct_branch_pair(assert_condition_node_, assert_condition_node); 11738 | construct_branch_pair(assert_message_node_ , assert_message_node ); 11739 | 11740 | #ifndef exprtk_disable_string_capabilities 11741 | if ( 11742 | assert_message_node_.first && 11743 | details::is_generally_string_node(assert_message_node_.first) 11744 | ) 11745 | { 11746 | assert_message_str_base_ = dynamic_cast<str_base_ptr>(assert_message_node_.first); 11747 | } 11748 | #endif 11749 | 11750 | assert(valid()); 11751 | } 11752 | 11753 | inline T value() const exprtk_override 11754 | { 11755 | if (details::is_true(assert_condition_node_.first->value())) 11756 | { 11757 | return T(1); 11758 | } 11759 | 11760 | #ifndef exprtk_disable_string_capabilities 11761 | if (assert_message_node_.first) 11762 | { 11763 | assert_message_node_.first->value(); 11764 | assert(assert_message_str_base_); 11765 | context_.message = assert_message_str_base_->str(); 11766 | } 11767 | #endif 11768 | 11769 | assert_check_->handle_assert(context_); 11770 | return T(0); 11771 | } 11772 | 11773 | inline typename expression_node<T>::node_type type() const exprtk_override 11774 | { 11775 | return expression_node<T>::e_assert; 11776 | } 11777 | 11778 | inline bool valid() const exprtk_override 11779 | { 11780 | return ( 11781 | assert_check_ && 11782 | assert_condition_node_.first && 11783 | assert_condition_node_.first->valid() 11784 | ) && 11785 | ( 11786 | (0 == assert_message_node_.first) || 11787 | ( 11788 | assert_message_node_.first && 11789 | assert_message_str_base_ && 11790 | assert_message_node_.first->valid() && 11791 | details::is_generally_string_node(assert_message_node_.first) 11792 | ) 11793 | ); 11794 | } 11795 | 11796 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 11797 | { 11798 | expression_node<T>::ndb_t::collect(assert_condition_node_, node_delete_list); 11799 | expression_node<T>::ndb_t::collect(assert_message_node_ , node_delete_list); 11800 | } 11801 | 11802 | std::size_t node_depth() const exprtk_override 11803 | { 11804 | return expression_node<T>::ndb_t::compute_node_depth 11805 | (assert_condition_node_, assert_message_node_); 11806 | } 11807 | 11808 | private: 11809 | 11810 | branch_t assert_condition_node_; 11811 | branch_t assert_message_node_; 11812 | str_base_ptr assert_message_str_base_; 11813 | assert_check_ptr assert_check_; 11814 | mutable assert_context_t context_; 11815 | }; 11816 | 11817 | template <typename T, std::size_t N> 11818 | inline T axn(const T a, const T x) 11819 | { 11820 | // a*x^n 11821 | return a * exprtk::details::numeric::fast_exp<T,N>::result(x); 11822 | } 11823 | 11824 | template <typename T, std::size_t N> 11825 | inline T axnb(const T a, const T x, const T b) 11826 | { 11827 | // a*x^n+b 11828 | return a * exprtk::details::numeric::fast_exp<T,N>::result(x) + b; 11829 | } 11830 | 11831 | template <typename T> 11832 | struct sf_base 11833 | { 11834 | typedef typename details::functor_t<T>::Type Type; 11835 | typedef typename details::functor_t<T> functor_t; 11836 | typedef typename functor_t::qfunc_t quaternary_functor_t; 11837 | typedef typename functor_t::tfunc_t trinary_functor_t; 11838 | typedef typename functor_t::bfunc_t binary_functor_t; 11839 | typedef typename functor_t::ufunc_t unary_functor_t; 11840 | }; 11841 | 11842 | #define define_sfop3(NN, OP0, OP1) \ 11843 | template <typename T> \ 11844 | struct sf##NN##_op : public sf_base<T> \ 11845 | { \ 11846 | typedef typename sf_base<T>::Type const Type; \ 11847 | static inline T process(Type x, Type y, Type z) \ 11848 | { \ 11849 | return (OP0); \ 11850 | } \ 11851 | static inline std::string id() \ 11852 | { \ 11853 | return (OP1); \ 11854 | } \ 11855 | }; \ 11856 | 11857 | define_sfop3(00,(x + y) / z ,"(t+t)/t") 11858 | define_sfop3(01,(x + y) * z ,"(t+t)*t") 11859 | define_sfop3(02,(x + y) - z ,"(t+t)-t") 11860 | define_sfop3(03,(x + y) + z ,"(t+t)+t") 11861 | define_sfop3(04,(x - y) + z ,"(t-t)+t") 11862 | define_sfop3(05,(x - y) / z ,"(t-t)/t") 11863 | define_sfop3(06,(x - y) * z ,"(t-t)*t") 11864 | define_sfop3(07,(x * y) + z ,"(t*t)+t") 11865 | define_sfop3(08,(x * y) - z ,"(t*t)-t") 11866 | define_sfop3(09,(x * y) / z ,"(t*t)/t") 11867 | define_sfop3(10,(x * y) * z ,"(t*t)*t") 11868 | define_sfop3(11,(x / y) + z ,"(t/t)+t") 11869 | define_sfop3(12,(x / y) - z ,"(t/t)-t") 11870 | define_sfop3(13,(x / y) / z ,"(t/t)/t") 11871 | define_sfop3(14,(x / y) * z ,"(t/t)*t") 11872 | define_sfop3(15,x / (y + z) ,"t/(t+t)") 11873 | define_sfop3(16,x / (y - z) ,"t/(t-t)") 11874 | define_sfop3(17,x / (y * z) ,"t/(t*t)") 11875 | define_sfop3(18,x / (y / z) ,"t/(t/t)") 11876 | define_sfop3(19,x * (y + z) ,"t*(t+t)") 11877 | define_sfop3(20,x * (y - z) ,"t*(t-t)") 11878 | define_sfop3(21,x * (y * z) ,"t*(t*t)") 11879 | define_sfop3(22,x * (y / z) ,"t*(t/t)") 11880 | define_sfop3(23,x - (y + z) ,"t-(t+t)") 11881 | define_sfop3(24,x - (y - z) ,"t-(t-t)") 11882 | define_sfop3(25,x - (y / z) ,"t-(t/t)") 11883 | define_sfop3(26,x - (y * z) ,"t-(t*t)") 11884 | define_sfop3(27,x + (y * z) ,"t+(t*t)") 11885 | define_sfop3(28,x + (y / z) ,"t+(t/t)") 11886 | define_sfop3(29,x + (y + z) ,"t+(t+t)") 11887 | define_sfop3(30,x + (y - z) ,"t+(t-t)") 11888 | define_sfop3(31,(axnb<T,2>(x,y,z))," ") 11889 | define_sfop3(32,(axnb<T,3>(x,y,z))," ") 11890 | define_sfop3(33,(axnb<T,4>(x,y,z))," ") 11891 | define_sfop3(34,(axnb<T,5>(x,y,z))," ") 11892 | define_sfop3(35,(axnb<T,6>(x,y,z))," ") 11893 | define_sfop3(36,(axnb<T,7>(x,y,z))," ") 11894 | define_sfop3(37,(axnb<T,8>(x,y,z))," ") 11895 | define_sfop3(38,(axnb<T,9>(x,y,z))," ") 11896 | define_sfop3(39,x * numeric::log(y) + z,"") 11897 | define_sfop3(40,x * numeric::log(y) - z,"") 11898 | define_sfop3(41,x * numeric::log10(y) + z,"") 11899 | define_sfop3(42,x * numeric::log10(y) - z,"") 11900 | define_sfop3(43,x * numeric::sin(y) + z ,"") 11901 | define_sfop3(44,x * numeric::sin(y) - z ,"") 11902 | define_sfop3(45,x * numeric::cos(y) + z ,"") 11903 | define_sfop3(46,x * numeric::cos(y) - z ,"") 11904 | define_sfop3(47,details::is_true(x) ? y : z,"") 11905 | 11906 | #define define_sfop4(NN, OP0, OP1) \ 11907 | template <typename T> \ 11908 | struct sf##NN##_op : public sf_base<T> \ 11909 | { \ 11910 | typedef typename sf_base<T>::Type const Type; \ 11911 | static inline T process(Type x, Type y, Type z, Type w) \ 11912 | { \ 11913 | return (OP0); \ 11914 | } \ 11915 | static inline std::string id() \ 11916 | { \ 11917 | return (OP1); \ 11918 | } \ 11919 | }; \ 11920 | 11921 | define_sfop4(48,(x + ((y + z) / w)),"t+((t+t)/t)") 11922 | define_sfop4(49,(x + ((y + z) * w)),"t+((t+t)*t)") 11923 | define_sfop4(50,(x + ((y - z) / w)),"t+((t-t)/t)") 11924 | define_sfop4(51,(x + ((y - z) * w)),"t+((t-t)*t)") 11925 | define_sfop4(52,(x + ((y * z) / w)),"t+((t*t)/t)") 11926 | define_sfop4(53,(x + ((y * z) * w)),"t+((t*t)*t)") 11927 | define_sfop4(54,(x + ((y / z) + w)),"t+((t/t)+t)") 11928 | define_sfop4(55,(x + ((y / z) / w)),"t+((t/t)/t)") 11929 | define_sfop4(56,(x + ((y / z) * w)),"t+((t/t)*t)") 11930 | define_sfop4(57,(x - ((y + z) / w)),"t-((t+t)/t)") 11931 | define_sfop4(58,(x - ((y + z) * w)),"t-((t+t)*t)") 11932 | define_sfop4(59,(x - ((y - z) / w)),"t-((t-t)/t)") 11933 | define_sfop4(60,(x - ((y - z) * w)),"t-((t-t)*t)") 11934 | define_sfop4(61,(x - ((y * z) / w)),"t-((t*t)/t)") 11935 | define_sfop4(62,(x - ((y * z) * w)),"t-((t*t)*t)") 11936 | define_sfop4(63,(x - ((y / z) / w)),"t-((t/t)/t)") 11937 | define_sfop4(64,(x - ((y / z) * w)),"t-((t/t)*t)") 11938 | define_sfop4(65,(((x + y) * z) - w),"((t+t)*t)-t") 11939 | define_sfop4(66,(((x - y) * z) - w),"((t-t)*t)-t") 11940 | define_sfop4(67,(((x * y) * z) - w),"((t*t)*t)-t") 11941 | define_sfop4(68,(((x / y) * z) - w),"((t/t)*t)-t") 11942 | define_sfop4(69,(((x + y) / z) - w),"((t+t)/t)-t") 11943 | define_sfop4(70,(((x - y) / z) - w),"((t-t)/t)-t") 11944 | define_sfop4(71,(((x * y) / z) - w),"((t*t)/t)-t") 11945 | define_sfop4(72,(((x / y) / z) - w),"((t/t)/t)-t") 11946 | define_sfop4(73,((x * y) + (z * w)),"(t*t)+(t*t)") 11947 | define_sfop4(74,((x * y) - (z * w)),"(t*t)-(t*t)") 11948 | define_sfop4(75,((x * y) + (z / w)),"(t*t)+(t/t)") 11949 | define_sfop4(76,((x * y) - (z / w)),"(t*t)-(t/t)") 11950 | define_sfop4(77,((x / y) + (z / w)),"(t/t)+(t/t)") 11951 | define_sfop4(78,((x / y) - (z / w)),"(t/t)-(t/t)") 11952 | define_sfop4(79,((x / y) - (z * w)),"(t/t)-(t*t)") 11953 | define_sfop4(80,(x / (y + (z * w))),"t/(t+(t*t))") 11954 | define_sfop4(81,(x / (y - (z * w))),"t/(t-(t*t))") 11955 | define_sfop4(82,(x * (y + (z * w))),"t*(t+(t*t))") 11956 | define_sfop4(83,(x * (y - (z * w))),"t*(t-(t*t))") 11957 | 11958 | define_sfop4(84,(axn<T,2>(x,y) + axn<T,2>(z,w)),"") 11959 | define_sfop4(85,(axn<T,3>(x,y) + axn<T,3>(z,w)),"") 11960 | define_sfop4(86,(axn<T,4>(x,y) + axn<T,4>(z,w)),"") 11961 | define_sfop4(87,(axn<T,5>(x,y) + axn<T,5>(z,w)),"") 11962 | define_sfop4(88,(axn<T,6>(x,y) + axn<T,6>(z,w)),"") 11963 | define_sfop4(89,(axn<T,7>(x,y) + axn<T,7>(z,w)),"") 11964 | define_sfop4(90,(axn<T,8>(x,y) + axn<T,8>(z,w)),"") 11965 | define_sfop4(91,(axn<T,9>(x,y) + axn<T,9>(z,w)),"") 11966 | define_sfop4(92,((details::is_true(x) && details::is_true(y)) ? z : w),"") 11967 | define_sfop4(93,((details::is_true(x) || details::is_true(y)) ? z : w),"") 11968 | define_sfop4(94,((x < y) ? z : w),"") 11969 | define_sfop4(95,((x <= y) ? z : w),"") 11970 | define_sfop4(96,((x > y) ? z : w),"") 11971 | define_sfop4(97,((x >= y) ? z : w),"") 11972 | define_sfop4(98,(details::is_true(numeric::equal(x,y)) ? z : w),"") 11973 | define_sfop4(99,(x * numeric::sin(y) + z * numeric::cos(w)),"") 11974 | 11975 | define_sfop4(ext00,((x + y) - (z * w)),"(t+t)-(t*t)") 11976 | define_sfop4(ext01,((x + y) - (z / w)),"(t+t)-(t/t)") 11977 | define_sfop4(ext02,((x + y) + (z * w)),"(t+t)+(t*t)") 11978 | define_sfop4(ext03,((x + y) + (z / w)),"(t+t)+(t/t)") 11979 | define_sfop4(ext04,((x - y) + (z * w)),"(t-t)+(t*t)") 11980 | define_sfop4(ext05,((x - y) + (z / w)),"(t-t)+(t/t)") 11981 | define_sfop4(ext06,((x - y) - (z * w)),"(t-t)-(t*t)") 11982 | define_sfop4(ext07,((x - y) - (z / w)),"(t-t)-(t/t)") 11983 | define_sfop4(ext08,((x + y) - (z - w)),"(t+t)-(t-t)") 11984 | define_sfop4(ext09,((x + y) + (z - w)),"(t+t)+(t-t)") 11985 | define_sfop4(ext10,((x + y) + (z + w)),"(t+t)+(t+t)") 11986 | define_sfop4(ext11,((x + y) * (z - w)),"(t+t)*(t-t)") 11987 | define_sfop4(ext12,((x + y) / (z - w)),"(t+t)/(t-t)") 11988 | define_sfop4(ext13,((x - y) - (z + w)),"(t-t)-(t+t)") 11989 | define_sfop4(ext14,((x - y) + (z + w)),"(t-t)+(t+t)") 11990 | define_sfop4(ext15,((x - y) * (z + w)),"(t-t)*(t+t)") 11991 | define_sfop4(ext16,((x - y) / (z + w)),"(t-t)/(t+t)") 11992 | define_sfop4(ext17,((x * y) - (z + w)),"(t*t)-(t+t)") 11993 | define_sfop4(ext18,((x / y) - (z + w)),"(t/t)-(t+t)") 11994 | define_sfop4(ext19,((x * y) + (z + w)),"(t*t)+(t+t)") 11995 | define_sfop4(ext20,((x / y) + (z + w)),"(t/t)+(t+t)") 11996 | define_sfop4(ext21,((x * y) + (z - w)),"(t*t)+(t-t)") 11997 | define_sfop4(ext22,((x / y) + (z - w)),"(t/t)+(t-t)") 11998 | define_sfop4(ext23,((x * y) - (z - w)),"(t*t)-(t-t)") 11999 | define_sfop4(ext24,((x / y) - (z - w)),"(t/t)-(t-t)") 12000 | define_sfop4(ext25,((x + y) * (z * w)),"(t+t)*(t*t)") 12001 | define_sfop4(ext26,((x + y) * (z / w)),"(t+t)*(t/t)") 12002 | define_sfop4(ext27,((x + y) / (z * w)),"(t+t)/(t*t)") 12003 | define_sfop4(ext28,((x + y) / (z / w)),"(t+t)/(t/t)") 12004 | define_sfop4(ext29,((x - y) / (z * w)),"(t-t)/(t*t)") 12005 | define_sfop4(ext30,((x - y) / (z / w)),"(t-t)/(t/t)") 12006 | define_sfop4(ext31,((x - y) * (z * w)),"(t-t)*(t*t)") 12007 | define_sfop4(ext32,((x - y) * (z / w)),"(t-t)*(t/t)") 12008 | define_sfop4(ext33,((x * y) * (z + w)),"(t*t)*(t+t)") 12009 | define_sfop4(ext34,((x / y) * (z + w)),"(t/t)*(t+t)") 12010 | define_sfop4(ext35,((x * y) / (z + w)),"(t*t)/(t+t)") 12011 | define_sfop4(ext36,((x / y) / (z + w)),"(t/t)/(t+t)") 12012 | define_sfop4(ext37,((x * y) / (z - w)),"(t*t)/(t-t)") 12013 | define_sfop4(ext38,((x / y) / (z - w)),"(t/t)/(t-t)") 12014 | define_sfop4(ext39,((x * y) * (z - w)),"(t*t)*(t-t)") 12015 | define_sfop4(ext40,((x * y) / (z * w)),"(t*t)/(t*t)") 12016 | define_sfop4(ext41,((x / y) * (z / w)),"(t/t)*(t/t)") 12017 | define_sfop4(ext42,((x / y) * (z - w)),"(t/t)*(t-t)") 12018 | define_sfop4(ext43,((x * y) * (z * w)),"(t*t)*(t*t)") 12019 | define_sfop4(ext44,(x + (y * (z / w))),"t+(t*(t/t))") 12020 | define_sfop4(ext45,(x - (y * (z / w))),"t-(t*(t/t))") 12021 | define_sfop4(ext46,(x + (y / (z * w))),"t+(t/(t*t))") 12022 | define_sfop4(ext47,(x - (y / (z * w))),"t-(t/(t*t))") 12023 | define_sfop4(ext48,(((x - y) - z) * w),"((t-t)-t)*t") 12024 | define_sfop4(ext49,(((x - y) - z) / w),"((t-t)-t)/t") 12025 | define_sfop4(ext50,(((x - y) + z) * w),"((t-t)+t)*t") 12026 | define_sfop4(ext51,(((x - y) + z) / w),"((t-t)+t)/t") 12027 | define_sfop4(ext52,((x + (y - z)) * w),"(t+(t-t))*t") 12028 | define_sfop4(ext53,((x + (y - z)) / w),"(t+(t-t))/t") 12029 | define_sfop4(ext54,((x + y) / (z + w)),"(t+t)/(t+t)") 12030 | define_sfop4(ext55,((x - y) / (z - w)),"(t-t)/(t-t)") 12031 | define_sfop4(ext56,((x + y) * (z + w)),"(t+t)*(t+t)") 12032 | define_sfop4(ext57,((x - y) * (z - w)),"(t-t)*(t-t)") 12033 | define_sfop4(ext58,((x - y) + (z - w)),"(t-t)+(t-t)") 12034 | define_sfop4(ext59,((x - y) - (z - w)),"(t-t)-(t-t)") 12035 | define_sfop4(ext60,((x / y) + (z * w)),"(t/t)+(t*t)") 12036 | define_sfop4(ext61,(((x * y) * z) / w),"((t*t)*t)/t") 12037 | 12038 | #undef define_sfop3 12039 | #undef define_sfop4 12040 | 12041 | template <typename T, typename SpecialFunction> 12042 | class sf3_node exprtk_final : public trinary_node<T> 12043 | { 12044 | public: 12045 | 12046 | typedef expression_node<T>* expression_ptr; 12047 | 12048 | sf3_node(const operator_type& opr, 12049 | expression_ptr branch0, 12050 | expression_ptr branch1, 12051 | expression_ptr branch2) 12052 | : trinary_node<T>(opr, branch0, branch1, branch2) 12053 | {} 12054 | 12055 | inline T value() const exprtk_override 12056 | { 12057 | const T x = trinary_node<T>::branch_[0].first->value(); 12058 | const T y = trinary_node<T>::branch_[1].first->value(); 12059 | const T z = trinary_node<T>::branch_[2].first->value(); 12060 | 12061 | return SpecialFunction::process(x, y, z); 12062 | } 12063 | }; 12064 | 12065 | template <typename T, typename SpecialFunction> 12066 | class sf4_node exprtk_final : public quaternary_node<T> 12067 | { 12068 | public: 12069 | 12070 | typedef expression_node<T>* expression_ptr; 12071 | 12072 | sf4_node(const operator_type& opr, 12073 | expression_ptr branch0, 12074 | expression_ptr branch1, 12075 | expression_ptr branch2, 12076 | expression_ptr branch3) 12077 | : quaternary_node<T>(opr, branch0, branch1, branch2, branch3) 12078 | {} 12079 | 12080 | inline T value() const exprtk_override 12081 | { 12082 | const T x = quaternary_node<T>::branch_[0].first->value(); 12083 | const T y = quaternary_node<T>::branch_[1].first->value(); 12084 | const T z = quaternary_node<T>::branch_[2].first->value(); 12085 | const T w = quaternary_node<T>::branch_[3].first->value(); 12086 | 12087 | return SpecialFunction::process(x, y, z, w); 12088 | } 12089 | }; 12090 | 12091 | template <typename T, typename SpecialFunction> 12092 | class sf3_var_node exprtk_final : public expression_node<T> 12093 | { 12094 | public: 12095 | 12096 | typedef expression_node<T>* expression_ptr; 12097 | 12098 | sf3_var_node(const T& v0, const T& v1, const T& v2) 12099 | : v0_(v0) 12100 | , v1_(v1) 12101 | , v2_(v2) 12102 | {} 12103 | 12104 | inline T value() const exprtk_override 12105 | { 12106 | return SpecialFunction::process(v0_, v1_, v2_); 12107 | } 12108 | 12109 | inline typename expression_node<T>::node_type type() const exprtk_override 12110 | { 12111 | return expression_node<T>::e_trinary; 12112 | } 12113 | 12114 | private: 12115 | 12116 | sf3_var_node(const sf3_var_node<T,SpecialFunction>&) exprtk_delete; 12117 | sf3_var_node<T,SpecialFunction>& operator=(const sf3_var_node<T,SpecialFunction>&) exprtk_delete; 12118 | 12119 | const T& v0_; 12120 | const T& v1_; 12121 | const T& v2_; 12122 | }; 12123 | 12124 | template <typename T, typename SpecialFunction> 12125 | class sf4_var_node exprtk_final : public expression_node<T> 12126 | { 12127 | public: 12128 | 12129 | typedef expression_node<T>* expression_ptr; 12130 | 12131 | sf4_var_node(const T& v0, const T& v1, const T& v2, const T& v3) 12132 | : v0_(v0) 12133 | , v1_(v1) 12134 | , v2_(v2) 12135 | , v3_(v3) 12136 | {} 12137 | 12138 | inline T value() const exprtk_override 12139 | { 12140 | return SpecialFunction::process(v0_, v1_, v2_, v3_); 12141 | } 12142 | 12143 | inline typename expression_node<T>::node_type type() const exprtk_override 12144 | { 12145 | return expression_node<T>::e_trinary; 12146 | } 12147 | 12148 | private: 12149 | 12150 | sf4_var_node(const sf4_var_node<T,SpecialFunction>&) exprtk_delete; 12151 | sf4_var_node<T,SpecialFunction>& operator=(const sf4_var_node<T,SpecialFunction>&) exprtk_delete; 12152 | 12153 | const T& v0_; 12154 | const T& v1_; 12155 | const T& v2_; 12156 | const T& v3_; 12157 | }; 12158 | 12159 | template <typename T, typename VarArgFunction> 12160 | class vararg_node exprtk_final : public expression_node<T> 12161 | { 12162 | public: 12163 | 12164 | typedef expression_node<T>* expression_ptr; 12165 | typedef std::pair<expression_ptr,bool> branch_t; 12166 | 12167 | template <typename Allocator, 12168 | template <typename, typename> class Sequence> 12169 | explicit vararg_node(const Sequence<expression_ptr,Allocator>& arg_list) 12170 | : initialised_(false) 12171 | { 12172 | arg_list_.resize(arg_list.size()); 12173 | 12174 | for (std::size_t i = 0; i < arg_list.size(); ++i) 12175 | { 12176 | if (arg_list[i] && arg_list[i]->valid()) 12177 | { 12178 | construct_branch_pair(arg_list_[i],arg_list[i]); 12179 | } 12180 | else 12181 | { 12182 | arg_list_.clear(); 12183 | return; 12184 | } 12185 | } 12186 | 12187 | initialised_ = (arg_list_.size() == arg_list.size()); 12188 | assert(valid()); 12189 | } 12190 | 12191 | inline T value() const exprtk_override 12192 | { 12193 | return VarArgFunction::process(arg_list_); 12194 | } 12195 | 12196 | inline typename expression_node<T>::node_type type() const exprtk_override 12197 | { 12198 | return expression_node<T>::e_vararg; 12199 | } 12200 | 12201 | inline bool valid() const exprtk_override 12202 | { 12203 | return initialised_; 12204 | } 12205 | 12206 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 12207 | { 12208 | expression_node<T>::ndb_t::collect(arg_list_, node_delete_list); 12209 | } 12210 | 12211 | std::size_t node_depth() const exprtk_override 12212 | { 12213 | return expression_node<T>::ndb_t::compute_node_depth(arg_list_); 12214 | } 12215 | 12216 | std::size_t size() const 12217 | { 12218 | return arg_list_.size(); 12219 | } 12220 | 12221 | expression_ptr operator[](const std::size_t& index) const 12222 | { 12223 | return arg_list_[index].first; 12224 | } 12225 | 12226 | private: 12227 | 12228 | std::vector<branch_t> arg_list_; 12229 | bool initialised_; 12230 | }; 12231 | 12232 | template <typename T, typename VarArgFunction> 12233 | class vararg_varnode exprtk_final : public expression_node<T> 12234 | { 12235 | public: 12236 | 12237 | typedef expression_node<T>* expression_ptr; 12238 | 12239 | template <typename Allocator, 12240 | template <typename, typename> class Sequence> 12241 | explicit vararg_varnode(const Sequence<expression_ptr,Allocator>& arg_list) 12242 | : initialised_(false) 12243 | { 12244 | arg_list_.resize(arg_list.size()); 12245 | 12246 | for (std::size_t i = 0; i < arg_list.size(); ++i) 12247 | { 12248 | if (arg_list[i] && arg_list[i]->valid() && is_variable_node(arg_list[i])) 12249 | { 12250 | variable_node<T>* var_node_ptr = static_cast<variable_node<T>*>(arg_list[i]); 12251 | arg_list_[i] = (&var_node_ptr->ref()); 12252 | } 12253 | else 12254 | { 12255 | arg_list_.clear(); 12256 | return; 12257 | } 12258 | } 12259 | 12260 | initialised_ = (arg_list.size() == arg_list_.size()); 12261 | assert(valid()); 12262 | } 12263 | 12264 | inline T value() const exprtk_override 12265 | { 12266 | return VarArgFunction::process(arg_list_); 12267 | } 12268 | 12269 | inline typename expression_node<T>::node_type type() const exprtk_override 12270 | { 12271 | return expression_node<T>::e_vararg; 12272 | } 12273 | 12274 | inline bool valid() const exprtk_override 12275 | { 12276 | return initialised_; 12277 | } 12278 | 12279 | private: 12280 | 12281 | std::vector<const T*> arg_list_; 12282 | bool initialised_; 12283 | }; 12284 | 12285 | template <typename T, typename VecFunction> 12286 | class vectorize_node exprtk_final : public expression_node<T> 12287 | { 12288 | public: 12289 | 12290 | typedef expression_node<T>* expression_ptr; 12291 | typedef std::pair<expression_ptr,bool> branch_t; 12292 | 12293 | explicit vectorize_node(const expression_ptr v) 12294 | : ivec_ptr_(0) 12295 | { 12296 | construct_branch_pair(v_, v); 12297 | 12298 | if (is_ivector_node(v_.first)) 12299 | { 12300 | ivec_ptr_ = dynamic_cast<vector_interface<T>*>(v_.first); 12301 | } 12302 | } 12303 | 12304 | inline T value() const exprtk_override 12305 | { 12306 | v_.first->value(); 12307 | return VecFunction::process(ivec_ptr_); 12308 | } 12309 | 12310 | inline typename expression_node<T>::node_type type() const exprtk_override 12311 | { 12312 | return expression_node<T>::e_vecfunc; 12313 | } 12314 | 12315 | inline bool valid() const exprtk_override 12316 | { 12317 | return ivec_ptr_ && v_.first && v_.first->valid(); 12318 | } 12319 | 12320 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 12321 | { 12322 | expression_node<T>::ndb_t::collect(v_, node_delete_list); 12323 | } 12324 | 12325 | std::size_t node_depth() const exprtk_override 12326 | { 12327 | return expression_node<T>::ndb_t::compute_node_depth(v_); 12328 | } 12329 | 12330 | private: 12331 | 12332 | vector_interface<T>* ivec_ptr_; 12333 | branch_t v_; 12334 | }; 12335 | 12336 | template <typename T> 12337 | class assignment_node exprtk_final : public binary_node<T> 12338 | { 12339 | public: 12340 | 12341 | typedef expression_node<T>* expression_ptr; 12342 | using binary_node<T>::branch; 12343 | 12344 | assignment_node(const operator_type& opr, 12345 | expression_ptr branch0, 12346 | expression_ptr branch1) 12347 | : binary_node<T>(opr, branch0, branch1) 12348 | , var_node_ptr_(0) 12349 | { 12350 | if (is_variable_node(branch(0))) 12351 | { 12352 | var_node_ptr_ = static_cast<variable_node<T>*>(branch(0)); 12353 | } 12354 | } 12355 | 12356 | inline T value() const exprtk_override 12357 | { 12358 | T& result = var_node_ptr_->ref(); 12359 | result = branch(1)->value(); 12360 | 12361 | return result; 12362 | } 12363 | 12364 | inline bool valid() const exprtk_override 12365 | { 12366 | return var_node_ptr_ && binary_node<T>::valid(); 12367 | } 12368 | 12369 | private: 12370 | 12371 | variable_node<T>* var_node_ptr_; 12372 | }; 12373 | 12374 | template <typename T> 12375 | class assignment_vec_elem_node exprtk_final : public binary_node<T> 12376 | { 12377 | public: 12378 | 12379 | typedef expression_node<T>* expression_ptr; 12380 | using binary_node<T>::branch; 12381 | 12382 | assignment_vec_elem_node(const operator_type& opr, 12383 | expression_ptr branch0, 12384 | expression_ptr branch1) 12385 | : binary_node<T>(opr, branch0, branch1) 12386 | , vec_node_ptr_(0) 12387 | { 12388 | if (is_vector_elem_node(branch(0))) 12389 | { 12390 | vec_node_ptr_ = static_cast<vector_elem_node<T>*>(branch(0)); 12391 | } 12392 | 12393 | assert(valid()); 12394 | } 12395 | 12396 | inline T value() const exprtk_override 12397 | { 12398 | T& result = vec_node_ptr_->ref(); 12399 | result = branch(1)->value(); 12400 | 12401 | return result; 12402 | } 12403 | 12404 | inline bool valid() const exprtk_override 12405 | { 12406 | return vec_node_ptr_ && binary_node<T>::valid(); 12407 | } 12408 | 12409 | private: 12410 | 12411 | vector_elem_node<T>* vec_node_ptr_; 12412 | }; 12413 | 12414 | template <typename T> 12415 | class assignment_vec_elem_rtc_node exprtk_final : public binary_node<T> 12416 | { 12417 | public: 12418 | 12419 | typedef expression_node<T>* expression_ptr; 12420 | using binary_node<T>::branch; 12421 | 12422 | assignment_vec_elem_rtc_node(const operator_type& opr, 12423 | expression_ptr branch0, 12424 | expression_ptr branch1) 12425 | : binary_node<T>(opr, branch0, branch1) 12426 | , vec_node_ptr_(0) 12427 | { 12428 | if (is_vector_elem_rtc_node(branch(0))) 12429 | { 12430 | vec_node_ptr_ = static_cast<vector_elem_rtc_node<T>*>(branch(0)); 12431 | } 12432 | 12433 | assert(valid()); 12434 | } 12435 | 12436 | inline T value() const exprtk_override 12437 | { 12438 | T& result = vec_node_ptr_->ref(); 12439 | result = branch(1)->value(); 12440 | 12441 | return result; 12442 | } 12443 | 12444 | inline bool valid() const exprtk_override 12445 | { 12446 | return vec_node_ptr_ && binary_node<T>::valid(); 12447 | } 12448 | 12449 | private: 12450 | 12451 | vector_elem_rtc_node<T>* vec_node_ptr_; 12452 | }; 12453 | 12454 | template <typename T> 12455 | class assignment_rebasevec_elem_node exprtk_final : public binary_node<T> 12456 | { 12457 | public: 12458 | 12459 | typedef expression_node<T>* expression_ptr; 12460 | using expression_node<T>::branch; 12461 | 12462 | assignment_rebasevec_elem_node(const operator_type& opr, 12463 | expression_ptr branch0, 12464 | expression_ptr branch1) 12465 | : binary_node<T>(opr, branch0, branch1) 12466 | , rbvec_node_ptr_(0) 12467 | { 12468 | if (is_rebasevector_elem_node(branch(0))) 12469 | { 12470 | rbvec_node_ptr_ = static_cast<rebasevector_elem_node<T>*>(branch(0)); 12471 | } 12472 | 12473 | assert(valid()); 12474 | } 12475 | 12476 | inline T value() const exprtk_override 12477 | { 12478 | T& result = rbvec_node_ptr_->ref(); 12479 | result = branch(1)->value(); 12480 | 12481 | return result; 12482 | } 12483 | 12484 | inline bool valid() const exprtk_override 12485 | { 12486 | return rbvec_node_ptr_ && binary_node<T>::valid(); 12487 | } 12488 | 12489 | private: 12490 | 12491 | rebasevector_elem_node<T>* rbvec_node_ptr_; 12492 | }; 12493 | 12494 | template <typename T> 12495 | class assignment_rebasevec_elem_rtc_node exprtk_final : public binary_node<T> 12496 | { 12497 | public: 12498 | 12499 | typedef expression_node<T>* expression_ptr; 12500 | using expression_node<T>::branch; 12501 | 12502 | assignment_rebasevec_elem_rtc_node(const operator_type& opr, 12503 | expression_ptr branch0, 12504 | expression_ptr branch1) 12505 | : binary_node<T>(opr, branch0, branch1) 12506 | , rbvec_node_ptr_(0) 12507 | { 12508 | if (is_rebasevector_elem_rtc_node(branch(0))) 12509 | { 12510 | rbvec_node_ptr_ = static_cast<rebasevector_elem_rtc_node<T>*>(branch(0)); 12511 | } 12512 | 12513 | assert(valid()); 12514 | } 12515 | 12516 | inline T value() const exprtk_override 12517 | { 12518 | T& result = rbvec_node_ptr_->ref(); 12519 | result = branch(1)->value(); 12520 | 12521 | return result; 12522 | } 12523 | 12524 | inline bool valid() const exprtk_override 12525 | { 12526 | return rbvec_node_ptr_ && binary_node<T>::valid(); 12527 | } 12528 | 12529 | private: 12530 | 12531 | rebasevector_elem_rtc_node<T>* rbvec_node_ptr_; 12532 | }; 12533 | 12534 | template <typename T> 12535 | class assignment_rebasevec_celem_node exprtk_final : public binary_node<T> 12536 | { 12537 | public: 12538 | 12539 | typedef expression_node<T>* expression_ptr; 12540 | using binary_node<T>::branch; 12541 | 12542 | assignment_rebasevec_celem_node(const operator_type& opr, 12543 | expression_ptr branch0, 12544 | expression_ptr branch1) 12545 | : binary_node<T>(opr, branch0, branch1) 12546 | , rbvec_node_ptr_(0) 12547 | { 12548 | if (is_rebasevector_celem_node(branch(0))) 12549 | { 12550 | rbvec_node_ptr_ = static_cast<rebasevector_celem_node<T>*>(branch(0)); 12551 | } 12552 | 12553 | assert(valid()); 12554 | } 12555 | 12556 | inline T value() const exprtk_override 12557 | { 12558 | T& result = rbvec_node_ptr_->ref(); 12559 | result = branch(1)->value(); 12560 | 12561 | return result; 12562 | } 12563 | 12564 | inline bool valid() const exprtk_override 12565 | { 12566 | return rbvec_node_ptr_ && binary_node<T>::valid(); 12567 | } 12568 | 12569 | private: 12570 | 12571 | rebasevector_celem_node<T>* rbvec_node_ptr_; 12572 | }; 12573 | 12574 | template <typename T> 12575 | class assignment_vec_node exprtk_final 12576 | : public binary_node <T> 12577 | , public vector_interface<T> 12578 | { 12579 | public: 12580 | 12581 | typedef expression_node<T>* expression_ptr; 12582 | typedef vector_node<T>* vector_node_ptr; 12583 | typedef vec_data_store<T> vds_t; 12584 | 12585 | using binary_node<T>::branch; 12586 | 12587 | assignment_vec_node(const operator_type& opr, 12588 | expression_ptr branch0, 12589 | expression_ptr branch1) 12590 | : binary_node<T>(opr, branch0, branch1) 12591 | , vec_node_ptr_(0) 12592 | { 12593 | if (is_vector_node(branch(0))) 12594 | { 12595 | vec_node_ptr_ = static_cast<vector_node<T>*>(branch(0)); 12596 | vds() = vec_node_ptr_->vds(); 12597 | } 12598 | 12599 | assert(valid()); 12600 | } 12601 | 12602 | inline T value() const exprtk_override 12603 | { 12604 | const T v = branch(1)->value(); 12605 | 12606 | T* vec = vds().data(); 12607 | 12608 | loop_unroll::details lud(size()); 12609 | const T* upper_bound = vec + lud.upper_bound; 12610 | 12611 | while (vec < upper_bound) 12612 | { 12613 | #define exprtk_loop(N) \ 12614 | vec[N] = v; \ 12615 | 12616 | exprtk_loop( 0) exprtk_loop( 1) 12617 | exprtk_loop( 2) exprtk_loop( 3) 12618 | #ifndef exprtk_disable_superscalar_unroll 12619 | exprtk_loop( 4) exprtk_loop( 5) 12620 | exprtk_loop( 6) exprtk_loop( 7) 12621 | exprtk_loop( 8) exprtk_loop( 9) 12622 | exprtk_loop(10) exprtk_loop(11) 12623 | exprtk_loop(12) exprtk_loop(13) 12624 | exprtk_loop(14) exprtk_loop(15) 12625 | #endif 12626 | 12627 | vec += lud.batch_size; 12628 | } 12629 | 12630 | switch (lud.remainder) 12631 | { 12632 | #define case_stmt(N) \ 12633 | case N : *vec++ = v; \ 12634 | exprtk_fallthrough \ 12635 | 12636 | #ifndef exprtk_disable_superscalar_unroll 12637 | case_stmt(15) case_stmt(14) 12638 | case_stmt(13) case_stmt(12) 12639 | case_stmt(11) case_stmt(10) 12640 | case_stmt( 9) case_stmt( 8) 12641 | case_stmt( 7) case_stmt( 6) 12642 | case_stmt( 5) case_stmt( 4) 12643 | #endif 12644 | case_stmt( 3) case_stmt( 2) 12645 | case 1 : *vec++ = v; 12646 | } 12647 | 12648 | #undef exprtk_loop 12649 | #undef case_stmt 12650 | 12651 | return vec_node_ptr_->value(); 12652 | } 12653 | 12654 | vector_node_ptr vec() const exprtk_override 12655 | { 12656 | return vec_node_ptr_; 12657 | } 12658 | 12659 | vector_node_ptr vec() exprtk_override 12660 | { 12661 | return vec_node_ptr_; 12662 | } 12663 | 12664 | inline typename expression_node<T>::node_type type() const exprtk_override 12665 | { 12666 | return expression_node<T>::e_vecvalass; 12667 | } 12668 | 12669 | inline bool valid() const exprtk_override 12670 | { 12671 | return 12672 | vec_node_ptr_ && 12673 | (vds().size() <= vec_node_ptr_->vec_holder().base_size()) && 12674 | binary_node<T>::valid(); 12675 | } 12676 | 12677 | std::size_t size() const exprtk_override 12678 | { 12679 | return vec_node_ptr_->vec_holder().size(); 12680 | } 12681 | 12682 | std::size_t base_size() const exprtk_override 12683 | { 12684 | return vec_node_ptr_->vec_holder().base_size(); 12685 | } 12686 | 12687 | vds_t& vds() exprtk_override 12688 | { 12689 | return vds_; 12690 | } 12691 | 12692 | const vds_t& vds() const exprtk_override 12693 | { 12694 | return vds_; 12695 | } 12696 | 12697 | private: 12698 | 12699 | vector_node<T>* vec_node_ptr_; 12700 | vds_t vds_; 12701 | }; 12702 | 12703 | template <typename T> 12704 | class assignment_vecvec_node exprtk_final 12705 | : public binary_node <T> 12706 | , public vector_interface<T> 12707 | { 12708 | public: 12709 | 12710 | typedef expression_node<T>* expression_ptr; 12711 | typedef vector_node<T>* vector_node_ptr; 12712 | typedef vec_data_store<T> vds_t; 12713 | 12714 | using binary_node<T>::branch; 12715 | 12716 | assignment_vecvec_node(const operator_type& opr, 12717 | expression_ptr branch0, 12718 | expression_ptr branch1) 12719 | : binary_node<T>(opr, branch0, branch1) 12720 | , vec0_node_ptr_(0) 12721 | , vec1_node_ptr_(0) 12722 | , initialised_(false) 12723 | , src_is_ivec_(false) 12724 | { 12725 | if (is_vector_node(branch(0))) 12726 | { 12727 | vec0_node_ptr_ = static_cast<vector_node<T>*>(branch(0)); 12728 | vds() = vec0_node_ptr_->vds(); 12729 | } 12730 | 12731 | if (is_vector_node(branch(1))) 12732 | { 12733 | vec1_node_ptr_ = static_cast<vector_node<T>*>(branch(1)); 12734 | vds_t::match_sizes(vds(),vec1_node_ptr_->vds()); 12735 | } 12736 | else if (is_ivector_node(branch(1))) 12737 | { 12738 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 12739 | 12740 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1)))) 12741 | { 12742 | vec1_node_ptr_ = vi->vec(); 12743 | 12744 | if (!vi->side_effect()) 12745 | { 12746 | vi->vds() = vds(); 12747 | src_is_ivec_ = true; 12748 | } 12749 | else 12750 | vds_t::match_sizes(vds(),vi->vds()); 12751 | } 12752 | } 12753 | 12754 | initialised_ = 12755 | vec0_node_ptr_ && 12756 | vec1_node_ptr_ && 12757 | (size() <= base_size()) && 12758 | (vds_.size() <= base_size()) && 12759 | binary_node<T>::valid(); 12760 | 12761 | assert(valid()); 12762 | } 12763 | 12764 | inline T value() const exprtk_override 12765 | { 12766 | branch(1)->value(); 12767 | 12768 | if (src_is_ivec_) 12769 | return vec0_node_ptr_->value(); 12770 | 12771 | T* vec0 = vec0_node_ptr_->vds().data(); 12772 | T* vec1 = vec1_node_ptr_->vds().data(); 12773 | 12774 | loop_unroll::details lud(size()); 12775 | const T* upper_bound = vec0 + lud.upper_bound; 12776 | 12777 | while (vec0 < upper_bound) 12778 | { 12779 | #define exprtk_loop(N) \ 12780 | vec0[N] = vec1[N]; \ 12781 | 12782 | exprtk_loop( 0) exprtk_loop( 1) 12783 | exprtk_loop( 2) exprtk_loop( 3) 12784 | #ifndef exprtk_disable_superscalar_unroll 12785 | exprtk_loop( 4) exprtk_loop( 5) 12786 | exprtk_loop( 6) exprtk_loop( 7) 12787 | exprtk_loop( 8) exprtk_loop( 9) 12788 | exprtk_loop(10) exprtk_loop(11) 12789 | exprtk_loop(12) exprtk_loop(13) 12790 | exprtk_loop(14) exprtk_loop(15) 12791 | #endif 12792 | 12793 | vec0 += lud.batch_size; 12794 | vec1 += lud.batch_size; 12795 | } 12796 | 12797 | switch (lud.remainder) 12798 | { 12799 | #define case_stmt(N,fall_through) \ 12800 | case N : *vec0++ = *vec1++; \ 12801 | fall_through \ 12802 | 12803 | #ifndef exprtk_disable_superscalar_unroll 12804 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 12805 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 12806 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 12807 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 12808 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 12809 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 12810 | #endif 12811 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 12812 | case_stmt( 1, (void)0;) 12813 | } 12814 | 12815 | #undef exprtk_loop 12816 | #undef case_stmt 12817 | 12818 | return vec0_node_ptr_->value(); 12819 | } 12820 | 12821 | vector_node_ptr vec() exprtk_override 12822 | { 12823 | return vec0_node_ptr_; 12824 | } 12825 | 12826 | vector_node_ptr vec() const exprtk_override 12827 | { 12828 | return vec0_node_ptr_; 12829 | } 12830 | 12831 | inline typename expression_node<T>::node_type type() const exprtk_override 12832 | { 12833 | return expression_node<T>::e_vecvecass; 12834 | } 12835 | 12836 | inline bool valid() const exprtk_override 12837 | { 12838 | return initialised_; 12839 | } 12840 | 12841 | std::size_t size() const exprtk_override 12842 | { 12843 | return std::min( 12844 | vec0_node_ptr_->vec_holder().size(), 12845 | vec1_node_ptr_->vec_holder().size()); 12846 | } 12847 | 12848 | std::size_t base_size() const exprtk_override 12849 | { 12850 | return std::min( 12851 | vec0_node_ptr_->vec_holder().base_size(), 12852 | vec1_node_ptr_->vec_holder().base_size()); 12853 | } 12854 | 12855 | vds_t& vds() exprtk_override 12856 | { 12857 | return vds_; 12858 | } 12859 | 12860 | const vds_t& vds() const exprtk_override 12861 | { 12862 | return vds_; 12863 | } 12864 | 12865 | private: 12866 | 12867 | vector_node<T>* vec0_node_ptr_; 12868 | vector_node<T>* vec1_node_ptr_; 12869 | bool initialised_; 12870 | bool src_is_ivec_; 12871 | vds_t vds_; 12872 | }; 12873 | 12874 | template <typename T, typename Operation> 12875 | class assignment_op_node exprtk_final : public binary_node<T> 12876 | { 12877 | public: 12878 | 12879 | typedef expression_node<T>* expression_ptr; 12880 | using binary_node<T>::branch; 12881 | 12882 | assignment_op_node(const operator_type& opr, 12883 | expression_ptr branch0, 12884 | expression_ptr branch1) 12885 | : binary_node<T>(opr, branch0, branch1) 12886 | , var_node_ptr_(0) 12887 | { 12888 | if (is_variable_node(branch(0))) 12889 | { 12890 | var_node_ptr_ = static_cast<variable_node<T>*>(branch(0)); 12891 | } 12892 | 12893 | assert(valid()); 12894 | } 12895 | 12896 | inline T value() const exprtk_override 12897 | { 12898 | T& v = var_node_ptr_->ref(); 12899 | v = Operation::process(v,branch(1)->value()); 12900 | 12901 | return v; 12902 | } 12903 | 12904 | inline bool valid() const exprtk_override 12905 | { 12906 | return var_node_ptr_ && binary_node<T>::valid(); 12907 | } 12908 | 12909 | private: 12910 | 12911 | variable_node<T>* var_node_ptr_; 12912 | }; 12913 | 12914 | template <typename T, typename Operation> 12915 | class assignment_vec_elem_op_node exprtk_final : public binary_node<T> 12916 | { 12917 | public: 12918 | 12919 | typedef expression_node<T>* expression_ptr; 12920 | using binary_node<T>::branch; 12921 | 12922 | assignment_vec_elem_op_node(const operator_type& opr, 12923 | expression_ptr branch0, 12924 | expression_ptr branch1) 12925 | : binary_node<T>(opr, branch0, branch1) 12926 | , vec_node_ptr_(0) 12927 | { 12928 | if (is_vector_elem_node(branch(0))) 12929 | { 12930 | vec_node_ptr_ = static_cast<vector_elem_node<T>*>(branch(0)); 12931 | } 12932 | 12933 | assert(valid()); 12934 | } 12935 | 12936 | inline T value() const exprtk_override 12937 | { 12938 | T& v = vec_node_ptr_->ref(); 12939 | v = Operation::process(v,branch(1)->value()); 12940 | 12941 | return v; 12942 | } 12943 | 12944 | inline bool valid() const exprtk_override 12945 | { 12946 | return vec_node_ptr_ && binary_node<T>::valid(); 12947 | } 12948 | 12949 | private: 12950 | 12951 | vector_elem_node<T>* vec_node_ptr_; 12952 | }; 12953 | 12954 | template <typename T, typename Operation> 12955 | class assignment_vec_elem_op_rtc_node exprtk_final : public binary_node<T> 12956 | { 12957 | public: 12958 | 12959 | typedef expression_node<T>* expression_ptr; 12960 | using binary_node<T>::branch; 12961 | 12962 | assignment_vec_elem_op_rtc_node(const operator_type& opr, 12963 | expression_ptr branch0, 12964 | expression_ptr branch1) 12965 | : binary_node<T>(opr, branch0, branch1) 12966 | , vec_node_ptr_(0) 12967 | { 12968 | if (is_vector_elem_rtc_node(branch(0))) 12969 | { 12970 | vec_node_ptr_ = static_cast<vector_elem_rtc_node<T>*>(branch(0)); 12971 | } 12972 | 12973 | assert(valid()); 12974 | } 12975 | 12976 | inline T value() const exprtk_override 12977 | { 12978 | T& v = vec_node_ptr_->ref(); 12979 | v = Operation::process(v,branch(1)->value()); 12980 | 12981 | return v; 12982 | } 12983 | 12984 | inline bool valid() const exprtk_override 12985 | { 12986 | return vec_node_ptr_ && binary_node<T>::valid(); 12987 | } 12988 | 12989 | private: 12990 | 12991 | vector_elem_rtc_node<T>* vec_node_ptr_; 12992 | }; 12993 | 12994 | template <typename T, typename Operation> 12995 | class assignment_vec_celem_op_rtc_node exprtk_final : public binary_node<T> 12996 | { 12997 | public: 12998 | 12999 | typedef expression_node<T>* expression_ptr; 13000 | using binary_node<T>::branch; 13001 | 13002 | assignment_vec_celem_op_rtc_node(const operator_type& opr, 13003 | expression_ptr branch0, 13004 | expression_ptr branch1) 13005 | : binary_node<T>(opr, branch0, branch1) 13006 | , vec_node_ptr_(0) 13007 | { 13008 | if (is_vector_celem_rtc_node(branch(0))) 13009 | { 13010 | vec_node_ptr_ = static_cast<vector_celem_rtc_node<T>*>(branch(0)); 13011 | } 13012 | 13013 | assert(valid()); 13014 | } 13015 | 13016 | inline T value() const exprtk_override 13017 | { 13018 | T& v = vec_node_ptr_->ref(); 13019 | v = Operation::process(v,branch(1)->value()); 13020 | 13021 | return v; 13022 | } 13023 | 13024 | inline bool valid() const exprtk_override 13025 | { 13026 | return vec_node_ptr_ && binary_node<T>::valid(); 13027 | } 13028 | 13029 | private: 13030 | 13031 | vector_celem_rtc_node<T>* vec_node_ptr_; 13032 | }; 13033 | 13034 | template <typename T, typename Operation> 13035 | class assignment_rebasevec_elem_op_node exprtk_final : public binary_node<T> 13036 | { 13037 | public: 13038 | 13039 | typedef expression_node<T>* expression_ptr; 13040 | using binary_node<T>::branch; 13041 | 13042 | assignment_rebasevec_elem_op_node(const operator_type& opr, 13043 | expression_ptr branch0, 13044 | expression_ptr branch1) 13045 | : binary_node<T>(opr, branch0, branch1) 13046 | , rbvec_node_ptr_(0) 13047 | { 13048 | if (is_rebasevector_elem_node(branch(0))) 13049 | { 13050 | rbvec_node_ptr_ = static_cast<rebasevector_elem_node<T>*>(branch(0)); 13051 | } 13052 | 13053 | assert(valid()); 13054 | } 13055 | 13056 | inline T value() const exprtk_override 13057 | { 13058 | T& v = rbvec_node_ptr_->ref(); 13059 | v = Operation::process(v,branch(1)->value()); 13060 | 13061 | return v; 13062 | } 13063 | 13064 | inline bool valid() const exprtk_override 13065 | { 13066 | return rbvec_node_ptr_ && binary_node<T>::valid(); 13067 | } 13068 | 13069 | private: 13070 | 13071 | rebasevector_elem_node<T>* rbvec_node_ptr_; 13072 | }; 13073 | 13074 | template <typename T, typename Operation> 13075 | class assignment_rebasevec_celem_op_node exprtk_final : public binary_node<T> 13076 | { 13077 | public: 13078 | 13079 | typedef expression_node<T>* expression_ptr; 13080 | using binary_node<T>::branch; 13081 | 13082 | assignment_rebasevec_celem_op_node(const operator_type& opr, 13083 | expression_ptr branch0, 13084 | expression_ptr branch1) 13085 | : binary_node<T>(opr, branch0, branch1) 13086 | , rbvec_node_ptr_(0) 13087 | { 13088 | if (is_rebasevector_celem_node(branch(0))) 13089 | { 13090 | rbvec_node_ptr_ = static_cast<rebasevector_celem_node<T>*>(branch(0)); 13091 | } 13092 | 13093 | assert(valid()); 13094 | } 13095 | 13096 | inline T value() const exprtk_override 13097 | { 13098 | T& v = rbvec_node_ptr_->ref(); 13099 | v = Operation::process(v,branch(1)->value()); 13100 | 13101 | return v; 13102 | } 13103 | 13104 | inline bool valid() const exprtk_override 13105 | { 13106 | return rbvec_node_ptr_ && binary_node<T>::valid(); 13107 | } 13108 | 13109 | private: 13110 | 13111 | rebasevector_celem_node<T>* rbvec_node_ptr_; 13112 | }; 13113 | 13114 | template <typename T, typename Operation> 13115 | class assignment_rebasevec_elem_op_rtc_node exprtk_final : public binary_node<T> 13116 | { 13117 | public: 13118 | 13119 | typedef expression_node<T>* expression_ptr; 13120 | using binary_node<T>::branch; 13121 | 13122 | assignment_rebasevec_elem_op_rtc_node(const operator_type& opr, 13123 | expression_ptr branch0, 13124 | expression_ptr branch1) 13125 | : binary_node<T>(opr, branch0, branch1) 13126 | , rbvec_node_ptr_(0) 13127 | { 13128 | if (is_rebasevector_elem_rtc_node(branch(0))) 13129 | { 13130 | rbvec_node_ptr_ = static_cast<rebasevector_elem_rtc_node<T>*>(branch(0)); 13131 | } 13132 | 13133 | assert(valid()); 13134 | } 13135 | 13136 | inline T value() const exprtk_override 13137 | { 13138 | T& v = rbvec_node_ptr_->ref(); 13139 | v = Operation::process(v,branch(1)->value()); 13140 | 13141 | return v; 13142 | } 13143 | 13144 | inline bool valid() const exprtk_override 13145 | { 13146 | return rbvec_node_ptr_ && binary_node<T>::valid(); 13147 | } 13148 | 13149 | private: 13150 | 13151 | rebasevector_elem_rtc_node<T>* rbvec_node_ptr_; 13152 | }; 13153 | 13154 | template <typename T, typename Operation> 13155 | class assignment_rebasevec_celem_op_rtc_node exprtk_final : public binary_node<T> 13156 | { 13157 | public: 13158 | 13159 | typedef expression_node<T>* expression_ptr; 13160 | using binary_node<T>::branch; 13161 | 13162 | assignment_rebasevec_celem_op_rtc_node(const operator_type& opr, 13163 | expression_ptr branch0, 13164 | expression_ptr branch1) 13165 | : binary_node<T>(opr, branch0, branch1) 13166 | , rbvec_node_ptr_(0) 13167 | { 13168 | if (is_rebasevector_celem_rtc_node(branch(0))) 13169 | { 13170 | rbvec_node_ptr_ = static_cast<rebasevector_celem_rtc_node<T>*>(branch(0)); 13171 | } 13172 | 13173 | assert(valid()); 13174 | } 13175 | 13176 | inline T value() const exprtk_override 13177 | { 13178 | T& v = rbvec_node_ptr_->ref(); 13179 | v = Operation::process(v,branch(1)->value()); 13180 | 13181 | return v; 13182 | } 13183 | 13184 | inline bool valid() const exprtk_override 13185 | { 13186 | return rbvec_node_ptr_ && binary_node<T>::valid(); 13187 | } 13188 | 13189 | private: 13190 | 13191 | rebasevector_celem_rtc_node<T>* rbvec_node_ptr_; 13192 | }; 13193 | 13194 | template <typename T, typename Operation> 13195 | class assignment_vec_op_node exprtk_final 13196 | : public binary_node <T> 13197 | , public vector_interface<T> 13198 | { 13199 | public: 13200 | 13201 | typedef expression_node<T>* expression_ptr; 13202 | typedef vector_node<T>* vector_node_ptr; 13203 | typedef vec_data_store<T> vds_t; 13204 | 13205 | using binary_node<T>::branch; 13206 | 13207 | assignment_vec_op_node(const operator_type& opr, 13208 | expression_ptr branch0, 13209 | expression_ptr branch1) 13210 | : binary_node<T>(opr, branch0, branch1) 13211 | , vec_node_ptr_(0) 13212 | { 13213 | if (is_vector_node(branch(0))) 13214 | { 13215 | vec_node_ptr_ = static_cast<vector_node<T>*>(branch(0)); 13216 | vds() = vec_node_ptr_->vds(); 13217 | } 13218 | 13219 | assert(valid()); 13220 | } 13221 | 13222 | inline T value() const exprtk_override 13223 | { 13224 | const T v = branch(1)->value(); 13225 | 13226 | T* vec = vds().data(); 13227 | 13228 | loop_unroll::details lud(size()); 13229 | const T* upper_bound = vec + lud.upper_bound; 13230 | 13231 | while (vec < upper_bound) 13232 | { 13233 | #define exprtk_loop(N) \ 13234 | Operation::assign(vec[N],v); \ 13235 | 13236 | exprtk_loop( 0) exprtk_loop( 1) 13237 | exprtk_loop( 2) exprtk_loop( 3) 13238 | #ifndef exprtk_disable_superscalar_unroll 13239 | exprtk_loop( 4) exprtk_loop( 5) 13240 | exprtk_loop( 6) exprtk_loop( 7) 13241 | exprtk_loop( 8) exprtk_loop( 9) 13242 | exprtk_loop(10) exprtk_loop(11) 13243 | exprtk_loop(12) exprtk_loop(13) 13244 | exprtk_loop(14) exprtk_loop(15) 13245 | #endif 13246 | 13247 | vec += lud.batch_size; 13248 | } 13249 | 13250 | switch (lud.remainder) 13251 | { 13252 | #define case_stmt(N,fall_through) \ 13253 | case N : Operation::assign(*vec++,v); \ 13254 | fall_through \ 13255 | 13256 | #ifndef exprtk_disable_superscalar_unroll 13257 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 13258 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 13259 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 13260 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 13261 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 13262 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 13263 | #endif 13264 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 13265 | case_stmt( 1, (void)0;) 13266 | } 13267 | 13268 | #undef exprtk_loop 13269 | #undef case_stmt 13270 | 13271 | return vec_node_ptr_->value(); 13272 | } 13273 | 13274 | vector_node_ptr vec() const exprtk_override 13275 | { 13276 | return vec_node_ptr_; 13277 | } 13278 | 13279 | vector_node_ptr vec() exprtk_override 13280 | { 13281 | return vec_node_ptr_; 13282 | } 13283 | 13284 | inline typename expression_node<T>::node_type type() const exprtk_override 13285 | { 13286 | return expression_node<T>::e_vecopvalass; 13287 | } 13288 | 13289 | inline bool valid() const exprtk_override 13290 | { 13291 | return 13292 | vec_node_ptr_ && 13293 | (size() <= base_size()) && 13294 | binary_node<T>::valid() ; 13295 | } 13296 | 13297 | std::size_t size() const exprtk_override 13298 | { 13299 | return vec_node_ptr_->vec_holder().size(); 13300 | } 13301 | 13302 | std::size_t base_size() const exprtk_override 13303 | { 13304 | return vec_node_ptr_->vec_holder().base_size(); 13305 | } 13306 | 13307 | vds_t& vds() exprtk_override 13308 | { 13309 | return vds_; 13310 | } 13311 | 13312 | const vds_t& vds() const exprtk_override 13313 | { 13314 | return vds_; 13315 | } 13316 | 13317 | bool side_effect() const exprtk_override 13318 | { 13319 | return true; 13320 | } 13321 | 13322 | private: 13323 | 13324 | vector_node<T>* vec_node_ptr_; 13325 | vds_t vds_; 13326 | }; 13327 | 13328 | template <typename T, typename Operation> 13329 | class assignment_vecvec_op_node exprtk_final 13330 | : public binary_node <T> 13331 | , public vector_interface<T> 13332 | { 13333 | public: 13334 | 13335 | typedef expression_node<T>* expression_ptr; 13336 | typedef vector_node<T>* vector_node_ptr; 13337 | typedef vec_data_store<T> vds_t; 13338 | 13339 | using binary_node<T>::branch; 13340 | 13341 | assignment_vecvec_op_node(const operator_type& opr, 13342 | expression_ptr branch0, 13343 | expression_ptr branch1) 13344 | : binary_node<T>(opr, branch0, branch1) 13345 | , vec0_node_ptr_(0) 13346 | , vec1_node_ptr_(0) 13347 | , initialised_(false) 13348 | { 13349 | if (is_vector_node(branch(0))) 13350 | { 13351 | vec0_node_ptr_ = static_cast<vector_node<T>*>(branch(0)); 13352 | vds() = vec0_node_ptr_->vds(); 13353 | } 13354 | 13355 | if (is_vector_node(branch(1))) 13356 | { 13357 | vec1_node_ptr_ = static_cast<vector_node<T>*>(branch(1)); 13358 | vec1_node_ptr_->vds() = vds(); 13359 | } 13360 | else if (is_ivector_node(branch(1))) 13361 | { 13362 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 13363 | 13364 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1)))) 13365 | { 13366 | vec1_node_ptr_ = vi->vec(); 13367 | vec1_node_ptr_->vds() = vi->vds(); 13368 | } 13369 | else 13370 | vds_t::match_sizes(vds(),vec1_node_ptr_->vds()); 13371 | } 13372 | 13373 | initialised_ = 13374 | vec0_node_ptr_ && 13375 | vec1_node_ptr_ && 13376 | (size() <= base_size()) && 13377 | binary_node<T>::valid(); 13378 | 13379 | assert(valid()); 13380 | } 13381 | 13382 | inline T value() const exprtk_override 13383 | { 13384 | branch(0)->value(); 13385 | branch(1)->value(); 13386 | 13387 | T* vec0 = vec0_node_ptr_->vds().data(); 13388 | const T* vec1 = vec1_node_ptr_->vds().data(); 13389 | 13390 | loop_unroll::details lud(size()); 13391 | const T* upper_bound = vec0 + lud.upper_bound; 13392 | 13393 | while (vec0 < upper_bound) 13394 | { 13395 | #define exprtk_loop(N) \ 13396 | vec0[N] = Operation::process(vec0[N], vec1[N]); \ 13397 | 13398 | exprtk_loop( 0) exprtk_loop( 1) 13399 | exprtk_loop( 2) exprtk_loop( 3) 13400 | #ifndef exprtk_disable_superscalar_unroll 13401 | exprtk_loop( 4) exprtk_loop( 5) 13402 | exprtk_loop( 6) exprtk_loop( 7) 13403 | exprtk_loop( 8) exprtk_loop( 9) 13404 | exprtk_loop(10) exprtk_loop(11) 13405 | exprtk_loop(12) exprtk_loop(13) 13406 | exprtk_loop(14) exprtk_loop(15) 13407 | #endif 13408 | 13409 | vec0 += lud.batch_size; 13410 | vec1 += lud.batch_size; 13411 | } 13412 | 13413 | int i = 0; 13414 | 13415 | switch (lud.remainder) 13416 | { 13417 | #define case_stmt(N,fall_through) \ 13418 | case N : { vec0[i] = Operation::process(vec0[i], vec1[i]); ++i; } \ 13419 | fall_through \ 13420 | 13421 | #ifndef exprtk_disable_superscalar_unroll 13422 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 13423 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 13424 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 13425 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 13426 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 13427 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 13428 | #endif 13429 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 13430 | case_stmt( 1, (void)0;) 13431 | } 13432 | 13433 | #undef exprtk_loop 13434 | #undef case_stmt 13435 | 13436 | return vec0_node_ptr_->value(); 13437 | } 13438 | 13439 | vector_node_ptr vec() const exprtk_override 13440 | { 13441 | return vec0_node_ptr_; 13442 | } 13443 | 13444 | vector_node_ptr vec() exprtk_override 13445 | { 13446 | return vec0_node_ptr_; 13447 | } 13448 | 13449 | inline typename expression_node<T>::node_type type() const exprtk_override 13450 | { 13451 | return expression_node<T>::e_vecopvecass; 13452 | } 13453 | 13454 | inline bool valid() const exprtk_override 13455 | { 13456 | return initialised_; 13457 | } 13458 | 13459 | std::size_t size() const exprtk_override 13460 | { 13461 | return std::min( 13462 | vec0_node_ptr_->vec_holder().size(), 13463 | vec1_node_ptr_->vec_holder().size()); 13464 | } 13465 | 13466 | std::size_t base_size() const exprtk_override 13467 | { 13468 | return std::min( 13469 | vec0_node_ptr_->vec_holder().base_size(), 13470 | vec1_node_ptr_->vec_holder().base_size()); 13471 | } 13472 | 13473 | vds_t& vds() exprtk_override 13474 | { 13475 | return vds_; 13476 | } 13477 | 13478 | const vds_t& vds() const exprtk_override 13479 | { 13480 | return vds_; 13481 | } 13482 | 13483 | bool side_effect() const exprtk_override 13484 | { 13485 | return true; 13486 | } 13487 | 13488 | private: 13489 | 13490 | vector_node<T>* vec0_node_ptr_; 13491 | vector_node<T>* vec1_node_ptr_; 13492 | bool initialised_; 13493 | vds_t vds_; 13494 | }; 13495 | 13496 | template <typename T> 13497 | struct memory_context_t 13498 | { 13499 | typedef vector_node<T>* vector_node_ptr; 13500 | typedef vector_holder<T> vector_holder_t; 13501 | typedef vector_holder_t* vector_holder_ptr; 13502 | 13503 | memory_context_t() 13504 | : temp_(0) 13505 | , temp_vec_node_(0) 13506 | {} 13507 | 13508 | void clear() 13509 | { 13510 | delete temp_vec_node_; 13511 | delete temp_; 13512 | } 13513 | 13514 | vector_holder_ptr temp_; 13515 | vector_node_ptr temp_vec_node_; 13516 | }; 13517 | 13518 | template <typename T> 13519 | inline memory_context_t<T> make_memory_context(vector_holder<T>& vec_holder, 13520 | vec_data_store<T>& vds) 13521 | { 13522 | memory_context_t<T> result_ctxt; 13523 | result_ctxt.temp_ = (vec_holder.rebaseable()) ? 13524 | new vector_holder<T>(vec_holder,vds) : 13525 | new vector_holder<T>(vds) ; 13526 | result_ctxt.temp_vec_node_ = new vector_node <T>(vds,result_ctxt.temp_); 13527 | return result_ctxt; 13528 | } 13529 | 13530 | template <typename T> 13531 | inline memory_context_t<T> make_memory_context(vector_holder<T>& vec_holder0, 13532 | vector_holder<T>& vec_holder1, 13533 | vec_data_store<T>& vds) 13534 | { 13535 | memory_context_t<T> result_ctxt; 13536 | 13537 | if (!vec_holder0.rebaseable() && !vec_holder1.rebaseable()) 13538 | result_ctxt.temp_ = new vector_holder<T>(vds); 13539 | else if (vec_holder0.rebaseable() && !vec_holder1.rebaseable()) 13540 | result_ctxt.temp_ = new vector_holder<T>(vec_holder0,vds); 13541 | else if (!vec_holder0.rebaseable() && vec_holder1.rebaseable()) 13542 | result_ctxt.temp_ = new vector_holder<T>(vec_holder1,vds); 13543 | else 13544 | { 13545 | result_ctxt.temp_ = (vec_holder0.base_size() >= vec_holder1.base_size()) ? 13546 | new vector_holder<T>(vec_holder0, vds) : 13547 | new vector_holder<T>(vec_holder1, vds) ; 13548 | } 13549 | 13550 | result_ctxt.temp_vec_node_ = new vector_node <T>(vds,result_ctxt.temp_); 13551 | return result_ctxt; 13552 | } 13553 | 13554 | template <typename T, typename Operation> 13555 | class vec_binop_vecvec_node exprtk_final 13556 | : public binary_node <T> 13557 | , public vector_interface<T> 13558 | { 13559 | public: 13560 | 13561 | typedef expression_node<T>* expression_ptr; 13562 | typedef vector_node<T>* vector_node_ptr; 13563 | typedef vector_holder<T> vector_holder_t; 13564 | typedef vector_holder_t* vector_holder_ptr; 13565 | typedef vec_data_store<T> vds_t; 13566 | typedef memory_context_t<T> memory_context; 13567 | 13568 | using binary_node<T>::branch; 13569 | 13570 | vec_binop_vecvec_node(const operator_type& opr, 13571 | expression_ptr branch0, 13572 | expression_ptr branch1) 13573 | : binary_node<T>(opr, branch0, branch1) 13574 | , vec0_node_ptr_(0) 13575 | , vec1_node_ptr_(0) 13576 | , initialised_(false) 13577 | { 13578 | bool v0_is_ivec = false; 13579 | bool v1_is_ivec = false; 13580 | 13581 | if (is_vector_node(branch(0))) 13582 | { 13583 | vec0_node_ptr_ = static_cast<vector_node_ptr>(branch(0)); 13584 | } 13585 | else if (is_ivector_node(branch(0))) 13586 | { 13587 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 13588 | 13589 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(0)))) 13590 | { 13591 | vec0_node_ptr_ = vi->vec(); 13592 | v0_is_ivec = true; 13593 | } 13594 | } 13595 | 13596 | if (is_vector_node(branch(1))) 13597 | { 13598 | vec1_node_ptr_ = static_cast<vector_node_ptr>(branch(1)); 13599 | } 13600 | else if (is_ivector_node(branch(1))) 13601 | { 13602 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 13603 | 13604 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1)))) 13605 | { 13606 | vec1_node_ptr_ = vi->vec(); 13607 | v1_is_ivec = true; 13608 | } 13609 | } 13610 | 13611 | if (vec0_node_ptr_ && vec1_node_ptr_) 13612 | { 13613 | vector_holder<T>& vec0 = vec0_node_ptr_->vec_holder(); 13614 | vector_holder<T>& vec1 = vec1_node_ptr_->vec_holder(); 13615 | 13616 | if (v0_is_ivec && (vec0.base_size() <= vec1.base_size())) 13617 | { 13618 | vds_ = vds_t(vec0_node_ptr_->vds()); 13619 | } 13620 | else if (v1_is_ivec && (vec1.base_size() <= vec0.base_size())) 13621 | { 13622 | vds_ = vds_t(vec1_node_ptr_->vds()); 13623 | } 13624 | else 13625 | { 13626 | vds_ = vds_t(std::min(vec0.base_size(),vec1.base_size())); 13627 | } 13628 | 13629 | memory_context_ = make_memory_context(vec0, vec1, vds()); 13630 | 13631 | initialised_ = 13632 | (size() <= base_size()) && 13633 | binary_node<T>::valid(); 13634 | } 13635 | 13636 | assert(valid()); 13637 | } 13638 | 13639 | ~vec_binop_vecvec_node() 13640 | { 13641 | memory_context_.clear(); 13642 | } 13643 | 13644 | inline T value() const exprtk_override 13645 | { 13646 | branch(0)->value(); 13647 | branch(1)->value(); 13648 | 13649 | const T* vec0 = vec0_node_ptr_->vds().data(); 13650 | const T* vec1 = vec1_node_ptr_->vds().data(); 13651 | T* vec2 = vds().data(); 13652 | 13653 | loop_unroll::details lud(size()); 13654 | const T* upper_bound = vec2 + lud.upper_bound; 13655 | 13656 | while (vec2 < upper_bound) 13657 | { 13658 | #define exprtk_loop(N) \ 13659 | vec2[N] = Operation::process(vec0[N], vec1[N]); \ 13660 | 13661 | exprtk_loop( 0) exprtk_loop( 1) 13662 | exprtk_loop( 2) exprtk_loop( 3) 13663 | #ifndef exprtk_disable_superscalar_unroll 13664 | exprtk_loop( 4) exprtk_loop( 5) 13665 | exprtk_loop( 6) exprtk_loop( 7) 13666 | exprtk_loop( 8) exprtk_loop( 9) 13667 | exprtk_loop(10) exprtk_loop(11) 13668 | exprtk_loop(12) exprtk_loop(13) 13669 | exprtk_loop(14) exprtk_loop(15) 13670 | #endif 13671 | 13672 | vec0 += lud.batch_size; 13673 | vec1 += lud.batch_size; 13674 | vec2 += lud.batch_size; 13675 | } 13676 | 13677 | int i = 0; 13678 | 13679 | switch (lud.remainder) 13680 | { 13681 | #define case_stmt(N) \ 13682 | case N : { vec2[i] = Operation::process(vec0[i], vec1[i]); ++i; } \ 13683 | exprtk_fallthrough \ 13684 | 13685 | #ifndef exprtk_disable_superscalar_unroll 13686 | case_stmt(15) case_stmt(14) 13687 | case_stmt(13) case_stmt(12) 13688 | case_stmt(11) case_stmt(10) 13689 | case_stmt( 9) case_stmt( 8) 13690 | case_stmt( 7) case_stmt( 6) 13691 | case_stmt( 5) case_stmt( 4) 13692 | #endif 13693 | case_stmt( 3) case_stmt( 2) 13694 | case_stmt( 1) 13695 | default: break; 13696 | } 13697 | 13698 | #undef exprtk_loop 13699 | #undef case_stmt 13700 | 13701 | return (vds().data())[0]; 13702 | } 13703 | 13704 | vector_node_ptr vec() const exprtk_override 13705 | { 13706 | return memory_context_.temp_vec_node_; 13707 | } 13708 | 13709 | vector_node_ptr vec() exprtk_override 13710 | { 13711 | return memory_context_.temp_vec_node_; 13712 | } 13713 | 13714 | inline typename expression_node<T>::node_type type() const exprtk_override 13715 | { 13716 | return expression_node<T>::e_vecvecarith; 13717 | } 13718 | 13719 | inline bool valid() const exprtk_override 13720 | { 13721 | return initialised_; 13722 | } 13723 | 13724 | std::size_t size() const exprtk_override 13725 | { 13726 | return std::min( 13727 | vec0_node_ptr_->vec_holder().size(), 13728 | vec1_node_ptr_->vec_holder().size()); 13729 | } 13730 | 13731 | std::size_t base_size() const exprtk_override 13732 | { 13733 | return std::min( 13734 | vec0_node_ptr_->vec_holder().base_size(), 13735 | vec1_node_ptr_->vec_holder().base_size()); 13736 | } 13737 | 13738 | vds_t& vds() exprtk_override 13739 | { 13740 | return vds_; 13741 | } 13742 | 13743 | const vds_t& vds() const exprtk_override 13744 | { 13745 | return vds_; 13746 | } 13747 | 13748 | private: 13749 | 13750 | vector_node_ptr vec0_node_ptr_; 13751 | vector_node_ptr vec1_node_ptr_; 13752 | bool initialised_; 13753 | vds_t vds_; 13754 | memory_context memory_context_; 13755 | }; 13756 | 13757 | template <typename T, typename Operation> 13758 | class vec_binop_vecval_node exprtk_final 13759 | : public binary_node <T> 13760 | , public vector_interface<T> 13761 | { 13762 | public: 13763 | 13764 | typedef expression_node<T>* expression_ptr; 13765 | typedef vector_node<T>* vector_node_ptr; 13766 | typedef vector_holder<T> vector_holder_t; 13767 | typedef vector_holder_t* vector_holder_ptr; 13768 | typedef vec_data_store<T> vds_t; 13769 | typedef memory_context_t<T> memory_context; 13770 | 13771 | using binary_node<T>::branch; 13772 | 13773 | vec_binop_vecval_node(const operator_type& opr, 13774 | expression_ptr branch0, 13775 | expression_ptr branch1) 13776 | : binary_node<T>(opr, branch0, branch1) 13777 | , vec0_node_ptr_(0) 13778 | { 13779 | bool v0_is_ivec = false; 13780 | 13781 | if (is_vector_node(branch(0))) 13782 | { 13783 | vec0_node_ptr_ = static_cast<vector_node_ptr>(branch(0)); 13784 | } 13785 | else if (is_ivector_node(branch(0))) 13786 | { 13787 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 13788 | 13789 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(0)))) 13790 | { 13791 | vec0_node_ptr_ = vi->vec(); 13792 | v0_is_ivec = true; 13793 | } 13794 | } 13795 | 13796 | if (vec0_node_ptr_) 13797 | { 13798 | if (v0_is_ivec) 13799 | vds() = vec0_node_ptr_->vds(); 13800 | else 13801 | vds() = vds_t(vec0_node_ptr_->base_size()); 13802 | 13803 | memory_context_ = make_memory_context(vec0_node_ptr_->vec_holder(), vds()); 13804 | } 13805 | 13806 | assert(valid()); 13807 | } 13808 | 13809 | ~vec_binop_vecval_node() 13810 | { 13811 | memory_context_.clear(); 13812 | } 13813 | 13814 | inline T value() const exprtk_override 13815 | { 13816 | branch(0)->value(); 13817 | const T v = branch(1)->value(); 13818 | 13819 | const T* vec0 = vec0_node_ptr_->vds().data(); 13820 | T* vec1 = vds().data(); 13821 | 13822 | loop_unroll::details lud(size()); 13823 | const T* upper_bound = vec0 + lud.upper_bound; 13824 | 13825 | while (vec0 < upper_bound) 13826 | { 13827 | #define exprtk_loop(N) \ 13828 | vec1[N] = Operation::process(vec0[N], v); \ 13829 | 13830 | exprtk_loop( 0) exprtk_loop( 1) 13831 | exprtk_loop( 2) exprtk_loop( 3) 13832 | #ifndef exprtk_disable_superscalar_unroll 13833 | exprtk_loop( 4) exprtk_loop( 5) 13834 | exprtk_loop( 6) exprtk_loop( 7) 13835 | exprtk_loop( 8) exprtk_loop( 9) 13836 | exprtk_loop(10) exprtk_loop(11) 13837 | exprtk_loop(12) exprtk_loop(13) 13838 | exprtk_loop(14) exprtk_loop(15) 13839 | #endif 13840 | 13841 | vec0 += lud.batch_size; 13842 | vec1 += lud.batch_size; 13843 | } 13844 | 13845 | int i = 0; 13846 | 13847 | switch (lud.remainder) 13848 | { 13849 | #define case_stmt(N,fall_through) \ 13850 | case N : { vec1[i] = Operation::process(vec0[i], v); ++i; } \ 13851 | fall_through \ 13852 | 13853 | #ifndef exprtk_disable_superscalar_unroll 13854 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 13855 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 13856 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 13857 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 13858 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 13859 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 13860 | #endif 13861 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 13862 | case_stmt( 1, (void)0;) 13863 | } 13864 | 13865 | #undef exprtk_loop 13866 | #undef case_stmt 13867 | 13868 | return (vds().data())[0]; 13869 | } 13870 | 13871 | vector_node_ptr vec() const exprtk_override 13872 | { 13873 | return memory_context_.temp_vec_node_; 13874 | } 13875 | 13876 | vector_node_ptr vec() exprtk_override 13877 | { 13878 | return memory_context_.temp_vec_node_; 13879 | } 13880 | 13881 | inline typename expression_node<T>::node_type type() const exprtk_override 13882 | { 13883 | return expression_node<T>::e_vecvalarith; 13884 | } 13885 | 13886 | inline bool valid() const exprtk_override 13887 | { 13888 | return 13889 | vec0_node_ptr_ && 13890 | (size() <= base_size()) && 13891 | binary_node<T>::valid(); 13892 | } 13893 | 13894 | std::size_t size() const exprtk_override 13895 | { 13896 | return vec0_node_ptr_->size(); 13897 | } 13898 | 13899 | std::size_t base_size() const exprtk_override 13900 | { 13901 | return vec0_node_ptr_->vec_holder().base_size(); 13902 | } 13903 | 13904 | vds_t& vds() exprtk_override 13905 | { 13906 | return vds_; 13907 | } 13908 | 13909 | const vds_t& vds() const exprtk_override 13910 | { 13911 | return vds_; 13912 | } 13913 | 13914 | private: 13915 | 13916 | vector_node_ptr vec0_node_ptr_; 13917 | vds_t vds_; 13918 | memory_context memory_context_; 13919 | }; 13920 | 13921 | template <typename T, typename Operation> 13922 | class vec_binop_valvec_node exprtk_final 13923 | : public binary_node <T> 13924 | , public vector_interface<T> 13925 | { 13926 | public: 13927 | 13928 | typedef expression_node<T>* expression_ptr; 13929 | typedef vector_node<T>* vector_node_ptr; 13930 | typedef vector_holder<T> vector_holder_t; 13931 | typedef vector_holder_t* vector_holder_ptr; 13932 | typedef vec_data_store<T> vds_t; 13933 | typedef memory_context_t<T> memory_context; 13934 | 13935 | using binary_node<T>::branch; 13936 | 13937 | vec_binop_valvec_node(const operator_type& opr, 13938 | expression_ptr branch0, 13939 | expression_ptr branch1) 13940 | : binary_node<T>(opr, branch0, branch1) 13941 | , vec1_node_ptr_(0) 13942 | { 13943 | bool v1_is_ivec = false; 13944 | 13945 | if (is_vector_node(branch(1))) 13946 | { 13947 | vec1_node_ptr_ = static_cast<vector_node_ptr>(branch(1)); 13948 | } 13949 | else if (is_ivector_node(branch(1))) 13950 | { 13951 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 13952 | 13953 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(1)))) 13954 | { 13955 | vec1_node_ptr_ = vi->vec(); 13956 | v1_is_ivec = true; 13957 | } 13958 | } 13959 | 13960 | if (vec1_node_ptr_) 13961 | { 13962 | if (v1_is_ivec) 13963 | vds() = vec1_node_ptr_->vds(); 13964 | else 13965 | vds() = vds_t(vec1_node_ptr_->base_size()); 13966 | 13967 | memory_context_ = make_memory_context(vec1_node_ptr_->vec_holder(), vds()); 13968 | } 13969 | 13970 | assert(valid()); 13971 | } 13972 | 13973 | ~vec_binop_valvec_node() 13974 | { 13975 | memory_context_.clear(); 13976 | } 13977 | 13978 | inline T value() const exprtk_override 13979 | { 13980 | const T v = branch(0)->value(); 13981 | branch(1)->value(); 13982 | 13983 | T* vec0 = vds().data(); 13984 | const T* vec1 = vec1_node_ptr_->vds().data(); 13985 | 13986 | loop_unroll::details lud(size()); 13987 | const T* upper_bound = vec0 + lud.upper_bound; 13988 | 13989 | while (vec0 < upper_bound) 13990 | { 13991 | #define exprtk_loop(N) \ 13992 | vec0[N] = Operation::process(v, vec1[N]); \ 13993 | 13994 | exprtk_loop( 0) exprtk_loop( 1) 13995 | exprtk_loop( 2) exprtk_loop( 3) 13996 | #ifndef exprtk_disable_superscalar_unroll 13997 | exprtk_loop( 4) exprtk_loop( 5) 13998 | exprtk_loop( 6) exprtk_loop( 7) 13999 | exprtk_loop( 8) exprtk_loop( 9) 14000 | exprtk_loop(10) exprtk_loop(11) 14001 | exprtk_loop(12) exprtk_loop(13) 14002 | exprtk_loop(14) exprtk_loop(15) 14003 | #endif 14004 | 14005 | vec0 += lud.batch_size; 14006 | vec1 += lud.batch_size; 14007 | } 14008 | 14009 | int i = 0; 14010 | 14011 | switch (lud.remainder) 14012 | { 14013 | #define case_stmt(N,fall_through) \ 14014 | case N : { vec0[i] = Operation::process(v, vec1[i]); ++i; } \ 14015 | fall_through \ 14016 | 14017 | #ifndef exprtk_disable_superscalar_unroll 14018 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 14019 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 14020 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 14021 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 14022 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 14023 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 14024 | #endif 14025 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 14026 | case_stmt( 1, (void)0;) 14027 | } 14028 | 14029 | #undef exprtk_loop 14030 | #undef case_stmt 14031 | 14032 | return (vds().data())[0]; 14033 | } 14034 | 14035 | vector_node_ptr vec() const exprtk_override 14036 | { 14037 | return memory_context_.temp_vec_node_; 14038 | } 14039 | 14040 | vector_node_ptr vec() exprtk_override 14041 | { 14042 | return memory_context_.temp_vec_node_; 14043 | } 14044 | 14045 | inline typename expression_node<T>::node_type type() const exprtk_override 14046 | { 14047 | return expression_node<T>::e_vecvalarith; 14048 | } 14049 | 14050 | inline bool valid() const exprtk_override 14051 | { 14052 | return 14053 | vec1_node_ptr_ && 14054 | (size() <= base_size()) && 14055 | (vds_.size() <= base_size()) && 14056 | binary_node<T>::valid(); 14057 | } 14058 | 14059 | std::size_t size() const exprtk_override 14060 | { 14061 | return vec1_node_ptr_->vec_holder().size(); 14062 | } 14063 | 14064 | std::size_t base_size() const exprtk_override 14065 | { 14066 | return vec1_node_ptr_->vec_holder().base_size(); 14067 | } 14068 | 14069 | vds_t& vds() exprtk_override 14070 | { 14071 | return vds_; 14072 | } 14073 | 14074 | const vds_t& vds() const exprtk_override 14075 | { 14076 | return vds_; 14077 | } 14078 | 14079 | private: 14080 | 14081 | vector_node_ptr vec1_node_ptr_; 14082 | vds_t vds_; 14083 | memory_context memory_context_; 14084 | }; 14085 | 14086 | template <typename T, typename Operation> 14087 | class unary_vector_node exprtk_final 14088 | : public unary_node <T> 14089 | , public vector_interface<T> 14090 | { 14091 | public: 14092 | 14093 | typedef expression_node<T>* expression_ptr; 14094 | typedef vector_node<T>* vector_node_ptr; 14095 | typedef vector_holder<T> vector_holder_t; 14096 | typedef vector_holder_t* vector_holder_ptr; 14097 | typedef vec_data_store<T> vds_t; 14098 | typedef memory_context_t<T> memory_context; 14099 | 14100 | using expression_node<T>::branch; 14101 | 14102 | unary_vector_node(const operator_type& opr, expression_ptr branch0) 14103 | : unary_node<T>(opr, branch0) 14104 | , vec0_node_ptr_(0) 14105 | { 14106 | bool vec0_is_ivec = false; 14107 | 14108 | if (is_vector_node(branch(0))) 14109 | { 14110 | vec0_node_ptr_ = static_cast<vector_node_ptr>(branch(0)); 14111 | } 14112 | else if (is_ivector_node(branch(0))) 14113 | { 14114 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 14115 | 14116 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(branch(0)))) 14117 | { 14118 | vec0_node_ptr_ = vi->vec(); 14119 | vec0_is_ivec = true; 14120 | } 14121 | } 14122 | 14123 | if (vec0_node_ptr_) 14124 | { 14125 | if (vec0_is_ivec) 14126 | vds_ = vec0_node_ptr_->vds(); 14127 | else 14128 | vds_ = vds_t(vec0_node_ptr_->base_size()); 14129 | 14130 | memory_context_ = make_memory_context(vec0_node_ptr_->vec_holder(), vds()); 14131 | } 14132 | 14133 | assert(valid()); 14134 | } 14135 | 14136 | ~unary_vector_node() 14137 | { 14138 | memory_context_.clear(); 14139 | } 14140 | 14141 | inline T value() const exprtk_override 14142 | { 14143 | branch()->value(); 14144 | 14145 | const T* vec0 = vec0_node_ptr_->vds().data(); 14146 | T* vec1 = vds().data(); 14147 | 14148 | loop_unroll::details lud(size()); 14149 | const T* upper_bound = vec0 + lud.upper_bound; 14150 | 14151 | while (vec0 < upper_bound) 14152 | { 14153 | #define exprtk_loop(N) \ 14154 | vec1[N] = Operation::process(vec0[N]); \ 14155 | 14156 | exprtk_loop( 0) exprtk_loop( 1) 14157 | exprtk_loop( 2) exprtk_loop( 3) 14158 | #ifndef exprtk_disable_superscalar_unroll 14159 | exprtk_loop( 4) exprtk_loop( 5) 14160 | exprtk_loop( 6) exprtk_loop( 7) 14161 | exprtk_loop( 8) exprtk_loop( 9) 14162 | exprtk_loop(10) exprtk_loop(11) 14163 | exprtk_loop(12) exprtk_loop(13) 14164 | exprtk_loop(14) exprtk_loop(15) 14165 | #endif 14166 | 14167 | vec0 += lud.batch_size; 14168 | vec1 += lud.batch_size; 14169 | } 14170 | 14171 | int i = 0; 14172 | 14173 | switch (lud.remainder) 14174 | { 14175 | #define case_stmt(N) \ 14176 | case N : { vec1[i] = Operation::process(vec0[i]); ++i; } \ 14177 | exprtk_fallthrough \ 14178 | 14179 | #ifndef exprtk_disable_superscalar_unroll 14180 | case_stmt(15) case_stmt(14) 14181 | case_stmt(13) case_stmt(12) 14182 | case_stmt(11) case_stmt(10) 14183 | case_stmt( 9) case_stmt( 8) 14184 | case_stmt( 7) case_stmt( 6) 14185 | case_stmt( 5) case_stmt( 4) 14186 | #endif 14187 | case_stmt( 3) case_stmt( 2) 14188 | case_stmt( 1) 14189 | default: break; 14190 | } 14191 | 14192 | #undef exprtk_loop 14193 | #undef case_stmt 14194 | 14195 | return (vds().data())[0]; 14196 | } 14197 | 14198 | vector_node_ptr vec() const exprtk_override 14199 | { 14200 | return memory_context_.temp_vec_node_; 14201 | } 14202 | 14203 | vector_node_ptr vec() exprtk_override 14204 | { 14205 | return memory_context_.temp_vec_node_; 14206 | } 14207 | 14208 | inline typename expression_node<T>::node_type type() const exprtk_override 14209 | { 14210 | return expression_node<T>::e_vecunaryop; 14211 | } 14212 | 14213 | inline bool valid() const exprtk_override 14214 | { 14215 | return vec0_node_ptr_ && unary_node<T>::valid(); 14216 | } 14217 | 14218 | std::size_t size() const exprtk_override 14219 | { 14220 | return vec0_node_ptr_->vec_holder().size(); 14221 | } 14222 | 14223 | std::size_t base_size() const exprtk_override 14224 | { 14225 | return vec0_node_ptr_->vec_holder().base_size(); 14226 | } 14227 | 14228 | vds_t& vds() exprtk_override 14229 | { 14230 | return vds_; 14231 | } 14232 | 14233 | const vds_t& vds() const exprtk_override 14234 | { 14235 | return vds_; 14236 | } 14237 | 14238 | private: 14239 | 14240 | vector_node_ptr vec0_node_ptr_; 14241 | vds_t vds_; 14242 | memory_context memory_context_; 14243 | }; 14244 | 14245 | template <typename T> 14246 | class conditional_vector_node exprtk_final 14247 | : public expression_node <T> 14248 | , public vector_interface<T> 14249 | { 14250 | public: 14251 | 14252 | typedef expression_node <T>* expression_ptr; 14253 | typedef vector_interface<T>* vec_interface_ptr; 14254 | typedef vector_node <T>* vector_node_ptr; 14255 | typedef vector_holder <T> vector_holder_t; 14256 | typedef vector_holder_t* vector_holder_ptr; 14257 | typedef vec_data_store <T> vds_t; 14258 | typedef memory_context_t<T> memory_context; 14259 | typedef std::pair<expression_ptr,bool> branch_t; 14260 | 14261 | conditional_vector_node(expression_ptr condition, 14262 | expression_ptr consequent, 14263 | expression_ptr alternative) 14264 | : consequent_node_ptr_ (0) 14265 | , alternative_node_ptr_(0) 14266 | , temp_vec_node_ (0) 14267 | , temp_ (0) 14268 | , result_vec_size_ (0) 14269 | , initialised_ (false) 14270 | { 14271 | construct_branch_pair(condition_ , condition ); 14272 | construct_branch_pair(consequent_ , consequent ); 14273 | construct_branch_pair(alternative_, alternative); 14274 | 14275 | if (details::is_ivector_node(consequent_.first)) 14276 | { 14277 | vec_interface_ptr ivec_ptr = dynamic_cast<vec_interface_ptr>(consequent_.first); 14278 | 14279 | if (0 != ivec_ptr) 14280 | { 14281 | consequent_node_ptr_ = ivec_ptr->vec(); 14282 | } 14283 | } 14284 | 14285 | if (details::is_ivector_node(alternative_.first)) 14286 | { 14287 | vec_interface_ptr ivec_ptr = dynamic_cast<vec_interface_ptr>(alternative_.first); 14288 | 14289 | if (0 != ivec_ptr) 14290 | { 14291 | alternative_node_ptr_ = ivec_ptr->vec(); 14292 | } 14293 | } 14294 | 14295 | if (consequent_node_ptr_ && alternative_node_ptr_) 14296 | { 14297 | const std::size_t vec_size = 14298 | std::max(consequent_node_ptr_ ->vec_holder().base_size(), 14299 | alternative_node_ptr_->vec_holder().base_size()); 14300 | 14301 | vds_ = vds_t(vec_size); 14302 | memory_context_ = make_memory_context( 14303 | consequent_node_ptr_ ->vec_holder(), 14304 | alternative_node_ptr_->vec_holder(), 14305 | vds()); 14306 | 14307 | initialised_ = (vec_size > 0); 14308 | } 14309 | 14310 | assert(initialised_); 14311 | } 14312 | 14313 | ~conditional_vector_node() 14314 | { 14315 | memory_context_.clear(); 14316 | } 14317 | 14318 | inline T value() const exprtk_override 14319 | { 14320 | T result = T(0); 14321 | T* source_vector = 0; 14322 | T* result_vector = vds().data(); 14323 | 14324 | if (is_true(condition_)) 14325 | { 14326 | result = consequent_.first->value(); 14327 | source_vector = consequent_node_ptr_->vds().data(); 14328 | result_vec_size_ = consequent_node_ptr_->size(); 14329 | } 14330 | else 14331 | { 14332 | result = alternative_.first->value(); 14333 | source_vector = alternative_node_ptr_->vds().data(); 14334 | result_vec_size_ = alternative_node_ptr_->size(); 14335 | } 14336 | 14337 | for (std::size_t i = 0; i < result_vec_size_; ++i) 14338 | { 14339 | result_vector[i] = source_vector[i]; 14340 | } 14341 | 14342 | return result; 14343 | } 14344 | 14345 | vector_node_ptr vec() const exprtk_override 14346 | { 14347 | return memory_context_.temp_vec_node_; 14348 | } 14349 | 14350 | vector_node_ptr vec() exprtk_override 14351 | { 14352 | return memory_context_.temp_vec_node_; 14353 | } 14354 | 14355 | inline typename expression_node<T>::node_type type() const exprtk_override 14356 | { 14357 | return expression_node<T>::e_vecondition; 14358 | } 14359 | 14360 | inline bool valid() const exprtk_override 14361 | { 14362 | return 14363 | initialised_ && 14364 | condition_ .first && condition_ .first->valid() && 14365 | consequent_ .first && consequent_ .first->valid() && 14366 | alternative_.first && alternative_.first->valid() && 14367 | size() <= base_size(); 14368 | } 14369 | 14370 | std::size_t size() const exprtk_override 14371 | { 14372 | return result_vec_size_; 14373 | } 14374 | 14375 | std::size_t base_size() const exprtk_override 14376 | { 14377 | return std::min( 14378 | consequent_node_ptr_ ->vec_holder().base_size(), 14379 | alternative_node_ptr_->vec_holder().base_size()); 14380 | } 14381 | 14382 | vds_t& vds() exprtk_override 14383 | { 14384 | return vds_; 14385 | } 14386 | 14387 | const vds_t& vds() const exprtk_override 14388 | { 14389 | return vds_; 14390 | } 14391 | 14392 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 14393 | { 14394 | expression_node<T>::ndb_t::collect(condition_ , node_delete_list); 14395 | expression_node<T>::ndb_t::collect(consequent_ , node_delete_list); 14396 | expression_node<T>::ndb_t::collect(alternative_ , node_delete_list); 14397 | } 14398 | 14399 | std::size_t node_depth() const exprtk_override 14400 | { 14401 | return expression_node<T>::ndb_t::compute_node_depth 14402 | (condition_, consequent_, alternative_); 14403 | } 14404 | 14405 | private: 14406 | 14407 | branch_t condition_; 14408 | branch_t consequent_; 14409 | branch_t alternative_; 14410 | vector_node_ptr consequent_node_ptr_; 14411 | vector_node_ptr alternative_node_ptr_; 14412 | vector_node_ptr temp_vec_node_; 14413 | vector_holder_ptr temp_; 14414 | vds_t vds_; 14415 | mutable std::size_t result_vec_size_; 14416 | bool initialised_; 14417 | memory_context memory_context_; 14418 | }; 14419 | 14420 | template <typename T> 14421 | class scand_node exprtk_final : public binary_node<T> 14422 | { 14423 | public: 14424 | 14425 | typedef expression_node<T>* expression_ptr; 14426 | using binary_node<T>::branch; 14427 | 14428 | scand_node(const operator_type& opr, 14429 | expression_ptr branch0, 14430 | expression_ptr branch1) 14431 | : binary_node<T>(opr, branch0, branch1) 14432 | { 14433 | assert(binary_node<T>::valid()); 14434 | } 14435 | 14436 | inline T value() const exprtk_override 14437 | { 14438 | return ( 14439 | std::not_equal_to<T>() 14440 | (T(0),branch(0)->value()) && 14441 | std::not_equal_to<T>() 14442 | (T(0),branch(1)->value()) 14443 | ) ? T(1) : T(0); 14444 | } 14445 | }; 14446 | 14447 | template <typename T> 14448 | class scor_node exprtk_final : public binary_node<T> 14449 | { 14450 | public: 14451 | 14452 | typedef expression_node<T>* expression_ptr; 14453 | using binary_node<T>::branch; 14454 | 14455 | scor_node(const operator_type& opr, 14456 | expression_ptr branch0, 14457 | expression_ptr branch1) 14458 | : binary_node<T>(opr, branch0, branch1) 14459 | { 14460 | assert(binary_node<T>::valid()); 14461 | } 14462 | 14463 | inline T value() const exprtk_override 14464 | { 14465 | return ( 14466 | std::not_equal_to<T>() 14467 | (T(0),branch(0)->value()) || 14468 | std::not_equal_to<T>() 14469 | (T(0),branch(1)->value()) 14470 | ) ? T(1) : T(0); 14471 | } 14472 | }; 14473 | 14474 | template <typename T, typename IFunction, std::size_t N> 14475 | class function_N_node exprtk_final : public expression_node<T> 14476 | { 14477 | public: 14478 | 14479 | // Function of N parameters. 14480 | typedef expression_node<T>* expression_ptr; 14481 | typedef std::pair<expression_ptr,bool> branch_t; 14482 | typedef IFunction ifunction; 14483 | 14484 | explicit function_N_node(ifunction* func) 14485 | : function_((N == func->param_count) ? func : reinterpret_cast<ifunction*>(0)) 14486 | , parameter_count_(func->param_count) 14487 | , initialised_(false) 14488 | {} 14489 | 14490 | template <std::size_t NumBranches> 14491 | bool init_branches(expression_ptr (&b)[NumBranches]) 14492 | { 14493 | // Needed for incompetent and broken msvc compiler versions 14494 | #ifdef _MSC_VER 14495 | #pragma warning(push) 14496 | #pragma warning(disable: 4127) 14497 | #endif 14498 | 14499 | if (N != NumBranches) 14500 | { 14501 | return false; 14502 | } 14503 | 14504 | for (std::size_t i = 0; i < NumBranches; ++i) 14505 | { 14506 | if (b[i] && b[i]->valid()) 14507 | branch_[i] = std::make_pair(b[i],branch_deletable(b[i])); 14508 | else 14509 | return false; 14510 | } 14511 | 14512 | initialised_ = function_; 14513 | assert(valid()); 14514 | return initialised_; 14515 | 14516 | #ifdef _MSC_VER 14517 | #pragma warning(pop) 14518 | #endif 14519 | } 14520 | 14521 | inline bool operator <(const function_N_node<T,IFunction,N>& fn) const 14522 | { 14523 | return this < (&fn); 14524 | } 14525 | 14526 | inline T value() const exprtk_override 14527 | { 14528 | // Needed for incompetent and broken msvc compiler versions 14529 | #ifdef _MSC_VER 14530 | #pragma warning(push) 14531 | #pragma warning(disable: 4127) 14532 | #endif 14533 | 14534 | T v[N]; 14535 | evaluate_branches<T,N>::execute(v,branch_); 14536 | return invoke<T,N>::execute(*function_,v); 14537 | 14538 | #ifdef _MSC_VER 14539 | #pragma warning(pop) 14540 | #endif 14541 | } 14542 | 14543 | inline typename expression_node<T>::node_type type() const exprtk_override 14544 | { 14545 | return expression_node<T>::e_function; 14546 | } 14547 | 14548 | inline bool valid() const exprtk_override 14549 | { 14550 | return initialised_; 14551 | } 14552 | 14553 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 14554 | { 14555 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 14556 | } 14557 | 14558 | std::size_t node_depth() const exprtk_override 14559 | { 14560 | return expression_node<T>::ndb_t::template compute_node_depth<N>(branch_); 14561 | } 14562 | 14563 | template <typename T_, std::size_t BranchCount> 14564 | struct evaluate_branches 14565 | { 14566 | static inline void execute(T_ (&v)[BranchCount], const branch_t (&b)[BranchCount]) 14567 | { 14568 | for (std::size_t i = 0; i < BranchCount; ++i) 14569 | { 14570 | v[i] = b[i].first->value(); 14571 | } 14572 | } 14573 | }; 14574 | 14575 | template <typename T_> 14576 | struct evaluate_branches <T_,6> 14577 | { 14578 | static inline void execute(T_ (&v)[6], const branch_t (&b)[6]) 14579 | { 14580 | v[0] = b[0].first->value(); 14581 | v[1] = b[1].first->value(); 14582 | v[2] = b[2].first->value(); 14583 | v[3] = b[3].first->value(); 14584 | v[4] = b[4].first->value(); 14585 | v[5] = b[5].first->value(); 14586 | } 14587 | }; 14588 | 14589 | template <typename T_> 14590 | struct evaluate_branches <T_,5> 14591 | { 14592 | static inline void execute(T_ (&v)[5], const branch_t (&b)[5]) 14593 | { 14594 | v[0] = b[0].first->value(); 14595 | v[1] = b[1].first->value(); 14596 | v[2] = b[2].first->value(); 14597 | v[3] = b[3].first->value(); 14598 | v[4] = b[4].first->value(); 14599 | } 14600 | }; 14601 | 14602 | template <typename T_> 14603 | struct evaluate_branches <T_,4> 14604 | { 14605 | static inline void execute(T_ (&v)[4], const branch_t (&b)[4]) 14606 | { 14607 | v[0] = b[0].first->value(); 14608 | v[1] = b[1].first->value(); 14609 | v[2] = b[2].first->value(); 14610 | v[3] = b[3].first->value(); 14611 | } 14612 | }; 14613 | 14614 | template <typename T_> 14615 | struct evaluate_branches <T_,3> 14616 | { 14617 | static inline void execute(T_ (&v)[3], const branch_t (&b)[3]) 14618 | { 14619 | v[0] = b[0].first->value(); 14620 | v[1] = b[1].first->value(); 14621 | v[2] = b[2].first->value(); 14622 | } 14623 | }; 14624 | 14625 | template <typename T_> 14626 | struct evaluate_branches <T_,2> 14627 | { 14628 | static inline void execute(T_ (&v)[2], const branch_t (&b)[2]) 14629 | { 14630 | v[0] = b[0].first->value(); 14631 | v[1] = b[1].first->value(); 14632 | } 14633 | }; 14634 | 14635 | template <typename T_> 14636 | struct evaluate_branches <T_,1> 14637 | { 14638 | static inline void execute(T_ (&v)[1], const branch_t (&b)[1]) 14639 | { 14640 | v[0] = b[0].first->value(); 14641 | } 14642 | }; 14643 | 14644 | template <typename T_, std::size_t ParamCount> 14645 | struct invoke { static inline T execute(ifunction&, branch_t (&)[ParamCount]) { return std::numeric_limits<T_>::quiet_NaN(); } }; 14646 | 14647 | template <typename T_> 14648 | struct invoke<T_,20> 14649 | { 14650 | static inline T_ execute(ifunction& f, T_ (&v)[20]) 14651 | { 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]); } 14652 | }; 14653 | 14654 | template <typename T_> 14655 | struct invoke<T_,19> 14656 | { 14657 | static inline T_ execute(ifunction& f, T_ (&v)[19]) 14658 | { 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]); } 14659 | }; 14660 | 14661 | template <typename T_> 14662 | struct invoke<T_,18> 14663 | { 14664 | static inline T_ execute(ifunction& f, T_ (&v)[18]) 14665 | { 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]); } 14666 | }; 14667 | 14668 | template <typename T_> 14669 | struct invoke<T_,17> 14670 | { 14671 | static inline T_ execute(ifunction& f, T_ (&v)[17]) 14672 | { 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]); } 14673 | }; 14674 | 14675 | template <typename T_> 14676 | struct invoke<T_,16> 14677 | { 14678 | static inline T_ execute(ifunction& f, T_ (&v)[16]) 14679 | { 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]); } 14680 | }; 14681 | 14682 | template <typename T_> 14683 | struct invoke<T_,15> 14684 | { 14685 | static inline T_ execute(ifunction& f, T_ (&v)[15]) 14686 | { 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]); } 14687 | }; 14688 | 14689 | template <typename T_> 14690 | struct invoke<T_,14> 14691 | { 14692 | static inline T_ execute(ifunction& f, T_ (&v)[14]) 14693 | { 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]); } 14694 | }; 14695 | 14696 | template <typename T_> 14697 | struct invoke<T_,13> 14698 | { 14699 | static inline T_ execute(ifunction& f, T_ (&v)[13]) 14700 | { 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]); } 14701 | }; 14702 | 14703 | template <typename T_> 14704 | struct invoke<T_,12> 14705 | { 14706 | static inline T_ execute(ifunction& f, T_ (&v)[12]) 14707 | { 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]); } 14708 | }; 14709 | 14710 | template <typename T_> 14711 | struct invoke<T_,11> 14712 | { 14713 | static inline T_ execute(ifunction& f, T_ (&v)[11]) 14714 | { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9], v[10]); } 14715 | }; 14716 | 14717 | template <typename T_> 14718 | struct invoke<T_,10> 14719 | { 14720 | static inline T_ execute(ifunction& f, T_ (&v)[10]) 14721 | { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9]); } 14722 | }; 14723 | 14724 | template <typename T_> 14725 | struct invoke<T_,9> 14726 | { 14727 | static inline T_ execute(ifunction& f, T_ (&v)[9]) 14728 | { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8]); } 14729 | }; 14730 | 14731 | template <typename T_> 14732 | struct invoke<T_,8> 14733 | { 14734 | static inline T_ execute(ifunction& f, T_ (&v)[8]) 14735 | { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]); } 14736 | }; 14737 | 14738 | template <typename T_> 14739 | struct invoke<T_,7> 14740 | { 14741 | static inline T_ execute(ifunction& f, T_ (&v)[7]) 14742 | { return f(v[0], v[1], v[2], v[3], v[4], v[5], v[6]); } 14743 | }; 14744 | 14745 | template <typename T_> 14746 | struct invoke<T_,6> 14747 | { 14748 | static inline T_ execute(ifunction& f, T_ (&v)[6]) 14749 | { return f(v[0], v[1], v[2], v[3], v[4], v[5]); } 14750 | }; 14751 | 14752 | template <typename T_> 14753 | struct invoke<T_,5> 14754 | { 14755 | static inline T_ execute(ifunction& f, T_ (&v)[5]) 14756 | { return f(v[0], v[1], v[2], v[3], v[4]); } 14757 | }; 14758 | 14759 | template <typename T_> 14760 | struct invoke<T_,4> 14761 | { 14762 | static inline T_ execute(ifunction& f, T_ (&v)[4]) 14763 | { return f(v[0], v[1], v[2], v[3]); } 14764 | }; 14765 | 14766 | template <typename T_> 14767 | struct invoke<T_,3> 14768 | { 14769 | static inline T_ execute(ifunction& f, T_ (&v)[3]) 14770 | { return f(v[0], v[1], v[2]); } 14771 | }; 14772 | 14773 | template <typename T_> 14774 | struct invoke<T_,2> 14775 | { 14776 | static inline T_ execute(ifunction& f, T_ (&v)[2]) 14777 | { return f(v[0], v[1]); } 14778 | }; 14779 | 14780 | template <typename T_> 14781 | struct invoke<T_,1> 14782 | { 14783 | static inline T_ execute(ifunction& f, T_ (&v)[1]) 14784 | { return f(v[0]); } 14785 | }; 14786 | 14787 | private: 14788 | 14789 | ifunction* function_; 14790 | std::size_t parameter_count_; 14791 | branch_t branch_[N]; 14792 | bool initialised_; 14793 | }; 14794 | 14795 | template <typename T, typename IFunction> 14796 | class function_N_node<T,IFunction,0> exprtk_final : public expression_node<T> 14797 | { 14798 | public: 14799 | 14800 | typedef expression_node<T>* expression_ptr; 14801 | typedef IFunction ifunction; 14802 | 14803 | explicit function_N_node(ifunction* func) 14804 | : function_((0 == func->param_count) ? func : reinterpret_cast<ifunction*>(0)) 14805 | { 14806 | assert(valid()); 14807 | } 14808 | 14809 | inline bool operator <(const function_N_node<T,IFunction,0>& fn) const 14810 | { 14811 | return this < (&fn); 14812 | } 14813 | 14814 | inline T value() const exprtk_override 14815 | { 14816 | return (*function_)(); 14817 | } 14818 | 14819 | inline typename expression_node<T>::node_type type() const exprtk_override 14820 | { 14821 | return expression_node<T>::e_function; 14822 | } 14823 | 14824 | inline bool valid() const exprtk_override 14825 | { 14826 | return function_; 14827 | } 14828 | 14829 | private: 14830 | 14831 | ifunction* function_; 14832 | }; 14833 | 14834 | template <typename T, typename VarArgFunction> 14835 | class vararg_function_node exprtk_final : public expression_node<T> 14836 | { 14837 | public: 14838 | 14839 | typedef expression_node<T>* expression_ptr; 14840 | 14841 | vararg_function_node(VarArgFunction* func, 14842 | const std::vector<expression_ptr>& arg_list) 14843 | : function_(func) 14844 | , arg_list_(arg_list) 14845 | { 14846 | value_list_.resize(arg_list.size(),std::numeric_limits<T>::quiet_NaN()); 14847 | assert(valid()); 14848 | } 14849 | 14850 | inline bool operator <(const vararg_function_node<T,VarArgFunction>& fn) const 14851 | { 14852 | return this < (&fn); 14853 | } 14854 | 14855 | inline T value() const exprtk_override 14856 | { 14857 | populate_value_list(); 14858 | return (*function_)(value_list_); 14859 | } 14860 | 14861 | inline typename expression_node<T>::node_type type() const exprtk_override 14862 | { 14863 | return expression_node<T>::e_vafunction; 14864 | } 14865 | 14866 | inline bool valid() const exprtk_override 14867 | { 14868 | return function_; 14869 | } 14870 | 14871 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 14872 | { 14873 | for (std::size_t i = 0; i < arg_list_.size(); ++i) 14874 | { 14875 | if (arg_list_[i] && !details::is_variable_node(arg_list_[i])) 14876 | { 14877 | node_delete_list.push_back(&arg_list_[i]); 14878 | } 14879 | } 14880 | } 14881 | 14882 | std::size_t node_depth() const exprtk_override 14883 | { 14884 | return expression_node<T>::ndb_t::compute_node_depth(arg_list_); 14885 | } 14886 | 14887 | private: 14888 | 14889 | inline void populate_value_list() const 14890 | { 14891 | for (std::size_t i = 0; i < arg_list_.size(); ++i) 14892 | { 14893 | value_list_[i] = arg_list_[i]->value(); 14894 | } 14895 | } 14896 | 14897 | VarArgFunction* function_; 14898 | std::vector<expression_ptr> arg_list_; 14899 | mutable std::vector<T> value_list_; 14900 | }; 14901 | 14902 | template <typename T, typename GenericFunction> 14903 | class generic_function_node : public expression_node<T> 14904 | { 14905 | public: 14906 | 14907 | typedef type_store<T> type_store_t; 14908 | typedef expression_node<T>* expression_ptr; 14909 | typedef variable_node<T> variable_node_t; 14910 | typedef vector_node<T> vector_node_t; 14911 | typedef variable_node_t* variable_node_ptr_t; 14912 | typedef vector_node_t* vector_node_ptr_t; 14913 | typedef range_interface<T> range_interface_t; 14914 | typedef range_data_type<T> range_data_type_t; 14915 | typedef typename range_interface<T>::range_t range_t; 14916 | 14917 | typedef std::pair<expression_ptr,bool> branch_t; 14918 | typedef vector_holder<T>* vh_t; 14919 | typedef vector_view<T>* vecview_t; 14920 | 14921 | typedef std::vector<T> tmp_vs_t; 14922 | typedef std::vector<type_store_t> typestore_list_t; 14923 | typedef std::vector<range_data_type_t> range_list_t; 14924 | 14925 | explicit generic_function_node(const std::vector<expression_ptr>& arg_list, 14926 | GenericFunction* func = reinterpret_cast<GenericFunction*>(0)) 14927 | : function_(func) 14928 | , arg_list_(arg_list) 14929 | {} 14930 | 14931 | virtual ~generic_function_node() 14932 | { 14933 | for (std::size_t i = 0; i < vv_list_.size(); ++i) 14934 | { 14935 | vecview_t& vv = vv_list_[i]; 14936 | if (vv && typestore_list_[i].vec_data) 14937 | { 14938 | vv->remove_ref(&typestore_list_[i].vec_data); 14939 | typestore_list_[i].vec_data = 0; 14940 | } 14941 | } 14942 | } 14943 | 14944 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 14945 | { 14946 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 14947 | } 14948 | 14949 | std::size_t node_depth() const exprtk_override exprtk_final 14950 | { 14951 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 14952 | } 14953 | 14954 | virtual bool init_branches() 14955 | { 14956 | expr_as_vec1_store_.resize(arg_list_.size(), T(0) ); 14957 | typestore_list_ .resize(arg_list_.size(), type_store_t() ); 14958 | range_list_ .resize(arg_list_.size(), range_data_type_t()); 14959 | branch_ .resize(arg_list_.size(), branch_t(reinterpret_cast<expression_ptr>(0),false)); 14960 | vv_list_ .resize(arg_list_.size(), vecview_t(0)); 14961 | 14962 | for (std::size_t i = 0; i < arg_list_.size(); ++i) 14963 | { 14964 | type_store_t& ts = typestore_list_[i]; 14965 | 14966 | if (0 == arg_list_[i]) 14967 | return false; 14968 | else if (is_ivector_node(arg_list_[i])) 14969 | { 14970 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); 14971 | 14972 | if (0 == (vi = dynamic_cast<vector_interface<T>*>(arg_list_[i]))) 14973 | return false; 14974 | 14975 | ts.size = vi->size(); 14976 | ts.data = vi->vds().data(); 14977 | ts.type = type_store_t::e_vector; 14978 | 14979 | if ( 14980 | vi->vec()->vec_holder().rebaseable() && 14981 | vi->vec()->vec_holder().rebaseable_instance() 14982 | ) 14983 | { 14984 | vv_list_[i] = vi->vec()->vec_holder().rebaseable_instance(); 14985 | vv_list_[i]->set_ref(&ts.vec_data); 14986 | } 14987 | } 14988 | #ifndef exprtk_disable_string_capabilities 14989 | else if (is_generally_string_node(arg_list_[i])) 14990 | { 14991 | string_base_node<T>* sbn = reinterpret_cast<string_base_node<T>*>(0); 14992 | 14993 | if (0 == (sbn = dynamic_cast<string_base_node<T>*>(arg_list_[i]))) 14994 | return false; 14995 | 14996 | ts.size = sbn->size(); 14997 | ts.data = reinterpret_cast<void*>(const_cast<char_ptr>(sbn->base())); 14998 | ts.type = type_store_t::e_string; 14999 | 15000 | range_list_[i].data = ts.data; 15001 | range_list_[i].size = ts.size; 15002 | range_list_[i].type_size = sizeof(char); 15003 | range_list_[i].str_node = sbn; 15004 | 15005 | range_interface_t* ri = reinterpret_cast<range_interface_t*>(0); 15006 | 15007 | if (0 == (ri = dynamic_cast<range_interface_t*>(arg_list_[i]))) 15008 | return false; 15009 | 15010 | const range_t& rp = ri->range_ref(); 15011 | 15012 | if ( 15013 | rp.const_range() && 15014 | is_const_string_range_node(arg_list_[i]) 15015 | ) 15016 | { 15017 | ts.size = rp.const_size(); 15018 | ts.data = static_cast<char_ptr>(ts.data) + rp.n0_c.second; 15019 | range_list_[i].range = reinterpret_cast<range_t*>(0); 15020 | } 15021 | else 15022 | { 15023 | range_list_[i].range = &(ri->range_ref()); 15024 | range_param_list_.push_back(i); 15025 | } 15026 | } 15027 | #endif 15028 | else if (is_variable_node(arg_list_[i])) 15029 | { 15030 | variable_node_ptr_t var = variable_node_ptr_t(0); 15031 | 15032 | if (0 == (var = dynamic_cast<variable_node_ptr_t>(arg_list_[i]))) 15033 | return false; 15034 | 15035 | ts.size = 1; 15036 | ts.data = &var->ref(); 15037 | ts.type = type_store_t::e_scalar; 15038 | } 15039 | else 15040 | { 15041 | ts.size = 1; 15042 | ts.data = reinterpret_cast<void*>(&expr_as_vec1_store_[i]); 15043 | ts.type = type_store_t::e_scalar; 15044 | } 15045 | 15046 | branch_[i] = std::make_pair(arg_list_[i],branch_deletable(arg_list_[i])); 15047 | } 15048 | 15049 | return true; 15050 | } 15051 | 15052 | inline bool operator <(const generic_function_node<T,GenericFunction>& fn) const 15053 | { 15054 | return this < (&fn); 15055 | } 15056 | 15057 | inline T value() const exprtk_override 15058 | { 15059 | if (populate_value_list()) 15060 | { 15061 | typedef typename GenericFunction::parameter_list_t parameter_list_t; 15062 | 15063 | return (*function_)(parameter_list_t(typestore_list_)); 15064 | } 15065 | 15066 | return std::numeric_limits<T>::quiet_NaN(); 15067 | } 15068 | 15069 | inline typename expression_node<T>::node_type type() const exprtk_override 15070 | { 15071 | return expression_node<T>::e_genfunction; 15072 | } 15073 | 15074 | inline bool valid() const exprtk_override 15075 | { 15076 | return function_; 15077 | } 15078 | 15079 | protected: 15080 | 15081 | inline virtual bool populate_value_list() const 15082 | { 15083 | for (std::size_t i = 0; i < branch_.size(); ++i) 15084 | { 15085 | expr_as_vec1_store_[i] = branch_[i].first->value(); 15086 | } 15087 | 15088 | if (!range_param_list_.empty()) 15089 | { 15090 | assert(range_param_list_.size() <= branch_.size()); 15091 | 15092 | for (std::size_t i = 0; i < range_param_list_.size(); ++i) 15093 | { 15094 | const std::size_t index = range_param_list_[i]; 15095 | range_data_type_t& rdt = range_list_[index]; 15096 | 15097 | const range_t& rp = (*rdt.range); 15098 | std::size_t r0 = 0; 15099 | std::size_t r1 = 0; 15100 | 15101 | const std::size_t data_size = 15102 | #ifndef exprtk_disable_string_capabilities 15103 | rdt.str_node ? rdt.str_node->size() : rdt.size; 15104 | #else 15105 | rdt.size; 15106 | #endif 15107 | 15108 | if (!rp(r0, r1, data_size)) 15109 | { 15110 | return false; 15111 | } 15112 | 15113 | type_store_t& ts = typestore_list_[index]; 15114 | 15115 | ts.size = rp.cache_size(); 15116 | #ifndef exprtk_disable_string_capabilities 15117 | if (ts.type == type_store_t::e_string) 15118 | ts.data = const_cast<char_ptr>(rdt.str_node->base()) + rp.cache.first; 15119 | else 15120 | #endif 15121 | ts.data = static_cast<char_ptr>(rdt.data) + (rp.cache.first * rdt.type_size); 15122 | } 15123 | } 15124 | 15125 | return true; 15126 | } 15127 | 15128 | GenericFunction* function_; 15129 | mutable typestore_list_t typestore_list_; 15130 | 15131 | private: 15132 | 15133 | std::vector<expression_ptr> arg_list_; 15134 | std::vector<branch_t> branch_; 15135 | std::vector<vecview_t> vv_list_; 15136 | mutable tmp_vs_t expr_as_vec1_store_; 15137 | mutable range_list_t range_list_; 15138 | std::vector<std::size_t> range_param_list_; 15139 | }; 15140 | 15141 | #ifndef exprtk_disable_string_capabilities 15142 | template <typename T, typename StringFunction> 15143 | class string_function_node : public generic_function_node<T,StringFunction> 15144 | , public string_base_node<T> 15145 | , public range_interface <T> 15146 | { 15147 | public: 15148 | 15149 | typedef generic_function_node<T,StringFunction> gen_function_t; 15150 | typedef typename range_interface<T>::range_t range_t; 15151 | 15152 | string_function_node(StringFunction* func, 15153 | const std::vector<typename gen_function_t::expression_ptr>& arg_list) 15154 | : gen_function_t(arg_list,func) 15155 | { 15156 | range_.n0_c = std::make_pair<bool,std::size_t>(true,0); 15157 | range_.n1_c = std::make_pair<bool,std::size_t>(true,0); 15158 | range_.cache.first = range_.n0_c.second; 15159 | range_.cache.second = range_.n1_c.second; 15160 | assert(valid()); 15161 | } 15162 | 15163 | inline bool operator <(const string_function_node<T,StringFunction>& fn) const 15164 | { 15165 | return this < (&fn); 15166 | } 15167 | 15168 | inline T value() const exprtk_override 15169 | { 15170 | if (gen_function_t::populate_value_list()) 15171 | { 15172 | typedef typename StringFunction::parameter_list_t parameter_list_t; 15173 | 15174 | const T result = 15175 | (*gen_function_t::function_) 15176 | ( 15177 | ret_string_, 15178 | parameter_list_t(gen_function_t::typestore_list_) 15179 | ); 15180 | 15181 | range_.n1_c.second = ret_string_.size(); 15182 | range_.cache.second = range_.n1_c.second; 15183 | 15184 | return result; 15185 | } 15186 | 15187 | return std::numeric_limits<T>::quiet_NaN(); 15188 | } 15189 | 15190 | inline typename expression_node<T>::node_type type() const exprtk_override 15191 | { 15192 | return expression_node<T>::e_strfunction; 15193 | } 15194 | 15195 | inline bool valid() const exprtk_override 15196 | { 15197 | return gen_function_t::function_; 15198 | } 15199 | 15200 | std::string str() const exprtk_override 15201 | { 15202 | return ret_string_; 15203 | } 15204 | 15205 | char_cptr base() const exprtk_override 15206 | { 15207 | return &ret_string_[0]; 15208 | } 15209 | 15210 | std::size_t size() const exprtk_override 15211 | { 15212 | return ret_string_.size(); 15213 | } 15214 | 15215 | range_t& range_ref() exprtk_override 15216 | { 15217 | return range_; 15218 | } 15219 | 15220 | const range_t& range_ref() const exprtk_override 15221 | { 15222 | return range_; 15223 | } 15224 | 15225 | protected: 15226 | 15227 | mutable range_t range_; 15228 | mutable std::string ret_string_; 15229 | }; 15230 | #endif 15231 | 15232 | template <typename T, typename GenericFunction> 15233 | class multimode_genfunction_node : public generic_function_node<T,GenericFunction> 15234 | { 15235 | public: 15236 | 15237 | typedef generic_function_node<T,GenericFunction> gen_function_t; 15238 | typedef typename gen_function_t::range_t range_t; 15239 | 15240 | multimode_genfunction_node(GenericFunction* func, 15241 | const std::size_t& param_seq_index, 15242 | const std::vector<typename gen_function_t::expression_ptr>& arg_list) 15243 | : gen_function_t(arg_list,func) 15244 | , param_seq_index_(param_seq_index) 15245 | {} 15246 | 15247 | inline T value() const exprtk_override 15248 | { 15249 | assert(gen_function_t::valid()); 15250 | 15251 | if (gen_function_t::populate_value_list()) 15252 | { 15253 | typedef typename GenericFunction::parameter_list_t parameter_list_t; 15254 | 15255 | return 15256 | (*gen_function_t::function_) 15257 | ( 15258 | param_seq_index_, 15259 | parameter_list_t(gen_function_t::typestore_list_) 15260 | ); 15261 | } 15262 | 15263 | return std::numeric_limits<T>::quiet_NaN(); 15264 | } 15265 | 15266 | inline typename expression_node<T>::node_type type() const exprtk_override exprtk_final 15267 | { 15268 | return expression_node<T>::e_genfunction; 15269 | } 15270 | 15271 | private: 15272 | 15273 | std::size_t param_seq_index_; 15274 | }; 15275 | 15276 | #ifndef exprtk_disable_string_capabilities 15277 | template <typename T, typename StringFunction> 15278 | class multimode_strfunction_node exprtk_final : public string_function_node<T,StringFunction> 15279 | { 15280 | public: 15281 | 15282 | typedef string_function_node<T,StringFunction> str_function_t; 15283 | typedef typename str_function_t::range_t range_t; 15284 | 15285 | multimode_strfunction_node(StringFunction* func, 15286 | const std::size_t& param_seq_index, 15287 | const std::vector<typename str_function_t::expression_ptr>& arg_list) 15288 | : str_function_t(func,arg_list) 15289 | , param_seq_index_(param_seq_index) 15290 | {} 15291 | 15292 | inline T value() const exprtk_override 15293 | { 15294 | if (str_function_t::populate_value_list()) 15295 | { 15296 | typedef typename StringFunction::parameter_list_t parameter_list_t; 15297 | 15298 | const T result = 15299 | (*str_function_t::function_) 15300 | ( 15301 | param_seq_index_, 15302 | str_function_t::ret_string_, 15303 | parameter_list_t(str_function_t::typestore_list_) 15304 | ); 15305 | 15306 | str_function_t::range_.n1_c.second = str_function_t::ret_string_.size(); 15307 | str_function_t::range_.cache.second = str_function_t::range_.n1_c.second; 15308 | 15309 | return result; 15310 | } 15311 | 15312 | return std::numeric_limits<T>::quiet_NaN(); 15313 | } 15314 | 15315 | inline typename expression_node<T>::node_type type() const exprtk_override 15316 | { 15317 | return expression_node<T>::e_strfunction; 15318 | } 15319 | 15320 | private: 15321 | 15322 | const std::size_t param_seq_index_; 15323 | }; 15324 | #endif 15325 | 15326 | class return_exception {}; 15327 | 15328 | template <typename T> 15329 | class null_igenfunc 15330 | { 15331 | public: 15332 | 15333 | virtual ~null_igenfunc() 15334 | {} 15335 | 15336 | typedef type_store<T> generic_type; 15337 | typedef typename generic_type::parameter_list parameter_list_t; 15338 | 15339 | inline virtual T operator() (parameter_list_t) 15340 | { 15341 | return std::numeric_limits<T>::quiet_NaN(); 15342 | } 15343 | }; 15344 | 15345 | #ifndef exprtk_disable_return_statement 15346 | template <typename T> 15347 | class return_node exprtk_final : public generic_function_node<T,null_igenfunc<T> > 15348 | { 15349 | public: 15350 | 15351 | typedef results_context<T> results_context_t; 15352 | typedef null_igenfunc<T> igeneric_function_t; 15353 | typedef igeneric_function_t* igeneric_function_ptr; 15354 | typedef generic_function_node<T,igeneric_function_t> gen_function_t; 15355 | 15356 | return_node(const std::vector<typename gen_function_t::expression_ptr>& arg_list, 15357 | results_context_t& rc) 15358 | : gen_function_t (arg_list) 15359 | , results_context_(&rc) 15360 | { 15361 | assert(valid()); 15362 | } 15363 | 15364 | inline T value() const exprtk_override 15365 | { 15366 | if (gen_function_t::populate_value_list()) 15367 | { 15368 | typedef typename type_store<T>::parameter_list parameter_list_t; 15369 | 15370 | results_context_-> 15371 | assign(parameter_list_t(gen_function_t::typestore_list_)); 15372 | 15373 | throw return_exception(); 15374 | } 15375 | 15376 | return std::numeric_limits<T>::quiet_NaN(); 15377 | } 15378 | 15379 | inline typename expression_node<T>::node_type type() const exprtk_override 15380 | { 15381 | return expression_node<T>::e_return; 15382 | } 15383 | 15384 | inline bool valid() const exprtk_override 15385 | { 15386 | return results_context_; 15387 | } 15388 | 15389 | private: 15390 | 15391 | results_context_t* results_context_; 15392 | }; 15393 | 15394 | template <typename T> 15395 | class return_envelope_node exprtk_final : public expression_node<T> 15396 | { 15397 | public: 15398 | 15399 | typedef expression_node<T>* expression_ptr; 15400 | typedef results_context<T> results_context_t; 15401 | typedef std::pair<expression_ptr,bool> branch_t; 15402 | 15403 | return_envelope_node(expression_ptr body, results_context_t& rc) 15404 | : results_context_(&rc ) 15405 | , return_invoked_ (false) 15406 | { 15407 | construct_branch_pair(body_, body); 15408 | assert(valid()); 15409 | } 15410 | 15411 | inline T value() const exprtk_override 15412 | { 15413 | try 15414 | { 15415 | return_invoked_ = false; 15416 | results_context_->clear(); 15417 | 15418 | return body_.first->value(); 15419 | } 15420 | catch(const return_exception&) 15421 | { 15422 | return_invoked_ = true; 15423 | 15424 | return std::numeric_limits<T>::quiet_NaN(); 15425 | } 15426 | } 15427 | 15428 | inline typename expression_node<T>::node_type type() const exprtk_override 15429 | { 15430 | return expression_node<T>::e_retenv; 15431 | } 15432 | 15433 | inline bool valid() const exprtk_override 15434 | { 15435 | return results_context_ && body_.first; 15436 | } 15437 | 15438 | inline bool* retinvk_ptr() 15439 | { 15440 | return &return_invoked_; 15441 | } 15442 | 15443 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 15444 | { 15445 | expression_node<T>::ndb_t::collect(body_, node_delete_list); 15446 | } 15447 | 15448 | std::size_t node_depth() const exprtk_override 15449 | { 15450 | return expression_node<T>::ndb_t::compute_node_depth(body_); 15451 | } 15452 | 15453 | private: 15454 | 15455 | results_context_t* results_context_; 15456 | mutable bool return_invoked_; 15457 | branch_t body_; 15458 | }; 15459 | #endif 15460 | 15461 | #define exprtk_define_unary_op(OpName) \ 15462 | template <typename T> \ 15463 | struct OpName##_op \ 15464 | { \ 15465 | typedef typename functor_t<T>::Type Type; \ 15466 | typedef typename expression_node<T>::node_type node_t; \ 15467 | \ 15468 | static inline T process(Type v) \ 15469 | { \ 15470 | return numeric:: OpName (v); \ 15471 | } \ 15472 | \ 15473 | static inline node_t type() \ 15474 | { \ 15475 | return expression_node<T>::e_##OpName; \ 15476 | } \ 15477 | \ 15478 | static inline details::operator_type operation() \ 15479 | { \ 15480 | return details::e_##OpName; \ 15481 | } \ 15482 | }; \ 15483 | 15484 | exprtk_define_unary_op(abs ) 15485 | exprtk_define_unary_op(acos ) 15486 | exprtk_define_unary_op(acosh) 15487 | exprtk_define_unary_op(asin ) 15488 | exprtk_define_unary_op(asinh) 15489 | exprtk_define_unary_op(atan ) 15490 | exprtk_define_unary_op(atanh) 15491 | exprtk_define_unary_op(ceil ) 15492 | exprtk_define_unary_op(cos ) 15493 | exprtk_define_unary_op(cosh ) 15494 | exprtk_define_unary_op(cot ) 15495 | exprtk_define_unary_op(csc ) 15496 | exprtk_define_unary_op(d2g ) 15497 | exprtk_define_unary_op(d2r ) 15498 | exprtk_define_unary_op(erf ) 15499 | exprtk_define_unary_op(erfc ) 15500 | exprtk_define_unary_op(exp ) 15501 | exprtk_define_unary_op(expm1) 15502 | exprtk_define_unary_op(floor) 15503 | exprtk_define_unary_op(frac ) 15504 | exprtk_define_unary_op(g2d ) 15505 | exprtk_define_unary_op(log ) 15506 | exprtk_define_unary_op(log10) 15507 | exprtk_define_unary_op(log2 ) 15508 | exprtk_define_unary_op(log1p) 15509 | exprtk_define_unary_op(ncdf ) 15510 | exprtk_define_unary_op(neg ) 15511 | exprtk_define_unary_op(notl ) 15512 | exprtk_define_unary_op(pos ) 15513 | exprtk_define_unary_op(r2d ) 15514 | exprtk_define_unary_op(round) 15515 | exprtk_define_unary_op(sec ) 15516 | exprtk_define_unary_op(sgn ) 15517 | exprtk_define_unary_op(sin ) 15518 | exprtk_define_unary_op(sinc ) 15519 | exprtk_define_unary_op(sinh ) 15520 | exprtk_define_unary_op(sqrt ) 15521 | exprtk_define_unary_op(tan ) 15522 | exprtk_define_unary_op(tanh ) 15523 | exprtk_define_unary_op(trunc) 15524 | #undef exprtk_define_unary_op 15525 | 15526 | template <typename T> 15527 | struct opr_base 15528 | { 15529 | typedef typename details::functor_t<T>::Type Type; 15530 | typedef typename details::functor_t<T>::RefType RefType; 15531 | typedef typename details::functor_t<T> functor_t; 15532 | typedef typename functor_t::qfunc_t quaternary_functor_t; 15533 | typedef typename functor_t::tfunc_t trinary_functor_t; 15534 | typedef typename functor_t::bfunc_t binary_functor_t; 15535 | typedef typename functor_t::ufunc_t unary_functor_t; 15536 | }; 15537 | 15538 | template <typename T> 15539 | struct add_op : public opr_base<T> 15540 | { 15541 | typedef typename opr_base<T>::Type Type; 15542 | typedef typename opr_base<T>::RefType RefType; 15543 | 15544 | static inline T process(Type t1, Type t2) { return t1 + t2; } 15545 | static inline T process(Type t1, Type t2, Type t3) { return t1 + t2 + t3; } 15546 | static inline void assign(RefType t1, Type t2) { t1 += t2; } 15547 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_add; } 15548 | static inline details::operator_type operation() { return details::e_add; } 15549 | }; 15550 | 15551 | template <typename T> 15552 | struct mul_op : public opr_base<T> 15553 | { 15554 | typedef typename opr_base<T>::Type Type; 15555 | typedef typename opr_base<T>::RefType RefType; 15556 | 15557 | static inline T process(Type t1, Type t2) { return t1 * t2; } 15558 | static inline T process(Type t1, Type t2, Type t3) { return t1 * t2 * t3; } 15559 | static inline void assign(RefType t1, Type t2) { t1 *= t2; } 15560 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_mul; } 15561 | static inline details::operator_type operation() { return details::e_mul; } 15562 | }; 15563 | 15564 | template <typename T> 15565 | struct sub_op : public opr_base<T> 15566 | { 15567 | typedef typename opr_base<T>::Type Type; 15568 | typedef typename opr_base<T>::RefType RefType; 15569 | 15570 | static inline T process(Type t1, Type t2) { return t1 - t2; } 15571 | static inline T process(Type t1, Type t2, Type t3) { return t1 - t2 - t3; } 15572 | static inline void assign(RefType t1, Type t2) { t1 -= t2; } 15573 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_sub; } 15574 | static inline details::operator_type operation() { return details::e_sub; } 15575 | }; 15576 | 15577 | template <typename T> 15578 | struct div_op : public opr_base<T> 15579 | { 15580 | typedef typename opr_base<T>::Type Type; 15581 | typedef typename opr_base<T>::RefType RefType; 15582 | 15583 | static inline T process(Type t1, Type t2) { return t1 / t2; } 15584 | static inline T process(Type t1, Type t2, Type t3) { return t1 / t2 / t3; } 15585 | static inline void assign(RefType t1, Type t2) { t1 /= t2; } 15586 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_div; } 15587 | static inline details::operator_type operation() { return details::e_div; } 15588 | }; 15589 | 15590 | template <typename T> 15591 | struct mod_op : public opr_base<T> 15592 | { 15593 | typedef typename opr_base<T>::Type Type; 15594 | typedef typename opr_base<T>::RefType RefType; 15595 | 15596 | static inline T process(Type t1, Type t2) { return numeric::modulus<T>(t1,t2); } 15597 | static inline void assign(RefType t1, Type t2) { t1 = numeric::modulus<T>(t1,t2); } 15598 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_mod; } 15599 | static inline details::operator_type operation() { return details::e_mod; } 15600 | }; 15601 | 15602 | template <typename T> 15603 | struct pow_op : public opr_base<T> 15604 | { 15605 | typedef typename opr_base<T>::Type Type; 15606 | typedef typename opr_base<T>::RefType RefType; 15607 | 15608 | static inline T process(Type t1, Type t2) { return numeric::pow<T>(t1,t2); } 15609 | static inline void assign(RefType t1, Type t2) { t1 = numeric::pow<T>(t1,t2); } 15610 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_pow; } 15611 | static inline details::operator_type operation() { return details::e_pow; } 15612 | }; 15613 | 15614 | template <typename T> 15615 | struct lt_op : public opr_base<T> 15616 | { 15617 | typedef typename opr_base<T>::Type Type; 15618 | 15619 | static inline T process(Type t1, Type t2) { return ((t1 < t2) ? T(1) : T(0)); } 15620 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 < t2) ? T(1) : T(0)); } 15621 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_lt; } 15622 | static inline details::operator_type operation() { return details::e_lt; } 15623 | }; 15624 | 15625 | template <typename T> 15626 | struct lte_op : public opr_base<T> 15627 | { 15628 | typedef typename opr_base<T>::Type Type; 15629 | 15630 | static inline T process(Type t1, Type t2) { return ((t1 <= t2) ? T(1) : T(0)); } 15631 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 <= t2) ? T(1) : T(0)); } 15632 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_lte; } 15633 | static inline details::operator_type operation() { return details::e_lte; } 15634 | }; 15635 | 15636 | template <typename T> 15637 | struct gt_op : public opr_base<T> 15638 | { 15639 | typedef typename opr_base<T>::Type Type; 15640 | 15641 | static inline T process(Type t1, Type t2) { return ((t1 > t2) ? T(1) : T(0)); } 15642 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 > t2) ? T(1) : T(0)); } 15643 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_gt; } 15644 | static inline details::operator_type operation() { return details::e_gt; } 15645 | }; 15646 | 15647 | template <typename T> 15648 | struct gte_op : public opr_base<T> 15649 | { 15650 | typedef typename opr_base<T>::Type Type; 15651 | 15652 | static inline T process(Type t1, Type t2) { return ((t1 >= t2) ? T(1) : T(0)); } 15653 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 >= t2) ? T(1) : T(0)); } 15654 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_gte; } 15655 | static inline details::operator_type operation() { return details::e_gte; } 15656 | }; 15657 | 15658 | template <typename T> 15659 | struct eq_op : public opr_base<T> 15660 | { 15661 | typedef typename opr_base<T>::Type Type; 15662 | static inline T process(Type t1, Type t2) { return (std::equal_to<T>()(t1,t2) ? T(1) : T(0)); } 15663 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 == t2) ? T(1) : T(0)); } 15664 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_eq; } 15665 | static inline details::operator_type operation() { return details::e_eq; } 15666 | }; 15667 | 15668 | template <typename T> 15669 | struct equal_op : public opr_base<T> 15670 | { 15671 | typedef typename opr_base<T>::Type Type; 15672 | 15673 | static inline T process(Type t1, Type t2) { return numeric::equal(t1,t2); } 15674 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 == t2) ? T(1) : T(0)); } 15675 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_eq; } 15676 | static inline details::operator_type operation() { return details::e_equal; } 15677 | }; 15678 | 15679 | template <typename T> 15680 | struct ne_op : public opr_base<T> 15681 | { 15682 | typedef typename opr_base<T>::Type Type; 15683 | 15684 | static inline T process(Type t1, Type t2) { return (std::not_equal_to<T>()(t1,t2) ? T(1) : T(0)); } 15685 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 != t2) ? T(1) : T(0)); } 15686 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_ne; } 15687 | static inline details::operator_type operation() { return details::e_ne; } 15688 | }; 15689 | 15690 | template <typename T> 15691 | struct and_op : public opr_base<T> 15692 | { 15693 | typedef typename opr_base<T>::Type Type; 15694 | 15695 | static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(1) : T(0); } 15696 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_and; } 15697 | static inline details::operator_type operation() { return details::e_and; } 15698 | }; 15699 | 15700 | template <typename T> 15701 | struct nand_op : public opr_base<T> 15702 | { 15703 | typedef typename opr_base<T>::Type Type; 15704 | 15705 | static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(0) : T(1); } 15706 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nand; } 15707 | static inline details::operator_type operation() { return details::e_nand; } 15708 | }; 15709 | 15710 | template <typename T> 15711 | struct or_op : public opr_base<T> 15712 | { 15713 | typedef typename opr_base<T>::Type Type; 15714 | 15715 | static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(1) : T(0); } 15716 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_or; } 15717 | static inline details::operator_type operation() { return details::e_or; } 15718 | }; 15719 | 15720 | template <typename T> 15721 | struct nor_op : public opr_base<T> 15722 | { 15723 | typedef typename opr_base<T>::Type Type; 15724 | 15725 | static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(0) : T(1); } 15726 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; } 15727 | static inline details::operator_type operation() { return details::e_nor; } 15728 | }; 15729 | 15730 | template <typename T> 15731 | struct xor_op : public opr_base<T> 15732 | { 15733 | typedef typename opr_base<T>::Type Type; 15734 | 15735 | static inline T process(Type t1, Type t2) { return numeric::xor_opr<T>(t1,t2); } 15736 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; } 15737 | static inline details::operator_type operation() { return details::e_xor; } 15738 | }; 15739 | 15740 | template <typename T> 15741 | struct xnor_op : public opr_base<T> 15742 | { 15743 | typedef typename opr_base<T>::Type Type; 15744 | 15745 | static inline T process(Type t1, Type t2) { return numeric::xnor_opr<T>(t1,t2); } 15746 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; } 15747 | static inline details::operator_type operation() { return details::e_xnor; } 15748 | }; 15749 | 15750 | template <typename T> 15751 | struct in_op : public opr_base<T> 15752 | { 15753 | typedef typename opr_base<T>::Type Type; 15754 | 15755 | static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); } 15756 | static inline T process(const std::string& t1, const std::string& t2) { return ((std::string::npos != t2.find(t1)) ? T(1) : T(0)); } 15757 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_in; } 15758 | static inline details::operator_type operation() { return details::e_in; } 15759 | }; 15760 | 15761 | template <typename T> 15762 | struct like_op : public opr_base<T> 15763 | { 15764 | typedef typename opr_base<T>::Type Type; 15765 | 15766 | static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); } 15767 | static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_match(t2,t1) ? T(1) : T(0)); } 15768 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_like; } 15769 | static inline details::operator_type operation() { return details::e_like; } 15770 | }; 15771 | 15772 | template <typename T> 15773 | struct ilike_op : public opr_base<T> 15774 | { 15775 | typedef typename opr_base<T>::Type Type; 15776 | 15777 | static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); } 15778 | static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_imatch(t2,t1) ? T(1) : T(0)); } 15779 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_ilike; } 15780 | static inline details::operator_type operation() { return details::e_ilike; } 15781 | }; 15782 | 15783 | template <typename T> 15784 | struct inrange_op : public opr_base<T> 15785 | { 15786 | typedef typename opr_base<T>::Type Type; 15787 | 15788 | static inline T process(const T& t0, const T& t1, const T& t2) { return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0); } 15789 | static inline T process(const std::string& t0, const std::string& t1, const std::string& t2) 15790 | { 15791 | return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0); 15792 | } 15793 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_inranges; } 15794 | static inline details::operator_type operation() { return details::e_inrange; } 15795 | }; 15796 | 15797 | template <typename T> 15798 | inline T value(details::expression_node<T>* n) 15799 | { 15800 | return n->value(); 15801 | } 15802 | 15803 | template <typename T> 15804 | inline T value(std::pair<details::expression_node<T>*,bool> n) 15805 | { 15806 | return n.first->value(); 15807 | } 15808 | 15809 | template <typename T> 15810 | inline T value(const T* t) 15811 | { 15812 | return (*t); 15813 | } 15814 | 15815 | template <typename T> 15816 | inline T value(const T& t) 15817 | { 15818 | return t; 15819 | } 15820 | 15821 | template <typename T> 15822 | struct vararg_add_op exprtk_final : public opr_base<T> 15823 | { 15824 | typedef typename opr_base<T>::Type Type; 15825 | 15826 | template <typename Type, 15827 | typename Allocator, 15828 | template <typename, typename> class Sequence> 15829 | static inline T process(const Sequence<Type,Allocator>& arg_list) 15830 | { 15831 | switch (arg_list.size()) 15832 | { 15833 | case 0 : return T(0); 15834 | case 1 : return process_1(arg_list); 15835 | case 2 : return process_2(arg_list); 15836 | case 3 : return process_3(arg_list); 15837 | case 4 : return process_4(arg_list); 15838 | case 5 : return process_5(arg_list); 15839 | default : 15840 | { 15841 | T result = T(0); 15842 | 15843 | for (std::size_t i = 0; i < arg_list.size(); ++i) 15844 | { 15845 | result += value(arg_list[i]); 15846 | } 15847 | 15848 | return result; 15849 | } 15850 | } 15851 | } 15852 | 15853 | template <typename Sequence> 15854 | static inline T process_1(const Sequence& arg_list) 15855 | { 15856 | return value(arg_list[0]); 15857 | } 15858 | 15859 | template <typename Sequence> 15860 | static inline T process_2(const Sequence& arg_list) 15861 | { 15862 | return value(arg_list[0]) + value(arg_list[1]); 15863 | } 15864 | 15865 | template <typename Sequence> 15866 | static inline T process_3(const Sequence& arg_list) 15867 | { 15868 | return value(arg_list[0]) + value(arg_list[1]) + 15869 | value(arg_list[2]) ; 15870 | } 15871 | 15872 | template <typename Sequence> 15873 | static inline T process_4(const Sequence& arg_list) 15874 | { 15875 | return value(arg_list[0]) + value(arg_list[1]) + 15876 | value(arg_list[2]) + value(arg_list[3]) ; 15877 | } 15878 | 15879 | template <typename Sequence> 15880 | static inline T process_5(const Sequence& arg_list) 15881 | { 15882 | return value(arg_list[0]) + value(arg_list[1]) + 15883 | value(arg_list[2]) + value(arg_list[3]) + 15884 | value(arg_list[4]) ; 15885 | } 15886 | }; 15887 | 15888 | template <typename T> 15889 | struct vararg_mul_op exprtk_final : public opr_base<T> 15890 | { 15891 | typedef typename opr_base<T>::Type Type; 15892 | 15893 | template <typename Type, 15894 | typename Allocator, 15895 | template <typename, typename> class Sequence> 15896 | static inline T process(const Sequence<Type,Allocator>& arg_list) 15897 | { 15898 | switch (arg_list.size()) 15899 | { 15900 | case 0 : return T(0); 15901 | case 1 : return process_1(arg_list); 15902 | case 2 : return process_2(arg_list); 15903 | case 3 : return process_3(arg_list); 15904 | case 4 : return process_4(arg_list); 15905 | case 5 : return process_5(arg_list); 15906 | default : 15907 | { 15908 | T result = T(value(arg_list[0])); 15909 | 15910 | for (std::size_t i = 1; i < arg_list.size(); ++i) 15911 | { 15912 | result *= value(arg_list[i]); 15913 | } 15914 | 15915 | return result; 15916 | } 15917 | } 15918 | } 15919 | 15920 | template <typename Sequence> 15921 | static inline T process_1(const Sequence& arg_list) 15922 | { 15923 | return value(arg_list[0]); 15924 | } 15925 | 15926 | template <typename Sequence> 15927 | static inline T process_2(const Sequence& arg_list) 15928 | { 15929 | return value(arg_list[0]) * value(arg_list[1]); 15930 | } 15931 | 15932 | template <typename Sequence> 15933 | static inline T process_3(const Sequence& arg_list) 15934 | { 15935 | return value(arg_list[0]) * value(arg_list[1]) * 15936 | value(arg_list[2]) ; 15937 | } 15938 | 15939 | template <typename Sequence> 15940 | static inline T process_4(const Sequence& arg_list) 15941 | { 15942 | return value(arg_list[0]) * value(arg_list[1]) * 15943 | value(arg_list[2]) * value(arg_list[3]) ; 15944 | } 15945 | 15946 | template <typename Sequence> 15947 | static inline T process_5(const Sequence& arg_list) 15948 | { 15949 | return value(arg_list[0]) * value(arg_list[1]) * 15950 | value(arg_list[2]) * value(arg_list[3]) * 15951 | value(arg_list[4]) ; 15952 | } 15953 | }; 15954 | 15955 | template <typename T> 15956 | struct vararg_avg_op exprtk_final : public opr_base<T> 15957 | { 15958 | typedef typename opr_base<T>::Type Type; 15959 | 15960 | template <typename Type, 15961 | typename Allocator, 15962 | template <typename, typename> class Sequence> 15963 | static inline T process(const Sequence<Type,Allocator>& arg_list) 15964 | { 15965 | switch (arg_list.size()) 15966 | { 15967 | case 0 : return T(0); 15968 | case 1 : return process_1(arg_list); 15969 | case 2 : return process_2(arg_list); 15970 | case 3 : return process_3(arg_list); 15971 | case 4 : return process_4(arg_list); 15972 | case 5 : return process_5(arg_list); 15973 | default : return vararg_add_op<T>::process(arg_list) / T(arg_list.size()); 15974 | } 15975 | } 15976 | 15977 | template <typename Sequence> 15978 | static inline T process_1(const Sequence& arg_list) 15979 | { 15980 | return value(arg_list[0]); 15981 | } 15982 | 15983 | template <typename Sequence> 15984 | static inline T process_2(const Sequence& arg_list) 15985 | { 15986 | return (value(arg_list[0]) + value(arg_list[1])) / T(2); 15987 | } 15988 | 15989 | template <typename Sequence> 15990 | static inline T process_3(const Sequence& arg_list) 15991 | { 15992 | return (value(arg_list[0]) + value(arg_list[1]) + value(arg_list[2])) / T(3); 15993 | } 15994 | 15995 | template <typename Sequence> 15996 | static inline T process_4(const Sequence& arg_list) 15997 | { 15998 | return (value(arg_list[0]) + value(arg_list[1]) + 15999 | value(arg_list[2]) + value(arg_list[3])) / T(4); 16000 | } 16001 | 16002 | template <typename Sequence> 16003 | static inline T process_5(const Sequence& arg_list) 16004 | { 16005 | return (value(arg_list[0]) + value(arg_list[1]) + 16006 | value(arg_list[2]) + value(arg_list[3]) + 16007 | value(arg_list[4])) / T(5); 16008 | } 16009 | }; 16010 | 16011 | template <typename T> 16012 | struct vararg_min_op exprtk_final : public opr_base<T> 16013 | { 16014 | typedef typename opr_base<T>::Type Type; 16015 | 16016 | template <typename Type, 16017 | typename Allocator, 16018 | template <typename, typename> class Sequence> 16019 | static inline T process(const Sequence<Type,Allocator>& arg_list) 16020 | { 16021 | switch (arg_list.size()) 16022 | { 16023 | case 0 : return T(0); 16024 | case 1 : return process_1(arg_list); 16025 | case 2 : return process_2(arg_list); 16026 | case 3 : return process_3(arg_list); 16027 | case 4 : return process_4(arg_list); 16028 | case 5 : return process_5(arg_list); 16029 | default : 16030 | { 16031 | T result = T(value(arg_list[0])); 16032 | 16033 | for (std::size_t i = 1; i < arg_list.size(); ++i) 16034 | { 16035 | const T v = value(arg_list[i]); 16036 | 16037 | if (v < result) 16038 | result = v; 16039 | } 16040 | 16041 | return result; 16042 | } 16043 | } 16044 | } 16045 | 16046 | template <typename Sequence> 16047 | static inline T process_1(const Sequence& arg_list) 16048 | { 16049 | return value(arg_list[0]); 16050 | } 16051 | 16052 | template <typename Sequence> 16053 | static inline T process_2(const Sequence& arg_list) 16054 | { 16055 | return std::min<T>(value(arg_list[0]),value(arg_list[1])); 16056 | } 16057 | 16058 | template <typename Sequence> 16059 | static inline T process_3(const Sequence& arg_list) 16060 | { 16061 | return std::min<T>(std::min<T>(value(arg_list[0]),value(arg_list[1])),value(arg_list[2])); 16062 | } 16063 | 16064 | template <typename Sequence> 16065 | static inline T process_4(const Sequence& arg_list) 16066 | { 16067 | return std::min<T>( 16068 | std::min<T>(value(arg_list[0]), value(arg_list[1])), 16069 | std::min<T>(value(arg_list[2]), value(arg_list[3]))); 16070 | } 16071 | 16072 | template <typename Sequence> 16073 | static inline T process_5(const Sequence& arg_list) 16074 | { 16075 | return std::min<T>( 16076 | std::min<T>(std::min<T>(value(arg_list[0]), value(arg_list[1])), 16077 | std::min<T>(value(arg_list[2]), value(arg_list[3]))), 16078 | value(arg_list[4])); 16079 | } 16080 | }; 16081 | 16082 | template <typename T> 16083 | struct vararg_max_op exprtk_final : public opr_base<T> 16084 | { 16085 | typedef typename opr_base<T>::Type Type; 16086 | 16087 | template <typename Type, 16088 | typename Allocator, 16089 | template <typename, typename> class Sequence> 16090 | static inline T process(const Sequence<Type,Allocator>& arg_list) 16091 | { 16092 | switch (arg_list.size()) 16093 | { 16094 | case 0 : return T(0); 16095 | case 1 : return process_1(arg_list); 16096 | case 2 : return process_2(arg_list); 16097 | case 3 : return process_3(arg_list); 16098 | case 4 : return process_4(arg_list); 16099 | case 5 : return process_5(arg_list); 16100 | default : 16101 | { 16102 | T result = T(value(arg_list[0])); 16103 | 16104 | for (std::size_t i = 1; i < arg_list.size(); ++i) 16105 | { 16106 | const T v = value(arg_list[i]); 16107 | 16108 | if (v > result) 16109 | result = v; 16110 | } 16111 | 16112 | return result; 16113 | } 16114 | } 16115 | } 16116 | 16117 | template <typename Sequence> 16118 | static inline T process_1(const Sequence& arg_list) 16119 | { 16120 | return value(arg_list[0]); 16121 | } 16122 | 16123 | template <typename Sequence> 16124 | static inline T process_2(const Sequence& arg_list) 16125 | { 16126 | return std::max<T>(value(arg_list[0]),value(arg_list[1])); 16127 | } 16128 | 16129 | template <typename Sequence> 16130 | static inline T process_3(const Sequence& arg_list) 16131 | { 16132 | return std::max<T>(std::max<T>(value(arg_list[0]),value(arg_list[1])),value(arg_list[2])); 16133 | } 16134 | 16135 | template <typename Sequence> 16136 | static inline T process_4(const Sequence& arg_list) 16137 | { 16138 | return std::max<T>( 16139 | std::max<T>(value(arg_list[0]), value(arg_list[1])), 16140 | std::max<T>(value(arg_list[2]), value(arg_list[3]))); 16141 | } 16142 | 16143 | template <typename Sequence> 16144 | static inline T process_5(const Sequence& arg_list) 16145 | { 16146 | return std::max<T>( 16147 | std::max<T>(std::max<T>(value(arg_list[0]), value(arg_list[1])), 16148 | std::max<T>(value(arg_list[2]), value(arg_list[3]))), 16149 | value(arg_list[4])); 16150 | } 16151 | }; 16152 | 16153 | template <typename T> 16154 | struct vararg_mand_op exprtk_final : public opr_base<T> 16155 | { 16156 | typedef typename opr_base<T>::Type Type; 16157 | 16158 | template <typename Type, 16159 | typename Allocator, 16160 | template <typename, typename> class Sequence> 16161 | static inline T process(const Sequence<Type,Allocator>& arg_list) 16162 | { 16163 | switch (arg_list.size()) 16164 | { 16165 | case 1 : return process_1(arg_list); 16166 | case 2 : return process_2(arg_list); 16167 | case 3 : return process_3(arg_list); 16168 | case 4 : return process_4(arg_list); 16169 | case 5 : return process_5(arg_list); 16170 | default : 16171 | { 16172 | for (std::size_t i = 0; i < arg_list.size(); ++i) 16173 | { 16174 | if (std::equal_to<T>()(T(0), value(arg_list[i]))) 16175 | return T(0); 16176 | } 16177 | 16178 | return T(1); 16179 | } 16180 | } 16181 | } 16182 | 16183 | template <typename Sequence> 16184 | static inline T process_1(const Sequence& arg_list) 16185 | { 16186 | return std::not_equal_to<T>() 16187 | (T(0), value(arg_list[0])) ? T(1) : T(0); 16188 | } 16189 | 16190 | template <typename Sequence> 16191 | static inline T process_2(const Sequence& arg_list) 16192 | { 16193 | return ( 16194 | std::not_equal_to<T>()(T(0), value(arg_list[0])) && 16195 | std::not_equal_to<T>()(T(0), value(arg_list[1])) 16196 | ) ? T(1) : T(0); 16197 | } 16198 | 16199 | template <typename Sequence> 16200 | static inline T process_3(const Sequence& arg_list) 16201 | { 16202 | return ( 16203 | std::not_equal_to<T>()(T(0), value(arg_list[0])) && 16204 | std::not_equal_to<T>()(T(0), value(arg_list[1])) && 16205 | std::not_equal_to<T>()(T(0), value(arg_list[2])) 16206 | ) ? T(1) : T(0); 16207 | } 16208 | 16209 | template <typename Sequence> 16210 | static inline T process_4(const Sequence& arg_list) 16211 | { 16212 | return ( 16213 | std::not_equal_to<T>()(T(0), value(arg_list[0])) && 16214 | std::not_equal_to<T>()(T(0), value(arg_list[1])) && 16215 | std::not_equal_to<T>()(T(0), value(arg_list[2])) && 16216 | std::not_equal_to<T>()(T(0), value(arg_list[3])) 16217 | ) ? T(1) : T(0); 16218 | } 16219 | 16220 | template <typename Sequence> 16221 | static inline T process_5(const Sequence& arg_list) 16222 | { 16223 | return ( 16224 | std::not_equal_to<T>()(T(0), value(arg_list[0])) && 16225 | std::not_equal_to<T>()(T(0), value(arg_list[1])) && 16226 | std::not_equal_to<T>()(T(0), value(arg_list[2])) && 16227 | std::not_equal_to<T>()(T(0), value(arg_list[3])) && 16228 | std::not_equal_to<T>()(T(0), value(arg_list[4])) 16229 | ) ? T(1) : T(0); 16230 | } 16231 | }; 16232 | 16233 | template <typename T> 16234 | struct vararg_mor_op exprtk_final : public opr_base<T> 16235 | { 16236 | typedef typename opr_base<T>::Type Type; 16237 | 16238 | template <typename Type, 16239 | typename Allocator, 16240 | template <typename, typename> class Sequence> 16241 | static inline T process(const Sequence<Type,Allocator>& arg_list) 16242 | { 16243 | switch (arg_list.size()) 16244 | { 16245 | case 1 : return process_1(arg_list); 16246 | case 2 : return process_2(arg_list); 16247 | case 3 : return process_3(arg_list); 16248 | case 4 : return process_4(arg_list); 16249 | case 5 : return process_5(arg_list); 16250 | default : 16251 | { 16252 | for (std::size_t i = 0; i < arg_list.size(); ++i) 16253 | { 16254 | if (std::not_equal_to<T>()(T(0), value(arg_list[i]))) 16255 | return T(1); 16256 | } 16257 | 16258 | return T(0); 16259 | } 16260 | } 16261 | } 16262 | 16263 | template <typename Sequence> 16264 | static inline T process_1(const Sequence& arg_list) 16265 | { 16266 | return std::not_equal_to<T>() 16267 | (T(0), value(arg_list[0])) ? T(1) : T(0); 16268 | } 16269 | 16270 | template <typename Sequence> 16271 | static inline T process_2(const Sequence& arg_list) 16272 | { 16273 | return ( 16274 | std::not_equal_to<T>()(T(0), value(arg_list[0])) || 16275 | std::not_equal_to<T>()(T(0), value(arg_list[1])) 16276 | ) ? T(1) : T(0); 16277 | } 16278 | 16279 | template <typename Sequence> 16280 | static inline T process_3(const Sequence& arg_list) 16281 | { 16282 | return ( 16283 | std::not_equal_to<T>()(T(0), value(arg_list[0])) || 16284 | std::not_equal_to<T>()(T(0), value(arg_list[1])) || 16285 | std::not_equal_to<T>()(T(0), value(arg_list[2])) 16286 | ) ? T(1) : T(0); 16287 | } 16288 | 16289 | template <typename Sequence> 16290 | static inline T process_4(const Sequence& arg_list) 16291 | { 16292 | return ( 16293 | std::not_equal_to<T>()(T(0), value(arg_list[0])) || 16294 | std::not_equal_to<T>()(T(0), value(arg_list[1])) || 16295 | std::not_equal_to<T>()(T(0), value(arg_list[2])) || 16296 | std::not_equal_to<T>()(T(0), value(arg_list[3])) 16297 | ) ? T(1) : T(0); 16298 | } 16299 | 16300 | template <typename Sequence> 16301 | static inline T process_5(const Sequence& arg_list) 16302 | { 16303 | return ( 16304 | std::not_equal_to<T>()(T(0), value(arg_list[0])) || 16305 | std::not_equal_to<T>()(T(0), value(arg_list[1])) || 16306 | std::not_equal_to<T>()(T(0), value(arg_list[2])) || 16307 | std::not_equal_to<T>()(T(0), value(arg_list[3])) || 16308 | std::not_equal_to<T>()(T(0), value(arg_list[4])) 16309 | ) ? T(1) : T(0); 16310 | } 16311 | }; 16312 | 16313 | template <typename T> 16314 | struct vararg_multi_op exprtk_final : public opr_base<T> 16315 | { 16316 | typedef typename opr_base<T>::Type Type; 16317 | 16318 | template <typename Type, 16319 | typename Allocator, 16320 | template <typename, typename> class Sequence> 16321 | static inline T process(const Sequence<Type,Allocator>& arg_list) 16322 | { 16323 | switch (arg_list.size()) 16324 | { 16325 | case 0 : return std::numeric_limits<T>::quiet_NaN(); 16326 | case 1 : return process_1(arg_list); 16327 | case 2 : return process_2(arg_list); 16328 | case 3 : return process_3(arg_list); 16329 | case 4 : return process_4(arg_list); 16330 | case 5 : return process_5(arg_list); 16331 | case 6 : return process_6(arg_list); 16332 | case 7 : return process_7(arg_list); 16333 | case 8 : return process_8(arg_list); 16334 | default : 16335 | { 16336 | for (std::size_t i = 0; i < (arg_list.size() - 1); ++i) 16337 | { 16338 | value(arg_list[i]); 16339 | } 16340 | return value(arg_list.back()); 16341 | } 16342 | } 16343 | } 16344 | 16345 | template <typename Sequence> 16346 | static inline T process_1(const Sequence& arg_list) 16347 | { 16348 | return value(arg_list[0]); 16349 | } 16350 | 16351 | template <typename Sequence> 16352 | static inline T process_2(const Sequence& arg_list) 16353 | { 16354 | value(arg_list[0]); 16355 | return value(arg_list[1]); 16356 | } 16357 | 16358 | template <typename Sequence> 16359 | static inline T process_3(const Sequence& arg_list) 16360 | { 16361 | value(arg_list[0]); 16362 | value(arg_list[1]); 16363 | return value(arg_list[2]); 16364 | } 16365 | 16366 | template <typename Sequence> 16367 | static inline T process_4(const Sequence& arg_list) 16368 | { 16369 | value(arg_list[0]); 16370 | value(arg_list[1]); 16371 | value(arg_list[2]); 16372 | return value(arg_list[3]); 16373 | } 16374 | 16375 | template <typename Sequence> 16376 | static inline T process_5(const Sequence& arg_list) 16377 | { 16378 | value(arg_list[0]); 16379 | value(arg_list[1]); 16380 | value(arg_list[2]); 16381 | value(arg_list[3]); 16382 | return value(arg_list[4]); 16383 | } 16384 | 16385 | template <typename Sequence> 16386 | static inline T process_6(const Sequence& arg_list) 16387 | { 16388 | value(arg_list[0]); 16389 | value(arg_list[1]); 16390 | value(arg_list[2]); 16391 | value(arg_list[3]); 16392 | value(arg_list[4]); 16393 | return value(arg_list[5]); 16394 | } 16395 | 16396 | template <typename Sequence> 16397 | static inline T process_7(const Sequence& arg_list) 16398 | { 16399 | value(arg_list[0]); 16400 | value(arg_list[1]); 16401 | value(arg_list[2]); 16402 | value(arg_list[3]); 16403 | value(arg_list[4]); 16404 | value(arg_list[5]); 16405 | return value(arg_list[6]); 16406 | } 16407 | 16408 | template <typename Sequence> 16409 | static inline T process_8(const Sequence& arg_list) 16410 | { 16411 | value(arg_list[0]); 16412 | value(arg_list[1]); 16413 | value(arg_list[2]); 16414 | value(arg_list[3]); 16415 | value(arg_list[4]); 16416 | value(arg_list[5]); 16417 | value(arg_list[6]); 16418 | return value(arg_list[7]); 16419 | } 16420 | }; 16421 | 16422 | template <typename T> 16423 | struct vec_add_op 16424 | { 16425 | typedef vector_interface<T>* ivector_ptr; 16426 | 16427 | static inline T process(const ivector_ptr v) 16428 | { 16429 | const T* vec = v->vec()->vds().data(); 16430 | const std::size_t vec_size = v->size(); 16431 | 16432 | loop_unroll::details lud(vec_size); 16433 | 16434 | if (vec_size <= static_cast<std::size_t>(lud.batch_size)) 16435 | { 16436 | T result = T(0); 16437 | int i = 0; 16438 | 16439 | switch (vec_size) 16440 | { 16441 | #define case_stmt(N,fall_through) \ 16442 | case N : result += vec[i++]; \ 16443 | fall_through \ 16444 | 16445 | #ifndef exprtk_disable_superscalar_unroll 16446 | case_stmt(16, exprtk_fallthrough) case_stmt(15, exprtk_fallthrough) 16447 | case_stmt(14, exprtk_fallthrough) case_stmt(13, exprtk_fallthrough) 16448 | case_stmt(12, exprtk_fallthrough) case_stmt(11, exprtk_fallthrough) 16449 | case_stmt(10, exprtk_fallthrough) case_stmt( 9, exprtk_fallthrough) 16450 | case_stmt( 8, exprtk_fallthrough) case_stmt( 7, exprtk_fallthrough) 16451 | case_stmt( 6, exprtk_fallthrough) case_stmt( 5, exprtk_fallthrough) 16452 | 16453 | #endif 16454 | case_stmt( 4, exprtk_fallthrough) case_stmt( 3, exprtk_fallthrough) 16455 | case_stmt( 2, exprtk_fallthrough) case_stmt( 1, (void)0;) 16456 | } 16457 | 16458 | #undef case_stmt 16459 | 16460 | return result; 16461 | } 16462 | 16463 | T r[] = { 16464 | T(0), T(0), T(0), T(0), T(0), T(0), T(0), T(0), 16465 | T(0), T(0), T(0), T(0), T(0), T(0), T(0), T(0) 16466 | }; 16467 | 16468 | const T* upper_bound = vec + lud.upper_bound; 16469 | 16470 | while (vec < upper_bound) 16471 | { 16472 | #define exprtk_loop(N) \ 16473 | r[N] += vec[N]; \ 16474 | 16475 | exprtk_loop( 0) exprtk_loop( 1) 16476 | exprtk_loop( 2) exprtk_loop( 3) 16477 | #ifndef exprtk_disable_superscalar_unroll 16478 | exprtk_loop( 4) exprtk_loop( 5) 16479 | exprtk_loop( 6) exprtk_loop( 7) 16480 | exprtk_loop( 8) exprtk_loop( 9) 16481 | exprtk_loop(10) exprtk_loop(11) 16482 | exprtk_loop(12) exprtk_loop(13) 16483 | exprtk_loop(14) exprtk_loop(15) 16484 | #endif 16485 | 16486 | vec += lud.batch_size; 16487 | } 16488 | 16489 | int i = 0; 16490 | 16491 | switch (lud.remainder) 16492 | { 16493 | #define case_stmt(N,fall_through) \ 16494 | case N : r[0] += vec[i++]; \ 16495 | fall_through \ 16496 | 16497 | #ifndef exprtk_disable_superscalar_unroll 16498 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 16499 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 16500 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 16501 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 16502 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 16503 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 16504 | #endif 16505 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 16506 | case_stmt( 1, (void)0;) 16507 | } 16508 | 16509 | #undef exprtk_loop 16510 | #undef case_stmt 16511 | 16512 | return (r[ 0] + r[ 1] + r[ 2] + r[ 3]) 16513 | #ifndef exprtk_disable_superscalar_unroll 16514 | + (r[ 4] + r[ 5] + r[ 6] + r[ 7]) 16515 | + (r[ 8] + r[ 9] + r[10] + r[11]) 16516 | + (r[12] + r[13] + r[14] + r[15]) 16517 | #endif 16518 | ; 16519 | } 16520 | }; 16521 | 16522 | template <typename T> 16523 | struct vec_mul_op 16524 | { 16525 | typedef vector_interface<T>* ivector_ptr; 16526 | 16527 | static inline T process(const ivector_ptr v) 16528 | { 16529 | const T* vec = v->vec()->vds().data(); 16530 | const std::size_t vec_size = v->vec()->size(); 16531 | 16532 | loop_unroll::details lud(vec_size); 16533 | 16534 | if (vec_size <= static_cast<std::size_t>(lud.batch_size)) 16535 | { 16536 | T result = T(1); 16537 | int i = 0; 16538 | 16539 | switch (vec_size) 16540 | { 16541 | #define case_stmt(N,fall_through) \ 16542 | case N : result *= vec[i++]; \ 16543 | fall_through \ 16544 | 16545 | #ifndef exprtk_disable_superscalar_unroll 16546 | case_stmt(16, exprtk_fallthrough) case_stmt(15, exprtk_fallthrough) 16547 | case_stmt(14, exprtk_fallthrough) case_stmt(13, exprtk_fallthrough) 16548 | case_stmt(12, exprtk_fallthrough) case_stmt(11, exprtk_fallthrough) 16549 | case_stmt(10, exprtk_fallthrough) case_stmt( 9, exprtk_fallthrough) 16550 | case_stmt( 8, exprtk_fallthrough) case_stmt( 7, exprtk_fallthrough) 16551 | case_stmt( 6, exprtk_fallthrough) case_stmt( 5, exprtk_fallthrough) 16552 | #endif 16553 | case_stmt( 4, exprtk_fallthrough) case_stmt( 3, exprtk_fallthrough) 16554 | case_stmt( 2, exprtk_fallthrough) case_stmt( 1, (void)0;) 16555 | } 16556 | 16557 | #undef case_stmt 16558 | 16559 | return result; 16560 | } 16561 | 16562 | T r[] = { 16563 | T(1), T(1), T(1), T(1), T(1), T(1), T(1), T(1), 16564 | T(1), T(1), T(1), T(1), T(1), T(1), T(1), T(1) 16565 | }; 16566 | 16567 | const T* upper_bound = vec + lud.upper_bound; 16568 | 16569 | while (vec < upper_bound) 16570 | { 16571 | #define exprtk_loop(N) \ 16572 | r[N] *= vec[N]; \ 16573 | 16574 | exprtk_loop( 0) exprtk_loop( 1) 16575 | exprtk_loop( 2) exprtk_loop( 3) 16576 | #ifndef exprtk_disable_superscalar_unroll 16577 | exprtk_loop( 4) exprtk_loop( 5) 16578 | exprtk_loop( 6) exprtk_loop( 7) 16579 | exprtk_loop( 8) exprtk_loop( 9) 16580 | exprtk_loop(10) exprtk_loop(11) 16581 | exprtk_loop(12) exprtk_loop(13) 16582 | exprtk_loop(14) exprtk_loop(15) 16583 | #endif 16584 | 16585 | vec += lud.batch_size; 16586 | } 16587 | 16588 | int i = 0; 16589 | 16590 | switch (lud.remainder) 16591 | { 16592 | #define case_stmt(N,fall_through) \ 16593 | case N : r[0] *= vec[i++]; \ 16594 | fall_through \ 16595 | 16596 | #ifndef exprtk_disable_superscalar_unroll 16597 | case_stmt(15, exprtk_fallthrough) case_stmt(14, exprtk_fallthrough) 16598 | case_stmt(13, exprtk_fallthrough) case_stmt(12, exprtk_fallthrough) 16599 | case_stmt(11, exprtk_fallthrough) case_stmt(10, exprtk_fallthrough) 16600 | case_stmt( 9, exprtk_fallthrough) case_stmt( 8, exprtk_fallthrough) 16601 | case_stmt( 7, exprtk_fallthrough) case_stmt( 6, exprtk_fallthrough) 16602 | case_stmt( 5, exprtk_fallthrough) case_stmt( 4, exprtk_fallthrough) 16603 | #endif 16604 | case_stmt( 3, exprtk_fallthrough) case_stmt( 2, exprtk_fallthrough) 16605 | case_stmt( 1, (void)0;) 16606 | } 16607 | 16608 | #undef exprtk_loop 16609 | #undef case_stmt 16610 | 16611 | return (r[ 0] * r[ 1] * r[ 2] * r[ 3]) 16612 | #ifndef exprtk_disable_superscalar_unroll 16613 | * (r[ 4] * r[ 5] * r[ 6] * r[ 7]) 16614 | * (r[ 8] * r[ 9] * r[10] * r[11]) 16615 | * (r[12] * r[13] * r[14] * r[15]) 16616 | #endif 16617 | ; 16618 | } 16619 | }; 16620 | 16621 | template <typename T> 16622 | struct vec_avg_op 16623 | { 16624 | typedef vector_interface<T>* ivector_ptr; 16625 | 16626 | static inline T process(const ivector_ptr v) 16627 | { 16628 | const T vec_size = T(v->vec()->size()); 16629 | return vec_add_op<T>::process(v) / vec_size; 16630 | } 16631 | }; 16632 | 16633 | template <typename T> 16634 | struct vec_min_op 16635 | { 16636 | typedef vector_interface<T>* ivector_ptr; 16637 | 16638 | static inline T process(const ivector_ptr v) 16639 | { 16640 | const T* vec = v->vec()->vds().data(); 16641 | const std::size_t vec_size = v->vec()->size(); 16642 | 16643 | T result = vec[0]; 16644 | 16645 | for (std::size_t i = 1; i < vec_size; ++i) 16646 | { 16647 | const T v_i = vec[i]; 16648 | 16649 | if (v_i < result) 16650 | result = v_i; 16651 | } 16652 | 16653 | return result; 16654 | } 16655 | }; 16656 | 16657 | template <typename T> 16658 | struct vec_max_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 | class vov_base_node : public expression_node<T> 16683 | { 16684 | public: 16685 | 16686 | virtual ~vov_base_node() 16687 | {} 16688 | 16689 | inline virtual operator_type operation() const 16690 | { 16691 | return details::e_default; 16692 | } 16693 | 16694 | virtual const T& v0() const = 0; 16695 | 16696 | virtual const T& v1() const = 0; 16697 | }; 16698 | 16699 | template <typename T> 16700 | class cov_base_node : public expression_node<T> 16701 | { 16702 | public: 16703 | 16704 | virtual ~cov_base_node() 16705 | {} 16706 | 16707 | inline virtual operator_type operation() const 16708 | { 16709 | return details::e_default; 16710 | } 16711 | 16712 | virtual const T c() const = 0; 16713 | 16714 | virtual const T& v() const = 0; 16715 | }; 16716 | 16717 | template <typename T> 16718 | class voc_base_node : public expression_node<T> 16719 | { 16720 | public: 16721 | 16722 | virtual ~voc_base_node() 16723 | {} 16724 | 16725 | inline virtual operator_type operation() const 16726 | { 16727 | return details::e_default; 16728 | } 16729 | 16730 | virtual const T c() const = 0; 16731 | 16732 | virtual const T& v() const = 0; 16733 | }; 16734 | 16735 | template <typename T> 16736 | class vob_base_node : public expression_node<T> 16737 | { 16738 | public: 16739 | 16740 | virtual ~vob_base_node() 16741 | {} 16742 | 16743 | virtual const T& v() const = 0; 16744 | }; 16745 | 16746 | template <typename T> 16747 | class bov_base_node : public expression_node<T> 16748 | { 16749 | public: 16750 | 16751 | virtual ~bov_base_node() 16752 | {} 16753 | 16754 | virtual const T& v() const = 0; 16755 | }; 16756 | 16757 | template <typename T> 16758 | class cob_base_node : public expression_node<T> 16759 | { 16760 | public: 16761 | 16762 | virtual ~cob_base_node() 16763 | {} 16764 | 16765 | inline virtual operator_type operation() const 16766 | { 16767 | return details::e_default; 16768 | } 16769 | 16770 | virtual const T c() const = 0; 16771 | 16772 | virtual void set_c(const T) = 0; 16773 | 16774 | virtual expression_node<T>* move_branch(const std::size_t& index) = 0; 16775 | }; 16776 | 16777 | template <typename T> 16778 | class boc_base_node : public expression_node<T> 16779 | { 16780 | public: 16781 | 16782 | virtual ~boc_base_node() 16783 | {} 16784 | 16785 | inline virtual operator_type operation() const 16786 | { 16787 | return details::e_default; 16788 | } 16789 | 16790 | virtual const T c() const = 0; 16791 | 16792 | virtual void set_c(const T) = 0; 16793 | 16794 | virtual expression_node<T>* move_branch(const std::size_t& index) = 0; 16795 | }; 16796 | 16797 | template <typename T> 16798 | class uv_base_node : public expression_node<T> 16799 | { 16800 | public: 16801 | 16802 | virtual ~uv_base_node() 16803 | {} 16804 | 16805 | inline virtual operator_type operation() const 16806 | { 16807 | return details::e_default; 16808 | } 16809 | 16810 | virtual const T& v() const = 0; 16811 | }; 16812 | 16813 | template <typename T> 16814 | class sos_base_node : public expression_node<T> 16815 | { 16816 | public: 16817 | 16818 | virtual ~sos_base_node() 16819 | {} 16820 | 16821 | inline virtual operator_type operation() const 16822 | { 16823 | return details::e_default; 16824 | } 16825 | }; 16826 | 16827 | template <typename T> 16828 | class sosos_base_node : public expression_node<T> 16829 | { 16830 | public: 16831 | 16832 | virtual ~sosos_base_node() 16833 | {} 16834 | 16835 | inline virtual operator_type operation() const 16836 | { 16837 | return details::e_default; 16838 | } 16839 | }; 16840 | 16841 | template <typename T> 16842 | class T0oT1oT2_base_node : public expression_node<T> 16843 | { 16844 | public: 16845 | 16846 | virtual ~T0oT1oT2_base_node() 16847 | {} 16848 | 16849 | virtual std::string type_id() const = 0; 16850 | }; 16851 | 16852 | template <typename T> 16853 | class T0oT1oT2oT3_base_node : public expression_node<T> 16854 | { 16855 | public: 16856 | 16857 | virtual ~T0oT1oT2oT3_base_node() 16858 | {} 16859 | 16860 | virtual std::string type_id() const = 0; 16861 | }; 16862 | 16863 | template <typename T, typename Operation> 16864 | class unary_variable_node exprtk_final : public uv_base_node<T> 16865 | { 16866 | public: 16867 | 16868 | typedef expression_node<T>* expression_ptr; 16869 | typedef Operation operation_t; 16870 | 16871 | explicit unary_variable_node(const T& var) 16872 | : v_(var) 16873 | {} 16874 | 16875 | inline T value() const exprtk_override 16876 | { 16877 | return Operation::process(v_); 16878 | } 16879 | 16880 | inline typename expression_node<T>::node_type type() const exprtk_override 16881 | { 16882 | return Operation::type(); 16883 | } 16884 | 16885 | inline operator_type operation() const exprtk_override 16886 | { 16887 | return Operation::operation(); 16888 | } 16889 | 16890 | inline const T& v() const exprtk_override 16891 | { 16892 | return v_; 16893 | } 16894 | 16895 | private: 16896 | 16897 | unary_variable_node(const unary_variable_node<T,Operation>&) exprtk_delete; 16898 | unary_variable_node<T,Operation>& operator=(const unary_variable_node<T,Operation>&) exprtk_delete; 16899 | 16900 | const T& v_; 16901 | }; 16902 | 16903 | template <typename T> 16904 | class uvouv_node exprtk_final : public expression_node<T> 16905 | { 16906 | public: 16907 | 16908 | // UOpr1(v0) Op UOpr2(v1) 16909 | typedef typename details::functor_t<T> functor_t; 16910 | typedef typename functor_t::bfunc_t bfunc_t; 16911 | typedef typename functor_t::ufunc_t ufunc_t; 16912 | typedef expression_node<T>* expression_ptr; 16913 | 16914 | explicit uvouv_node(const T& var0,const T& var1, 16915 | ufunc_t uf0, ufunc_t uf1, bfunc_t bf) 16916 | : v0_(var0) 16917 | , v1_(var1) 16918 | , u0_(uf0 ) 16919 | , u1_(uf1 ) 16920 | , f_ (bf ) 16921 | {} 16922 | 16923 | inline T value() const exprtk_override 16924 | { 16925 | return f_(u0_(v0_),u1_(v1_)); 16926 | } 16927 | 16928 | inline typename expression_node<T>::node_type type() const exprtk_override 16929 | { 16930 | return expression_node<T>::e_uvouv; 16931 | } 16932 | 16933 | inline const T& v0() 16934 | { 16935 | return v0_; 16936 | } 16937 | 16938 | inline const T& v1() 16939 | { 16940 | return v1_; 16941 | } 16942 | 16943 | inline ufunc_t u0() 16944 | { 16945 | return u0_; 16946 | } 16947 | 16948 | inline ufunc_t u1() 16949 | { 16950 | return u1_; 16951 | } 16952 | 16953 | inline ufunc_t f() 16954 | { 16955 | return f_; 16956 | } 16957 | 16958 | private: 16959 | 16960 | uvouv_node(const uvouv_node<T>&) exprtk_delete; 16961 | uvouv_node<T>& operator=(const uvouv_node<T>&) exprtk_delete; 16962 | 16963 | const T& v0_; 16964 | const T& v1_; 16965 | const ufunc_t u0_; 16966 | const ufunc_t u1_; 16967 | const bfunc_t f_; 16968 | }; 16969 | 16970 | template <typename T, typename Operation> 16971 | class unary_branch_node exprtk_final : public expression_node<T> 16972 | { 16973 | public: 16974 | 16975 | typedef Operation operation_t; 16976 | typedef expression_node<T>* expression_ptr; 16977 | typedef std::pair<expression_ptr,bool> branch_t; 16978 | 16979 | explicit unary_branch_node(expression_ptr branch) 16980 | { 16981 | construct_branch_pair(branch_, branch); 16982 | } 16983 | 16984 | inline T value() const exprtk_override 16985 | { 16986 | return Operation::process(branch_.first->value()); 16987 | } 16988 | 16989 | inline typename expression_node<T>::node_type type() const exprtk_override 16990 | { 16991 | return Operation::type(); 16992 | } 16993 | 16994 | inline bool valid() const exprtk_override 16995 | { 16996 | return branch_.first && branch_.first->valid(); 16997 | } 16998 | 16999 | inline operator_type operation() 17000 | { 17001 | return Operation::operation(); 17002 | } 17003 | 17004 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 17005 | { 17006 | return branch_.first; 17007 | } 17008 | 17009 | inline void release() 17010 | { 17011 | branch_.second = false; 17012 | } 17013 | 17014 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 17015 | { 17016 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 17017 | } 17018 | 17019 | std::size_t node_depth() const exprtk_override 17020 | { 17021 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 17022 | } 17023 | 17024 | private: 17025 | 17026 | unary_branch_node(const unary_branch_node<T,Operation>&) exprtk_delete; 17027 | unary_branch_node<T,Operation>& operator=(const unary_branch_node<T,Operation>&) exprtk_delete; 17028 | 17029 | branch_t branch_; 17030 | }; 17031 | 17032 | template <typename T> struct is_const { enum {result = 0}; }; 17033 | template <typename T> struct is_const <const T> { enum {result = 1}; }; 17034 | template <typename T> struct is_const_ref { enum {result = 0}; }; 17035 | template <typename T> struct is_const_ref <const T&> { enum {result = 1}; }; 17036 | template <typename T> struct is_ref { enum {result = 0}; }; 17037 | template <typename T> struct is_ref<T&> { enum {result = 1}; }; 17038 | template <typename T> struct is_ref<const T&> { enum {result = 0}; }; 17039 | 17040 | template <std::size_t State> 17041 | struct param_to_str { static std::string result() { static const std::string r("v"); return r; } }; 17042 | 17043 | template <> 17044 | struct param_to_str<0> { static std::string result() { static const std::string r("c"); return r; } }; 17045 | 17046 | #define exprtk_crtype(Type) \ 17047 | param_to_str<is_const_ref< Type >::result>::result() \ 17048 | 17049 | template <typename T> 17050 | struct T0oT1oT2process 17051 | { 17052 | typedef typename details::functor_t<T> functor_t; 17053 | typedef typename functor_t::bfunc_t bfunc_t; 17054 | 17055 | struct mode0 17056 | { 17057 | static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1) 17058 | { 17059 | // (T0 o0 T1) o1 T2 17060 | return bf1(bf0(t0,t1),t2); 17061 | } 17062 | 17063 | template <typename T0, typename T1, typename T2> 17064 | static inline std::string id() 17065 | { 17066 | static const std::string result = "(" + exprtk_crtype(T0) + "o" + 17067 | exprtk_crtype(T1) + ")o(" + 17068 | exprtk_crtype(T2) + ")" ; 17069 | return result; 17070 | } 17071 | }; 17072 | 17073 | struct mode1 17074 | { 17075 | static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1) 17076 | { 17077 | // T0 o0 (T1 o1 T2) 17078 | return bf0(t0,bf1(t1,t2)); 17079 | } 17080 | 17081 | template <typename T0, typename T1, typename T2> 17082 | static inline std::string id() 17083 | { 17084 | static const std::string result = "(" + exprtk_crtype(T0) + ")o(" + 17085 | exprtk_crtype(T1) + "o" + 17086 | exprtk_crtype(T2) + ")" ; 17087 | return result; 17088 | } 17089 | }; 17090 | }; 17091 | 17092 | template <typename T> 17093 | struct T0oT1oT20T3process 17094 | { 17095 | typedef typename details::functor_t<T> functor_t; 17096 | typedef typename functor_t::bfunc_t bfunc_t; 17097 | 17098 | struct mode0 17099 | { 17100 | static inline T process(const T& t0, const T& t1, 17101 | const T& t2, const T& t3, 17102 | const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) 17103 | { 17104 | // (T0 o0 T1) o1 (T2 o2 T3) 17105 | return bf1(bf0(t0,t1),bf2(t2,t3)); 17106 | } 17107 | 17108 | template <typename T0, typename T1, typename T2, typename T3> 17109 | static inline std::string id() 17110 | { 17111 | static const std::string result = "(" + exprtk_crtype(T0) + "o" + 17112 | exprtk_crtype(T1) + ")o" + 17113 | "(" + exprtk_crtype(T2) + "o" + 17114 | exprtk_crtype(T3) + ")" ; 17115 | return result; 17116 | } 17117 | }; 17118 | 17119 | struct mode1 17120 | { 17121 | static inline T process(const T& t0, const T& t1, 17122 | const T& t2, const T& t3, 17123 | const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) 17124 | { 17125 | // (T0 o0 (T1 o1 (T2 o2 T3)) 17126 | return bf0(t0,bf1(t1,bf2(t2,t3))); 17127 | } 17128 | template <typename T0, typename T1, typename T2, typename T3> 17129 | static inline std::string id() 17130 | { 17131 | static const std::string result = "(" + exprtk_crtype(T0) + ")o((" + 17132 | exprtk_crtype(T1) + ")o(" + 17133 | exprtk_crtype(T2) + "o" + 17134 | exprtk_crtype(T3) + "))" ; 17135 | return result; 17136 | } 17137 | }; 17138 | 17139 | struct mode2 17140 | { 17141 | static inline T process(const T& t0, const T& t1, 17142 | const T& t2, const T& t3, 17143 | const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) 17144 | { 17145 | // (T0 o0 ((T1 o1 T2) o2 T3) 17146 | return bf0(t0,bf2(bf1(t1,t2),t3)); 17147 | } 17148 | 17149 | template <typename T0, typename T1, typename T2, typename T3> 17150 | static inline std::string id() 17151 | { 17152 | static const std::string result = "(" + exprtk_crtype(T0) + ")o((" + 17153 | exprtk_crtype(T1) + "o" + 17154 | exprtk_crtype(T2) + ")o(" + 17155 | exprtk_crtype(T3) + "))" ; 17156 | return result; 17157 | } 17158 | }; 17159 | 17160 | struct mode3 17161 | { 17162 | static inline T process(const T& t0, const T& t1, 17163 | const T& t2, const T& t3, 17164 | const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) 17165 | { 17166 | // (((T0 o0 T1) o1 T2) o2 T3) 17167 | return bf2(bf1(bf0(t0,t1),t2),t3); 17168 | } 17169 | 17170 | template <typename T0, typename T1, typename T2, typename T3> 17171 | static inline std::string id() 17172 | { 17173 | static const std::string result = "((" + exprtk_crtype(T0) + "o" + 17174 | exprtk_crtype(T1) + ")o(" + 17175 | exprtk_crtype(T2) + "))o(" + 17176 | exprtk_crtype(T3) + ")" 17177 | return result; 17178 | } 17179 | }; 17180 | 17181 | struct mode4 17182 | { 17183 | static inline T process(const T& t0, const T& t1, 17184 | const T& t2, const T& t3, 17185 | const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) 17186 | { 17187 | // ((T0 o0 (T1 o1 T2)) o2 T3 17188 | return bf2(bf0(t0,bf1(t1,t2)),t3); 17189 | } 17190 | 17191 | template <typename T0, typename T1, typename T2, typename T3> 17192 | static inline std::string id() 17193 | { 17194 | static const std::string result = "((" + exprtk_crtype(T0) + ")o(" + 17195 | exprtk_crtype(T1) + "o" + 17196 | exprtk_crtype(T2) + "))o(" + 17197 | exprtk_crtype(T3) + ")" ; 17198 | return result; 17199 | } 17200 | }; 17201 | }; 17202 | 17203 | #undef exprtk_crtype 17204 | 17205 | template <typename T, typename T0, typename T1> 17206 | struct nodetype_T0oT1 { static const typename expression_node<T>::node_type result; }; 17207 | template <typename T, typename T0, typename T1> 17208 | const typename expression_node<T>::node_type nodetype_T0oT1<T,T0,T1>::result = expression_node<T>::e_none; 17209 | 17210 | #define synthesis_node_type_define(T0_, T1_, v_) \ 17211 | template <typename T, typename T0, typename T1> \ 17212 | struct nodetype_T0oT1<T,T0_,T1_> { static const typename expression_node<T>::node_type result; }; \ 17213 | template <typename T, typename T0, typename T1> \ 17214 | const typename expression_node<T>::node_type nodetype_T0oT1<T,T0_,T1_>::result = expression_node<T>:: v_; \ 17215 | 17216 | synthesis_node_type_define(const T0&, const T1&, e_vov) 17217 | synthesis_node_type_define(const T0&, const T1 , e_voc) 17218 | synthesis_node_type_define(const T0 , const T1&, e_cov) 17219 | synthesis_node_type_define( T0&, T1&, e_none) 17220 | synthesis_node_type_define(const T0 , const T1 , e_none) 17221 | synthesis_node_type_define( T0&, const T1 , e_none) 17222 | synthesis_node_type_define(const T0 , T1&, e_none) 17223 | synthesis_node_type_define(const T0&, T1&, e_none) 17224 | synthesis_node_type_define( T0&, const T1&, e_none) 17225 | #undef synthesis_node_type_define 17226 | 17227 | template <typename T, typename T0, typename T1, typename T2> 17228 | struct nodetype_T0oT1oT2 { static const typename expression_node<T>::node_type result; }; 17229 | template <typename T, typename T0, typename T1, typename T2> 17230 | const typename expression_node<T>::node_type nodetype_T0oT1oT2<T,T0,T1,T2>::result = expression_node<T>::e_none; 17231 | 17232 | #define synthesis_node_type_define(T0_, T1_, T2_, v_) \ 17233 | template <typename T, typename T0, typename T1, typename T2> \ 17234 | struct nodetype_T0oT1oT2<T,T0_,T1_,T2_> { static const typename expression_node<T>::node_type result; }; \ 17235 | template <typename T, typename T0, typename T1, typename T2> \ 17236 | const typename expression_node<T>::node_type nodetype_T0oT1oT2<T,T0_,T1_,T2_>::result = expression_node<T>:: v_; \ 17237 | 17238 | synthesis_node_type_define(const T0&, const T1&, const T2&, e_vovov) 17239 | synthesis_node_type_define(const T0&, const T1&, const T2 , e_vovoc) 17240 | synthesis_node_type_define(const T0&, const T1 , const T2&, e_vocov) 17241 | synthesis_node_type_define(const T0 , const T1&, const T2&, e_covov) 17242 | synthesis_node_type_define(const T0 , const T1&, const T2 , e_covoc) 17243 | synthesis_node_type_define(const T0 , const T1 , const T2 , e_none ) 17244 | synthesis_node_type_define(const T0 , const T1 , const T2&, e_none ) 17245 | synthesis_node_type_define(const T0&, const T1 , const T2 , e_none ) 17246 | synthesis_node_type_define( T0&, T1&, T2&, e_none ) 17247 | #undef synthesis_node_type_define 17248 | 17249 | template <typename T, typename T0, typename T1, typename T2, typename T3> 17250 | struct nodetype_T0oT1oT2oT3 { static const typename expression_node<T>::node_type result; }; 17251 | template <typename T, typename T0, typename T1, typename T2, typename T3> 17252 | const typename expression_node<T>::node_type nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result = expression_node<T>::e_none; 17253 | 17254 | #define synthesis_node_type_define(T0_, T1_, T2_, T3_, v_) \ 17255 | template <typename T, typename T0, typename T1, typename T2, typename T3> \ 17256 | struct nodetype_T0oT1oT2oT3<T,T0_,T1_,T2_,T3_> { static const typename expression_node<T>::node_type result; }; \ 17257 | template <typename T, typename T0, typename T1, typename T2, typename T3> \ 17258 | const typename expression_node<T>::node_type nodetype_T0oT1oT2oT3<T,T0_,T1_,T2_,T3_>::result = expression_node<T>:: v_; \ 17259 | 17260 | synthesis_node_type_define(const T0&, const T1&, const T2&, const T3&, e_vovovov) 17261 | synthesis_node_type_define(const T0&, const T1&, const T2&, const T3 , e_vovovoc) 17262 | synthesis_node_type_define(const T0&, const T1&, const T2 , const T3&, e_vovocov) 17263 | synthesis_node_type_define(const T0&, const T1 , const T2&, const T3&, e_vocovov) 17264 | synthesis_node_type_define(const T0 , const T1&, const T2&, const T3&, e_covovov) 17265 | synthesis_node_type_define(const T0 , const T1&, const T2 , const T3&, e_covocov) 17266 | synthesis_node_type_define(const T0&, const T1 , const T2&, const T3 , e_vocovoc) 17267 | synthesis_node_type_define(const T0 , const T1&, const T2&, const T3 , e_covovoc) 17268 | synthesis_node_type_define(const T0&, const T1 , const T2 , const T3&, e_vococov) 17269 | synthesis_node_type_define(const T0 , const T1 , const T2 , const T3 , e_none ) 17270 | synthesis_node_type_define(const T0 , const T1 , const T2 , const T3&, e_none ) 17271 | synthesis_node_type_define(const T0 , const T1 , const T2&, const T3 , e_none ) 17272 | synthesis_node_type_define(const T0 , const T1&, const T2 , const T3 , e_none ) 17273 | synthesis_node_type_define(const T0&, const T1 , const T2 , const T3 , e_none ) 17274 | synthesis_node_type_define(const T0 , const T1 , const T2&, const T3&, e_none ) 17275 | synthesis_node_type_define(const T0&, const T1&, const T2 , const T3 , e_none ) 17276 | #undef synthesis_node_type_define 17277 | 17278 | template <typename T, typename T0, typename T1> 17279 | class T0oT1 exprtk_final : public expression_node<T> 17280 | { 17281 | public: 17282 | 17283 | typedef typename details::functor_t<T> functor_t; 17284 | typedef typename functor_t::bfunc_t bfunc_t; 17285 | typedef T value_type; 17286 | typedef T0oT1<T,T0,T1> node_type; 17287 | 17288 | T0oT1(T0 p0, T1 p1, const bfunc_t p2) 17289 | : t0_(p0) 17290 | , t1_(p1) 17291 | , f_ (p2) 17292 | {} 17293 | 17294 | inline typename expression_node<T>::node_type type() const exprtk_override 17295 | { 17296 | static const typename expression_node<T>::node_type result = nodetype_T0oT1<T,T0,T1>::result; 17297 | return result; 17298 | } 17299 | 17300 | inline operator_type operation() const exprtk_override 17301 | { 17302 | return e_default; 17303 | } 17304 | 17305 | inline T value() const exprtk_override 17306 | { 17307 | return f_(t0_,t1_); 17308 | } 17309 | 17310 | inline T0 t0() const 17311 | { 17312 | return t0_; 17313 | } 17314 | 17315 | inline T1 t1() const 17316 | { 17317 | return t1_; 17318 | } 17319 | 17320 | inline bfunc_t f() const 17321 | { 17322 | return f_; 17323 | } 17324 | 17325 | template <typename Allocator> 17326 | static inline expression_node<T>* allocate(Allocator& allocator, 17327 | T0 p0, T1 p1, 17328 | bfunc_t p2) 17329 | { 17330 | return allocator 17331 | .template allocate_type<node_type, T0, T1, bfunc_t&> 17332 | (p0, p1, p2); 17333 | } 17334 | 17335 | private: 17336 | 17337 | T0oT1(const T0oT1<T,T0,T1>&) exprtk_delete; 17338 | T0oT1<T,T0,T1>& operator=(const T0oT1<T,T0,T1>&) { return (*this); } 17339 | 17340 | T0 t0_; 17341 | T1 t1_; 17342 | const bfunc_t f_; 17343 | }; 17344 | 17345 | template <typename T, typename T0, typename T1, typename T2, typename ProcessMode> 17346 | class T0oT1oT2 exprtk_final : public T0oT1oT2_base_node<T> 17347 | { 17348 | public: 17349 | 17350 | typedef typename details::functor_t<T> functor_t; 17351 | typedef typename functor_t::bfunc_t bfunc_t; 17352 | typedef T value_type; 17353 | typedef T0oT1oT2<T,T0,T1,T2,ProcessMode> node_type; 17354 | typedef ProcessMode process_mode_t; 17355 | 17356 | T0oT1oT2(T0 p0, T1 p1, T2 p2, const bfunc_t p3, const bfunc_t p4) 17357 | : t0_(p0) 17358 | , t1_(p1) 17359 | , t2_(p2) 17360 | , f0_(p3) 17361 | , f1_(p4) 17362 | {} 17363 | 17364 | inline typename expression_node<T>::node_type type() const exprtk_override 17365 | { 17366 | static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result; 17367 | return result; 17368 | } 17369 | 17370 | inline operator_type operation() 17371 | { 17372 | return e_default; 17373 | } 17374 | 17375 | inline T value() const exprtk_override 17376 | { 17377 | return ProcessMode::process(t0_, t1_, t2_, f0_, f1_); 17378 | } 17379 | 17380 | inline T0 t0() const 17381 | { 17382 | return t0_; 17383 | } 17384 | 17385 | inline T1 t1() const 17386 | { 17387 | return t1_; 17388 | } 17389 | 17390 | inline T2 t2() const 17391 | { 17392 | return t2_; 17393 | } 17394 | 17395 | bfunc_t f0() const 17396 | { 17397 | return f0_; 17398 | } 17399 | 17400 | bfunc_t f1() const 17401 | { 17402 | return f1_; 17403 | } 17404 | 17405 | std::string type_id() const exprtk_override 17406 | { 17407 | return id(); 17408 | } 17409 | 17410 | static inline std::string id() 17411 | { 17412 | return process_mode_t::template id<T0,T1,T2>(); 17413 | } 17414 | 17415 | template <typename Allocator> 17416 | static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, bfunc_t p3, bfunc_t p4) 17417 | { 17418 | return allocator 17419 | .template allocate_type<node_type, T0, T1, T2, bfunc_t, bfunc_t> 17420 | (p0, p1, p2, p3, p4); 17421 | } 17422 | 17423 | private: 17424 | 17425 | T0oT1oT2(const node_type&) exprtk_delete; 17426 | node_type& operator=(const node_type&) exprtk_delete; 17427 | 17428 | T0 t0_; 17429 | T1 t1_; 17430 | T2 t2_; 17431 | const bfunc_t f0_; 17432 | const bfunc_t f1_; 17433 | }; 17434 | 17435 | template <typename T, typename T0_, typename T1_, typename T2_, typename T3_, typename ProcessMode> 17436 | class T0oT1oT2oT3 exprtk_final : public T0oT1oT2oT3_base_node<T> 17437 | { 17438 | public: 17439 | 17440 | typedef typename details::functor_t<T> functor_t; 17441 | typedef typename functor_t::bfunc_t bfunc_t; 17442 | typedef T value_type; 17443 | typedef T0_ T0; 17444 | typedef T1_ T1; 17445 | typedef T2_ T2; 17446 | typedef T3_ T3; 17447 | typedef T0oT1oT2oT3<T,T0,T1,T2,T3,ProcessMode> node_type; 17448 | typedef ProcessMode process_mode_t; 17449 | 17450 | T0oT1oT2oT3(T0 p0, T1 p1, T2 p2, T3 p3, bfunc_t p4, bfunc_t p5, bfunc_t p6) 17451 | : t0_(p0) 17452 | , t1_(p1) 17453 | , t2_(p2) 17454 | , t3_(p3) 17455 | , f0_(p4) 17456 | , f1_(p5) 17457 | , f2_(p6) 17458 | {} 17459 | 17460 | inline T value() const exprtk_override 17461 | { 17462 | return ProcessMode::process(t0_, t1_, t2_, t3_, f0_, f1_, f2_); 17463 | } 17464 | 17465 | inline T0 t0() const 17466 | { 17467 | return t0_; 17468 | } 17469 | 17470 | inline T1 t1() const 17471 | { 17472 | return t1_; 17473 | } 17474 | 17475 | inline T2 t2() const 17476 | { 17477 | return t2_; 17478 | } 17479 | 17480 | inline T3 t3() const 17481 | { 17482 | return t3_; 17483 | } 17484 | 17485 | inline bfunc_t f0() const 17486 | { 17487 | return f0_; 17488 | } 17489 | 17490 | inline bfunc_t f1() const 17491 | { 17492 | return f1_; 17493 | } 17494 | 17495 | inline bfunc_t f2() const 17496 | { 17497 | return f2_; 17498 | } 17499 | 17500 | inline std::string type_id() const exprtk_override 17501 | { 17502 | return id(); 17503 | } 17504 | 17505 | static inline std::string id() 17506 | { 17507 | return process_mode_t::template id<T0, T1, T2, T3>(); 17508 | } 17509 | 17510 | template <typename Allocator> 17511 | static inline expression_node<T>* allocate(Allocator& allocator, 17512 | T0 p0, T1 p1, T2 p2, T3 p3, 17513 | bfunc_t p4, bfunc_t p5, bfunc_t p6) 17514 | { 17515 | return allocator 17516 | .template allocate_type<node_type, T0, T1, T2, T3, bfunc_t, bfunc_t> 17517 | (p0, p1, p2, p3, p4, p5, p6); 17518 | } 17519 | 17520 | private: 17521 | 17522 | T0oT1oT2oT3(const node_type&) exprtk_delete; 17523 | node_type& operator=(const node_type&) exprtk_delete; 17524 | 17525 | T0 t0_; 17526 | T1 t1_; 17527 | T2 t2_; 17528 | T3 t3_; 17529 | const bfunc_t f0_; 17530 | const bfunc_t f1_; 17531 | const bfunc_t f2_; 17532 | }; 17533 | 17534 | template <typename T, typename T0, typename T1, typename T2> 17535 | class T0oT1oT2_sf3 exprtk_final : public T0oT1oT2_base_node<T> 17536 | { 17537 | public: 17538 | 17539 | typedef typename details::functor_t<T> functor_t; 17540 | typedef typename functor_t::tfunc_t tfunc_t; 17541 | typedef T value_type; 17542 | typedef T0oT1oT2_sf3<T,T0,T1,T2> node_type; 17543 | 17544 | T0oT1oT2_sf3(T0 p0, T1 p1, T2 p2, const tfunc_t p3) 17545 | : t0_(p0) 17546 | , t1_(p1) 17547 | , t2_(p2) 17548 | , f_ (p3) 17549 | {} 17550 | 17551 | inline typename expression_node<T>::node_type type() const exprtk_override 17552 | { 17553 | static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result; 17554 | return result; 17555 | } 17556 | 17557 | inline operator_type operation() const exprtk_override 17558 | { 17559 | return e_default; 17560 | } 17561 | 17562 | inline T value() const exprtk_override 17563 | { 17564 | return f_(t0_, t1_, t2_); 17565 | } 17566 | 17567 | inline T0 t0() const 17568 | { 17569 | return t0_; 17570 | } 17571 | 17572 | inline T1 t1() const 17573 | { 17574 | return t1_; 17575 | } 17576 | 17577 | inline T2 t2() const 17578 | { 17579 | return t2_; 17580 | } 17581 | 17582 | tfunc_t f() const 17583 | { 17584 | return f_; 17585 | } 17586 | 17587 | std::string type_id() const 17588 | { 17589 | return id(); 17590 | } 17591 | 17592 | static inline std::string id() 17593 | { 17594 | return "sf3" 17595 | } 17596 | 17597 | template <typename Allocator> 17598 | static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, tfunc_t p3) 17599 | { 17600 | return allocator 17601 | .template allocate_type<node_type, T0, T1, T2, tfunc_t> 17602 | (p0, p1, p2, p3); 17603 | } 17604 | 17605 | private: 17606 | 17607 | T0oT1oT2_sf3(const node_type&) exprtk_delete; 17608 | node_type& operator=(const node_type&) exprtk_delete; 17609 | 17610 | T0 t0_; 17611 | T1 t1_; 17612 | T2 t2_; 17613 | const tfunc_t f_; 17614 | }; 17615 | 17616 | template <typename T, typename T0, typename T1, typename T2> 17617 | class sf3ext_type_node : public T0oT1oT2_base_node<T> 17618 | { 17619 | public: 17620 | 17621 | virtual ~sf3ext_type_node() 17622 | {} 17623 | 17624 | virtual T0 t0() const = 0; 17625 | 17626 | virtual T1 t1() const = 0; 17627 | 17628 | virtual T2 t2() const = 0; 17629 | }; 17630 | 17631 | template <typename T, typename T0, typename T1, typename T2, typename SF3Operation> 17632 | class T0oT1oT2_sf3ext exprtk_final : public sf3ext_type_node<T,T0,T1,T2> 17633 | { 17634 | public: 17635 | 17636 | typedef T value_type; 17637 | typedef T0oT1oT2_sf3ext<T, T0, T1, T2, SF3Operation> node_type; 17638 | 17639 | T0oT1oT2_sf3ext(T0 p0, T1 p1, T2 p2) 17640 | : t0_(p0) 17641 | , t1_(p1) 17642 | , t2_(p2) 17643 | {} 17644 | 17645 | inline typename expression_node<T>::node_type type() const exprtk_override 17646 | { 17647 | static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result; 17648 | return result; 17649 | } 17650 | 17651 | inline operator_type operation() 17652 | { 17653 | return e_default; 17654 | } 17655 | 17656 | inline T value() const exprtk_override 17657 | { 17658 | return SF3Operation::process(t0_, t1_, t2_); 17659 | } 17660 | 17661 | T0 t0() const exprtk_override 17662 | { 17663 | return t0_; 17664 | } 17665 | 17666 | T1 t1() const exprtk_override 17667 | { 17668 | return t1_; 17669 | } 17670 | 17671 | T2 t2() const exprtk_override 17672 | { 17673 | return t2_; 17674 | } 17675 | 17676 | std::string type_id() const exprtk_override 17677 | { 17678 | return id(); 17679 | } 17680 | 17681 | static inline std::string id() 17682 | { 17683 | return SF3Operation::id(); 17684 | } 17685 | 17686 | template <typename Allocator> 17687 | static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2) 17688 | { 17689 | return allocator 17690 | .template allocate_type<node_type, T0, T1, T2> 17691 | (p0, p1, p2); 17692 | } 17693 | 17694 | private: 17695 | 17696 | T0oT1oT2_sf3ext(const node_type&) exprtk_delete; 17697 | node_type& operator=(const node_type&) exprtk_delete; 17698 | 17699 | T0 t0_; 17700 | T1 t1_; 17701 | T2 t2_; 17702 | }; 17703 | 17704 | template <typename T> 17705 | inline bool is_sf3ext_node(const expression_node<T>* n) 17706 | { 17707 | switch (n->type()) 17708 | { 17709 | case expression_node<T>::e_vovov : return true; 17710 | case expression_node<T>::e_vovoc : return true; 17711 | case expression_node<T>::e_vocov : return true; 17712 | case expression_node<T>::e_covov : return true; 17713 | case expression_node<T>::e_covoc : return true; 17714 | default : return false; 17715 | } 17716 | } 17717 | 17718 | template <typename T, typename T0, typename T1, typename T2, typename T3> 17719 | class T0oT1oT2oT3_sf4 exprtk_final : public T0oT1oT2_base_node<T> 17720 | { 17721 | public: 17722 | 17723 | typedef typename details::functor_t<T> functor_t; 17724 | typedef typename functor_t::qfunc_t qfunc_t; 17725 | typedef T value_type; 17726 | typedef T0oT1oT2oT3_sf4<T, T0, T1, T2, T3> node_type; 17727 | 17728 | T0oT1oT2oT3_sf4(T0 p0, T1 p1, T2 p2, T3 p3, const qfunc_t p4) 17729 | : t0_(p0) 17730 | , t1_(p1) 17731 | , t2_(p2) 17732 | , t3_(p3) 17733 | , f_ (p4) 17734 | {} 17735 | 17736 | inline typename expression_node<T>::node_type type() const exprtk_override 17737 | { 17738 | static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result; 17739 | return result; 17740 | } 17741 | 17742 | inline operator_type operation() const exprtk_override 17743 | { 17744 | return e_default; 17745 | } 17746 | 17747 | inline T value() const exprtk_override 17748 | { 17749 | return f_(t0_, t1_, t2_, t3_); 17750 | } 17751 | 17752 | inline T0 t0() const 17753 | { 17754 | return t0_; 17755 | } 17756 | 17757 | inline T1 t1() const 17758 | { 17759 | return t1_; 17760 | } 17761 | 17762 | inline T2 t2() const 17763 | { 17764 | return t2_; 17765 | } 17766 | 17767 | inline T3 t3() const 17768 | { 17769 | return t3_; 17770 | } 17771 | 17772 | qfunc_t f() const 17773 | { 17774 | return f_; 17775 | } 17776 | 17777 | std::string type_id() const 17778 | { 17779 | return id(); 17780 | } 17781 | 17782 | static inline std::string id() 17783 | { 17784 | return "sf4" 17785 | } 17786 | 17787 | template <typename Allocator> 17788 | static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, T3 p3, qfunc_t p4) 17789 | { 17790 | return allocator 17791 | .template allocate_type<node_type, T0, T1, T2, T3, qfunc_t> 17792 | (p0, p1, p2, p3, p4); 17793 | } 17794 | 17795 | private: 17796 | 17797 | T0oT1oT2oT3_sf4(const node_type&) exprtk_delete; 17798 | node_type& operator=(const node_type&) exprtk_delete; 17799 | 17800 | T0 t0_; 17801 | T1 t1_; 17802 | T2 t2_; 17803 | T3 t3_; 17804 | const qfunc_t f_; 17805 | }; 17806 | 17807 | template <typename T, typename T0, typename T1, typename T2, typename T3, typename SF4Operation> 17808 | class T0oT1oT2oT3_sf4ext exprtk_final : public T0oT1oT2oT3_base_node<T> 17809 | { 17810 | public: 17811 | 17812 | typedef T value_type; 17813 | typedef T0oT1oT2oT3_sf4ext<T, T0, T1, T2, T3, SF4Operation> node_type; 17814 | 17815 | T0oT1oT2oT3_sf4ext(T0 p0, T1 p1, T2 p2, T3 p3) 17816 | : t0_(p0) 17817 | , t1_(p1) 17818 | , t2_(p2) 17819 | , t3_(p3) 17820 | {} 17821 | 17822 | inline typename expression_node<T>::node_type type() const exprtk_override 17823 | { 17824 | static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result; 17825 | return result; 17826 | } 17827 | 17828 | inline T value() const exprtk_override 17829 | { 17830 | return SF4Operation::process(t0_, t1_, t2_, t3_); 17831 | } 17832 | 17833 | inline T0 t0() const 17834 | { 17835 | return t0_; 17836 | } 17837 | 17838 | inline T1 t1() const 17839 | { 17840 | return t1_; 17841 | } 17842 | 17843 | inline T2 t2() const 17844 | { 17845 | return t2_; 17846 | } 17847 | 17848 | inline T3 t3() const 17849 | { 17850 | return t3_; 17851 | } 17852 | 17853 | std::string type_id() const exprtk_override 17854 | { 17855 | return id(); 17856 | } 17857 | 17858 | static inline std::string id() 17859 | { 17860 | return SF4Operation::id(); 17861 | } 17862 | 17863 | template <typename Allocator> 17864 | static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, T3 p3) 17865 | { 17866 | return allocator 17867 | .template allocate_type<node_type, T0, T1, T2, T3> 17868 | (p0, p1, p2, p3); 17869 | } 17870 | 17871 | private: 17872 | 17873 | T0oT1oT2oT3_sf4ext(const node_type&) exprtk_delete; 17874 | node_type& operator=(const node_type&) exprtk_delete; 17875 | 17876 | T0 t0_; 17877 | T1 t1_; 17878 | T2 t2_; 17879 | T3 t3_; 17880 | }; 17881 | 17882 | template <typename T> 17883 | inline bool is_sf4ext_node(const expression_node<T>* n) 17884 | { 17885 | switch (n->type()) 17886 | { 17887 | case expression_node<T>::e_vovovov : return true; 17888 | case expression_node<T>::e_vovovoc : return true; 17889 | case expression_node<T>::e_vovocov : return true; 17890 | case expression_node<T>::e_vocovov : return true; 17891 | case expression_node<T>::e_covovov : return true; 17892 | case expression_node<T>::e_covocov : return true; 17893 | case expression_node<T>::e_vocovoc : return true; 17894 | case expression_node<T>::e_covovoc : return true; 17895 | case expression_node<T>::e_vococov : return true; 17896 | default : return false; 17897 | } 17898 | } 17899 | 17900 | template <typename T, typename T0, typename T1> 17901 | struct T0oT1_define 17902 | { 17903 | typedef details::T0oT1<T, T0, T1> type0; 17904 | }; 17905 | 17906 | template <typename T, typename T0, typename T1, typename T2> 17907 | struct T0oT1oT2_define 17908 | { 17909 | typedef details::T0oT1oT2<T, T0, T1, T2, typename T0oT1oT2process<T>::mode0> type0; 17910 | typedef details::T0oT1oT2<T, T0, T1, T2, typename T0oT1oT2process<T>::mode1> type1; 17911 | typedef details::T0oT1oT2_sf3<T, T0, T1, T2> sf3_type; 17912 | typedef details::sf3ext_type_node<T, T0, T1, T2> sf3_type_node; 17913 | }; 17914 | 17915 | template <typename T, typename T0, typename T1, typename T2, typename T3> 17916 | struct T0oT1oT2oT3_define 17917 | { 17918 | typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode0> type0; 17919 | typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode1> type1; 17920 | typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode2> type2; 17921 | typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode3> type3; 17922 | typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode4> type4; 17923 | typedef details::T0oT1oT2oT3_sf4<T, T0, T1, T2, T3> sf4_type; 17924 | }; 17925 | 17926 | template <typename T, typename Operation> 17927 | class vov_node exprtk_final : public vov_base_node<T> 17928 | { 17929 | public: 17930 | 17931 | typedef expression_node<T>* expression_ptr; 17932 | typedef Operation operation_t; 17933 | 17934 | // variable op variable node 17935 | explicit vov_node(const T& var0, const T& var1) 17936 | : v0_(var0) 17937 | , v1_(var1) 17938 | {} 17939 | 17940 | inline T value() const exprtk_override 17941 | { 17942 | return Operation::process(v0_,v1_); 17943 | } 17944 | 17945 | inline typename expression_node<T>::node_type type() const exprtk_override 17946 | { 17947 | return Operation::type(); 17948 | } 17949 | 17950 | inline operator_type operation() const exprtk_override 17951 | { 17952 | return Operation::operation(); 17953 | } 17954 | 17955 | inline const T& v0() const exprtk_override 17956 | { 17957 | return v0_; 17958 | } 17959 | 17960 | inline const T& v1() const exprtk_override 17961 | { 17962 | return v1_; 17963 | } 17964 | 17965 | protected: 17966 | 17967 | const T& v0_; 17968 | const T& v1_; 17969 | 17970 | private: 17971 | 17972 | vov_node(const vov_node<T,Operation>&) exprtk_delete; 17973 | vov_node<T,Operation>& operator=(const vov_node<T,Operation>&) exprtk_delete; 17974 | }; 17975 | 17976 | template <typename T, typename Operation> 17977 | class cov_node exprtk_final : public cov_base_node<T> 17978 | { 17979 | public: 17980 | 17981 | typedef expression_node<T>* expression_ptr; 17982 | typedef Operation operation_t; 17983 | 17984 | // constant op variable node 17985 | explicit cov_node(const T& const_var, const T& var) 17986 | : c_(const_var) 17987 | , v_(var) 17988 | {} 17989 | 17990 | inline T value() const exprtk_override 17991 | { 17992 | return Operation::process(c_,v_); 17993 | } 17994 | 17995 | inline typename expression_node<T>::node_type type() const exprtk_override 17996 | { 17997 | return Operation::type(); 17998 | } 17999 | 18000 | inline operator_type operation() const exprtk_override 18001 | { 18002 | return Operation::operation(); 18003 | } 18004 | 18005 | inline const T c() const exprtk_override 18006 | { 18007 | return c_; 18008 | } 18009 | 18010 | inline const T& v() const exprtk_override 18011 | { 18012 | return v_; 18013 | } 18014 | 18015 | protected: 18016 | 18017 | const T c_; 18018 | const T& v_; 18019 | 18020 | private: 18021 | 18022 | cov_node(const cov_node<T,Operation>&) exprtk_delete; 18023 | cov_node<T,Operation>& operator=(const cov_node<T,Operation>&) exprtk_delete; 18024 | }; 18025 | 18026 | template <typename T, typename Operation> 18027 | class voc_node exprtk_final : public voc_base_node<T> 18028 | { 18029 | public: 18030 | 18031 | typedef expression_node<T>* expression_ptr; 18032 | typedef Operation operation_t; 18033 | 18034 | // variable op constant node 18035 | explicit voc_node(const T& var, const T& const_var) 18036 | : v_(var) 18037 | , c_(const_var) 18038 | {} 18039 | 18040 | inline T value() const exprtk_override 18041 | { 18042 | return Operation::process(v_,c_); 18043 | } 18044 | 18045 | inline operator_type operation() const exprtk_override 18046 | { 18047 | return Operation::operation(); 18048 | } 18049 | 18050 | inline const T c() const exprtk_override 18051 | { 18052 | return c_; 18053 | } 18054 | 18055 | inline const T& v() const exprtk_override 18056 | { 18057 | return v_; 18058 | } 18059 | 18060 | protected: 18061 | 18062 | const T& v_; 18063 | const T c_; 18064 | 18065 | private: 18066 | 18067 | voc_node(const voc_node<T,Operation>&) exprtk_delete; 18068 | voc_node<T,Operation>& operator=(const voc_node<T,Operation>&) exprtk_delete; 18069 | }; 18070 | 18071 | template <typename T, typename Operation> 18072 | class vob_node exprtk_final : public vob_base_node<T> 18073 | { 18074 | public: 18075 | 18076 | typedef expression_node<T>* expression_ptr; 18077 | typedef std::pair<expression_ptr,bool> branch_t; 18078 | typedef Operation operation_t; 18079 | 18080 | // variable op binary node 18081 | explicit vob_node(const T& var, const expression_ptr branch) 18082 | : v_(var) 18083 | { 18084 | construct_branch_pair(branch_, branch); 18085 | assert(valid()); 18086 | } 18087 | 18088 | inline T value() const exprtk_override 18089 | { 18090 | return Operation::process(v_,branch_.first->value()); 18091 | } 18092 | 18093 | inline const T& v() const exprtk_override 18094 | { 18095 | return v_; 18096 | } 18097 | 18098 | inline bool valid() const exprtk_override 18099 | { 18100 | return branch_.first && branch_.first->valid(); 18101 | } 18102 | 18103 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 18104 | { 18105 | return branch_.first; 18106 | } 18107 | 18108 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 18109 | { 18110 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 18111 | } 18112 | 18113 | std::size_t node_depth() const exprtk_override 18114 | { 18115 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 18116 | } 18117 | 18118 | private: 18119 | 18120 | vob_node(const vob_node<T,Operation>&) exprtk_delete; 18121 | vob_node<T,Operation>& operator=(const vob_node<T,Operation>&) exprtk_delete; 18122 | 18123 | const T& v_; 18124 | branch_t branch_; 18125 | }; 18126 | 18127 | template <typename T, typename Operation> 18128 | class bov_node exprtk_final : public bov_base_node<T> 18129 | { 18130 | public: 18131 | 18132 | typedef expression_node<T>* expression_ptr; 18133 | typedef std::pair<expression_ptr,bool> branch_t; 18134 | typedef Operation operation_t; 18135 | 18136 | // binary node op variable node 18137 | explicit bov_node(const expression_ptr branch, const T& var) 18138 | : v_(var) 18139 | { 18140 | construct_branch_pair(branch_, branch); 18141 | assert(valid()); 18142 | } 18143 | 18144 | inline T value() const exprtk_override 18145 | { 18146 | return Operation::process(branch_.first->value(),v_); 18147 | } 18148 | 18149 | inline const T& v() const exprtk_override 18150 | { 18151 | return v_; 18152 | } 18153 | 18154 | inline bool valid() const exprtk_override 18155 | { 18156 | return branch_.first && branch_.first->valid(); 18157 | } 18158 | 18159 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 18160 | { 18161 | return branch_.first; 18162 | } 18163 | 18164 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 18165 | { 18166 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 18167 | } 18168 | 18169 | std::size_t node_depth() const exprtk_override 18170 | { 18171 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 18172 | } 18173 | 18174 | private: 18175 | 18176 | bov_node(const bov_node<T,Operation>&) exprtk_delete; 18177 | bov_node<T,Operation>& operator=(const bov_node<T,Operation>&) exprtk_delete; 18178 | 18179 | const T& v_; 18180 | branch_t branch_; 18181 | }; 18182 | 18183 | template <typename T, typename Operation> 18184 | class cob_node exprtk_final : public cob_base_node<T> 18185 | { 18186 | public: 18187 | 18188 | typedef expression_node<T>* expression_ptr; 18189 | typedef std::pair<expression_ptr,bool> branch_t; 18190 | typedef Operation operation_t; 18191 | 18192 | // constant op variable node 18193 | explicit cob_node(const T const_var, const expression_ptr branch) 18194 | : c_(const_var) 18195 | { 18196 | construct_branch_pair(branch_, branch); 18197 | assert(valid()); 18198 | } 18199 | 18200 | inline T value() const exprtk_override 18201 | { 18202 | return Operation::process(c_,branch_.first->value()); 18203 | } 18204 | 18205 | inline operator_type operation() const exprtk_override 18206 | { 18207 | return Operation::operation(); 18208 | } 18209 | 18210 | inline const T c() const exprtk_override 18211 | { 18212 | return c_; 18213 | } 18214 | 18215 | inline void set_c(const T new_c) exprtk_override 18216 | { 18217 | (*const_cast<T*>(&c_)) = new_c; 18218 | } 18219 | 18220 | inline bool valid() const exprtk_override 18221 | { 18222 | return branch_.first && branch_.first->valid(); 18223 | } 18224 | 18225 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 18226 | { 18227 | return branch_.first; 18228 | } 18229 | 18230 | inline expression_node<T>* move_branch(const std::size_t&) exprtk_override 18231 | { 18232 | branch_.second = false; 18233 | return branch_.first; 18234 | } 18235 | 18236 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 18237 | { 18238 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 18239 | } 18240 | 18241 | std::size_t node_depth() const exprtk_override 18242 | { 18243 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 18244 | } 18245 | 18246 | private: 18247 | 18248 | cob_node(const cob_node<T,Operation>&) exprtk_delete; 18249 | cob_node<T,Operation>& operator=(const cob_node<T,Operation>&) exprtk_delete; 18250 | 18251 | const T c_; 18252 | branch_t branch_; 18253 | }; 18254 | 18255 | template <typename T, typename Operation> 18256 | class boc_node exprtk_final : public boc_base_node<T> 18257 | { 18258 | public: 18259 | 18260 | typedef expression_node<T>* expression_ptr; 18261 | typedef std::pair<expression_ptr,bool> branch_t; 18262 | typedef Operation operation_t; 18263 | 18264 | // binary node op constant node 18265 | explicit boc_node(const expression_ptr branch, const T const_var) 18266 | : c_(const_var) 18267 | { 18268 | construct_branch_pair(branch_, branch); 18269 | assert(valid()); 18270 | } 18271 | 18272 | inline T value() const exprtk_override 18273 | { 18274 | return Operation::process(branch_.first->value(),c_); 18275 | } 18276 | 18277 | inline operator_type operation() const exprtk_override 18278 | { 18279 | return Operation::operation(); 18280 | } 18281 | 18282 | inline const T c() const exprtk_override 18283 | { 18284 | return c_; 18285 | } 18286 | 18287 | inline void set_c(const T new_c) exprtk_override 18288 | { 18289 | (*const_cast<T*>(&c_)) = new_c; 18290 | } 18291 | 18292 | inline bool valid() const exprtk_override 18293 | { 18294 | return branch_.first && branch_.first->valid(); 18295 | } 18296 | 18297 | inline expression_node<T>* branch(const std::size_t&) const exprtk_override 18298 | { 18299 | return branch_.first; 18300 | } 18301 | 18302 | inline expression_node<T>* move_branch(const std::size_t&) exprtk_override 18303 | { 18304 | branch_.second = false; 18305 | return branch_.first; 18306 | } 18307 | 18308 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 18309 | { 18310 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 18311 | } 18312 | 18313 | std::size_t node_depth() const exprtk_override 18314 | { 18315 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 18316 | } 18317 | 18318 | private: 18319 | 18320 | boc_node(const boc_node<T,Operation>&) exprtk_delete; 18321 | boc_node<T,Operation>& operator=(const boc_node<T,Operation>&) exprtk_delete; 18322 | 18323 | const T c_; 18324 | branch_t branch_; 18325 | }; 18326 | 18327 | #ifndef exprtk_disable_string_capabilities 18328 | template <typename T, typename SType0, typename SType1, typename Operation> 18329 | class sos_node exprtk_final : public sos_base_node<T> 18330 | { 18331 | public: 18332 | 18333 | typedef expression_node<T>* expression_ptr; 18334 | typedef Operation operation_t; 18335 | 18336 | // string op string node 18337 | explicit sos_node(SType0 p0, SType1 p1) 18338 | : s0_(p0) 18339 | , s1_(p1) 18340 | {} 18341 | 18342 | inline T value() const exprtk_override 18343 | { 18344 | return Operation::process(s0_,s1_); 18345 | } 18346 | 18347 | inline typename expression_node<T>::node_type type() const exprtk_override 18348 | { 18349 | return Operation::type(); 18350 | } 18351 | 18352 | inline operator_type operation() const exprtk_override 18353 | { 18354 | return Operation::operation(); 18355 | } 18356 | 18357 | inline std::string& s0() 18358 | { 18359 | return s0_; 18360 | } 18361 | 18362 | inline std::string& s1() 18363 | { 18364 | return s1_; 18365 | } 18366 | 18367 | protected: 18368 | 18369 | SType0 s0_; 18370 | SType1 s1_; 18371 | 18372 | private: 18373 | 18374 | sos_node(const sos_node<T,SType0,SType1,Operation>&) exprtk_delete; 18375 | sos_node<T,SType0,SType1,Operation>& operator=(const sos_node<T,SType0,SType1,Operation>&) exprtk_delete; 18376 | }; 18377 | 18378 | template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation> 18379 | class str_xrox_node exprtk_final : public sos_base_node<T> 18380 | { 18381 | public: 18382 | 18383 | typedef expression_node<T>* expression_ptr; 18384 | typedef Operation operation_t; 18385 | typedef str_xrox_node<T,SType0,SType1,RangePack,Operation> node_type; 18386 | 18387 | // string-range op string node 18388 | explicit str_xrox_node(SType0 p0, SType1 p1, RangePack rp0) 18389 | : s0_ (p0 ) 18390 | , s1_ (p1 ) 18391 | , rp0_(rp0) 18392 | {} 18393 | 18394 | ~str_xrox_node() exprtk_override 18395 | { 18396 | rp0_.free(); 18397 | } 18398 | 18399 | inline T value() const exprtk_override 18400 | { 18401 | std::size_t r0 = 0; 18402 | std::size_t r1 = 0; 18403 | 18404 | if (rp0_(r0, r1, s0_.size())) 18405 | return Operation::process(s0_.substr(r0, (r1 - r0) + 1), s1_); 18406 | else 18407 | return T(0); 18408 | } 18409 | 18410 | inline typename expression_node<T>::node_type type() const exprtk_override 18411 | { 18412 | return Operation::type(); 18413 | } 18414 | 18415 | inline operator_type operation() const exprtk_override 18416 | { 18417 | return Operation::operation(); 18418 | } 18419 | 18420 | inline std::string& s0() 18421 | { 18422 | return s0_; 18423 | } 18424 | 18425 | inline std::string& s1() 18426 | { 18427 | return s1_; 18428 | } 18429 | 18430 | protected: 18431 | 18432 | SType0 s0_; 18433 | SType1 s1_; 18434 | RangePack rp0_; 18435 | 18436 | private: 18437 | 18438 | str_xrox_node(const node_type&) exprtk_delete; 18439 | node_type& operator=(const node_type&) exprtk_delete; 18440 | }; 18441 | 18442 | template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation> 18443 | class str_xoxr_node exprtk_final : public sos_base_node<T> 18444 | { 18445 | public: 18446 | 18447 | typedef expression_node<T>* expression_ptr; 18448 | typedef Operation operation_t; 18449 | typedef str_xoxr_node<T,SType0,SType1,RangePack,Operation> node_type; 18450 | 18451 | // string op string range node 18452 | explicit str_xoxr_node(SType0 p0, SType1 p1, RangePack rp1) 18453 | : s0_ (p0 ) 18454 | , s1_ (p1 ) 18455 | , rp1_(rp1) 18456 | {} 18457 | 18458 | ~str_xoxr_node() 18459 | { 18460 | rp1_.free(); 18461 | } 18462 | 18463 | inline T value() const exprtk_override 18464 | { 18465 | std::size_t r0 = 0; 18466 | std::size_t r1 = 0; 18467 | 18468 | if (rp1_(r0, r1, s1_.size())) 18469 | { 18470 | return Operation::process 18471 | ( 18472 | s0_, 18473 | s1_.substr(r0, (r1 - r0) + 1) 18474 | ); 18475 | } 18476 | else 18477 | return T(0); 18478 | } 18479 | 18480 | inline typename expression_node<T>::node_type type() const exprtk_override 18481 | { 18482 | return Operation::type(); 18483 | } 18484 | 18485 | inline operator_type operation() const exprtk_override 18486 | { 18487 | return Operation::operation(); 18488 | } 18489 | 18490 | inline std::string& s0() 18491 | { 18492 | return s0_; 18493 | } 18494 | 18495 | inline std::string& s1() 18496 | { 18497 | return s1_; 18498 | } 18499 | 18500 | protected: 18501 | 18502 | SType0 s0_; 18503 | SType1 s1_; 18504 | RangePack rp1_; 18505 | 18506 | private: 18507 | 18508 | str_xoxr_node(const node_type&) exprtk_delete; 18509 | node_type& operator=(const node_type&) exprtk_delete; 18510 | }; 18511 | 18512 | template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation> 18513 | class str_xroxr_node exprtk_final : public sos_base_node<T> 18514 | { 18515 | public: 18516 | 18517 | typedef expression_node<T>* expression_ptr; 18518 | typedef Operation operation_t; 18519 | typedef str_xroxr_node<T,SType0,SType1,RangePack,Operation> node_type; 18520 | 18521 | // string-range op string-range node 18522 | explicit str_xroxr_node(SType0 p0, SType1 p1, RangePack rp0, RangePack rp1) 18523 | : s0_ (p0 ) 18524 | , s1_ (p1 ) 18525 | , rp0_(rp0) 18526 | , rp1_(rp1) 18527 | {} 18528 | 18529 | ~str_xroxr_node() exprtk_override 18530 | { 18531 | rp0_.free(); 18532 | rp1_.free(); 18533 | } 18534 | 18535 | inline T value() const exprtk_override 18536 | { 18537 | std::size_t r0_0 = 0; 18538 | std::size_t r0_1 = 0; 18539 | std::size_t r1_0 = 0; 18540 | std::size_t r1_1 = 0; 18541 | 18542 | if ( 18543 | rp0_(r0_0, r1_0, s0_.size()) && 18544 | rp1_(r0_1, r1_1, s1_.size()) 18545 | ) 18546 | { 18547 | return Operation::process 18548 | ( 18549 | s0_.substr(r0_0, (r1_0 - r0_0) + 1), 18550 | s1_.substr(r0_1, (r1_1 - r0_1) + 1) 18551 | ); 18552 | } 18553 | else 18554 | return T(0); 18555 | } 18556 | 18557 | inline typename expression_node<T>::node_type type() const exprtk_override 18558 | { 18559 | return Operation::type(); 18560 | } 18561 | 18562 | inline operator_type operation() const exprtk_override 18563 | { 18564 | return Operation::operation(); 18565 | } 18566 | 18567 | inline std::string& s0() 18568 | { 18569 | return s0_; 18570 | } 18571 | 18572 | inline std::string& s1() 18573 | { 18574 | return s1_; 18575 | } 18576 | 18577 | protected: 18578 | 18579 | SType0 s0_; 18580 | SType1 s1_; 18581 | RangePack rp0_; 18582 | RangePack rp1_; 18583 | 18584 | private: 18585 | 18586 | str_xroxr_node(const node_type&) exprtk_delete; 18587 | node_type& operator=(const node_type&) exprtk_delete; 18588 | }; 18589 | 18590 | template <typename T, typename Operation> 18591 | class str_sogens_node exprtk_final : public binary_node<T> 18592 | { 18593 | public: 18594 | 18595 | typedef expression_node <T>* expression_ptr; 18596 | typedef string_base_node<T>* str_base_ptr; 18597 | typedef range_pack <T> range_t; 18598 | typedef range_t* range_ptr; 18599 | typedef range_interface <T> irange_t; 18600 | typedef irange_t* irange_ptr; 18601 | 18602 | using binary_node<T>::branch; 18603 | 18604 | str_sogens_node(const operator_type& opr, 18605 | expression_ptr branch0, 18606 | expression_ptr branch1) 18607 | : binary_node<T>(opr, branch0, branch1) 18608 | , str0_base_ptr_ (0) 18609 | , str1_base_ptr_ (0) 18610 | , str0_range_ptr_(0) 18611 | , str1_range_ptr_(0) 18612 | , initialised_ (false) 18613 | { 18614 | if (is_generally_string_node(branch(0))) 18615 | { 18616 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(branch(0)); 18617 | 18618 | if (0 == str0_base_ptr_) 18619 | return; 18620 | 18621 | irange_ptr range = dynamic_cast<irange_ptr>(branch(0)); 18622 | 18623 | if (0 == range) 18624 | return; 18625 | 18626 | str0_range_ptr_ = &(range->range_ref()); 18627 | } 18628 | 18629 | if (is_generally_string_node(branch(1))) 18630 | { 18631 | str1_base_ptr_ = dynamic_cast<str_base_ptr>(branch(1)); 18632 | 18633 | if (0 == str1_base_ptr_) 18634 | return; 18635 | 18636 | irange_ptr range = dynamic_cast<irange_ptr>(branch(1)); 18637 | 18638 | if (0 == range) 18639 | return; 18640 | 18641 | str1_range_ptr_ = &(range->range_ref()); 18642 | } 18643 | 18644 | initialised_ = 18645 | str0_base_ptr_ && 18646 | str1_base_ptr_ && 18647 | str0_range_ptr_ && 18648 | str1_range_ptr_; 18649 | 18650 | assert(valid()); 18651 | } 18652 | 18653 | inline T value() const exprtk_override 18654 | { 18655 | branch(0)->value(); 18656 | branch(1)->value(); 18657 | 18658 | std::size_t str0_r0 = 0; 18659 | std::size_t str0_r1 = 0; 18660 | 18661 | std::size_t str1_r0 = 0; 18662 | std::size_t str1_r1 = 0; 18663 | 18664 | const range_t& range0 = (*str0_range_ptr_); 18665 | const range_t& range1 = (*str1_range_ptr_); 18666 | 18667 | if ( 18668 | range0(str0_r0, str0_r1, str0_base_ptr_->size()) && 18669 | range1(str1_r0, str1_r1, str1_base_ptr_->size()) 18670 | ) 18671 | { 18672 | return Operation::process 18673 | ( 18674 | str0_base_ptr_->str().substr(str0_r0,(str0_r1 - str0_r0)), 18675 | str1_base_ptr_->str().substr(str1_r0,(str1_r1 - str1_r0)) 18676 | ); 18677 | } 18678 | 18679 | return std::numeric_limits<T>::quiet_NaN(); 18680 | } 18681 | 18682 | inline typename expression_node<T>::node_type type() const exprtk_override 18683 | { 18684 | return Operation::type(); 18685 | } 18686 | 18687 | inline bool valid() const exprtk_override 18688 | { 18689 | return initialised_; 18690 | } 18691 | 18692 | private: 18693 | 18694 | str_sogens_node(const str_sogens_node<T,Operation>&) exprtk_delete; 18695 | str_sogens_node<T,Operation>& operator=(const str_sogens_node<T,Operation>&) exprtk_delete; 18696 | 18697 | str_base_ptr str0_base_ptr_; 18698 | str_base_ptr str1_base_ptr_; 18699 | range_ptr str0_range_ptr_; 18700 | range_ptr str1_range_ptr_; 18701 | bool initialised_; 18702 | }; 18703 | 18704 | template <typename T, typename SType0, typename SType1, typename SType2, typename Operation> 18705 | class sosos_node exprtk_final : public sosos_base_node<T> 18706 | { 18707 | public: 18708 | 18709 | typedef expression_node<T>* expression_ptr; 18710 | typedef Operation operation_t; 18711 | typedef sosos_node<T, SType0, SType1, SType2, Operation> node_type; 18712 | 18713 | // string op string op string node 18714 | explicit sosos_node(SType0 p0, SType1 p1, SType2 p2) 18715 | : s0_(p0) 18716 | , s1_(p1) 18717 | , s2_(p2) 18718 | {} 18719 | 18720 | inline T value() const exprtk_override 18721 | { 18722 | return Operation::process(s0_, s1_, s2_); 18723 | } 18724 | 18725 | inline typename expression_node<T>::node_type type() const exprtk_override 18726 | { 18727 | return Operation::type(); 18728 | } 18729 | 18730 | inline operator_type operation() const exprtk_override 18731 | { 18732 | return Operation::operation(); 18733 | } 18734 | 18735 | inline std::string& s0() 18736 | { 18737 | return s0_; 18738 | } 18739 | 18740 | inline std::string& s1() 18741 | { 18742 | return s1_; 18743 | } 18744 | 18745 | inline std::string& s2() 18746 | { 18747 | return s2_; 18748 | } 18749 | 18750 | protected: 18751 | 18752 | SType0 s0_; 18753 | SType1 s1_; 18754 | SType2 s2_; 18755 | 18756 | private: 18757 | 18758 | sosos_node(const node_type&) exprtk_delete; 18759 | node_type& operator=(const node_type&) exprtk_delete; 18760 | }; 18761 | #endif 18762 | 18763 | template <typename T, typename PowOp> 18764 | class ipow_node exprtk_final: public expression_node<T> 18765 | { 18766 | public: 18767 | 18768 | typedef expression_node<T>* expression_ptr; 18769 | typedef PowOp operation_t; 18770 | 18771 | explicit ipow_node(const T& v) 18772 | : v_(v) 18773 | {} 18774 | 18775 | inline T value() const exprtk_override 18776 | { 18777 | return PowOp::result(v_); 18778 | } 18779 | 18780 | inline typename expression_node<T>::node_type type() const exprtk_override 18781 | { 18782 | return expression_node<T>::e_ipow; 18783 | } 18784 | 18785 | private: 18786 | 18787 | ipow_node(const ipow_node<T,PowOp>&) exprtk_delete; 18788 | ipow_node<T,PowOp>& operator=(const ipow_node<T,PowOp>&) exprtk_delete; 18789 | 18790 | const T& v_; 18791 | }; 18792 | 18793 | template <typename T, typename PowOp> 18794 | class bipow_node exprtk_final : public expression_node<T> 18795 | { 18796 | public: 18797 | 18798 | typedef expression_node<T>* expression_ptr; 18799 | typedef std::pair<expression_ptr, bool> branch_t; 18800 | typedef PowOp operation_t; 18801 | 18802 | explicit bipow_node(expression_ptr branch) 18803 | { 18804 | construct_branch_pair(branch_, branch); 18805 | assert(valid()); 18806 | } 18807 | 18808 | inline T value() const exprtk_override 18809 | { 18810 | return PowOp::result(branch_.first->value()); 18811 | } 18812 | 18813 | inline typename expression_node<T>::node_type type() const exprtk_override 18814 | { 18815 | return expression_node<T>::e_ipow; 18816 | } 18817 | 18818 | inline bool valid() const exprtk_override 18819 | { 18820 | return branch_.first && branch_.first->valid(); 18821 | } 18822 | 18823 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 18824 | { 18825 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 18826 | } 18827 | 18828 | std::size_t node_depth() const exprtk_override 18829 | { 18830 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 18831 | } 18832 | 18833 | private: 18834 | 18835 | bipow_node(const bipow_node<T,PowOp>&) exprtk_delete; 18836 | bipow_node<T,PowOp>& operator=(const bipow_node<T,PowOp>&) exprtk_delete; 18837 | 18838 | branch_t branch_; 18839 | }; 18840 | 18841 | template <typename T, typename PowOp> 18842 | class ipowinv_node exprtk_final : public expression_node<T> 18843 | { 18844 | public: 18845 | 18846 | typedef expression_node<T>* expression_ptr; 18847 | typedef PowOp operation_t; 18848 | 18849 | explicit ipowinv_node(const T& v) 18850 | : v_(v) 18851 | {} 18852 | 18853 | inline T value() const exprtk_override 18854 | { 18855 | return (T(1) / PowOp::result(v_)); 18856 | } 18857 | 18858 | inline typename expression_node<T>::node_type type() const exprtk_override 18859 | { 18860 | return expression_node<T>::e_ipowinv; 18861 | } 18862 | 18863 | private: 18864 | 18865 | ipowinv_node(const ipowinv_node<T,PowOp>&) exprtk_delete; 18866 | ipowinv_node<T,PowOp>& operator=(const ipowinv_node<T,PowOp>&) exprtk_delete; 18867 | 18868 | const T& v_; 18869 | }; 18870 | 18871 | template <typename T, typename PowOp> 18872 | class bipowinv_node exprtk_final : public expression_node<T> 18873 | { 18874 | public: 18875 | 18876 | typedef expression_node<T>* expression_ptr; 18877 | typedef std::pair<expression_ptr, bool> branch_t; 18878 | typedef PowOp operation_t; 18879 | 18880 | explicit bipowinv_node(expression_ptr branch) 18881 | { 18882 | construct_branch_pair(branch_, branch); 18883 | assert(valid()); 18884 | } 18885 | 18886 | inline T value() const exprtk_override 18887 | { 18888 | return (T(1) / PowOp::result(branch_.first->value())); 18889 | } 18890 | 18891 | inline typename expression_node<T>::node_type type() const exprtk_override 18892 | { 18893 | return expression_node<T>::e_ipowinv; 18894 | } 18895 | 18896 | inline bool valid() const exprtk_override 18897 | { 18898 | return branch_.first && branch_.first->valid(); 18899 | } 18900 | 18901 | void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) exprtk_override 18902 | { 18903 | expression_node<T>::ndb_t::collect(branch_, node_delete_list); 18904 | } 18905 | 18906 | std::size_t node_depth() const exprtk_override 18907 | { 18908 | return expression_node<T>::ndb_t::compute_node_depth(branch_); 18909 | } 18910 | 18911 | private: 18912 | 18913 | bipowinv_node(const bipowinv_node<T,PowOp>&) exprtk_delete; 18914 | bipowinv_node<T,PowOp>& operator=(const bipowinv_node<T,PowOp>&) exprtk_delete; 18915 | 18916 | branch_t branch_; 18917 | }; 18918 | 18919 | template <typename T> 18920 | inline bool is_vov_node(const expression_node<T>* node) 18921 | { 18922 | return (0 != dynamic_cast<const vov_base_node<T>*>(node)); 18923 | } 18924 | 18925 | template <typename T> 18926 | inline bool is_cov_node(const expression_node<T>* node) 18927 | { 18928 | return (0 != dynamic_cast<const cov_base_node<T>*>(node)); 18929 | } 18930 | 18931 | template <typename T> 18932 | inline bool is_voc_node(const expression_node<T>* node) 18933 | { 18934 | return (0 != dynamic_cast<const voc_base_node<T>*>(node)); 18935 | } 18936 | 18937 | template <typename T> 18938 | inline bool is_cob_node(const expression_node<T>* node) 18939 | { 18940 | return (0 != dynamic_cast<const cob_base_node<T>*>(node)); 18941 | } 18942 | 18943 | template <typename T> 18944 | inline bool is_boc_node(const expression_node<T>* node) 18945 | { 18946 | return (0 != dynamic_cast<const boc_base_node<T>*>(node)); 18947 | } 18948 | 18949 | template <typename T> 18950 | inline bool is_t0ot1ot2_node(const expression_node<T>* node) 18951 | { 18952 | return (0 != dynamic_cast<const T0oT1oT2_base_node<T>*>(node)); 18953 | } 18954 | 18955 | template <typename T> 18956 | inline bool is_t0ot1ot2ot3_node(const expression_node<T>* node) 18957 | { 18958 | return (0 != dynamic_cast<const T0oT1oT2oT3_base_node<T>*>(node)); 18959 | } 18960 | 18961 | template <typename T> 18962 | inline bool is_uv_node(const expression_node<T>* node) 18963 | { 18964 | return (0 != dynamic_cast<const uv_base_node<T>*>(node)); 18965 | } 18966 | 18967 | template <typename T> 18968 | inline bool is_string_node(const expression_node<T>* node) 18969 | { 18970 | return node && (expression_node<T>::e_stringvar == node->type()); 18971 | } 18972 | 18973 | template <typename T> 18974 | inline bool is_string_range_node(const expression_node<T>* node) 18975 | { 18976 | return node && (expression_node<T>::e_stringvarrng == node->type()); 18977 | } 18978 | 18979 | template <typename T> 18980 | inline bool is_const_string_node(const expression_node<T>* node) 18981 | { 18982 | return node && (expression_node<T>::e_stringconst == node->type()); 18983 | } 18984 | 18985 | template <typename T> 18986 | inline bool is_const_string_range_node(const expression_node<T>* node) 18987 | { 18988 | return node && (expression_node<T>::e_cstringvarrng == node->type()); 18989 | } 18990 | 18991 | template <typename T> 18992 | inline bool is_string_assignment_node(const expression_node<T>* node) 18993 | { 18994 | return node && (expression_node<T>::e_strass == node->type()); 18995 | } 18996 | 18997 | template <typename T> 18998 | inline bool is_string_concat_node(const expression_node<T>* node) 18999 | { 19000 | return node && (expression_node<T>::e_strconcat == node->type()); 19001 | } 19002 | 19003 | template <typename T> 19004 | inline bool is_string_function_node(const expression_node<T>* node) 19005 | { 19006 | return node && (expression_node<T>::e_strfunction == node->type()); 19007 | } 19008 | 19009 | template <typename T> 19010 | inline bool is_string_condition_node(const expression_node<T>* node) 19011 | { 19012 | return node && (expression_node<T>::e_strcondition == node->type()); 19013 | } 19014 | 19015 | template <typename T> 19016 | inline bool is_string_ccondition_node(const expression_node<T>* node) 19017 | { 19018 | return node && (expression_node<T>::e_strccondition == node->type()); 19019 | } 19020 | 19021 | template <typename T> 19022 | inline bool is_string_vararg_node(const expression_node<T>* node) 19023 | { 19024 | return node && (expression_node<T>::e_stringvararg == node->type()); 19025 | } 19026 | 19027 | template <typename T> 19028 | inline bool is_genricstring_range_node(const expression_node<T>* node) 19029 | { 19030 | return node && (expression_node<T>::e_strgenrange == node->type()); 19031 | } 19032 | 19033 | template <typename T> 19034 | inline bool is_generally_string_node(const expression_node<T>* node) 19035 | { 19036 | if (node) 19037 | { 19038 | switch (node->type()) 19039 | { 19040 | case expression_node<T>::e_stringvar : 19041 | case expression_node<T>::e_stringconst : 19042 | case expression_node<T>::e_stringvarrng : 19043 | case expression_node<T>::e_cstringvarrng : 19044 | case expression_node<T>::e_strgenrange : 19045 | case expression_node<T>::e_strass : 19046 | case expression_node<T>::e_strconcat : 19047 | case expression_node<T>::e_strfunction : 19048 | case expression_node<T>::e_strcondition : 19049 | case expression_node<T>::e_strccondition : 19050 | case expression_node<T>::e_stringvararg : return true; 19051 | default : return false; 19052 | } 19053 | } 19054 | 19055 | return false; 19056 | } 19057 | 19058 | template <typename T> 19059 | inline bool is_loop_node(const expression_node<T>* node) 19060 | { 19061 | if (node) 19062 | { 19063 | switch (node->type()) 19064 | { 19065 | case expression_node<T>::e_for : 19066 | case expression_node<T>::e_repeat : 19067 | case expression_node<T>::e_while : return true; 19068 | default : return false; 19069 | } 19070 | } 19071 | 19072 | return false; 19073 | } 19074 | 19075 | template <typename T> 19076 | inline bool is_block_node(const expression_node<T>* node) 19077 | { 19078 | if (node) 19079 | { 19080 | if (is_loop_node(node)) 19081 | { 19082 | return true; 19083 | } 19084 | 19085 | switch (node->type()) 19086 | { 19087 | case expression_node<T>::e_conditional : 19088 | case expression_node<T>::e_mswitch : 19089 | case expression_node<T>::e_switch : 19090 | case expression_node<T>::e_vararg : return true; 19091 | default : return false; 19092 | } 19093 | } 19094 | 19095 | return false; 19096 | } 19097 | 19098 | class node_allocator 19099 | { 19100 | public: 19101 | 19102 | template <typename ResultNode, typename OpType, typename ExprNode> 19103 | inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[1]) 19104 | { 19105 | expression_node<typename ResultNode::value_type>* result = 19106 | allocate<ResultNode>(operation, branch[0]); 19107 | result->node_depth(); 19108 | return result; 19109 | } 19110 | 19111 | template <typename ResultNode, typename OpType, typename ExprNode> 19112 | inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[2]) 19113 | { 19114 | expression_node<typename ResultNode::value_type>* result = 19115 | allocate<ResultNode>(operation, branch[0], branch[1]); 19116 | result->node_depth(); 19117 | return result; 19118 | } 19119 | 19120 | template <typename ResultNode, typename OpType, typename ExprNode> 19121 | inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[3]) 19122 | { 19123 | expression_node<typename ResultNode::value_type>* result = 19124 | allocate<ResultNode>(operation, branch[0], branch[1], branch[2]); 19125 | result->node_depth(); 19126 | return result; 19127 | } 19128 | 19129 | template <typename ResultNode, typename OpType, typename ExprNode> 19130 | inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[4]) 19131 | { 19132 | expression_node<typename ResultNode::value_type>* result = 19133 | allocate<ResultNode>(operation, branch[0], branch[1], branch[2], branch[3]); 19134 | result->node_depth(); 19135 | return result; 19136 | } 19137 | 19138 | template <typename ResultNode, typename OpType, typename ExprNode> 19139 | inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[5]) 19140 | { 19141 | expression_node<typename ResultNode::value_type>* result = 19142 | allocate<ResultNode>(operation, branch[0],branch[1], branch[2], branch[3], branch[4]); 19143 | result->node_depth(); 19144 | return result; 19145 | } 19146 | 19147 | template <typename ResultNode, typename OpType, typename ExprNode> 19148 | inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[6]) 19149 | { 19150 | expression_node<typename ResultNode::value_type>* result = 19151 | allocate<ResultNode>(operation, branch[0], branch[1], branch[2], branch[3], branch[4], branch[5]); 19152 | result->node_depth(); 19153 | return result; 19154 | } 19155 | 19156 | template <typename node_type> 19157 | inline expression_node<typename node_type::value_type>* allocate() const 19158 | { 19159 | return (new node_type()); 19160 | } 19161 | 19162 | template <typename node_type, 19163 | typename Type, 19164 | typename Allocator, 19165 | template <typename, typename> class Sequence> 19166 | inline expression_node<typename node_type::value_type>* allocate(const Sequence<Type,Allocator>& seq) const 19167 | { 19168 | expression_node<typename node_type::value_type>* 19169 | result = (new node_type(seq)); 19170 | result->node_depth(); 19171 | return result; 19172 | } 19173 | 19174 | template <typename node_type, typename T1> 19175 | inline expression_node<typename node_type::value_type>* allocate(T1& t1) const 19176 | { 19177 | expression_node<typename node_type::value_type>* 19178 | result = (new node_type(t1)); 19179 | result->node_depth(); 19180 | return result; 19181 | } 19182 | 19183 | template <typename node_type, typename T1> 19184 | inline expression_node<typename node_type::value_type>* allocate_c(const T1& t1) const 19185 | { 19186 | expression_node<typename node_type::value_type>* 19187 | result = (new node_type(t1)); 19188 | result->node_depth(); 19189 | return result; 19190 | } 19191 | 19192 | template <typename node_type, 19193 | typename T1, typename T2> 19194 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2) const 19195 | { 19196 | expression_node<typename node_type::value_type>* 19197 | result = (new node_type(t1, t2)); 19198 | result->node_depth(); 19199 | return result; 19200 | } 19201 | 19202 | template <typename node_type, 19203 | typename T1, typename T2> 19204 | inline expression_node<typename node_type::value_type>* allocate_cr(const T1& t1, T2& t2) const 19205 | { 19206 | expression_node<typename node_type::value_type>* 19207 | result = (new node_type(t1, t2)); 19208 | result->node_depth(); 19209 | return result; 19210 | } 19211 | 19212 | template <typename node_type, 19213 | typename T1, typename T2> 19214 | inline expression_node<typename node_type::value_type>* allocate_rc(T1& t1, const T2& t2) const 19215 | { 19216 | expression_node<typename node_type::value_type>* 19217 | result = (new node_type(t1, t2)); 19218 | result->node_depth(); 19219 | return result; 19220 | } 19221 | 19222 | template <typename node_type, 19223 | typename T1, typename T2> 19224 | inline expression_node<typename node_type::value_type>* allocate_rr(T1& t1, T2& t2) const 19225 | { 19226 | expression_node<typename node_type::value_type>* 19227 | result = (new node_type(t1, t2)); 19228 | result->node_depth(); 19229 | return result; 19230 | } 19231 | 19232 | template <typename node_type, 19233 | typename T1, typename T2> 19234 | inline expression_node<typename node_type::value_type>* allocate_tt(T1 t1, T2 t2) const 19235 | { 19236 | expression_node<typename node_type::value_type>* 19237 | result = (new node_type(t1, t2)); 19238 | result->node_depth(); 19239 | return result; 19240 | } 19241 | 19242 | template <typename node_type, 19243 | typename T1, typename T2, typename T3> 19244 | inline expression_node<typename node_type::value_type>* allocate_ttt(T1 t1, T2 t2, T3 t3) const 19245 | { 19246 | expression_node<typename node_type::value_type>* 19247 | result = (new node_type(t1, t2, t3)); 19248 | result->node_depth(); 19249 | return result; 19250 | } 19251 | 19252 | template <typename node_type, 19253 | typename T1, typename T2, typename T3, typename T4> 19254 | inline expression_node<typename node_type::value_type>* allocate_tttt(T1 t1, T2 t2, T3 t3, T4 t4) const 19255 | { 19256 | expression_node<typename node_type::value_type>* 19257 | result = (new node_type(t1, t2, t3, t4)); 19258 | result->node_depth(); 19259 | return result; 19260 | } 19261 | 19262 | template <typename node_type, 19263 | typename T1, typename T2, typename T3> 19264 | inline expression_node<typename node_type::value_type>* allocate_rrr(T1& t1, T2& t2, T3& t3) const 19265 | { 19266 | expression_node<typename node_type::value_type>* 19267 | result = (new node_type(t1, t2, t3)); 19268 | result->node_depth(); 19269 | return result; 19270 | } 19271 | 19272 | template <typename node_type, 19273 | typename T1, typename T2, typename T3, typename T4> 19274 | inline expression_node<typename node_type::value_type>* allocate_rrrr(T1& t1, T2& t2, T3& t3, T4& t4) const 19275 | { 19276 | expression_node<typename node_type::value_type>* 19277 | result = (new node_type(t1, t2, t3, t4)); 19278 | result->node_depth(); 19279 | return result; 19280 | } 19281 | 19282 | template <typename node_type, 19283 | typename T1, typename T2, typename T3, typename T4, typename T5> 19284 | inline expression_node<typename node_type::value_type>* allocate_rrrrr(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5) const 19285 | { 19286 | expression_node<typename node_type::value_type>* 19287 | result = (new node_type(t1, t2, t3, t4, t5)); 19288 | result->node_depth(); 19289 | return result; 19290 | } 19291 | 19292 | template <typename node_type, 19293 | typename T1, typename T2, typename T3> 19294 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19295 | const T3& t3) const 19296 | { 19297 | expression_node<typename node_type::value_type>* 19298 | result = (new node_type(t1, t2, t3)); 19299 | result->node_depth(); 19300 | return result; 19301 | } 19302 | 19303 | template <typename node_type, 19304 | typename T1, typename T2, 19305 | typename T3, typename T4> 19306 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19307 | const T3& t3, const T4& t4) const 19308 | { 19309 | expression_node<typename node_type::value_type>* 19310 | result = (new node_type(t1, t2, t3, t4)); 19311 | result->node_depth(); 19312 | return result; 19313 | } 19314 | 19315 | template <typename node_type, 19316 | typename T1, typename T2, 19317 | typename T3, typename T4, typename T5> 19318 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19319 | const T3& t3, const T4& t4, 19320 | const T5& t5) const 19321 | { 19322 | expression_node<typename node_type::value_type>* 19323 | result = (new node_type(t1, t2, t3, t4, t5)); 19324 | result->node_depth(); 19325 | return result; 19326 | } 19327 | 19328 | template <typename node_type, 19329 | typename T1, typename T2, 19330 | typename T3, typename T4, typename T5, typename T6> 19331 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19332 | const T3& t3, const T4& t4, 19333 | const T5& t5, const T6& t6) const 19334 | { 19335 | expression_node<typename node_type::value_type>* 19336 | result = (new node_type(t1, t2, t3, t4, t5, t6)); 19337 | result->node_depth(); 19338 | return result; 19339 | } 19340 | 19341 | template <typename node_type, 19342 | typename T1, typename T2, 19343 | typename T3, typename T4, 19344 | typename T5, typename T6, typename T7> 19345 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19346 | const T3& t3, const T4& t4, 19347 | const T5& t5, const T6& t6, 19348 | const T7& t7) const 19349 | { 19350 | expression_node<typename node_type::value_type>* 19351 | result = (new node_type(t1, t2, t3, t4, t5, t6, t7)); 19352 | result->node_depth(); 19353 | return result; 19354 | } 19355 | 19356 | template <typename node_type, 19357 | typename T1, typename T2, 19358 | typename T3, typename T4, 19359 | typename T5, typename T6, 19360 | typename T7, typename T8> 19361 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19362 | const T3& t3, const T4& t4, 19363 | const T5& t5, const T6& t6, 19364 | const T7& t7, const T8& t8) const 19365 | { 19366 | expression_node<typename node_type::value_type>* 19367 | result = (new node_type(t1, t2, t3, t4, t5, t6, t7, t8)); 19368 | result->node_depth(); 19369 | return result; 19370 | } 19371 | 19372 | template <typename node_type, 19373 | typename T1, typename T2, 19374 | typename T3, typename T4, 19375 | typename T5, typename T6, 19376 | typename T7, typename T8, typename T9> 19377 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19378 | const T3& t3, const T4& t4, 19379 | const T5& t5, const T6& t6, 19380 | const T7& t7, const T8& t8, 19381 | const T9& t9) const 19382 | { 19383 | expression_node<typename node_type::value_type>* 19384 | result = (new node_type(t1, t2, t3, t4, t5, t6, t7, t8, t9)); 19385 | result->node_depth(); 19386 | return result; 19387 | } 19388 | 19389 | template <typename node_type, 19390 | typename T1, typename T2, 19391 | typename T3, typename T4, 19392 | typename T5, typename T6, 19393 | typename T7, typename T8, 19394 | typename T9, typename T10> 19395 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, 19396 | const T3& t3, const T4& t4, 19397 | const T5& t5, const T6& t6, 19398 | const T7& t7, const T8& t8, 19399 | const T9& t9, const T10& t10) const 19400 | { 19401 | expression_node<typename node_type::value_type>* 19402 | result = (new node_type(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10)); 19403 | result->node_depth(); 19404 | return result; 19405 | } 19406 | 19407 | template <typename node_type, 19408 | typename T1, typename T2, typename T3> 19409 | inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, T3 t3) const 19410 | { 19411 | expression_node<typename node_type::value_type>* 19412 | result = (new node_type(t1, t2, t3)); 19413 | result->node_depth(); 19414 | return result; 19415 | } 19416 | 19417 | template <typename node_type, 19418 | typename T1, typename T2, 19419 | typename T3, typename T4> 19420 | inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, 19421 | T3 t3, T4 t4) const 19422 | { 19423 | expression_node<typename node_type::value_type>* 19424 | result = (new node_type(t1, t2, t3, t4)); 19425 | result->node_depth(); 19426 | return result; 19427 | } 19428 | 19429 | template <typename node_type, 19430 | typename T1, typename T2, 19431 | typename T3, typename T4, 19432 | typename T5> 19433 | inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, 19434 | T3 t3, T4 t4, 19435 | T5 t5) const 19436 | { 19437 | expression_node<typename node_type::value_type>* 19438 | result = (new node_type(t1, t2, t3, t4, t5)); 19439 | result->node_depth(); 19440 | return result; 19441 | } 19442 | 19443 | template <typename node_type, 19444 | typename T1, typename T2, 19445 | typename T3, typename T4, 19446 | typename T5, typename T6> 19447 | inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, 19448 | T3 t3, T4 t4, 19449 | T5 t5, T6 t6) const 19450 | { 19451 | expression_node<typename node_type::value_type>* 19452 | result = (new node_type(t1, t2, t3, t4, t5, t6)); 19453 | result->node_depth(); 19454 | return result; 19455 | } 19456 | 19457 | template <typename node_type, 19458 | typename T1, typename T2, 19459 | typename T3, typename T4, 19460 | typename T5, typename T6, typename T7> 19461 | inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, 19462 | T3 t3, T4 t4, 19463 | T5 t5, T6 t6, 19464 | T7 t7) const 19465 | { 19466 | expression_node<typename node_type::value_type>* 19467 | result = (new node_type(t1, t2, t3, t4, t5, t6, t7)); 19468 | result->node_depth(); 19469 | return result; 19470 | } 19471 | 19472 | template <typename T> 19473 | void inline free(expression_node<T>*& e) const 19474 | { 19475 | exprtk_debug(("node_allocator::free() - deleting expression_node " 19476 | "type: %03d addr: %p\n", 19477 | static_cast<int>(e->type()), 19478 | reinterpret_cast<void*>(e))); 19479 | delete e; 19480 | e = 0; 19481 | } 19482 | }; 19483 | 19484 | inline void load_operations_map(std::multimap<std::string,details::base_operation_t,details::ilesscompare>& m) 19485 | { 19486 | #define register_op(Symbol, Type, Args) \ 19487 | m.insert(std::make_pair(std::string(Symbol),details::base_operation_t(Type,Args))); \ 19488 | 19489 | register_op("abs" , e_abs , 1) 19490 | register_op("acos" , e_acos , 1) 19491 | register_op("acosh" , e_acosh , 1) 19492 | register_op("asin" , e_asin , 1) 19493 | register_op("asinh" , e_asinh , 1) 19494 | register_op("atan" , e_atan , 1) 19495 | register_op("atanh" , e_atanh , 1) 19496 | register_op("ceil" , e_ceil , 1) 19497 | register_op("cos" , e_cos , 1) 19498 | register_op("cosh" , e_cosh , 1) 19499 | register_op("exp" , e_exp , 1) 19500 | register_op("expm1" , e_expm1 , 1) 19501 | register_op("floor" , e_floor , 1) 19502 | register_op("log" , e_log , 1) 19503 | register_op("log10" , e_log10 , 1) 19504 | register_op("log2" , e_log2 , 1) 19505 | register_op("log1p" , e_log1p , 1) 19506 | register_op("round" , e_round , 1) 19507 | register_op("sin" , e_sin , 1) 19508 | register_op("sinc" , e_sinc , 1) 19509 | register_op("sinh" , e_sinh , 1) 19510 | register_op("sec" , e_sec , 1) 19511 | register_op("csc" , e_csc , 1) 19512 | register_op("sqrt" , e_sqrt , 1) 19513 | register_op("tan" , e_tan , 1) 19514 | register_op("tanh" , e_tanh , 1) 19515 | register_op("cot" , e_cot , 1) 19516 | register_op("rad2deg" , e_r2d , 1) 19517 | register_op("deg2rad" , e_d2r , 1) 19518 | register_op("deg2grad" , e_d2g , 1) 19519 | register_op("grad2deg" , e_g2d , 1) 19520 | register_op("sgn" , e_sgn , 1) 19521 | register_op("not" , e_notl , 1) 19522 | register_op("erf" , e_erf , 1) 19523 | register_op("erfc" , e_erfc , 1) 19524 | register_op("ncdf" , e_ncdf , 1) 19525 | register_op("frac" , e_frac , 1) 19526 | register_op("trunc" , e_trunc , 1) 19527 | register_op("atan2" , e_atan2 , 2) 19528 | register_op("mod" , e_mod , 2) 19529 | register_op("logn" , e_logn , 2) 19530 | register_op("pow" , e_pow , 2) 19531 | register_op("root" , e_root , 2) 19532 | register_op("roundn" , e_roundn , 2) 19533 | register_op("equal" , e_equal , 2) 19534 | register_op("not_equal" , e_nequal , 2) 19535 | register_op("hypot" , e_hypot , 2) 19536 | register_op("shr" , e_shr , 2) 19537 | register_op("shl" , e_shl , 2) 19538 | register_op("clamp" , e_clamp , 3) 19539 | register_op("iclamp" , e_iclamp , 3) 19540 | register_op("inrange" , e_inrange , 3) 19541 | #undef register_op 19542 | } 19543 | 19544 | } // namespace details 19545 | 19546 | class function_traits 19547 | { 19548 | public: 19549 | 19550 | function_traits() 19551 | : allow_zero_parameters_(false) 19552 | , has_side_effects_(true) 19553 | , min_num_args_(0) 19554 | , max_num_args_(std::numeric_limits<std::size_t>::max()) 19555 | {} 19556 | 19557 | inline bool& allow_zero_parameters() 19558 | { 19559 | return allow_zero_parameters_; 19560 | } 19561 | 19562 | inline bool& has_side_effects() 19563 | { 19564 | return has_side_effects_; 19565 | } 19566 | 19567 | std::size_t& min_num_args() 19568 | { 19569 | return min_num_args_; 19570 | } 19571 | 19572 | std::size_t& max_num_args() 19573 | { 19574 | return max_num_args_; 19575 | } 19576 | 19577 | private: 19578 | 19579 | bool allow_zero_parameters_; 19580 | bool has_side_effects_; 19581 | std::size_t min_num_args_; 19582 | std::size_t max_num_args_; 19583 | }; 19584 | 19585 | template <typename FunctionType> 19586 | void enable_zero_parameters(FunctionType& func) 19587 | { 19588 | func.allow_zero_parameters() = true; 19589 | 19590 | if (0 != func.min_num_args()) 19591 | { 19592 | func.min_num_args() = 0; 19593 | } 19594 | } 19595 | 19596 | template <typename FunctionType> 19597 | void disable_zero_parameters(FunctionType& func) 19598 | { 19599 | func.allow_zero_parameters() = false; 19600 | } 19601 | 19602 | template <typename FunctionType> 19603 | void enable_has_side_effects(FunctionType& func) 19604 | { 19605 | func.has_side_effects() = true; 19606 | } 19607 | 19608 | template <typename FunctionType> 19609 | void disable_has_side_effects(FunctionType& func) 19610 | { 19611 | func.has_side_effects() = false; 19612 | } 19613 | 19614 | template <typename FunctionType> 19615 | void set_min_num_args(FunctionType& func, const std::size_t& num_args) 19616 | { 19617 | func.min_num_args() = num_args; 19618 | 19619 | if ((0 != func.min_num_args()) && func.allow_zero_parameters()) 19620 | func.allow_zero_parameters() = false; 19621 | } 19622 | 19623 | template <typename FunctionType> 19624 | void set_max_num_args(FunctionType& func, const std::size_t& num_args) 19625 | { 19626 | func.max_num_args() = num_args; 19627 | } 19628 | 19629 | template <typename T> 19630 | class ifunction : public function_traits 19631 | { 19632 | public: 19633 | 19634 | explicit ifunction(const std::size_t& pc) 19635 | : param_count(pc) 19636 | {} 19637 | 19638 | virtual ~ifunction() 19639 | {} 19640 | 19641 | #define empty_method_body(N) \ 19642 | { \ 19643 | exprtk_debug(("ifunction::operator() - Operator(" #N ") has not been overridden\n")); \ 19644 | return std::numeric_limits<T>::quiet_NaN(); \ 19645 | } \ 19646 | 19647 | inline virtual T operator() () 19648 | empty_method_body(0) 19649 | 19650 | inline virtual T operator() (const T&) 19651 | empty_method_body(1) 19652 | 19653 | inline virtual T operator() (const T&,const T&) 19654 | empty_method_body(2) 19655 | 19656 | inline virtual T operator() (const T&, const T&, const T&) 19657 | empty_method_body(3) 19658 | 19659 | inline virtual T operator() (const T&, const T&, const T&, const T&) 19660 | empty_method_body(4) 19661 | 19662 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&) 19663 | empty_method_body(5) 19664 | 19665 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&) 19666 | empty_method_body(6) 19667 | 19668 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19669 | empty_method_body(7) 19670 | 19671 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19672 | empty_method_body(8) 19673 | 19674 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19675 | empty_method_body(9) 19676 | 19677 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) 19678 | empty_method_body(10) 19679 | 19680 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19681 | const T&) 19682 | empty_method_body(11) 19683 | 19684 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19685 | const T&, const T&) 19686 | empty_method_body(12) 19687 | 19688 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19689 | const T&, const T&, const T&) 19690 | empty_method_body(13) 19691 | 19692 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19693 | const T&, const T&, const T&, const T&) 19694 | empty_method_body(14) 19695 | 19696 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19697 | const T&, const T&, const T&, const T&, const T&) 19698 | empty_method_body(15) 19699 | 19700 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, 19701 | const T&, const T&, const T&, const T&, const T&, const T&) 19702 | empty_method_body(16) 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&, const T&, const T&, const T&, const T&, const T&, const T&) 19706 | empty_method_body(17) 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&, const T&, const T&, const T&, const T&, const T&, const T&) 19710 | empty_method_body(18) 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&, const T&, const T&, const T&, const T&, const T&, const T&) 19714 | empty_method_body(19) 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&, const T&, const T&, const T&, const T&, const T&, const T&) 19718 | empty_method_body(20) 19719 | 19720 | #undef empty_method_body 19721 | 19722 | std::size_t param_count; 19723 | }; 19724 | 19725 | template <typename T> 19726 | class ivararg_function : public function_traits 19727 | { 19728 | public: 19729 | 19730 | virtual ~ivararg_function() 19731 | {} 19732 | 19733 | inline virtual T operator() (const std::vector<T>&) 19734 | { 19735 | exprtk_debug(("ivararg_function::operator() - Operator has not been overridden\n")); 19736 | return std::numeric_limits<T>::quiet_NaN(); 19737 | } 19738 | }; 19739 | 19740 | template <typename T> 19741 | class igeneric_function : public function_traits 19742 | { 19743 | public: 19744 | 19745 | enum return_type 19746 | { 19747 | e_rtrn_scalar = 0, 19748 | e_rtrn_string = 1, 19749 | e_rtrn_overload = 2 19750 | }; 19751 | 19752 | typedef T type; 19753 | typedef type_store<T> generic_type; 19754 | typedef typename generic_type::parameter_list parameter_list_t; 19755 | 19756 | explicit igeneric_function(const std::string& param_seq = "", const return_type rtr_type = e_rtrn_scalar) 19757 | : parameter_sequence(param_seq) 19758 | , rtrn_type(rtr_type) 19759 | {} 19760 | 19761 | virtual ~igeneric_function() 19762 | {} 19763 | 19764 | #define igeneric_function_empty_body(N) \ 19765 | { \ 19766 | exprtk_debug(("igeneric_function::operator() - Operator(" #N ") has not been overridden\n")); \ 19767 | return std::numeric_limits<T>::quiet_NaN(); \ 19768 | } \ 19769 | 19770 | // f(i_0,i_1,....,i_N) --> Scalar 19771 | inline virtual T operator() (parameter_list_t) 19772 | igeneric_function_empty_body(1) 19773 | 19774 | // f(i_0,i_1,....,i_N) --> String 19775 | inline virtual T operator() (std::string&, parameter_list_t) 19776 | igeneric_function_empty_body(2) 19777 | 19778 | // f(psi,i_0,i_1,....,i_N) --> Scalar 19779 | inline virtual T operator() (const std::size_t&, parameter_list_t) 19780 | igeneric_function_empty_body(3) 19781 | 19782 | // f(psi,i_0,i_1,....,i_N) --> String 19783 | inline virtual T operator() (const std::size_t&, std::string&, parameter_list_t) 19784 | igeneric_function_empty_body(4) 19785 | 19786 | #undef igeneric_function_empty_body 19787 | 19788 | std::string parameter_sequence; 19789 | return_type rtrn_type; 19790 | }; 19791 | 19792 | #ifndef exprtk_disable_string_capabilities 19793 | template <typename T> 19794 | class stringvar_base 19795 | { 19796 | public: 19797 | 19798 | typedef typename details::stringvar_node<T> stringvar_node_t; 19799 | 19800 | stringvar_base(const std::string& name, stringvar_node_t* svn) 19801 | : name_(name) 19802 | , string_varnode_(svn) 19803 | {} 19804 | 19805 | bool valid() const 19806 | { 19807 | return !name_.empty() && (0 != string_varnode_); 19808 | } 19809 | 19810 | std::string name() const 19811 | { 19812 | assert(string_varnode_); 19813 | return name_; 19814 | } 19815 | 19816 | void rebase(std::string& s) 19817 | { 19818 | assert(string_varnode_); 19819 | string_varnode_->rebase(s); 19820 | } 19821 | 19822 | private: 19823 | 19824 | std::string name_; 19825 | stringvar_node_t* string_varnode_; 19826 | }; 19827 | #endif 19828 | 19829 | template <typename T> class parser; 19830 | template <typename T> class expression_helper; 19831 | 19832 | template <typename T> 19833 | class symbol_table 19834 | { 19835 | public: 19836 | 19837 | enum symtab_mutability_type 19838 | { 19839 | e_unknown = 0, 19840 | e_mutable = 1, 19841 | e_immutable = 2 19842 | }; 19843 | 19844 | typedef T (*ff00_functor)(); 19845 | typedef T (*ff01_functor)(T); 19846 | typedef T (*ff02_functor)(T, T); 19847 | typedef T (*ff03_functor)(T, T, T); 19848 | typedef T (*ff04_functor)(T, T, T, T); 19849 | typedef T (*ff05_functor)(T, T, T, T, T); 19850 | typedef T (*ff06_functor)(T, T, T, T, T, T); 19851 | typedef T (*ff07_functor)(T, T, T, T, T, T, T); 19852 | typedef T (*ff08_functor)(T, T, T, T, T, T, T, T); 19853 | typedef T (*ff09_functor)(T, T, T, T, T, T, T, T, T); 19854 | typedef T (*ff10_functor)(T, T, T, T, T, T, T, T, T, T); 19855 | typedef T (*ff11_functor)(T, T, T, T, T, T, T, T, T, T, T); 19856 | typedef T (*ff12_functor)(T, T, T, T, T, T, T, T, T, T, T, T); 19857 | typedef T (*ff13_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T); 19858 | typedef T (*ff14_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T); 19859 | typedef T (*ff15_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T, T); 19860 | 19861 | protected: 19862 | 19863 | struct freefunc00 exprtk_final : public exprtk::ifunction<T> 19864 | { 19865 | using exprtk::ifunction<T>::operator(); 19866 | 19867 | explicit freefunc00(ff00_functor ff) : exprtk::ifunction<T>(0), f(ff) {} 19868 | inline T operator() () exprtk_override 19869 | { return f(); } 19870 | ff00_functor f; 19871 | }; 19872 | 19873 | struct freefunc01 exprtk_final : public exprtk::ifunction<T> 19874 | { 19875 | using exprtk::ifunction<T>::operator(); 19876 | 19877 | explicit freefunc01(ff01_functor ff) : exprtk::ifunction<T>(1), f(ff) {} 19878 | inline T operator() (const T& v0) exprtk_override 19879 | { return f(v0); } 19880 | ff01_functor f; 19881 | }; 19882 | 19883 | struct freefunc02 exprtk_final : public exprtk::ifunction<T> 19884 | { 19885 | using exprtk::ifunction<T>::operator(); 19886 | 19887 | explicit freefunc02(ff02_functor ff) : exprtk::ifunction<T>(2), f(ff) {} 19888 | inline T operator() (const T& v0, const T& v1) exprtk_override 19889 | { return f(v0, v1); } 19890 | ff02_functor f; 19891 | }; 19892 | 19893 | struct freefunc03 exprtk_final : public exprtk::ifunction<T> 19894 | { 19895 | using exprtk::ifunction<T>::operator(); 19896 | 19897 | explicit freefunc03(ff03_functor ff) : exprtk::ifunction<T>(3), f(ff) {} 19898 | inline T operator() (const T& v0, const T& v1, const T& v2) exprtk_override 19899 | { return f(v0, v1, v2); } 19900 | ff03_functor f; 19901 | }; 19902 | 19903 | struct freefunc04 exprtk_final : public exprtk::ifunction<T> 19904 | { 19905 | using exprtk::ifunction<T>::operator(); 19906 | 19907 | explicit freefunc04(ff04_functor ff) : exprtk::ifunction<T>(4), f(ff) {} 19908 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3) exprtk_override 19909 | { return f(v0, v1, v2, v3); } 19910 | ff04_functor f; 19911 | }; 19912 | 19913 | struct freefunc05 : public exprtk::ifunction<T> 19914 | { 19915 | using exprtk::ifunction<T>::operator(); 19916 | 19917 | explicit freefunc05(ff05_functor ff) : exprtk::ifunction<T>(5), f(ff) {} 19918 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4) exprtk_override 19919 | { return f(v0, v1, v2, v3, v4); } 19920 | ff05_functor f; 19921 | }; 19922 | 19923 | struct freefunc06 exprtk_final : public exprtk::ifunction<T> 19924 | { 19925 | using exprtk::ifunction<T>::operator(); 19926 | 19927 | explicit freefunc06(ff06_functor ff) : exprtk::ifunction<T>(6), f(ff) {} 19928 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5) exprtk_override 19929 | { return f(v0, v1, v2, v3, v4, v5); } 19930 | ff06_functor f; 19931 | }; 19932 | 19933 | struct freefunc07 exprtk_final : public exprtk::ifunction<T> 19934 | { 19935 | using exprtk::ifunction<T>::operator(); 19936 | 19937 | explicit freefunc07(ff07_functor ff) : exprtk::ifunction<T>(7), f(ff) {} 19938 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, 19939 | const T& v5, const T& v6) exprtk_override 19940 | { return f(v0, v1, v2, v3, v4, v5, v6); } 19941 | ff07_functor f; 19942 | }; 19943 | 19944 | struct freefunc08 exprtk_final : public exprtk::ifunction<T> 19945 | { 19946 | using exprtk::ifunction<T>::operator(); 19947 | 19948 | explicit freefunc08(ff08_functor ff) : exprtk::ifunction<T>(8), f(ff) {} 19949 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, 19950 | const T& v5, const T& v6, const T& v7) exprtk_override 19951 | { return f(v0, v1, v2, v3, v4, v5, v6, v7); } 19952 | ff08_functor f; 19953 | }; 19954 | 19955 | struct freefunc09 exprtk_final : public exprtk::ifunction<T> 19956 | { 19957 | using exprtk::ifunction<T>::operator(); 19958 | 19959 | explicit freefunc09(ff09_functor ff) : exprtk::ifunction<T>(9), f(ff) {} 19960 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, 19961 | const T& v5, const T& v6, const T& v7, const T& v8) exprtk_override 19962 | { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8); } 19963 | ff09_functor f; 19964 | }; 19965 | 19966 | struct freefunc10 exprtk_final : public exprtk::ifunction<T> 19967 | { 19968 | using exprtk::ifunction<T>::operator(); 19969 | 19970 | explicit freefunc10(ff10_functor ff) : exprtk::ifunction<T>(10), f(ff) {} 19971 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, 19972 | const T& v5, const T& v6, const T& v7, const T& v8, const T& v9) exprtk_override 19973 | { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9); } 19974 | ff10_functor f; 19975 | }; 19976 | 19977 | struct freefunc11 exprtk_final : public exprtk::ifunction<T> 19978 | { 19979 | using exprtk::ifunction<T>::operator(); 19980 | 19981 | explicit freefunc11(ff11_functor ff) : exprtk::ifunction<T>(11), f(ff) {} 19982 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, 19983 | const T& v5, const T& v6, const T& v7, const T& v8, const T& v9, const T& v10) exprtk_override 19984 | { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10); } 19985 | ff11_functor f; 19986 | }; 19987 | 19988 | struct freefunc12 exprtk_final : public exprtk::ifunction<T> 19989 | { 19990 | using exprtk::ifunction<T>::operator(); 19991 | 19992 | explicit freefunc12(ff12_functor ff) : exprtk::ifunction<T>(12), f(ff) {} 19993 | inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04, 19994 | const T& v05, const T& v06, const T& v07, const T& v08, const T& v09, 19995 | const T& v10, const T& v11) exprtk_override 19996 | { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11); } 19997 | ff12_functor f; 19998 | }; 19999 | 20000 | struct freefunc13 exprtk_final : public exprtk::ifunction<T> 20001 | { 20002 | using exprtk::ifunction<T>::operator(); 20003 | 20004 | explicit freefunc13(ff13_functor ff) : exprtk::ifunction<T>(13), f(ff) {} 20005 | inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04, 20006 | const T& v05, const T& v06, const T& v07, const T& v08, const T& v09, 20007 | const T& v10, const T& v11, const T& v12) exprtk_override 20008 | { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12); } 20009 | ff13_functor f; 20010 | }; 20011 | 20012 | struct freefunc14 exprtk_final : public exprtk::ifunction<T> 20013 | { 20014 | using exprtk::ifunction<T>::operator(); 20015 | 20016 | explicit freefunc14(ff14_functor ff) : exprtk::ifunction<T>(14), 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, const T& v12, const T& v13) exprtk_override 20020 | { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12, v13); } 20021 | ff14_functor f; 20022 | }; 20023 | 20024 | struct freefunc15 exprtk_final : public exprtk::ifunction<T> 20025 | { 20026 | using exprtk::ifunction<T>::operator(); 20027 | 20028 | explicit freefunc15(ff15_functor ff) : exprtk::ifunction<T>(15), 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, const T& v13, const T& v14) exprtk_override 20032 | { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12, v13, v14); } 20033 | ff15_functor f; 20034 | }; 20035 | 20036 | template <typename Type, typename RawType> 20037 | struct type_store 20038 | { 20039 | typedef details::expression_node<T>* expression_ptr; 20040 | typedef typename details::variable_node<T> variable_node_t; 20041 | typedef ifunction<T> ifunction_t; 20042 | typedef ivararg_function<T> ivararg_function_t; 20043 | typedef igeneric_function<T> igeneric_function_t; 20044 | typedef details::vector_holder<T> vector_t; 20045 | #ifndef exprtk_disable_string_capabilities 20046 | typedef typename details::stringvar_node<T> stringvar_node_t; 20047 | #endif 20048 | 20049 | typedef Type type_t; 20050 | typedef type_t* type_ptr; 20051 | typedef std::pair<bool,type_ptr> type_pair_t; 20052 | typedef std::map<std::string,type_pair_t,details::ilesscompare> type_map_t; 20053 | typedef typename type_map_t::iterator tm_itr_t; 20054 | typedef typename type_map_t::const_iterator tm_const_itr_t; 20055 | 20056 | enum { lut_size = 256 }; 20057 | 20058 | type_map_t map; 20059 | std::size_t size; 20060 | 20061 | type_store() 20062 | : size(0) 20063 | {} 20064 | 20065 | struct deleter 20066 | { 20067 | #define exprtk_define_process(Type) \ 20068 | static inline void process(std::pair<bool,Type*>& n) \ 20069 | { \ 20070 | delete n.second; \ 20071 | } \ 20072 | 20073 | exprtk_define_process(variable_node_t ) 20074 | exprtk_define_process(vector_t ) 20075 | #ifndef exprtk_disable_string_capabilities 20076 | exprtk_define_process(stringvar_node_t) 20077 | #endif 20078 | 20079 | #undef exprtk_define_process 20080 | 20081 | template <typename DeleteType> 20082 | static inline void process(std::pair<bool,DeleteType*>&) 20083 | {} 20084 | }; 20085 | 20086 | inline bool symbol_exists(const std::string& symbol_name) const 20087 | { 20088 | if (symbol_name.empty()) 20089 | return false; 20090 | else if (map.end() != map.find(symbol_name)) 20091 | return true; 20092 | else 20093 | return false; 20094 | } 20095 | 20096 | template <typename PtrType> 20097 | inline std::string entity_name(const PtrType& ptr) const 20098 | { 20099 | if (map.empty()) 20100 | return std::string(); 20101 | 20102 | tm_const_itr_t itr = map.begin(); 20103 | 20104 | while (map.end() != itr) 20105 | { 20106 | if (itr->second.second == ptr) 20107 | { 20108 | return itr->first; 20109 | } 20110 | else 20111 | ++itr; 20112 | } 20113 | 20114 | return std::string(); 20115 | } 20116 | 20117 | inline bool is_constant(const std::string& symbol_name) const 20118 | { 20119 | if (symbol_name.empty()) 20120 | return false; 20121 | else 20122 | { 20123 | const tm_const_itr_t itr = map.find(symbol_name); 20124 | 20125 | if (map.end() == itr) 20126 | return false; 20127 | else 20128 | return (*itr).second.first; 20129 | } 20130 | } 20131 | 20132 | template <typename Tie, typename RType> 20133 | inline bool add_impl(const std::string& symbol_name, RType t, const bool is_const) 20134 | { 20135 | if (symbol_name.size() > 1) 20136 | { 20137 | for (std::size_t i = 0; i < details::reserved_symbols_size; ++i) 20138 | { 20139 | if (details::imatch(symbol_name, details::reserved_symbols[i])) 20140 | { 20141 | return false; 20142 | } 20143 | } 20144 | } 20145 | 20146 | const tm_itr_t itr = map.find(symbol_name); 20147 | 20148 | if (map.end() == itr) 20149 | { 20150 | map[symbol_name] = Tie::make(t,is_const); 20151 | ++size; 20152 | } 20153 | 20154 | return true; 20155 | } 20156 | 20157 | struct tie_array 20158 | { 20159 | static inline std::pair<bool,vector_t*> make(std::pair<T*,std::size_t> v, const bool is_const = false) 20160 | { 20161 | return std::make_pair(is_const, new vector_t(v.first, v.second)); 20162 | } 20163 | }; 20164 | 20165 | struct tie_stdvec 20166 | { 20167 | template <typename Allocator> 20168 | static inline std::pair<bool,vector_t*> make(std::vector<T,Allocator>& v, const bool is_const = false) 20169 | { 20170 | return std::make_pair(is_const, new vector_t(v)); 20171 | } 20172 | }; 20173 | 20174 | struct tie_vecview 20175 | { 20176 | static inline std::pair<bool,vector_t*> make(exprtk::vector_view<T>& v, const bool is_const = false) 20177 | { 20178 | return std::make_pair(is_const, new vector_t(v)); 20179 | } 20180 | }; 20181 | 20182 | struct tie_stddeq 20183 | { 20184 | template <typename Allocator> 20185 | static inline std::pair<bool,vector_t*> make(std::deque<T,Allocator>& v, const bool is_const = false) 20186 | { 20187 | return std::make_pair(is_const, new vector_t(v)); 20188 | } 20189 | }; 20190 | 20191 | template <std::size_t v_size> 20192 | inline bool add(const std::string& symbol_name, T (&v)[v_size], const bool is_const = false) 20193 | { 20194 | return add_impl<tie_array,std::pair<T*,std::size_t> > 20195 | (symbol_name, std::make_pair(v,v_size), is_const); 20196 | } 20197 | 20198 | inline bool add(const std::string& symbol_name, T* v, const std::size_t v_size, const bool is_const = false) 20199 | { 20200 | return add_impl<tie_array,std::pair<T*,std::size_t> > 20201 | (symbol_name, std::make_pair(v,v_size), is_const); 20202 | } 20203 | 20204 | template <typename Allocator> 20205 | inline bool add(const std::string& symbol_name, std::vector<T,Allocator>& v, const bool is_const = false) 20206 | { 20207 | return add_impl<tie_stdvec,std::vector<T,Allocator>&> 20208 | (symbol_name, v, is_const); 20209 | } 20210 | 20211 | inline bool add(const std::string& symbol_name, exprtk::vector_view<T>& v, const bool is_const = false) 20212 | { 20213 | return add_impl<tie_vecview,exprtk::vector_view<T>&> 20214 | (symbol_name, v, is_const); 20215 | } 20216 | 20217 | template <typename Allocator> 20218 | inline bool add(const std::string& symbol_name, std::deque<T,Allocator>& v, const bool is_const = false) 20219 | { 20220 | return add_impl<tie_stddeq,std::deque<T,Allocator>&> 20221 | (symbol_name, v, is_const); 20222 | } 20223 | 20224 | inline bool add(const std::string& symbol_name, RawType& t_, const bool is_const = false) 20225 | { 20226 | struct tie 20227 | { 20228 | static inline std::pair<bool,variable_node_t*> make(T& t, const bool is_constant = false) 20229 | { 20230 | return std::make_pair(is_constant, new variable_node_t(t)); 20231 | } 20232 | 20233 | #ifndef exprtk_disable_string_capabilities 20234 | static inline std::pair<bool,stringvar_node_t*> make(std::string& t, const bool is_constant = false) 20235 | { 20236 | return std::make_pair(is_constant, new stringvar_node_t(t)); 20237 | } 20238 | #endif 20239 | 20240 | static inline std::pair<bool,function_t*> make(function_t& t, const bool is_constant = false) 20241 | { 20242 | return std::make_pair(is_constant,&t); 20243 | } 20244 | 20245 | static inline std::pair<bool,vararg_function_t*> make(vararg_function_t& t, const bool is_constant = false) 20246 | { 20247 | return std::make_pair(is_constant,&t); 20248 | } 20249 | 20250 | static inline std::pair<bool,generic_function_t*> make(generic_function_t& t, const bool is_constant = false) 20251 | { 20252 | return std::make_pair(is_constant,&t); 20253 | } 20254 | }; 20255 | 20256 | const tm_itr_t itr = map.find(symbol_name); 20257 | 20258 | if (map.end() == itr) 20259 | { 20260 | map[symbol_name] = tie::make(t_,is_const); 20261 | ++size; 20262 | } 20263 | 20264 | return true; 20265 | } 20266 | 20267 | inline type_ptr get(const std::string& symbol_name) const 20268 | { 20269 | const tm_const_itr_t itr = map.find(symbol_name); 20270 | 20271 | if (map.end() == itr) 20272 | return reinterpret_cast<type_ptr>(0); 20273 | else 20274 | return itr->second.second; 20275 | } 20276 | 20277 | template <typename TType, typename TRawType, typename PtrType> 20278 | struct ptr_match 20279 | { 20280 | static inline bool test(const PtrType, const void*) 20281 | { 20282 | return false; 20283 | } 20284 | }; 20285 | 20286 | template <typename TType, typename TRawType> 20287 | struct ptr_match<TType,TRawType,variable_node_t*> 20288 | { 20289 | static inline bool test(const variable_node_t* p, const void* ptr) 20290 | { 20291 | exprtk_debug(("ptr_match::test() - %p <--> %p\n", reinterpret_cast<const void*>(&(p->ref())), ptr)); 20292 | return (&(p->ref()) == ptr); 20293 | } 20294 | }; 20295 | 20296 | inline type_ptr get_from_varptr(const void* ptr) const 20297 | { 20298 | tm_const_itr_t itr = map.begin(); 20299 | 20300 | while (map.end() != itr) 20301 | { 20302 | type_ptr ret_ptr = itr->second.second; 20303 | 20304 | if (ptr_match<Type,RawType,type_ptr>::test(ret_ptr,ptr)) 20305 | { 20306 | return ret_ptr; 20307 | } 20308 | 20309 | ++itr; 20310 | } 20311 | 20312 | return type_ptr(0); 20313 | } 20314 | 20315 | inline bool remove(const std::string& symbol_name, const bool delete_node = true) 20316 | { 20317 | const tm_itr_t itr = map.find(symbol_name); 20318 | 20319 | if (map.end() != itr) 20320 | { 20321 | if (delete_node) 20322 | { 20323 | deleter::process((*itr).second); 20324 | } 20325 | 20326 | map.erase(itr); 20327 | --size; 20328 | 20329 | return true; 20330 | } 20331 | else 20332 | return false; 20333 | } 20334 | 20335 | inline RawType& type_ref(const std::string& symbol_name) 20336 | { 20337 | struct init_type 20338 | { 20339 | static inline double set(double) { return (0.0); } 20340 | static inline double set(long double) { return (0.0); } 20341 | static inline float set(float) { return (0.0f); } 20342 | static inline std::string set(std::string) { return std::string(""); } 20343 | }; 20344 | 20345 | static RawType null_type = init_type::set(RawType()); 20346 | 20347 | const tm_const_itr_t itr = map.find(symbol_name); 20348 | 20349 | if (map.end() == itr) 20350 | return null_type; 20351 | else 20352 | return itr->second.second->ref(); 20353 | } 20354 | 20355 | inline void clear(const bool delete_node = true) 20356 | { 20357 | if (!map.empty()) 20358 | { 20359 | if (delete_node) 20360 | { 20361 | tm_itr_t itr = map.begin(); 20362 | tm_itr_t end = map.end (); 20363 | 20364 | while (end != itr) 20365 | { 20366 | deleter::process((*itr).second); 20367 | ++itr; 20368 | } 20369 | } 20370 | 20371 | map.clear(); 20372 | } 20373 | 20374 | size = 0; 20375 | } 20376 | 20377 | template <typename Allocator, 20378 | template <typename, typename> class Sequence> 20379 | inline std::size_t get_list(Sequence<std::pair<std::string,RawType>,Allocator>& list) const 20380 | { 20381 | std::size_t count = 0; 20382 | 20383 | if (!map.empty()) 20384 | { 20385 | tm_const_itr_t itr = map.begin(); 20386 | tm_const_itr_t end = map.end (); 20387 | 20388 | while (end != itr) 20389 | { 20390 | list.push_back(std::make_pair((*itr).first,itr->second.second->ref())); 20391 | ++itr; 20392 | ++count; 20393 | } 20394 | } 20395 | 20396 | return count; 20397 | } 20398 | 20399 | template <typename Allocator, 20400 | template <typename, typename> class Sequence> 20401 | inline std::size_t get_list(Sequence<std::string,Allocator>& vlist) const 20402 | { 20403 | std::size_t count = 0; 20404 | 20405 | if (!map.empty()) 20406 | { 20407 | tm_const_itr_t itr = map.begin(); 20408 | tm_const_itr_t end = map.end (); 20409 | 20410 | while (end != itr) 20411 | { 20412 | vlist.push_back((*itr).first); 20413 | ++itr; 20414 | ++count; 20415 | } 20416 | } 20417 | 20418 | return count; 20419 | } 20420 | }; 20421 | 20422 | typedef details::expression_node<T>* expression_ptr; 20423 | typedef typename details::variable_node<T> variable_t; 20424 | typedef typename details::vector_holder<T> vector_holder_t; 20425 | typedef variable_t* variable_ptr; 20426 | #ifndef exprtk_disable_string_capabilities 20427 | typedef typename details::stringvar_node<T> stringvar_t; 20428 | typedef stringvar_t* stringvar_ptr; 20429 | #endif 20430 | typedef ifunction <T> function_t; 20431 | typedef ivararg_function <T> vararg_function_t; 20432 | typedef igeneric_function<T> generic_function_t; 20433 | typedef function_t* function_ptr; 20434 | typedef vararg_function_t* vararg_function_ptr; 20435 | typedef generic_function_t* generic_function_ptr; 20436 | 20437 | static const std::size_t lut_size = 256; 20438 | 20439 | // Symbol Table Holder 20440 | struct control_block 20441 | { 20442 | struct st_data 20443 | { 20444 | type_store<variable_t , T > variable_store; 20445 | type_store<function_t , function_t > function_store; 20446 | type_store<vararg_function_t , vararg_function_t > vararg_function_store; 20447 | type_store<generic_function_t, generic_function_t> generic_function_store; 20448 | type_store<generic_function_t, generic_function_t> string_function_store; 20449 | type_store<generic_function_t, generic_function_t> overload_function_store; 20450 | type_store<vector_holder_t , vector_holder_t > vector_store; 20451 | #ifndef exprtk_disable_string_capabilities 20452 | type_store<stringvar_t , std::string > stringvar_store; 20453 | #endif 20454 | 20455 | st_data() 20456 | { 20457 | for (std::size_t i = 0; i < details::reserved_words_size; ++i) 20458 | { 20459 | reserved_symbol_table_.insert(details::reserved_words[i]); 20460 | } 20461 | 20462 | for (std::size_t i = 0; i < details::reserved_symbols_size; ++i) 20463 | { 20464 | reserved_symbol_table_.insert(details::reserved_symbols[i]); 20465 | } 20466 | } 20467 | 20468 | ~st_data() 20469 | { 20470 | for (std::size_t i = 0; i < free_function_list_.size(); ++i) 20471 | { 20472 | delete free_function_list_[i]; 20473 | } 20474 | } 20475 | 20476 | inline bool is_reserved_symbol(const std::string& symbol) const 20477 | { 20478 | return (reserved_symbol_table_.end() != reserved_symbol_table_.find(symbol)); 20479 | } 20480 | 20481 | static inline st_data* create() 20482 | { 20483 | return (new st_data); 20484 | } 20485 | 20486 | static inline void destroy(st_data*& sd) 20487 | { 20488 | delete sd; 20489 | sd = reinterpret_cast<st_data*>(0); 20490 | } 20491 | 20492 | std::list<T> local_symbol_list_; 20493 | std::list<std::string> local_stringvar_list_; 20494 | std::set<std::string> reserved_symbol_table_; 20495 | std::vector<ifunction<T>*> free_function_list_; 20496 | }; 20497 | 20498 | control_block() 20499 | : ref_count(1) 20500 | , data_(st_data::create()) 20501 | , mutability_(e_mutable) 20502 | {} 20503 | 20504 | explicit control_block(st_data* data) 20505 | : ref_count(1) 20506 | , data_(data) 20507 | , mutability_(e_mutable) 20508 | {} 20509 | 20510 | ~control_block() 20511 | { 20512 | if (data_ && (0 == ref_count)) 20513 | { 20514 | st_data::destroy(data_); 20515 | } 20516 | } 20517 | 20518 | static inline control_block* create() 20519 | { 20520 | return (new control_block); 20521 | } 20522 | 20523 | template <typename SymTab> 20524 | static inline void destroy(control_block*& cntrl_blck, SymTab* sym_tab) 20525 | { 20526 | if (cntrl_blck) 20527 | { 20528 | if ( 20529 | (0 != cntrl_blck->ref_count) && 20530 | (0 == --cntrl_blck->ref_count) 20531 | ) 20532 | { 20533 | if (sym_tab) 20534 | sym_tab->clear(); 20535 | 20536 | delete cntrl_blck; 20537 | } 20538 | 20539 | cntrl_blck = 0; 20540 | } 20541 | } 20542 | 20543 | void set_mutability(const symtab_mutability_type mutability) 20544 | { 20545 | mutability_ = mutability; 20546 | } 20547 | 20548 | std::size_t ref_count; 20549 | st_data* data_; 20550 | symtab_mutability_type mutability_; 20551 | }; 20552 | 20553 | public: 20554 | 20555 | explicit symbol_table(const symtab_mutability_type mutability = e_mutable) 20556 | : control_block_(control_block::create()) 20557 | { 20558 | control_block_->set_mutability(mutability); 20559 | clear(); 20560 | } 20561 | 20562 | ~symbol_table() 20563 | { 20564 | exprtk::details::dump_ptr("~symbol_table", this); 20565 | control_block::destroy(control_block_, this); 20566 | } 20567 | 20568 | symbol_table(const symbol_table<T>& st) 20569 | { 20570 | control_block_ = st.control_block_; 20571 | control_block_->ref_count++; 20572 | } 20573 | 20574 | inline symbol_table<T>& operator=(const symbol_table<T>& st) 20575 | { 20576 | if (this != &st) 20577 | { 20578 | control_block::destroy(control_block_,reinterpret_cast<symbol_table<T>*>(0)); 20579 | 20580 | control_block_ = st.control_block_; 20581 | control_block_->ref_count++; 20582 | } 20583 | 20584 | return (*this); 20585 | } 20586 | 20587 | inline bool operator==(const symbol_table<T>& st) const 20588 | { 20589 | return (this == &st) || (control_block_ == st.control_block_); 20590 | } 20591 | 20592 | inline symtab_mutability_type mutability() const 20593 | { 20594 | return valid() ? control_block_->mutability_ : e_unknown; 20595 | } 20596 | 20597 | inline void clear_variables(const bool delete_node = true) 20598 | { 20599 | local_data().variable_store.clear(delete_node); 20600 | } 20601 | 20602 | inline void clear_functions() 20603 | { 20604 | local_data().function_store.clear(); 20605 | } 20606 | 20607 | inline void clear_strings() 20608 | { 20609 | #ifndef exprtk_disable_string_capabilities 20610 | local_data().stringvar_store.clear(); 20611 | #endif 20612 | } 20613 | 20614 | inline void clear_vectors() 20615 | { 20616 | local_data().vector_store.clear(); 20617 | } 20618 | 20619 | inline void clear_local_constants() 20620 | { 20621 | local_data().local_symbol_list_.clear(); 20622 | } 20623 | 20624 | inline void clear() 20625 | { 20626 | if (!valid()) return; 20627 | clear_variables (); 20628 | clear_functions (); 20629 | clear_strings (); 20630 | clear_vectors (); 20631 | clear_local_constants(); 20632 | } 20633 | 20634 | inline std::size_t variable_count() const 20635 | { 20636 | if (valid()) 20637 | return local_data().variable_store.size; 20638 | else 20639 | return 0; 20640 | } 20641 | 20642 | #ifndef exprtk_disable_string_capabilities 20643 | inline std::size_t stringvar_count() const 20644 | { 20645 | if (valid()) 20646 | return local_data().stringvar_store.size; 20647 | else 20648 | return 0; 20649 | } 20650 | #endif 20651 | 20652 | inline std::size_t function_count() const 20653 | { 20654 | if (valid()) 20655 | return local_data().function_store.size; 20656 | else 20657 | return 0; 20658 | } 20659 | 20660 | inline std::size_t vector_count() const 20661 | { 20662 | if (valid()) 20663 | return local_data().vector_store.size; 20664 | else 20665 | return 0; 20666 | } 20667 | 20668 | inline variable_ptr get_variable(const std::string& variable_name) const 20669 | { 20670 | if (!valid()) 20671 | return reinterpret_cast<variable_ptr>(0); 20672 | else if (!valid_symbol(variable_name)) 20673 | return reinterpret_cast<variable_ptr>(0); 20674 | else 20675 | return local_data().variable_store.get(variable_name); 20676 | } 20677 | 20678 | inline variable_ptr get_variable(const T& var_ref) const 20679 | { 20680 | if (!valid()) 20681 | return reinterpret_cast<variable_ptr>(0); 20682 | else 20683 | return local_data().variable_store.get_from_varptr( 20684 | reinterpret_cast<const void*>(&var_ref)); 20685 | } 20686 | 20687 | #ifndef exprtk_disable_string_capabilities 20688 | inline stringvar_ptr get_stringvar(const std::string& string_name) const 20689 | { 20690 | if (!valid()) 20691 | return reinterpret_cast<stringvar_ptr>(0); 20692 | else if (!valid_symbol(string_name)) 20693 | return reinterpret_cast<stringvar_ptr>(0); 20694 | else 20695 | return local_data().stringvar_store.get(string_name); 20696 | } 20697 | 20698 | inline stringvar_base<T> get_stringvar_base(const std::string& string_name) const 20699 | { 20700 | static stringvar_base<T> null_stringvar_base("",reinterpret_cast<stringvar_ptr>(0)); 20701 | if (!valid()) 20702 | return null_stringvar_base; 20703 | else if (!valid_symbol(string_name)) 20704 | return null_stringvar_base; 20705 | 20706 | stringvar_ptr stringvar = local_data().stringvar_store.get(string_name); 20707 | 20708 | if (0 == stringvar) 20709 | { 20710 | return null_stringvar_base; 20711 | } 20712 | 20713 | return stringvar_base<T>(string_name,stringvar); 20714 | } 20715 | #endif 20716 | 20717 | inline function_ptr get_function(const std::string& function_name) const 20718 | { 20719 | if (!valid()) 20720 | return reinterpret_cast<function_ptr>(0); 20721 | else if (!valid_symbol(function_name)) 20722 | return reinterpret_cast<function_ptr>(0); 20723 | else 20724 | return local_data().function_store.get(function_name); 20725 | } 20726 | 20727 | inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name) const 20728 | { 20729 | if (!valid()) 20730 | return reinterpret_cast<vararg_function_ptr>(0); 20731 | else if (!valid_symbol(vararg_function_name)) 20732 | return reinterpret_cast<vararg_function_ptr>(0); 20733 | else 20734 | return local_data().vararg_function_store.get(vararg_function_name); 20735 | } 20736 | 20737 | inline generic_function_ptr get_generic_function(const std::string& function_name) const 20738 | { 20739 | if (!valid()) 20740 | return reinterpret_cast<generic_function_ptr>(0); 20741 | else if (!valid_symbol(function_name)) 20742 | return reinterpret_cast<generic_function_ptr>(0); 20743 | else 20744 | return local_data().generic_function_store.get(function_name); 20745 | } 20746 | 20747 | inline generic_function_ptr get_string_function(const std::string& function_name) const 20748 | { 20749 | if (!valid()) 20750 | return reinterpret_cast<generic_function_ptr>(0); 20751 | else if (!valid_symbol(function_name)) 20752 | return reinterpret_cast<generic_function_ptr>(0); 20753 | else 20754 | return local_data().string_function_store.get(function_name); 20755 | } 20756 | 20757 | inline generic_function_ptr get_overload_function(const std::string& function_name) const 20758 | { 20759 | if (!valid()) 20760 | return reinterpret_cast<generic_function_ptr>(0); 20761 | else if (!valid_symbol(function_name)) 20762 | return reinterpret_cast<generic_function_ptr>(0); 20763 | else 20764 | return local_data().overload_function_store.get(function_name); 20765 | } 20766 | 20767 | typedef vector_holder_t* vector_holder_ptr; 20768 | 20769 | inline vector_holder_ptr get_vector(const std::string& vector_name) const 20770 | { 20771 | if (!valid()) 20772 | return reinterpret_cast<vector_holder_ptr>(0); 20773 | else if (!valid_symbol(vector_name)) 20774 | return reinterpret_cast<vector_holder_ptr>(0); 20775 | else 20776 | return local_data().vector_store.get(vector_name); 20777 | } 20778 | 20779 | inline T& variable_ref(const std::string& symbol_name) 20780 | { 20781 | static T null_var = T(0); 20782 | if (!valid()) 20783 | return null_var; 20784 | else if (!valid_symbol(symbol_name)) 20785 | return null_var; 20786 | else 20787 | return local_data().variable_store.type_ref(symbol_name); 20788 | } 20789 | 20790 | #ifndef exprtk_disable_string_capabilities 20791 | inline std::string& stringvar_ref(const std::string& symbol_name) 20792 | { 20793 | static std::string null_stringvar; 20794 | if (!valid()) 20795 | return null_stringvar; 20796 | else if (!valid_symbol(symbol_name)) 20797 | return null_stringvar; 20798 | else 20799 | return local_data().stringvar_store.type_ref(symbol_name); 20800 | } 20801 | #endif 20802 | 20803 | inline bool is_constant_node(const std::string& symbol_name) const 20804 | { 20805 | if (!valid()) 20806 | return false; 20807 | else if (!valid_symbol(symbol_name)) 20808 | return false; 20809 | else 20810 | return local_data().variable_store.is_constant(symbol_name); 20811 | } 20812 | 20813 | #ifndef exprtk_disable_string_capabilities 20814 | inline bool is_constant_string(const std::string& symbol_name) const 20815 | { 20816 | if (!valid()) 20817 | return false; 20818 | else if (!valid_symbol(symbol_name)) 20819 | return false; 20820 | else if (!local_data().stringvar_store.symbol_exists(symbol_name)) 20821 | return false; 20822 | else 20823 | return local_data().stringvar_store.is_constant(symbol_name); 20824 | } 20825 | #endif 20826 | 20827 | inline bool create_variable(const std::string& variable_name, const T& value = T(0)) 20828 | { 20829 | if (!valid()) 20830 | return false; 20831 | else if (!valid_symbol(variable_name)) 20832 | return false; 20833 | else if (symbol_exists(variable_name)) 20834 | return false; 20835 | 20836 | local_data().local_symbol_list_.push_back(value); 20837 | T& t = local_data().local_symbol_list_.back(); 20838 | 20839 | return add_variable(variable_name,t); 20840 | } 20841 | 20842 | #ifndef exprtk_disable_string_capabilities 20843 | inline bool create_stringvar(const std::string& stringvar_name, const std::string& value = std::string("")) 20844 | { 20845 | if (!valid()) 20846 | return false; 20847 | else if (!valid_symbol(stringvar_name)) 20848 | return false; 20849 | else if (symbol_exists(stringvar_name)) 20850 | return false; 20851 | 20852 | local_data().local_stringvar_list_.push_back(value); 20853 | std::string& s = local_data().local_stringvar_list_.back(); 20854 | 20855 | return add_stringvar(stringvar_name,s); 20856 | } 20857 | #endif 20858 | 20859 | inline bool add_variable(const std::string& variable_name, T& t, const bool is_constant = false) 20860 | { 20861 | if (!valid()) 20862 | return false; 20863 | else if (!valid_symbol(variable_name)) 20864 | return false; 20865 | else if (symbol_exists(variable_name)) 20866 | return false; 20867 | else 20868 | return local_data().variable_store.add(variable_name, t, is_constant); 20869 | } 20870 | 20871 | inline bool add_constant(const std::string& constant_name, const T& value) 20872 | { 20873 | if (!valid()) 20874 | return false; 20875 | else if (!valid_symbol(constant_name)) 20876 | return false; 20877 | else if (symbol_exists(constant_name)) 20878 | return false; 20879 | 20880 | local_data().local_symbol_list_.push_back(value); 20881 | T& t = local_data().local_symbol_list_.back(); 20882 | 20883 | return add_variable(constant_name, t, true); 20884 | } 20885 | 20886 | #ifndef exprtk_disable_string_capabilities 20887 | inline bool add_stringvar(const std::string& stringvar_name, std::string& s, const bool is_constant = false) 20888 | { 20889 | if (!valid()) 20890 | return false; 20891 | else if (!valid_symbol(stringvar_name)) 20892 | return false; 20893 | else if (symbol_exists(stringvar_name)) 20894 | return false; 20895 | else 20896 | return local_data().stringvar_store.add(stringvar_name, s, is_constant); 20897 | } 20898 | #endif 20899 | 20900 | inline bool add_function(const std::string& function_name, function_t& function) 20901 | { 20902 | if (!valid()) 20903 | return false; 20904 | else if (!valid_symbol(function_name)) 20905 | return false; 20906 | else if (symbol_exists(function_name)) 20907 | return false; 20908 | else 20909 | return local_data().function_store.add(function_name,function); 20910 | } 20911 | 20912 | inline bool add_function(const std::string& vararg_function_name, vararg_function_t& vararg_function) 20913 | { 20914 | if (!valid()) 20915 | return false; 20916 | else if (!valid_symbol(vararg_function_name)) 20917 | return false; 20918 | else if (symbol_exists(vararg_function_name)) 20919 | return false; 20920 | else 20921 | return local_data().vararg_function_store.add(vararg_function_name,vararg_function); 20922 | } 20923 | 20924 | inline bool add_function(const std::string& function_name, generic_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 | { 20934 | switch (function.rtrn_type) 20935 | { 20936 | case generic_function_t::e_rtrn_scalar : 20937 | return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ? 20938 | local_data().generic_function_store.add(function_name,function) : false; 20939 | 20940 | case generic_function_t::e_rtrn_string : 20941 | return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ? 20942 | local_data().string_function_store.add(function_name,function) : false; 20943 | 20944 | case generic_function_t::e_rtrn_overload : 20945 | return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|:")) ? 20946 | local_data().overload_function_store.add(function_name,function) : false; 20947 | } 20948 | } 20949 | 20950 | return false; 20951 | } 20952 | 20953 | #define exprtk_define_freefunction(NN) \ 20954 | inline bool add_function(const std::string& function_name, ff##NN##_functor function) \ 20955 | { \ 20956 | if (!valid()) \ 20957 | { return false; } \ 20958 | if (!valid_symbol(function_name)) \ 20959 | { return false; } \ 20960 | if (symbol_exists(function_name)) \ 20961 | { return false; } \ 20962 | \ 20963 | exprtk::ifunction<T>* ifunc = new freefunc##NN(function); \ 20964 | \ 20965 | local_data().free_function_list_.push_back(ifunc); \ 20966 | \ 20967 | return add_function(function_name,(*local_data().free_function_list_.back())); \ 20968 | } \ 20969 | 20970 | exprtk_define_freefunction(00) exprtk_define_freefunction(01) 20971 | exprtk_define_freefunction(02) exprtk_define_freefunction(03) 20972 | exprtk_define_freefunction(04) exprtk_define_freefunction(05) 20973 | exprtk_define_freefunction(06) exprtk_define_freefunction(07) 20974 | exprtk_define_freefunction(08) exprtk_define_freefunction(09) 20975 | exprtk_define_freefunction(10) exprtk_define_freefunction(11) 20976 | exprtk_define_freefunction(12) exprtk_define_freefunction(13) 20977 | exprtk_define_freefunction(14) exprtk_define_freefunction(15) 20978 | 20979 | #undef exprtk_define_freefunction 20980 | 20981 | inline bool add_reserved_function(const std::string& function_name, function_t& function) 20982 | { 20983 | if (!valid()) 20984 | return false; 20985 | else if (!valid_symbol(function_name,false)) 20986 | return false; 20987 | else if (symbol_exists(function_name,false)) 20988 | return false; 20989 | else 20990 | return local_data().function_store.add(function_name,function); 20991 | } 20992 | 20993 | inline bool add_reserved_function(const std::string& vararg_function_name, vararg_function_t& vararg_function) 20994 | { 20995 | if (!valid()) 20996 | return false; 20997 | else if (!valid_symbol(vararg_function_name,false)) 20998 | return false; 20999 | else if (symbol_exists(vararg_function_name,false)) 21000 | return false; 21001 | else 21002 | return local_data().vararg_function_store.add(vararg_function_name,vararg_function); 21003 | } 21004 | 21005 | inline bool add_reserved_function(const std::string& function_name, generic_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 | { 21015 | switch (function.rtrn_type) 21016 | { 21017 | case generic_function_t::e_rtrn_scalar : 21018 | return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ? 21019 | local_data().generic_function_store.add(function_name,function) : false; 21020 | 21021 | case generic_function_t::e_rtrn_string : 21022 | return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ? 21023 | local_data().string_function_store.add(function_name,function) : false; 21024 | 21025 | case generic_function_t::e_rtrn_overload : 21026 | return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|:")) ? 21027 | local_data().overload_function_store.add(function_name,function) : false; 21028 | } 21029 | } 21030 | 21031 | return false; 21032 | } 21033 | 21034 | #define exprtk_define_reserved_function(NN) \ 21035 | inline bool add_reserved_function(const std::string& function_name, ff##NN##_functor function) \ 21036 | { \ 21037 | if (!valid()) \ 21038 | { return false; } \ 21039 | if (!valid_symbol(function_name,false)) \ 21040 | { return false; } \ 21041 | if (symbol_exists(function_name,false)) \ 21042 | { return false; } \ 21043 | \ 21044 | exprtk::ifunction<T>* ifunc = new freefunc##NN(function); \ 21045 | \ 21046 | local_data().free_function_list_.push_back(ifunc); \ 21047 | \ 21048 | return add_reserved_function(function_name,(*local_data().free_function_list_.back())); \ 21049 | } \ 21050 | 21051 | exprtk_define_reserved_function(00) exprtk_define_reserved_function(01) 21052 | exprtk_define_reserved_function(02) exprtk_define_reserved_function(03) 21053 | exprtk_define_reserved_function(04) exprtk_define_reserved_function(05) 21054 | exprtk_define_reserved_function(06) exprtk_define_reserved_function(07) 21055 | exprtk_define_reserved_function(08) exprtk_define_reserved_function(09) 21056 | exprtk_define_reserved_function(10) exprtk_define_reserved_function(11) 21057 | exprtk_define_reserved_function(12) exprtk_define_reserved_function(13) 21058 | exprtk_define_reserved_function(14) exprtk_define_reserved_function(15) 21059 | 21060 | #undef exprtk_define_reserved_function 21061 | 21062 | template <std::size_t N> 21063 | inline bool add_vector(const std::string& vector_name, T (&v)[N]) 21064 | { 21065 | if (!valid()) 21066 | return false; 21067 | else if (!valid_symbol(vector_name)) 21068 | return false; 21069 | else if (symbol_exists(vector_name)) 21070 | return false; 21071 | else 21072 | return local_data().vector_store.add(vector_name,v); 21073 | } 21074 | 21075 | inline bool add_vector(const std::string& vector_name, T* v, const std::size_t& v_size) 21076 | { 21077 | if (!valid()) 21078 | return false; 21079 | else if (!valid_symbol(vector_name)) 21080 | return false; 21081 | else if (symbol_exists(vector_name)) 21082 | return false; 21083 | else if (0 == v_size) 21084 | return false; 21085 | else 21086 | return local_data().vector_store.add(vector_name, v, v_size); 21087 | } 21088 | 21089 | template <typename Allocator> 21090 | inline bool add_vector(const std::string& vector_name, std::vector<T,Allocator>& v) 21091 | { 21092 | if (!valid()) 21093 | return false; 21094 | else if (!valid_symbol(vector_name)) 21095 | return false; 21096 | else if (symbol_exists(vector_name)) 21097 | return false; 21098 | else if (0 == v.size()) 21099 | return false; 21100 | else 21101 | return local_data().vector_store.add(vector_name,v); 21102 | } 21103 | 21104 | inline bool add_vector(const std::string& vector_name, exprtk::vector_view<T>& v) 21105 | { 21106 | if (!valid()) 21107 | return false; 21108 | else if (!valid_symbol(vector_name)) 21109 | return false; 21110 | else if (symbol_exists(vector_name)) 21111 | return false; 21112 | else if (0 == v.size()) 21113 | return false; 21114 | else 21115 | return local_data().vector_store.add(vector_name,v); 21116 | } 21117 | 21118 | inline bool remove_variable(const std::string& variable_name, const bool delete_node = true) 21119 | { 21120 | if (!valid()) 21121 | return false; 21122 | else 21123 | return local_data().variable_store.remove(variable_name, delete_node); 21124 | } 21125 | 21126 | #ifndef exprtk_disable_string_capabilities 21127 | inline bool remove_stringvar(const std::string& string_name) 21128 | { 21129 | if (!valid()) 21130 | return false; 21131 | else 21132 | return local_data().stringvar_store.remove(string_name); 21133 | } 21134 | #endif 21135 | 21136 | inline bool remove_function(const std::string& function_name) 21137 | { 21138 | if (!valid()) 21139 | return false; 21140 | else 21141 | return local_data().function_store.remove(function_name); 21142 | } 21143 | 21144 | inline bool remove_vararg_function(const std::string& vararg_function_name) 21145 | { 21146 | if (!valid()) 21147 | return false; 21148 | else 21149 | return local_data().vararg_function_store.remove(vararg_function_name); 21150 | } 21151 | 21152 | inline bool remove_vector(const std::string& vector_name) 21153 | { 21154 | if (!valid()) 21155 | return false; 21156 | else 21157 | return local_data().vector_store.remove(vector_name); 21158 | } 21159 | 21160 | inline bool add_constants() 21161 | { 21162 | return add_pi () && 21163 | add_epsilon () && 21164 | add_infinity() ; 21165 | } 21166 | 21167 | inline bool add_pi() 21168 | { 21169 | const typename details::numeric::details::number_type<T>::type num_type; 21170 | static const T local_pi = details::numeric::details::const_pi_impl<T>(num_type); 21171 | return add_constant("pi",local_pi); 21172 | } 21173 | 21174 | inline bool add_epsilon() 21175 | { 21176 | static const T local_epsilon = details::numeric::details::epsilon_type<T>::value(); 21177 | return add_constant("epsilon",local_epsilon); 21178 | } 21179 | 21180 | inline bool add_infinity() 21181 | { 21182 | static const T local_infinity = std::numeric_limits<T>::infinity(); 21183 | return add_constant("inf",local_infinity); 21184 | } 21185 | 21186 | template <typename Package> 21187 | inline bool add_package(Package& package) 21188 | { 21189 | return package.register_package(*this); 21190 | } 21191 | 21192 | template <typename Allocator, 21193 | template <typename, typename> class Sequence> 21194 | inline std::size_t get_variable_list(Sequence<std::pair<std::string,T>,Allocator>& vlist) const 21195 | { 21196 | if (!valid()) 21197 | return 0; 21198 | else 21199 | return local_data().variable_store.get_list(vlist); 21200 | } 21201 | 21202 | template <typename Allocator, 21203 | template <typename, typename> class Sequence> 21204 | inline std::size_t get_variable_list(Sequence<std::string,Allocator>& vlist) const 21205 | { 21206 | if (!valid()) 21207 | return 0; 21208 | else 21209 | return local_data().variable_store.get_list(vlist); 21210 | } 21211 | 21212 | #ifndef exprtk_disable_string_capabilities 21213 | template <typename Allocator, 21214 | template <typename, typename> class Sequence> 21215 | inline std::size_t get_stringvar_list(Sequence<std::pair<std::string,std::string>,Allocator>& svlist) const 21216 | { 21217 | if (!valid()) 21218 | return 0; 21219 | else 21220 | return local_data().stringvar_store.get_list(svlist); 21221 | } 21222 | 21223 | template <typename Allocator, 21224 | template <typename, typename> class Sequence> 21225 | inline std::size_t get_stringvar_list(Sequence<std::string,Allocator>& svlist) const 21226 | { 21227 | if (!valid()) 21228 | return 0; 21229 | else 21230 | return local_data().stringvar_store.get_list(svlist); 21231 | } 21232 | #endif 21233 | 21234 | template <typename Allocator, 21235 | template <typename, typename> class Sequence> 21236 | inline std::size_t get_vector_list(Sequence<std::string,Allocator>& vec_list) const 21237 | { 21238 | if (!valid()) 21239 | return 0; 21240 | else 21241 | return local_data().vector_store.get_list(vec_list); 21242 | } 21243 | 21244 | template <typename Allocator, 21245 | template <typename, typename> class Sequence> 21246 | inline std::size_t get_function_list(Sequence<std::string,Allocator>& function_list) const 21247 | { 21248 | if (!valid()) 21249 | return 0; 21250 | 21251 | std::vector<std::string> function_names; 21252 | std::size_t count = 0; 21253 | 21254 | count += local_data().function_store .get_list(function_names); 21255 | count += local_data().vararg_function_store .get_list(function_names); 21256 | count += local_data().generic_function_store .get_list(function_names); 21257 | count += local_data().string_function_store .get_list(function_names); 21258 | count += local_data().overload_function_store.get_list(function_names); 21259 | 21260 | std::set<std::string> function_set; 21261 | 21262 | for (std::size_t i = 0; i < function_names.size(); ++i) 21263 | { 21264 | function_set.insert(function_names[i]); 21265 | } 21266 | 21267 | std::copy(function_set.begin(), function_set.end(), 21268 | std::back_inserter(function_list)); 21269 | 21270 | return count; 21271 | } 21272 | 21273 | inline std::vector<std::string> get_function_list() const 21274 | { 21275 | std::vector<std::string> result; 21276 | get_function_list(result); 21277 | return result; 21278 | } 21279 | 21280 | inline bool symbol_exists(const std::string& symbol_name, const bool check_reserved_symb = true) const 21281 | { 21282 | /* 21283 | Function will return true if symbol_name exists as either a 21284 | reserved symbol, variable, stringvar, vector or function name 21285 | in any of the type stores. 21286 | */ 21287 | if (!valid()) 21288 | return false; 21289 | else if (local_data().variable_store.symbol_exists(symbol_name)) 21290 | return true; 21291 | #ifndef exprtk_disable_string_capabilities 21292 | else if (local_data().stringvar_store.symbol_exists(symbol_name)) 21293 | return true; 21294 | #endif 21295 | else if (local_data().vector_store.symbol_exists(symbol_name)) 21296 | return true; 21297 | else if (local_data().function_store.symbol_exists(symbol_name)) 21298 | return true; 21299 | else if (check_reserved_symb && local_data().is_reserved_symbol(symbol_name)) 21300 | return true; 21301 | else 21302 | return false; 21303 | } 21304 | 21305 | inline bool is_variable(const std::string& variable_name) const 21306 | { 21307 | if (!valid()) 21308 | return false; 21309 | else 21310 | return local_data().variable_store.symbol_exists(variable_name); 21311 | } 21312 | 21313 | #ifndef exprtk_disable_string_capabilities 21314 | inline bool is_stringvar(const std::string& stringvar_name) const 21315 | { 21316 | if (!valid()) 21317 | return false; 21318 | else 21319 | return local_data().stringvar_store.symbol_exists(stringvar_name); 21320 | } 21321 | 21322 | inline bool is_conststr_stringvar(const std::string& symbol_name) const 21323 | { 21324 | if (!valid()) 21325 | return false; 21326 | else if (!valid_symbol(symbol_name)) 21327 | return false; 21328 | else if (!local_data().stringvar_store.symbol_exists(symbol_name)) 21329 | return false; 21330 | 21331 | return ( 21332 | local_data().stringvar_store.symbol_exists(symbol_name) || 21333 | local_data().stringvar_store.is_constant (symbol_name) 21334 | ); 21335 | } 21336 | #endif 21337 | 21338 | inline bool is_function(const std::string& function_name) const 21339 | { 21340 | if (!valid()) 21341 | return false; 21342 | else 21343 | return local_data().function_store.symbol_exists(function_name); 21344 | } 21345 | 21346 | inline bool is_vararg_function(const std::string& vararg_function_name) const 21347 | { 21348 | if (!valid()) 21349 | return false; 21350 | else 21351 | return local_data().vararg_function_store.symbol_exists(vararg_function_name); 21352 | } 21353 | 21354 | inline bool is_vector(const std::string& vector_name) const 21355 | { 21356 | if (!valid()) 21357 | return false; 21358 | else 21359 | return local_data().vector_store.symbol_exists(vector_name); 21360 | } 21361 | 21362 | inline std::string get_variable_name(const expression_ptr& ptr) const 21363 | { 21364 | return local_data().variable_store.entity_name(ptr); 21365 | } 21366 | 21367 | inline std::string get_vector_name(const vector_holder_ptr& ptr) const 21368 | { 21369 | return local_data().vector_store.entity_name(ptr); 21370 | } 21371 | 21372 | #ifndef exprtk_disable_string_capabilities 21373 | inline std::string get_stringvar_name(const expression_ptr& ptr) const 21374 | { 21375 | return local_data().stringvar_store.entity_name(ptr); 21376 | } 21377 | 21378 | inline std::string get_conststr_stringvar_name(const expression_ptr& ptr) const 21379 | { 21380 | return local_data().stringvar_store.entity_name(ptr); 21381 | } 21382 | #endif 21383 | 21384 | inline bool valid() const 21385 | { 21386 | // Symbol table sanity check. 21387 | return control_block_ && control_block_->data_; 21388 | } 21389 | 21390 | inline void load_from(const symbol_table<T>& st) 21391 | { 21392 | { 21393 | std::vector<std::string> name_list; 21394 | 21395 | st.local_data().function_store.get_list(name_list); 21396 | 21397 | if (!name_list.empty()) 21398 | { 21399 | for (std::size_t i = 0; i < name_list.size(); ++i) 21400 | { 21401 | exprtk::ifunction<T>& ifunc = *st.get_function(name_list[i]); 21402 | add_function(name_list[i],ifunc); 21403 | } 21404 | } 21405 | } 21406 | 21407 | { 21408 | std::vector<std::string> name_list; 21409 | 21410 | st.local_data().vararg_function_store.get_list(name_list); 21411 | 21412 | if (!name_list.empty()) 21413 | { 21414 | for (std::size_t i = 0; i < name_list.size(); ++i) 21415 | { 21416 | exprtk::ivararg_function<T>& ivafunc = *st.get_vararg_function(name_list[i]); 21417 | add_function(name_list[i],ivafunc); 21418 | } 21419 | } 21420 | } 21421 | 21422 | { 21423 | std::vector<std::string> name_list; 21424 | 21425 | st.local_data().generic_function_store.get_list(name_list); 21426 | 21427 | if (!name_list.empty()) 21428 | { 21429 | for (std::size_t i = 0; i < name_list.size(); ++i) 21430 | { 21431 | exprtk::igeneric_function<T>& ifunc = *st.get_generic_function(name_list[i]); 21432 | add_function(name_list[i],ifunc); 21433 | } 21434 | } 21435 | } 21436 | 21437 | { 21438 | std::vector<std::string> name_list; 21439 | 21440 | st.local_data().string_function_store.get_list(name_list); 21441 | 21442 | if (!name_list.empty()) 21443 | { 21444 | for (std::size_t i = 0; i < name_list.size(); ++i) 21445 | { 21446 | exprtk::igeneric_function<T>& ifunc = *st.get_string_function(name_list[i]); 21447 | add_function(name_list[i],ifunc); 21448 | } 21449 | } 21450 | } 21451 | 21452 | { 21453 | std::vector<std::string> name_list; 21454 | 21455 | st.local_data().overload_function_store.get_list(name_list); 21456 | 21457 | if (!name_list.empty()) 21458 | { 21459 | for (std::size_t i = 0; i < name_list.size(); ++i) 21460 | { 21461 | exprtk::igeneric_function<T>& ifunc = *st.get_overload_function(name_list[i]); 21462 | add_function(name_list[i],ifunc); 21463 | } 21464 | } 21465 | } 21466 | } 21467 | 21468 | inline void load_variables_from(const symbol_table<T>& st) 21469 | { 21470 | std::vector<std::string> name_list; 21471 | 21472 | st.local_data().variable_store.get_list(name_list); 21473 | 21474 | if (!name_list.empty()) 21475 | { 21476 | for (std::size_t i = 0; i < name_list.size(); ++i) 21477 | { 21478 | T& variable = st.get_variable(name_list[i])->ref(); 21479 | add_variable(name_list[i], variable); 21480 | } 21481 | } 21482 | } 21483 | 21484 | inline void load_vectors_from(const symbol_table<T>& st) 21485 | { 21486 | std::vector<std::string> name_list; 21487 | 21488 | st.local_data().vector_store.get_list(name_list); 21489 | 21490 | if (!name_list.empty()) 21491 | { 21492 | for (std::size_t i = 0; i < name_list.size(); ++i) 21493 | { 21494 | vector_holder_t& vecholder = *st.get_vector(name_list[i]); 21495 | add_vector(name_list[i], vecholder.data(), vecholder.size()); 21496 | } 21497 | } 21498 | } 21499 | 21500 | private: 21501 | 21502 | inline bool valid_symbol(const std::string& symbol, const bool check_reserved_symb = true) const 21503 | { 21504 | if (symbol.empty()) 21505 | return false; 21506 | else if (!details::is_letter(symbol[0])) 21507 | return false; 21508 | else if (symbol.size() > 1) 21509 | { 21510 | for (std::size_t i = 1; i < symbol.size(); ++i) 21511 | { 21512 | if ( 21513 | !details::is_letter_or_digit(symbol[i]) && 21514 | ('_' != symbol[i]) 21515 | ) 21516 | { 21517 | if ((i < (symbol.size() - 1)) && ('.' == symbol[i])) 21518 | continue; 21519 | else 21520 | return false; 21521 | } 21522 | } 21523 | } 21524 | 21525 | return (check_reserved_symb) ? (!local_data().is_reserved_symbol(symbol)) : true; 21526 | } 21527 | 21528 | inline bool valid_function(const std::string& symbol) const 21529 | { 21530 | if (symbol.empty()) 21531 | return false; 21532 | else if (!details::is_letter(symbol[0])) 21533 | return false; 21534 | else if (symbol.size() > 1) 21535 | { 21536 | for (std::size_t i = 1; i < symbol.size(); ++i) 21537 | { 21538 | if ( 21539 | !details::is_letter_or_digit(symbol[i]) && 21540 | ('_' != symbol[i]) 21541 | ) 21542 | { 21543 | if ((i < (symbol.size() - 1)) && ('.' == symbol[i])) 21544 | continue; 21545 | else 21546 | return false; 21547 | } 21548 | } 21549 | } 21550 | 21551 | return true; 21552 | } 21553 | 21554 | typedef typename control_block::st_data local_data_t; 21555 | 21556 | inline local_data_t& local_data() 21557 | { 21558 | return *(control_block_->data_); 21559 | } 21560 | 21561 | inline const local_data_t& local_data() const 21562 | { 21563 | return *(control_block_->data_); 21564 | } 21565 | 21566 | control_block* control_block_; 21567 | 21568 | friend class parser<T>; 21569 | }; // class symbol_table 21570 | 21571 | template <typename T> 21572 | class function_compositor; 21573 | 21574 | template <typename T> 21575 | class expression 21576 | { 21577 | private: 21578 | 21579 | typedef details::expression_node<T>* expression_ptr; 21580 | typedef details::vector_holder<T>* vector_holder_ptr; 21581 | typedef std::vector<symbol_table<T> > symtab_list_t; 21582 | 21583 | struct control_block 21584 | { 21585 | enum data_type 21586 | { 21587 | e_unknown , 21588 | e_expr , 21589 | e_vecholder, 21590 | e_data , 21591 | e_vecdata , 21592 | e_string 21593 | }; 21594 | 21595 | static std::string to_str(data_type dt) 21596 | { 21597 | switch (dt) 21598 | { 21599 | case e_unknown : return "e_unknown " 21600 | case e_expr : return "e_expr" ; 21601 | case e_vecholder : return "e_vecholder" 21602 | case e_data : return "e_data" ; 21603 | case e_vecdata : return "e_vecdata" ; 21604 | case e_string : return "e_string" ; 21605 | } 21606 | 21607 | return "" 21608 | } 21609 | 21610 | struct data_pack 21611 | { 21612 | data_pack() 21613 | : pointer(0) 21614 | , type(e_unknown) 21615 | , size(0) 21616 | {} 21617 | 21618 | data_pack(void* ptr, const data_type dt, const std::size_t sz = 0) 21619 | : pointer(ptr) 21620 | , type(dt) 21621 | , size(sz) 21622 | {} 21623 | 21624 | void* pointer; 21625 | data_type type; 21626 | std::size_t size; 21627 | }; 21628 | 21629 | typedef std::vector<data_pack> local_data_list_t; 21630 | typedef results_context<T> results_context_t; 21631 | typedef control_block* cntrl_blck_ptr_t; 21632 | 21633 | control_block() 21634 | : ref_count(0) 21635 | , expr (0) 21636 | , results (0) 21637 | , retinv_null(false) 21638 | , return_invoked(&retinv_null) 21639 | {} 21640 | 21641 | explicit control_block(expression_ptr e) 21642 | : ref_count(1) 21643 | , expr (e) 21644 | , results (0) 21645 | , retinv_null(false) 21646 | , return_invoked(&retinv_null) 21647 | {} 21648 | 21649 | ~control_block() 21650 | { 21651 | if (expr && details::branch_deletable(expr)) 21652 | { 21653 | destroy_node(expr); 21654 | } 21655 | 21656 | if (!local_data_list.empty()) 21657 | { 21658 | for (std::size_t i = 0; i < local_data_list.size(); ++i) 21659 | { 21660 | switch (local_data_list[i].type) 21661 | { 21662 | case e_expr : delete reinterpret_cast<expression_ptr>(local_data_list[i].pointer); 21663 | break; 21664 | 21665 | case e_vecholder : delete reinterpret_cast<vector_holder_ptr>(local_data_list[i].pointer); 21666 | break; 21667 | 21668 | case e_data : delete reinterpret_cast<T*>(local_data_list[i].pointer); 21669 | break; 21670 | 21671 | case e_vecdata : delete [] reinterpret_cast<T*>(local_data_list[i].pointer); 21672 | break; 21673 | 21674 | case e_string : delete reinterpret_cast<std::string*>(local_data_list[i].pointer); 21675 | break; 21676 | 21677 | default : break; 21678 | } 21679 | } 21680 | } 21681 | 21682 | if (results) 21683 | { 21684 | delete results; 21685 | } 21686 | } 21687 | 21688 | static inline cntrl_blck_ptr_t create(expression_ptr e) 21689 | { 21690 | return new control_block(e); 21691 | } 21692 | 21693 | static inline void destroy(cntrl_blck_ptr_t& cntrl_blck) 21694 | { 21695 | if (cntrl_blck) 21696 | { 21697 | if ( 21698 | (0 != cntrl_blck->ref_count) && 21699 | (0 == --cntrl_blck->ref_count) 21700 | ) 21701 | { 21702 | delete cntrl_blck; 21703 | } 21704 | 21705 | cntrl_blck = 0; 21706 | } 21707 | } 21708 | 21709 | std::size_t ref_count; 21710 | expression_ptr expr; 21711 | local_data_list_t local_data_list; 21712 | results_context_t* results; 21713 | bool retinv_null; 21714 | bool* return_invoked; 21715 | 21716 | friend class function_compositor<T>; 21717 | }; 21718 | 21719 | public: 21720 | 21721 | expression() 21722 | : control_block_(0) 21723 | { 21724 | set_expression(new details::null_node<T>()); 21725 | } 21726 | 21727 | expression(const expression<T>& e) 21728 | : control_block_ (e.control_block_ ) 21729 | , symbol_table_list_(e.symbol_table_list_) 21730 | { 21731 | control_block_->ref_count++; 21732 | } 21733 | 21734 | explicit expression(const symbol_table<T>& symbol_table) 21735 | : control_block_(0) 21736 | { 21737 | set_expression(new details::null_node<T>()); 21738 | symbol_table_list_.push_back(symbol_table); 21739 | } 21740 | 21741 | inline expression<T>& operator=(const expression<T>& e) 21742 | { 21743 | if (this != &e) 21744 | { 21745 | if (control_block_) 21746 | { 21747 | if ( 21748 | (0 != control_block_->ref_count) && 21749 | (0 == --control_block_->ref_count) 21750 | ) 21751 | { 21752 | delete control_block_; 21753 | } 21754 | 21755 | control_block_ = 0; 21756 | } 21757 | 21758 | control_block_ = e.control_block_; 21759 | control_block_->ref_count++; 21760 | symbol_table_list_ = e.symbol_table_list_; 21761 | } 21762 | 21763 | return *this; 21764 | } 21765 | 21766 | inline bool operator==(const expression<T>& e) const 21767 | { 21768 | return (this == &e); 21769 | } 21770 | 21771 | inline bool operator!() const 21772 | { 21773 | return ( 21774 | (0 == control_block_ ) || 21775 | (0 == control_block_->expr) 21776 | ); 21777 | } 21778 | 21779 | inline expression<T>& release() 21780 | { 21781 | exprtk::details::dump_ptr("expression::release", this); 21782 | control_block::destroy(control_block_); 21783 | 21784 | return (*this); 21785 | } 21786 | 21787 | ~expression() 21788 | { 21789 | control_block::destroy(control_block_); 21790 | } 21791 | 21792 | inline T value() const 21793 | { 21794 | assert(control_block_ ); 21795 | assert(control_block_->expr); 21796 | 21797 | return control_block_->expr->value(); 21798 | } 21799 | 21800 | inline T operator() () const 21801 | { 21802 | return value(); 21803 | } 21804 | 21805 | inline operator T() const 21806 | { 21807 | return value(); 21808 | } 21809 | 21810 | inline operator bool() const 21811 | { 21812 | return details::is_true(value()); 21813 | } 21814 | 21815 | inline bool register_symbol_table(symbol_table<T>& st) 21816 | { 21817 | for (std::size_t i = 0; i < symbol_table_list_.size(); ++i) 21818 | { 21819 | if (st == symbol_table_list_[i]) 21820 | { 21821 | return false; 21822 | } 21823 | } 21824 | 21825 | symbol_table_list_.push_back(st); 21826 | return true; 21827 | } 21828 | 21829 | inline const symbol_table<T>& get_symbol_table(const std::size_t& index = 0) const 21830 | { 21831 | return symbol_table_list_[index]; 21832 | } 21833 | 21834 | inline symbol_table<T>& get_symbol_table(const std::size_t& index = 0) 21835 | { 21836 | return symbol_table_list_[index]; 21837 | } 21838 | 21839 | std::size_t num_symbol_tables() const 21840 | { 21841 | return symbol_table_list_.size(); 21842 | } 21843 | 21844 | typedef results_context<T> results_context_t; 21845 | 21846 | inline const results_context_t& results() const 21847 | { 21848 | if (control_block_->results) 21849 | return (*control_block_->results); 21850 | else 21851 | { 21852 | static const results_context_t null_results; 21853 | return null_results; 21854 | } 21855 | } 21856 | 21857 | inline bool return_invoked() const 21858 | { 21859 | return (*control_block_->return_invoked); 21860 | } 21861 | 21862 | private: 21863 | 21864 | inline symtab_list_t get_symbol_table_list() const 21865 | { 21866 | return symbol_table_list_; 21867 | } 21868 | 21869 | inline void set_expression(const expression_ptr expr) 21870 | { 21871 | if (expr) 21872 | { 21873 | if (control_block_) 21874 | { 21875 | if (0 == --control_block_->ref_count) 21876 | { 21877 | delete control_block_; 21878 | } 21879 | } 21880 | 21881 | control_block_ = control_block::create(expr); 21882 | } 21883 | } 21884 | 21885 | inline void register_local_var(expression_ptr expr) 21886 | { 21887 | if (expr) 21888 | { 21889 | if (control_block_) 21890 | { 21891 | control_block_-> 21892 | local_data_list.push_back( 21893 | typename expression<T>::control_block:: 21894 | data_pack(reinterpret_cast<void*>(expr), 21895 | control_block::e_expr)); 21896 | } 21897 | } 21898 | } 21899 | 21900 | inline void register_local_var(vector_holder_ptr vec_holder) 21901 | { 21902 | if (vec_holder) 21903 | { 21904 | if (control_block_) 21905 | { 21906 | control_block_-> 21907 | local_data_list.push_back( 21908 | typename expression<T>::control_block:: 21909 | data_pack(reinterpret_cast<void*>(vec_holder), 21910 | control_block::e_vecholder)); 21911 | } 21912 | } 21913 | } 21914 | 21915 | inline void register_local_data(void* data, const std::size_t& size = 0, const std::size_t data_mode = 0) 21916 | { 21917 | if (data) 21918 | { 21919 | if (control_block_) 21920 | { 21921 | typename control_block::data_type dt = control_block::e_data; 21922 | 21923 | switch (data_mode) 21924 | { 21925 | case 0 : dt = control_block::e_data; break; 21926 | case 1 : dt = control_block::e_vecdata; break; 21927 | case 2 : dt = control_block::e_string; break; 21928 | } 21929 | 21930 | control_block_-> 21931 | local_data_list.push_back( 21932 | typename expression<T>::control_block:: 21933 | data_pack(reinterpret_cast<void*>(data), dt, size)); 21934 | } 21935 | } 21936 | } 21937 | 21938 | inline const typename control_block::local_data_list_t& local_data_list() 21939 | { 21940 | if (control_block_) 21941 | { 21942 | return control_block_->local_data_list; 21943 | } 21944 | else 21945 | { 21946 | static typename control_block::local_data_list_t null_local_data_list; 21947 | return null_local_data_list; 21948 | } 21949 | } 21950 | 21951 | inline void register_return_results(results_context_t* rc) 21952 | { 21953 | if (control_block_ && rc) 21954 | { 21955 | control_block_->results = rc; 21956 | } 21957 | } 21958 | 21959 | inline void set_retinvk(bool* retinvk_ptr) 21960 | { 21961 | if (control_block_) 21962 | { 21963 | control_block_->return_invoked = retinvk_ptr; 21964 | } 21965 | } 21966 | 21967 | control_block* control_block_; 21968 | symtab_list_t symbol_table_list_; 21969 | 21970 | friend class parser<T>; 21971 | friend class expression_helper<T>; 21972 | friend class function_compositor<T>; 21973 | template <typename TT> 21974 | friend bool is_valid(const expression<TT>& expr); 21975 | }; // class expression 21976 | 21977 | template <typename T> 21978 | class expression_helper 21979 | { 21980 | public: 21981 | 21982 | enum node_types 21983 | { 21984 | e_literal, 21985 | e_variable, 21986 | e_string, 21987 | e_unary, 21988 | e_binary, 21989 | e_function, 21990 | e_vararg, 21991 | e_null, 21992 | e_assert, 21993 | e_sf3ext, 21994 | e_sf4ext 21995 | }; 21996 | 21997 | static inline bool is_literal(const expression<T>& expr) 21998 | { 21999 | return expr.control_block_ && details::is_literal_node(expr.control_block_->expr); 22000 | } 22001 | 22002 | static inline bool is_variable(const expression<T>& expr) 22003 | { 22004 | return expr.control_block_ && details::is_variable_node(expr.control_block_->expr); 22005 | } 22006 | 22007 | static inline bool is_string(const expression<T>& expr) 22008 | { 22009 | return expr.control_block_ && details::is_generally_string_node(expr.control_block_->expr); 22010 | } 22011 | 22012 | static inline bool is_unary(const expression<T>& expr) 22013 | { 22014 | return expr.control_block_ && details::is_unary_node(expr.control_block_->expr); 22015 | } 22016 | 22017 | static inline bool is_binary(const expression<T>& expr) 22018 | { 22019 | return expr.control_block_ && details::is_binary_node(expr.control_block_->expr); 22020 | } 22021 | 22022 | static inline bool is_function(const expression<T>& expr) 22023 | { 22024 | return expr.control_block_ && details::is_function(expr.control_block_->expr); 22025 | } 22026 | 22027 | static inline bool is_vararg(const expression<T>& expr) 22028 | { 22029 | return expr.control_block_ && details::is_vararg_node(expr.control_block_->expr); 22030 | } 22031 | 22032 | static inline bool is_null(const expression<T>& expr) 22033 | { 22034 | return expr.control_block_ && details::is_null_node(expr.control_block_->expr); 22035 | } 22036 | 22037 | static inline bool is_assert(const expression<T>& expr) 22038 | { 22039 | return expr.control_block_ && details::is_assert_node(expr.control_block_->expr); 22040 | } 22041 | 22042 | static inline bool is_sf3ext(const expression<T>& expr) 22043 | { 22044 | return expr.control_block_ && details::is_sf3ext_node(expr.control_block_->expr); 22045 | } 22046 | 22047 | static inline bool is_sf4ext(const expression<T>& expr) 22048 | { 22049 | return expr.control_block_ && details::is_sf4ext_node(expr.control_block_->expr); 22050 | } 22051 | 22052 | static inline bool is_type(const expression<T>& expr, const node_types node_type) 22053 | { 22054 | if (0 == expr.control_block_) 22055 | { 22056 | return false; 22057 | } 22058 | 22059 | switch (node_type) 22060 | { 22061 | case e_literal : return is_literal_node(expr); 22062 | case e_variable : return is_variable (expr); 22063 | case e_string : return is_string (expr); 22064 | case e_unary : return is_unary (expr); 22065 | case e_binary : return is_binary (expr); 22066 | case e_function : return is_function (expr); 22067 | case e_null : return is_null (expr); 22068 | case e_assert : return is_assert (expr); 22069 | case e_sf3ext : return is_sf3ext (expr); 22070 | case e_sf4ext : return is_sf4ext (expr); 22071 | }; 22072 | 22073 | return false; 22074 | } 22075 | 22076 | static inline bool match_type_sequence(const expression<T>& expr, const std::vector<node_types>& type_seq) 22077 | { 22078 | if ((0 == expr.control_block_) || !is_vararg(expr)) 22079 | { 22080 | return false; 22081 | } 22082 | 22083 | typedef details::vararg_node<T, exprtk::details::vararg_multi_op<T> > mo_vararg_t; 22084 | 22085 | mo_vararg_t* vnode = dynamic_cast<mo_vararg_t*>(expr.control_block_->expr); 22086 | 22087 | if ( 22088 | (0 == vnode) || 22089 | type_seq.empty() || 22090 | (vnode->size() < type_seq.size()) 22091 | ) 22092 | { 22093 | return false; 22094 | } 22095 | 22096 | for (std::size_t i = 0; i < type_seq.size(); ++i) 22097 | { 22098 | assert((*vnode)[i]); 22099 | 22100 | switch (type_seq[i]) 22101 | { 22102 | case e_literal : { if (details::is_literal_node ((*vnode)[i])) continue; } break; 22103 | case e_variable : { if (details::is_variable_node ((*vnode)[i])) continue; } break; 22104 | case e_string : { if (details::is_generally_string_node((*vnode)[i])) continue; } break; 22105 | case e_unary : { if (details::is_unary_node ((*vnode)[i])) continue; } break; 22106 | case e_binary : { if (details::is_binary_node ((*vnode)[i])) continue; } break; 22107 | case e_function : { if (details::is_function ((*vnode)[i])) continue; } break; 22108 | case e_null : { if (details::is_null_node ((*vnode)[i])) continue; } break; 22109 | case e_assert : { if (details::is_assert_node ((*vnode)[i])) continue; } break; 22110 | case e_sf3ext : { if (details::is_sf3ext_node ((*vnode)[i])) continue; } break; 22111 | case e_sf4ext : { if (details::is_sf4ext_node ((*vnode)[i])) continue; } break; 22112 | case e_vararg : break; 22113 | } 22114 | 22115 | return false; 22116 | } 22117 | 22118 | return true; 22119 | } 22120 | }; 22121 | 22122 | template <typename T> 22123 | inline bool is_valid(const expression<T>& expr) 22124 | { 22125 | return expr.control_block_ && !expression_helper<T>::is_null(expr); 22126 | } 22127 | 22128 | namespace parser_error 22129 | { 22130 | enum error_mode 22131 | { 22132 | e_unknown = 0, 22133 | e_syntax = 1, 22134 | e_token = 2, 22135 | e_numeric = 4, 22136 | e_symtab = 5, 22137 | e_lexer = 6, 22138 | e_synthesis = 7, 22139 | e_helper = 8, 22140 | e_parser = 9 22141 | }; 22142 | 22143 | struct type 22144 | { 22145 | type() 22146 | : mode(parser_error::e_unknown) 22147 | , line_no (0) 22148 | , column_no(0) 22149 | {} 22150 | 22151 | lexer::token token; 22152 | error_mode mode; 22153 | std::string diagnostic; 22154 | std::string src_location; 22155 | std::string error_line; 22156 | std::size_t line_no; 22157 | std::size_t column_no; 22158 | }; 22159 | 22160 | inline type make_error(const error_mode mode, 22161 | const std::string& diagnostic = "", 22162 | const std::string& src_location = "") 22163 | { 22164 | type t; 22165 | t.mode = mode; 22166 | t.token.type = lexer::token::e_error; 22167 | t.diagnostic = diagnostic; 22168 | t.src_location = src_location; 22169 | exprtk_debug(("%s\n", diagnostic .c_str())); 22170 | return t; 22171 | } 22172 | 22173 | inline type make_error(const error_mode mode, 22174 | const lexer::token& tk, 22175 | const std::string& diagnostic = "", 22176 | const std::string& src_location = "") 22177 | { 22178 | type t; 22179 | t.mode = mode; 22180 | t.token = tk; 22181 | t.diagnostic = diagnostic; 22182 | t.src_location = src_location; 22183 | exprtk_debug(("%s\n", diagnostic .c_str())); 22184 | return t; 22185 | } 22186 | 22187 | inline std::string to_str(error_mode mode) 22188 | { 22189 | switch (mode) 22190 | { 22191 | case e_unknown : return std::string("Unknown Error"); 22192 | case e_syntax : return std::string("Syntax Error" ); 22193 | case e_token : return std::string("Token Error" ); 22194 | case e_numeric : return std::string("Numeric Error"); 22195 | case e_symtab : return std::string("Symbol Error" ); 22196 | case e_lexer : return std::string("Lexer Error" ); 22197 | case e_helper : return std::string("Helper Error" ); 22198 | case e_parser : return std::string("Parser Error" ); 22199 | default : return std::string("Unknown Error"); 22200 | } 22201 | } 22202 | 22203 | inline bool update_error(type& error, const std::string& expression) 22204 | { 22205 | if ( 22206 | expression.empty() || 22207 | (error.token.position > expression.size()) || 22208 | (std::numeric_limits<std::size_t>::max() == error.token.position) 22209 | ) 22210 | { 22211 | return false; 22212 | } 22213 | 22214 | std::size_t error_line_start = 0; 22215 | 22216 | for (std::size_t i = error.token.position; i > 0; --i) 22217 | { 22218 | const details::char_t c = expression[i]; 22219 | 22220 | if (('\n' == c) || ('\r' == c)) 22221 | { 22222 | error_line_start = i + 1; 22223 | break; 22224 | } 22225 | } 22226 | 22227 | std::size_t next_nl_position = std::min(expression.size(), 22228 | expression.find_first_of('\n',error.token.position + 1)); 22229 | 22230 | error.column_no = error.token.position - error_line_start; 22231 | error.error_line = expression.substr(error_line_start, 22232 | next_nl_position - error_line_start); 22233 | 22234 | error.line_no = 0; 22235 | 22236 | for (std::size_t i = 0; i < next_nl_position; ++i) 22237 | { 22238 | if ('\n' == expression[i]) 22239 | ++error.line_no; 22240 | } 22241 | 22242 | return true; 22243 | } 22244 | 22245 | inline void dump_error(const type& error) 22246 | { 22247 | printf("Position: %02d Type: [%s] Msg: %s\n", 22248 | static_cast<int>(error.token.position), 22249 | exprtk::parser_error::to_str(error.mode).c_str(), 22250 | error.diagnostic.c_str()); 22251 | } 22252 | } 22253 | 22254 | namespace details 22255 | { 22256 | template <typename Parser> 22257 | inline void disable_type_checking(Parser& p) 22258 | { 22259 | p.state_.type_check_enabled = false; 22260 | } 22261 | } 22262 | 22263 | template <typename T> 22264 | class parser : public lexer::parser_helper 22265 | { 22266 | private: 22267 | 22268 | enum precedence_level 22269 | { 22270 | e_level00, e_level01, e_level02, e_level03, e_level04, 22271 | e_level05, e_level06, e_level07, e_level08, e_level09, 22272 | e_level10, e_level11, e_level12, e_level13, e_level14 22273 | }; 22274 | 22275 | typedef const T& cref_t; 22276 | typedef const T const_t; 22277 | typedef ifunction<T> F; 22278 | typedef ivararg_function<T> VAF; 22279 | typedef igeneric_function<T> GF; 22280 | typedef ifunction<T> ifunction_t; 22281 | typedef ivararg_function<T> ivararg_function_t; 22282 | typedef igeneric_function<T> igeneric_function_t; 22283 | typedef details::expression_node<T> expression_node_t; 22284 | typedef details::literal_node<T> literal_node_t; 22285 | typedef details::unary_node<T> unary_node_t; 22286 | typedef details::binary_node<T> binary_node_t; 22287 | typedef details::trinary_node<T> trinary_node_t; 22288 | typedef details::quaternary_node<T> quaternary_node_t; 22289 | typedef details::conditional_node<T> conditional_node_t; 22290 | typedef details::cons_conditional_node<T> cons_conditional_node_t; 22291 | typedef details::while_loop_node<T> while_loop_node_t; 22292 | typedef details::repeat_until_loop_node<T> repeat_until_loop_node_t; 22293 | typedef details::for_loop_node<T> for_loop_node_t; 22294 | typedef details::while_loop_rtc_node<T> while_loop_rtc_node_t; 22295 | typedef details::repeat_until_loop_rtc_node<T> repeat_until_loop_rtc_node_t; 22296 | typedef details::for_loop_rtc_node<T> for_loop_rtc_node_t; 22297 | #ifndef exprtk_disable_break_continue 22298 | typedef details::while_loop_bc_node<T> while_loop_bc_node_t; 22299 | typedef details::repeat_until_loop_bc_node<T> repeat_until_loop_bc_node_t; 22300 | typedef details::for_loop_bc_node<T> for_loop_bc_node_t; 22301 | typedef details::while_loop_bc_rtc_node<T> while_loop_bc_rtc_node_t; 22302 | typedef details::repeat_until_loop_bc_rtc_node<T> repeat_until_loop_bc_rtc_node_t; 22303 | typedef details::for_loop_bc_rtc_node<T> for_loop_bc_rtc_node_t; 22304 | #endif 22305 | typedef details::switch_node<T> switch_node_t; 22306 | typedef details::variable_node<T> variable_node_t; 22307 | typedef details::vector_elem_node<T> vector_elem_node_t; 22308 | typedef details::vector_celem_node<T> vector_celem_node_t; 22309 | typedef details::vector_elem_rtc_node<T> vector_elem_rtc_node_t; 22310 | typedef details::vector_celem_rtc_node<T> vector_celem_rtc_node_t; 22311 | typedef details::rebasevector_elem_node<T> rebasevector_elem_node_t; 22312 | typedef details::rebasevector_celem_node<T> rebasevector_celem_node_t; 22313 | typedef details::rebasevector_elem_rtc_node<T> rebasevector_elem_rtc_node_t; 22314 | typedef details::rebasevector_celem_rtc_node<T> rebasevector_celem_rtc_node_t; 22315 | typedef details::vector_node<T> vector_node_t; 22316 | typedef details::vector_size_node<T> vector_size_node_t; 22317 | typedef details::range_pack<T> range_t; 22318 | #ifndef exprtk_disable_string_capabilities 22319 | typedef details::stringvar_node<T> stringvar_node_t; 22320 | typedef details::string_literal_node<T> string_literal_node_t; 22321 | typedef details::string_range_node<T> string_range_node_t; 22322 | typedef details::const_string_range_node<T> const_string_range_node_t; 22323 | typedef details::generic_string_range_node<T> generic_string_range_node_t; 22324 | typedef details::string_concat_node<T> string_concat_node_t; 22325 | typedef details::assignment_string_node<T> assignment_string_node_t; 22326 | typedef details::assignment_string_range_node<T> assignment_string_range_node_t; 22327 | typedef details::conditional_string_node<T> conditional_string_node_t; 22328 | typedef details::cons_conditional_str_node<T> cons_conditional_str_node_t; 22329 | #endif 22330 | typedef details::assignment_node<T> assignment_node_t; 22331 | typedef details::assignment_vec_elem_node<T> assignment_vec_elem_node_t; 22332 | typedef details::assignment_vec_elem_rtc_node<T> assignment_vec_elem_rtc_node_t; 22333 | typedef details::assignment_rebasevec_elem_node<T> assignment_rebasevec_elem_node_t; 22334 | typedef details::assignment_rebasevec_elem_rtc_node<T> assignment_rebasevec_elem_rtc_node_t; 22335 | typedef details::assignment_rebasevec_celem_node<T> assignment_rebasevec_celem_node_t; 22336 | typedef details::assignment_vec_node<T> assignment_vec_node_t; 22337 | typedef details::assignment_vecvec_node<T> assignment_vecvec_node_t; 22338 | typedef details::conditional_vector_node<T> conditional_vector_node_t; 22339 | typedef details::scand_node<T> scand_node_t; 22340 | typedef details::scor_node<T> scor_node_t; 22341 | typedef lexer::token token_t; 22342 | typedef expression_node_t* expression_node_ptr; 22343 | typedef expression<T> expression_t; 22344 | typedef symbol_table<T> symbol_table_t; 22345 | typedef typename expression<T>::symtab_list_t symbol_table_list_t; 22346 | typedef details::vector_holder<T> vector_holder_t; 22347 | typedef vector_holder_t* vector_holder_ptr; 22348 | 22349 | typedef typename details::functor_t<T> functor_t; 22350 | typedef typename functor_t::qfunc_t quaternary_functor_t; 22351 | typedef typename functor_t::tfunc_t trinary_functor_t; 22352 | typedef typename functor_t::bfunc_t binary_functor_t; 22353 | typedef typename functor_t::ufunc_t unary_functor_t; 22354 | 22355 | typedef details::operator_type operator_t; 22356 | 22357 | typedef std::map<operator_t, unary_functor_t > unary_op_map_t; 22358 | typedef std::map<operator_t, binary_functor_t > binary_op_map_t; 22359 | typedef std::map<operator_t, trinary_functor_t> trinary_op_map_t; 22360 | 22361 | typedef std::map<std::string,std::pair<trinary_functor_t ,operator_t> > sf3_map_t; 22362 | typedef std::map<std::string,std::pair<quaternary_functor_t,operator_t> > sf4_map_t; 22363 | 22364 | typedef std::map<binary_functor_t,operator_t> inv_binary_op_map_t; 22365 | typedef std::multimap<std::string,details::base_operation_t,details::ilesscompare> base_ops_map_t; 22366 | typedef std::set<std::string,details::ilesscompare> disabled_func_set_t; 22367 | 22368 | typedef details::T0oT1_define<T, cref_t , cref_t > vov_t; 22369 | typedef details::T0oT1_define<T, const_t, cref_t > cov_t; 22370 | typedef details::T0oT1_define<T, cref_t , const_t> voc_t; 22371 | 22372 | typedef details::T0oT1oT2_define<T, cref_t , cref_t , cref_t > vovov_t; 22373 | typedef details::T0oT1oT2_define<T, cref_t , cref_t , const_t> vovoc_t; 22374 | typedef details::T0oT1oT2_define<T, cref_t , const_t, cref_t > vocov_t; 22375 | typedef details::T0oT1oT2_define<T, const_t, cref_t , cref_t > covov_t; 22376 | typedef details::T0oT1oT2_define<T, const_t, cref_t , const_t> covoc_t; 22377 | typedef details::T0oT1oT2_define<T, const_t, const_t, cref_t > cocov_t; 22378 | typedef details::T0oT1oT2_define<T, cref_t , const_t, const_t> vococ_t; 22379 | 22380 | typedef details::T0oT1oT2oT3_define<T, cref_t , cref_t , cref_t , cref_t > vovovov_t; 22381 | typedef details::T0oT1oT2oT3_define<T, cref_t , cref_t , cref_t , const_t> vovovoc_t; 22382 | typedef details::T0oT1oT2oT3_define<T, cref_t , cref_t , const_t, cref_t > vovocov_t; 22383 | typedef details::T0oT1oT2oT3_define<T, cref_t , const_t, cref_t , cref_t > vocovov_t; 22384 | typedef details::T0oT1oT2oT3_define<T, const_t, cref_t , cref_t , cref_t > covovov_t; 22385 | 22386 | typedef details::T0oT1oT2oT3_define<T, const_t, cref_t , const_t, cref_t > covocov_t; 22387 | typedef details::T0oT1oT2oT3_define<T, cref_t , const_t, cref_t , const_t> vocovoc_t; 22388 | typedef details::T0oT1oT2oT3_define<T, const_t, cref_t , cref_t , const_t> covovoc_t; 22389 | typedef details::T0oT1oT2oT3_define<T, cref_t , const_t, const_t, cref_t > vococov_t; 22390 | 22391 | typedef results_context<T> results_context_t; 22392 | 22393 | typedef parser_helper prsrhlpr_t; 22394 | 22395 | struct scope_element 22396 | { 22397 | enum element_type 22398 | { 22399 | e_none , 22400 | e_literal , 22401 | e_variable, 22402 | e_vector , 22403 | e_vecelem , 22404 | e_string 22405 | }; 22406 | 22407 | typedef details::vector_holder<T> vector_holder_t; 22408 | typedef literal_node_t* literal_node_ptr; 22409 | typedef variable_node_t* variable_node_ptr; 22410 | typedef vector_holder_t* vector_holder_ptr; 22411 | typedef expression_node_t* expression_node_ptr; 22412 | #ifndef exprtk_disable_string_capabilities 22413 | typedef stringvar_node_t* stringvar_node_ptr; 22414 | #endif 22415 | 22416 | scope_element() 22417 | : name("???") 22418 | , size (std::numeric_limits<std::size_t>::max()) 22419 | , index(std::numeric_limits<std::size_t>::max()) 22420 | , depth(std::numeric_limits<std::size_t>::max()) 22421 | , ref_count(0) 22422 | , ip_index (0) 22423 | , type (e_none) 22424 | , active (false) 22425 | , data (0) 22426 | , var_node (0) 22427 | , vec_node (0) 22428 | #ifndef exprtk_disable_string_capabilities 22429 | , str_node(0) 22430 | #endif 22431 | {} 22432 | 22433 | bool operator < (const scope_element& se) const 22434 | { 22435 | if (ip_index < se.ip_index) 22436 | return true; 22437 | else if (ip_index > se.ip_index) 22438 | return false; 22439 | else if (depth < se.depth) 22440 | return true; 22441 | else if (depth > se.depth) 22442 | return false; 22443 | else if (index < se.index) 22444 | return true; 22445 | else if (index > se.index) 22446 | return false; 22447 | else 22448 | return (name < se.name); 22449 | } 22450 | 22451 | void clear() 22452 | { 22453 | name = "???" 22454 | size = std::numeric_limits<std::size_t>::max(); 22455 | index = std::numeric_limits<std::size_t>::max(); 22456 | depth = std::numeric_limits<std::size_t>::max(); 22457 | type = e_none; 22458 | active = false; 22459 | ref_count = 0; 22460 | ip_index = 0; 22461 | data = 0; 22462 | var_node = 0; 22463 | vec_node = 0; 22464 | #ifndef exprtk_disable_string_capabilities 22465 | str_node = 0; 22466 | #endif 22467 | } 22468 | 22469 | std::string name; 22470 | std::size_t size; 22471 | std::size_t index; 22472 | std::size_t depth; 22473 | std::size_t ref_count; 22474 | std::size_t ip_index; 22475 | element_type type; 22476 | bool active; 22477 | void* data; 22478 | expression_node_ptr var_node; 22479 | vector_holder_ptr vec_node; 22480 | #ifndef exprtk_disable_string_capabilities 22481 | stringvar_node_ptr str_node; 22482 | #endif 22483 | }; 22484 | 22485 | class scope_element_manager 22486 | { 22487 | public: 22488 | 22489 | typedef expression_node_t* expression_node_ptr; 22490 | typedef variable_node_t* variable_node_ptr; 22491 | typedef parser<T> parser_t; 22492 | 22493 | explicit scope_element_manager(parser<T>& p) 22494 | : parser_(p) 22495 | , input_param_cnt_(0) 22496 | , total_local_symb_size_bytes_(0) 22497 | {} 22498 | 22499 | inline std::size_t size() const 22500 | { 22501 | return element_.size(); 22502 | } 22503 | 22504 | inline bool empty() const 22505 | { 22506 | return element_.empty(); 22507 | } 22508 | 22509 | inline scope_element& get_element(const std::size_t& index) 22510 | { 22511 | if (index < element_.size()) 22512 | return element_[index]; 22513 | else 22514 | return null_element_; 22515 | } 22516 | 22517 | inline scope_element& get_element(const std::string& var_name, 22518 | const std::size_t index = std::numeric_limits<std::size_t>::max()) 22519 | { 22520 | const std::size_t current_depth = parser_.state_.scope_depth; 22521 | 22522 | for (std::size_t i = 0; i < element_.size(); ++i) 22523 | { 22524 | scope_element& se = element_[i]; 22525 | 22526 | if (se.depth > current_depth) 22527 | continue; 22528 | else if ( 22529 | details::imatch(se.name, var_name) && 22530 | (se.index == index) 22531 | ) 22532 | return se; 22533 | } 22534 | 22535 | return null_element_; 22536 | } 22537 | 22538 | inline scope_element& get_active_element(const std::string& var_name, 22539 | const std::size_t index = std::numeric_limits<std::size_t>::max()) 22540 | { 22541 | const std::size_t current_depth = parser_.state_.scope_depth; 22542 | 22543 | for (std::size_t i = 0; i < element_.size(); ++i) 22544 | { 22545 | scope_element& se = element_[i]; 22546 | 22547 | if (se.depth > current_depth) 22548 | continue; 22549 | else if ( 22550 | details::imatch(se.name, var_name) && 22551 | (se.index == index) && 22552 | (se.active) 22553 | ) 22554 | return se; 22555 | } 22556 | 22557 | return null_element_; 22558 | } 22559 | 22560 | inline bool add_element(const scope_element& se) 22561 | { 22562 | for (std::size_t i = 0; i < element_.size(); ++i) 22563 | { 22564 | scope_element& cse = element_[i]; 22565 | 22566 | if ( 22567 | details::imatch(cse.name, se.name) && 22568 | (cse.depth <= se.depth) && 22569 | (cse.index == se.index) && 22570 | (cse.size == se.size ) && 22571 | (cse.type == se.type ) && 22572 | (cse.active) 22573 | ) 22574 | return false; 22575 | } 22576 | 22577 | switch (se.type) 22578 | { 22579 | case scope_element::e_variable : total_local_symb_size_bytes_ += sizeof(T); 22580 | break; 22581 | 22582 | case scope_element::e_literal : total_local_symb_size_bytes_ += sizeof(T); 22583 | break; 22584 | 22585 | case scope_element::e_vector : total_local_symb_size_bytes_ += sizeof(T) * se.size; 22586 | break; 22587 | 22588 | default : break; 22589 | } 22590 | 22591 | element_.push_back(se); 22592 | std::sort(element_.begin(),element_.end()); 22593 | 22594 | return true; 22595 | } 22596 | 22597 | inline void deactivate(const std::size_t& scope_depth) 22598 | { 22599 | exprtk_debug(("deactivate() - Scope depth: %d\n", 22600 | static_cast<int>(parser_.state_.scope_depth))); 22601 | 22602 | for (std::size_t i = 0; i < element_.size(); ++i) 22603 | { 22604 | scope_element& se = element_[i]; 22605 | 22606 | if (se.active && (se.depth >= scope_depth)) 22607 | { 22608 | exprtk_debug(("deactivate() - element[%02d] '%s'\n", 22609 | static_cast<int>(i), 22610 | se.name.c_str())); 22611 | 22612 | se.active = false; 22613 | } 22614 | } 22615 | } 22616 | 22617 | inline void free_element(scope_element& se) 22618 | { 22619 | exprtk_debug(("free_element() - se[%s]\n", se.name.c_str())); 22620 | 22621 | switch (se.type) 22622 | { 22623 | case scope_element::e_literal : delete reinterpret_cast<T*>(se.data); 22624 | delete se.var_node; 22625 | break; 22626 | 22627 | case scope_element::e_variable : delete reinterpret_cast<T*>(se.data); 22628 | delete se.var_node; 22629 | break; 22630 | 22631 | case scope_element::e_vector : delete[] reinterpret_cast<T*>(se.data); 22632 | delete se.vec_node; 22633 | break; 22634 | 22635 | case scope_element::e_vecelem : delete se.var_node; 22636 | break; 22637 | 22638 | #ifndef exprtk_disable_string_capabilities 22639 | case scope_element::e_string : delete reinterpret_cast<std::string*>(se.data); 22640 | delete se.str_node; 22641 | break; 22642 | #endif 22643 | 22644 | default : return; 22645 | } 22646 | 22647 | se.clear(); 22648 | } 22649 | 22650 | inline void cleanup() 22651 | { 22652 | for (std::size_t i = 0; i < element_.size(); ++i) 22653 | { 22654 | free_element(element_[i]); 22655 | } 22656 | 22657 | element_.clear(); 22658 | 22659 | input_param_cnt_ = 0; 22660 | total_local_symb_size_bytes_ = 0; 22661 | } 22662 | 22663 | inline std::size_t total_local_symb_size_bytes() const 22664 | { 22665 | return total_local_symb_size_bytes_; 22666 | } 22667 | 22668 | inline std::size_t next_ip_index() 22669 | { 22670 | return ++input_param_cnt_; 22671 | } 22672 | 22673 | inline expression_node_ptr get_variable(const T& v) 22674 | { 22675 | for (std::size_t i = 0; i < element_.size(); ++i) 22676 | { 22677 | scope_element& se = element_[i]; 22678 | 22679 | if ( 22680 | se.active && 22681 | se.var_node && 22682 | details::is_variable_node(se.var_node) 22683 | ) 22684 | { 22685 | variable_node_ptr vn = reinterpret_cast<variable_node_ptr>(se.var_node); 22686 | 22687 | if (&(vn->ref()) == (&v)) 22688 | { 22689 | return se.var_node; 22690 | } 22691 | } 22692 | } 22693 | 22694 | return expression_node_ptr(0); 22695 | } 22696 | 22697 | inline std::string get_vector_name(const T* data) 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.vec_node && 22706 | (se.vec_node->data() == data) 22707 | ) 22708 | { 22709 | return se.name; 22710 | } 22711 | } 22712 | 22713 | return "neo-vector" 22714 | } 22715 | 22716 | private: 22717 | 22718 | scope_element_manager(const scope_element_manager&) exprtk_delete; 22719 | scope_element_manager& operator=(const scope_element_manager&) exprtk_delete; 22720 | 22721 | parser_t& parser_; 22722 | std::vector<scope_element> element_; 22723 | scope_element null_element_; 22724 | std::size_t input_param_cnt_; 22725 | std::size_t total_local_symb_size_bytes_; 22726 | }; 22727 | 22728 | class scope_handler 22729 | { 22730 | public: 22731 | 22732 | typedef parser<T> parser_t; 22733 | 22734 | explicit scope_handler(parser<T>& p) 22735 | : parser_(p) 22736 | { 22737 | parser_.state_.scope_depth++; 22738 | #ifdef exprtk_enable_debugging 22739 | const std::string depth(2 * parser_.state_.scope_depth,'-'); 22740 | exprtk_debug(("%s> Scope Depth: %02d\n", 22741 | depth.c_str(), 22742 | static_cast<int>(parser_.state_.scope_depth))); 22743 | #endif 22744 | } 22745 | 22746 | ~scope_handler() 22747 | { 22748 | parser_.sem_.deactivate(parser_.state_.scope_depth); 22749 | parser_.state_.scope_depth--; 22750 | #ifdef exprtk_enable_debugging 22751 | const std::string depth(2 * parser_.state_.scope_depth,'-'); 22752 | exprtk_debug(("<%s Scope Depth: %02d\n", 22753 | depth.c_str(), 22754 | static_cast<int>(parser_.state_.scope_depth))); 22755 | #endif 22756 | } 22757 | 22758 | private: 22759 | 22760 | scope_handler(const scope_handler&) exprtk_delete; 22761 | scope_handler& operator=(const scope_handler&) exprtk_delete; 22762 | 22763 | parser_t& parser_; 22764 | }; 22765 | 22766 | template <typename T_> 22767 | struct halfopen_range_policy 22768 | { 22769 | static inline bool is_within(const T_& v, const T_& begin, const T_& end) 22770 | { 22771 | assert(begin <= end); 22772 | return (begin <= v) && (v < end); 22773 | } 22774 | 22775 | static inline bool is_less(const T_& v, const T_& begin) 22776 | { 22777 | return (v < begin); 22778 | } 22779 | 22780 | static inline bool is_greater(const T_& v, const T_& end) 22781 | { 22782 | return (end <= v); 22783 | } 22784 | 22785 | static inline bool end_inclusive() 22786 | { 22787 | return false; 22788 | } 22789 | }; 22790 | 22791 | template <typename T_> 22792 | struct closed_range_policy 22793 | { 22794 | static inline bool is_within(const T_& v, const T_& begin, const T_& end) 22795 | { 22796 | assert(begin <= end); 22797 | return (begin <= v) && (v <= end); 22798 | } 22799 | 22800 | static inline bool is_less(const T_& v, const T_& begin) 22801 | { 22802 | return (v < begin); 22803 | } 22804 | 22805 | static inline bool is_greater(const T_& v, const T_& end) 22806 | { 22807 | return (end < v); 22808 | } 22809 | 22810 | static inline bool end_inclusive() 22811 | { 22812 | return true; 22813 | } 22814 | }; 22815 | 22816 | template <typename IntervalPointType, 22817 | typename RangePolicy = halfopen_range_policy<IntervalPointType> > 22818 | class interval_container_t 22819 | { 22820 | public: 22821 | 22822 | typedef IntervalPointType interval_point_t; 22823 | typedef std::pair<interval_point_t, interval_point_t> interval_t; 22824 | typedef std::map<interval_point_t, interval_t> interval_map_t; 22825 | typedef typename interval_map_t::const_iterator interval_map_citr_t; 22826 | 22827 | std::size_t size() const 22828 | { 22829 | return interval_map_.size(); 22830 | } 22831 | 22832 | void reset() 22833 | { 22834 | interval_map_.clear(); 22835 | } 22836 | 22837 | bool in_interval(const interval_point_t point, interval_t& interval) const 22838 | { 22839 | interval_map_citr_t itr = RangePolicy::end_inclusive() ? 22840 | interval_map_.lower_bound(point): 22841 | interval_map_.upper_bound(point); 22842 | 22843 | for (; itr != interval_map_.end(); ++itr) 22844 | { 22845 | const interval_point_t& begin = itr->second.first; 22846 | const interval_point_t& end = itr->second.second; 22847 | 22848 | if (RangePolicy::is_within(point, begin, end)) 22849 | { 22850 | interval = interval_t(begin,end); 22851 | return true; 22852 | } 22853 | else if (RangePolicy::is_greater(point, end)) 22854 | { 22855 | break; 22856 | } 22857 | } 22858 | 22859 | return false; 22860 | } 22861 | 22862 | bool in_interval(const interval_point_t point) const 22863 | { 22864 | interval_t interval; 22865 | return in_interval(point,interval); 22866 | } 22867 | 22868 | bool add_interval(const interval_point_t begin, const interval_point_t end) 22869 | { 22870 | if ((end <= begin) || in_interval(begin) || in_interval(end)) 22871 | { 22872 | return false; 22873 | } 22874 | 22875 | interval_map_[end] = std::make_pair(begin, end); 22876 | 22877 | return true; 22878 | } 22879 | 22880 | bool add_interval(const interval_t interval) 22881 | { 22882 | return add_interval(interval.first, interval.second); 22883 | } 22884 | 22885 | private: 22886 | 22887 | interval_map_t interval_map_; 22888 | }; 22889 | 22890 | class stack_limit_handler 22891 | { 22892 | public: 22893 | 22894 | typedef parser<T> parser_t; 22895 | 22896 | explicit stack_limit_handler(parser<T>& p) 22897 | : parser_(p) 22898 | , limit_exceeded_(false) 22899 | { 22900 | if (++parser_.state_.stack_depth > parser_.settings_.max_stack_depth_) 22901 | { 22902 | limit_exceeded_ = true; 22903 | parser_.set_error(make_error( 22904 | parser_error::e_parser, 22905 | "ERR000 - Current stack depth " + details::to_str(parser_.state_.stack_depth) + 22906 | " exceeds maximum allowed stack depth of " + details::to_str(parser_.settings_.max_stack_depth_), 22907 | exprtk_error_location)); 22908 | } 22909 | } 22910 | 22911 | ~stack_limit_handler() 22912 | { 22913 | assert(parser_.state_.stack_depth > 0); 22914 | parser_.state_.stack_depth--; 22915 | } 22916 | 22917 | bool operator!() 22918 | { 22919 | return limit_exceeded_; 22920 | } 22921 | 22922 | private: 22923 | 22924 | stack_limit_handler(const stack_limit_handler&) exprtk_delete; 22925 | stack_limit_handler& operator=(const stack_limit_handler&) exprtk_delete; 22926 | 22927 | parser_t& parser_; 22928 | bool limit_exceeded_; 22929 | }; 22930 | 22931 | struct symtab_store 22932 | { 22933 | symbol_table_list_t symtab_list_; 22934 | 22935 | typedef typename symbol_table_t::local_data_t local_data_t; 22936 | typedef typename symbol_table_t::variable_ptr variable_ptr; 22937 | typedef typename symbol_table_t::function_ptr function_ptr; 22938 | #ifndef exprtk_disable_string_capabilities 22939 | typedef typename symbol_table_t::stringvar_ptr stringvar_ptr; 22940 | #endif 22941 | typedef typename symbol_table_t::vector_holder_ptr vector_holder_ptr; 22942 | typedef typename symbol_table_t::vararg_function_ptr vararg_function_ptr; 22943 | typedef typename symbol_table_t::generic_function_ptr generic_function_ptr; 22944 | 22945 | struct variable_context 22946 | { 22947 | variable_context() 22948 | : symbol_table(0) 22949 | , variable(0) 22950 | {} 22951 | 22952 | const symbol_table_t* symbol_table; 22953 | variable_ptr variable; 22954 | }; 22955 | 22956 | struct vector_context 22957 | { 22958 | vector_context() 22959 | : symbol_table(0) 22960 | , vector_holder(0) 22961 | {} 22962 | 22963 | const symbol_table_t* symbol_table; 22964 | vector_holder_ptr vector_holder; 22965 | }; 22966 | 22967 | #ifndef exprtk_disable_string_capabilities 22968 | struct string_context 22969 | { 22970 | string_context() 22971 | : symbol_table(0) 22972 | , str_var(0) 22973 | {} 22974 | 22975 | const symbol_table_t* symbol_table; 22976 | stringvar_ptr str_var; 22977 | }; 22978 | #endif 22979 | 22980 | inline bool empty() const 22981 | { 22982 | return symtab_list_.empty(); 22983 | } 22984 | 22985 | inline void clear() 22986 | { 22987 | symtab_list_.clear(); 22988 | } 22989 | 22990 | inline bool valid() const 22991 | { 22992 | if (!empty()) 22993 | { 22994 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 22995 | { 22996 | if (symtab_list_[i].valid()) 22997 | return true; 22998 | } 22999 | } 23000 | 23001 | return false; 23002 | } 23003 | 23004 | inline bool valid_symbol(const std::string& symbol) const 23005 | { 23006 | if (!symtab_list_.empty()) 23007 | return symtab_list_[0].valid_symbol(symbol); 23008 | else 23009 | return false; 23010 | } 23011 | 23012 | inline bool valid_function_name(const std::string& symbol) const 23013 | { 23014 | if (!symtab_list_.empty()) 23015 | return symtab_list_[0].valid_function(symbol); 23016 | else 23017 | return false; 23018 | } 23019 | 23020 | inline variable_context get_variable_context(const std::string& variable_name) const 23021 | { 23022 | variable_context result; 23023 | 23024 | if (valid_symbol(variable_name)) 23025 | { 23026 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23027 | { 23028 | if (!symtab_list_[i].valid()) 23029 | { 23030 | continue; 23031 | } 23032 | 23033 | result.variable = local_data(i) 23034 | .variable_store.get(variable_name); 23035 | if (result.variable) 23036 | { 23037 | result.symbol_table = &symtab_list_[i]; 23038 | break; 23039 | } 23040 | } 23041 | } 23042 | 23043 | return result; 23044 | } 23045 | 23046 | inline variable_ptr get_variable(const std::string& variable_name) const 23047 | { 23048 | if (!valid_symbol(variable_name)) 23049 | return reinterpret_cast<variable_ptr>(0); 23050 | 23051 | variable_ptr result = reinterpret_cast<variable_ptr>(0); 23052 | 23053 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23054 | { 23055 | if (!symtab_list_[i].valid()) 23056 | continue; 23057 | else 23058 | result = local_data(i) 23059 | .variable_store.get(variable_name); 23060 | 23061 | if (result) break; 23062 | } 23063 | 23064 | return result; 23065 | } 23066 | 23067 | inline variable_ptr get_variable(const T& var_ref) const 23068 | { 23069 | variable_ptr result = reinterpret_cast<variable_ptr>(0); 23070 | 23071 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23072 | { 23073 | if (!symtab_list_[i].valid()) 23074 | continue; 23075 | else 23076 | result = local_data(i).variable_store 23077 | .get_from_varptr(reinterpret_cast<const void*>(&var_ref)); 23078 | 23079 | if (result) break; 23080 | } 23081 | 23082 | return result; 23083 | } 23084 | 23085 | #ifndef exprtk_disable_string_capabilities 23086 | inline string_context get_string_context(const std::string& string_name) const 23087 | { 23088 | string_context result; 23089 | 23090 | if (!valid_symbol(string_name)) 23091 | return result; 23092 | 23093 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23094 | { 23095 | if (!symtab_list_[i].valid()) 23096 | { 23097 | continue; 23098 | } 23099 | 23100 | result.str_var = local_data(i).stringvar_store.get(string_name); 23101 | 23102 | if (result.str_var) 23103 | { 23104 | result.symbol_table = &symtab_list_[i]; 23105 | break; 23106 | } 23107 | } 23108 | 23109 | return result; 23110 | } 23111 | 23112 | inline stringvar_ptr get_stringvar(const std::string& string_name) const 23113 | { 23114 | if (!valid_symbol(string_name)) 23115 | return reinterpret_cast<stringvar_ptr>(0); 23116 | 23117 | stringvar_ptr result = reinterpret_cast<stringvar_ptr>(0); 23118 | 23119 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23120 | { 23121 | if (!symtab_list_[i].valid()) 23122 | continue; 23123 | else 23124 | result = local_data(i) 23125 | .stringvar_store.get(string_name); 23126 | 23127 | if (result) break; 23128 | } 23129 | 23130 | return result; 23131 | } 23132 | #endif 23133 | 23134 | inline function_ptr get_function(const std::string& function_name) const 23135 | { 23136 | if (!valid_function_name(function_name)) 23137 | return reinterpret_cast<function_ptr>(0); 23138 | 23139 | function_ptr result = reinterpret_cast<function_ptr>(0); 23140 | 23141 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23142 | { 23143 | if (!symtab_list_[i].valid()) 23144 | continue; 23145 | else 23146 | result = local_data(i) 23147 | .function_store.get(function_name); 23148 | 23149 | if (result) break; 23150 | } 23151 | 23152 | return result; 23153 | } 23154 | 23155 | inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name) const 23156 | { 23157 | if (!valid_function_name(vararg_function_name)) 23158 | return reinterpret_cast<vararg_function_ptr>(0); 23159 | 23160 | vararg_function_ptr result = reinterpret_cast<vararg_function_ptr>(0); 23161 | 23162 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23163 | { 23164 | if (!symtab_list_[i].valid()) 23165 | continue; 23166 | else 23167 | result = local_data(i) 23168 | .vararg_function_store.get(vararg_function_name); 23169 | 23170 | if (result) break; 23171 | } 23172 | 23173 | return result; 23174 | } 23175 | 23176 | inline generic_function_ptr get_generic_function(const std::string& function_name) const 23177 | { 23178 | if (!valid_function_name(function_name)) 23179 | return reinterpret_cast<generic_function_ptr>(0); 23180 | 23181 | generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0); 23182 | 23183 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23184 | { 23185 | if (!symtab_list_[i].valid()) 23186 | continue; 23187 | else 23188 | result = local_data(i) 23189 | .generic_function_store.get(function_name); 23190 | 23191 | if (result) break; 23192 | } 23193 | 23194 | return result; 23195 | } 23196 | 23197 | inline generic_function_ptr get_string_function(const std::string& function_name) const 23198 | { 23199 | if (!valid_function_name(function_name)) 23200 | return reinterpret_cast<generic_function_ptr>(0); 23201 | 23202 | generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0); 23203 | 23204 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23205 | { 23206 | if (!symtab_list_[i].valid()) 23207 | continue; 23208 | else 23209 | result = 23210 | local_data(i).string_function_store.get(function_name); 23211 | 23212 | if (result) break; 23213 | } 23214 | 23215 | return result; 23216 | } 23217 | 23218 | inline generic_function_ptr get_overload_function(const std::string& function_name) const 23219 | { 23220 | if (!valid_function_name(function_name)) 23221 | return reinterpret_cast<generic_function_ptr>(0); 23222 | 23223 | generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0); 23224 | 23225 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23226 | { 23227 | if (!symtab_list_[i].valid()) 23228 | continue; 23229 | else 23230 | result = 23231 | local_data(i).overload_function_store.get(function_name); 23232 | 23233 | if (result) break; 23234 | } 23235 | 23236 | return result; 23237 | } 23238 | 23239 | inline vector_context get_vector_context(const std::string& vector_name) const 23240 | { 23241 | vector_context result; 23242 | if (!valid_symbol(vector_name)) 23243 | return result; 23244 | 23245 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23246 | { 23247 | if (!symtab_list_[i].valid()) 23248 | { 23249 | continue; 23250 | } 23251 | 23252 | result.vector_holder = local_data(i).vector_store.get(vector_name); 23253 | 23254 | if (result.vector_holder) 23255 | { 23256 | result.symbol_table = &symtab_list_[i]; 23257 | break; 23258 | } 23259 | } 23260 | 23261 | return result; 23262 | } 23263 | 23264 | inline vector_holder_ptr get_vector(const std::string& vector_name) const 23265 | { 23266 | if (!valid_symbol(vector_name)) 23267 | return reinterpret_cast<vector_holder_ptr>(0); 23268 | 23269 | vector_holder_ptr result = reinterpret_cast<vector_holder_ptr>(0); 23270 | 23271 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23272 | { 23273 | if (!symtab_list_[i].valid()) 23274 | { 23275 | continue; 23276 | } 23277 | 23278 | result = local_data(i).vector_store.get(vector_name); 23279 | 23280 | if (result) 23281 | { 23282 | break; 23283 | } 23284 | } 23285 | 23286 | return result; 23287 | } 23288 | 23289 | inline bool is_constant_node(const std::string& symbol_name) const 23290 | { 23291 | if (!valid_symbol(symbol_name)) 23292 | return false; 23293 | 23294 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23295 | { 23296 | if (!symtab_list_[i].valid()) 23297 | { 23298 | continue; 23299 | } 23300 | 23301 | if (local_data(i).variable_store.is_constant(symbol_name)) 23302 | { 23303 | return true; 23304 | } 23305 | } 23306 | 23307 | return false; 23308 | } 23309 | 23310 | #ifndef exprtk_disable_string_capabilities 23311 | inline bool is_constant_string(const std::string& symbol_name) const 23312 | { 23313 | if (!valid_symbol(symbol_name)) 23314 | return false; 23315 | 23316 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23317 | { 23318 | if (!symtab_list_[i].valid()) 23319 | continue; 23320 | else if (!local_data(i).stringvar_store.symbol_exists(symbol_name)) 23321 | continue; 23322 | else if (local_data(i).stringvar_store.is_constant(symbol_name)) 23323 | return true; 23324 | } 23325 | 23326 | return false; 23327 | } 23328 | #endif 23329 | 23330 | inline bool symbol_exists(const std::string& symbol) const 23331 | { 23332 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23333 | { 23334 | if (!symtab_list_[i].valid()) 23335 | { 23336 | continue; 23337 | } 23338 | 23339 | if (symtab_list_[i].symbol_exists(symbol)) 23340 | { 23341 | return true; 23342 | } 23343 | } 23344 | 23345 | return false; 23346 | } 23347 | 23348 | inline bool is_variable(const std::string& variable_name) const 23349 | { 23350 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23351 | { 23352 | if (!symtab_list_[i].valid()) 23353 | continue; 23354 | else if ( 23355 | symtab_list_[i].local_data().variable_store 23356 | .symbol_exists(variable_name) 23357 | ) 23358 | return true; 23359 | } 23360 | 23361 | return false; 23362 | } 23363 | 23364 | #ifndef exprtk_disable_string_capabilities 23365 | inline bool is_stringvar(const std::string& stringvar_name) const 23366 | { 23367 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23368 | { 23369 | if (!symtab_list_[i].valid()) 23370 | continue; 23371 | else if ( 23372 | symtab_list_[i].local_data().stringvar_store 23373 | .symbol_exists(stringvar_name) 23374 | ) 23375 | return true; 23376 | } 23377 | 23378 | return false; 23379 | } 23380 | 23381 | inline bool is_conststr_stringvar(const std::string& symbol_name) const 23382 | { 23383 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23384 | { 23385 | if (!symtab_list_[i].valid()) 23386 | continue; 23387 | else if ( 23388 | symtab_list_[i].local_data().stringvar_store 23389 | .symbol_exists(symbol_name) 23390 | ) 23391 | { 23392 | return ( 23393 | local_data(i).stringvar_store.symbol_exists(symbol_name) || 23394 | local_data(i).stringvar_store.is_constant (symbol_name) 23395 | ); 23396 | 23397 | } 23398 | } 23399 | 23400 | return false; 23401 | } 23402 | #endif 23403 | 23404 | inline bool is_function(const std::string& function_name) const 23405 | { 23406 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23407 | { 23408 | if (!symtab_list_[i].valid()) 23409 | continue; 23410 | else if ( 23411 | local_data(i).vararg_function_store 23412 | .symbol_exists(function_name) 23413 | ) 23414 | return true; 23415 | } 23416 | 23417 | return false; 23418 | } 23419 | 23420 | inline bool is_vararg_function(const std::string& vararg_function_name) const 23421 | { 23422 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23423 | { 23424 | if (!symtab_list_[i].valid()) 23425 | continue; 23426 | else if ( 23427 | local_data(i).vararg_function_store 23428 | .symbol_exists(vararg_function_name) 23429 | ) 23430 | return true; 23431 | } 23432 | 23433 | return false; 23434 | } 23435 | 23436 | inline bool is_vector(const std::string& vector_name) const 23437 | { 23438 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) 23439 | { 23440 | if (!symtab_list_[i].valid()) 23441 | continue; 23442 | else if ( 23443 | local_data(i).vector_store 23444 | .symbol_exists(vector_name) 23445 | ) 23446 | return true; 23447 | } 23448 | 23449 | return false; 23450 | } 23451 | 23452 | inline std::string get_variable_name(const expression_node_ptr& ptr) const 23453 | { 23454 | return local_data().variable_store.entity_name(ptr); 23455 | } 23456 | 23457 | inline std::string get_vector_name(const vector_holder_ptr& ptr) const 23458 | { 23459 | return local_data().vector_store.entity_name(ptr); 23460 | } 23461 | 23462 | #ifndef exprtk_disable_string_capabilities 23463 | inline std::string get_stringvar_name(const expression_node_ptr& ptr) const 23464 | { 23465 | return local_data().stringvar_store.entity_name(ptr); 23466 | } 23467 | 23468 | inline std::string get_conststr_stringvar_name(const expression_node_ptr& ptr) const 23469 | { 23470 | return local_data().stringvar_store.entity_name(ptr); 23471 | } 23472 | #endif 23473 | 23474 | inline local_data_t& local_data(const std::size_t& index = 0) 23475 | { 23476 | return symtab_list_[index].local_data(); 23477 | } 23478 | 23479 | inline const local_data_t& local_data(const std::size_t& index = 0) const 23480 | { 23481 | return symtab_list_[index].local_data(); 23482 | } 23483 | 23484 | inline symbol_table_t& get_symbol_table(const std::size_t& index = 0) 23485 | { 23486 | return symtab_list_[index]; 23487 | } 23488 | }; 23489 | 23490 | struct parser_state 23491 | { 23492 | parser_state() 23493 | : type_check_enabled(true) 23494 | { 23495 | reset(); 23496 | } 23497 | 23498 | void reset() 23499 | { 23500 | parsing_return_stmt = false; 23501 | parsing_break_stmt = false; 23502 | parsing_assert_stmt = false; 23503 | return_stmt_present = false; 23504 | side_effect_present = false; 23505 | scope_depth = 0; 23506 | stack_depth = 0; 23507 | parsing_loop_stmt_count = 0; 23508 | } 23509 | 23510 | #ifndef exprtk_enable_debugging 23511 | void activate_side_effect(const std::string&) 23512 | #else 23513 | void activate_side_effect(const std::string& source) 23514 | #endif 23515 | { 23516 | if (!side_effect_present) 23517 | { 23518 | side_effect_present = true; 23519 | 23520 | exprtk_debug(("activate_side_effect() - caller: %s\n", source.c_str())); 23521 | } 23522 | } 23523 | 23524 | bool parsing_return_stmt; 23525 | bool parsing_break_stmt; 23526 | bool parsing_assert_stmt; 23527 | bool return_stmt_present; 23528 | bool side_effect_present; 23529 | bool type_check_enabled; 23530 | std::size_t scope_depth; 23531 | std::size_t stack_depth; 23532 | std::size_t parsing_loop_stmt_count; 23533 | }; 23534 | 23535 | public: 23536 | 23537 | struct unknown_symbol_resolver 23538 | { 23539 | 23540 | enum usr_symbol_type 23541 | { 23542 | e_usr_unknown_type = 0, 23543 | e_usr_variable_type = 1, 23544 | e_usr_constant_type = 2 23545 | }; 23546 | 23547 | enum usr_mode 23548 | { 23549 | e_usrmode_default = 0, 23550 | e_usrmode_extended = 1 23551 | }; 23552 | 23553 | usr_mode mode; 23554 | 23555 | explicit unknown_symbol_resolver(const usr_mode m = e_usrmode_default) 23556 | : mode(m) 23557 | {} 23558 | 23559 | virtual ~unknown_symbol_resolver() 23560 | {} 23561 | 23562 | virtual bool process(const std::string& /*unknown_symbol*/, 23563 | usr_symbol_type& st, 23564 | T& default_value, 23565 | std::string& error_message) 23566 | { 23567 | if (e_usrmode_default != mode) 23568 | return false; 23569 | 23570 | st = e_usr_variable_type; 23571 | default_value = T(0); 23572 | error_message.clear(); 23573 | 23574 | return true; 23575 | } 23576 | 23577 | virtual bool process(const std::string& /* unknown_symbol */, 23578 | symbol_table_t& /* symbol_table */, 23579 | std::string& /* error_message */) 23580 | { 23581 | return false; 23582 | } 23583 | }; 23584 | 23585 | enum collect_type 23586 | { 23587 | e_ct_none = 0, 23588 | e_ct_variables = 1, 23589 | e_ct_functions = 2, 23590 | e_ct_assignments = 4 23591 | }; 23592 | 23593 | enum symbol_type 23594 | { 23595 | e_st_unknown = 0, 23596 | e_st_variable = 1, 23597 | e_st_vector = 2, 23598 | e_st_vecelem = 3, 23599 | e_st_string = 4, 23600 | e_st_function = 5, 23601 | e_st_local_variable = 6, 23602 | e_st_local_vector = 7, 23603 | e_st_local_string = 8 23604 | }; 23605 | 23606 | class dependent_entity_collector 23607 | { 23608 | public: 23609 | 23610 | typedef std::pair<std::string,symbol_type> symbol_t; 23611 | typedef std::vector<symbol_t> symbol_list_t; 23612 | 23613 | explicit dependent_entity_collector(const std::size_t options = e_ct_none) 23614 | : options_(options) 23615 | , collect_variables_ ((options_ & e_ct_variables ) == e_ct_variables ) 23616 | , collect_functions_ ((options_ & e_ct_functions ) == e_ct_functions ) 23617 | , collect_assignments_((options_ & e_ct_assignments) == e_ct_assignments) 23618 | , return_present_ (false) 23619 | , final_stmt_return_(false) 23620 | {} 23621 | 23622 | template <typename Allocator, 23623 | template <typename, typename> class Sequence> 23624 | inline std::size_t symbols(Sequence<symbol_t,Allocator>& symbols_list) 23625 | { 23626 | if (!collect_variables_ && !collect_functions_) 23627 | return 0; 23628 | else if (symbol_name_list_.empty()) 23629 | return 0; 23630 | 23631 | for (std::size_t i = 0; i < symbol_name_list_.size(); ++i) 23632 | { 23633 | details::case_normalise(symbol_name_list_[i].first); 23634 | } 23635 | 23636 | std::sort(symbol_name_list_.begin(), symbol_name_list_.end()); 23637 | 23638 | std::unique_copy 23639 | ( 23640 | symbol_name_list_.begin(), 23641 | symbol_name_list_.end (), 23642 | std::back_inserter(symbols_list) 23643 | ); 23644 | 23645 | return symbols_list.size(); 23646 | } 23647 | 23648 | template <typename Allocator, 23649 | template <typename, typename> class Sequence> 23650 | inline std::size_t assignment_symbols(Sequence<symbol_t,Allocator>& assignment_list) 23651 | { 23652 | if (!collect_assignments_) 23653 | return 0; 23654 | else if (assignment_name_list_.empty()) 23655 | return 0; 23656 | 23657 | for (std::size_t i = 0; i < assignment_name_list_.size(); ++i) 23658 | { 23659 | details::case_normalise(assignment_name_list_[i].first); 23660 | } 23661 | 23662 | std::sort(assignment_name_list_.begin(),assignment_name_list_.end()); 23663 | 23664 | std::unique_copy 23665 | ( 23666 | assignment_name_list_.begin(), 23667 | assignment_name_list_.end (), 23668 | std::back_inserter(assignment_list) 23669 | ); 23670 | 23671 | return assignment_list.size(); 23672 | } 23673 | 23674 | void clear() 23675 | { 23676 | symbol_name_list_ .clear(); 23677 | assignment_name_list_.clear(); 23678 | retparam_list_ .clear(); 23679 | return_present_ = false; 23680 | final_stmt_return_ = false; 23681 | } 23682 | 23683 | bool& collect_variables() 23684 | { 23685 | return collect_variables_; 23686 | } 23687 | 23688 | bool& collect_functions() 23689 | { 23690 | return collect_functions_; 23691 | } 23692 | 23693 | bool& collect_assignments() 23694 | { 23695 | return collect_assignments_; 23696 | } 23697 | 23698 | bool return_present() const 23699 | { 23700 | return return_present_; 23701 | } 23702 | 23703 | bool final_stmt_return() const 23704 | { 23705 | return final_stmt_return_; 23706 | } 23707 | 23708 | typedef std::vector<std::string> retparam_list_t; 23709 | 23710 | retparam_list_t return_param_type_list() const 23711 | { 23712 | return retparam_list_; 23713 | } 23714 | 23715 | private: 23716 | 23717 | inline void add_symbol(const std::string& symbol, const symbol_type st) 23718 | { 23719 | switch (st) 23720 | { 23721 | case e_st_variable : 23722 | case e_st_vector : 23723 | case e_st_string : 23724 | case e_st_local_variable : 23725 | case e_st_local_vector : 23726 | case e_st_local_string : if (collect_variables_) 23727 | symbol_name_list_ 23728 | .push_back(std::make_pair(symbol, st)); 23729 | break; 23730 | 23731 | case e_st_function : if (collect_functions_) 23732 | symbol_name_list_ 23733 | .push_back(std::make_pair(symbol, st)); 23734 | break; 23735 | 23736 | default : return; 23737 | } 23738 | } 23739 | 23740 | inline void add_assignment(const std::string& symbol, const symbol_type st) 23741 | { 23742 | switch (st) 23743 | { 23744 | case e_st_variable : 23745 | case e_st_vector : 23746 | case e_st_string : if (collect_assignments_) 23747 | assignment_name_list_ 23748 | .push_back(std::make_pair(symbol, st)); 23749 | break; 23750 | 23751 | default : return; 23752 | } 23753 | } 23754 | 23755 | std::size_t options_; 23756 | bool collect_variables_; 23757 | bool collect_functions_; 23758 | bool collect_assignments_; 23759 | bool return_present_; 23760 | bool final_stmt_return_; 23761 | symbol_list_t symbol_name_list_; 23762 | symbol_list_t assignment_name_list_; 23763 | retparam_list_t retparam_list_; 23764 | 23765 | friend class parser<T>; 23766 | }; 23767 | 23768 | class settings_store 23769 | { 23770 | private: 23771 | 23772 | typedef std::set<std::string,details::ilesscompare> disabled_entity_set_t; 23773 | typedef disabled_entity_set_t::iterator des_itr_t; 23774 | 23775 | public: 23776 | 23777 | enum settings_compilation_options 23778 | { 23779 | e_unknown = 0, 23780 | e_replacer = 1, 23781 | e_joiner = 2, 23782 | e_numeric_check = 4, 23783 | e_bracket_check = 8, 23784 | e_sequence_check = 16, 23785 | e_commutative_check = 32, 23786 | e_strength_reduction = 64, 23787 | e_disable_vardef = 128, 23788 | e_collect_vars = 256, 23789 | e_collect_funcs = 512, 23790 | e_collect_assings = 1024, 23791 | e_disable_usr_on_rsrvd = 2048, 23792 | e_disable_zero_return = 4096 23793 | }; 23794 | 23795 | enum settings_base_funcs 23796 | { 23797 | e_bf_unknown = 0, 23798 | e_bf_abs , e_bf_acos , e_bf_acosh , e_bf_asin , 23799 | e_bf_asinh , e_bf_atan , e_bf_atan2 , e_bf_atanh , 23800 | e_bf_avg , e_bf_ceil , e_bf_clamp , e_bf_cos , 23801 | e_bf_cosh , e_bf_cot , e_bf_csc , e_bf_equal , 23802 | e_bf_erf , e_bf_erfc , e_bf_exp , e_bf_expm1 , 23803 | e_bf_floor , e_bf_frac , e_bf_hypot , e_bf_iclamp , 23804 | e_bf_like , e_bf_log , e_bf_log10 , e_bf_log1p , 23805 | e_bf_log2 , e_bf_logn , e_bf_mand , e_bf_max , 23806 | e_bf_min , e_bf_mod , e_bf_mor , e_bf_mul , 23807 | e_bf_ncdf , e_bf_pow , e_bf_root , e_bf_round , 23808 | e_bf_roundn , e_bf_sec , e_bf_sgn , e_bf_sin , 23809 | e_bf_sinc , e_bf_sinh , e_bf_sqrt , e_bf_sum , 23810 | e_bf_swap , e_bf_tan , e_bf_tanh , e_bf_trunc , 23811 | e_bf_not_equal , e_bf_inrange , e_bf_deg2grad , e_bf_deg2rad , 23812 | e_bf_rad2deg , e_bf_grad2deg 23813 | }; 23814 | 23815 | enum settings_control_structs 23816 | { 23817 | e_ctrl_unknown = 0, 23818 | e_ctrl_ifelse, 23819 | e_ctrl_switch, 23820 | e_ctrl_for_loop, 23821 | e_ctrl_while_loop, 23822 | e_ctrl_repeat_loop, 23823 | e_ctrl_return 23824 | }; 23825 | 23826 | enum settings_logic_opr 23827 | { 23828 | e_logic_unknown = 0, 23829 | e_logic_and, e_logic_nand , e_logic_nor , 23830 | e_logic_not, e_logic_or , e_logic_xnor, 23831 | e_logic_xor, e_logic_scand, e_logic_scor 23832 | }; 23833 | 23834 | enum settings_arithmetic_opr 23835 | { 23836 | e_arith_unknown = 0, 23837 | e_arith_add, e_arith_sub, e_arith_mul, 23838 | e_arith_div, e_arith_mod, e_arith_pow 23839 | }; 23840 | 23841 | enum settings_assignment_opr 23842 | { 23843 | e_assign_unknown = 0, 23844 | e_assign_assign, e_assign_addass, e_assign_subass, 23845 | e_assign_mulass, e_assign_divass, e_assign_modass 23846 | }; 23847 | 23848 | enum settings_inequality_opr 23849 | { 23850 | e_ineq_unknown = 0, 23851 | e_ineq_lt , e_ineq_lte, e_ineq_eq , 23852 | e_ineq_equal, e_ineq_ne , e_ineq_nequal, 23853 | e_ineq_gte , e_ineq_gt 23854 | }; 23855 | 23856 | static const std::size_t default_compile_all_opts = 23857 | e_replacer + 23858 | e_joiner + 23859 | e_numeric_check + 23860 | e_bracket_check + 23861 | e_sequence_check + 23862 | e_commutative_check + 23863 | e_strength_reduction; 23864 | 23865 | settings_store(const std::size_t compile_options = default_compile_all_opts) 23866 | : max_stack_depth_(400) 23867 | , max_node_depth_(10000) 23868 | , max_total_local_symbol_size_bytes_(2000000000) 23869 | , max_local_vector_size_(max_total_local_symbol_size_bytes_ / sizeof(T)) 23870 | { 23871 | load_compile_options(compile_options); 23872 | } 23873 | 23874 | settings_store& enable_all_base_functions() 23875 | { 23876 | disabled_func_set_.clear(); 23877 | return (*this); 23878 | } 23879 | 23880 | settings_store& enable_all_control_structures() 23881 | { 23882 | disabled_ctrl_set_.clear(); 23883 | return (*this); 23884 | } 23885 | 23886 | settings_store& enable_all_logic_ops() 23887 | { 23888 | disabled_logic_set_.clear(); 23889 | return (*this); 23890 | } 23891 | 23892 | settings_store& enable_all_arithmetic_ops() 23893 | { 23894 | disabled_arithmetic_set_.clear(); 23895 | return (*this); 23896 | } 23897 | 23898 | settings_store& enable_all_assignment_ops() 23899 | { 23900 | disabled_assignment_set_.clear(); 23901 | return (*this); 23902 | } 23903 | 23904 | settings_store& enable_all_inequality_ops() 23905 | { 23906 | disabled_inequality_set_.clear(); 23907 | return (*this); 23908 | } 23909 | 23910 | settings_store& enable_local_vardef() 23911 | { 23912 | disable_vardef_ = false; 23913 | return (*this); 23914 | } 23915 | 23916 | settings_store& enable_commutative_check() 23917 | { 23918 | enable_commutative_check_ = true; 23919 | return (*this); 23920 | } 23921 | 23922 | settings_store& enable_strength_reduction() 23923 | { 23924 | enable_strength_reduction_ = true; 23925 | return (*this); 23926 | } 23927 | 23928 | settings_store& disable_all_base_functions() 23929 | { 23930 | std::copy(details::base_function_list, 23931 | details::base_function_list + details::base_function_list_size, 23932 | std::insert_iterator<disabled_entity_set_t> 23933 | (disabled_func_set_, disabled_func_set_.begin())); 23934 | return (*this); 23935 | } 23936 | 23937 | settings_store& disable_all_control_structures() 23938 | { 23939 | std::copy(details::cntrl_struct_list, 23940 | details::cntrl_struct_list + details::cntrl_struct_list_size, 23941 | std::insert_iterator<disabled_entity_set_t> 23942 | (disabled_ctrl_set_, disabled_ctrl_set_.begin())); 23943 | return (*this); 23944 | } 23945 | 23946 | settings_store& disable_all_logic_ops() 23947 | { 23948 | std::copy(details::logic_ops_list, 23949 | details::logic_ops_list + details::logic_ops_list_size, 23950 | std::insert_iterator<disabled_entity_set_t> 23951 | (disabled_logic_set_, disabled_logic_set_.begin())); 23952 | return (*this); 23953 | } 23954 | 23955 | settings_store& disable_all_arithmetic_ops() 23956 | { 23957 | std::copy(details::arithmetic_ops_list, 23958 | details::arithmetic_ops_list + details::arithmetic_ops_list_size, 23959 | std::insert_iterator<disabled_entity_set_t> 23960 | (disabled_arithmetic_set_, disabled_arithmetic_set_.begin())); 23961 | return (*this); 23962 | } 23963 | 23964 | settings_store& disable_all_assignment_ops() 23965 | { 23966 | std::copy(details::assignment_ops_list, 23967 | details::assignment_ops_list + details::assignment_ops_list_size, 23968 | std::insert_iterator<disabled_entity_set_t> 23969 | (disabled_assignment_set_, disabled_assignment_set_.begin())); 23970 | return (*this); 23971 | } 23972 | 23973 | settings_store& disable_all_inequality_ops() 23974 | { 23975 | std::copy(details::inequality_ops_list, 23976 | details::inequality_ops_list + details::inequality_ops_list_size, 23977 | std::insert_iterator<disabled_entity_set_t> 23978 | (disabled_inequality_set_, disabled_inequality_set_.begin())); 23979 | return (*this); 23980 | } 23981 | 23982 | settings_store& disable_local_vardef() 23983 | { 23984 | disable_vardef_ = true; 23985 | return (*this); 23986 | } 23987 | 23988 | settings_store& disable_commutative_check() 23989 | { 23990 | enable_commutative_check_ = false; 23991 | return (*this); 23992 | } 23993 | 23994 | settings_store& disable_strength_reduction() 23995 | { 23996 | enable_strength_reduction_ = false; 23997 | return (*this); 23998 | } 23999 | 24000 | bool replacer_enabled () const { return enable_replacer_; } 24001 | bool commutative_check_enabled () const { return enable_commutative_check_; } 24002 | bool joiner_enabled () const { return enable_joiner_; } 24003 | bool numeric_check_enabled () const { return enable_numeric_check_; } 24004 | bool bracket_check_enabled () const { return enable_bracket_check_; } 24005 | bool sequence_check_enabled () const { return enable_sequence_check_; } 24006 | bool strength_reduction_enabled () const { return enable_strength_reduction_; } 24007 | bool collect_variables_enabled () const { return enable_collect_vars_; } 24008 | bool collect_functions_enabled () const { return enable_collect_funcs_; } 24009 | bool collect_assignments_enabled() const { return enable_collect_assings_; } 24010 | bool vardef_disabled () const { return disable_vardef_; } 24011 | bool rsrvd_sym_usr_disabled () const { return disable_rsrvd_sym_usr_; } 24012 | bool zero_return_disabled () const { return disable_zero_return_; } 24013 | 24014 | bool function_enabled(const std::string& function_name) const 24015 | { 24016 | if (disabled_func_set_.empty()) 24017 | return true; 24018 | else 24019 | return (disabled_func_set_.end() == disabled_func_set_.find(function_name)); 24020 | } 24021 | 24022 | bool control_struct_enabled(const std::string& control_struct) const 24023 | { 24024 | if (disabled_ctrl_set_.empty()) 24025 | return true; 24026 | else 24027 | return (disabled_ctrl_set_.end() == disabled_ctrl_set_.find(control_struct)); 24028 | } 24029 | 24030 | bool logic_enabled(const std::string& logic_operation) const 24031 | { 24032 | if (disabled_logic_set_.empty()) 24033 | return true; 24034 | else 24035 | return (disabled_logic_set_.end() == disabled_logic_set_.find(logic_operation)); 24036 | } 24037 | 24038 | bool arithmetic_enabled(const details::operator_type& arithmetic_operation) const 24039 | { 24040 | if (disabled_logic_set_.empty()) 24041 | return true; 24042 | else 24043 | return disabled_arithmetic_set_.end() == disabled_arithmetic_set_ 24044 | .find(arith_opr_to_string(arithmetic_operation)); 24045 | } 24046 | 24047 | bool assignment_enabled(const details::operator_type& assignment) const 24048 | { 24049 | if (disabled_assignment_set_.empty()) 24050 | return true; 24051 | else 24052 | return disabled_assignment_set_.end() == disabled_assignment_set_ 24053 | .find(assign_opr_to_string(assignment)); 24054 | } 24055 | 24056 | bool inequality_enabled(const details::operator_type& inequality) const 24057 | { 24058 | if (disabled_inequality_set_.empty()) 24059 | return true; 24060 | else 24061 | return disabled_inequality_set_.end() == disabled_inequality_set_ 24062 | .find(inequality_opr_to_string(inequality)); 24063 | } 24064 | 24065 | bool function_disabled(const std::string& function_name) const 24066 | { 24067 | if (disabled_func_set_.empty()) 24068 | return false; 24069 | else 24070 | return (disabled_func_set_.end() != disabled_func_set_.find(function_name)); 24071 | } 24072 | 24073 | bool control_struct_disabled(const std::string& control_struct) const 24074 | { 24075 | if (disabled_ctrl_set_.empty()) 24076 | return false; 24077 | else 24078 | return (disabled_ctrl_set_.end() != disabled_ctrl_set_.find(control_struct)); 24079 | } 24080 | 24081 | bool logic_disabled(const std::string& logic_operation) const 24082 | { 24083 | if (disabled_logic_set_.empty()) 24084 | return false; 24085 | else 24086 | return (disabled_logic_set_.end() != disabled_logic_set_.find(logic_operation)); 24087 | } 24088 | 24089 | bool assignment_disabled(const details::operator_type assignment_operation) const 24090 | { 24091 | if (disabled_assignment_set_.empty()) 24092 | return false; 24093 | else 24094 | return disabled_assignment_set_.end() != disabled_assignment_set_ 24095 | .find(assign_opr_to_string(assignment_operation)); 24096 | } 24097 | 24098 | bool logic_disabled(const details::operator_type logic_operation) const 24099 | { 24100 | if (disabled_logic_set_.empty()) 24101 | return false; 24102 | else 24103 | return disabled_logic_set_.end() != disabled_logic_set_ 24104 | .find(logic_opr_to_string(logic_operation)); 24105 | } 24106 | 24107 | bool arithmetic_disabled(const details::operator_type arithmetic_operation) const 24108 | { 24109 | if (disabled_arithmetic_set_.empty()) 24110 | return false; 24111 | else 24112 | return disabled_arithmetic_set_.end() != disabled_arithmetic_set_ 24113 | .find(arith_opr_to_string(arithmetic_operation)); 24114 | } 24115 | 24116 | bool inequality_disabled(const details::operator_type& inequality) const 24117 | { 24118 | if (disabled_inequality_set_.empty()) 24119 | return false; 24120 | else 24121 | return disabled_inequality_set_.end() != disabled_inequality_set_ 24122 | .find(inequality_opr_to_string(inequality)); 24123 | } 24124 | 24125 | settings_store& disable_base_function(const settings_base_funcs bf) 24126 | { 24127 | if ( 24128 | (e_bf_unknown != bf) && 24129 | (static_cast<std::size_t>(bf) < (details::base_function_list_size + 1)) 24130 | ) 24131 | { 24132 | disabled_func_set_.insert(details::base_function_list[bf - 1]); 24133 | } 24134 | 24135 | return (*this); 24136 | } 24137 | 24138 | settings_store& disable_control_structure(const settings_control_structs ctrl_struct) 24139 | { 24140 | if ( 24141 | (e_ctrl_unknown != ctrl_struct) && 24142 | (static_cast<std::size_t>(ctrl_struct) < (details::cntrl_struct_list_size + 1)) 24143 | ) 24144 | { 24145 | disabled_ctrl_set_.insert(details::cntrl_struct_list[ctrl_struct - 1]); 24146 | } 24147 | 24148 | return (*this); 24149 | } 24150 | 24151 | settings_store& disable_logic_operation(const settings_logic_opr logic) 24152 | { 24153 | if ( 24154 | (e_logic_unknown != logic) && 24155 | (static_cast<std::size_t>(logic) < (details::logic_ops_list_size + 1)) 24156 | ) 24157 | { 24158 | disabled_logic_set_.insert(details::logic_ops_list[logic - 1]); 24159 | } 24160 | 24161 | return (*this); 24162 | } 24163 | 24164 | settings_store& disable_arithmetic_operation(const settings_arithmetic_opr arithmetic) 24165 | { 24166 | if ( 24167 | (e_arith_unknown != arithmetic) && 24168 | (static_cast<std::size_t>(arithmetic) < (details::arithmetic_ops_list_size + 1)) 24169 | ) 24170 | { 24171 | disabled_arithmetic_set_.insert(details::arithmetic_ops_list[arithmetic - 1]); 24172 | } 24173 | 24174 | return (*this); 24175 | } 24176 | 24177 | settings_store& disable_assignment_operation(const settings_assignment_opr assignment) 24178 | { 24179 | if ( 24180 | (e_assign_unknown != assignment) && 24181 | (static_cast<std::size_t>(assignment) < (details::assignment_ops_list_size + 1)) 24182 | ) 24183 | { 24184 | disabled_assignment_set_.insert(details::assignment_ops_list[assignment - 1]); 24185 | } 24186 | 24187 | return (*this); 24188 | } 24189 | 24190 | settings_store& disable_inequality_operation(const settings_inequality_opr inequality) 24191 | { 24192 | if ( 24193 | (e_ineq_unknown != inequality) && 24194 | (static_cast<std::size_t>(inequality) < (details::inequality_ops_list_size + 1)) 24195 | ) 24196 | { 24197 | disabled_inequality_set_.insert(details::inequality_ops_list[inequality - 1]); 24198 | } 24199 | 24200 | return (*this); 24201 | } 24202 | 24203 | settings_store& enable_base_function(const settings_base_funcs bf) 24204 | { 24205 | if ( 24206 | (e_bf_unknown != bf) && 24207 | (static_cast<std::size_t>(bf) < (details::base_function_list_size + 1)) 24208 | ) 24209 | { 24210 | const des_itr_t itr = disabled_func_set_.find(details::base_function_list[bf - 1]); 24211 | 24212 | if (disabled_func_set_.end() != itr) 24213 | { 24214 | disabled_func_set_.erase(itr); 24215 | } 24216 | } 24217 | 24218 | return (*this); 24219 | } 24220 | 24221 | settings_store& enable_control_structure(const settings_control_structs ctrl_struct) 24222 | { 24223 | if ( 24224 | (e_ctrl_unknown != ctrl_struct) && 24225 | (static_cast<std::size_t>(ctrl_struct) < (details::cntrl_struct_list_size + 1)) 24226 | ) 24227 | { 24228 | const des_itr_t itr = disabled_ctrl_set_.find(details::cntrl_struct_list[ctrl_struct - 1]); 24229 | 24230 | if (disabled_ctrl_set_.end() != itr) 24231 | { 24232 | disabled_ctrl_set_.erase(itr); 24233 | } 24234 | } 24235 | 24236 | return (*this); 24237 | } 24238 | 24239 | settings_store& enable_logic_operation(const settings_logic_opr logic) 24240 | { 24241 | if ( 24242 | (e_logic_unknown != logic) && 24243 | (static_cast<std::size_t>(logic) < (details::logic_ops_list_size + 1)) 24244 | ) 24245 | { 24246 | const des_itr_t itr = disabled_logic_set_.find(details::logic_ops_list[logic - 1]); 24247 | 24248 | if (disabled_logic_set_.end() != itr) 24249 | { 24250 | disabled_logic_set_.erase(itr); 24251 | } 24252 | } 24253 | 24254 | return (*this); 24255 | } 24256 | 24257 | settings_store& enable_arithmetic_operation(const settings_arithmetic_opr arithmetic) 24258 | { 24259 | if ( 24260 | (e_arith_unknown != arithmetic) && 24261 | (static_cast<std::size_t>(arithmetic) < (details::arithmetic_ops_list_size + 1)) 24262 | ) 24263 | { 24264 | const des_itr_t itr = disabled_arithmetic_set_.find(details::arithmetic_ops_list[arithmetic - 1]); 24265 | 24266 | if (disabled_arithmetic_set_.end() != itr) 24267 | { 24268 | disabled_arithmetic_set_.erase(itr); 24269 | } 24270 | } 24271 | 24272 | return (*this); 24273 | } 24274 | 24275 | settings_store& enable_assignment_operation(const settings_assignment_opr assignment) 24276 | { 24277 | if ( 24278 | (e_assign_unknown != assignment) && 24279 | (static_cast<std::size_t>(assignment) < (details::assignment_ops_list_size + 1)) 24280 | ) 24281 | { 24282 | const des_itr_t itr = disabled_assignment_set_.find(details::assignment_ops_list[assignment - 1]); 24283 | 24284 | if (disabled_assignment_set_.end() != itr) 24285 | { 24286 | disabled_assignment_set_.erase(itr); 24287 | } 24288 | } 24289 | 24290 | return (*this); 24291 | } 24292 | 24293 | settings_store& enable_inequality_operation(const settings_inequality_opr inequality) 24294 | { 24295 | if ( 24296 | (e_ineq_unknown != inequality) && 24297 | (static_cast<std::size_t>(inequality) < (details::inequality_ops_list_size + 1)) 24298 | ) 24299 | { 24300 | const des_itr_t itr = disabled_inequality_set_.find(details::inequality_ops_list[inequality - 1]); 24301 | 24302 | if (disabled_inequality_set_.end() != itr) 24303 | { 24304 | disabled_inequality_set_.erase(itr); 24305 | } 24306 | } 24307 | 24308 | return (*this); 24309 | } 24310 | 24311 | void set_max_stack_depth(const std::size_t max_stack_depth) 24312 | { 24313 | max_stack_depth_ = max_stack_depth; 24314 | } 24315 | 24316 | void set_max_node_depth(const std::size_t max_node_depth) 24317 | { 24318 | max_node_depth_ = max_node_depth; 24319 | } 24320 | 24321 | void set_max_local_vector_size(const std::size_t max_local_vector_size) 24322 | { 24323 | max_local_vector_size_ = max_local_vector_size; 24324 | } 24325 | 24326 | void set_max_total_local_symbol_size_bytes(const std::size_t max_total_lcl_symb_size) 24327 | { 24328 | max_total_local_symbol_size_bytes_ = max_total_lcl_symb_size; 24329 | } 24330 | 24331 | std::size_t max_stack_depth() const 24332 | { 24333 | return max_stack_depth_; 24334 | } 24335 | 24336 | std::size_t max_node_depth() const 24337 | { 24338 | return max_node_depth_; 24339 | } 24340 | 24341 | std::size_t max_local_vector_size() const 24342 | { 24343 | return max_local_vector_size_; 24344 | } 24345 | 24346 | std::size_t max_total_local_symbol_size_bytes() const 24347 | { 24348 | return max_total_local_symbol_size_bytes_; 24349 | } 24350 | 24351 | private: 24352 | 24353 | void load_compile_options(const std::size_t compile_options) 24354 | { 24355 | enable_replacer_ = (compile_options & e_replacer ) == e_replacer; 24356 | enable_joiner_ = (compile_options & e_joiner ) == e_joiner; 24357 | enable_numeric_check_ = (compile_options & e_numeric_check ) == e_numeric_check; 24358 | enable_bracket_check_ = (compile_options & e_bracket_check ) == e_bracket_check; 24359 | enable_sequence_check_ = (compile_options & e_sequence_check ) == e_sequence_check; 24360 | enable_commutative_check_ = (compile_options & e_commutative_check ) == e_commutative_check; 24361 | enable_strength_reduction_ = (compile_options & e_strength_reduction ) == e_strength_reduction; 24362 | enable_collect_vars_ = (compile_options & e_collect_vars ) == e_collect_vars; 24363 | enable_collect_funcs_ = (compile_options & e_collect_funcs ) == e_collect_funcs; 24364 | enable_collect_assings_ = (compile_options & e_collect_assings ) == e_collect_assings; 24365 | disable_vardef_ = (compile_options & e_disable_vardef ) == e_disable_vardef; 24366 | disable_rsrvd_sym_usr_ = (compile_options & e_disable_usr_on_rsrvd) == e_disable_usr_on_rsrvd; 24367 | disable_zero_return_ = (compile_options & e_disable_zero_return ) == e_disable_zero_return; 24368 | } 24369 | 24370 | std::string assign_opr_to_string(details::operator_type opr) const 24371 | { 24372 | switch (opr) 24373 | { 24374 | case details::e_assign : return ":=" 24375 | case details::e_addass : return "+=" 24376 | case details::e_subass : return "-=" 24377 | case details::e_mulass : return "*=" 24378 | case details::e_divass : return "/=" 24379 | case details::e_modass : return "%=" 24380 | default : return "" ; 24381 | } 24382 | } 24383 | 24384 | std::string arith_opr_to_string(details::operator_type opr) const 24385 | { 24386 | switch (opr) 24387 | { 24388 | case details::e_add : return "+" 24389 | case details::e_sub : return "-" 24390 | case details::e_mul : return "*" 24391 | case details::e_div : return "/" 24392 | case details::e_mod : return "%" 24393 | case details::e_pow : return "^" 24394 | default : return "" ; 24395 | } 24396 | } 24397 | 24398 | std::string inequality_opr_to_string(details::operator_type opr) const 24399 | { 24400 | switch (opr) 24401 | { 24402 | case details::e_lt : return "<" ; 24403 | case details::e_lte : return "<=" 24404 | case details::e_eq : return "==" 24405 | case details::e_equal : return "=" ; 24406 | case details::e_ne : return "!=" 24407 | case details::e_nequal: return "<>" 24408 | case details::e_gte : return ">=" 24409 | case details::e_gt : return ">" ; 24410 | default : return "" ; 24411 | } 24412 | } 24413 | 24414 | std::string logic_opr_to_string(details::operator_type opr) const 24415 | { 24416 | switch (opr) 24417 | { 24418 | case details::e_and : return "and" ; 24419 | case details::e_or : return "or" ; 24420 | case details::e_xor : return "xor" ; 24421 | case details::e_nand : return "nand" 24422 | case details::e_nor : return "nor" ; 24423 | case details::e_xnor : return "xnor" 24424 | case details::e_notl : return "not" ; 24425 | default : return "" ; 24426 | } 24427 | } 24428 | 24429 | bool enable_replacer_; 24430 | bool enable_joiner_; 24431 | bool enable_numeric_check_; 24432 | bool enable_bracket_check_; 24433 | bool enable_sequence_check_; 24434 | bool enable_commutative_check_; 24435 | bool enable_strength_reduction_; 24436 | bool enable_collect_vars_; 24437 | bool enable_collect_funcs_; 24438 | bool enable_collect_assings_; 24439 | bool disable_vardef_; 24440 | bool disable_rsrvd_sym_usr_; 24441 | bool disable_zero_return_; 24442 | 24443 | disabled_entity_set_t disabled_func_set_ ; 24444 | disabled_entity_set_t disabled_ctrl_set_ ; 24445 | disabled_entity_set_t disabled_logic_set_; 24446 | disabled_entity_set_t disabled_arithmetic_set_; 24447 | disabled_entity_set_t disabled_assignment_set_; 24448 | disabled_entity_set_t disabled_inequality_set_; 24449 | 24450 | std::size_t max_stack_depth_; 24451 | std::size_t max_node_depth_; 24452 | std::size_t max_total_local_symbol_size_bytes_; 24453 | std::size_t max_local_vector_size_; 24454 | 24455 | friend class parser<T>; 24456 | }; 24457 | 24458 | typedef settings_store settings_t; 24459 | 24460 | explicit parser(const settings_t& settings = settings_t()) 24461 | : settings_(settings) 24462 | , resolve_unknown_symbol_(false) 24463 | , results_context_(0) 24464 | , unknown_symbol_resolver_(reinterpret_cast<unknown_symbol_resolver*>(0)) 24465 | #ifdef _MSC_VER 24466 | #pragma warning(push) 24467 | #pragma warning (disable:4355) 24468 | #endif 24469 | , sem_(*this) 24470 | #ifdef _MSC_VER 24471 | #pragma warning(pop) 24472 | #endif 24473 | , operator_joiner_2_(2) 24474 | , operator_joiner_3_(3) 24475 | , loop_runtime_check_(0) 24476 | , vector_access_runtime_check_(0) 24477 | , compilation_check_ptr_(0) 24478 | , assert_check_(0) 24479 | { 24480 | init_precompilation(); 24481 | 24482 | load_operations_map (base_ops_map_ ); 24483 | load_unary_operations_map (unary_op_map_ ); 24484 | load_binary_operations_map (binary_op_map_ ); 24485 | load_inv_binary_operations_map(inv_binary_op_map_); 24486 | load_sf3_map (sf3_map_ ); 24487 | load_sf4_map (sf4_map_ ); 24488 | 24489 | expression_generator_.init_synthesize_map(); 24490 | expression_generator_.set_parser(*this); 24491 | expression_generator_.set_uom (unary_op_map_ ); 24492 | expression_generator_.set_bom (binary_op_map_ ); 24493 | expression_generator_.set_ibom(inv_binary_op_map_); 24494 | expression_generator_.set_sf3m(sf3_map_ ); 24495 | expression_generator_.set_sf4m(sf4_map_ ); 24496 | expression_generator_.set_strength_reduction_state(settings_.strength_reduction_enabled()); 24497 | } 24498 | 24499 | ~parser() 24500 | {} 24501 | 24502 | inline void init_precompilation() 24503 | { 24504 | dec_.collect_variables() = 24505 | settings_.collect_variables_enabled(); 24506 | 24507 | dec_.collect_functions() = 24508 | settings_.collect_functions_enabled(); 24509 | 24510 | dec_.collect_assignments() = 24511 | settings_.collect_assignments_enabled(); 24512 | 24513 | if (settings_.replacer_enabled()) 24514 | { 24515 | symbol_replacer_.clear(); 24516 | symbol_replacer_.add_replace("true" , "1", lexer::token::e_number); 24517 | symbol_replacer_.add_replace("false", "0", lexer::token::e_number); 24518 | helper_assembly_.token_modifier_list.clear(); 24519 | helper_assembly_.register_modifier(&symbol_replacer_); 24520 | } 24521 | 24522 | if (settings_.commutative_check_enabled()) 24523 | { 24524 | for (std::size_t i = 0; i < details::reserved_words_size; ++i) 24525 | { 24526 | commutative_inserter_.ignore_symbol(details::reserved_words[i]); 24527 | } 24528 | 24529 | helper_assembly_.token_inserter_list.clear(); 24530 | helper_assembly_.register_inserter(&commutative_inserter_); 24531 | } 24532 | 24533 | if (settings_.joiner_enabled()) 24534 | { 24535 | helper_assembly_.token_joiner_list.clear(); 24536 | helper_assembly_.register_joiner(&operator_joiner_2_); 24537 | helper_assembly_.register_joiner(&operator_joiner_3_); 24538 | } 24539 | 24540 | if ( 24541 | settings_.numeric_check_enabled () || 24542 | settings_.bracket_check_enabled () || 24543 | settings_.sequence_check_enabled() 24544 | ) 24545 | { 24546 | helper_assembly_.token_scanner_list.clear(); 24547 | 24548 | if (settings_.numeric_check_enabled()) 24549 | { 24550 | helper_assembly_.register_scanner(&numeric_checker_); 24551 | } 24552 | 24553 | if (settings_.bracket_check_enabled()) 24554 | { 24555 | helper_assembly_.register_scanner(&bracket_checker_); 24556 | } 24557 | 24558 | if (settings_.sequence_check_enabled()) 24559 | { 24560 | helper_assembly_.register_scanner(&sequence_validator_ ); 24561 | helper_assembly_.register_scanner(&sequence_validator_3tkns_); 24562 | } 24563 | } 24564 | } 24565 | 24566 | inline bool compile(const std::string& expression_string, expression<T>& expr) 24567 | { 24568 | state_ .reset(); 24569 | error_list_ .clear(); 24570 | brkcnt_list_ .clear(); 24571 | synthesis_error_ .clear(); 24572 | immutable_memory_map_.reset(); 24573 | immutable_symtok_map_.clear(); 24574 | current_state_stack_ .clear(); 24575 | assert_ids_ .clear(); 24576 | sem_ .cleanup(); 24577 | 24578 | return_cleanup(); 24579 | 24580 | if (!valid_settings()) 24581 | { 24582 | return false; 24583 | } 24584 | 24585 | expression_generator_.set_allocator(node_allocator_); 24586 | 24587 | if (expression_string.empty()) 24588 | { 24589 | set_error(make_error( 24590 | parser_error::e_syntax, 24591 | "ERR001 - Empty expression!", 24592 | exprtk_error_location)); 24593 | 24594 | return false; 24595 | } 24596 | 24597 | if (!init(expression_string)) 24598 | { 24599 | process_lexer_errors(); 24600 | return false; 24601 | } 24602 | 24603 | if (lexer().empty()) 24604 | { 24605 | set_error(make_error( 24606 | parser_error::e_syntax, 24607 | "ERR002 - Empty expression!", 24608 | exprtk_error_location)); 24609 | 24610 | return false; 24611 | } 24612 | 24613 | if (halt_compilation_check()) 24614 | { 24615 | exprtk_debug(("halt_compilation_check() - compile checkpoint 0\n")); 24616 | sem_.cleanup(); 24617 | return false; 24618 | } 24619 | 24620 | if (!run_assemblies()) 24621 | { 24622 | sem_.cleanup(); 24623 | return false; 24624 | } 24625 | 24626 | if (halt_compilation_check()) 24627 | { 24628 | exprtk_debug(("halt_compilation_check() - compile checkpoint 1\n")); 24629 | sem_.cleanup(); 24630 | return false; 24631 | } 24632 | 24633 | symtab_store_.symtab_list_ = expr.get_symbol_table_list(); 24634 | dec_.clear(); 24635 | 24636 | lexer().begin(); 24637 | 24638 | next_token(); 24639 | 24640 | expression_node_ptr e = parse_corpus(); 24641 | 24642 | if ((0 != e) && (token_t::e_eof == current_token().type)) 24643 | { 24644 | bool* retinvk_ptr = 0; 24645 | 24646 | if (state_.return_stmt_present) 24647 | { 24648 | dec_.return_present_ = true; 24649 | 24650 | e = expression_generator_ 24651 | .return_envelope(e, results_context_, retinvk_ptr); 24652 | } 24653 | 24654 | expr.set_expression(e); 24655 | expr.set_retinvk(retinvk_ptr); 24656 | 24657 | register_local_vars(expr); 24658 | register_return_results(expr); 24659 | 24660 | return !(!expr); 24661 | } 24662 | else 24663 | { 24664 | if (error_list_.empty()) 24665 | { 24666 | set_error(make_error( 24667 | parser_error::e_syntax, 24668 | current_token(), 24669 | "ERR003 - Invalid expression encountered", 24670 | exprtk_error_location)); 24671 | } 24672 | 24673 | if ((0 != e) && branch_deletable(e)) 24674 | { 24675 | destroy_node(e); 24676 | } 24677 | 24678 | dec_.clear (); 24679 | sem_.cleanup (); 24680 | return_cleanup(); 24681 | 24682 | return false; 24683 | } 24684 | } 24685 | 24686 | inline expression_t compile(const std::string& expression_string, symbol_table_t& symtab) 24687 | { 24688 | expression_t expression; 24689 | expression.register_symbol_table(symtab); 24690 | compile(expression_string,expression); 24691 | return expression; 24692 | } 24693 | 24694 | void process_lexer_errors() 24695 | { 24696 | for (std::size_t i = 0; i < lexer().size(); ++i) 24697 | { 24698 | if (lexer()[i].is_error()) 24699 | { 24700 | std::string diagnostic = "ERR004 - " 24701 | 24702 | switch (lexer()[i].type) 24703 | { 24704 | case lexer::token::e_error : diagnostic += "General token error" 24705 | break; 24706 | 24707 | case lexer::token::e_err_symbol : diagnostic += "Symbol error" 24708 | break; 24709 | 24710 | case lexer::token::e_err_number : diagnostic += "Invalid numeric token" 24711 | break; 24712 | 24713 | case lexer::token::e_err_string : diagnostic += "Invalid string token" 24714 | break; 24715 | 24716 | case lexer::token::e_err_sfunc : diagnostic += "Invalid special function token" 24717 | break; 24718 | 24719 | default : diagnostic += "Unknown compiler error" 24720 | } 24721 | 24722 | set_error(make_error( 24723 | parser_error::e_lexer, 24724 | lexer()[i], 24725 | diagnostic + ": " + lexer()[i].value, 24726 | exprtk_error_location)); 24727 | } 24728 | } 24729 | } 24730 | 24731 | inline bool run_assemblies() 24732 | { 24733 | if (settings_.commutative_check_enabled()) 24734 | { 24735 | helper_assembly_.run_inserters(lexer()); 24736 | } 24737 | 24738 | if (settings_.joiner_enabled()) 24739 | { 24740 | helper_assembly_.run_joiners(lexer()); 24741 | } 24742 | 24743 | if (settings_.replacer_enabled()) 24744 | { 24745 | helper_assembly_.run_modifiers(lexer()); 24746 | } 24747 | 24748 | if ( 24749 | settings_.numeric_check_enabled () || 24750 | settings_.bracket_check_enabled () || 24751 | settings_.sequence_check_enabled() 24752 | ) 24753 | { 24754 | if (!helper_assembly_.run_scanners(lexer())) 24755 | { 24756 | if (helper_assembly_.error_token_scanner) 24757 | { 24758 | lexer::helper::bracket_checker* bracket_checker_ptr = 0; 24759 | lexer::helper::numeric_checker<T>* numeric_checker_ptr = 0; 24760 | lexer::helper::sequence_validator* sequence_validator_ptr = 0; 24761 | lexer::helper::sequence_validator_3tokens* sequence_validator3_ptr = 0; 24762 | 24763 | if (0 != (bracket_checker_ptr = dynamic_cast<lexer::helper::bracket_checker*>(helper_assembly_.error_token_scanner))) 24764 | { 24765 | set_error(make_error( 24766 | parser_error::e_token, 24767 | bracket_checker_ptr->error_token(), 24768 | "ERR005 - Mismatched brackets: '" + bracket_checker_ptr->error_token().value + "'", 24769 | exprtk_error_location)); 24770 | } 24771 | else if (0 != (numeric_checker_ptr = dynamic_cast<lexer::helper::numeric_checker<T>*>(helper_assembly_.error_token_scanner))) 24772 | { 24773 | for (std::size_t i = 0; i < numeric_checker_ptr->error_count(); ++i) 24774 | { 24775 | lexer::token error_token = lexer()[numeric_checker_ptr->error_index(i)]; 24776 | 24777 | set_error(make_error( 24778 | parser_error::e_token, 24779 | error_token, 24780 | "ERR006 - Invalid numeric token: '" + error_token.value + "'", 24781 | exprtk_error_location)); 24782 | } 24783 | 24784 | if (numeric_checker_ptr->error_count()) 24785 | { 24786 | numeric_checker_ptr->clear_errors(); 24787 | } 24788 | } 24789 | else if (0 != (sequence_validator_ptr = dynamic_cast<lexer::helper::sequence_validator*>(helper_assembly_.error_token_scanner))) 24790 | { 24791 | for (std::size_t i = 0; i < sequence_validator_ptr->error_count(); ++i) 24792 | { 24793 | std::pair<lexer::token,lexer::token> error_token = sequence_validator_ptr->error(i); 24794 | 24795 | set_error(make_error( 24796 | parser_error::e_token, 24797 | error_token.first, 24798 | "ERR007 - Invalid token sequence: '" + 24799 | error_token.first.value + "' and '" + 24800 | error_token.second.value + "'", 24801 | exprtk_error_location)); 24802 | } 24803 | 24804 | if (sequence_validator_ptr->error_count()) 24805 | { 24806 | sequence_validator_ptr->clear_errors(); 24807 | } 24808 | } 24809 | else if (0 != (sequence_validator3_ptr = dynamic_cast<lexer::helper::sequence_validator_3tokens*>(helper_assembly_.error_token_scanner))) 24810 | { 24811 | for (std::size_t i = 0; i < sequence_validator3_ptr->error_count(); ++i) 24812 | { 24813 | std::pair<lexer::token,lexer::token> error_token = sequence_validator3_ptr->error(i); 24814 | 24815 | set_error(make_error( 24816 | parser_error::e_token, 24817 | error_token.first, 24818 | "ERR008 - Invalid token sequence: '" + 24819 | error_token.first.value + "' and '" + 24820 | error_token.second.value + "'", 24821 | exprtk_error_location)); 24822 | } 24823 | 24824 | if (sequence_validator3_ptr->error_count()) 24825 | { 24826 | sequence_validator3_ptr->clear_errors(); 24827 | } 24828 | } 24829 | } 24830 | 24831 | return false; 24832 | } 24833 | } 24834 | 24835 | return true; 24836 | } 24837 | 24838 | inline settings_store& settings() 24839 | { 24840 | return settings_; 24841 | } 24842 | 24843 | inline parser_error::type get_error(const std::size_t& index) const 24844 | { 24845 | if (index < error_list_.size()) 24846 | { 24847 | return error_list_[index]; 24848 | } 24849 | 24850 | throw std::invalid_argument("parser::get_error() - Invalid error index specified"); 24851 | } 24852 | 24853 | inline std::string error() const 24854 | { 24855 | if (!error_list_.empty()) 24856 | { 24857 | return error_list_[0].diagnostic; 24858 | } 24859 | else 24860 | return std::string("No Error"); 24861 | } 24862 | 24863 | inline std::size_t error_count() const 24864 | { 24865 | return error_list_.size(); 24866 | } 24867 | 24868 | inline dependent_entity_collector& dec() 24869 | { 24870 | return dec_; 24871 | } 24872 | 24873 | inline std::size_t total_local_symbol_size_bytes() const 24874 | { 24875 | return sem_.total_local_symb_size_bytes(); 24876 | } 24877 | 24878 | inline bool replace_symbol(const std::string& old_symbol, const std::string& new_symbol) 24879 | { 24880 | if (!settings_.replacer_enabled()) 24881 | return false; 24882 | else if (details::is_reserved_word(old_symbol)) 24883 | return false; 24884 | else 24885 | return symbol_replacer_.add_replace(old_symbol,new_symbol,lexer::token::e_symbol); 24886 | } 24887 | 24888 | inline bool remove_replace_symbol(const std::string& symbol) 24889 | { 24890 | if (!settings_.replacer_enabled()) 24891 | return false; 24892 | else if (details::is_reserved_word(symbol)) 24893 | return false; 24894 | else 24895 | return symbol_replacer_.remove(symbol); 24896 | } 24897 | 24898 | inline void enable_unknown_symbol_resolver(unknown_symbol_resolver* usr = reinterpret_cast<unknown_symbol_resolver*>(0)) 24899 | { 24900 | resolve_unknown_symbol_ = true; 24901 | 24902 | if (usr) 24903 | unknown_symbol_resolver_ = usr; 24904 | else 24905 | unknown_symbol_resolver_ = &default_usr_; 24906 | } 24907 | 24908 | inline void enable_unknown_symbol_resolver(unknown_symbol_resolver& usr) 24909 | { 24910 | enable_unknown_symbol_resolver(&usr); 24911 | } 24912 | 24913 | inline void disable_unknown_symbol_resolver() 24914 | { 24915 | resolve_unknown_symbol_ = false; 24916 | unknown_symbol_resolver_ = &default_usr_; 24917 | } 24918 | 24919 | inline void register_loop_runtime_check(loop_runtime_check& lrtchk) 24920 | { 24921 | loop_runtime_check_ = &lrtchk; 24922 | } 24923 | 24924 | inline void register_vector_access_runtime_check(vector_access_runtime_check& vartchk) 24925 | { 24926 | vector_access_runtime_check_ = &vartchk; 24927 | } 24928 | 24929 | inline void register_compilation_timeout_check(compilation_check& compchk) 24930 | { 24931 | compilation_check_ptr_ = &compchk; 24932 | } 24933 | 24934 | inline void register_assert_check(assert_check& assrt_chck) 24935 | { 24936 | assert_check_ = &assrt_chck; 24937 | } 24938 | 24939 | inline void clear_loop_runtime_check() 24940 | { 24941 | loop_runtime_check_ = loop_runtime_check_ptr(0); 24942 | } 24943 | 24944 | inline void clear_vector_access_runtime_check() 24945 | { 24946 | vector_access_runtime_check_ = vector_access_runtime_check_ptr(0); 24947 | } 24948 | 24949 | inline void clear_compilation_timeout_check() 24950 | { 24951 | compilation_check_ptr_ = compilation_check_ptr(0); 24952 | } 24953 | 24954 | inline void clear_assert_check() 24955 | { 24956 | assert_check_ = assert_check_ptr(0); 24957 | } 24958 | 24959 | private: 24960 | 24961 | inline bool valid_base_operation(const std::string& symbol) const 24962 | { 24963 | const std::size_t length = symbol.size(); 24964 | 24965 | if ( 24966 | (length < 3) || // Shortest base op symbol length 24967 | (length > 9) // Longest base op symbol length 24968 | ) 24969 | return false; 24970 | else 24971 | return settings_.function_enabled(symbol) && 24972 | (base_ops_map_.end() != base_ops_map_.find(symbol)); 24973 | } 24974 | 24975 | inline bool valid_vararg_operation(const std::string& symbol) const 24976 | { 24977 | static const std::string s_sum = "sum" ; 24978 | static const std::string s_mul = "mul" ; 24979 | static const std::string s_avg = "avg" ; 24980 | static const std::string s_min = "min" ; 24981 | static const std::string s_max = "max" ; 24982 | static const std::string s_mand = "mand" 24983 | static const std::string s_mor = "mor" ; 24984 | static const std::string s_multi = "~" ; 24985 | static const std::string s_mswitch = "[*]" ; 24986 | 24987 | return 24988 | ( 24989 | details::imatch(symbol,s_sum ) || 24990 | details::imatch(symbol,s_mul ) || 24991 | details::imatch(symbol,s_avg ) || 24992 | details::imatch(symbol,s_min ) || 24993 | details::imatch(symbol,s_max ) || 24994 | details::imatch(symbol,s_mand ) || 24995 | details::imatch(symbol,s_mor ) || 24996 | details::imatch(symbol,s_multi ) || 24997 | details::imatch(symbol,s_mswitch) 24998 | ) && 24999 | settings_.function_enabled(symbol); 25000 | } 25001 | 25002 | bool is_invalid_logic_operation(const details::operator_type operation) const 25003 | { 25004 | return settings_.logic_disabled(operation); 25005 | } 25006 | 25007 | bool is_invalid_arithmetic_operation(const details::operator_type operation) const 25008 | { 25009 | return settings_.arithmetic_disabled(operation); 25010 | } 25011 | 25012 | bool is_invalid_assignment_operation(const details::operator_type operation) const 25013 | { 25014 | return settings_.assignment_disabled(operation); 25015 | } 25016 | 25017 | bool is_invalid_inequality_operation(const details::operator_type operation) const 25018 | { 25019 | return settings_.inequality_disabled(operation); 25020 | } 25021 | 25022 | #ifdef exprtk_enable_debugging 25023 | inline void next_token() 25024 | { 25025 | const std::string ct_str = current_token().value; 25026 | const std::size_t ct_pos = current_token().position; 25027 | parser_helper::next_token(); 25028 | const std::string depth(2 * state_.scope_depth,' '); 25029 | exprtk_debug(("%s" 25030 | "prev[%s | %04d] --> curr[%s | %04d] stack_level: %3d\n", 25031 | depth.c_str(), 25032 | ct_str.c_str(), 25033 | static_cast<unsigned int>(ct_pos), 25034 | current_token().value.c_str(), 25035 | static_cast<unsigned int>(current_token().position), 25036 | static_cast<unsigned int>(state_.stack_depth))); 25037 | } 25038 | #endif 25039 | 25040 | inline expression_node_ptr parse_corpus() 25041 | { 25042 | std::vector<expression_node_ptr> arg_list; 25043 | std::vector<bool> side_effect_list; 25044 | 25045 | scoped_vec_delete<expression_node_t> sdd((*this),arg_list); 25046 | 25047 | lexer::token begin_token; 25048 | lexer::token end_token; 25049 | 25050 | for ( ; ; ) 25051 | { 25052 | state_.side_effect_present = false; 25053 | 25054 | begin_token = current_token(); 25055 | 25056 | expression_node_ptr arg = parse_expression(); 25057 | 25058 | if (0 == arg) 25059 | { 25060 | if (error_list_.empty()) 25061 | { 25062 | set_error(make_error( 25063 | parser_error::e_syntax, 25064 | current_token(), 25065 | "ERR009 - Invalid expression encountered", 25066 | exprtk_error_location)); 25067 | } 25068 | 25069 | return error_node(); 25070 | } 25071 | else 25072 | { 25073 | arg_list.push_back(arg); 25074 | 25075 | side_effect_list.push_back(state_.side_effect_present); 25076 | 25077 | end_token = current_token(); 25078 | 25079 | const std::string sub_expr = construct_subexpr(begin_token, end_token); 25080 | 25081 | exprtk_debug(("parse_corpus(%02d) Subexpr: %s\n", 25082 | static_cast<int>(arg_list.size() - 1), 25083 | sub_expr.c_str())); 25084 | 25085 | exprtk_debug(("parse_corpus(%02d) - Side effect present: %s\n", 25086 | static_cast<int>(arg_list.size() - 1), 25087 | state_.side_effect_present ? "true" : "false")); 25088 | 25089 | exprtk_debug(("-------------------------------------------------\n")); 25090 | } 25091 | 25092 | if (token_is(token_t::e_eof,prsrhlpr_t::e_hold)) 25093 | { 25094 | if (lexer().finished()) 25095 | break; 25096 | else 25097 | next_token(); 25098 | } 25099 | else if ( 25100 | !settings_.commutative_check_enabled() && 25101 | ( 25102 | current_token().type == token_t::e_symbol || 25103 | current_token().type == token_t::e_number || 25104 | current_token().type == token_t::e_string || 25105 | token_is_bracket(prsrhlpr_t::e_hold) 25106 | ) 25107 | ) 25108 | { 25109 | set_error(make_error( 25110 | parser_error::e_syntax, 25111 | current_token(), 25112 | "ERR010 - Invalid syntax '" + current_token().value + "' possible missing operator or context", 25113 | exprtk_error_location)); 25114 | 25115 | return error_node(); 25116 | } 25117 | } 25118 | 25119 | if ( 25120 | !arg_list.empty() && 25121 | is_return_node(arg_list.back()) 25122 | ) 25123 | { 25124 | dec_.final_stmt_return_ = true; 25125 | } 25126 | 25127 | const expression_node_ptr result = simplify(arg_list,side_effect_list); 25128 | 25129 | sdd.delete_ptr = (0 == result); 25130 | 25131 | return result; 25132 | } 25133 | 25134 | std::string construct_subexpr(lexer::token& begin_token, 25135 | lexer::token& end_token, 25136 | const bool cleanup_whitespace = true) 25137 | { 25138 | std::string result = lexer().substr(begin_token.position,end_token.position); 25139 | if (cleanup_whitespace) 25140 | { 25141 | for (std::size_t i = 0; i < result.size(); ++i) 25142 | { 25143 | if (details::is_whitespace(result[i])) result[i] = ' '; 25144 | } 25145 | } 25146 | 25147 | return result; 25148 | } 25149 | 25150 | static const precedence_level default_precedence = e_level00; 25151 | 25152 | struct state_t 25153 | { 25154 | inline void set(const precedence_level& l, 25155 | const precedence_level& r, 25156 | const details::operator_type& o, 25157 | const token_t tkn = token_t()) 25158 | { 25159 | left = l; 25160 | right = r; 25161 | operation = o; 25162 | token = tkn; 25163 | } 25164 | 25165 | inline void reset() 25166 | { 25167 | left = e_level00; 25168 | right = e_level00; 25169 | operation = details::e_default; 25170 | } 25171 | 25172 | precedence_level left; 25173 | precedence_level right; 25174 | details::operator_type operation; 25175 | token_t token; 25176 | }; 25177 | 25178 | inline void push_current_state(const state_t current_state) 25179 | { 25180 | current_state_stack_.push_back(current_state); 25181 | } 25182 | 25183 | inline void pop_current_state() 25184 | { 25185 | if (!current_state_stack_.empty()) 25186 | { 25187 | current_state_stack_.pop_back(); 25188 | } 25189 | } 25190 | 25191 | inline state_t current_state() const 25192 | { 25193 | return (!current_state_stack_.empty()) ? 25194 | current_state_stack_.back() : 25195 | state_t(); 25196 | } 25197 | 25198 | inline bool halt_compilation_check() 25199 | { 25200 | compilation_check::compilation_context context; 25201 | 25202 | if (compilation_check_ptr_ && !compilation_check_ptr_->continue_compilation(context)) 25203 | { 25204 | const std::string error_message = 25205 | !context.error_message.empty() ? " Details: " + context.error_message : "" 25206 | 25207 | set_error(make_error( 25208 | parser_error::e_parser, 25209 | token_t(), 25210 | "ERR011 - Internal compilation check failed." + error_message, 25211 | exprtk_error_location)); 25212 | 25213 | return true; 25214 | } 25215 | 25216 | return false; 25217 | } 25218 | 25219 | inline expression_node_ptr parse_expression(precedence_level precedence = e_level00) 25220 | { 25221 | if (halt_compilation_check()) 25222 | { 25223 | exprtk_debug(("halt_compilation_check() - parse_expression checkpoint 2\n")); 25224 | return error_node(); 25225 | } 25226 | 25227 | stack_limit_handler slh(*this); 25228 | 25229 | if (!slh) 25230 | { 25231 | return error_node(); 25232 | } 25233 | 25234 | expression_node_ptr expression = parse_branch(precedence); 25235 | 25236 | if (0 == expression) 25237 | { 25238 | return error_node(); 25239 | } 25240 | 25241 | if (token_is(token_t::e_eof,prsrhlpr_t::e_hold)) 25242 | { 25243 | return expression; 25244 | } 25245 | 25246 | bool break_loop = false; 25247 | 25248 | state_t current_state; 25249 | 25250 | for ( ; ; ) 25251 | { 25252 | current_state.reset(); 25253 | 25254 | switch (current_token().type) 25255 | { 25256 | case token_t::e_assign : current_state.set(e_level00, e_level00, details::e_assign, current_token()); break; 25257 | case token_t::e_addass : current_state.set(e_level00, e_level00, details::e_addass, current_token()); break; 25258 | case token_t::e_subass : current_state.set(e_level00, e_level00, details::e_subass, current_token()); break; 25259 | case token_t::e_mulass : current_state.set(e_level00, e_level00, details::e_mulass, current_token()); break; 25260 | case token_t::e_divass : current_state.set(e_level00, e_level00, details::e_divass, current_token()); break; 25261 | case token_t::e_modass : current_state.set(e_level00, e_level00, details::e_modass, current_token()); break; 25262 | case token_t::e_swap : current_state.set(e_level00, e_level00, details::e_swap , current_token()); break; 25263 | case token_t::e_lt : current_state.set(e_level05, e_level06, details::e_lt , current_token()); break; 25264 | case token_t::e_lte : current_state.set(e_level05, e_level06, details::e_lte , current_token()); break; 25265 | case token_t::e_eq : current_state.set(e_level05, e_level06, details::e_eq , current_token()); break; 25266 | case token_t::e_ne : current_state.set(e_level05, e_level06, details::e_ne , current_token()); break; 25267 | case token_t::e_gte : current_state.set(e_level05, e_level06, details::e_gte , current_token()); break; 25268 | case token_t::e_gt : current_state.set(e_level05, e_level06, details::e_gt , current_token()); break; 25269 | case token_t::e_add : current_state.set(e_level07, e_level08, details::e_add , current_token()); break; 25270 | case token_t::e_sub : current_state.set(e_level07, e_level08, details::e_sub , current_token()); break; 25271 | case token_t::e_div : current_state.set(e_level10, e_level11, details::e_div , current_token()); break; 25272 | case token_t::e_mul : current_state.set(e_level10, e_level11, details::e_mul , current_token()); break; 25273 | case token_t::e_mod : current_state.set(e_level10, e_level11, details::e_mod , current_token()); break; 25274 | case token_t::e_pow : current_state.set(e_level12, e_level12, details::e_pow , current_token()); break; 25275 | default : 25276 | if (token_t::e_symbol == current_token().type) 25277 | { 25278 | static const std::string s_and = "and" ; 25279 | static const std::string s_nand = "nand" ; 25280 | static const std::string s_or = "or" ; 25281 | static const std::string s_nor = "nor" ; 25282 | static const std::string s_xor = "xor" ; 25283 | static const std::string s_xnor = "xnor" ; 25284 | static const std::string s_in = "in" ; 25285 | static const std::string s_like = "like" ; 25286 | static const std::string s_ilike = "ilike" 25287 | static const std::string s_and1 = "&" ; 25288 | static const std::string s_or1 = "|" ; 25289 | static const std::string s_not = "not" ; 25290 | 25291 | if (details::imatch(current_token().value,s_and)) 25292 | { 25293 | current_state.set(e_level03, e_level04, details::e_and, current_token()); 25294 | break; 25295 | } 25296 | else if (details::imatch(current_token().value,s_and1)) 25297 | { 25298 | #ifndef exprtk_disable_sc_andor 25299 | current_state.set(e_level03, e_level04, details::e_scand, current_token()); 25300 | #else 25301 | current_state.set(e_level03, e_level04, details::e_and, current_token()); 25302 | #endif 25303 | break; 25304 | } 25305 | else if (details::imatch(current_token().value,s_nand)) 25306 | { 25307 | current_state.set(e_level03, e_level04, details::e_nand, current_token()); 25308 | break; 25309 | } 25310 | else if (details::imatch(current_token().value,s_or)) 25311 | { 25312 | current_state.set(e_level01, e_level02, details::e_or, current_token()); 25313 | break; 25314 | } 25315 | else if (details::imatch(current_token().value,s_or1)) 25316 | { 25317 | #ifndef exprtk_disable_sc_andor 25318 | current_state.set(e_level01, e_level02, details::e_scor, current_token()); 25319 | #else 25320 | current_state.set(e_level01, e_level02, details::e_or, current_token()); 25321 | #endif 25322 | break; 25323 | } 25324 | else if (details::imatch(current_token().value,s_nor)) 25325 | { 25326 | current_state.set(e_level01, e_level02, details::e_nor, current_token()); 25327 | break; 25328 | } 25329 | else if (details::imatch(current_token().value,s_xor)) 25330 | { 25331 | current_state.set(e_level01, e_level02, details::e_xor, current_token()); 25332 | break; 25333 | } 25334 | else if (details::imatch(current_token().value,s_xnor)) 25335 | { 25336 | current_state.set(e_level01, e_level02, details::e_xnor, current_token()); 25337 | break; 25338 | } 25339 | else if (details::imatch(current_token().value,s_in)) 25340 | { 25341 | current_state.set(e_level04, e_level04, details::e_in, current_token()); 25342 | break; 25343 | } 25344 | else if (details::imatch(current_token().value,s_like)) 25345 | { 25346 | current_state.set(e_level04, e_level04, details::e_like, current_token()); 25347 | break; 25348 | } 25349 | else if (details::imatch(current_token().value,s_ilike)) 25350 | { 25351 | current_state.set(e_level04, e_level04, details::e_ilike, current_token()); 25352 | break; 25353 | } 25354 | else if (details::imatch(current_token().value,s_not)) 25355 | { 25356 | break; 25357 | } 25358 | } 25359 | 25360 | break_loop = true; 25361 | } 25362 | 25363 | if (break_loop) 25364 | { 25365 | parse_pending_string_rangesize(expression); 25366 | break; 25367 | } 25368 | else if (current_state.left < precedence) 25369 | break; 25370 | 25371 | const lexer::token prev_token = current_token(); 25372 | 25373 | next_token(); 25374 | 25375 | expression_node_ptr right_branch = error_node(); 25376 | expression_node_ptr new_expression = error_node(); 25377 | 25378 | if (is_invalid_logic_operation(current_state.operation)) 25379 | { 25380 | free_node(node_allocator_, expression); 25381 | 25382 | set_error(make_error( 25383 | parser_error::e_syntax, 25384 | prev_token, 25385 | "ERR012 - Invalid or disabled logic operation '" + details::to_str(current_state.operation) + "'", 25386 | exprtk_error_location)); 25387 | 25388 | return error_node(); 25389 | } 25390 | else if (is_invalid_arithmetic_operation(current_state.operation)) 25391 | { 25392 | free_node(node_allocator_, expression); 25393 | 25394 | set_error(make_error( 25395 | parser_error::e_syntax, 25396 | prev_token, 25397 | "ERR013 - Invalid or disabled arithmetic operation '" + details::to_str(current_state.operation) + "'", 25398 | exprtk_error_location)); 25399 | 25400 | return error_node(); 25401 | } 25402 | else if (is_invalid_inequality_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 | "ERR014 - Invalid inequality operation '" + details::to_str(current_state.operation) + "'", 25410 | exprtk_error_location)); 25411 | 25412 | return error_node(); 25413 | } 25414 | else if (is_invalid_assignment_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 | "ERR015 - Invalid or disabled assignment operation '" + details::to_str(current_state.operation) + "'", 25422 | exprtk_error_location)); 25423 | 25424 | return error_node(); 25425 | } 25426 | 25427 | if (0 != (right_branch = parse_expression(current_state.right))) 25428 | { 25429 | if ( 25430 | details::is_return_node(expression ) || 25431 | details::is_return_node(right_branch) 25432 | ) 25433 | { 25434 | free_node(node_allocator_, expression ); 25435 | free_node(node_allocator_, right_branch); 25436 | 25437 | set_error(make_error( 25438 | parser_error::e_syntax, 25439 | prev_token, 25440 | "ERR016 - Return statements cannot be part of sub-expressions", 25441 | exprtk_error_location)); 25442 | 25443 | return error_node(); 25444 | } 25445 | 25446 | push_current_state(current_state); 25447 | 25448 | new_expression = expression_generator_ 25449 | ( 25450 | current_state.operation, 25451 | expression, 25452 | right_branch 25453 | ); 25454 | 25455 | pop_current_state(); 25456 | } 25457 | 25458 | if (0 == new_expression) 25459 | { 25460 | if (error_list_.empty()) 25461 | { 25462 | set_error(make_error( 25463 | parser_error::e_syntax, 25464 | prev_token, 25465 | !synthesis_error_.empty() ? 25466 | synthesis_error_ : 25467 | "ERR017 - General parsing error at token: '" + prev_token.value + "'", 25468 | exprtk_error_location)); 25469 | } 25470 | 25471 | free_node(node_allocator_, expression ); 25472 | free_node(node_allocator_, right_branch); 25473 | 25474 | return error_node(); 25475 | } 25476 | else 25477 | { 25478 | if ( 25479 | token_is(token_t::e_ternary,prsrhlpr_t::e_hold) && 25480 | (e_level00 == precedence) 25481 | ) 25482 | { 25483 | expression = parse_ternary_conditional_statement(new_expression); 25484 | } 25485 | else 25486 | expression = new_expression; 25487 | 25488 | parse_pending_string_rangesize(expression); 25489 | } 25490 | } 25491 | 25492 | if ((0 != expression) && (expression->node_depth() > settings_.max_node_depth_)) 25493 | { 25494 | set_error(make_error( 25495 | parser_error::e_syntax, 25496 | current_token(), 25497 | "ERR018 - Expression depth of " + details::to_str(static_cast<int>(expression->node_depth())) + 25498 | " exceeds maximum allowed expression depth of " + details::to_str(static_cast<int>(settings_.max_node_depth_)), 25499 | exprtk_error_location)); 25500 | 25501 | free_node(node_allocator_, expression); 25502 | 25503 | return error_node(); 25504 | } 25505 | else if ( 25506 | !settings_.commutative_check_enabled() && 25507 | !details::is_logic_opr(current_token().value) && 25508 | (current_state.operation == details::e_default) && 25509 | ( 25510 | current_token().type == token_t::e_symbol || 25511 | current_token().type == token_t::e_number || 25512 | current_token().type == token_t::e_string 25513 | ) 25514 | ) 25515 | { 25516 | set_error(make_error( 25517 | parser_error::e_syntax, 25518 | current_token(), 25519 | "ERR019 - Invalid syntax '" + current_token().value + "' possible missing operator or context", 25520 | exprtk_error_location)); 25521 | 25522 | free_node(node_allocator_, expression); 25523 | 25524 | return error_node(); 25525 | } 25526 | 25527 | return expression; 25528 | } 25529 | 25530 | bool simplify_unary_negation_branch(expression_node_ptr& node) 25531 | { 25532 | { 25533 | typedef details::unary_branch_node<T,details::neg_op<T> > ubn_t; 25534 | ubn_t* n = dynamic_cast<ubn_t*>(node); 25535 | 25536 | if (n) 25537 | { 25538 | expression_node_ptr un_r = n->branch(0); 25539 | n->release(); 25540 | free_node(node_allocator_, node); 25541 | node = un_r; 25542 | 25543 | return true; 25544 | } 25545 | } 25546 | 25547 | { 25548 | typedef details::unary_variable_node<T,details::neg_op<T> > uvn_t; 25549 | 25550 | uvn_t* n = dynamic_cast<uvn_t*>(node); 25551 | 25552 | if (n) 25553 | { 25554 | const T& v = n->v(); 25555 | expression_node_ptr return_node = error_node(); 25556 | 25557 | if ( 25558 | (0 != (return_node = symtab_store_.get_variable(v))) || 25559 | (0 != (return_node = sem_ .get_variable(v))) 25560 | ) 25561 | { 25562 | free_node(node_allocator_, node); 25563 | node = return_node; 25564 | 25565 | return true; 25566 | } 25567 | else 25568 | { 25569 | set_error(make_error( 25570 | parser_error::e_syntax, 25571 | current_token(), 25572 | "ERR020 - Failed to find variable node in symbol table", 25573 | exprtk_error_location)); 25574 | 25575 | free_node(node_allocator_, node); 25576 | 25577 | return false; 25578 | } 25579 | } 25580 | } 25581 | 25582 | return false; 25583 | } 25584 | 25585 | static inline expression_node_ptr error_node() 25586 | { 25587 | return reinterpret_cast<expression_node_ptr>(0); 25588 | } 25589 | 25590 | struct scoped_expression_delete 25591 | { 25592 | scoped_expression_delete(parser<T>& pr, expression_node_ptr& expression) 25593 | : delete_ptr(true) 25594 | , parser_(pr) 25595 | , expression_(expression) 25596 | {} 25597 | 25598 | ~scoped_expression_delete() 25599 | { 25600 | if (delete_ptr) 25601 | { 25602 | free_node(parser_.node_allocator_, expression_); 25603 | } 25604 | } 25605 | 25606 | bool delete_ptr; 25607 | parser<T>& parser_; 25608 | expression_node_ptr& expression_; 25609 | 25610 | private: 25611 | 25612 | scoped_expression_delete(const scoped_expression_delete&) exprtk_delete; 25613 | scoped_expression_delete& operator=(const scoped_expression_delete&) exprtk_delete; 25614 | }; 25615 | 25616 | template <typename Type, std::size_t N> 25617 | struct scoped_delete 25618 | { 25619 | typedef Type* ptr_t; 25620 | 25621 | scoped_delete(parser<T>& pr, ptr_t& p) 25622 | : delete_ptr(true) 25623 | , parser_(pr) 25624 | , p_(&p) 25625 | {} 25626 | 25627 | scoped_delete(parser<T>& pr, ptr_t (&p)[N]) 25628 | : delete_ptr(true) 25629 | , parser_(pr) 25630 | , p_(&p[0]) 25631 | {} 25632 | 25633 | ~scoped_delete() 25634 | { 25635 | if (delete_ptr) 25636 | { 25637 | for (std::size_t i = 0; i < N; ++i) 25638 | { 25639 | free_node(parser_.node_allocator_, p_[i]); 25640 | } 25641 | } 25642 | } 25643 | 25644 | bool delete_ptr; 25645 | parser<T>& parser_; 25646 | ptr_t* p_; 25647 | 25648 | private: 25649 | 25650 | scoped_delete(const scoped_delete<Type,N>&) exprtk_delete; 25651 | scoped_delete<Type,N>& operator=(const scoped_delete<Type,N>&) exprtk_delete; 25652 | }; 25653 | 25654 | template <typename Type> 25655 | struct scoped_deq_delete 25656 | { 25657 | typedef Type* ptr_t; 25658 | 25659 | scoped_deq_delete(parser<T>& pr, std::deque<ptr_t>& deq) 25660 | : delete_ptr(true) 25661 | , parser_(pr) 25662 | , deq_(deq) 25663 | {} 25664 | 25665 | ~scoped_deq_delete() 25666 | { 25667 | if (delete_ptr && !deq_.empty()) 25668 | { 25669 | for (std::size_t i = 0; i < deq_.size(); ++i) 25670 | { 25671 | exprtk_debug(("~scoped_deq_delete() - deleting node: %p\n", reinterpret_cast<void*>(deq_[i]))); 25672 | free_node(parser_.node_allocator_,deq_[i]); 25673 | } 25674 | 25675 | deq_.clear(); 25676 | } 25677 | } 25678 | 25679 | bool delete_ptr; 25680 | parser<T>& parser_; 25681 | std::deque<ptr_t>& deq_; 25682 | 25683 | private: 25684 | 25685 | scoped_deq_delete(const scoped_deq_delete<Type>&) exprtk_delete; 25686 | scoped_deq_delete<Type>& operator=(const scoped_deq_delete<Type>&) exprtk_delete; 25687 | }; 25688 | 25689 | template <typename Type> 25690 | struct scoped_vec_delete 25691 | { 25692 | typedef Type* ptr_t; 25693 | 25694 | scoped_vec_delete(parser<T>& pr, std::vector<ptr_t>& vec) 25695 | : delete_ptr(true) 25696 | , parser_(pr) 25697 | , vec_(vec) 25698 | {} 25699 | 25700 | ~scoped_vec_delete() 25701 | { 25702 | if (delete_ptr && !vec_.empty()) 25703 | { 25704 | for (std::size_t i = 0; i < vec_.size(); ++i) 25705 | { 25706 | exprtk_debug(("~scoped_vec_delete() - deleting node: %p\n", reinterpret_cast<void*>(vec_[i]))); 25707 | free_node(parser_.node_allocator_,vec_[i]); 25708 | } 25709 | 25710 | vec_.clear(); 25711 | } 25712 | } 25713 | 25714 | ptr_t operator[](const std::size_t index) 25715 | { 25716 | return vec_[index]; 25717 | } 25718 | 25719 | bool delete_ptr; 25720 | parser<T>& parser_; 25721 | std::vector<ptr_t>& vec_; 25722 | 25723 | private: 25724 | 25725 | scoped_vec_delete(const scoped_vec_delete<Type>&) exprtk_delete; 25726 | scoped_vec_delete<Type>& operator=(const scoped_vec_delete<Type>&) exprtk_delete; 25727 | }; 25728 | 25729 | struct scoped_bool_negator 25730 | { 25731 | explicit scoped_bool_negator(bool& bb) 25732 | : b(bb) 25733 | { b = !b; } 25734 | 25735 | ~scoped_bool_negator() 25736 | { b = !b; } 25737 | 25738 | bool& b; 25739 | }; 25740 | 25741 | struct scoped_bool_or_restorer 25742 | { 25743 | explicit scoped_bool_or_restorer(bool& bb) 25744 | : b(bb) 25745 | , original_value_(bb) 25746 | {} 25747 | 25748 | ~scoped_bool_or_restorer() 25749 | { 25750 | b = b || original_value_; 25751 | } 25752 | 25753 | bool& b; 25754 | bool original_value_; 25755 | }; 25756 | 25757 | struct scoped_inc_dec 25758 | { 25759 | explicit scoped_inc_dec(std::size_t& v) 25760 | : v_(v) 25761 | { ++v_; } 25762 | 25763 | ~scoped_inc_dec() 25764 | { 25765 | assert(v_ > 0); 25766 | --v_; 25767 | } 25768 | 25769 | std::size_t& v_; 25770 | }; 25771 | 25772 | inline expression_node_ptr parse_function_invocation(ifunction<T>* function, const std::string& function_name) 25773 | { 25774 | expression_node_ptr func_node = reinterpret_cast<expression_node_ptr>(0); 25775 | 25776 | switch (function->param_count) 25777 | { 25778 | case 0 : func_node = parse_function_call_0 (function,function_name); break; 25779 | case 1 : func_node = parse_function_call< 1>(function,function_name); break; 25780 | case 2 : func_node = parse_function_call< 2>(function,function_name); break; 25781 | case 3 : func_node = parse_function_call< 3>(function,function_name); break; 25782 | case 4 : func_node = parse_function_call< 4>(function,function_name); break; 25783 | case 5 : func_node = parse_function_call< 5>(function,function_name); break; 25784 | case 6 : func_node = parse_function_call< 6>(function,function_name); break; 25785 | case 7 : func_node = parse_function_call< 7>(function,function_name); break; 25786 | case 8 : func_node = parse_function_call< 8>(function,function_name); break; 25787 | case 9 : func_node = parse_function_call< 9>(function,function_name); break; 25788 | case 10 : func_node = parse_function_call<10>(function,function_name); break; 25789 | case 11 : func_node = parse_function_call<11>(function,function_name); break; 25790 | case 12 : func_node = parse_function_call<12>(function,function_name); break; 25791 | case 13 : func_node = parse_function_call<13>(function,function_name); break; 25792 | case 14 : func_node = parse_function_call<14>(function,function_name); break; 25793 | case 15 : func_node = parse_function_call<15>(function,function_name); break; 25794 | case 16 : func_node = parse_function_call<16>(function,function_name); break; 25795 | case 17 : func_node = parse_function_call<17>(function,function_name); break; 25796 | case 18 : func_node = parse_function_call<18>(function,function_name); break; 25797 | case 19 : func_node = parse_function_call<19>(function,function_name); break; 25798 | case 20 : func_node = parse_function_call<20>(function,function_name); break; 25799 | default : { 25800 | set_error(make_error( 25801 | parser_error::e_syntax, 25802 | current_token(), 25803 | "ERR021 - Invalid number of parameters for function: '" + function_name + "'", 25804 | exprtk_error_location)); 25805 | 25806 | return error_node(); 25807 | } 25808 | } 25809 | 25810 | if (func_node) 25811 | return func_node; 25812 | else 25813 | { 25814 | set_error(make_error( 25815 | parser_error::e_syntax, 25816 | current_token(), 25817 | "ERR022 - Failed to generate call to function: '" + function_name + "'", 25818 | exprtk_error_location)); 25819 | 25820 | return error_node(); 25821 | } 25822 | } 25823 | 25824 | template <std::size_t NumberofParameters> 25825 | inline expression_node_ptr parse_function_call(ifunction<T>* function, const std::string& function_name) 25826 | { 25827 | #ifdef _MSC_VER 25828 | #pragma warning(push) 25829 | #pragma warning(disable: 4127) 25830 | #endif 25831 | if (0 == NumberofParameters) 25832 | { 25833 | set_error(make_error( 25834 | parser_error::e_syntax, 25835 | current_token(), 25836 | "ERR023 - Expecting ifunction '" + function_name + "' to have non-zero parameter count", 25837 | exprtk_error_location)); 25838 | 25839 | return error_node(); 25840 | } 25841 | #ifdef _MSC_VER 25842 | #pragma warning(pop) 25843 | #endif 25844 | 25845 | expression_node_ptr branch[NumberofParameters]; 25846 | expression_node_ptr result = error_node(); 25847 | 25848 | std::fill_n(branch, NumberofParameters, reinterpret_cast<expression_node_ptr>(0)); 25849 | 25850 | scoped_delete<expression_node_t,NumberofParameters> sd((*this),branch); 25851 | 25852 | next_token(); 25853 | 25854 | if (!token_is(token_t::e_lbracket)) 25855 | { 25856 | set_error(make_error( 25857 | parser_error::e_syntax, 25858 | current_token(), 25859 | "ERR024 - Expecting argument list for function: '" + function_name + "'", 25860 | exprtk_error_location)); 25861 | 25862 | return error_node(); 25863 | } 25864 | 25865 | for (int i = 0; i < static_cast<int>(NumberofParameters); ++i) 25866 | { 25867 | branch[i] = parse_expression(); 25868 | 25869 | if (0 == branch[i]) 25870 | { 25871 | set_error(make_error( 25872 | parser_error::e_syntax, 25873 | current_token(), 25874 | "ERR025 - Failed to parse argument " + details::to_str(i) + " for function: '" + function_name + "'", 25875 | exprtk_error_location)); 25876 | 25877 | return error_node(); 25878 | } 25879 | else if (i < static_cast<int>(NumberofParameters - 1)) 25880 | { 25881 | if (!token_is(token_t::e_comma)) 25882 | { 25883 | set_error(make_error( 25884 | parser_error::e_syntax, 25885 | current_token(), 25886 | "ERR026 - Invalid number of arguments for function: '" + function_name + "'", 25887 | exprtk_error_location)); 25888 | 25889 | return error_node(); 25890 | } 25891 | } 25892 | } 25893 | 25894 | if (!token_is(token_t::e_rbracket)) 25895 | { 25896 | set_error(make_error( 25897 | parser_error::e_syntax, 25898 | current_token(), 25899 | "ERR027 - Invalid number of arguments for function: '" + function_name + "'", 25900 | exprtk_error_location)); 25901 | 25902 | return error_node(); 25903 | } 25904 | else 25905 | result = expression_generator_.function(function,branch); 25906 | 25907 | sd.delete_ptr = (0 == result); 25908 | 25909 | return result; 25910 | } 25911 | 25912 | inline expression_node_ptr parse_function_call_0(ifunction<T>* function, const std::string& function_name) 25913 | { 25914 | expression_node_ptr result = expression_generator_.function(function); 25915 | 25916 | state_.side_effect_present = function->has_side_effects(); 25917 | 25918 | next_token(); 25919 | 25920 | if ( 25921 | token_is(token_t::e_lbracket) && 25922 | !token_is(token_t::e_rbracket) 25923 | ) 25924 | { 25925 | set_error(make_error( 25926 | parser_error::e_syntax, 25927 | current_token(), 25928 | "ERR028 - Expecting '()' to proceed call to function: '" + function_name + "'", 25929 | exprtk_error_location)); 25930 | 25931 | free_node(node_allocator_, result); 25932 | 25933 | return error_node(); 25934 | } 25935 | else 25936 | return result; 25937 | } 25938 | 25939 | template <std::size_t MaxNumberofParameters> 25940 | inline std::size_t parse_base_function_call(expression_node_ptr (¶m_list)[MaxNumberofParameters], const std::string& function_name = "") 25941 | { 25942 | std::fill_n(param_list, MaxNumberofParameters, reinterpret_cast<expression_node_ptr>(0)); 25943 | 25944 | scoped_delete<expression_node_t,MaxNumberofParameters> sd((*this),param_list); 25945 | 25946 | next_token(); 25947 | 25948 | if (!token_is(token_t::e_lbracket)) 25949 | { 25950 | set_error(make_error( 25951 | parser_error::e_syntax, 25952 | current_token(), 25953 | "ERR029 - Expected a '(' at start of function call to '" + function_name + 25954 | "', instead got: '" + current_token().value + "'", 25955 | exprtk_error_location)); 25956 | 25957 | return 0; 25958 | } 25959 | 25960 | if (token_is(token_t::e_rbracket, e_hold)) 25961 | { 25962 | set_error(make_error( 25963 | parser_error::e_syntax, 25964 | current_token(), 25965 | "ERR030 - Expected at least one input parameter for function call '" + function_name + "'", 25966 | exprtk_error_location)); 25967 | 25968 | return 0; 25969 | } 25970 | 25971 | std::size_t param_index = 0; 25972 | 25973 | for (; param_index < MaxNumberofParameters; ++param_index) 25974 | { 25975 | param_list[param_index] = parse_expression(); 25976 | 25977 | if (0 == param_list[param_index]) 25978 | return 0; 25979 | else if (token_is(token_t::e_rbracket)) 25980 | { 25981 | sd.delete_ptr = false; 25982 | break; 25983 | } 25984 | else if (token_is(token_t::e_comma)) 25985 | continue; 25986 | else 25987 | { 25988 | set_error(make_error( 25989 | parser_error::e_syntax, 25990 | current_token(), 25991 | "ERR031 - Expected a ',' between function input parameters, instead got: '" + current_token().value + "'", 25992 | exprtk_error_location)); 25993 | 25994 | return 0; 25995 | } 25996 | } 25997 | 25998 | if (sd.delete_ptr) 25999 | { 26000 | set_error(make_error( 26001 | parser_error::e_syntax, 26002 | current_token(), 26003 | "ERR032 - Invalid number of input parameters passed to function '" + function_name + "'", 26004 | exprtk_error_location)); 26005 | 26006 | return 0; 26007 | } 26008 | 26009 | return (param_index + 1); 26010 | } 26011 | 26012 | inline expression_node_ptr parse_base_operation() 26013 | { 26014 | typedef std::pair<base_ops_map_t::iterator,base_ops_map_t::iterator> map_range_t; 26015 | 26016 | const std::string operation_name = current_token().value; 26017 | const token_t diagnostic_token = current_token(); 26018 | 26019 | map_range_t itr_range = base_ops_map_.equal_range(operation_name); 26020 | 26021 | if (0 == std::distance(itr_range.first,itr_range.second)) 26022 | { 26023 | set_error(make_error( 26024 | parser_error::e_syntax, 26025 | diagnostic_token, 26026 | "ERR033 - No entry found for base operation: " + operation_name, 26027 | exprtk_error_location)); 26028 | 26029 | return error_node(); 26030 | } 26031 | 26032 | static const std::size_t MaxNumberofParameters = 4; 26033 | expression_node_ptr param_list[MaxNumberofParameters] = {0}; 26034 | 26035 | const std::size_t parameter_count = parse_base_function_call(param_list, operation_name); 26036 | 26037 | if ((parameter_count > 0) && (parameter_count <= MaxNumberofParameters)) 26038 | { 26039 | for (base_ops_map_t::iterator itr = itr_range.first; itr != itr_range.second; ++itr) 26040 | { 26041 | const details::base_operation_t& operation = itr->second; 26042 | 26043 | if (operation.num_params == parameter_count) 26044 | { 26045 | switch (parameter_count) 26046 | { 26047 | #define base_opr_case(N) \ 26048 | case N : { \ 26049 | expression_node_ptr pl##N[N] = {0}; \ 26050 | std::copy(param_list, param_list + N, pl##N); \ 26051 | lodge_symbol(operation_name, e_st_function); \ 26052 | return expression_generator_(operation.type, pl##N); \ 26053 | } \ 26054 | 26055 | base_opr_case(1) 26056 | base_opr_case(2) 26057 | base_opr_case(3) 26058 | base_opr_case(4) 26059 | #undef base_opr_case 26060 | } 26061 | } 26062 | } 26063 | } 26064 | 26065 | for (std::size_t i = 0; i < MaxNumberofParameters; ++i) 26066 | { 26067 | free_node(node_allocator_, param_list[i]); 26068 | } 26069 | 26070 | set_error(make_error( 26071 | parser_error::e_syntax, 26072 | diagnostic_token, 26073 | "ERR034 - Invalid number of input parameters for call to function: '" + operation_name + "'", 26074 | exprtk_error_location)); 26075 | 26076 | return error_node(); 26077 | } 26078 | 26079 | inline expression_node_ptr parse_conditional_statement_01(expression_node_ptr condition) 26080 | { 26081 | // Parse: [if][(][condition][,][consequent][,][alternative][)] 26082 | 26083 | expression_node_ptr consequent = error_node(); 26084 | expression_node_ptr alternative = error_node(); 26085 | 26086 | bool result = true; 26087 | 26088 | if (!token_is(token_t::e_comma)) 26089 | { 26090 | set_error(make_error( 26091 | parser_error::e_syntax, 26092 | current_token(), 26093 | "ERR035 - Expected ',' between if-statement condition and consequent", 26094 | exprtk_error_location)); 26095 | 26096 | result = false; 26097 | } 26098 | else if (0 == (consequent = parse_expression())) 26099 | { 26100 | set_error(make_error( 26101 | parser_error::e_syntax, 26102 | current_token(), 26103 | "ERR036 - Failed to parse consequent for if-statement", 26104 | exprtk_error_location)); 26105 | 26106 | result = false; 26107 | } 26108 | else if (!token_is(token_t::e_comma)) 26109 | { 26110 | set_error(make_error( 26111 | parser_error::e_syntax, 26112 | current_token(), 26113 | "ERR037 - Expected ',' between if-statement consequent and alternative", 26114 | exprtk_error_location)); 26115 | 26116 | result = false; 26117 | } 26118 | else if (0 == (alternative = parse_expression())) 26119 | { 26120 | set_error(make_error( 26121 | parser_error::e_syntax, 26122 | current_token(), 26123 | "ERR038 - Failed to parse alternative for if-statement", 26124 | exprtk_error_location)); 26125 | 26126 | result = false; 26127 | } 26128 | else if (!token_is(token_t::e_rbracket)) 26129 | { 26130 | set_error(make_error( 26131 | parser_error::e_syntax, 26132 | current_token(), 26133 | "ERR039 - Expected ')' at the end of if-statement", 26134 | exprtk_error_location)); 26135 | 26136 | result = false; 26137 | } 26138 | 26139 | #ifndef exprtk_disable_string_capabilities 26140 | if (result) 26141 | { 26142 | const bool consq_is_str = is_generally_string_node(consequent ); 26143 | const bool alter_is_str = is_generally_string_node(alternative); 26144 | 26145 | if (consq_is_str || alter_is_str) 26146 | { 26147 | if (consq_is_str && alter_is_str) 26148 | { 26149 | expression_node_ptr result_node = 26150 | expression_generator_ 26151 | .conditional_string(condition, consequent, alternative); 26152 | 26153 | if (result_node && result_node->valid()) 26154 | { 26155 | return result_node; 26156 | } 26157 | 26158 | set_error(make_error( 26159 | parser_error::e_synthesis, 26160 | current_token(), 26161 | "ERR040 - Failed to synthesize node: conditional_string", 26162 | exprtk_error_location)); 26163 | 26164 | free_node(node_allocator_, result_node); 26165 | return error_node(); 26166 | } 26167 | 26168 | set_error(make_error( 26169 | parser_error::e_syntax, 26170 | current_token(), 26171 | "ERR041 - Return types of if-statement differ: string/non-string", 26172 | exprtk_error_location)); 26173 | 26174 | result = false; 26175 | } 26176 | } 26177 | #endif 26178 | 26179 | if (result) 26180 | { 26181 | const bool consq_is_vec = is_ivector_node(consequent ); 26182 | const bool alter_is_vec = is_ivector_node(alternative); 26183 | 26184 | if (consq_is_vec || alter_is_vec) 26185 | { 26186 | if (consq_is_vec && alter_is_vec) 26187 | { 26188 | return expression_generator_ 26189 | .conditional_vector(condition, consequent, alternative); 26190 | } 26191 | 26192 | set_error(make_error( 26193 | parser_error::e_syntax, 26194 | current_token(), 26195 | "ERR042 - Return types of if-statement differ: vector/non-vector", 26196 | exprtk_error_location)); 26197 | 26198 | result = false; 26199 | } 26200 | } 26201 | 26202 | if (!result) 26203 | { 26204 | free_node(node_allocator_, condition ); 26205 | free_node(node_allocator_, consequent ); 26206 | free_node(node_allocator_, alternative); 26207 | 26208 | return error_node(); 26209 | } 26210 | else 26211 | return expression_generator_ 26212 | .conditional(condition, consequent, alternative); 26213 | } 26214 | 26215 | inline expression_node_ptr parse_conditional_statement_02(expression_node_ptr condition) 26216 | { 26217 | expression_node_ptr consequent = error_node(); 26218 | expression_node_ptr alternative = error_node(); 26219 | 26220 | bool result = true; 26221 | 26222 | if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) 26223 | { 26224 | if (0 == (consequent = parse_multi_sequence("if-statement-01"))) 26225 | { 26226 | set_error(make_error( 26227 | parser_error::e_syntax, 26228 | current_token(), 26229 | "ERR043 - Failed to parse body of consequent for if-statement", 26230 | exprtk_error_location)); 26231 | 26232 | result = false; 26233 | } 26234 | else if 26235 | ( 26236 | !settings_.commutative_check_enabled() && 26237 | !token_is("else",prsrhlpr_t::e_hold) && 26238 | !token_is_loop(prsrhlpr_t::e_hold) && 26239 | !token_is_arithmetic_opr(prsrhlpr_t::e_hold) && 26240 | !token_is_right_bracket (prsrhlpr_t::e_hold) && 26241 | !token_is_ineq_opr (prsrhlpr_t::e_hold) && 26242 | !token_is(token_t::e_ternary,prsrhlpr_t::e_hold) && 26243 | !token_is(token_t::e_eof ,prsrhlpr_t::e_hold) 26244 | ) 26245 | { 26246 | set_error(make_error( 26247 | parser_error::e_syntax, 26248 | current_token(), 26249 | "ERR044 - Expected ';' at the end of the consequent for if-statement (1)", 26250 | exprtk_error_location)); 26251 | 26252 | result = false; 26253 | } 26254 | } 26255 | else 26256 | { 26257 | if ( 26258 | settings_.commutative_check_enabled() && 26259 | token_is(token_t::e_mul,prsrhlpr_t::e_hold) 26260 | ) 26261 | { 26262 | next_token(); 26263 | } 26264 | 26265 | if (0 != (consequent = parse_expression())) 26266 | { 26267 | if (!token_is(token_t::e_eof, prsrhlpr_t::e_hold)) 26268 | { 26269 | set_error(make_error( 26270 | parser_error::e_syntax, 26271 | current_token(), 26272 | "ERR045 - Expected ';' at the end of the consequent for if-statement (2)", 26273 | exprtk_error_location)); 26274 | 26275 | result = false; 26276 | } 26277 | } 26278 | else 26279 | { 26280 | set_error(make_error( 26281 | parser_error::e_syntax, 26282 | current_token(), 26283 | "ERR046 - Failed to parse body of consequent for if-statement", 26284 | exprtk_error_location)); 26285 | 26286 | result = false; 26287 | } 26288 | } 26289 | 26290 | if (result) 26291 | { 26292 | if ( 26293 | details::imatch(current_token().value,"else") || 26294 | (token_is(token_t::e_eof, prsrhlpr_t::e_hold) && peek_token_is("else")) 26295 | ) 26296 | { 26297 | next_token(); 26298 | 26299 | if (details::imatch(current_token().value,"else")) 26300 | { 26301 | next_token(); 26302 | } 26303 | 26304 | if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) 26305 | { 26306 | if (0 == (alternative = parse_multi_sequence("else-statement-01"))) 26307 | { 26308 | set_error(make_error( 26309 | parser_error::e_syntax, 26310 | current_token(), 26311 | "ERR047 - Failed to parse body of the 'else' for if-statement", 26312 | exprtk_error_location)); 26313 | 26314 | result = false; 26315 | } 26316 | } 26317 | else if (details::imatch(current_token().value,"if")) 26318 | { 26319 | if (0 == (alternative = parse_conditional_statement())) 26320 | { 26321 | set_error(make_error( 26322 | parser_error::e_syntax, 26323 | current_token(), 26324 | "ERR048 - Failed to parse body of if-else statement", 26325 | exprtk_error_location)); 26326 | 26327 | result = false; 26328 | } 26329 | } 26330 | else if (0 != (alternative = parse_expression())) 26331 | { 26332 | if ( 26333 | !token_is(token_t::e_ternary , prsrhlpr_t::e_hold) && 26334 | !token_is(token_t::e_rcrlbracket, prsrhlpr_t::e_hold) && 26335 | !token_is(token_t::e_eof) 26336 | ) 26337 | { 26338 | set_error(make_error( 26339 | parser_error::e_syntax, 26340 | current_token(), 26341 | "ERR049 - Expected ';' at the end of the 'else-if' for the if-statement", 26342 | exprtk_error_location)); 26343 | 26344 | result = false; 26345 | } 26346 | } 26347 | else 26348 | { 26349 | set_error(make_error( 26350 | parser_error::e_syntax, 26351 | current_token(), 26352 | "ERR050 - Failed to parse body of the 'else' for if-statement", 26353 | exprtk_error_location)); 26354 | 26355 | result = false; 26356 | } 26357 | } 26358 | } 26359 | 26360 | #ifndef exprtk_disable_string_capabilities 26361 | if (result) 26362 | { 26363 | const bool consq_is_str = is_generally_string_node(consequent ); 26364 | const bool alter_is_str = is_generally_string_node(alternative); 26365 | 26366 | if (consq_is_str || alter_is_str) 26367 | { 26368 | if (consq_is_str && alter_is_str) 26369 | { 26370 | return expression_generator_ 26371 | .conditional_string(condition, consequent, alternative); 26372 | } 26373 | 26374 | set_error(make_error( 26375 | parser_error::e_syntax, 26376 | current_token(), 26377 | "ERR051 - Return types of if-statement differ: string/non-string", 26378 | exprtk_error_location)); 26379 | 26380 | result = false; 26381 | } 26382 | } 26383 | #endif 26384 | 26385 | if (result) 26386 | { 26387 | const bool consq_is_vec = is_ivector_node(consequent ); 26388 | const bool alter_is_vec = is_ivector_node(alternative); 26389 | 26390 | if (consq_is_vec || alter_is_vec) 26391 | { 26392 | if (consq_is_vec && alter_is_vec) 26393 | { 26394 | return expression_generator_ 26395 | .conditional_vector(condition, consequent, alternative); 26396 | } 26397 | 26398 | set_error(make_error( 26399 | parser_error::e_syntax, 26400 | current_token(), 26401 | "ERR052 - Return types of if-statement differ: vector/non-vector", 26402 | exprtk_error_location)); 26403 | 26404 | result = false; 26405 | } 26406 | } 26407 | 26408 | if (!result) 26409 | { 26410 | free_node(node_allocator_, condition ); 26411 | free_node(node_allocator_, consequent ); 26412 | free_node(node_allocator_, alternative); 26413 | 26414 | return error_node(); 26415 | } 26416 | else 26417 | return expression_generator_ 26418 | .conditional(condition, consequent, alternative); 26419 | } 26420 | 26421 | inline expression_node_ptr parse_conditional_statement() 26422 | { 26423 | expression_node_ptr condition = error_node(); 26424 | 26425 | next_token(); 26426 | 26427 | if (!token_is(token_t::e_lbracket)) 26428 | { 26429 | set_error(make_error( 26430 | parser_error::e_syntax, 26431 | current_token(), 26432 | "ERR053 - Expected '(' at start of if-statement, instead got: '" + current_token().value + "'", 26433 | exprtk_error_location)); 26434 | 26435 | return error_node(); 26436 | } 26437 | else if (0 == (condition = parse_expression())) 26438 | { 26439 | set_error(make_error( 26440 | parser_error::e_syntax, 26441 | current_token(), 26442 | "ERR054 - Failed to parse condition for if-statement", 26443 | exprtk_error_location)); 26444 | 26445 | return error_node(); 26446 | } 26447 | else if (token_is(token_t::e_comma,prsrhlpr_t::e_hold)) 26448 | { 26449 | // if (x,y,z) 26450 | return parse_conditional_statement_01(condition); 26451 | } 26452 | else if (token_is(token_t::e_rbracket)) 26453 | { 26454 | /* 26455 | 00. if (x) y; 26456 | 01. if (x) y; else z; 26457 | 02. if (x) y; else {z0; ... zn;} 26458 | 03. if (x) y; else if (z) w; 26459 | 04. if (x) y; else if (z) w; else u; 26460 | 05. if (x) y; else if (z) w; else {u0; ... un;} 26461 | 06. if (x) y; else if (z) {w0; ... wn;} 26462 | 07. if (x) {y0; ... yn;} 26463 | 08. if (x) {y0; ... yn;} else z; 26464 | 09. if (x) {y0; ... yn;} else {z0; ... zn;}; 26465 | 10. if (x) {y0; ... yn;} else if (z) w; 26466 | 11. if (x) {y0; ... yn;} else if (z) w; else u; 26467 | 12. if (x) {y0; ... nex;} else if (z) w; else {u0 ... un;} 26468 | 13. if (x) {y0; ... yn;} else if (z) {w0; ... wn;} 26469 | */ 26470 | return parse_conditional_statement_02(condition); 26471 | } 26472 | 26473 | set_error(make_error( 26474 | parser_error::e_syntax, 26475 | current_token(), 26476 | "ERR055 - Invalid if-statement", 26477 | exprtk_error_location)); 26478 | 26479 | free_node(node_allocator_, condition); 26480 | 26481 | return error_node(); 26482 | } 26483 | 26484 | inline expression_node_ptr parse_ternary_conditional_statement(expression_node_ptr condition) 26485 | { 26486 | // Parse: [condition][?][consequent][:][alternative] 26487 | expression_node_ptr consequent = error_node(); 26488 | expression_node_ptr alternative = error_node(); 26489 | 26490 | bool result = true; 26491 | 26492 | if (0 == condition) 26493 | { 26494 | set_error(make_error( 26495 | parser_error::e_syntax, 26496 | current_token(), 26497 | "ERR056 - Encountered invalid condition branch for ternary if-statement", 26498 | exprtk_error_location)); 26499 | 26500 | return error_node(); 26501 | } 26502 | else if (!token_is(token_t::e_ternary)) 26503 | { 26504 | set_error(make_error( 26505 | parser_error::e_syntax, 26506 | current_token(), 26507 | "ERR057 - Expected '?' after condition of ternary if-statement", 26508 | exprtk_error_location)); 26509 | 26510 | result = false; 26511 | } 26512 | else if (0 == (consequent = parse_expression())) 26513 | { 26514 | set_error(make_error( 26515 | parser_error::e_syntax, 26516 | current_token(), 26517 | "ERR058 - Failed to parse consequent for ternary if-statement", 26518 | exprtk_error_location)); 26519 | 26520 | result = false; 26521 | } 26522 | else if (!token_is(token_t::e_colon)) 26523 | { 26524 | set_error(make_error( 26525 | parser_error::e_syntax, 26526 | current_token(), 26527 | "ERR059 - Expected ':' between ternary if-statement consequent and alternative", 26528 | exprtk_error_location)); 26529 | 26530 | result = false; 26531 | } 26532 | else if (0 == (alternative = parse_expression())) 26533 | { 26534 | set_error(make_error( 26535 | parser_error::e_syntax, 26536 | current_token(), 26537 | "ERR060 - Failed to parse alternative for ternary if-statement", 26538 | exprtk_error_location)); 26539 | 26540 | result = false; 26541 | } 26542 | 26543 | #ifndef exprtk_disable_string_capabilities 26544 | if (result) 26545 | { 26546 | const bool consq_is_str = is_generally_string_node(consequent ); 26547 | const bool alter_is_str = is_generally_string_node(alternative); 26548 | 26549 | if (consq_is_str || alter_is_str) 26550 | { 26551 | if (consq_is_str && alter_is_str) 26552 | { 26553 | return expression_generator_ 26554 | .conditional_string(condition, consequent, alternative); 26555 | } 26556 | 26557 | set_error(make_error( 26558 | parser_error::e_syntax, 26559 | current_token(), 26560 | "ERR061 - Return types of ternary differ: string/non-string", 26561 | exprtk_error_location)); 26562 | 26563 | result = false; 26564 | } 26565 | } 26566 | #endif 26567 | 26568 | if (result) 26569 | { 26570 | const bool consq_is_vec = is_ivector_node(consequent ); 26571 | const bool alter_is_vec = is_ivector_node(alternative); 26572 | 26573 | if (consq_is_vec || alter_is_vec) 26574 | { 26575 | if (consq_is_vec && alter_is_vec) 26576 | { 26577 | return expression_generator_ 26578 | .conditional_vector(condition, consequent, alternative); 26579 | } 26580 | 26581 | set_error(make_error( 26582 | parser_error::e_syntax, 26583 | current_token(), 26584 | "ERR062 - Return types of ternary differ: vector/non-vector", 26585 | exprtk_error_location)); 26586 | 26587 | result = false; 26588 | } 26589 | } 26590 | 26591 | if (!result) 26592 | { 26593 | free_node(node_allocator_, condition ); 26594 | free_node(node_allocator_, consequent ); 26595 | free_node(node_allocator_, alternative); 26596 | 26597 | return error_node(); 26598 | } 26599 | else 26600 | return expression_generator_ 26601 | .conditional(condition, consequent, alternative); 26602 | } 26603 | 26604 | inline expression_node_ptr parse_not_statement() 26605 | { 26606 | if (settings_.logic_disabled("not")) 26607 | { 26608 | set_error(make_error( 26609 | parser_error::e_syntax, 26610 | current_token(), 26611 | "ERR063 - Invalid or disabled logic operation 'not'", 26612 | exprtk_error_location)); 26613 | 26614 | return error_node(); 26615 | } 26616 | 26617 | return parse_base_operation(); 26618 | } 26619 | 26620 | void handle_brkcnt_scope_exit() 26621 | { 26622 | assert(!brkcnt_list_.empty()); 26623 | brkcnt_list_.pop_front(); 26624 | } 26625 | 26626 | inline expression_node_ptr parse_while_loop() 26627 | { 26628 | // Parse: [while][(][test expr][)][{][expression][}] 26629 | expression_node_ptr condition = error_node(); 26630 | expression_node_ptr branch = error_node(); 26631 | expression_node_ptr result_node = error_node(); 26632 | 26633 | bool result = true; 26634 | 26635 | next_token(); 26636 | 26637 | if (!token_is(token_t::e_lbracket)) 26638 | { 26639 | set_error(make_error( 26640 | parser_error::e_syntax, 26641 | current_token(), 26642 | "ERR064 - Expected '(' at start of while-loop condition statement", 26643 | exprtk_error_location)); 26644 | 26645 | return error_node(); 26646 | } 26647 | else if (0 == (condition = parse_expression())) 26648 | { 26649 | set_error(make_error( 26650 | parser_error::e_syntax, 26651 | current_token(), 26652 | "ERR065 - Failed to parse condition for while-loop", 26653 | exprtk_error_location)); 26654 | 26655 | return error_node(); 26656 | } 26657 | else if (!token_is(token_t::e_rbracket)) 26658 | { 26659 | set_error(make_error( 26660 | parser_error::e_syntax, 26661 | current_token(), 26662 | "ERR066 - Expected ')' at end of while-loop condition statement", 26663 | exprtk_error_location)); 26664 | 26665 | result = false; 26666 | } 26667 | 26668 | brkcnt_list_.push_front(false); 26669 | 26670 | if (result) 26671 | { 26672 | scoped_inc_dec sid(state_.parsing_loop_stmt_count); 26673 | 26674 | if (0 == (branch = parse_multi_sequence("while-loop", true))) 26675 | { 26676 | set_error(make_error( 26677 | parser_error::e_syntax, 26678 | current_token(), 26679 | "ERR067 - Failed to parse body of while-loop")); 26680 | result = false; 26681 | } 26682 | else if (0 == (result_node = expression_generator_.while_loop(condition, 26683 | branch, 26684 | brkcnt_list_.front()))) 26685 | { 26686 | set_error(make_error( 26687 | parser_error::e_syntax, 26688 | current_token(), 26689 | "ERR068 - Failed to synthesize while-loop", 26690 | exprtk_error_location)); 26691 | 26692 | result = false; 26693 | } 26694 | } 26695 | 26696 | handle_brkcnt_scope_exit(); 26697 | 26698 | if (!result) 26699 | { 26700 | free_node(node_allocator_, branch ); 26701 | free_node(node_allocator_, condition ); 26702 | free_node(node_allocator_, result_node); 26703 | 26704 | return error_node(); 26705 | } 26706 | 26707 | if (result_node && result_node->valid()) 26708 | { 26709 | return result_node; 26710 | } 26711 | 26712 | set_error(make_error( 26713 | parser_error::e_synthesis, 26714 | current_token(), 26715 | "ERR069 - Failed to synthesize 'valid' while-loop", 26716 | exprtk_error_location)); 26717 | 26718 | free_node(node_allocator_, result_node); 26719 | 26720 | return error_node(); 26721 | } 26722 | 26723 | inline expression_node_ptr parse_repeat_until_loop() 26724 | { 26725 | // Parse: [repeat][{][expression][}][until][(][test expr][)] 26726 | expression_node_ptr condition = error_node(); 26727 | expression_node_ptr branch = error_node(); 26728 | next_token(); 26729 | 26730 | std::vector<expression_node_ptr> arg_list; 26731 | std::vector<bool> side_effect_list; 26732 | 26733 | scoped_vec_delete<expression_node_t> sdd((*this),arg_list); 26734 | 26735 | brkcnt_list_.push_front(false); 26736 | 26737 | if (details::imatch(current_token().value,"until")) 26738 | { 26739 | next_token(); 26740 | branch = node_allocator_.allocate<details::null_node<T> >(); 26741 | } 26742 | else 26743 | { 26744 | const token_t::token_type separator = token_t::e_eof; 26745 | 26746 | scope_handler sh(*this); 26747 | 26748 | scoped_bool_or_restorer sbr(state_.side_effect_present); 26749 | 26750 | scoped_inc_dec sid(state_.parsing_loop_stmt_count); 26751 | 26752 | for ( ; ; ) 26753 | { 26754 | state_.side_effect_present = false; 26755 | 26756 | expression_node_ptr arg = parse_expression(); 26757 | 26758 | if (0 == arg) 26759 | return error_node(); 26760 | else 26761 | { 26762 | arg_list.push_back(arg); 26763 | side_effect_list.push_back(state_.side_effect_present); 26764 | } 26765 | 26766 | if (details::imatch(current_token().value,"until")) 26767 | { 26768 | next_token(); 26769 | break; 26770 | } 26771 | 26772 | const bool is_next_until = peek_token_is(token_t::e_symbol) && 26773 | peek_token_is("until"); 26774 | 26775 | if (!token_is(separator) && is_next_until) 26776 | { 26777 | set_error(make_error( 26778 | parser_error::e_syntax, 26779 | current_token(), 26780 | "ERR070 - Expected '" + token_t::to_str(separator) + "' in body of repeat until loop", 26781 | exprtk_error_location)); 26782 | 26783 | return error_node(); 26784 | } 26785 | 26786 | if (details::imatch(current_token().value,"until")) 26787 | { 26788 | next_token(); 26789 | break; 26790 | } 26791 | } 26792 | 26793 | branch = simplify(arg_list,side_effect_list); 26794 | 26795 | sdd.delete_ptr = (0 == branch); 26796 | 26797 | if (sdd.delete_ptr) 26798 | { 26799 | set_error(make_error( 26800 | parser_error::e_syntax, 26801 | current_token(), 26802 | "ERR071 - Failed to parse body of repeat until loop", 26803 | exprtk_error_location)); 26804 | 26805 | return error_node(); 26806 | } 26807 | } 26808 | 26809 | if (!token_is(token_t::e_lbracket)) 26810 | { 26811 | set_error(make_error( 26812 | parser_error::e_syntax, 26813 | current_token(), 26814 | "ERR072 - Expected '(' before condition statement of repeat until loop", 26815 | exprtk_error_location)); 26816 | 26817 | free_node(node_allocator_, branch); 26818 | return error_node(); 26819 | } 26820 | else if (0 == (condition = parse_expression())) 26821 | { 26822 | set_error(make_error( 26823 | parser_error::e_syntax, 26824 | current_token(), 26825 | "ERR073 - Failed to parse condition for repeat until loop", 26826 | exprtk_error_location)); 26827 | 26828 | free_node(node_allocator_, branch); 26829 | return error_node(); 26830 | } 26831 | else if (!token_is(token_t::e_rbracket)) 26832 | { 26833 | set_error(make_error( 26834 | parser_error::e_syntax, 26835 | current_token(), 26836 | "ERR074 - Expected ')' after condition of repeat until loop", 26837 | exprtk_error_location)); 26838 | 26839 | free_node(node_allocator_, branch ); 26840 | free_node(node_allocator_, condition); 26841 | 26842 | return error_node(); 26843 | } 26844 | 26845 | expression_node_ptr result_node = 26846 | expression_generator_ 26847 | .repeat_until_loop( 26848 | condition, 26849 | branch, 26850 | brkcnt_list_.front()); 26851 | 26852 | if (0 == result_node) 26853 | { 26854 | set_error(make_error( 26855 | parser_error::e_syntax, 26856 | current_token(), 26857 | "ERR075 - Failed to synthesize repeat until loop", 26858 | exprtk_error_location)); 26859 | 26860 | free_node(node_allocator_, condition); 26861 | 26862 | return error_node(); 26863 | } 26864 | 26865 | handle_brkcnt_scope_exit(); 26866 | 26867 | if (result_node && result_node->valid()) 26868 | { 26869 | return result_node; 26870 | } 26871 | 26872 | set_error(make_error( 26873 | parser_error::e_synthesis, 26874 | current_token(), 26875 | "ERR076 - Failed to synthesize 'valid' repeat until loop", 26876 | exprtk_error_location)); 26877 | 26878 | free_node(node_allocator_, result_node); 26879 | 26880 | return error_node(); 26881 | } 26882 | 26883 | inline expression_node_ptr parse_for_loop() 26884 | { 26885 | expression_node_ptr initialiser = error_node(); 26886 | expression_node_ptr condition = error_node(); 26887 | expression_node_ptr incrementor = error_node(); 26888 | expression_node_ptr loop_body = error_node(); 26889 | 26890 | scope_element* se = 0; 26891 | bool result = true; 26892 | 26893 | next_token(); 26894 | 26895 | scope_handler sh(*this); 26896 | 26897 | if (!token_is(token_t::e_lbracket)) 26898 | { 26899 | set_error(make_error( 26900 | parser_error::e_syntax, 26901 | current_token(), 26902 | "ERR077 - Expected '(' at start of for-loop", 26903 | exprtk_error_location)); 26904 | 26905 | return error_node(); 26906 | } 26907 | 26908 | if (!token_is(token_t::e_eof)) 26909 | { 26910 | if ( 26911 | !token_is(token_t::e_symbol,prsrhlpr_t::e_hold) && 26912 | details::imatch(current_token().value,"var") 26913 | ) 26914 | { 26915 | next_token(); 26916 | 26917 | if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold)) 26918 | { 26919 | set_error(make_error( 26920 | parser_error::e_syntax, 26921 | current_token(), 26922 | "ERR078 - Expected a variable at the start of initialiser section of for-loop", 26923 | exprtk_error_location)); 26924 | 26925 | return error_node(); 26926 | } 26927 | else if (!peek_token_is(token_t::e_assign)) 26928 | { 26929 | set_error(make_error( 26930 | parser_error::e_syntax, 26931 | current_token(), 26932 | "ERR079 - Expected variable assignment of initialiser section of for-loop", 26933 | exprtk_error_location)); 26934 | 26935 | return error_node(); 26936 | } 26937 | 26938 | const std::string loop_counter_symbol = current_token().value; 26939 | 26940 | se = &sem_.get_element(loop_counter_symbol); 26941 | 26942 | if ((se->name == loop_counter_symbol) && se->active) 26943 | { 26944 | set_error(make_error( 26945 | parser_error::e_syntax, 26946 | current_token(), 26947 | "ERR080 - For-loop variable '" + loop_counter_symbol+ "' is being shadowed by a previous declaration", 26948 | exprtk_error_location)); 26949 | 26950 | return error_node(); 26951 | } 26952 | else if (!symtab_store_.is_variable(loop_counter_symbol)) 26953 | { 26954 | if ( 26955 | !se->active && 26956 | (se->name == loop_counter_symbol) && 26957 | (se->type == scope_element::e_variable) 26958 | ) 26959 | { 26960 | se->active = true; 26961 | se->ref_count++; 26962 | } 26963 | else 26964 | { 26965 | scope_element nse; 26966 | nse.name = loop_counter_symbol; 26967 | nse.active = true; 26968 | nse.ref_count = 1; 26969 | nse.type = scope_element::e_variable; 26970 | nse.depth = state_.scope_depth; 26971 | nse.data = new T(T(0)); 26972 | nse.var_node = node_allocator_.allocate<variable_node_t>(*reinterpret_cast<T*>(nse.data)); 26973 | 26974 | if (!sem_.add_element(nse)) 26975 | { 26976 | set_error(make_error( 26977 | parser_error::e_syntax, 26978 | current_token(), 26979 | "ERR081 - Failed to add new local variable '" + loop_counter_symbol + "' to SEM", 26980 | exprtk_error_location)); 26981 | 26982 | sem_.free_element(nse); 26983 | 26984 | result = false; 26985 | } 26986 | else 26987 | { 26988 | exprtk_debug(("parse_for_loop() - INFO - Added new local variable: %s\n", nse.name.c_str())); 26989 | 26990 | state_.activate_side_effect("parse_for_loop()"); 26991 | } 26992 | } 26993 | } 26994 | } 26995 | 26996 | if (0 == (initialiser = parse_expression())) 26997 | { 26998 | set_error(make_error( 26999 | parser_error::e_syntax, 27000 | current_token(), 27001 | "ERR082 - Failed to parse initialiser of for-loop", 27002 | exprtk_error_location)); 27003 | 27004 | result = false; 27005 | } 27006 | else if (!token_is(token_t::e_eof)) 27007 | { 27008 | set_error(make_error( 27009 | parser_error::e_syntax, 27010 | current_token(), 27011 | "ERR083 - Expected ';' after initialiser of for-loop", 27012 | exprtk_error_location)); 27013 | 27014 | result = false; 27015 | } 27016 | } 27017 | 27018 | if (!token_is(token_t::e_eof)) 27019 | { 27020 | if (0 == (condition = parse_expression())) 27021 | { 27022 | set_error(make_error( 27023 | parser_error::e_syntax, 27024 | current_token(), 27025 | "ERR084 - Failed to parse condition 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 | "ERR085 - Expected ';' after condition section of for-loop", 27036 | exprtk_error_location)); 27037 | 27038 | result = false; 27039 | } 27040 | } 27041 | 27042 | if (!token_is(token_t::e_rbracket)) 27043 | { 27044 | if (0 == (incrementor = parse_expression())) 27045 | { 27046 | set_error(make_error( 27047 | parser_error::e_syntax, 27048 | current_token(), 27049 | "ERR086 - Failed to parse incrementor of for-loop", 27050 | exprtk_error_location)); 27051 | 27052 | result = false; 27053 | } 27054 | else if (!token_is(token_t::e_rbracket)) 27055 | { 27056 | set_error(make_error( 27057 | parser_error::e_syntax, 27058 | current_token(), 27059 | "ERR087 - Expected ')' after incrementor section of for-loop", 27060 | exprtk_error_location)); 27061 | 27062 | result = false; 27063 | } 27064 | } 27065 | 27066 | if (result) 27067 | { 27068 | brkcnt_list_.push_front(false); 27069 | 27070 | scoped_inc_dec sid(state_.parsing_loop_stmt_count); 27071 | 27072 | if (0 == (loop_body = parse_multi_sequence("for-loop", true))) 27073 | { 27074 | set_error(make_error( 27075 | parser_error::e_syntax, 27076 | current_token(), 27077 | "ERR088 - Failed to parse body of for-loop", 27078 | exprtk_error_location)); 27079 | 27080 | result = false; 27081 | } 27082 | } 27083 | 27084 | if (!result) 27085 | { 27086 | if (se) 27087 | { 27088 | se->ref_count--; 27089 | } 27090 | 27091 | free_node(node_allocator_, initialiser); 27092 | free_node(node_allocator_, condition ); 27093 | free_node(node_allocator_, incrementor); 27094 | free_node(node_allocator_, loop_body ); 27095 | return error_node(); 27096 | } 27097 | 27098 | expression_node_ptr result_node = 27099 | expression_generator_.for_loop(initialiser, 27100 | condition, 27101 | incrementor, 27102 | loop_body, 27103 | brkcnt_list_.front()); 27104 | handle_brkcnt_scope_exit(); 27105 | 27106 | if (result_node && result_node->valid()) 27107 | { 27108 | return result_node; 27109 | } 27110 | 27111 | set_error(make_error( 27112 | parser_error::e_synthesis, 27113 | current_token(), 27114 | "ERR089 - Failed to synthesize 'valid' for-loop", 27115 | exprtk_error_location)); 27116 | 27117 | free_node(node_allocator_, result_node); 27118 | 27119 | return error_node(); 27120 | } 27121 | 27122 | inline expression_node_ptr parse_switch_statement() 27123 | { 27124 | std::vector<expression_node_ptr> arg_list; 27125 | 27126 | if (!details::imatch(current_token().value,"switch")) 27127 | { 27128 | set_error(make_error( 27129 | parser_error::e_syntax, 27130 | current_token(), 27131 | "ERR090 - Expected keyword 'switch'", 27132 | exprtk_error_location)); 27133 | 27134 | return error_node(); 27135 | } 27136 | 27137 | scoped_vec_delete<expression_node_t> svd((*this),arg_list); 27138 | 27139 | next_token(); 27140 | 27141 | if (!token_is(token_t::e_lcrlbracket)) 27142 | { 27143 | set_error(make_error( 27144 | parser_error::e_syntax, 27145 | current_token(), 27146 | "ERR091 - Expected '{' for call to switch statement", 27147 | exprtk_error_location)); 27148 | 27149 | return error_node(); 27150 | } 27151 | 27152 | expression_node_ptr default_statement = error_node(); 27153 | 27154 | scoped_expression_delete defstmt_delete((*this), default_statement); 27155 | 27156 | for ( ; ; ) 27157 | { 27158 | if (details::imatch("case",current_token().value)) 27159 | { 27160 | next_token(); 27161 | 27162 | expression_node_ptr condition = parse_expression(); 27163 | 27164 | if (0 == condition) 27165 | return error_node(); 27166 | else if (!token_is(token_t::e_colon)) 27167 | { 27168 | set_error(make_error( 27169 | parser_error::e_syntax, 27170 | current_token(), 27171 | "ERR092 - Expected ':' for case of switch statement", 27172 | exprtk_error_location)); 27173 | 27174 | free_node(node_allocator_, condition); 27175 | 27176 | return error_node(); 27177 | } 27178 | 27179 | expression_node_ptr consequent = 27180 | (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) ? 27181 | parse_multi_sequence("switch-consequent") : 27182 | parse_expression(); 27183 | 27184 | if (0 == consequent) 27185 | { 27186 | free_node(node_allocator_, condition); 27187 | 27188 | return error_node(); 27189 | } 27190 | else if (!token_is(token_t::e_eof)) 27191 | { 27192 | set_error(make_error( 27193 | parser_error::e_syntax, 27194 | current_token(), 27195 | "ERR093 - Expected ';' at end of case for switch statement", 27196 | exprtk_error_location)); 27197 | 27198 | free_node(node_allocator_, condition ); 27199 | free_node(node_allocator_, consequent); 27200 | 27201 | return error_node(); 27202 | } 27203 | 27204 | // Can we optimise away the case statement? 27205 | if (is_constant_node(condition) && is_false(condition)) 27206 | { 27207 | free_node(node_allocator_, condition ); 27208 | free_node(node_allocator_, consequent); 27209 | } 27210 | else 27211 | { 27212 | arg_list.push_back(condition ); 27213 | arg_list.push_back(consequent); 27214 | } 27215 | 27216 | } 27217 | else if (details::imatch("default",current_token().value)) 27218 | { 27219 | if (0 != default_statement) 27220 | { 27221 | set_error(make_error( 27222 | parser_error::e_syntax, 27223 | current_token(), 27224 | "ERR094 - Multiple default cases for switch statement", 27225 | exprtk_error_location)); 27226 | 27227 | return error_node(); 27228 | } 27229 | 27230 | next_token(); 27231 | 27232 | if (!token_is(token_t::e_colon)) 27233 | { 27234 | set_error(make_error( 27235 | parser_error::e_syntax, 27236 | current_token(), 27237 | "ERR095 - Expected ':' for default of switch statement", 27238 | exprtk_error_location)); 27239 | 27240 | return error_node(); 27241 | } 27242 | 27243 | default_statement = 27244 | (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) ? 27245 | parse_multi_sequence("switch-default"): 27246 | parse_expression(); 27247 | 27248 | if (0 == default_statement) 27249 | return error_node(); 27250 | else if (!token_is(token_t::e_eof)) 27251 | { 27252 | set_error(make_error( 27253 | parser_error::e_syntax, 27254 | current_token(), 27255 | "ERR096 - Expected ';' at end of default for switch statement", 27256 | exprtk_error_location)); 27257 | 27258 | return error_node(); 27259 | } 27260 | } 27261 | else if (token_is(token_t::e_rcrlbracket)) 27262 | break; 27263 | else 27264 | { 27265 | set_error(make_error( 27266 | parser_error::e_syntax, 27267 | current_token(), 27268 | "ERR097 - Expected '}' at end of switch statement", 27269 | exprtk_error_location)); 27270 | 27271 | return error_node(); 27272 | } 27273 | } 27274 | 27275 | const bool default_statement_present = (0 != default_statement); 27276 | 27277 | if (default_statement_present) 27278 | { 27279 | arg_list.push_back(default_statement); 27280 | } 27281 | else 27282 | { 27283 | arg_list.push_back(node_allocator_.allocate_c<literal_node_t>(std::numeric_limits<T>::quiet_NaN())); 27284 | } 27285 | 27286 | expression_node_ptr result = expression_generator_.switch_statement(arg_list, (0 != default_statement)); 27287 | 27288 | svd.delete_ptr = (0 == result); 27289 | defstmt_delete.delete_ptr = (0 == result); 27290 | 27291 | return result; 27292 | } 27293 | 27294 | inline expression_node_ptr parse_multi_switch_statement() 27295 | { 27296 | std::vector<expression_node_ptr> arg_list; 27297 | 27298 | if (!details::imatch(current_token().value,"[*]")) 27299 | { 27300 | set_error(make_error( 27301 | parser_error::e_syntax, 27302 | current_token(), 27303 | "ERR098 - Expected token '[*]'", 27304 | exprtk_error_location)); 27305 | 27306 | return error_node(); 27307 | } 27308 | 27309 | scoped_vec_delete<expression_node_t> svd((*this),arg_list); 27310 | 27311 | next_token(); 27312 | 27313 | if (!token_is(token_t::e_lcrlbracket)) 27314 | { 27315 | set_error(make_error( 27316 | parser_error::e_syntax, 27317 | current_token(), 27318 | "ERR099 - Expected '{' for call to [*] statement", 27319 | exprtk_error_location)); 27320 | 27321 | return error_node(); 27322 | } 27323 | 27324 | for ( ; ; ) 27325 | { 27326 | if (!details::imatch("case",current_token().value)) 27327 | { 27328 | set_error(make_error( 27329 | parser_error::e_syntax, 27330 | current_token(), 27331 | "ERR100 - Expected a 'case' statement for multi-switch", 27332 | exprtk_error_location)); 27333 | 27334 | return error_node(); 27335 | } 27336 | 27337 | next_token(); 27338 | 27339 | expression_node_ptr condition = parse_expression(); 27340 | 27341 | if (0 == condition) 27342 | return error_node(); 27343 | 27344 | if (!token_is(token_t::e_colon)) 27345 | { 27346 | set_error(make_error( 27347 | parser_error::e_syntax, 27348 | current_token(), 27349 | "ERR101 - Expected ':' for case of [*] statement", 27350 | exprtk_error_location)); 27351 | 27352 | return error_node(); 27353 | } 27354 | 27355 | expression_node_ptr consequent = 27356 | (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) ? 27357 | parse_multi_sequence("multi-switch-consequent") : 27358 | parse_expression(); 27359 | 27360 | if (0 == consequent) 27361 | return error_node(); 27362 | 27363 | if (!token_is(token_t::e_eof)) 27364 | { 27365 | set_error(make_error( 27366 | parser_error::e_syntax, 27367 | current_token(), 27368 | "ERR102 - Expected ';' at end of case for [*] statement", 27369 | exprtk_error_location)); 27370 | 27371 | return error_node(); 27372 | } 27373 | 27374 | // Can we optimise away the case statement? 27375 | if (is_constant_node(condition) && is_false(condition)) 27376 | { 27377 | free_node(node_allocator_, condition ); 27378 | free_node(node_allocator_, consequent); 27379 | } 27380 | else 27381 | { 27382 | arg_list.push_back(condition ); 27383 | arg_list.push_back(consequent); 27384 | } 27385 | 27386 | if (token_is(token_t::e_rcrlbracket,prsrhlpr_t::e_hold)) 27387 | { 27388 | break; 27389 | } 27390 | } 27391 | 27392 | if (!token_is(token_t::e_rcrlbracket)) 27393 | { 27394 | set_error(make_error( 27395 | parser_error::e_syntax, 27396 | current_token(), 27397 | "ERR103 - Expected '}' at end of [*] statement", 27398 | exprtk_error_location)); 27399 | 27400 | return error_node(); 27401 | } 27402 | 27403 | const expression_node_ptr result = expression_generator_.multi_switch_statement(arg_list); 27404 | 27405 | svd.delete_ptr = (0 == result); 27406 | 27407 | return result; 27408 | } 27409 | 27410 | inline expression_node_ptr parse_vararg_function() 27411 | { 27412 | std::vector<expression_node_ptr> arg_list; 27413 | 27414 | details::operator_type opt_type = details::e_default; 27415 | const std::string symbol = current_token().value; 27416 | 27417 | if (details::imatch(symbol,"~")) 27418 | { 27419 | next_token(); 27420 | return check_block_statement_closure(parse_multi_sequence()); 27421 | } 27422 | else if (details::imatch(symbol,"[*]")) 27423 | { 27424 | return check_block_statement_closure(parse_multi_switch_statement()); 27425 | } 27426 | else if (details::imatch(symbol, "avg" )) opt_type = details::e_avg ; 27427 | else if (details::imatch(symbol, "mand")) opt_type = details::e_mand; 27428 | else if (details::imatch(symbol, "max" )) opt_type = details::e_max ; 27429 | else if (details::imatch(symbol, "min" )) opt_type = details::e_min ; 27430 | else if (details::imatch(symbol, "mor" )) opt_type = details::e_mor ; 27431 | else if (details::imatch(symbol, "mul" )) opt_type = details::e_prod; 27432 | else if (details::imatch(symbol, "sum" )) opt_type = details::e_sum ; 27433 | else 27434 | { 27435 | set_error(make_error( 27436 | parser_error::e_syntax, 27437 | current_token(), 27438 | "ERR104 - Unsupported built-in vararg function: " + symbol, 27439 | exprtk_error_location)); 27440 | 27441 | return error_node(); 27442 | } 27443 | 27444 | scoped_vec_delete<expression_node_t> sdd((*this),arg_list); 27445 | 27446 | lodge_symbol(symbol, e_st_function); 27447 | 27448 | next_token(); 27449 | 27450 | if (!token_is(token_t::e_lbracket)) 27451 | { 27452 | set_error(make_error( 27453 | parser_error::e_syntax, 27454 | current_token(), 27455 | "ERR105 - Expected '(' for call to vararg function: " + symbol, 27456 | exprtk_error_location)); 27457 | 27458 | return error_node(); 27459 | } 27460 | 27461 | if (token_is(token_t::e_rbracket)) 27462 | { 27463 | set_error(make_error( 27464 | parser_error::e_syntax, 27465 | current_token(), 27466 | "ERR106 - vararg function: " + symbol + 27467 | " requires at least one input parameter", 27468 | exprtk_error_location)); 27469 | 27470 | return error_node(); 27471 | } 27472 | 27473 | for ( ; ; ) 27474 | { 27475 | expression_node_ptr arg = parse_expression(); 27476 | 27477 | if (0 == arg) 27478 | return error_node(); 27479 | else 27480 | arg_list.push_back(arg); 27481 | 27482 | if (token_is(token_t::e_rbracket)) 27483 | break; 27484 | else if (!token_is(token_t::e_comma)) 27485 | { 27486 | set_error(make_error( 27487 | parser_error::e_syntax, 27488 | current_token(), 27489 | "ERR107 - Expected ',' for call to vararg function: " + symbol, 27490 | exprtk_error_location)); 27491 | 27492 | return error_node(); 27493 | } 27494 | } 27495 | 27496 | const expression_node_ptr result = expression_generator_.vararg_function(opt_type,arg_list); 27497 | 27498 | sdd.delete_ptr = (0 == result); 27499 | return result; 27500 | } 27501 | 27502 | #ifndef exprtk_disable_string_capabilities 27503 | inline expression_node_ptr parse_string_range_statement(expression_node_ptr& expression) 27504 | { 27505 | if (!token_is(token_t::e_lsqrbracket)) 27506 | { 27507 | set_error(make_error( 27508 | parser_error::e_syntax, 27509 | current_token(), 27510 | "ERR108 - Expected '[' as start of string range definition", 27511 | exprtk_error_location)); 27512 | 27513 | free_node(node_allocator_, expression); 27514 | 27515 | return error_node(); 27516 | } 27517 | else if (token_is(token_t::e_rsqrbracket)) 27518 | { 27519 | return node_allocator_.allocate<details::string_size_node<T> >(expression); 27520 | } 27521 | 27522 | range_t rp; 27523 | 27524 | if (!parse_range(rp,true)) 27525 | { 27526 | free_node(node_allocator_, expression); 27527 | 27528 | return error_node(); 27529 | } 27530 | 27531 | expression_node_ptr result = expression_generator_(expression,rp); 27532 | 27533 | if (0 == result) 27534 | { 27535 | set_error(make_error( 27536 | parser_error::e_syntax, 27537 | current_token(), 27538 | "ERR109 - Failed to generate string range node", 27539 | exprtk_error_location)); 27540 | 27541 | free_node(node_allocator_, expression); 27542 | rp.free(); 27543 | } 27544 | 27545 | rp.clear(); 27546 | 27547 | if (result && result->valid()) 27548 | { 27549 | return result; 27550 | } 27551 | 27552 | set_error(make_error( 27553 | parser_error::e_synthesis, 27554 | current_token(), 27555 | "ERR110 - Failed to synthesize node: string_range_node", 27556 | exprtk_error_location)); 27557 | 27558 | free_node(node_allocator_, result); 27559 | rp.free(); 27560 | return error_node(); 27561 | } 27562 | #else 27563 | inline expression_node_ptr parse_string_range_statement(expression_node_ptr&) 27564 | { 27565 | return error_node(); 27566 | } 27567 | #endif 27568 | 27569 | inline bool parse_pending_string_rangesize(expression_node_ptr& expression) 27570 | { 27571 | // Allow no more than 100 range calls, eg: s[][][]...[][] 27572 | const std::size_t max_rangesize_parses = 100; 27573 | 27574 | std::size_t i = 0; 27575 | 27576 | while 27577 | ( 27578 | (0 != expression) && 27579 | (i++ < max_rangesize_parses) && 27580 | error_list_.empty() && 27581 | is_generally_string_node(expression) && 27582 | token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold) 27583 | ) 27584 | { 27585 | expression = parse_string_range_statement(expression); 27586 | } 27587 | 27588 | return (i > 1); 27589 | } 27590 | 27591 | inline void parse_pending_vector_index_operator(expression_node_ptr& expression) 27592 | { 27593 | if 27594 | ( 27595 | (0 != expression) && 27596 | error_list_.empty() && 27597 | is_ivector_node(expression) 27598 | ) 27599 | { 27600 | if ( 27601 | settings_.commutative_check_enabled() && 27602 | token_is(token_t::e_mul,prsrhlpr_t::e_hold) && 27603 | peek_token_is(token_t::e_lsqrbracket) 27604 | ) 27605 | { 27606 | token_is(token_t::e_mul); 27607 | token_is(token_t::e_lsqrbracket); 27608 | } 27609 | else if (token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold)) 27610 | { 27611 | token_is(token_t::e_lsqrbracket); 27612 | } 27613 | else if ( 27614 | token_is(token_t::e_rbracket,prsrhlpr_t::e_hold) && 27615 | peek_token_is(token_t::e_lsqrbracket) 27616 | ) 27617 | { 27618 | token_is(token_t::e_rbracket ); 27619 | token_is(token_t::e_lsqrbracket); 27620 | } 27621 | else 27622 | return; 27623 | 27624 | details::vector_interface<T>* vi = dynamic_cast<details::vector_interface<T>*>(expression); 27625 | 27626 | if (vi) 27627 | { 27628 | details::vector_holder<T>& vec = vi->vec()->vec_holder(); 27629 | const std::string vector_name = sem_.get_vector_name(vec.data()); 27630 | expression_node_ptr index = parse_vector_index(vector_name); 27631 | 27632 | if (index) 27633 | { 27634 | expression = synthesize_vector_element(vector_name, &vec, expression, index); 27635 | return; 27636 | } 27637 | } 27638 | 27639 | free_node(node_allocator_, expression); 27640 | expression = error_node(); 27641 | } 27642 | } 27643 | 27644 | template <typename Allocator1, 27645 | typename Allocator2, 27646 | template <typename, typename> class Sequence> 27647 | inline expression_node_ptr simplify(Sequence<expression_node_ptr,Allocator1>& expression_list, 27648 | Sequence<bool,Allocator2>& side_effect_list, 27649 | const bool specialise_on_final_type = false) 27650 | { 27651 | if (expression_list.empty()) 27652 | return error_node(); 27653 | else if (1 == expression_list.size()) 27654 | return expression_list[0]; 27655 | 27656 | Sequence<expression_node_ptr,Allocator1> tmp_expression_list; 27657 | 27658 | exprtk_debug(("simplify() - expression_list.size: %d side_effect_list.size(): %d\n", 27659 | static_cast<int>(expression_list .size()), 27660 | static_cast<int>(side_effect_list.size()))); 27661 | 27662 | bool return_node_present = false; 27663 | 27664 | for (std::size_t i = 0; i < (expression_list.size() - 1); ++i) 27665 | { 27666 | if (is_variable_node(expression_list[i])) 27667 | continue; 27668 | else if ( 27669 | is_return_node (expression_list[i]) || 27670 | is_break_node (expression_list[i]) || 27671 | is_continue_node(expression_list[i]) 27672 | ) 27673 | { 27674 | tmp_expression_list.push_back(expression_list[i]); 27675 | 27676 | // Remove all subexpressions after first short-circuit 27677 | // node has been encountered. 27678 | 27679 | for (std::size_t j = i + 1; j < expression_list.size(); ++j) 27680 | { 27681 | free_node(node_allocator_, expression_list[j]); 27682 | } 27683 | 27684 | return_node_present = true; 27685 | 27686 | break; 27687 | } 27688 | else if ( 27689 | is_constant_node(expression_list[i]) || 27690 | is_null_node (expression_list[i]) || 27691 | !side_effect_list[i] 27692 | ) 27693 | { 27694 | free_node(node_allocator_, expression_list[i]); 27695 | continue; 27696 | } 27697 | else 27698 | tmp_expression_list.push_back(expression_list[i]); 27699 | } 27700 | 27701 | if (!return_node_present) 27702 | { 27703 | tmp_expression_list.push_back(expression_list.back()); 27704 | } 27705 | 27706 | expression_list.swap(tmp_expression_list); 27707 | 27708 | if (tmp_expression_list.size() > expression_list.size()) 27709 | { 27710 | exprtk_debug(("simplify() - Reduced subexpressions from %d to %d\n", 27711 | static_cast<int>(tmp_expression_list.size()), 27712 | static_cast<int>(expression_list .size()))); 27713 | } 27714 | 27715 | if ( 27716 | return_node_present || 27717 | side_effect_list.back() || 27718 | (expression_list.size() > 1) 27719 | ) 27720 | state_.activate_side_effect("simplify()"); 27721 | 27722 | if (1 == expression_list.size()) 27723 | return expression_list[0]; 27724 | else if (specialise_on_final_type && is_generally_string_node(expression_list.back())) 27725 | return expression_generator_.vararg_function(details::e_smulti,expression_list); 27726 | else 27727 | return expression_generator_.vararg_function(details::e_multi,expression_list); 27728 | } 27729 | 27730 | inline expression_node_ptr parse_multi_sequence(const std::string& source = "", 27731 | const bool enforce_crlbrackets = false) 27732 | { 27733 | token_t::token_type open_bracket = token_t::e_lcrlbracket; 27734 | token_t::token_type close_bracket = token_t::e_rcrlbracket; 27735 | token_t::token_type separator = token_t::e_eof; 27736 | 27737 | if (!token_is(open_bracket)) 27738 | { 27739 | if (!enforce_crlbrackets && token_is(token_t::e_lbracket)) 27740 | { 27741 | open_bracket = token_t::e_lbracket; 27742 | close_bracket = token_t::e_rbracket; 27743 | separator = token_t::e_comma; 27744 | } 27745 | else 27746 | { 27747 | set_error(make_error( 27748 | parser_error::e_syntax, 27749 | current_token(), 27750 | "ERR111 - Expected '" + token_t::to_str(open_bracket) + "' for call to multi-sequence" + 27751 | ((!source.empty()) ? std::string(" section of " + source): ""), 27752 | exprtk_error_location)); 27753 | 27754 | return error_node(); 27755 | } 27756 | } 27757 | else if (token_is(close_bracket)) 27758 | { 27759 | return node_allocator_.allocate<details::null_node<T> >(); 27760 | } 27761 | 27762 | std::vector<expression_node_ptr> arg_list; 27763 | std::vector<bool> side_effect_list; 27764 | 27765 | scoped_vec_delete<expression_node_t> sdd((*this),arg_list); 27766 | 27767 | scope_handler sh(*this); 27768 | 27769 | scoped_bool_or_restorer sbr(state_.side_effect_present); 27770 | 27771 | for ( ; ; ) 27772 | { 27773 | state_.side_effect_present = false; 27774 | 27775 | expression_node_ptr arg = parse_expression(); 27776 | 27777 | if (0 == arg) 27778 | return error_node(); 27779 | else 27780 | { 27781 | arg_list.push_back(arg); 27782 | side_effect_list.push_back(state_.side_effect_present); 27783 | } 27784 | 27785 | if (token_is(close_bracket)) 27786 | break; 27787 | 27788 | const bool is_next_close = peek_token_is(close_bracket); 27789 | 27790 | if (!token_is(separator) && is_next_close) 27791 | { 27792 | set_error(make_error( 27793 | parser_error::e_syntax, 27794 | current_token(), 27795 | "ERR112 - Expected '" + lexer::token::seperator_to_str(separator) + "' for call to multi-sequence section of " + source, 27796 | exprtk_error_location)); 27797 | 27798 | return error_node(); 27799 | } 27800 | 27801 | if (token_is(close_bracket)) 27802 | break; 27803 | } 27804 | 27805 | expression_node_ptr result = simplify(arg_list, side_effect_list, source.empty()); 27806 | 27807 | sdd.delete_ptr = (0 == result); 27808 | return result; 27809 | } 27810 | 27811 | inline bool parse_range(range_t& rp, const bool skip_lsqr = false) 27812 | { 27813 | // Examples of valid ranges: 27814 | // 1. [1:5] -> [1,5) 27815 | // 2. [ :5] -> [0,5) 27816 | // 3. [1: ] -> [1,end) 27817 | // 4. [x:y] -> [x,y) where x <= y 27818 | // 5. [x+1:y/2] -> [x+1,y/2) where x+1 <= y/2 27819 | // 6. [ :y] -> [0,y) where 0 <= y 27820 | // 7. [x: ] -> [x,end) where x <= end 27821 | 27822 | rp.clear(); 27823 | 27824 | if (!skip_lsqr && !token_is(token_t::e_lsqrbracket)) 27825 | { 27826 | set_error(make_error( 27827 | parser_error::e_syntax, 27828 | current_token(), 27829 | "ERR113 - Expected '[' for start of range", 27830 | exprtk_error_location)); 27831 | 27832 | return false; 27833 | } 27834 | 27835 | if (token_is(token_t::e_colon)) 27836 | { 27837 | rp.n0_c.first = true; 27838 | rp.n0_c.second = 0; 27839 | rp.cache.first = 0; 27840 | } 27841 | else 27842 | { 27843 | expression_node_ptr r0 = parse_expression(); 27844 | 27845 | if (0 == r0) 27846 | { 27847 | set_error(make_error( 27848 | parser_error::e_syntax, 27849 | current_token(), 27850 | "ERR114 - Failed parse begin section of range", 27851 | exprtk_error_location)); 27852 | 27853 | return false; 27854 | } 27855 | else if (is_constant_node(r0)) 27856 | { 27857 | const T r0_value = r0->value(); 27858 | 27859 | if (r0_value >= T(0)) 27860 | { 27861 | rp.n0_c.first = true; 27862 | rp.n0_c.second = static_cast<std::size_t>(details::numeric::to_int64(r0_value)); 27863 | rp.cache.first = rp.n0_c.second; 27864 | } 27865 | 27866 | free_node(node_allocator_, r0); 27867 | 27868 | if (r0_value < T(0)) 27869 | { 27870 | set_error(make_error( 27871 | parser_error::e_syntax, 27872 | current_token(), 27873 | "ERR115 - Range lower bound less than zero! Constraint: r0 >= 0", 27874 | exprtk_error_location)); 27875 | 27876 | return false; 27877 | } 27878 | } 27879 | else 27880 | { 27881 | rp.n0_e.first = true; 27882 | rp.n0_e.second = r0; 27883 | } 27884 | 27885 | if (!token_is(token_t::e_colon)) 27886 | { 27887 | set_error(make_error( 27888 | parser_error::e_syntax, 27889 | current_token(), 27890 | "ERR116 - Expected ':' for break in range", 27891 | exprtk_error_location)); 27892 | 27893 | rp.free(); 27894 | 27895 | return false; 27896 | } 27897 | } 27898 | 27899 | if (token_is(token_t::e_rsqrbracket)) 27900 | { 27901 | rp.n1_c.first = true; 27902 | rp.n1_c.second = std::numeric_limits<std::size_t>::max(); 27903 | } 27904 | else 27905 | { 27906 | expression_node_ptr r1 = parse_expression(); 27907 | 27908 | if (0 == r1) 27909 | { 27910 | set_error(make_error( 27911 | parser_error::e_syntax, 27912 | current_token(), 27913 | "ERR117 - Failed parse end section of range", 27914 | exprtk_error_location)); 27915 | 27916 | rp.free(); 27917 | 27918 | return false; 27919 | } 27920 | else if (is_constant_node(r1)) 27921 | { 27922 | const T r1_value = r1->value(); 27923 | 27924 | if (r1_value >= T(0)) 27925 | { 27926 | rp.n1_c.first = true; 27927 | rp.n1_c.second = static_cast<std::size_t>(details::numeric::to_int64(r1_value)); 27928 | rp.cache.second = rp.n1_c.second; 27929 | } 27930 | 27931 | free_node(node_allocator_, r1); 27932 | 27933 | if (r1_value < T(0)) 27934 | { 27935 | set_error(make_error( 27936 | parser_error::e_syntax, 27937 | current_token(), 27938 | "ERR118 - Range upper bound less than zero! Constraint: r1 >= 0", 27939 | exprtk_error_location)); 27940 | 27941 | rp.free(); 27942 | 27943 | return false; 27944 | } 27945 | } 27946 | else 27947 | { 27948 | rp.n1_e.first = true; 27949 | rp.n1_e.second = r1; 27950 | } 27951 | 27952 | if (!token_is(token_t::e_rsqrbracket)) 27953 | { 27954 | set_error(make_error( 27955 | parser_error::e_syntax, 27956 | current_token(), 27957 | "ERR119 - Expected ']' for start of range", 27958 | exprtk_error_location)); 27959 | 27960 | rp.free(); 27961 | 27962 | return false; 27963 | } 27964 | } 27965 | 27966 | if (rp.const_range()) 27967 | { 27968 | std::size_t r0 = 0; 27969 | std::size_t r1 = 0; 27970 | 27971 | bool rp_result = false; 27972 | 27973 | try 27974 | { 27975 | rp_result = rp(r0, r1); 27976 | } 27977 | catch (std::runtime_error&) 27978 | {} 27979 | 27980 | if (!rp_result || (r0 > r1)) 27981 | { 27982 | set_error(make_error( 27983 | parser_error::e_syntax, 27984 | current_token(), 27985 | "ERR120 - Invalid range, Constraint: r0 <= r1", 27986 | exprtk_error_location)); 27987 | 27988 | return false; 27989 | } 27990 | } 27991 | 27992 | return true; 27993 | } 27994 | 27995 | inline void lodge_symbol(const std::string& symbol, 27996 | const symbol_type st) 27997 | { 27998 | dec_.add_symbol(symbol,st); 27999 | } 28000 | 28001 | #ifndef exprtk_disable_string_capabilities 28002 | inline expression_node_ptr parse_string() 28003 | { 28004 | const std::string symbol = current_token().value; 28005 | 28006 | typedef details::stringvar_node<T>* strvar_node_t; 28007 | 28008 | expression_node_ptr result = error_node(); 28009 | strvar_node_t const_str_node = static_cast<strvar_node_t>(0); 28010 | 28011 | scope_element& se = sem_.get_active_element(symbol); 28012 | 28013 | if (scope_element::e_string == se.type) 28014 | { 28015 | se.active = true; 28016 | result = se.str_node; 28017 | lodge_symbol(symbol, e_st_local_string); 28018 | } 28019 | else 28020 | { 28021 | typedef typename symtab_store::string_context str_ctxt_t; 28022 | str_ctxt_t str_ctx = symtab_store_.get_string_context(symbol); 28023 | 28024 | if ((0 == str_ctx.str_var) || !symtab_store_.is_conststr_stringvar(symbol)) 28025 | { 28026 | set_error(make_error( 28027 | parser_error::e_syntax, 28028 | current_token(), 28029 | "ERR121 - Unknown string symbol", 28030 | exprtk_error_location)); 28031 | 28032 | return error_node(); 28033 | } 28034 | 28035 | assert(str_ctx.str_var != 0); 28036 | assert(str_ctx.symbol_table != 0); 28037 | 28038 | result = str_ctx.str_var; 28039 | 28040 | if (symtab_store_.is_constant_string(symbol)) 28041 | { 28042 | const_str_node = static_cast<strvar_node_t>(result); 28043 | result = expression_generator_(const_str_node->str()); 28044 | } 28045 | else if (symbol_table_t::e_immutable == str_ctx.symbol_table->mutability()) 28046 | { 28047 | lodge_immutable_symbol( 28048 | current_token(), 28049 | make_memory_range(str_ctx.str_var->base(), str_ctx.str_var->size())); 28050 | } 28051 | 28052 | lodge_symbol(symbol, e_st_string); 28053 | } 28054 | 28055 | if (peek_token_is(token_t::e_lsqrbracket)) 28056 | { 28057 | next_token(); 28058 | 28059 | if (peek_token_is(token_t::e_rsqrbracket)) 28060 | { 28061 | next_token(); 28062 | next_token(); 28063 | 28064 | if (const_str_node) 28065 | { 28066 | free_node(node_allocator_, result); 28067 | 28068 | return expression_generator_(T(const_str_node->size())); 28069 | } 28070 | else 28071 | return node_allocator_.allocate<details::stringvar_size_node<T> > 28072 | (static_cast<details::stringvar_node<T>*>(result)->ref()); 28073 | } 28074 | 28075 | range_t rp; 28076 | 28077 | if (!parse_range(rp)) 28078 | { 28079 | free_node(node_allocator_, result); 28080 | 28081 | return error_node(); 28082 | } 28083 | else if (const_str_node) 28084 | { 28085 | free_node(node_allocator_, result); 28086 | result = expression_generator_(const_str_node->ref(),rp); 28087 | } 28088 | else 28089 | result = expression_generator_(static_cast<details::stringvar_node<T>*> 28090 | (result)->ref(), rp); 28091 | 28092 | if (result) 28093 | rp.clear(); 28094 | } 28095 | else 28096 | next_token(); 28097 | 28098 | return result; 28099 | } 28100 | #else 28101 | inline expression_node_ptr parse_string() 28102 | { 28103 | return error_node(); 28104 | } 28105 | #endif 28106 | 28107 | #ifndef exprtk_disable_string_capabilities 28108 | inline expression_node_ptr parse_const_string() 28109 | { 28110 | const std::string const_str = current_token().value; 28111 | expression_node_ptr result = expression_generator_(const_str); 28112 | 28113 | if (peek_token_is(token_t::e_lsqrbracket)) 28114 | { 28115 | next_token(); 28116 | 28117 | if (peek_token_is(token_t::e_rsqrbracket)) 28118 | { 28119 | next_token(); 28120 | next_token(); 28121 | 28122 | free_node(node_allocator_, result); 28123 | 28124 | return expression_generator_(T(const_str.size())); 28125 | } 28126 | 28127 | range_t rp; 28128 | 28129 | if (!parse_range(rp)) 28130 | { 28131 | free_node(node_allocator_, result); 28132 | rp.free(); 28133 | 28134 | return error_node(); 28135 | } 28136 | 28137 | free_node(node_allocator_, result); 28138 | 28139 | if (rp.n1_c.first && (rp.n1_c.second == std::numeric_limits<std::size_t>::max())) 28140 | { 28141 | rp.n1_c.second = const_str.size() - 1; 28142 | rp.cache.second = rp.n1_c.second; 28143 | } 28144 | 28145 | if ( 28146 | (rp.n0_c.first && (rp.n0_c.second >= const_str.size())) || 28147 | (rp.n1_c.first && (rp.n1_c.second >= const_str.size())) 28148 | ) 28149 | { 28150 | set_error(make_error( 28151 | parser_error::e_syntax, 28152 | current_token(), 28153 | "ERR122 - Overflow in range for string: '" + const_str + "'[" + 28154 | (rp.n0_c.first ? details::to_str(static_cast<int>(rp.n0_c.second)) : "?") + ":" + 28155 | (rp.n1_c.first ? details::to_str(static_cast<int>(rp.n1_c.second)) : "?") + "]", 28156 | exprtk_error_location)); 28157 | 28158 | rp.free(); 28159 | 28160 | return error_node(); 28161 | } 28162 | 28163 | result = expression_generator_(const_str,rp); 28164 | 28165 | if (result) 28166 | rp.clear(); 28167 | } 28168 | else 28169 | next_token(); 28170 | 28171 | return result; 28172 | } 28173 | #else 28174 | inline expression_node_ptr parse_const_string() 28175 | { 28176 | return error_node(); 28177 | } 28178 | #endif 28179 | 28180 | inline expression_node_ptr parse_vector_index(const std::string& vector_name = "") 28181 | { 28182 | expression_node_ptr index_expr = error_node(); 28183 | 28184 | if (0 == (index_expr = parse_expression())) 28185 | { 28186 | set_error(make_error( 28187 | parser_error::e_syntax, 28188 | current_token(), 28189 | "ERR123 - Failed to parse index for vector: '" + vector_name + "'", 28190 | exprtk_error_location)); 28191 | 28192 | return error_node(); 28193 | } 28194 | else if (!token_is(token_t::e_rsqrbracket)) 28195 | { 28196 | set_error(make_error( 28197 | parser_error::e_syntax, 28198 | current_token(), 28199 | "ERR124 - Expected ']' for index of vector: '" + vector_name + "'", 28200 | exprtk_error_location)); 28201 | 28202 | free_node(node_allocator_, index_expr); 28203 | 28204 | return error_node(); 28205 | } 28206 | 28207 | return index_expr; 28208 | } 28209 | 28210 | inline expression_node_ptr parse_vector() 28211 | { 28212 | const std::string vector_name = current_token().value; 28213 | 28214 | vector_holder_ptr vec = vector_holder_ptr(0); 28215 | 28216 | const scope_element& se = sem_.get_active_element(vector_name); 28217 | 28218 | if ( 28219 | !details::imatch(se.name, vector_name) || 28220 | (se.depth > state_.scope_depth) || 28221 | (scope_element::e_vector != se.type) 28222 | ) 28223 | { 28224 | typedef typename symtab_store::vector_context vec_ctxt_t; 28225 | vec_ctxt_t vec_ctx = symtab_store_.get_vector_context(vector_name); 28226 | 28227 | if (0 == vec_ctx.vector_holder) 28228 | { 28229 | set_error(make_error( 28230 | parser_error::e_syntax, 28231 | current_token(), 28232 | "ERR125 - Symbol '" + vector_name + " not a vector", 28233 | exprtk_error_location)); 28234 | 28235 | return error_node(); 28236 | } 28237 | 28238 | assert(0 != vec_ctx.vector_holder); 28239 | assert(0 != vec_ctx.symbol_table ); 28240 | 28241 | vec = vec_ctx.vector_holder; 28242 | 28243 | if (symbol_table_t::e_immutable == vec_ctx.symbol_table->mutability()) 28244 | { 28245 | lodge_immutable_symbol( 28246 | current_token(), 28247 | make_memory_range(vec->data(), vec->size())); 28248 | } 28249 | } 28250 | else 28251 | { 28252 | vec = se.vec_node; 28253 | } 28254 | 28255 | assert(0 != vec); 28256 | 28257 | next_token(); 28258 | 28259 | if (!token_is(token_t::e_lsqrbracket)) 28260 | { 28261 | return node_allocator_.allocate<vector_node_t>(vec); 28262 | } 28263 | else if (token_is(token_t::e_rsqrbracket)) 28264 | { 28265 | return (vec->rebaseable()) ? 28266 | node_allocator_.allocate<vector_size_node_t>(vec) : 28267 | expression_generator_(T(vec->size())); 28268 | } 28269 | 28270 | expression_node_ptr index_expr = parse_vector_index(vector_name); 28271 | 28272 | if (index_expr) 28273 | { 28274 | expression_node_ptr vec_node = node_allocator_.allocate<vector_node_t>(vec); 28275 | 28276 | return synthesize_vector_element(vector_name, vec, vec_node, index_expr); 28277 | } 28278 | 28279 | return error_node(); 28280 | } 28281 | 28282 | inline expression_node_ptr synthesize_vector_element(const std::string& vector_name, 28283 | vector_holder_ptr vec, 28284 | expression_node_ptr vec_node, 28285 | expression_node_ptr index_expr) 28286 | { 28287 | // Perform compile-time range check 28288 | if (details::is_constant_node(index_expr)) 28289 | { 28290 | const std::size_t index = static_cast<std::size_t>(details::numeric::to_int32(index_expr->value())); 28291 | const std::size_t vec_size = vec->size(); 28292 | 28293 | if (index >= vec_size) 28294 | { 28295 | set_error(make_error( 28296 | parser_error::e_syntax, 28297 | current_token(), 28298 | "ERR126 - Index of " + details::to_str(index) + " out of range for " 28299 | "vector '" + vector_name + "' of size " + details::to_str(vec_size), 28300 | exprtk_error_location)); 28301 | 28302 | free_node(node_allocator_, vec_node ); 28303 | free_node(node_allocator_, index_expr); 28304 | 28305 | return error_node(); 28306 | } 28307 | } 28308 | 28309 | return expression_generator_.vector_element(vector_name, vec, vec_node, index_expr); 28310 | } 28311 | 28312 | inline expression_node_ptr parse_vararg_function_call(ivararg_function<T>* vararg_function, const std::string& vararg_function_name) 28313 | { 28314 | std::vector<expression_node_ptr> arg_list; 28315 | 28316 | scoped_vec_delete<expression_node_t> sdd((*this),arg_list); 28317 | 28318 | next_token(); 28319 | 28320 | if (token_is(token_t::e_lbracket)) 28321 | { 28322 | if (token_is(token_t::e_rbracket)) 28323 | { 28324 | if (!vararg_function->allow_zero_parameters()) 28325 | { 28326 | set_error(make_error( 28327 | parser_error::e_syntax, 28328 | current_token(), 28329 | "ERR127 - Zero parameter call to vararg function: " 28330 | + vararg_function_name + " not allowed", 28331 | exprtk_error_location)); 28332 | 28333 | return error_node(); 28334 | } 28335 | } 28336 | else 28337 | { 28338 | for ( ; ; ) 28339 | { 28340 | expression_node_ptr arg = parse_expression(); 28341 | 28342 | if (0 == arg) 28343 | return error_node(); 28344 | else 28345 | arg_list.push_back(arg); 28346 | 28347 | if (token_is(token_t::e_rbracket)) 28348 | break; 28349 | else if (!token_is(token_t::e_comma)) 28350 | { 28351 | set_error(make_error( 28352 | parser_error::e_syntax, 28353 | current_token(), 28354 | "ERR128 - Expected ',' for call to vararg function: " 28355 | + vararg_function_name, 28356 | exprtk_error_location)); 28357 | 28358 | return error_node(); 28359 | } 28360 | } 28361 | } 28362 | } 28363 | else if (!vararg_function->allow_zero_parameters()) 28364 | { 28365 | set_error(make_error( 28366 | parser_error::e_syntax, 28367 | current_token(), 28368 | "ERR129 - Zero parameter call to vararg function: " 28369 | + vararg_function_name + " not allowed", 28370 | exprtk_error_location)); 28371 | 28372 | return error_node(); 28373 | } 28374 | 28375 | if (arg_list.size() < vararg_function->min_num_args()) 28376 | { 28377 | set_error(make_error( 28378 | parser_error::e_syntax, 28379 | current_token(), 28380 | "ERR130 - Invalid number of parameters to call to vararg function: " 28381 | + vararg_function_name + ", require at least " 28382 | + details::to_str(static_cast<int>(vararg_function->min_num_args())) + " parameters", 28383 | exprtk_error_location)); 28384 | 28385 | return error_node(); 28386 | } 28387 | else if (arg_list.size() > vararg_function->max_num_args()) 28388 | { 28389 | set_error(make_error( 28390 | parser_error::e_syntax, 28391 | current_token(), 28392 | "ERR131 - Invalid number of parameters to call to vararg function: " 28393 | + vararg_function_name + ", require no more than " 28394 | + details::to_str(static_cast<int>(vararg_function->max_num_args())) + " parameters", 28395 | exprtk_error_location)); 28396 | 28397 | return error_node(); 28398 | } 28399 | 28400 | expression_node_ptr result = expression_generator_.vararg_function_call(vararg_function,arg_list); 28401 | 28402 | sdd.delete_ptr = (0 == result); 28403 | 28404 | return result; 28405 | } 28406 | 28407 | class type_checker 28408 | { 28409 | public: 28410 | 28411 | enum return_type_t 28412 | { 28413 | e_overload = ' ', 28414 | e_numeric = 'T', 28415 | e_string = 'S' 28416 | }; 28417 | 28418 | struct function_prototype_t 28419 | { 28420 | return_type_t return_type; 28421 | std::string param_seq; 28422 | }; 28423 | 28424 | typedef parser<T> parser_t; 28425 | typedef std::vector<function_prototype_t> function_definition_list_t; 28426 | 28427 | type_checker(parser_t& p, 28428 | const std::string& func_name, 28429 | const std::string& func_prototypes, 28430 | const return_type_t default_return_type) 28431 | : invalid_state_(true) 28432 | , parser_(p) 28433 | , function_name_(func_name) 28434 | , default_return_type_(default_return_type) 28435 | { 28436 | parse_function_prototypes(func_prototypes); 28437 | } 28438 | 28439 | bool verify(const std::string& param_seq, std::size_t& pseq_index) 28440 | { 28441 | if (function_definition_list_.empty()) 28442 | return true; 28443 | 28444 | std::vector<std::pair<std::size_t,char> > error_list; 28445 | 28446 | for (std::size_t i = 0; i < function_definition_list_.size(); ++i) 28447 | { 28448 | details::char_t diff_value = 0; 28449 | std::size_t diff_index = 0; 28450 | 28451 | const bool result = details::sequence_match(function_definition_list_[i].param_seq, 28452 | param_seq, 28453 | diff_index, diff_value); 28454 | 28455 | if (result) 28456 | { 28457 | pseq_index = i; 28458 | return true; 28459 | } 28460 | else 28461 | error_list.push_back(std::make_pair(diff_index, diff_value)); 28462 | } 28463 | 28464 | if (1 == error_list.size()) 28465 | { 28466 | parser_.set_error(make_error( 28467 | parser_error::e_syntax, 28468 | parser_.current_token(), 28469 | "ERR132 - Failed parameter type check for function '" + function_name_ + "', " 28470 | "Expected '" + function_definition_list_[0].param_seq + 28471 | "' call set: '" + param_seq + "'", 28472 | exprtk_error_location)); 28473 | } 28474 | else 28475 | { 28476 | // find first with largest diff_index; 28477 | std::size_t max_diff_index = 0; 28478 | 28479 | for (std::size_t i = 1; i < error_list.size(); ++i) 28480 | { 28481 | if (error_list[i].first > error_list[max_diff_index].first) 28482 | { 28483 | max_diff_index = i; 28484 | } 28485 | } 28486 | 28487 | parser_.set_error(make_error( 28488 | parser_error::e_syntax, 28489 | parser_.current_token(), 28490 | "ERR133 - Failed parameter type check for function '" + function_name_ + "', " 28491 | "Best match: '" + function_definition_list_[max_diff_index].param_seq + 28492 | "' call set: '" + param_seq + "'", 28493 | exprtk_error_location)); 28494 | } 28495 | 28496 | return false; 28497 | } 28498 | 28499 | std::size_t paramseq_count() const 28500 | { 28501 | return function_definition_list_.size(); 28502 | } 28503 | 28504 | std::string paramseq(const std::size_t& index) const 28505 | { 28506 | return function_definition_list_[index].param_seq; 28507 | } 28508 | 28509 | return_type_t return_type(const std::size_t& index) const 28510 | { 28511 | return function_definition_list_[index].return_type; 28512 | } 28513 | 28514 | bool invalid() const 28515 | { 28516 | return !invalid_state_; 28517 | } 28518 | 28519 | bool allow_zero_parameters() const 28520 | { 28521 | 28522 | for (std::size_t i = 0; i < function_definition_list_.size(); ++i) 28523 | { 28524 | if (std::string::npos != function_definition_list_[i].param_seq.find("Z")) 28525 | { 28526 | return true; 28527 | } 28528 | } 28529 | 28530 | return false; 28531 | } 28532 | 28533 | private: 28534 | 28535 | std::vector<std::string> split_param_seq(const std::string& param_seq, const details::char_t delimiter = '|') const 28536 | { 28537 | std::string::const_iterator current_begin = param_seq.begin(); 28538 | std::string::const_iterator iter = param_seq.begin(); 28539 | 28540 | std::vector<std::string> result; 28541 | 28542 | while (iter != param_seq.end()) 28543 | { 28544 | if (*iter == delimiter) 28545 | { 28546 | result.push_back(std::string(current_begin, iter)); 28547 | current_begin = ++iter; 28548 | } 28549 | else 28550 | ++iter; 28551 | } 28552 | 28553 | if (current_begin != iter) 28554 | { 28555 | result.push_back(std::string(current_begin, iter)); 28556 | } 28557 | 28558 | return result; 28559 | } 28560 | 28561 | inline bool is_valid_token(std::string param_seq, 28562 | function_prototype_t& funcproto) const 28563 | { 28564 | // Determine return type 28565 | funcproto.return_type = default_return_type_; 28566 | 28567 | if (param_seq.size() > 2) 28568 | { 28569 | if (':' == param_seq[1]) 28570 | { 28571 | // Note: Only overloaded igeneric functions can have return 28572 | // type definitions. 28573 | if (type_checker::e_overload != default_return_type_) 28574 | return false; 28575 | 28576 | switch (param_seq[0]) 28577 | { 28578 | case 'T' : funcproto.return_type = type_checker::e_numeric; 28579 | break; 28580 | 28581 | case 'S' : funcproto.return_type = type_checker::e_string; 28582 | break; 28583 | 28584 | default : return false; 28585 | } 28586 | 28587 | param_seq.erase(0,2); 28588 | } 28589 | } 28590 | 28591 | if ( 28592 | (std::string::npos != param_seq.find("?*")) || 28593 | (std::string::npos != param_seq.find("**")) 28594 | ) 28595 | { 28596 | return false; 28597 | } 28598 | else if ( 28599 | (std::string::npos == param_seq.find_first_not_of("STV*?|")) || 28600 | ("Z" == param_seq) 28601 | ) 28602 | { 28603 | funcproto.param_seq = param_seq; 28604 | return true; 28605 | } 28606 | 28607 | return false; 28608 | } 28609 | 28610 | void parse_function_prototypes(const std::string& func_prototypes) 28611 | { 28612 | if (func_prototypes.empty()) 28613 | return; 28614 | 28615 | std::vector<std::string> param_seq_list = split_param_seq(func_prototypes); 28616 | 28617 | typedef std::map<std::string,std::size_t> param_seq_map_t; 28618 | param_seq_map_t param_seq_map; 28619 | 28620 | for (std::size_t i = 0; i < param_seq_list.size(); ++i) 28621 | { 28622 | function_prototype_t func_proto; 28623 | 28624 | if (!is_valid_token(param_seq_list[i], func_proto)) 28625 | { 28626 | invalid_state_ = false; 28627 | 28628 | parser_.set_error(make_error( 28629 | parser_error::e_syntax, 28630 | parser_.current_token(), 28631 | "ERR134 - Invalid parameter sequence of '" + param_seq_list[i] + 28632 | "' for function: " + function_name_, 28633 | exprtk_error_location)); 28634 | return; 28635 | } 28636 | 28637 | param_seq_map_t::const_iterator seq_itr = param_seq_map.find(param_seq_list[i]); 28638 | 28639 | if (param_seq_map.end() != seq_itr) 28640 | { 28641 | invalid_state_ = false; 28642 | 28643 | parser_.set_error(make_error( 28644 | parser_error::e_syntax, 28645 | parser_.current_token(), 28646 | "ERR135 - Function '" + function_name_ + "' has a parameter sequence conflict between " + 28647 | "pseq_idx[" + details::to_str(seq_itr->second) + "] and" + 28648 | "pseq_idx[" + details::to_str(i) + "] " + 28649 | "param seq: " + param_seq_list[i], 28650 | exprtk_error_location)); 28651 | return; 28652 | } 28653 | 28654 | function_definition_list_.push_back(func_proto); 28655 | } 28656 | } 28657 | 28658 | type_checker(const type_checker&) exprtk_delete; 28659 | type_checker& operator=(const type_checker&) exprtk_delete; 28660 | 28661 | bool invalid_state_; 28662 | parser_t& parser_; 28663 | std::string function_name_; 28664 | const return_type_t default_return_type_; 28665 | function_definition_list_t function_definition_list_; 28666 | }; 28667 | 28668 | inline expression_node_ptr parse_generic_function_call(igeneric_function<T>* function, const std::string& function_name) 28669 | { 28670 | std::vector<expression_node_ptr> arg_list; 28671 | 28672 | scoped_vec_delete<expression_node_t> sdd((*this),arg_list); 28673 | 28674 | next_token(); 28675 | 28676 | std::string param_type_list; 28677 | 28678 | type_checker tc( 28679 | (*this), 28680 | function_name, 28681 | function->parameter_sequence, 28682 | type_checker::e_string); 28683 | 28684 | if (tc.invalid()) 28685 | { 28686 | set_error(make_error( 28687 | parser_error::e_syntax, 28688 | current_token(), 28689 | "ERR136 - Type checker instantiation failure for generic function: " + function_name, 28690 | exprtk_error_location)); 28691 | 28692 | return error_node(); 28693 | } 28694 | 28695 | if (token_is(token_t::e_lbracket)) 28696 | { 28697 | if (token_is(token_t::e_rbracket)) 28698 | { 28699 | if ( 28700 | !function->allow_zero_parameters() && 28701 | !tc .allow_zero_parameters() 28702 | ) 28703 | { 28704 | set_error(make_error( 28705 | parser_error::e_syntax, 28706 | current_token(), 28707 | "ERR137 - Zero parameter call to generic function: " 28708 | + function_name + " not allowed", 28709 | exprtk_error_location)); 28710 | 28711 | return error_node(); 28712 | } 28713 | } 28714 | else 28715 | { 28716 | for ( ; ; ) 28717 | { 28718 | expression_node_ptr arg = parse_expression(); 28719 | 28720 | if (0 == arg) 28721 | return error_node(); 28722 | 28723 | if (is_ivector_node(arg)) 28724 | param_type_list += 'V'; 28725 | else if (is_generally_string_node(arg)) 28726 | param_type_list += 'S'; 28727 | else // Everything else is assumed to be a scalar returning expression 28728 | param_type_list += 'T'; 28729 | 28730 | arg_list.push_back(arg); 28731 | 28732 | if (token_is(token_t::e_rbracket)) 28733 | break; 28734 | else if (!token_is(token_t::e_comma)) 28735 | { 28736 | set_error(make_error( 28737 | parser_error::e_syntax, 28738 | current_token(), 28739 | "ERR138 - Expected ',' for call to generic function: " + function_name, 28740 | exprtk_error_location)); 28741 | 28742 | return error_node(); 28743 | } 28744 | } 28745 | } 28746 | } 28747 | else if ( 28748 | !function->parameter_sequence.empty() && 28749 | function->allow_zero_parameters () && 28750 | !tc .allow_zero_parameters () 28751 | ) 28752 | { 28753 | set_error(make_error( 28754 | parser_error::e_syntax, 28755 | current_token(), 28756 | "ERR139 - Zero parameter call to generic function: " 28757 | + function_name + " not allowed", 28758 | exprtk_error_location)); 28759 | 28760 | return error_node(); 28761 | } 28762 | 28763 | std::size_t param_seq_index = 0; 28764 | 28765 | if ( 28766 | state_.type_check_enabled && 28767 | !tc.verify(param_type_list, param_seq_index) 28768 | ) 28769 | { 28770 | set_error(make_error( 28771 | parser_error::e_syntax, 28772 | current_token(), 28773 | "ERR140 - Invalid input parameter sequence for call to generic function: " + function_name, 28774 | exprtk_error_location)); 28775 | 28776 | return error_node(); 28777 | } 28778 | 28779 | expression_node_ptr result = 28780 | (tc.paramseq_count() <= 1) ? 28781 | expression_generator_ 28782 | .generic_function_call(function, arg_list) : 28783 | expression_generator_ 28784 | .generic_function_call(function, arg_list, param_seq_index); 28785 | 28786 | sdd.delete_ptr = (0 == result); 28787 | 28788 | return result; 28789 | } 28790 | 28791 | inline bool parse_igeneric_function_params(std::string& param_type_list, 28792 | std::vector<expression_node_ptr>& arg_list, 28793 | const std::string& function_name, 28794 | igeneric_function<T>* function, 28795 | const type_checker& tc) 28796 | { 28797 | if (token_is(token_t::e_lbracket)) 28798 | { 28799 | if (token_is(token_t::e_rbracket)) 28800 | { 28801 | if ( 28802 | !function->allow_zero_parameters() && 28803 | !tc .allow_zero_parameters() 28804 | ) 28805 | { 28806 | set_error(make_error( 28807 | parser_error::e_syntax, 28808 | current_token(), 28809 | "ERR141 - Zero parameter call to generic function: " 28810 | + function_name + " not allowed", 28811 | exprtk_error_location)); 28812 | 28813 | return false; 28814 | } 28815 | } 28816 | else 28817 | { 28818 | for ( ; ; ) 28819 | { 28820 | expression_node_ptr arg = parse_expression(); 28821 | 28822 | if (0 == arg) 28823 | return false; 28824 | 28825 | if (is_ivector_node(arg)) 28826 | param_type_list += 'V'; 28827 | else if (is_generally_string_node(arg)) 28828 | param_type_list += 'S'; 28829 | else // Everything else is a scalar returning expression 28830 | param_type_list += 'T'; 28831 | 28832 | arg_list.push_back(arg); 28833 | 28834 | if (token_is(token_t::e_rbracket)) 28835 | break; 28836 | else if (!token_is(token_t::e_comma)) 28837 | { 28838 | set_error(make_error( 28839 | parser_error::e_syntax, 28840 | current_token(), 28841 | "ERR142 - Expected ',' for call to string function: " + function_name, 28842 | exprtk_error_location)); 28843 | 28844 | return false; 28845 | } 28846 | } 28847 | } 28848 | 28849 | return true; 28850 | } 28851 | else 28852 | return false; 28853 | } 28854 | 28855 | #ifndef exprtk_disable_string_capabilities 28856 | inline expression_node_ptr parse_string_function_call(igeneric_function<T>* function, const std::string& function_name) 28857 | { 28858 | // Move pass the function name 28859 | next_token(); 28860 | 28861 | std::string param_type_list; 28862 | 28863 | type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_string); 28864 | 28865 | if ( 28866 | (!function->parameter_sequence.empty()) && 28867 | (0 == tc.paramseq_count()) 28868 | ) 28869 | { 28870 | return error_node(); 28871 | } 28872 | 28873 | std::vector<expression_node_ptr> arg_list; 28874 | scoped_vec_delete<expression_node_t> sdd((*this),arg_list); 28875 | 28876 | if (!parse_igeneric_function_params(param_type_list, arg_list, function_name, function, tc)) 28877 | { 28878 | return error_node(); 28879 | } 28880 | 28881 | std::size_t param_seq_index = 0; 28882 | 28883 | if (!tc.verify(param_type_list, param_seq_index)) 28884 | { 28885 | set_error(make_error( 28886 | parser_error::e_syntax, 28887 | current_token(), 28888 | "ERR143 - Invalid input parameter sequence for call to string function: " + function_name, 28889 | exprtk_error_location)); 28890 | 28891 | return error_node(); 28892 | } 28893 | 28894 | expression_node_ptr result = 28895 | (tc.paramseq_count() <= 1) ? 28896 | expression_generator_ 28897 | .string_function_call(function, arg_list) : 28898 | expression_generator_ 28899 | .string_function_call(function, arg_list, param_seq_index); 28900 | 28901 | sdd.delete_ptr = (0 == result); 28902 | 28903 | return result; 28904 | } 28905 | 28906 | inline expression_node_ptr parse_overload_function_call(igeneric_function<T>* function, const std::string& function_name) 28907 | { 28908 | // Move pass the function name 28909 | next_token(); 28910 | 28911 | std::string param_type_list; 28912 | 28913 | type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_overload); 28914 | 28915 | if ( 28916 | (!function->parameter_sequence.empty()) && 28917 | (0 == tc.paramseq_count()) 28918 | ) 28919 | { 28920 | return error_node(); 28921 | } 28922 | 28923 | std::vector<expression_node_ptr> arg_list; 28924 | scoped_vec_delete<expression_node_t> sdd((*this),arg_list); 28925 | 28926 | if (!parse_igeneric_function_params(param_type_list, arg_list, function_name, function, tc)) 28927 | { 28928 | return error_node(); 28929 | } 28930 | 28931 | std::size_t param_seq_index = 0; 28932 | 28933 | if (!tc.verify(param_type_list, param_seq_index)) 28934 | { 28935 | set_error(make_error( 28936 | parser_error::e_syntax, 28937 | current_token(), 28938 | "ERR144 - Invalid input parameter sequence for call to overloaded function: " + function_name, 28939 | exprtk_error_location)); 28940 | 28941 | return error_node(); 28942 | } 28943 | 28944 | expression_node_ptr result = error_node(); 28945 | 28946 | if (type_checker::e_numeric == tc.return_type(param_seq_index)) 28947 | { 28948 | if (tc.paramseq_count() <= 1) 28949 | result = expression_generator_ 28950 | .generic_function_call(function, arg_list); 28951 | else 28952 | result = expression_generator_ 28953 | .generic_function_call(function, arg_list, param_seq_index); 28954 | } 28955 | else if (type_checker::e_string == tc.return_type(param_seq_index)) 28956 | { 28957 | if (tc.paramseq_count() <= 1) 28958 | result = expression_generator_ 28959 | .string_function_call(function, arg_list); 28960 | else 28961 | result = expression_generator_ 28962 | .string_function_call(function, arg_list, param_seq_index); 28963 | } 28964 | else 28965 | { 28966 | set_error(make_error( 28967 | parser_error::e_syntax, 28968 | current_token(), 28969 | "ERR145 - Invalid return type for call to overloaded function: " + function_name, 28970 | exprtk_error_location)); 28971 | } 28972 | 28973 | sdd.delete_ptr = (0 == result); 28974 | return result; 28975 | } 28976 | #endif 28977 | 28978 | template <typename Type, std::size_t NumberOfParameters> 28979 | struct parse_special_function_impl 28980 | { 28981 | static inline expression_node_ptr process(parser<Type>& p, const details::operator_type opt_type, const std::string& sf_name) 28982 | { 28983 | expression_node_ptr branch[NumberOfParameters]; 28984 | expression_node_ptr result = error_node(); 28985 | 28986 | std::fill_n(branch, NumberOfParameters, reinterpret_cast<expression_node_ptr>(0)); 28987 | 28988 | scoped_delete<expression_node_t,NumberOfParameters> sd(p,branch); 28989 | 28990 | p.next_token(); 28991 | 28992 | if (!p.token_is(token_t::e_lbracket)) 28993 | { 28994 | p.set_error(make_error( 28995 | parser_error::e_syntax, 28996 | p.current_token(), 28997 | "ERR146 - Expected '(' for special function '" + sf_name + "'", 28998 | exprtk_error_location)); 28999 | 29000 | return error_node(); 29001 | } 29002 | 29003 | for (std::size_t i = 0; i < NumberOfParameters; ++i) 29004 | { 29005 | branch[i] = p.parse_expression(); 29006 | 29007 | if (0 == branch[i]) 29008 | { 29009 | return p.error_node(); 29010 | } 29011 | else if (i < (NumberOfParameters - 1)) 29012 | { 29013 | if (!p.token_is(token_t::e_comma)) 29014 | { 29015 | p.set_error(make_error( 29016 | parser_error::e_syntax, 29017 | p.current_token(), 29018 | "ERR147 - Expected ',' before next parameter of special function '" + sf_name + "'", 29019 | exprtk_error_location)); 29020 | 29021 | return p.error_node(); 29022 | } 29023 | } 29024 | } 29025 | 29026 | if (!p.token_is(token_t::e_rbracket)) 29027 | { 29028 | p.set_error(make_error( 29029 | parser_error::e_syntax, 29030 | p.current_token(), 29031 | "ERR148 - Invalid number of parameters for special function '" + sf_name + "'", 29032 | exprtk_error_location)); 29033 | 29034 | return p.error_node(); 29035 | } 29036 | else 29037 | result = p.expression_generator_.special_function(opt_type,branch); 29038 | 29039 | sd.delete_ptr = (0 == result); 29040 | 29041 | return result; 29042 | } 29043 | }; 29044 | 29045 | inline expression_node_ptr parse_special_function() 29046 | { 29047 | const std::string sf_name = current_token().value; 29048 | 29049 | // Expect: $fDD(expr0,expr1,expr2) or $fDD(expr0,expr1,expr2,expr3) 29050 | if ( 29051 | !details::is_digit(sf_name[2]) || 29052 | !details::is_digit(sf_name[3]) 29053 | ) 29054 | { 29055 | set_error(make_error( 29056 | parser_error::e_token, 29057 | current_token(), 29058 | "ERR149 - Invalid special function[1]: " + sf_name, 29059 | exprtk_error_location)); 29060 | 29061 | return error_node(); 29062 | } 29063 | 29064 | const int id = (sf_name[2] - '0') * 10 + 29065 | (sf_name[3] - '0'); 29066 | 29067 | if (id >= details::e_sffinal) 29068 | { 29069 | set_error(make_error( 29070 | parser_error::e_token, 29071 | current_token(), 29072 | "ERR150 - Invalid special function[2]: " + sf_name, 29073 | exprtk_error_location)); 29074 | 29075 | return error_node(); 29076 | } 29077 | 29078 | const int sf_3_to_4 = details::e_sf48; 29079 | const details::operator_type opt_type = details::operator_type(id + 1000); 29080 | const std::size_t NumberOfParameters = (id < (sf_3_to_4 - 1000)) ? 3U : 4U; 29081 | 29082 | switch (NumberOfParameters) 29083 | { 29084 | case 3 : return parse_special_function_impl<T,3>::process((*this), opt_type, sf_name); 29085 | case 4 : return parse_special_function_impl<T,4>::process((*this), opt_type, sf_name); 29086 | default : return error_node(); 29087 | } 29088 | } 29089 | 29090 | inline expression_node_ptr parse_null_statement() 29091 | { 29092 | next_token(); 29093 | return node_allocator_.allocate<details::null_node<T> >(); 29094 | } 29095 | 29096 | #ifndef exprtk_disable_break_continue 29097 | inline expression_node_ptr parse_break_statement() 29098 | { 29099 | if (state_.parsing_break_stmt) 29100 | { 29101 | set_error(make_error( 29102 | parser_error::e_syntax, 29103 | current_token(), 29104 | "ERR151 - Invoking 'break' within a break call is not allowed", 29105 | exprtk_error_location)); 29106 | 29107 | return error_node(); 29108 | } 29109 | else if (0 == state_.parsing_loop_stmt_count) 29110 | { 29111 | set_error(make_error( 29112 | parser_error::e_syntax, 29113 | current_token(), 29114 | "ERR152 - Invalid use of 'break', allowed only in the scope of a loop", 29115 | exprtk_error_location)); 29116 | 29117 | return error_node(); 29118 | } 29119 | 29120 | scoped_bool_negator sbn(state_.parsing_break_stmt); 29121 | 29122 | if (!brkcnt_list_.empty()) 29123 | { 29124 | next_token(); 29125 | 29126 | brkcnt_list_.front() = true; 29127 | 29128 | expression_node_ptr return_expr = error_node(); 29129 | 29130 | if (token_is(token_t::e_lsqrbracket)) 29131 | { 29132 | if (0 == (return_expr = parse_expression())) 29133 | { 29134 | set_error(make_error( 29135 | parser_error::e_syntax, 29136 | current_token(), 29137 | "ERR153 - Failed to parse return expression for 'break' statement", 29138 | exprtk_error_location)); 29139 | 29140 | return error_node(); 29141 | } 29142 | else if (!token_is(token_t::e_rsqrbracket)) 29143 | { 29144 | set_error(make_error( 29145 | parser_error::e_syntax, 29146 | current_token(), 29147 | "ERR154 - Expected ']' at the completion of break's return expression", 29148 | exprtk_error_location)); 29149 | 29150 | free_node(node_allocator_, return_expr); 29151 | 29152 | return error_node(); 29153 | } 29154 | } 29155 | 29156 | state_.activate_side_effect("parse_break_statement()"); 29157 | 29158 | return node_allocator_.allocate<details::break_node<T> >(return_expr); 29159 | } 29160 | else 29161 | { 29162 | set_error(make_error( 29163 | parser_error::e_syntax, 29164 | current_token(), 29165 | "ERR155 - Invalid use of 'break', allowed only in the scope of a loop", 29166 | exprtk_error_location)); 29167 | } 29168 | 29169 | return error_node(); 29170 | } 29171 | 29172 | inline expression_node_ptr parse_continue_statement() 29173 | { 29174 | if (0 == state_.parsing_loop_stmt_count) 29175 | { 29176 | set_error(make_error( 29177 | parser_error::e_syntax, 29178 | current_token(), 29179 | "ERR156 - Invalid use of 'continue', allowed only in the scope of a loop", 29180 | exprtk_error_location)); 29181 | 29182 | return error_node(); 29183 | } 29184 | else 29185 | { 29186 | next_token(); 29187 | 29188 | brkcnt_list_.front() = true; 29189 | state_.activate_side_effect("parse_continue_statement()"); 29190 | 29191 | return node_allocator_.allocate<details::continue_node<T> >(); 29192 | } 29193 | } 29194 | #endif 29195 | 29196 | inline expression_node_ptr parse_define_vector_statement(const std::string& vec_name) 29197 | { 29198 | expression_node_ptr size_expression_node = error_node(); 29199 | 29200 | if (!token_is(token_t::e_lsqrbracket)) 29201 | { 29202 | set_error(make_error( 29203 | parser_error::e_syntax, 29204 | current_token(), 29205 | "ERR157 - Expected '[' as part of vector size definition", 29206 | exprtk_error_location)); 29207 | 29208 | return error_node(); 29209 | } 29210 | else if (0 == (size_expression_node = parse_expression())) 29211 | { 29212 | set_error(make_error( 29213 | parser_error::e_syntax, 29214 | current_token(), 29215 | "ERR158 - Failed to determine size of vector '" + vec_name + "'", 29216 | exprtk_error_location)); 29217 | 29218 | return error_node(); 29219 | } 29220 | else if (!is_constant_node(size_expression_node)) 29221 | { 29222 | const bool is_rebaseble_vector = 29223 | (size_expression_node->type() == details::expression_node<T>::e_vecsize) && 29224 | static_cast<details::vector_size_node<T>*>(size_expression_node)->vec_holder()->rebaseable(); 29225 | 29226 | free_node(node_allocator_, size_expression_node); 29227 | 29228 | const std::string error_msg = (is_rebaseble_vector) ? 29229 | std::string("Rebasable/Resizable vector cannot be used to define the size of vector") : 29230 | std::string("Expected a constant literal number as size of vector"); 29231 | set_error(make_error( 29232 | parser_error::e_syntax, 29233 | current_token(), 29234 | "ERR159 - " + error_msg + " '" + vec_name + "'", 29235 | exprtk_error_location)); 29236 | 29237 | return error_node(); 29238 | } 29239 | 29240 | const T vector_size = size_expression_node->value(); 29241 | 29242 | free_node(node_allocator_, size_expression_node); 29243 | 29244 | const std::size_t max_vector_size = settings_.max_local_vector_size(); 29245 | 29246 | if ( 29247 | (vector_size <= T(0)) || 29248 | std::not_equal_to<T>() 29249 | (T(0),vector_size - details::numeric::trunc(vector_size)) || 29250 | (static_cast<std::size_t>(vector_size) > max_vector_size) 29251 | ) 29252 | { 29253 | set_error(make_error( 29254 | parser_error::e_syntax, 29255 | current_token(), 29256 | "ERR160 - Invalid vector size. Must be an integer in the " 29257 | "range [0," + details::to_str(static_cast<std::size_t>(max_vector_size)) + "], size: " + 29258 | details::to_str(details::numeric::to_int32(vector_size)), 29259 | exprtk_error_location)); 29260 | 29261 | return error_node(); 29262 | } 29263 | 29264 | typename symbol_table_t::vector_holder_ptr vec_holder = typename symbol_table_t::vector_holder_ptr(0); 29265 | 29266 | const std::size_t vec_size = static_cast<std::size_t>(details::numeric::to_int32(vector_size)); 29267 | const std::size_t predicted_total_lclsymb_size = sizeof(T) * vec_size + sem_.total_local_symb_size_bytes(); 29268 | 29269 | if (predicted_total_lclsymb_size > settings().max_total_local_symbol_size_bytes()) 29270 | { 29271 | set_error(make_error( 29272 | parser_error::e_syntax, 29273 | current_token(), 29274 | "ERR161 - Adding vector '" + vec_name + "' of size " + details::to_str(vec_size) + " bytes " 29275 | "will exceed max total local symbol size of: " + details::to_str(settings().max_total_local_symbol_size_bytes()) + " bytes, " 29276 | "current total size: " + details::to_str(sem_.total_local_symb_size_bytes()) + " bytes", 29277 | exprtk_error_location)); 29278 | 29279 | return error_node(); 29280 | } 29281 | 29282 | scope_element& se = sem_.get_element(vec_name); 29283 | 29284 | if (se.name == vec_name) 29285 | { 29286 | if (se.active) 29287 | { 29288 | set_error(make_error( 29289 | parser_error::e_syntax, 29290 | current_token(), 29291 | "ERR162 - Illegal redefinition of local vector: '" + vec_name + "'", 29292 | exprtk_error_location)); 29293 | 29294 | return error_node(); 29295 | } 29296 | else if ( 29297 | (se.size == vec_size) && 29298 | (scope_element::e_vector == se.type) 29299 | ) 29300 | { 29301 | vec_holder = se.vec_node; 29302 | se.active = true; 29303 | se.depth = state_.scope_depth; 29304 | se.ref_count++; 29305 | } 29306 | } 29307 | 29308 | if (0 == vec_holder) 29309 | { 29310 | scope_element nse; 29311 | nse.name = vec_name; 29312 | nse.active = true; 29313 | nse.ref_count = 1; 29314 | nse.type = scope_element::e_vector; 29315 | nse.depth = state_.scope_depth; 29316 | nse.size = vec_size; 29317 | nse.data = new T[vec_size]; 29318 | nse.vec_node = new typename scope_element::vector_holder_t(reinterpret_cast<T*>(nse.data),nse.size); 29319 | 29320 | details::set_zero_value(reinterpret_cast<T*>(nse.data),vec_size); 29321 | 29322 | if (!sem_.add_element(nse)) 29323 | { 29324 | set_error(make_error( 29325 | parser_error::e_syntax, 29326 | current_token(), 29327 | "ERR163 - Failed to add new local vector '" + vec_name + "' to SEM", 29328 | exprtk_error_location)); 29329 | 29330 | sem_.free_element(nse); 29331 | 29332 | return error_node(); 29333 | } 29334 | 29335 | assert(sem_.total_local_symb_size_bytes() <= settings().max_total_local_symbol_size_bytes()); 29336 | 29337 | vec_holder = nse.vec_node; 29338 | 29339 | exprtk_debug(("parse_define_vector_statement() - INFO - Added new local vector: %s[%d]\n", 29340 | nse.name.c_str(), 29341 | static_cast<int>(nse.size))); 29342 | } 29343 | 29344 | state_.activate_side_effect("parse_define_vector_statement()"); 29345 | 29346 | lodge_symbol(vec_name, e_st_local_vector); 29347 | 29348 | std::vector<expression_node_ptr> vec_initilizer_list; 29349 | 29350 | scoped_vec_delete<expression_node_t> svd((*this),vec_initilizer_list); 29351 | 29352 | bool single_value_initialiser = false; 29353 | bool range_value_initialiser = false; 29354 | bool vec_to_vec_initialiser = false; 29355 | bool null_initialisation = false; 29356 | 29357 | if (!token_is(token_t::e_rsqrbracket)) 29358 | { 29359 | set_error(make_error( 29360 | parser_error::e_syntax, 29361 | current_token(), 29362 | "ERR164 - Expected ']' as part of vector size definition", 29363 | exprtk_error_location)); 29364 | 29365 | return error_node(); 29366 | } 29367 | else if (!token_is(token_t::e_eof, prsrhlpr_t::e_hold)) 29368 | { 29369 | if (!token_is(token_t::e_assign)) 29370 | { 29371 | set_error(make_error( 29372 | parser_error::e_syntax, 29373 | current_token(), 29374 | "ERR165 - Expected ':=' as part of vector definition", 29375 | exprtk_error_location)); 29376 | 29377 | return error_node(); 29378 | } 29379 | else if (token_is(token_t::e_lsqrbracket)) 29380 | { 29381 | expression_node_ptr initialiser_component = parse_expression(); 29382 | 29383 | if (0 == initialiser_component) 29384 | { 29385 | set_error(make_error( 29386 | parser_error::e_syntax, 29387 | current_token(), 29388 | "ERR166 - Failed to parse first component of vector initialiser for vector: " + vec_name, 29389 | exprtk_error_location)); 29390 | 29391 | return error_node(); 29392 | } 29393 | 29394 | vec_initilizer_list.push_back(initialiser_component); 29395 | 29396 | if (token_is(token_t::e_colon)) 29397 | { 29398 | initialiser_component = parse_expression(); 29399 | 29400 | if (0 == initialiser_component) 29401 | { 29402 | set_error(make_error( 29403 | parser_error::e_syntax, 29404 | current_token(), 29405 | "ERR167 - Failed to parse second component of vector initialiser for vector: " + vec_name, 29406 | exprtk_error_location)); 29407 | 29408 | return error_node(); 29409 | } 29410 | 29411 | vec_initilizer_list.push_back(initialiser_component); 29412 | } 29413 | 29414 | if (!token_is(token_t::e_rsqrbracket)) 29415 | { 29416 | set_error(make_error( 29417 | parser_error::e_syntax, 29418 | current_token(), 29419 | "ERR168 - Expected ']' to close single value vector initialiser", 29420 | exprtk_error_location)); 29421 | 29422 | return error_node(); 29423 | } 29424 | 29425 | switch (vec_initilizer_list.size()) 29426 | { 29427 | case 1 : single_value_initialiser = true; break; 29428 | case 2 : range_value_initialiser = true; break; 29429 | } 29430 | } 29431 | else if (!token_is(token_t::e_lcrlbracket)) 29432 | { 29433 | expression_node_ptr initialiser = error_node(); 29434 | 29435 | // Is this a vector to vector assignment and initialisation? 29436 | if (token_t::e_symbol == current_token().type) 29437 | { 29438 | // Is it a locally defined vector? 29439 | const scope_element& lcl_se = sem_.get_active_element(current_token().value); 29440 | 29441 | if (scope_element::e_vector == lcl_se.type) 29442 | { 29443 | if (0 != (initialiser = parse_expression())) 29444 | vec_initilizer_list.push_back(initialiser); 29445 | else 29446 | return error_node(); 29447 | } 29448 | // Are we dealing with a user defined vector? 29449 | else if (symtab_store_.is_vector(current_token().value)) 29450 | { 29451 | lodge_symbol(current_token().value, e_st_vector); 29452 | 29453 | if (0 != (initialiser = parse_expression())) 29454 | vec_initilizer_list.push_back(initialiser); 29455 | else 29456 | return error_node(); 29457 | } 29458 | // Are we dealing with a null initialisation vector definition? 29459 | else if (token_is(token_t::e_symbol,"null")) 29460 | null_initialisation = true; 29461 | } 29462 | 29463 | if (!null_initialisation) 29464 | { 29465 | if (0 == initialiser) 29466 | { 29467 | set_error(make_error( 29468 | parser_error::e_syntax, 29469 | current_token(), 29470 | "ERR169 - Expected '{' as part of vector initialiser list", 29471 | exprtk_error_location)); 29472 | 29473 | return error_node(); 29474 | } 29475 | else 29476 | vec_to_vec_initialiser = true; 29477 | } 29478 | } 29479 | else if (!token_is(token_t::e_rcrlbracket)) 29480 | { 29481 | for ( ; ; ) 29482 | { 29483 | expression_node_ptr initialiser = parse_expression(); 29484 | 29485 | if (0 == initialiser) 29486 | { 29487 | set_error(make_error( 29488 | parser_error::e_syntax, 29489 | current_token(), 29490 | "ERR170 - Expected '{' as part of vector initialiser list", 29491 | exprtk_error_location)); 29492 | 29493 | return error_node(); 29494 | } 29495 | else 29496 | vec_initilizer_list.push_back(initialiser); 29497 | 29498 | if (token_is(token_t::e_rcrlbracket)) 29499 | break; 29500 | 29501 | const bool is_next_close = peek_token_is(token_t::e_rcrlbracket); 29502 | 29503 | if (!token_is(token_t::e_comma) && is_next_close) 29504 | { 29505 | set_error(make_error( 29506 | parser_error::e_syntax, 29507 | current_token(), 29508 | "ERR171 - Expected ',' between vector initialisers", 29509 | exprtk_error_location)); 29510 | 29511 | return error_node(); 29512 | } 29513 | 29514 | if (token_is(token_t::e_rcrlbracket)) 29515 | break; 29516 | } 29517 | } 29518 | 29519 | if ( 29520 | !token_is(token_t::e_rbracket , prsrhlpr_t::e_hold) && 29521 | !token_is(token_t::e_rcrlbracket, prsrhlpr_t::e_hold) && 29522 | !token_is(token_t::e_rsqrbracket, prsrhlpr_t::e_hold) 29523 | ) 29524 | { 29525 | if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold)) 29526 | { 29527 | set_error(make_error( 29528 | parser_error::e_syntax, 29529 | current_token(), 29530 | "ERR172 - Expected ';' at end of vector definition", 29531 | exprtk_error_location)); 29532 | 29533 | return error_node(); 29534 | } 29535 | } 29536 | 29537 | if ( 29538 | !single_value_initialiser && 29539 | !range_value_initialiser && 29540 | (T(vec_initilizer_list.size()) > vector_size) 29541 | ) 29542 | { 29543 | set_error(make_error( 29544 | parser_error::e_syntax, 29545 | current_token(), 29546 | "ERR173 - Initialiser list larger than the number of elements in the vector: '" + vec_name + "'", 29547 | exprtk_error_location)); 29548 | 29549 | return error_node(); 29550 | } 29551 | } 29552 | 29553 | expression_node_ptr result = error_node(); 29554 | 29555 | if ( 29556 | (vec_initilizer_list.size() == 1) && 29557 | single_value_initialiser 29558 | ) 29559 | { 29560 | if (details::is_constant_node(vec_initilizer_list[0])) 29561 | { 29562 | // vector_init_zero_value_node var v[10] := [0] 29563 | if (T(0) == vec_initilizer_list[0]->value()) 29564 | { 29565 | result = node_allocator_ 29566 | .allocate<details::vector_init_zero_value_node<T> >( 29567 | (*vec_holder)[0], 29568 | vec_size, 29569 | vec_initilizer_list); 29570 | } 29571 | else 29572 | { 29573 | // vector_init_single_constvalue_node var v[10] := [123] 29574 | result = node_allocator_ 29575 | .allocate<details::vector_init_single_constvalue_node<T> >( 29576 | (*vec_holder)[0], 29577 | vec_size, 29578 | vec_initilizer_list); 29579 | } 29580 | } 29581 | else 29582 | { 29583 | // vector_init_single_value_node var v[10] := [123 + (x / y)] 29584 | result = node_allocator_ 29585 | .allocate<details::vector_init_single_value_node<T> >( 29586 | (*vec_holder)[0], 29587 | vec_size, 29588 | vec_initilizer_list); 29589 | } 29590 | } 29591 | else if ( 29592 | (vec_initilizer_list.size() == 2) && 29593 | range_value_initialiser 29594 | ) 29595 | { 29596 | bool base_const = details::is_constant_node(vec_initilizer_list[0]); 29597 | bool inc_const = details::is_constant_node(vec_initilizer_list[1]); 29598 | 29599 | if (base_const && inc_const) 29600 | { 29601 | // vector_init_single_value_node var v[10] := [1 : 3.5] 29602 | result = node_allocator_ 29603 | .allocate<details::vector_init_iota_constconst_node<T> >( 29604 | (*vec_holder)[0], 29605 | vec_size, 29606 | vec_initilizer_list); 29607 | } 29608 | else if (base_const && !inc_const) 29609 | { 29610 | // vector_init_single_value_node var v[10] := [1 : x + y] 29611 | result = node_allocator_ 29612 | .allocate<details::vector_init_iota_constnconst_node<T> >( 29613 | (*vec_holder)[0], 29614 | vec_size, 29615 | vec_initilizer_list); 29616 | } 29617 | else if (!base_const && inc_const) 29618 | { 29619 | // vector_init_single_value_node var v[10] := [x + y : 3] 29620 | result = node_allocator_ 29621 | .allocate<details::vector_init_iota_nconstconst_node<T> >( 29622 | (*vec_holder)[0], 29623 | vec_size, 29624 | vec_initilizer_list); 29625 | } 29626 | else if (!base_const && !inc_const) 29627 | { 29628 | // vector_init_single_value_node var v[10] := [x + y : z / w] 29629 | result = node_allocator_ 29630 | .allocate<details::vector_init_iota_nconstnconst_node<T> >( 29631 | (*vec_holder)[0], 29632 | vec_size, 29633 | vec_initilizer_list); 29634 | } 29635 | } 29636 | else if (null_initialisation) 29637 | result = expression_generator_(T(0.0)); 29638 | else if (vec_to_vec_initialiser) 29639 | { 29640 | expression_node_ptr vec_node = node_allocator_.allocate<vector_node_t>(vec_holder); 29641 | 29642 | result = expression_generator_( 29643 | details::e_assign, 29644 | vec_node, 29645 | vec_initilizer_list[0]); 29646 | } 29647 | else 29648 | { 29649 | result = node_allocator_ 29650 | .allocate<details::vector_initialisation_node<T> >( 29651 | (*vec_holder)[0], 29652 | vec_size, 29653 | vec_initilizer_list, 29654 | single_value_initialiser); 29655 | } 29656 | 29657 | svd.delete_ptr = false; 29658 | 29659 | if (result && result->valid()) 29660 | { 29661 | return result; 29662 | } 29663 | 29664 | details::free_node(node_allocator_, result); 29665 | 29666 | set_error(make_error( 29667 | parser_error::e_synthesis, 29668 | current_token(), 29669 | "ERR174 - Failed to generate initialisation node for vector: " + vec_name, 29670 | exprtk_error_location)); 29671 | 29672 | return error_node(); 29673 | } 29674 | 29675 | #ifndef exprtk_disable_string_capabilities 29676 | inline expression_node_ptr parse_define_string_statement(const std::string& str_name, expression_node_ptr initialisation_expression) 29677 | { 29678 | stringvar_node_t* str_node = reinterpret_cast<stringvar_node_t*>(0); 29679 | 29680 | scope_element& se = sem_.get_element(str_name); 29681 | 29682 | if (se.name == str_name) 29683 | { 29684 | if (se.active) 29685 | { 29686 | set_error(make_error( 29687 | parser_error::e_syntax, 29688 | current_token(), 29689 | "ERR175 - Illegal redefinition of local variable: '" + str_name + "'", 29690 | exprtk_error_location)); 29691 | 29692 | free_node(node_allocator_, initialisation_expression); 29693 | 29694 | return error_node(); 29695 | } 29696 | else if (scope_element::e_string == se.type) 29697 | { 29698 | str_node = se.str_node; 29699 | se.active = true; 29700 | se.depth = state_.scope_depth; 29701 | se.ref_count++; 29702 | } 29703 | } 29704 | 29705 | if (0 == str_node) 29706 | { 29707 | scope_element nse; 29708 | nse.name = str_name; 29709 | nse.active = true; 29710 | nse.ref_count = 1; 29711 | nse.type = scope_element::e_string; 29712 | nse.depth = state_.scope_depth; 29713 | nse.data = new std::string; 29714 | nse.str_node = new stringvar_node_t(*reinterpret_cast<std::string*>(nse.data)); 29715 | 29716 | if (!sem_.add_element(nse)) 29717 | { 29718 | set_error(make_error( 29719 | parser_error::e_syntax, 29720 | current_token(), 29721 | "ERR176 - Failed to add new local string variable '" + str_name + "' to SEM", 29722 | exprtk_error_location)); 29723 | 29724 | free_node(node_allocator_, initialisation_expression); 29725 | 29726 | sem_.free_element(nse); 29727 | 29728 | return error_node(); 29729 | } 29730 | 29731 | assert(sem_.total_local_symb_size_bytes() <= settings().max_total_local_symbol_size_bytes()); 29732 | 29733 | str_node = nse.str_node; 29734 | 29735 | exprtk_debug(("parse_define_string_statement() - INFO - Added new local string variable: %s\n", nse.name.c_str())); 29736 | } 29737 | 29738 | lodge_symbol(str_name, e_st_local_string); 29739 | 29740 | state_.activate_side_effect("parse_define_string_statement()"); 29741 | 29742 | expression_node_ptr branch[2] = {0}; 29743 | 29744 | branch[0] = str_node; 29745 | branch[1] = initialisation_expression; 29746 | 29747 | return expression_generator_(details::e_assign,branch); 29748 | } 29749 | #else 29750 | inline expression_node_ptr parse_define_string_statement(const std::string&, expression_node_ptr) 29751 | { 29752 | return error_node(); 29753 | } 29754 | #endif 29755 | 29756 | inline bool local_variable_is_shadowed(const std::string& symbol) 29757 | { 29758 | const scope_element& se = sem_.get_element(symbol); 29759 | return (se.name == symbol) && se.active; 29760 | } 29761 | 29762 | inline expression_node_ptr parse_define_var_statement() 29763 | { 29764 | if (settings_.vardef_disabled()) 29765 | { 29766 | set_error(make_error( 29767 | parser_error::e_syntax, 29768 | current_token(), 29769 | "ERR177 - Illegal variable definition", 29770 | exprtk_error_location)); 29771 | 29772 | return error_node(); 29773 | } 29774 | else if (!details::imatch(current_token().value,"var")) 29775 | { 29776 | return error_node(); 29777 | } 29778 | else 29779 | next_token(); 29780 | 29781 | const std::string var_name = current_token().value; 29782 | 29783 | expression_node_ptr initialisation_expression = error_node(); 29784 | 29785 | if (!token_is(token_t::e_symbol)) 29786 | { 29787 | set_error(make_error( 29788 | parser_error::e_syntax, 29789 | current_token(), 29790 | "ERR178 - Expected a symbol for variable definition", 29791 | exprtk_error_location)); 29792 | 29793 | return error_node(); 29794 | } 29795 | else if (details::is_reserved_symbol(var_name)) 29796 | { 29797 | set_error(make_error( 29798 | parser_error::e_syntax, 29799 | current_token(), 29800 | "ERR179 - Illegal redefinition of reserved keyword: '" + var_name + "'", 29801 | exprtk_error_location)); 29802 | 29803 | return error_node(); 29804 | } 29805 | else if (symtab_store_.symbol_exists(var_name)) 29806 | { 29807 | set_error(make_error( 29808 | parser_error::e_syntax, 29809 | current_token(), 29810 | "ERR180 - Illegal redefinition of variable '" + var_name + "'", 29811 | exprtk_error_location)); 29812 | 29813 | return error_node(); 29814 | } 29815 | else if (local_variable_is_shadowed(var_name)) 29816 | { 29817 | set_error(make_error( 29818 | parser_error::e_syntax, 29819 | current_token(), 29820 | "ERR181 - Illegal redefinition of local variable: '" + var_name + "'", 29821 | exprtk_error_location)); 29822 | 29823 | return error_node(); 29824 | } 29825 | else if (token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold)) 29826 | { 29827 | return parse_define_vector_statement(var_name); 29828 | } 29829 | else if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) 29830 | { 29831 | return parse_uninitialised_var_statement(var_name); 29832 | } 29833 | else if (token_is(token_t::e_assign)) 29834 | { 29835 | if (0 == (initialisation_expression = parse_expression())) 29836 | { 29837 | set_error(make_error( 29838 | parser_error::e_syntax, 29839 | current_token(), 29840 | "ERR182 - Failed to parse initialisation expression for variable '" + var_name + "'", 29841 | exprtk_error_location)); 29842 | 29843 | return error_node(); 29844 | } 29845 | } 29846 | 29847 | if ( 29848 | !token_is(token_t::e_rbracket , prsrhlpr_t::e_hold) && 29849 | !token_is(token_t::e_rcrlbracket, prsrhlpr_t::e_hold) && 29850 | !token_is(token_t::e_rsqrbracket, prsrhlpr_t::e_hold) 29851 | ) 29852 | { 29853 | if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold)) 29854 | { 29855 | set_error(make_error( 29856 | parser_error::e_syntax, 29857 | current_token(), 29858 | "ERR183 - Expected ';' after variable '" + var_name + "' definition", 29859 | exprtk_error_location)); 29860 | 29861 | free_node(node_allocator_, initialisation_expression); 29862 | 29863 | return error_node(); 29864 | } 29865 | } 29866 | 29867 | if ( 29868 | (0 != initialisation_expression) && 29869 | details::is_generally_string_node(initialisation_expression) 29870 | ) 29871 | { 29872 | return parse_define_string_statement(var_name,initialisation_expression); 29873 | } 29874 | 29875 | expression_node_ptr var_node = reinterpret_cast<expression_node_ptr>(0); 29876 | 29877 | scope_element& se = sem_.get_element(var_name); 29878 | 29879 | if (se.name == var_name) 29880 | { 29881 | if (se.active) 29882 | { 29883 | set_error(make_error( 29884 | parser_error::e_syntax, 29885 | current_token(), 29886 | "ERR184 - Illegal redefinition of local variable: '" + var_name + "'", 29887 | exprtk_error_location)); 29888 | 29889 | free_node(node_allocator_, initialisation_expression); 29890 | 29891 | return error_node(); 29892 | } 29893 | else if (scope_element::e_variable == se.type) 29894 | { 29895 | var_node = se.var_node; 29896 | se.active = true; 29897 | se.depth = state_.scope_depth; 29898 | se.ref_count++; 29899 | } 29900 | } 29901 | 29902 | if (0 == var_node) 29903 | { 29904 | const std::size_t predicted_total_lclsymb_size = sizeof(T) + sem_.total_local_symb_size_bytes(); 29905 | 29906 | if (predicted_total_lclsymb_size > settings().max_total_local_symbol_size_bytes()) 29907 | { 29908 | set_error(make_error( 29909 | parser_error::e_syntax, 29910 | current_token(), 29911 | "ERR185 - Adding variable '" + var_name + "' " 29912 | "will exceed max total local symbol size of: " + details::to_str(settings().max_total_local_symbol_size_bytes()) + " bytes, " 29913 | "current total size: " + details::to_str(sem_.total_local_symb_size_bytes()) + " bytes", 29914 | exprtk_error_location)); 29915 | 29916 | free_node(node_allocator_, initialisation_expression); 29917 | 29918 | return error_node(); 29919 | } 29920 | 29921 | scope_element nse; 29922 | nse.name = var_name; 29923 | nse.active = true; 29924 | nse.ref_count = 1; 29925 | nse.type = scope_element::e_variable; 29926 | nse.depth = state_.scope_depth; 29927 | nse.data = new T(T(0)); 29928 | nse.var_node = node_allocator_.allocate<variable_node_t>(*reinterpret_cast<T*>(nse.data)); 29929 | 29930 | if (!sem_.add_element(nse)) 29931 | { 29932 | set_error(make_error( 29933 | parser_error::e_syntax, 29934 | current_token(), 29935 | "ERR186 - Failed to add new local variable '" + var_name + "' to SEM", 29936 | exprtk_error_location)); 29937 | 29938 | free_node(node_allocator_, initialisation_expression); 29939 | 29940 | sem_.free_element(nse); 29941 | 29942 | return error_node(); 29943 | } 29944 | 29945 | assert(sem_.total_local_symb_size_bytes() <= settings().max_total_local_symbol_size_bytes()); 29946 | 29947 | var_node = nse.var_node; 29948 | 29949 | exprtk_debug(("parse_define_var_statement() - INFO - Added new local variable: %s\n", nse.name.c_str())); 29950 | } 29951 | 29952 | state_.activate_side_effect("parse_define_var_statement()"); 29953 | 29954 | lodge_symbol(var_name, e_st_local_variable); 29955 | 29956 | expression_node_ptr branch[2] = {0}; 29957 | 29958 | branch[0] = var_node; 29959 | branch[1] = initialisation_expression ? initialisation_expression : expression_generator_(T(0)); 29960 | 29961 | return expression_generator_(details::e_assign,branch); 29962 | } 29963 | 29964 | inline expression_node_ptr parse_define_constvar_statement() 29965 | { 29966 | if (settings_.vardef_disabled()) 29967 | { 29968 | set_error(make_error( 29969 | parser_error::e_syntax, 29970 | current_token(), 29971 | "ERR187 - Illegal const variable definition", 29972 | exprtk_error_location)); 29973 | 29974 | return error_node(); 29975 | } 29976 | else if (!token_is("const")) 29977 | { 29978 | set_error(make_error( 29979 | parser_error::e_syntax, 29980 | current_token(), 29981 | "ERR188 - Expected 'const' keyword for const-variable definition", 29982 | exprtk_error_location)); 29983 | 29984 | return error_node(); 29985 | } 29986 | else if (!token_is("var")) 29987 | { 29988 | set_error(make_error( 29989 | parser_error::e_syntax, 29990 | current_token(), 29991 | "ERR189 - Expected 'var' keyword for const-variable definition", 29992 | exprtk_error_location)); 29993 | 29994 | return error_node(); 29995 | } 29996 | 29997 | const std::string var_name = current_token().value; 29998 | 29999 | expression_node_ptr initialisation_expression = error_node(); 30000 | 30001 | if (!token_is(token_t::e_symbol)) 30002 | { 30003 | set_error(make_error( 30004 | parser_error::e_syntax, 30005 | current_token(), 30006 | "ERR190 - Expected a symbol for const-variable definition", 30007 | exprtk_error_location)); 30008 | 30009 | return error_node(); 30010 | } 30011 | else if (details::is_reserved_symbol(var_name)) 30012 | { 30013 | set_error(make_error( 30014 | parser_error::e_syntax, 30015 | current_token(), 30016 | "ERR191 - Illegal redefinition of reserved keyword: '" + var_name + "'", 30017 | exprtk_error_location)); 30018 | 30019 | return error_node(); 30020 | } 30021 | else if (symtab_store_.symbol_exists(var_name)) 30022 | { 30023 | set_error(make_error( 30024 | parser_error::e_syntax, 30025 | current_token(), 30026 | "ERR192 - Illegal redefinition of variable '" + var_name + "'", 30027 | exprtk_error_location)); 30028 | 30029 | return error_node(); 30030 | } 30031 | else if (local_variable_is_shadowed(var_name)) 30032 | { 30033 | set_error(make_error( 30034 | parser_error::e_syntax, 30035 | current_token(), 30036 | "ERR193 - Illegal redefinition of local variable: '" + var_name + "'", 30037 | exprtk_error_location)); 30038 | 30039 | return error_node(); 30040 | } 30041 | else if (token_is(token_t::e_assign)) 30042 | { 30043 | if (0 == (initialisation_expression = parse_expression())) 30044 | { 30045 | set_error(make_error( 30046 | parser_error::e_syntax, 30047 | current_token(), 30048 | "ERR194 - Failed to parse initialisation expression for const-variable: '" + var_name + "'", 30049 | exprtk_error_location)); 30050 | 30051 | return error_node(); 30052 | } 30053 | else if (!details::is_literal_node(initialisation_expression)) 30054 | { 30055 | set_error(make_error( 30056 | parser_error::e_syntax, 30057 | current_token(), 30058 | "ERR195 - initialisation expression for const-variable: '" + var_name + "' must be a constant/literal", 30059 | exprtk_error_location)); 30060 | 30061 | free_node(node_allocator_, initialisation_expression); 30062 | 30063 | return error_node(); 30064 | } 30065 | } 30066 | 30067 | const T init_value = initialisation_expression->value(); 30068 | 30069 | free_node(node_allocator_, initialisation_expression); 30070 | 30071 | expression_node_ptr var_node = reinterpret_cast<expression_node_ptr>(0); 30072 | 30073 | scope_element& se = sem_.get_element(var_name); 30074 | 30075 | if (se.name == var_name) 30076 | { 30077 | if (se.active) 30078 | { 30079 | set_error(make_error( 30080 | parser_error::e_syntax, 30081 | current_token(), 30082 | "ERR196 - Illegal redefinition of local variable: '" + var_name + "'", 30083 | exprtk_error_location)); 30084 | 30085 | return error_node(); 30086 | } 30087 | else if (scope_element::e_literal == se.type) 30088 | { 30089 | var_node = se.var_node; 30090 | se.active = true; 30091 | se.depth = state_.scope_depth; 30092 | se.ref_count++; 30093 | } 30094 | } 30095 | 30096 | if (0 == var_node) 30097 | { 30098 | const std::size_t predicted_total_lclsymb_size = sizeof(T) + sem_.total_local_symb_size_bytes(); 30099 | 30100 | if (predicted_total_lclsymb_size > settings().max_total_local_symbol_size_bytes()) 30101 | { 30102 | set_error(make_error( 30103 | parser_error::e_syntax, 30104 | current_token(), 30105 | "ERR197 - Adding variable '" + var_name + "' " 30106 | "will exceed max total local symbol size of: " + details::to_str(settings().max_total_local_symbol_size_bytes()) + " bytes, " 30107 | "current total size: " + details::to_str(sem_.total_local_symb_size_bytes()) + " bytes", 30108 | exprtk_error_location)); 30109 | 30110 | return error_node(); 30111 | } 30112 | 30113 | scope_element nse; 30114 | nse.name = var_name; 30115 | nse.active = true; 30116 | nse.ref_count = 1; 30117 | nse.type = scope_element::e_literal; 30118 | nse.depth = state_.scope_depth; 30119 | nse.data = 0; 30120 | nse.var_node = node_allocator_.allocate<literal_node_t>(init_value); 30121 | 30122 | if (!sem_.add_element(nse)) 30123 | { 30124 | set_error(make_error( 30125 | parser_error::e_syntax, 30126 | current_token(), 30127 | "ERR198 - Failed to add new local const-variable '" + var_name + "' to SEM", 30128 | exprtk_error_location)); 30129 | 30130 | sem_.free_element(nse); 30131 | 30132 | return error_node(); 30133 | } 30134 | 30135 | assert(sem_.total_local_symb_size_bytes() <= settings().max_total_local_symbol_size_bytes()); 30136 | 30137 | var_node = nse.var_node; 30138 | 30139 | exprtk_debug(("parse_define_constvar_statement() - INFO - Added new local const-variable: %s\n", nse.name.c_str())); 30140 | } 30141 | 30142 | state_.activate_side_effect("parse_define_constvar_statement()"); 30143 | 30144 | lodge_symbol(var_name, e_st_local_variable); 30145 | 30146 | return expression_generator_(var_node->value()); 30147 | } 30148 | 30149 | inline expression_node_ptr parse_uninitialised_var_statement(const std::string& var_name) 30150 | { 30151 | if ( 30152 | !token_is(token_t::e_lcrlbracket) || 30153 | !token_is(token_t::e_rcrlbracket) 30154 | ) 30155 | { 30156 | set_error(make_error( 30157 | parser_error::e_syntax, 30158 | current_token(), 30159 | "ERR199 - Expected a '{}' for uninitialised var definition", 30160 | exprtk_error_location)); 30161 | 30162 | return error_node(); 30163 | } 30164 | else if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold)) 30165 | { 30166 | set_error(make_error( 30167 | parser_error::e_syntax, 30168 | current_token(), 30169 | "ERR200 - Expected ';' after uninitialised variable definition", 30170 | exprtk_error_location)); 30171 | 30172 | return error_node(); 30173 | } 30174 | 30175 | expression_node_ptr var_node = reinterpret_cast<expression_node_ptr>(0); 30176 | 30177 | scope_element& se = sem_.get_element(var_name); 30178 | 30179 | if (se.name == var_name) 30180 | { 30181 | if (se.active) 30182 | { 30183 | set_error(make_error( 30184 | parser_error::e_syntax, 30185 | current_token(), 30186 | "ERR201 - Illegal redefinition of local variable: '" + var_name + "'", 30187 | exprtk_error_location)); 30188 | 30189 | return error_node(); 30190 | } 30191 | else if (scope_element::e_variable == se.type) 30192 | { 30193 | var_node = se.var_node; 30194 | se.active = true; 30195 | se.ref_count++; 30196 | } 30197 | } 30198 | 30199 | if (0 == var_node) 30200 | { 30201 | const std::size_t predicted_total_lclsymb_size = sizeof(T) + sem_.total_local_symb_size_bytes(); 30202 | 30203 | if (predicted_total_lclsymb_size > settings().max_total_local_symbol_size_bytes()) 30204 | { 30205 | set_error(make_error( 30206 | parser_error::e_syntax, 30207 | current_token(), 30208 | "ERR202 - Adding variable '" + var_name + "' " 30209 | "will exceed max total local symbol size of: " + details::to_str(settings().max_total_local_symbol_size_bytes()) + " bytes, " 30210 | "current total size: " + details::to_str(sem_.total_local_symb_size_bytes()) + " bytes", 30211 | exprtk_error_location)); 30212 | 30213 | return error_node(); 30214 | } 30215 | 30216 | scope_element nse; 30217 | nse.name = var_name; 30218 | nse.active = true; 30219 | nse.ref_count = 1; 30220 | nse.type = scope_element::e_variable; 30221 | nse.depth = state_.scope_depth; 30222 | nse.ip_index = sem_.next_ip_index(); 30223 | nse.data = new T(T(0)); 30224 | nse.var_node = node_allocator_.allocate<variable_node_t>(*reinterpret_cast<T*>(nse.data)); 30225 | 30226 | if (!sem_.add_element(nse)) 30227 | { 30228 | set_error(make_error( 30229 | parser_error::e_syntax, 30230 | current_token(), 30231 | "ERR203 - Failed to add new local variable '" + var_name + "' to SEM", 30232 | exprtk_error_location)); 30233 | 30234 | sem_.free_element(nse); 30235 | 30236 | return error_node(); 30237 | } 30238 | 30239 | assert(sem_.total_local_symb_size_bytes() <= settings().max_total_local_symbol_size_bytes()); 30240 | 30241 | exprtk_debug(("parse_uninitialised_var_statement() - INFO - Added new local variable: %s\n", 30242 | nse.name.c_str())); 30243 | } 30244 | 30245 | lodge_symbol(var_name, e_st_local_variable); 30246 | 30247 | state_.activate_side_effect("parse_uninitialised_var_statement()"); 30248 | 30249 | return expression_generator_(T(0)); 30250 | } 30251 | 30252 | inline expression_node_ptr parse_swap_statement() 30253 | { 30254 | if (!details::imatch(current_token().value,"swap")) 30255 | { 30256 | return error_node(); 30257 | } 30258 | else 30259 | next_token(); 30260 | 30261 | if (!token_is(token_t::e_lbracket)) 30262 | { 30263 | set_error(make_error( 30264 | parser_error::e_syntax, 30265 | current_token(), 30266 | "ERR204 - Expected '(' at start of swap statement", 30267 | exprtk_error_location)); 30268 | 30269 | return error_node(); 30270 | } 30271 | 30272 | expression_node_ptr variable0 = error_node(); 30273 | expression_node_ptr variable1 = error_node(); 30274 | 30275 | bool variable0_generated = false; 30276 | bool variable1_generated = false; 30277 | 30278 | const std::string var0_name = current_token().value; 30279 | 30280 | if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold)) 30281 | { 30282 | set_error(make_error( 30283 | parser_error::e_syntax, 30284 | current_token(), 30285 | "ERR205 - Expected a symbol for variable or vector element definition", 30286 | exprtk_error_location)); 30287 | 30288 | return error_node(); 30289 | } 30290 | else if (peek_token_is(token_t::e_lsqrbracket)) 30291 | { 30292 | if (0 == (variable0 = parse_vector())) 30293 | { 30294 | set_error(make_error( 30295 | parser_error::e_syntax, 30296 | current_token(), 30297 | "ERR206 - First parameter to swap is an invalid vector element: '" + var0_name + "'", 30298 | exprtk_error_location)); 30299 | 30300 | return error_node(); 30301 | } 30302 | 30303 | variable0_generated = true; 30304 | } 30305 | else 30306 | { 30307 | if (symtab_store_.is_variable(var0_name)) 30308 | { 30309 | variable0 = symtab_store_.get_variable(var0_name); 30310 | } 30311 | 30312 | const scope_element& se = sem_.get_element(var0_name); 30313 | 30314 | if ( 30315 | (se.active) && 30316 | (se.name == var0_name) && 30317 | (scope_element::e_variable == se.type) 30318 | ) 30319 | { 30320 | variable0 = se.var_node; 30321 | } 30322 | 30323 | lodge_symbol(var0_name, e_st_variable); 30324 | 30325 | if (0 == variable0) 30326 | { 30327 | set_error(make_error( 30328 | parser_error::e_syntax, 30329 | current_token(), 30330 | "ERR207 - First parameter to swap is an invalid variable: '" + var0_name + "'", 30331 | exprtk_error_location)); 30332 | 30333 | return error_node(); 30334 | } 30335 | else 30336 | next_token(); 30337 | } 30338 | 30339 | if (!token_is(token_t::e_comma)) 30340 | { 30341 | set_error(make_error( 30342 | parser_error::e_syntax, 30343 | current_token(), 30344 | "ERR208 - Expected ',' between parameters to swap", 30345 | exprtk_error_location)); 30346 | 30347 | if (variable0_generated) 30348 | { 30349 | free_node(node_allocator_, variable0); 30350 | } 30351 | 30352 | return error_node(); 30353 | } 30354 | 30355 | const std::string var1_name = current_token().value; 30356 | 30357 | if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold)) 30358 | { 30359 | set_error(make_error( 30360 | parser_error::e_syntax, 30361 | current_token(), 30362 | "ERR209 - Expected a symbol for variable or vector element definition", 30363 | exprtk_error_location)); 30364 | 30365 | if (variable0_generated) 30366 | { 30367 | free_node(node_allocator_, variable0); 30368 | } 30369 | 30370 | return error_node(); 30371 | } 30372 | else if (peek_token_is(token_t::e_lsqrbracket)) 30373 | { 30374 | if (0 == (variable1 = parse_vector())) 30375 | { 30376 | set_error(make_error( 30377 | parser_error::e_syntax, 30378 | current_token(), 30379 | "ERR210 - Second parameter to swap is an invalid vector element: '" + var1_name + "'", 30380 | exprtk_error_location)); 30381 | 30382 | if (variable0_generated) 30383 | { 30384 | free_node(node_allocator_, variable0); 30385 | } 30386 | 30387 | return error_node(); 30388 | } 30389 | 30390 | variable1_generated = true; 30391 | } 30392 | else 30393 | { 30394 | if (symtab_store_.is_variable(var1_name)) 30395 | { 30396 | variable1 = symtab_store_.get_variable(var1_name); 30397 | } 30398 | 30399 | const scope_element& se = sem_.get_element(var1_name); 30400 | 30401 | if ( 30402 | (se.active) && 30403 | (se.name == var1_name) && 30404 | (scope_element::e_variable == se.type) 30405 | ) 30406 | { 30407 | variable1 = se.var_node; 30408 | } 30409 | 30410 | lodge_symbol(var1_name, e_st_variable); 30411 | 30412 | if (0 == variable1) 30413 | { 30414 | set_error(make_error( 30415 | parser_error::e_syntax, 30416 | current_token(), 30417 | "ERR211 - Second parameter to swap is an invalid variable: '" + var1_name + "'", 30418 | exprtk_error_location)); 30419 | 30420 | if (variable0_generated) 30421 | { 30422 | free_node(node_allocator_, variable0); 30423 | } 30424 | 30425 | return error_node(); 30426 | } 30427 | else 30428 | next_token(); 30429 | } 30430 | 30431 | if (!token_is(token_t::e_rbracket)) 30432 | { 30433 | set_error(make_error( 30434 | parser_error::e_syntax, 30435 | current_token(), 30436 | "ERR212 - Expected ')' at end of swap statement", 30437 | exprtk_error_location)); 30438 | 30439 | if (variable0_generated) 30440 | { 30441 | free_node(node_allocator_, variable0); 30442 | } 30443 | 30444 | if (variable1_generated) 30445 | { 30446 | free_node(node_allocator_, variable1); 30447 | } 30448 | 30449 | return error_node(); 30450 | } 30451 | 30452 | typedef details::variable_node<T>* variable_node_ptr; 30453 | 30454 | variable_node_ptr v0 = variable_node_ptr(0); 30455 | variable_node_ptr v1 = variable_node_ptr(0); 30456 | 30457 | expression_node_ptr result = error_node(); 30458 | 30459 | if ( 30460 | (0 != (v0 = dynamic_cast<variable_node_ptr>(variable0))) && 30461 | (0 != (v1 = dynamic_cast<variable_node_ptr>(variable1))) 30462 | ) 30463 | { 30464 | result = node_allocator_.allocate<details::swap_node<T> >(v0, v1); 30465 | 30466 | if (variable0_generated) 30467 | { 30468 | free_node(node_allocator_, variable0); 30469 | } 30470 | 30471 | if (variable1_generated) 30472 | { 30473 | free_node(node_allocator_, variable1); 30474 | } 30475 | } 30476 | else 30477 | result = node_allocator_.allocate<details::swap_generic_node<T> > 30478 | (variable0, variable1); 30479 | 30480 | state_.activate_side_effect("parse_swap_statement()"); 30481 | 30482 | return result; 30483 | } 30484 | 30485 | #ifndef exprtk_disable_return_statement 30486 | inline expression_node_ptr parse_return_statement() 30487 | { 30488 | if (state_.parsing_return_stmt) 30489 | { 30490 | set_error(make_error( 30491 | parser_error::e_syntax, 30492 | current_token(), 30493 | "ERR213 - Return call within a return call is not allowed", 30494 | exprtk_error_location)); 30495 | 30496 | return error_node(); 30497 | } 30498 | 30499 | scoped_bool_negator sbn(state_.parsing_return_stmt); 30500 | 30501 | std::vector<expression_node_ptr> arg_list; 30502 | 30503 | scoped_vec_delete<expression_node_t> sdd((*this),arg_list); 30504 | 30505 | if (!details::imatch(current_token().value,"return")) 30506 | { 30507 | return error_node(); 30508 | } 30509 | else 30510 | next_token(); 30511 | 30512 | if (!token_is(token_t::e_lsqrbracket)) 30513 | { 30514 | set_error(make_error( 30515 | parser_error::e_syntax, 30516 | current_token(), 30517 | "ERR214 - Expected '[' at start of return statement", 30518 | exprtk_error_location)); 30519 | 30520 | return error_node(); 30521 | } 30522 | else if (!token_is(token_t::e_rsqrbracket)) 30523 | { 30524 | for ( ; ; ) 30525 | { 30526 | expression_node_ptr arg = parse_expression(); 30527 | 30528 | if (0 == arg) 30529 | return error_node(); 30530 | 30531 | arg_list.push_back(arg); 30532 | 30533 | if (token_is(token_t::e_rsqrbracket)) 30534 | break; 30535 | else if (!token_is(token_t::e_comma)) 30536 | { 30537 | set_error(make_error( 30538 | parser_error::e_syntax, 30539 | current_token(), 30540 | "ERR215 - Expected ',' between values during call to return", 30541 | exprtk_error_location)); 30542 | 30543 | return error_node(); 30544 | } 30545 | } 30546 | } 30547 | else if (settings_.zero_return_disabled()) 30548 | { 30549 | set_error(make_error( 30550 | parser_error::e_syntax, 30551 | current_token(), 30552 | "ERR216 - Zero parameter return statement not allowed", 30553 | exprtk_error_location)); 30554 | 30555 | return error_node(); 30556 | } 30557 | 30558 | const lexer::token prev_token = current_token(); 30559 | 30560 | if (token_is(token_t::e_rsqrbracket)) 30561 | { 30562 | if (!arg_list.empty()) 30563 | { 30564 | set_error(make_error( 30565 | parser_error::e_syntax, 30566 | prev_token, 30567 | "ERR217 - Invalid ']' found during return call", 30568 | exprtk_error_location)); 30569 | 30570 | return error_node(); 30571 | } 30572 | } 30573 | 30574 | std::string ret_param_type_list; 30575 | 30576 | for (std::size_t i = 0; i < arg_list.size(); ++i) 30577 | { 30578 | if (0 == arg_list[i]) 30579 | return error_node(); 30580 | else if (is_ivector_node(arg_list[i])) 30581 | ret_param_type_list += 'V'; 30582 | else if (is_generally_string_node(arg_list[i])) 30583 | ret_param_type_list += 'S'; 30584 | else 30585 | ret_param_type_list += 'T'; 30586 | } 30587 | 30588 | dec_.retparam_list_.push_back(ret_param_type_list); 30589 | 30590 | expression_node_ptr result = expression_generator_.return_call(arg_list); 30591 | 30592 | sdd.delete_ptr = (0 == result); 30593 | 30594 | state_.return_stmt_present = true; 30595 | 30596 | state_.activate_side_effect("parse_return_statement()"); 30597 | 30598 | return result; 30599 | } 30600 | #else 30601 | inline expression_node_ptr parse_return_statement() 30602 | { 30603 | return error_node(); 30604 | } 30605 | #endif 30606 | 30607 | inline expression_node_ptr parse_assert_statement() 30608 | { 30609 | assert(details::imatch(current_token().value, "assert")); 30610 | 30611 | if (state_.parsing_assert_stmt) 30612 | { 30613 | set_error(make_error( 30614 | parser_error::e_syntax, 30615 | current_token(), 30616 | "ERR218 - Assert statement within an assert statement is not allowed", 30617 | exprtk_error_location)); 30618 | 30619 | return error_node(); 30620 | } 30621 | 30622 | scoped_bool_negator sbn(state_.parsing_assert_stmt); 30623 | 30624 | next_token(); 30625 | 30626 | std::vector<expression_node_ptr> assert_arg_list(3, error_node()); 30627 | scoped_vec_delete<expression_node_t> sdd((*this), assert_arg_list); 30628 | 30629 | expression_node_ptr& assert_condition = assert_arg_list[0]; 30630 | expression_node_ptr& assert_message = assert_arg_list[1]; 30631 | expression_node_ptr& assert_id = assert_arg_list[2]; 30632 | 30633 | if (!token_is(token_t::e_lbracket)) 30634 | { 30635 | set_error(make_error( 30636 | parser_error::e_syntax, 30637 | current_token(), 30638 | "ERR219 - Expected '(' at start of assert statement", 30639 | exprtk_error_location)); 30640 | 30641 | return error_node(); 30642 | } 30643 | 30644 | const token_t start_token = current_token(); 30645 | 30646 | // Parse the assert condition 30647 | if (0 == (assert_condition = parse_expression())) 30648 | { 30649 | set_error(make_error( 30650 | parser_error::e_syntax, 30651 | current_token(), 30652 | "ERR220 - Failed to parse condition for assert statement", 30653 | exprtk_error_location)); 30654 | 30655 | return error_node(); 30656 | } 30657 | 30658 | const token_t end_token = current_token(); 30659 | 30660 | if (!token_is(token_t::e_rbracket)) 30661 | { 30662 | if (!token_is(token_t::e_comma)) 30663 | { 30664 | set_error(make_error( 30665 | parser_error::e_syntax, 30666 | current_token(), 30667 | "ERR221 - Expected ',' between condition and message for assert statement", 30668 | exprtk_error_location)); 30669 | 30670 | return error_node(); 30671 | } 30672 | // Parse the assert message 30673 | else if ( 30674 | (0 == (assert_message = parse_expression())) || 30675 | !details::is_generally_string_node(assert_message) 30676 | ) 30677 | { 30678 | set_error(make_error( 30679 | parser_error::e_syntax, 30680 | current_token(), 30681 | "ERR222 - " + 30682 | (assert_message ? 30683 | std::string("Expected string for assert message") : 30684 | std::string("Failed to parse message for assert statement")), 30685 | exprtk_error_location)); 30686 | 30687 | return error_node(); 30688 | } 30689 | else if (!token_is(token_t::e_rbracket)) 30690 | { 30691 | if (!token_is(token_t::e_comma)) 30692 | { 30693 | set_error(make_error( 30694 | parser_error::e_syntax, 30695 | current_token(), 30696 | "ERR223 - Expected ',' between message and ID for assert statement", 30697 | exprtk_error_location)); 30698 | 30699 | return error_node(); 30700 | } 30701 | // Parse assert ID 30702 | else if ( 30703 | (0 == (assert_id = parse_expression())) || 30704 | !details::is_const_string_node(assert_id) 30705 | ) 30706 | { 30707 | set_error(make_error( 30708 | parser_error::e_syntax, 30709 | current_token(), 30710 | "ERR224 - " + 30711 | (assert_id ? 30712 | std::string("Expected literal string for assert ID") : 30713 | std::string("Failed to parse string for assert ID")), 30714 | exprtk_error_location)); 30715 | 30716 | return error_node(); 30717 | } 30718 | else if (!token_is(token_t::e_rbracket)) 30719 | { 30720 | set_error(make_error( 30721 | parser_error::e_syntax, 30722 | current_token(), 30723 | "ERR225 - Expected ')' at start of assert statement", 30724 | exprtk_error_location)); 30725 | 30726 | return error_node(); 30727 | } 30728 | } 30729 | } 30730 | 30731 | exprtk::assert_check::assert_context context; 30732 | context.condition = lexer().substr(start_token.position, end_token.position); 30733 | context.offet = start_token.position; 30734 | 30735 | if (0 == assert_check_) 30736 | { 30737 | exprtk_debug(("parse_assert_statement() - assert functionality is disabled. assert condition: %s\n", 30738 | context.condition.c_str())); 30739 | 30740 | return new details::null_node<T>(); 30741 | } 30742 | 30743 | #ifndef exprtk_disable_string_capabilities 30744 | if (assert_message && details::is_const_string_node(assert_message)) 30745 | { 30746 | context.message = dynamic_cast<details::string_base_node<T>*>(assert_message)->str(); 30747 | } 30748 | 30749 | if (assert_id && details::is_const_string_node(assert_id)) 30750 | { 30751 | context.id = dynamic_cast<details::string_base_node<T>*>(assert_id)->str(); 30752 | 30753 | if (assert_ids_.end() != assert_ids_.find(context.id)) 30754 | { 30755 | set_error(make_error( 30756 | parser_error::e_syntax, 30757 | current_token(), 30758 | "ERR226 - Duplicate assert ID: " + context.id, 30759 | exprtk_error_location)); 30760 | 30761 | return error_node(); 30762 | } 30763 | 30764 | assert_ids_.insert(context.id); 30765 | free_node(node_allocator_, assert_id); 30766 | } 30767 | #endif 30768 | 30769 | expression_node_ptr result_node = 30770 | expression_generator_.assert_call( 30771 | assert_condition, 30772 | assert_message, 30773 | context); 30774 | 30775 | exprtk_debug(("parse_assert_statement() - assert condition: [%s]\n", context.condition.c_str() )); 30776 | exprtk_debug(("parse_assert_statement() - assert message: [%s]\n", context.message .c_str() )); 30777 | exprtk_debug(("parse_assert_statement() - assert id: [%s]\n", context.id .c_str() )); 30778 | exprtk_debug(("parse_assert_statement() - assert offset: [%d]\n", static_cast<int>(context.offet))); 30779 | 30780 | if (0 == result_node) 30781 | { 30782 | set_error(make_error( 30783 | parser_error::e_syntax, 30784 | current_token(), 30785 | "ERR227 - Failed to synthesize assert", 30786 | exprtk_error_location)); 30787 | 30788 | return error_node(); 30789 | } 30790 | 30791 | sdd.delete_ptr = false; 30792 | return result_node; 30793 | } 30794 | 30795 | inline bool post_variable_process(const std::string& symbol) 30796 | { 30797 | if ( 30798 | peek_token_is(token_t::e_lbracket ) || 30799 | peek_token_is(token_t::e_lcrlbracket) || 30800 | peek_token_is(token_t::e_lsqrbracket) 30801 | ) 30802 | { 30803 | if (!settings_.commutative_check_enabled()) 30804 | { 30805 | set_error(make_error( 30806 | parser_error::e_syntax, 30807 | current_token(), 30808 | "ERR228 - Invalid sequence of variable '" + symbol + "' and bracket", 30809 | exprtk_error_location)); 30810 | 30811 | return false; 30812 | } 30813 | 30814 | lexer().insert_front(token_t::e_mul); 30815 | } 30816 | 30817 | return true; 30818 | } 30819 | 30820 | inline bool post_bracket_process(const typename token_t::token_type& token, expression_node_ptr& branch) 30821 | { 30822 | bool implied_mul = false; 30823 | 30824 | if (details::is_generally_string_node(branch)) 30825 | return true; 30826 | 30827 | if (details::is_ivector_node(branch)) 30828 | return true; 30829 | 30830 | const lexer::parser_helper::token_advance_mode hold = prsrhlpr_t::e_hold; 30831 | 30832 | switch (token) 30833 | { 30834 | case token_t::e_lcrlbracket : implied_mul = token_is(token_t::e_lbracket , hold) || 30835 | token_is(token_t::e_lcrlbracket, hold) || 30836 | token_is(token_t::e_lsqrbracket, hold) ; 30837 | break; 30838 | 30839 | case token_t::e_lbracket : implied_mul = token_is(token_t::e_lbracket , hold) || 30840 | token_is(token_t::e_lcrlbracket, hold) || 30841 | token_is(token_t::e_lsqrbracket, hold) ; 30842 | break; 30843 | 30844 | case token_t::e_lsqrbracket : implied_mul = token_is(token_t::e_lbracket , hold) || 30845 | token_is(token_t::e_lcrlbracket, hold) || 30846 | token_is(token_t::e_lsqrbracket, hold) ; 30847 | break; 30848 | 30849 | default : return true; 30850 | } 30851 | 30852 | if (implied_mul) 30853 | { 30854 | if (!settings_.commutative_check_enabled()) 30855 | { 30856 | set_error(make_error( 30857 | parser_error::e_syntax, 30858 | current_token(), 30859 | "ERR229 - Invalid sequence of brackets", 30860 | exprtk_error_location)); 30861 | 30862 | return false; 30863 | } 30864 | else if (token_t::e_eof != current_token().type) 30865 | { 30866 | lexer().insert_front(current_token().type); 30867 | lexer().insert_front(token_t::e_mul); 30868 | next_token(); 30869 | } 30870 | } 30871 | 30872 | return true; 30873 | } 30874 | 30875 | typedef typename interval_container_t<const void*>::interval_t interval_t; 30876 | typedef interval_container_t<const void*> immutable_memory_map_t; 30877 | typedef std::map<interval_t,token_t> immutable_symtok_map_t; 30878 | 30879 | inline interval_t make_memory_range(const T& t) 30880 | { 30881 | const T* begin = reinterpret_cast<const T*>(&t); 30882 | const T* end = begin + 1; 30883 | return interval_t(begin, end); 30884 | } 30885 | 30886 | inline interval_t make_memory_range(const T* begin, const std::size_t size) 30887 | { 30888 | return interval_t(begin, begin + size); 30889 | } 30890 | 30891 | inline interval_t make_memory_range(details::char_cptr begin, const std::size_t size) 30892 | { 30893 | return interval_t(begin, begin + size); 30894 | } 30895 | 30896 | void lodge_immutable_symbol(const lexer::token& token, const interval_t interval) 30897 | { 30898 | immutable_memory_map_.add_interval(interval); 30899 | immutable_symtok_map_[interval] = token; 30900 | } 30901 | 30902 | inline expression_node_ptr parse_symtab_symbol() 30903 | { 30904 | const std::string symbol = current_token().value; 30905 | 30906 | // Are we dealing with a variable or a special constant? 30907 | typedef typename symtab_store::variable_context var_ctxt_t; 30908 | var_ctxt_t var_ctx = symtab_store_.get_variable_context(symbol); 30909 | 30910 | if (var_ctx.variable) 30911 | { 30912 | assert(var_ctx.symbol_table); 30913 | 30914 | expression_node_ptr result_variable = var_ctx.variable; 30915 | 30916 | if (symtab_store_.is_constant_node(symbol)) 30917 | { 30918 | result_variable = expression_generator_(var_ctx.variable->value()); 30919 | } 30920 | else if (symbol_table_t::e_immutable == var_ctx.symbol_table->mutability()) 30921 | { 30922 | lodge_immutable_symbol(current_token(), make_memory_range(var_ctx.variable->ref())); 30923 | result_variable = var_ctx.variable; 30924 | } 30925 | 30926 | if (!post_variable_process(symbol)) 30927 | return error_node(); 30928 | 30929 | lodge_symbol(symbol, e_st_variable); 30930 | 30931 | next_token(); 30932 | 30933 | return result_variable; 30934 | } 30935 | 30936 | // Are we dealing with a locally defined variable, vector or string? 30937 | if (!sem_.empty()) 30938 | { 30939 | scope_element& se = sem_.get_active_element(symbol); 30940 | 30941 | if (se.active && details::imatch(se.name, symbol)) 30942 | { 30943 | if ( 30944 | (scope_element::e_variable == se.type) || 30945 | (scope_element::e_literal == se.type) 30946 | ) 30947 | { 30948 | se.active = true; 30949 | lodge_symbol(symbol, e_st_local_variable); 30950 | 30951 | if (!post_variable_process(symbol)) 30952 | return error_node(); 30953 | 30954 | next_token(); 30955 | 30956 | return (scope_element::e_variable == se.type) ? 30957 | se.var_node : 30958 | expression_generator_(se.var_node->value()); 30959 | } 30960 | else if (scope_element::e_vector == se.type) 30961 | { 30962 | return parse_vector(); 30963 | } 30964 | #ifndef exprtk_disable_string_capabilities 30965 | else if (scope_element::e_string == se.type) 30966 | { 30967 | return parse_string(); 30968 | } 30969 | #endif 30970 | } 30971 | } 30972 | 30973 | #ifndef exprtk_disable_string_capabilities 30974 | // Are we dealing with a string variable? 30975 | if (symtab_store_.is_stringvar(symbol)) 30976 | { 30977 | return parse_string(); 30978 | } 30979 | #endif 30980 | 30981 | { 30982 | // Are we dealing with a function? 30983 | ifunction<T>* function = symtab_store_.get_function(symbol); 30984 | 30985 | if (function) 30986 | { 30987 | lodge_symbol(symbol, e_st_function); 30988 | 30989 | expression_node_ptr func_node = 30990 | parse_function_invocation(function,symbol); 30991 | 30992 | if (func_node) 30993 | return func_node; 30994 | else 30995 | { 30996 | set_error(make_error( 30997 | parser_error::e_syntax, 30998 | current_token(), 30999 | "ERR230 - Failed to generate node for function: '" + symbol + "'", 31000 | exprtk_error_location)); 31001 | 31002 | return error_node(); 31003 | } 31004 | } 31005 | } 31006 | 31007 | { 31008 | // Are we dealing with a vararg function? 31009 | ivararg_function<T>* vararg_function = symtab_store_.get_vararg_function(symbol); 31010 | 31011 | if (vararg_function) 31012 | { 31013 | lodge_symbol(symbol, e_st_function); 31014 | 31015 | expression_node_ptr vararg_func_node = 31016 | parse_vararg_function_call(vararg_function, symbol); 31017 | 31018 | if (vararg_func_node) 31019 | return vararg_func_node; 31020 | else 31021 | { 31022 | set_error(make_error( 31023 | parser_error::e_syntax, 31024 | current_token(), 31025 | "ERR231 - Failed to generate node for vararg function: '" + symbol + "'", 31026 | exprtk_error_location)); 31027 | 31028 | return error_node(); 31029 | } 31030 | } 31031 | } 31032 | 31033 | { 31034 | // Are we dealing with a vararg generic function? 31035 | igeneric_function<T>* generic_function = symtab_store_.get_generic_function(symbol); 31036 | 31037 | if (generic_function) 31038 | { 31039 | lodge_symbol(symbol, e_st_function); 31040 | 31041 | expression_node_ptr genericfunc_node = 31042 | parse_generic_function_call(generic_function, symbol); 31043 | 31044 | if (genericfunc_node) 31045 | return genericfunc_node; 31046 | else 31047 | { 31048 | set_error(make_error( 31049 | parser_error::e_syntax, 31050 | current_token(), 31051 | "ERR232 - Failed to generate node for generic function: '" + symbol + "'", 31052 | exprtk_error_location)); 31053 | 31054 | return error_node(); 31055 | } 31056 | } 31057 | } 31058 | 31059 | #ifndef exprtk_disable_string_capabilities 31060 | { 31061 | // Are we dealing with a vararg string returning function? 31062 | igeneric_function<T>* string_function = symtab_store_.get_string_function(symbol); 31063 | 31064 | if (string_function) 31065 | { 31066 | lodge_symbol(symbol, e_st_function); 31067 | 31068 | expression_node_ptr stringfunc_node = 31069 | parse_string_function_call(string_function, symbol); 31070 | 31071 | if (stringfunc_node) 31072 | return stringfunc_node; 31073 | else 31074 | { 31075 | set_error(make_error( 31076 | parser_error::e_syntax, 31077 | current_token(), 31078 | "ERR233 - Failed to generate node for string function: '" + symbol + "'", 31079 | exprtk_error_location)); 31080 | 31081 | return error_node(); 31082 | } 31083 | } 31084 | } 31085 | 31086 | { 31087 | // Are we dealing with a vararg overloaded scalar/string returning function? 31088 | igeneric_function<T>* overload_function = symtab_store_.get_overload_function(symbol); 31089 | 31090 | if (overload_function) 31091 | { 31092 | lodge_symbol(symbol, e_st_function); 31093 | 31094 | expression_node_ptr overloadfunc_node = 31095 | parse_overload_function_call(overload_function, symbol); 31096 | 31097 | if (overloadfunc_node) 31098 | return overloadfunc_node; 31099 | else 31100 | { 31101 | set_error(make_error( 31102 | parser_error::e_syntax, 31103 | current_token(), 31104 | "ERR234 - Failed to generate node for overload function: '" + symbol + "'", 31105 | exprtk_error_location)); 31106 | 31107 | return error_node(); 31108 | } 31109 | } 31110 | } 31111 | #endif 31112 | 31113 | // Are we dealing with a vector? 31114 | if (symtab_store_.is_vector(symbol)) 31115 | { 31116 | lodge_symbol(symbol, e_st_vector); 31117 | return parse_vector(); 31118 | } 31119 | 31120 | if (details::is_reserved_symbol(symbol)) 31121 | { 31122 | if ( 31123 | settings_.function_enabled(symbol) || 31124 | !details::is_base_function(symbol) 31125 | ) 31126 | { 31127 | set_error(make_error( 31128 | parser_error::e_syntax, 31129 | current_token(), 31130 | "ERR235 - Invalid use of reserved symbol '" + symbol + "'", 31131 | exprtk_error_location)); 31132 | 31133 | return error_node(); 31134 | } 31135 | } 31136 | 31137 | // Should we handle unknown symbols? 31138 | if (resolve_unknown_symbol_ && unknown_symbol_resolver_) 31139 | { 31140 | if (!(settings_.rsrvd_sym_usr_disabled() && details::is_reserved_symbol(symbol))) 31141 | { 31142 | symbol_table_t& symtab = symtab_store_.get_symbol_table(); 31143 | 31144 | std::string error_message; 31145 | 31146 | if (unknown_symbol_resolver::e_usrmode_default == unknown_symbol_resolver_->mode) 31147 | { 31148 | T default_value = T(0); 31149 | 31150 | typename unknown_symbol_resolver::usr_symbol_type usr_symbol_type = unknown_symbol_resolver::e_usr_unknown_type; 31151 | 31152 | if (unknown_symbol_resolver_->process(symbol, usr_symbol_type, default_value, error_message)) 31153 | { 31154 | bool create_result = false; 31155 | 31156 | switch (usr_symbol_type) 31157 | { 31158 | case unknown_symbol_resolver::e_usr_variable_type : 31159 | create_result = symtab.create_variable(symbol, default_value); 31160 | break; 31161 | 31162 | case unknown_symbol_resolver::e_usr_constant_type : 31163 | create_result = symtab.add_constant(symbol, default_value); 31164 | break; 31165 | 31166 | default : create_result = false; 31167 | } 31168 | 31169 | if (create_result) 31170 | { 31171 | expression_node_ptr var = symtab_store_.get_variable(symbol); 31172 | 31173 | if (var) 31174 | { 31175 | if (symtab_store_.is_constant_node(symbol)) 31176 | { 31177 | var = expression_generator_(var->value()); 31178 | } 31179 | 31180 | lodge_symbol(symbol, e_st_variable); 31181 | 31182 | if (!post_variable_process(symbol)) 31183 | return error_node(); 31184 | 31185 | next_token(); 31186 | 31187 | return var; 31188 | } 31189 | } 31190 | } 31191 | 31192 | set_error(make_error( 31193 | parser_error::e_symtab, 31194 | current_token(), 31195 | "ERR236 - Failed to create variable: '" + symbol + "'" + 31196 | (error_message.empty() ? "" : " - " + error_message), 31197 | exprtk_error_location)); 31198 | 31199 | } 31200 | else if (unknown_symbol_resolver::e_usrmode_extended == unknown_symbol_resolver_->mode) 31201 | { 31202 | if (unknown_symbol_resolver_->process(symbol, symtab, error_message)) 31203 | { 31204 | expression_node_ptr result = parse_symtab_symbol(); 31205 | 31206 | if (result) 31207 | { 31208 | return result; 31209 | } 31210 | } 31211 | 31212 | set_error(make_error( 31213 | parser_error::e_symtab, 31214 | current_token(), 31215 | "ERR237 - Failed to resolve symbol: '" + symbol + "'" + 31216 | (error_message.empty() ? "" : " - " + error_message), 31217 | exprtk_error_location)); 31218 | } 31219 | 31220 | return error_node(); 31221 | } 31222 | } 31223 | 31224 | set_error(make_error( 31225 | parser_error::e_syntax, 31226 | current_token(), 31227 | "ERR238 - Undefined symbol: '" + symbol + "'", 31228 | exprtk_error_location)); 31229 | 31230 | return error_node(); 31231 | } 31232 | 31233 | inline expression_node_ptr check_block_statement_closure(expression_node_ptr expression) 31234 | { 31235 | if ( 31236 | expression && 31237 | ( 31238 | (current_token().type == token_t::e_symbol) || 31239 | (current_token().type == token_t::e_number) 31240 | ) 31241 | ) 31242 | { 31243 | free_node(node_allocator_, expression); 31244 | 31245 | set_error(make_error( 31246 | parser_error::e_syntax, 31247 | current_token(), 31248 | "ERR239 - Invalid syntax '" + current_token().value + "' possible missing operator or context", 31249 | exprtk_error_location)); 31250 | 31251 | return error_node(); 31252 | } 31253 | 31254 | return expression; 31255 | } 31256 | 31257 | inline expression_node_ptr parse_symbol() 31258 | { 31259 | static const std::string symbol_if = "if" ; 31260 | static const std::string symbol_while = "while" ; 31261 | static const std::string symbol_repeat = "repeat" ; 31262 | static const std::string symbol_for = "for" ; 31263 | static const std::string symbol_switch = "switch" ; 31264 | static const std::string symbol_null = "null" ; 31265 | static const std::string symbol_break = "break" ; 31266 | static const std::string symbol_continue = "continue" 31267 | static const std::string symbol_var = "var" ; 31268 | static const std::string symbol_const = "const" ; 31269 | static const std::string symbol_swap = "swap" ; 31270 | static const std::string symbol_return = "return" ; 31271 | static const std::string symbol_not = "not" ; 31272 | static const std::string symbol_assert = "assert" ; 31273 | 31274 | const std::string symbol = current_token().value; 31275 | 31276 | if (valid_vararg_operation(symbol)) 31277 | { 31278 | return parse_vararg_function(); 31279 | } 31280 | else if (details::imatch(symbol, symbol_not)) 31281 | { 31282 | return parse_not_statement(); 31283 | } 31284 | else if (valid_base_operation(symbol)) 31285 | { 31286 | return parse_base_operation(); 31287 | } 31288 | else if ( 31289 | details::imatch(symbol, symbol_if) && 31290 | settings_.control_struct_enabled(symbol) 31291 | ) 31292 | { 31293 | return parse_conditional_statement(); 31294 | } 31295 | else if ( 31296 | details::imatch(symbol, symbol_while) && 31297 | settings_.control_struct_enabled(symbol) 31298 | ) 31299 | { 31300 | return check_block_statement_closure(parse_while_loop()); 31301 | } 31302 | else if ( 31303 | details::imatch(symbol, symbol_repeat) && 31304 | settings_.control_struct_enabled(symbol) 31305 | ) 31306 | { 31307 | return check_block_statement_closure(parse_repeat_until_loop()); 31308 | } 31309 | else if ( 31310 | details::imatch(symbol, symbol_for) && 31311 | settings_.control_struct_enabled(symbol) 31312 | ) 31313 | { 31314 | return check_block_statement_closure(parse_for_loop()); 31315 | } 31316 | else if ( 31317 | details::imatch(symbol, symbol_switch) && 31318 | settings_.control_struct_enabled(symbol) 31319 | ) 31320 | { 31321 | return check_block_statement_closure(parse_switch_statement()); 31322 | } 31323 | else if (details::is_valid_sf_symbol(symbol)) 31324 | { 31325 | return parse_special_function(); 31326 | } 31327 | else if (details::imatch(symbol, symbol_null)) 31328 | { 31329 | return parse_null_statement(); 31330 | } 31331 | #ifndef exprtk_disable_break_continue 31332 | else if (details::imatch(symbol, symbol_break)) 31333 | { 31334 | return parse_break_statement(); 31335 | } 31336 | else if (details::imatch(symbol, symbol_continue)) 31337 | { 31338 | return parse_continue_statement(); 31339 | } 31340 | #endif 31341 | else if (details::imatch(symbol, symbol_var)) 31342 | { 31343 | return parse_define_var_statement(); 31344 | } 31345 | else if (details::imatch(symbol, symbol_const)) 31346 | { 31347 | return parse_define_constvar_statement(); 31348 | } 31349 | else if (details::imatch(symbol, symbol_swap)) 31350 | { 31351 | return parse_swap_statement(); 31352 | } 31353 | #ifndef exprtk_disable_return_statement 31354 | else if ( 31355 | details::imatch(symbol, symbol_return) && 31356 | settings_.control_struct_enabled(symbol) 31357 | ) 31358 | { 31359 | return check_block_statement_closure(parse_return_statement()); 31360 | } 31361 | #endif 31362 | else if (details::imatch(symbol, symbol_assert)) 31363 | { 31364 | return parse_assert_statement(); 31365 | } 31366 | else if (symtab_store_.valid() || !sem_.empty()) 31367 | { 31368 | return parse_symtab_symbol(); 31369 | } 31370 | else 31371 | { 31372 | set_error(make_error( 31373 | parser_error::e_symtab, 31374 | current_token(), 31375 | "ERR240 - Unknown variable or function encountered. Symbol table(s) " 31376 | "is either invalid or does not contain symbol: '" + symbol + "'", 31377 | exprtk_error_location)); 31378 | 31379 | return error_node(); 31380 | } 31381 | } 31382 | 31383 | inline expression_node_ptr parse_branch(precedence_level precedence = e_level00) 31384 | { 31385 | stack_limit_handler slh(*this); 31386 | 31387 | if (!slh) 31388 | { 31389 | return error_node(); 31390 | } 31391 | 31392 | expression_node_ptr branch = error_node(); 31393 | 31394 | if (token_t::e_number == current_token().type) 31395 | { 31396 | T numeric_value = T(0); 31397 | 31398 | if (details::string_to_real(current_token().value, numeric_value)) 31399 | { 31400 | expression_node_ptr literal_exp = expression_generator_(numeric_value); 31401 | 31402 | if (0 == literal_exp) 31403 | { 31404 | set_error(make_error( 31405 | parser_error::e_numeric, 31406 | current_token(), 31407 | "ERR241 - Failed generate node for scalar: '" + current_token().value + "'", 31408 | exprtk_error_location)); 31409 | 31410 | return error_node(); 31411 | } 31412 | 31413 | next_token(); 31414 | branch = literal_exp; 31415 | } 31416 | else 31417 | { 31418 | set_error(make_error( 31419 | parser_error::e_numeric, 31420 | current_token(), 31421 | "ERR242 - Failed to convert '" + current_token().value + "' to a number", 31422 | exprtk_error_location)); 31423 | 31424 | return error_node(); 31425 | } 31426 | } 31427 | else if (token_t::e_symbol == current_token().type) 31428 | { 31429 | branch = parse_symbol(); 31430 | } 31431 | #ifndef exprtk_disable_string_capabilities 31432 | else if (token_t::e_string == current_token().type) 31433 | { 31434 | branch = parse_const_string(); 31435 | } 31436 | #endif 31437 | else if (token_t::e_lbracket == current_token().type) 31438 | { 31439 | next_token(); 31440 | 31441 | if (0 == (branch = parse_expression())) 31442 | { 31443 | return error_node(); 31444 | } 31445 | 31446 | token_is(token_t::e_eof); 31447 | 31448 | if (!token_is(token_t::e_rbracket)) 31449 | { 31450 | set_error(make_error( 31451 | parser_error::e_syntax, 31452 | current_token(), 31453 | "ERR243 - Expected ')' instead of: '" + current_token().value + "'", 31454 | exprtk_error_location)); 31455 | 31456 | details::free_node(node_allocator_, branch); 31457 | 31458 | return error_node(); 31459 | } 31460 | else if (!post_bracket_process(token_t::e_lbracket,branch)) 31461 | { 31462 | details::free_node(node_allocator_, branch); 31463 | 31464 | return error_node(); 31465 | } 31466 | 31467 | parse_pending_vector_index_operator(branch); 31468 | } 31469 | else if (token_t::e_lsqrbracket == current_token().type) 31470 | { 31471 | next_token(); 31472 | 31473 | if (0 == (branch = parse_expression())) 31474 | return error_node(); 31475 | else if (!token_is(token_t::e_rsqrbracket)) 31476 | { 31477 | set_error(make_error( 31478 | parser_error::e_syntax, 31479 | current_token(), 31480 | "ERR244 - Expected ']' instead of: '" + current_token().value + "'", 31481 | exprtk_error_location)); 31482 | 31483 | details::free_node(node_allocator_, branch); 31484 | 31485 | return error_node(); 31486 | } 31487 | else if (!post_bracket_process(token_t::e_lsqrbracket,branch)) 31488 | { 31489 | details::free_node(node_allocator_, branch); 31490 | 31491 | return error_node(); 31492 | } 31493 | } 31494 | else if (token_t::e_lcrlbracket == current_token().type) 31495 | { 31496 | next_token(); 31497 | 31498 | if (0 == (branch = parse_expression())) 31499 | return error_node(); 31500 | else if (!token_is(token_t::e_rcrlbracket)) 31501 | { 31502 | set_error(make_error( 31503 | parser_error::e_syntax, 31504 | current_token(), 31505 | "ERR245 - Expected '}' instead of: '" + current_token().value + "'", 31506 | exprtk_error_location)); 31507 | 31508 | details::free_node(node_allocator_, branch); 31509 | 31510 | return error_node(); 31511 | } 31512 | else if (!post_bracket_process(token_t::e_lcrlbracket,branch)) 31513 | { 31514 | details::free_node(node_allocator_, branch); 31515 | 31516 | return error_node(); 31517 | } 31518 | } 31519 | else if (token_t::e_sub == current_token().type) 31520 | { 31521 | next_token(); 31522 | branch = parse_expression(e_level11); 31523 | 31524 | if ( 31525 | branch && 31526 | !( 31527 | details::is_neg_unary_node (branch) && 31528 | simplify_unary_negation_branch(branch) 31529 | ) 31530 | ) 31531 | { 31532 | expression_node_ptr result = expression_generator_(details::e_neg,branch); 31533 | 31534 | if (0 == result) 31535 | { 31536 | details::free_node(node_allocator_, branch); 31537 | 31538 | return error_node(); 31539 | } 31540 | else 31541 | branch = result; 31542 | } 31543 | } 31544 | else if (token_t::e_add == current_token().type) 31545 | { 31546 | next_token(); 31547 | branch = parse_expression(e_level13); 31548 | } 31549 | else if (token_t::e_eof == current_token().type) 31550 | { 31551 | set_error(make_error( 31552 | parser_error::e_syntax, 31553 | current_token(), 31554 | "ERR246 - Premature end of expression[1]", 31555 | exprtk_error_location)); 31556 | 31557 | return error_node(); 31558 | } 31559 | else 31560 | { 31561 | set_error(make_error( 31562 | parser_error::e_syntax, 31563 | current_token(), 31564 | "ERR247 - Premature end of expression[2]", 31565 | exprtk_error_location)); 31566 | 31567 | return error_node(); 31568 | } 31569 | 31570 | if ( 31571 | branch && 31572 | (e_level00 == precedence) && 31573 | token_is(token_t::e_ternary,prsrhlpr_t::e_hold) 31574 | ) 31575 | { 31576 | branch = parse_ternary_conditional_statement(branch); 31577 | } 31578 | 31579 | parse_pending_string_rangesize(branch); 31580 | 31581 | return branch; 31582 | } 31583 | 31584 | template <typename Type> 31585 | class expression_generator 31586 | { 31587 | public: 31588 | 31589 | typedef details::expression_node<Type>* expression_node_ptr; 31590 | typedef expression_node_ptr (*synthesize_functor_t)(expression_generator<T>&, const details::operator_type& operation, expression_node_ptr (&branch)[2]); 31591 | typedef std::map<std::string,synthesize_functor_t> synthesize_map_t; 31592 | typedef typename exprtk::parser<Type> parser_t; 31593 | typedef const Type& vtype; 31594 | typedef const Type ctype; 31595 | 31596 | inline void init_synthesize_map() 31597 | { 31598 | #ifndef exprtk_disable_enhanced_features 31599 | synthesize_map_["(v)o(v)"] = synthesize_vov_expression::process; 31600 | synthesize_map_["(c)o(v)"] = synthesize_cov_expression::process; 31601 | synthesize_map_["(v)o(c)"] = synthesize_voc_expression::process; 31602 | 31603 | #define register_synthezier(S) \ 31604 | synthesize_map_[S ::node_type::id()] = S ::process; \ 31605 | 31606 | register_synthezier(synthesize_vovov_expression0) 31607 | register_synthezier(synthesize_vovov_expression1) 31608 | register_synthezier(synthesize_vovoc_expression0) 31609 | register_synthezier(synthesize_vovoc_expression1) 31610 | register_synthezier(synthesize_vocov_expression0) 31611 | register_synthezier(synthesize_vocov_expression1) 31612 | register_synthezier(synthesize_covov_expression0) 31613 | register_synthezier(synthesize_covov_expression1) 31614 | register_synthezier(synthesize_covoc_expression0) 31615 | register_synthezier(synthesize_covoc_expression1) 31616 | register_synthezier(synthesize_cocov_expression1) 31617 | register_synthezier(synthesize_vococ_expression0) 31618 | 31619 | register_synthezier(synthesize_vovovov_expression0) 31620 | register_synthezier(synthesize_vovovoc_expression0) 31621 | register_synthezier(synthesize_vovocov_expression0) 31622 | register_synthezier(synthesize_vocovov_expression0) 31623 | register_synthezier(synthesize_covovov_expression0) 31624 | register_synthezier(synthesize_covocov_expression0) 31625 | register_synthezier(synthesize_vocovoc_expression0) 31626 | register_synthezier(synthesize_covovoc_expression0) 31627 | register_synthezier(synthesize_vococov_expression0) 31628 | 31629 | register_synthezier(synthesize_vovovov_expression1) 31630 | register_synthezier(synthesize_vovovoc_expression1) 31631 | register_synthezier(synthesize_vovocov_expression1) 31632 | register_synthezier(synthesize_vocovov_expression1) 31633 | register_synthezier(synthesize_covovov_expression1) 31634 | register_synthezier(synthesize_covocov_expression1) 31635 | register_synthezier(synthesize_vocovoc_expression1) 31636 | register_synthezier(synthesize_covovoc_expression1) 31637 | register_synthezier(synthesize_vococov_expression1) 31638 | 31639 | register_synthezier(synthesize_vovovov_expression2) 31640 | register_synthezier(synthesize_vovovoc_expression2) 31641 | register_synthezier(synthesize_vovocov_expression2) 31642 | register_synthezier(synthesize_vocovov_expression2) 31643 | register_synthezier(synthesize_covovov_expression2) 31644 | register_synthezier(synthesize_covocov_expression2) 31645 | register_synthezier(synthesize_vocovoc_expression2) 31646 | register_synthezier(synthesize_covovoc_expression2) 31647 | 31648 | register_synthezier(synthesize_vovovov_expression3) 31649 | register_synthezier(synthesize_vovovoc_expression3) 31650 | register_synthezier(synthesize_vovocov_expression3) 31651 | register_synthezier(synthesize_vocovov_expression3) 31652 | register_synthezier(synthesize_covovov_expression3) 31653 | register_synthezier(synthesize_covocov_expression3) 31654 | register_synthezier(synthesize_vocovoc_expression3) 31655 | register_synthezier(synthesize_covovoc_expression3) 31656 | register_synthezier(synthesize_vococov_expression3) 31657 | 31658 | register_synthezier(synthesize_vovovov_expression4) 31659 | register_synthezier(synthesize_vovovoc_expression4) 31660 | register_synthezier(synthesize_vovocov_expression4) 31661 | register_synthezier(synthesize_vocovov_expression4) 31662 | register_synthezier(synthesize_covovov_expression4) 31663 | register_synthezier(synthesize_covocov_expression4) 31664 | register_synthezier(synthesize_vocovoc_expression4) 31665 | register_synthezier(synthesize_covovoc_expression4) 31666 | 31667 | #undef register_synthezier 31668 | #endif 31669 | } 31670 | 31671 | inline void set_parser(parser_t& p) 31672 | { 31673 | parser_ = &p; 31674 | } 31675 | 31676 | inline void set_uom(unary_op_map_t& unary_op_map) 31677 | { 31678 | unary_op_map_ = &unary_op_map; 31679 | } 31680 | 31681 | inline void set_bom(binary_op_map_t& binary_op_map) 31682 | { 31683 | binary_op_map_ = &binary_op_map; 31684 | } 31685 | 31686 | inline void set_ibom(inv_binary_op_map_t& inv_binary_op_map) 31687 | { 31688 | inv_binary_op_map_ = &inv_binary_op_map; 31689 | } 31690 | 31691 | inline void set_sf3m(sf3_map_t& sf3_map) 31692 | { 31693 | sf3_map_ = &sf3_map; 31694 | } 31695 | 31696 | inline void set_sf4m(sf4_map_t& sf4_map) 31697 | { 31698 | sf4_map_ = &sf4_map; 31699 | } 31700 | 31701 | inline void set_allocator(details::node_allocator& na) 31702 | { 31703 | node_allocator_ = &na; 31704 | } 31705 | 31706 | inline void set_strength_reduction_state(const bool enabled) 31707 | { 31708 | strength_reduction_enabled_ = enabled; 31709 | } 31710 | 31711 | inline bool strength_reduction_enabled() const 31712 | { 31713 | return strength_reduction_enabled_; 31714 | } 31715 | 31716 | inline bool valid_operator(const details::operator_type& operation, binary_functor_t& bop) 31717 | { 31718 | typename binary_op_map_t::iterator bop_itr = binary_op_map_->find(operation); 31719 | 31720 | if (binary_op_map_->end() == bop_itr) 31721 | return false; 31722 | 31723 | bop = bop_itr->second; 31724 | 31725 | return true; 31726 | } 31727 | 31728 | inline bool valid_operator(const details::operator_type& operation, unary_functor_t& uop) 31729 | { 31730 | typename unary_op_map_t::iterator uop_itr = unary_op_map_->find(operation); 31731 | 31732 | if ((*unary_op_map_).end() == uop_itr) 31733 | return false; 31734 | 31735 | uop = uop_itr->second; 31736 | 31737 | return true; 31738 | } 31739 | 31740 | inline details::operator_type get_operator(const binary_functor_t& bop) const 31741 | { 31742 | return (*inv_binary_op_map_).find(bop)->second; 31743 | } 31744 | 31745 | inline expression_node_ptr operator() (const Type& v) const 31746 | { 31747 | return node_allocator_->allocate<literal_node_t>(v); 31748 | } 31749 | 31750 | #ifndef exprtk_disable_string_capabilities 31751 | inline expression_node_ptr operator() (const std::string& s) const 31752 | { 31753 | return node_allocator_->allocate<string_literal_node_t>(s); 31754 | } 31755 | 31756 | inline expression_node_ptr operator() (std::string& s, range_t& rp) const 31757 | { 31758 | return node_allocator_->allocate_rr<string_range_node_t>(s,rp); 31759 | } 31760 | 31761 | inline expression_node_ptr operator() (const std::string& s, range_t& rp) const 31762 | { 31763 | return node_allocator_->allocate_tt<const_string_range_node_t>(s,rp); 31764 | } 31765 | 31766 | inline expression_node_ptr operator() (expression_node_ptr branch, range_t& rp) const 31767 | { 31768 | if (is_generally_string_node(branch)) 31769 | return node_allocator_->allocate_tt<generic_string_range_node_t>(branch,rp); 31770 | else 31771 | return error_node(); 31772 | } 31773 | #endif 31774 | 31775 | inline bool unary_optimisable(const details::operator_type& operation) const 31776 | { 31777 | return (details::e_abs == operation) || (details::e_acos == operation) || 31778 | (details::e_acosh == operation) || (details::e_asin == operation) || 31779 | (details::e_asinh == operation) || (details::e_atan == operation) || 31780 | (details::e_atanh == operation) || (details::e_ceil == operation) || 31781 | (details::e_cos == operation) || (details::e_cosh == operation) || 31782 | (details::e_exp == operation) || (details::e_expm1 == operation) || 31783 | (details::e_floor == operation) || (details::e_log == operation) || 31784 | (details::e_log10 == operation) || (details::e_log2 == operation) || 31785 | (details::e_log1p == operation) || (details::e_neg == operation) || 31786 | (details::e_pos == operation) || (details::e_round == operation) || 31787 | (details::e_sin == operation) || (details::e_sinc == operation) || 31788 | (details::e_sinh == operation) || (details::e_sqrt == operation) || 31789 | (details::e_tan == operation) || (details::e_tanh == operation) || 31790 | (details::e_cot == operation) || (details::e_sec == operation) || 31791 | (details::e_csc == operation) || (details::e_r2d == operation) || 31792 | (details::e_d2r == operation) || (details::e_d2g == operation) || 31793 | (details::e_g2d == operation) || (details::e_notl == operation) || 31794 | (details::e_sgn == operation) || (details::e_erf == operation) || 31795 | (details::e_erfc == operation) || (details::e_ncdf == operation) || 31796 | (details::e_frac == operation) || (details::e_trunc == operation) ; 31797 | } 31798 | 31799 | inline bool sf3_optimisable(const std::string& sf3id, trinary_functor_t& tfunc) const 31800 | { 31801 | typename sf3_map_t::const_iterator itr = sf3_map_->find(sf3id); 31802 | 31803 | if (sf3_map_->end() == itr) 31804 | return false; 31805 | else 31806 | tfunc = itr->second.first; 31807 | 31808 | return true; 31809 | } 31810 | 31811 | inline bool sf4_optimisable(const std::string& sf4id, quaternary_functor_t& qfunc) const 31812 | { 31813 | typename sf4_map_t::const_iterator itr = sf4_map_->find(sf4id); 31814 | 31815 | if (sf4_map_->end() == itr) 31816 | return false; 31817 | else 31818 | qfunc = itr->second.first; 31819 | 31820 | return true; 31821 | } 31822 | 31823 | inline bool sf3_optimisable(const std::string& sf3id, details::operator_type& operation) const 31824 | { 31825 | typename sf3_map_t::const_iterator itr = sf3_map_->find(sf3id); 31826 | 31827 | if (sf3_map_->end() == itr) 31828 | return false; 31829 | else 31830 | operation = itr->second.second; 31831 | 31832 | return true; 31833 | } 31834 | 31835 | inline bool sf4_optimisable(const std::string& sf4id, details::operator_type& operation) const 31836 | { 31837 | typename sf4_map_t::const_iterator itr = sf4_map_->find(sf4id); 31838 | 31839 | if (sf4_map_->end() == itr) 31840 | return false; 31841 | else 31842 | operation = itr->second.second; 31843 | 31844 | return true; 31845 | } 31846 | 31847 | inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[1]) 31848 | { 31849 | if (0 == branch[0]) 31850 | { 31851 | return error_node(); 31852 | } 31853 | else if (details::is_null_node(branch[0])) 31854 | { 31855 | return branch[0]; 31856 | } 31857 | else if (details::is_break_node(branch[0])) 31858 | { 31859 | return error_node(); 31860 | } 31861 | else if (details::is_continue_node(branch[0])) 31862 | { 31863 | return error_node(); 31864 | } 31865 | else if (details::is_constant_node(branch[0])) 31866 | { 31867 | return synthesize_expression<unary_node_t,1>(operation,branch); 31868 | } 31869 | else if (unary_optimisable(operation) && details::is_variable_node(branch[0])) 31870 | { 31871 | return synthesize_uv_expression(operation,branch); 31872 | } 31873 | else if (unary_optimisable(operation) && details::is_ivector_node(branch[0])) 31874 | { 31875 | return synthesize_uvec_expression(operation,branch); 31876 | } 31877 | else 31878 | return synthesize_unary_expression(operation,branch); 31879 | } 31880 | 31881 | inline bool is_assignment_operation(const details::operator_type& operation) const 31882 | { 31883 | return ( 31884 | (details::e_addass == operation) || 31885 | (details::e_subass == operation) || 31886 | (details::e_mulass == operation) || 31887 | (details::e_divass == operation) || 31888 | (details::e_modass == operation) 31889 | ) && 31890 | parser_->settings_.assignment_enabled(operation); 31891 | } 31892 | 31893 | #ifndef exprtk_disable_string_capabilities 31894 | inline bool valid_string_operation(const details::operator_type& operation) const 31895 | { 31896 | return (details::e_add == operation) || 31897 | (details::e_lt == operation) || 31898 | (details::e_lte == operation) || 31899 | (details::e_gt == operation) || 31900 | (details::e_gte == operation) || 31901 | (details::e_eq == operation) || 31902 | (details::e_ne == operation) || 31903 | (details::e_in == operation) || 31904 | (details::e_like == operation) || 31905 | (details::e_ilike == operation) || 31906 | (details::e_assign == operation) || 31907 | (details::e_addass == operation) || 31908 | (details::e_swap == operation) ; 31909 | } 31910 | #else 31911 | inline bool valid_string_operation(const details::operator_type&) const 31912 | { 31913 | return false; 31914 | } 31915 | #endif 31916 | 31917 | inline std::string to_str(const details::operator_type& operation) const 31918 | { 31919 | switch (operation) 31920 | { 31921 | case details::e_add : return "+" ; 31922 | case details::e_sub : return "-" ; 31923 | case details::e_mul : return "*" ; 31924 | case details::e_div : return "/" ; 31925 | case details::e_mod : return "%" ; 31926 | case details::e_pow : return "^" ; 31927 | case details::e_lt : return "<" ; 31928 | case details::e_lte : return "<=" ; 31929 | case details::e_gt : return ">" ; 31930 | case details::e_gte : return ">=" ; 31931 | case details::e_eq : return "==" ; 31932 | case details::e_ne : return "!=" ; 31933 | case details::e_and : return "and" ; 31934 | case details::e_nand : return "nand" ; 31935 | case details::e_or : return "or" ; 31936 | case details::e_nor : return "nor" ; 31937 | case details::e_xor : return "xor" ; 31938 | case details::e_xnor : return "xnor" ; 31939 | default : return "UNKNOWN" 31940 | } 31941 | } 31942 | 31943 | inline bool operation_optimisable(const details::operator_type& operation) const 31944 | { 31945 | return (details::e_add == operation) || 31946 | (details::e_sub == operation) || 31947 | (details::e_mul == operation) || 31948 | (details::e_div == operation) || 31949 | (details::e_mod == operation) || 31950 | (details::e_pow == operation) || 31951 | (details::e_lt == operation) || 31952 | (details::e_lte == operation) || 31953 | (details::e_gt == operation) || 31954 | (details::e_gte == operation) || 31955 | (details::e_eq == operation) || 31956 | (details::e_ne == operation) || 31957 | (details::e_and == operation) || 31958 | (details::e_nand == operation) || 31959 | (details::e_or == operation) || 31960 | (details::e_nor == operation) || 31961 | (details::e_xor == operation) || 31962 | (details::e_xnor == operation) ; 31963 | } 31964 | 31965 | inline std::string branch_to_id(expression_node_ptr branch) const 31966 | { 31967 | static const std::string null_str ("(null)" ); 31968 | static const std::string const_str ("(c)" ); 31969 | static const std::string var_str ("(v)" ); 31970 | static const std::string vov_str ("(vov)" ); 31971 | static const std::string cov_str ("(cov)" ); 31972 | static const std::string voc_str ("(voc)" ); 31973 | static const std::string str_str ("(s)" ); 31974 | static const std::string strrng_str ("(rngs)" ); 31975 | static const std::string cs_str ("(cs)" ); 31976 | static const std::string cstrrng_str("(crngs)"); 31977 | 31978 | if (details::is_null_node(branch)) 31979 | return null_str; 31980 | else if (details::is_constant_node(branch)) 31981 | return const_str; 31982 | else if (details::is_variable_node(branch)) 31983 | return var_str; 31984 | else if (details::is_vov_node(branch)) 31985 | return vov_str; 31986 | else if (details::is_cov_node(branch)) 31987 | return cov_str; 31988 | else if (details::is_voc_node(branch)) 31989 | return voc_str; 31990 | else if (details::is_string_node(branch)) 31991 | return str_str; 31992 | else if (details::is_const_string_node(branch)) 31993 | return cs_str; 31994 | else if (details::is_string_range_node(branch)) 31995 | return strrng_str; 31996 | else if (details::is_const_string_range_node(branch)) 31997 | return cstrrng_str; 31998 | else if (details::is_t0ot1ot2_node(branch)) 31999 | return "(" + dynamic_cast<details::T0oT1oT2_base_node<T>*>(branch)->type_id() + ")" 32000 | else if (details::is_t0ot1ot2ot3_node(branch)) 32001 | return "(" + dynamic_cast<details::T0oT1oT2oT3_base_node<T>*>(branch)->type_id() + ")" 32002 | else 32003 | return "ERROR" 32004 | } 32005 | 32006 | inline std::string branch_to_id(expression_node_ptr (&branch)[2]) const 32007 | { 32008 | return branch_to_id(branch[0]) + std::string("o") + branch_to_id(branch[1]); 32009 | } 32010 | 32011 | inline bool cov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32012 | { 32013 | if (!operation_optimisable(operation)) 32014 | return false; 32015 | else 32016 | return details::is_constant_node(branch[0]) && 32017 | details::is_variable_node(branch[1]) ; 32018 | } 32019 | 32020 | inline bool voc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32021 | { 32022 | if (!operation_optimisable(operation)) 32023 | return false; 32024 | else 32025 | return details::is_variable_node(branch[0]) && 32026 | details::is_constant_node(branch[1]) ; 32027 | } 32028 | 32029 | inline bool vov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32030 | { 32031 | if (!operation_optimisable(operation)) 32032 | return false; 32033 | else 32034 | return details::is_variable_node(branch[0]) && 32035 | details::is_variable_node(branch[1]) ; 32036 | } 32037 | 32038 | inline bool cob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32039 | { 32040 | if (!operation_optimisable(operation)) 32041 | return false; 32042 | else 32043 | return details::is_constant_node(branch[0]) && 32044 | !details::is_constant_node(branch[1]) ; 32045 | } 32046 | 32047 | inline bool boc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32048 | { 32049 | if (!operation_optimisable(operation)) 32050 | return false; 32051 | else 32052 | return !details::is_constant_node(branch[0]) && 32053 | details::is_constant_node(branch[1]) ; 32054 | } 32055 | 32056 | inline bool cocob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32057 | { 32058 | if ( 32059 | (details::e_add == operation) || 32060 | (details::e_sub == operation) || 32061 | (details::e_mul == operation) || 32062 | (details::e_div == operation) 32063 | ) 32064 | { 32065 | return (details::is_constant_node(branch[0]) && details::is_cob_node(branch[1])) || 32066 | (details::is_constant_node(branch[1]) && details::is_cob_node(branch[0])) ; 32067 | } 32068 | else 32069 | return false; 32070 | } 32071 | 32072 | inline bool coboc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32073 | { 32074 | if ( 32075 | (details::e_add == operation) || 32076 | (details::e_sub == operation) || 32077 | (details::e_mul == operation) || 32078 | (details::e_div == operation) 32079 | ) 32080 | { 32081 | return (details::is_constant_node(branch[0]) && details::is_boc_node(branch[1])) || 32082 | (details::is_constant_node(branch[1]) && details::is_boc_node(branch[0])) ; 32083 | } 32084 | else 32085 | return false; 32086 | } 32087 | 32088 | inline bool uvouv_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32089 | { 32090 | if (!operation_optimisable(operation)) 32091 | return false; 32092 | else 32093 | return details::is_uv_node(branch[0]) && 32094 | details::is_uv_node(branch[1]) ; 32095 | } 32096 | 32097 | inline bool vob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32098 | { 32099 | if (!operation_optimisable(operation)) 32100 | return false; 32101 | else 32102 | return details::is_variable_node(branch[0]) && 32103 | !details::is_variable_node(branch[1]) ; 32104 | } 32105 | 32106 | inline bool bov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32107 | { 32108 | if (!operation_optimisable(operation)) 32109 | return false; 32110 | else 32111 | return !details::is_variable_node(branch[0]) && 32112 | details::is_variable_node(branch[1]) ; 32113 | } 32114 | 32115 | inline bool binext_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32116 | { 32117 | if (!operation_optimisable(operation)) 32118 | return false; 32119 | else 32120 | return !details::is_constant_node(branch[0]) || 32121 | !details::is_constant_node(branch[1]) ; 32122 | } 32123 | 32124 | inline bool is_invalid_assignment_op(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32125 | { 32126 | if (is_assignment_operation(operation)) 32127 | { 32128 | const bool b1_is_genstring = details::is_generally_string_node(branch[1]); 32129 | 32130 | if (details::is_string_node(branch[0])) 32131 | return !b1_is_genstring; 32132 | else if (details::is_literal_node(branch[0])) 32133 | return true; 32134 | else 32135 | return ( 32136 | !details::is_variable_node (branch[0]) && 32137 | !details::is_vector_elem_node (branch[0]) && 32138 | !details::is_vector_celem_node (branch[0]) && 32139 | !details::is_vector_elem_rtc_node (branch[0]) && 32140 | !details::is_vector_celem_rtc_node (branch[0]) && 32141 | !details::is_rebasevector_elem_node (branch[0]) && 32142 | !details::is_rebasevector_celem_node (branch[0]) && 32143 | !details::is_rebasevector_elem_rtc_node (branch[0]) && 32144 | !details::is_rebasevector_celem_rtc_node(branch[0]) && 32145 | !details::is_vector_node (branch[0]) 32146 | ) 32147 | || b1_is_genstring; 32148 | } 32149 | else 32150 | return false; 32151 | } 32152 | 32153 | inline bool is_constpow_operation(const details::operator_type& operation, expression_node_ptr(&branch)[2]) const 32154 | { 32155 | if ( 32156 | !details::is_constant_node(branch[1]) || 32157 | details::is_constant_node(branch[0]) || 32158 | details::is_variable_node(branch[0]) || 32159 | details::is_vector_node (branch[0]) || 32160 | details::is_generally_string_node(branch[0]) 32161 | ) 32162 | return false; 32163 | 32164 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 32165 | 32166 | return cardinal_pow_optimisable(operation, c); 32167 | } 32168 | 32169 | inline bool is_invalid_break_continue_op(expression_node_ptr (&branch)[2]) const 32170 | { 32171 | return ( 32172 | details::is_break_node (branch[0]) || 32173 | details::is_break_node (branch[1]) || 32174 | details::is_continue_node(branch[0]) || 32175 | details::is_continue_node(branch[1]) 32176 | ); 32177 | } 32178 | 32179 | inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32180 | { 32181 | const bool b0_string = is_generally_string_node(branch[0]); 32182 | const bool b1_string = is_generally_string_node(branch[1]); 32183 | 32184 | bool result = false; 32185 | 32186 | if (b0_string != b1_string) 32187 | result = true; 32188 | else if (!valid_string_operation(operation) && b0_string && b1_string) 32189 | result = true; 32190 | 32191 | if (result) 32192 | { 32193 | parser_->set_synthesis_error("Invalid string operation"); 32194 | } 32195 | 32196 | return result; 32197 | } 32198 | 32199 | inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[3]) const 32200 | { 32201 | const bool b0_string = is_generally_string_node(branch[0]); 32202 | const bool b1_string = is_generally_string_node(branch[1]); 32203 | const bool b2_string = is_generally_string_node(branch[2]); 32204 | 32205 | bool result = false; 32206 | 32207 | if ((b0_string != b1_string) || (b1_string != b2_string)) 32208 | result = true; 32209 | else if ((details::e_inrange != operation) && b0_string && b1_string && b2_string) 32210 | result = true; 32211 | 32212 | if (result) 32213 | { 32214 | parser_->set_synthesis_error("Invalid string operation"); 32215 | } 32216 | 32217 | return result; 32218 | } 32219 | 32220 | inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32221 | { 32222 | const bool b0_string = is_generally_string_node(branch[0]); 32223 | const bool b1_string = is_generally_string_node(branch[1]); 32224 | 32225 | return (b0_string && b1_string && valid_string_operation(operation)); 32226 | } 32227 | 32228 | inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[3]) const 32229 | { 32230 | const bool b0_string = is_generally_string_node(branch[0]); 32231 | const bool b1_string = is_generally_string_node(branch[1]); 32232 | const bool b2_string = is_generally_string_node(branch[2]); 32233 | 32234 | return (b0_string && b1_string && b2_string && (details::e_inrange == operation)); 32235 | } 32236 | 32237 | #ifndef exprtk_disable_sc_andor 32238 | inline bool is_shortcircuit_expression(const details::operator_type& operation) const 32239 | { 32240 | return ( 32241 | (details::e_scand == operation) || 32242 | (details::e_scor == operation) 32243 | ); 32244 | } 32245 | #else 32246 | inline bool is_shortcircuit_expression(const details::operator_type&) const 32247 | { 32248 | return false; 32249 | } 32250 | #endif 32251 | 32252 | inline bool is_null_present(expression_node_ptr (&branch)[2]) const 32253 | { 32254 | return ( 32255 | details::is_null_node(branch[0]) || 32256 | details::is_null_node(branch[1]) 32257 | ); 32258 | } 32259 | 32260 | inline bool is_vector_eqineq_logic_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32261 | { 32262 | if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1])) 32263 | return false; 32264 | else 32265 | return ( 32266 | (details::e_lt == operation) || 32267 | (details::e_lte == operation) || 32268 | (details::e_gt == operation) || 32269 | (details::e_gte == operation) || 32270 | (details::e_eq == operation) || 32271 | (details::e_ne == operation) || 32272 | (details::e_equal == operation) || 32273 | (details::e_and == operation) || 32274 | (details::e_nand == operation) || 32275 | (details::e_or == operation) || 32276 | (details::e_nor == operation) || 32277 | (details::e_xor == operation) || 32278 | (details::e_xnor == operation) 32279 | ); 32280 | } 32281 | 32282 | inline bool is_vector_arithmetic_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const 32283 | { 32284 | if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1])) 32285 | return false; 32286 | else 32287 | return ( 32288 | (details::e_add == operation) || 32289 | (details::e_sub == operation) || 32290 | (details::e_mul == operation) || 32291 | (details::e_div == operation) || 32292 | (details::e_pow == operation) 32293 | ); 32294 | } 32295 | 32296 | inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[2]) 32297 | { 32298 | if ((0 == branch[0]) || (0 == branch[1])) 32299 | { 32300 | parser_->set_error(parser_error::make_error( 32301 | parser_error::e_syntax, 32302 | parser_->current_state().token, 32303 | "ERR248 - Invalid branches received for operator '" + details::to_str(operation) + "'", 32304 | exprtk_error_location)); 32305 | 32306 | return error_node(); 32307 | } 32308 | else if (is_invalid_string_op(operation,branch)) 32309 | { 32310 | parser_->set_error(parser_error::make_error( 32311 | parser_error::e_syntax, 32312 | parser_->current_state().token, 32313 | "ERR249 - Invalid branch pair for string operator '" + details::to_str(operation) + "'", 32314 | exprtk_error_location)); 32315 | 32316 | return error_node(); 32317 | } 32318 | else if (is_invalid_assignment_op(operation,branch)) 32319 | { 32320 | parser_->set_error(parser_error::make_error( 32321 | parser_error::e_syntax, 32322 | parser_->current_state().token, 32323 | "ERR250 - Invalid branch pair for assignment operator '" + details::to_str(operation) + "'", 32324 | exprtk_error_location)); 32325 | 32326 | return error_node(); 32327 | } 32328 | else if (is_invalid_break_continue_op(branch)) 32329 | { 32330 | parser_->set_error(parser_error::make_error( 32331 | parser_error::e_syntax, 32332 | parser_->current_state().token, 32333 | "ERR251 - Invalid branch pair for break/continue operator '" + details::to_str(operation) + "'", 32334 | exprtk_error_location)); 32335 | 32336 | return error_node(); 32337 | } 32338 | else if (details::e_assign == operation) 32339 | { 32340 | return synthesize_assignment_expression(operation, branch); 32341 | } 32342 | else if (details::e_swap == operation) 32343 | { 32344 | return synthesize_swap_expression(branch); 32345 | } 32346 | else if (is_assignment_operation(operation)) 32347 | { 32348 | return synthesize_assignment_operation_expression(operation, branch); 32349 | } 32350 | else if (is_vector_eqineq_logic_operation(operation, branch)) 32351 | { 32352 | return synthesize_veceqineqlogic_operation_expression(operation, branch); 32353 | } 32354 | else if (is_vector_arithmetic_operation(operation, branch)) 32355 | { 32356 | return synthesize_vecarithmetic_operation_expression(operation, branch); 32357 | } 32358 | else if (is_shortcircuit_expression(operation)) 32359 | { 32360 | return synthesize_shortcircuit_expression(operation, branch); 32361 | } 32362 | else if (is_string_operation(operation, branch)) 32363 | { 32364 | return synthesize_string_expression(operation, branch); 32365 | } 32366 | else if (is_null_present(branch)) 32367 | { 32368 | return synthesize_null_expression(operation, branch); 32369 | } 32370 | #ifndef exprtk_disable_cardinal_pow_optimisation 32371 | else if (is_constpow_operation(operation, branch)) 32372 | { 32373 | return cardinal_pow_optimisation(branch); 32374 | } 32375 | #endif 32376 | 32377 | expression_node_ptr result = error_node(); 32378 | 32379 | #ifndef exprtk_disable_enhanced_features 32380 | if (synthesize_expression(operation, branch, result)) 32381 | { 32382 | return result; 32383 | } 32384 | else 32385 | #endif 32386 | 32387 | { 32388 | /* 32389 | Possible reductions: 32390 | 1. c o cob -> cob 32391 | 2. cob o c -> cob 32392 | 3. c o boc -> boc 32393 | 4. boc o c -> boc 32394 | */ 32395 | result = error_node(); 32396 | 32397 | if (cocob_optimisable(operation, branch)) 32398 | { 32399 | result = synthesize_cocob_expression::process((*this), operation, branch); 32400 | } 32401 | else if (coboc_optimisable(operation, branch) && (0 == result)) 32402 | { 32403 | result = synthesize_coboc_expression::process((*this), operation, branch); 32404 | } 32405 | 32406 | if (result) 32407 | return result; 32408 | } 32409 | 32410 | if (uvouv_optimisable(operation, branch)) 32411 | { 32412 | return synthesize_uvouv_expression(operation, branch); 32413 | } 32414 | else if (vob_optimisable(operation, branch)) 32415 | { 32416 | return synthesize_vob_expression::process((*this), operation, branch); 32417 | } 32418 | else if (bov_optimisable(operation, branch)) 32419 | { 32420 | return synthesize_bov_expression::process((*this), operation, branch); 32421 | } 32422 | else if (cob_optimisable(operation, branch)) 32423 | { 32424 | return synthesize_cob_expression::process((*this), operation, branch); 32425 | } 32426 | else if (boc_optimisable(operation, branch)) 32427 | { 32428 | return synthesize_boc_expression::process((*this), operation, branch); 32429 | } 32430 | #ifndef exprtk_disable_enhanced_features 32431 | else if (cov_optimisable(operation, branch)) 32432 | { 32433 | return synthesize_cov_expression::process((*this), operation, branch); 32434 | } 32435 | #endif 32436 | else if (binext_optimisable(operation, branch)) 32437 | { 32438 | return synthesize_binary_ext_expression::process((*this), operation, branch); 32439 | } 32440 | else 32441 | return synthesize_expression<binary_node_t,2>(operation, branch); 32442 | } 32443 | 32444 | inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[3]) 32445 | { 32446 | if ( 32447 | (0 == branch[0]) || 32448 | (0 == branch[1]) || 32449 | (0 == branch[2]) 32450 | ) 32451 | { 32452 | details::free_all_nodes(*node_allocator_,branch); 32453 | 32454 | parser_->set_error(parser_error::make_error( 32455 | parser_error::e_syntax, 32456 | parser_->current_state().token, 32457 | "ERR252 - Invalid branches operator '" + details::to_str(operation) + "'", 32458 | exprtk_error_location)); 32459 | 32460 | return error_node(); 32461 | } 32462 | else if (is_invalid_string_op(operation, branch)) 32463 | { 32464 | parser_->set_error(parser_error::make_error( 32465 | parser_error::e_syntax, 32466 | parser_->current_state().token, 32467 | "ERR253 - Invalid branches for string operator '" + details::to_str(operation) + "'", 32468 | exprtk_error_location)); 32469 | 32470 | return error_node(); 32471 | } 32472 | else if (is_string_operation(operation, branch)) 32473 | { 32474 | return synthesize_string_expression(operation, branch); 32475 | } 32476 | else 32477 | return synthesize_expression<trinary_node_t,3>(operation, branch); 32478 | } 32479 | 32480 | inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[4]) 32481 | { 32482 | return synthesize_expression<quaternary_node_t,4>(operation,branch); 32483 | } 32484 | 32485 | inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr b0) 32486 | { 32487 | expression_node_ptr branch[1] = { b0 }; 32488 | return (*this)(operation,branch); 32489 | } 32490 | 32491 | inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr& b0, expression_node_ptr& b1) 32492 | { 32493 | expression_node_ptr result = error_node(); 32494 | 32495 | if ((0 != b0) && (0 != b1)) 32496 | { 32497 | expression_node_ptr branch[2] = { b0, b1 }; 32498 | result = expression_generator<Type>::operator()(operation, branch); 32499 | b0 = branch[0]; 32500 | b1 = branch[1]; 32501 | } 32502 | 32503 | return result; 32504 | } 32505 | 32506 | inline expression_node_ptr conditional(expression_node_ptr condition, 32507 | expression_node_ptr consequent, 32508 | expression_node_ptr alternative) const 32509 | { 32510 | if ((0 == condition) || (0 == consequent)) 32511 | { 32512 | details::free_node(*node_allocator_, condition ); 32513 | details::free_node(*node_allocator_, consequent ); 32514 | details::free_node(*node_allocator_, alternative); 32515 | 32516 | const std::string invalid_branches = 32517 | ((0 == condition ) ? std::string("condition ") : "") + 32518 | ((0 == consequent) ? std::string("consequent") : "") ; 32519 | 32520 | parser_->set_error(parser_error::make_error( 32521 | parser_error::e_parser, 32522 | parser_->current_state().token, 32523 | "ERR254 - Invalid " + invalid_branches + " for conditional statement", 32524 | exprtk_error_location)); 32525 | 32526 | return error_node(); 32527 | } 32528 | // Can the condition be immediately evaluated? if so optimise. 32529 | else if (details::is_constant_node(condition)) 32530 | { 32531 | // True branch 32532 | if (details::is_true(condition)) 32533 | { 32534 | details::free_node(*node_allocator_, condition ); 32535 | details::free_node(*node_allocator_, alternative); 32536 | 32537 | return consequent; 32538 | } 32539 | // False branch 32540 | else 32541 | { 32542 | details::free_node(*node_allocator_, condition ); 32543 | details::free_node(*node_allocator_, consequent); 32544 | 32545 | if (alternative) 32546 | return alternative; 32547 | else 32548 | return node_allocator_->allocate<details::null_node<T> >(); 32549 | } 32550 | } 32551 | 32552 | expression_node_ptr result = error_node(); 32553 | std::string node_name = "Unknown!" 32554 | 32555 | if ((0 != consequent) && (0 != alternative)) 32556 | { 32557 | result = node_allocator_->allocate<conditional_node_t>(condition, consequent, alternative); 32558 | node_name = "conditional_node_t" 32559 | } 32560 | else 32561 | { 32562 | result = node_allocator_->allocate<cons_conditional_node_t>(condition, consequent); 32563 | node_name = "cons_conditional_node_t" 32564 | } 32565 | 32566 | if (result && result->valid()) 32567 | { 32568 | return result; 32569 | } 32570 | 32571 | parser_->set_error(parser_error::make_error( 32572 | parser_error::e_parser, 32573 | token_t(), 32574 | "ERR255 - Failed to synthesize node: " + node_name, 32575 | exprtk_error_location)); 32576 | 32577 | details::free_node(*node_allocator_, result); 32578 | return error_node(); 32579 | } 32580 | 32581 | #ifndef exprtk_disable_string_capabilities 32582 | inline expression_node_ptr conditional_string(expression_node_ptr condition, 32583 | expression_node_ptr consequent, 32584 | expression_node_ptr alternative) const 32585 | { 32586 | if ((0 == condition) || (0 == consequent)) 32587 | { 32588 | details::free_node(*node_allocator_, condition ); 32589 | details::free_node(*node_allocator_, consequent ); 32590 | details::free_node(*node_allocator_, alternative); 32591 | 32592 | const std::string invalid_branches = 32593 | ((0 == condition ) ? std::string("condition ") : "") + 32594 | ((0 == consequent) ? std::string("consequent") : "") ; 32595 | 32596 | parser_->set_error(parser_error::make_error( 32597 | parser_error::e_parser, 32598 | parser_->current_state().token, 32599 | "ERR256 - Invalid " + invalid_branches + " for string conditional statement", 32600 | exprtk_error_location)); 32601 | 32602 | return error_node(); 32603 | } 32604 | // Can the condition be immediately evaluated? if so optimise. 32605 | else if (details::is_constant_node(condition)) 32606 | { 32607 | // True branch 32608 | if (details::is_true(condition)) 32609 | { 32610 | details::free_node(*node_allocator_, condition ); 32611 | details::free_node(*node_allocator_, alternative); 32612 | 32613 | return consequent; 32614 | } 32615 | // False branch 32616 | else 32617 | { 32618 | details::free_node(*node_allocator_, condition ); 32619 | details::free_node(*node_allocator_, consequent); 32620 | 32621 | if (alternative) 32622 | return alternative; 32623 | else 32624 | return node_allocator_-> 32625 | allocate_c<details::string_literal_node<Type> >(""); 32626 | } 32627 | } 32628 | else if ((0 != consequent) && (0 != alternative)) 32629 | { 32630 | expression_node_ptr result = 32631 | node_allocator_->allocate<conditional_string_node_t>(condition, consequent, alternative); 32632 | 32633 | if (result && result->valid()) 32634 | { 32635 | return result; 32636 | } 32637 | 32638 | parser_->set_error(parser_error::make_error( 32639 | parser_error::e_parser, 32640 | token_t(), 32641 | "ERR257 - Failed to synthesize node: conditional_string_node_t", 32642 | exprtk_error_location)); 32643 | 32644 | details::free_node(*node_allocator_, result); 32645 | } 32646 | 32647 | return error_node(); 32648 | } 32649 | #else 32650 | inline expression_node_ptr conditional_string(expression_node_ptr, 32651 | expression_node_ptr, 32652 | expression_node_ptr) const 32653 | { 32654 | return error_node(); 32655 | } 32656 | #endif 32657 | 32658 | inline expression_node_ptr conditional_vector(expression_node_ptr condition, 32659 | expression_node_ptr consequent, 32660 | expression_node_ptr alternative) const 32661 | { 32662 | if ((0 == condition) || (0 == consequent)) 32663 | { 32664 | details::free_node(*node_allocator_, condition ); 32665 | details::free_node(*node_allocator_, consequent ); 32666 | details::free_node(*node_allocator_, alternative); 32667 | 32668 | const std::string invalid_branches = 32669 | ((0 == condition ) ? std::string("condition ") : "") + 32670 | ((0 == consequent) ? std::string("consequent") : "") ; 32671 | 32672 | parser_->set_error(parser_error::make_error( 32673 | parser_error::e_parser, 32674 | parser_->current_state().token, 32675 | "ERR258 - Invalid " + invalid_branches + " for vector conditional statement", 32676 | exprtk_error_location)); 32677 | 32678 | return error_node(); 32679 | } 32680 | // Can the condition be immediately evaluated? if so optimise. 32681 | else if (details::is_constant_node(condition)) 32682 | { 32683 | // True branch 32684 | if (details::is_true(condition)) 32685 | { 32686 | details::free_node(*node_allocator_, condition ); 32687 | details::free_node(*node_allocator_, alternative); 32688 | 32689 | return consequent; 32690 | } 32691 | // False branch 32692 | else 32693 | { 32694 | details::free_node(*node_allocator_, condition ); 32695 | details::free_node(*node_allocator_, consequent); 32696 | 32697 | if (alternative) 32698 | return alternative; 32699 | else 32700 | return node_allocator_->allocate<details::null_node<T> >(); 32701 | 32702 | } 32703 | } 32704 | else if ((0 != consequent) && (0 != alternative)) 32705 | { 32706 | return node_allocator_-> 32707 | allocate<conditional_vector_node_t>(condition, consequent, alternative); 32708 | } 32709 | else 32710 | return error_node(); 32711 | } 32712 | 32713 | inline loop_runtime_check_ptr get_loop_runtime_check(const loop_runtime_check::loop_types loop_type) const 32714 | { 32715 | if ( 32716 | parser_->loop_runtime_check_ && 32717 | (loop_type == (parser_->loop_runtime_check_->loop_set & loop_type)) 32718 | ) 32719 | { 32720 | return parser_->loop_runtime_check_; 32721 | } 32722 | 32723 | return loop_runtime_check_ptr(0); 32724 | } 32725 | 32726 | inline vector_access_runtime_check_ptr get_vector_access_runtime_check() const 32727 | { 32728 | return parser_->vector_access_runtime_check_; 32729 | } 32730 | 32731 | inline expression_node_ptr while_loop(expression_node_ptr& condition, 32732 | expression_node_ptr& branch, 32733 | const bool break_continue_present = false) const 32734 | { 32735 | if ( 32736 | !break_continue_present && 32737 | !parser_->state_.return_stmt_present && 32738 | details::is_constant_node(condition) 32739 | ) 32740 | { 32741 | expression_node_ptr result = error_node(); 32742 | if (details::is_true(condition)) 32743 | { 32744 | // Infinite loops are not allowed. 32745 | 32746 | parser_->set_error(parser_error::make_error( 32747 | parser_error::e_parser, 32748 | parser_->current_state().token, 32749 | "ERR259 - Infinite loop condition without 'break' or 'return' not allowed in while-loops", 32750 | exprtk_error_location)); 32751 | 32752 | result = error_node(); 32753 | } 32754 | else 32755 | result = node_allocator_->allocate<details::null_node<Type> >(); 32756 | 32757 | details::free_node(*node_allocator_, condition); 32758 | details::free_node(*node_allocator_, branch ); 32759 | 32760 | return result; 32761 | } 32762 | else if (details::is_null_node(condition)) 32763 | { 32764 | details::free_node(*node_allocator_,condition); 32765 | 32766 | return branch; 32767 | } 32768 | 32769 | loop_runtime_check_ptr rtc = get_loop_runtime_check(loop_runtime_check::e_while_loop); 32770 | 32771 | if (!break_continue_present) 32772 | { 32773 | if (rtc) 32774 | return node_allocator_->allocate<while_loop_rtc_node_t> 32775 | (condition, branch, rtc); 32776 | else 32777 | return node_allocator_->allocate<while_loop_node_t> 32778 | (condition, branch); 32779 | } 32780 | #ifndef exprtk_disable_break_continue 32781 | else 32782 | { 32783 | if (rtc) 32784 | return node_allocator_->allocate<while_loop_bc_rtc_node_t> 32785 | (condition, branch, rtc); 32786 | else 32787 | return node_allocator_->allocate<while_loop_bc_node_t> 32788 | (condition, branch); 32789 | } 32790 | #else 32791 | return error_node(); 32792 | #endif 32793 | } 32794 | 32795 | inline expression_node_ptr repeat_until_loop(expression_node_ptr& condition, 32796 | expression_node_ptr& branch, 32797 | const bool break_continue_present = false) const 32798 | { 32799 | if (!break_continue_present && details::is_constant_node(condition)) 32800 | { 32801 | if ( 32802 | details::is_true(condition) && 32803 | details::is_constant_node(branch) 32804 | ) 32805 | { 32806 | free_node(*node_allocator_,condition); 32807 | 32808 | return branch; 32809 | } 32810 | 32811 | details::free_node(*node_allocator_, condition); 32812 | details::free_node(*node_allocator_, branch ); 32813 | 32814 | return error_node(); 32815 | } 32816 | else if (details::is_null_node(condition)) 32817 | { 32818 | details::free_node(*node_allocator_,condition); 32819 | 32820 | return branch; 32821 | } 32822 | 32823 | loop_runtime_check_ptr rtc = get_loop_runtime_check(loop_runtime_check::e_repeat_until_loop); 32824 | 32825 | if (!break_continue_present) 32826 | { 32827 | if (rtc) 32828 | return node_allocator_->allocate<repeat_until_loop_rtc_node_t> 32829 | (condition, branch, rtc); 32830 | else 32831 | return node_allocator_->allocate<repeat_until_loop_node_t> 32832 | (condition, branch); 32833 | } 32834 | #ifndef exprtk_disable_break_continue 32835 | else 32836 | { 32837 | if (rtc) 32838 | return node_allocator_->allocate<repeat_until_loop_bc_rtc_node_t> 32839 | (condition, branch, rtc); 32840 | else 32841 | return node_allocator_->allocate<repeat_until_loop_bc_node_t> 32842 | (condition, branch); 32843 | } 32844 | #else 32845 | return error_node(); 32846 | #endif 32847 | } 32848 | 32849 | inline expression_node_ptr for_loop(expression_node_ptr& initialiser, 32850 | expression_node_ptr& condition, 32851 | expression_node_ptr& incrementor, 32852 | expression_node_ptr& loop_body, 32853 | bool break_continue_present = false) const 32854 | { 32855 | if ( 32856 | !break_continue_present && 32857 | !parser_->state_.return_stmt_present && 32858 | details::is_constant_node(condition) 32859 | ) 32860 | { 32861 | expression_node_ptr result = error_node(); 32862 | 32863 | if (details::is_true(condition)) 32864 | { 32865 | // Infinite loops are not allowed. 32866 | 32867 | parser_->set_error(parser_error::make_error( 32868 | parser_error::e_parser, 32869 | parser_->current_state().token, 32870 | "ERR260 - Infinite loop condition without 'break' or 'return' not allowed in for-loop", 32871 | exprtk_error_location)); 32872 | 32873 | result = error_node(); 32874 | } 32875 | else 32876 | result = node_allocator_->allocate<details::null_node<Type> >(); 32877 | 32878 | details::free_node(*node_allocator_, initialiser); 32879 | details::free_node(*node_allocator_, condition ); 32880 | details::free_node(*node_allocator_, incrementor); 32881 | details::free_node(*node_allocator_, loop_body ); 32882 | 32883 | return result; 32884 | } 32885 | else if (details::is_null_node(condition) || (0 == condition)) 32886 | { 32887 | details::free_node(*node_allocator_, initialiser); 32888 | details::free_node(*node_allocator_, condition ); 32889 | details::free_node(*node_allocator_, incrementor); 32890 | 32891 | return loop_body; 32892 | } 32893 | 32894 | loop_runtime_check_ptr rtc = get_loop_runtime_check(loop_runtime_check::e_for_loop); 32895 | 32896 | if (!break_continue_present) 32897 | { 32898 | if (rtc) 32899 | return node_allocator_->allocate<for_loop_rtc_node_t> 32900 | ( 32901 | initialiser, 32902 | condition, 32903 | incrementor, 32904 | loop_body, 32905 | rtc 32906 | ); 32907 | else 32908 | return node_allocator_->allocate<for_loop_node_t> 32909 | ( 32910 | initialiser, 32911 | condition, 32912 | incrementor, 32913 | loop_body 32914 | ); 32915 | } 32916 | #ifndef exprtk_disable_break_continue 32917 | else 32918 | { 32919 | if (rtc) 32920 | return node_allocator_->allocate<for_loop_bc_rtc_node_t> 32921 | ( 32922 | initialiser, 32923 | condition, 32924 | incrementor, 32925 | loop_body, 32926 | rtc 32927 | ); 32928 | else 32929 | return node_allocator_->allocate<for_loop_bc_node_t> 32930 | ( 32931 | initialiser, 32932 | condition, 32933 | incrementor, 32934 | loop_body 32935 | ); 32936 | } 32937 | #else 32938 | return error_node(); 32939 | #endif 32940 | } 32941 | 32942 | template <typename Allocator, 32943 | template <typename, typename> class Sequence> 32944 | inline expression_node_ptr const_optimise_switch(Sequence<expression_node_ptr,Allocator>& arg_list) 32945 | { 32946 | expression_node_ptr result = error_node(); 32947 | 32948 | for (std::size_t i = 0; i < (arg_list.size() / 2); ++i) 32949 | { 32950 | expression_node_ptr condition = arg_list[(2 * i) ]; 32951 | expression_node_ptr consequent = arg_list[(2 * i) + 1]; 32952 | 32953 | if ((0 == result) && details::is_true(condition)) 32954 | { 32955 | result = consequent; 32956 | break; 32957 | } 32958 | } 32959 | 32960 | if (0 == result) 32961 | { 32962 | result = arg_list.back(); 32963 | } 32964 | 32965 | for (std::size_t i = 0; i < arg_list.size(); ++i) 32966 | { 32967 | expression_node_ptr current_expr = arg_list[i]; 32968 | 32969 | if (current_expr && (current_expr != result)) 32970 | { 32971 | free_node(*node_allocator_,current_expr); 32972 | } 32973 | } 32974 | 32975 | return result; 32976 | } 32977 | 32978 | template <typename Allocator, 32979 | template <typename, typename> class Sequence> 32980 | inline expression_node_ptr const_optimise_mswitch(Sequence<expression_node_ptr,Allocator>& arg_list) 32981 | { 32982 | expression_node_ptr result = error_node(); 32983 | 32984 | for (std::size_t i = 0; i < (arg_list.size() / 2); ++i) 32985 | { 32986 | expression_node_ptr condition = arg_list[(2 * i) ]; 32987 | expression_node_ptr consequent = arg_list[(2 * i) + 1]; 32988 | 32989 | if (details::is_true(condition)) 32990 | { 32991 | result = consequent; 32992 | } 32993 | } 32994 | 32995 | if (0 == result) 32996 | { 32997 | const T zero = T(0); 32998 | result = node_allocator_->allocate<literal_node_t>(zero); 32999 | } 33000 | 33001 | for (std::size_t i = 0; i < arg_list.size(); ++i) 33002 | { 33003 | expression_node_ptr& current_expr = arg_list[i]; 33004 | 33005 | if (current_expr && (current_expr != result)) 33006 | { 33007 | details::free_node(*node_allocator_,current_expr); 33008 | } 33009 | } 33010 | 33011 | return result; 33012 | } 33013 | 33014 | struct switch_nodes 33015 | { 33016 | typedef std::vector<std::pair<expression_node_ptr,bool> > arg_list_t; 33017 | 33018 | #define case_stmt(N) \ 33019 | if (is_true(arg[(2 * N)].first)) { return arg[(2 * N) + 1].first->value(); } \ 33020 | 33021 | struct switch_impl_1 33022 | { 33023 | static inline T process(const arg_list_t& arg) 33024 | { 33025 | case_stmt(0) 33026 | 33027 | assert(arg.size() == ((2 * 1) + 1)); 33028 | 33029 | return arg.back().first->value(); 33030 | } 33031 | }; 33032 | 33033 | struct switch_impl_2 33034 | { 33035 | static inline T process(const arg_list_t& arg) 33036 | { 33037 | case_stmt(0) case_stmt(1) 33038 | 33039 | assert(arg.size() == ((2 * 2) + 1)); 33040 | 33041 | return arg.back().first->value(); 33042 | } 33043 | }; 33044 | 33045 | struct switch_impl_3 33046 | { 33047 | static inline T process(const arg_list_t& arg) 33048 | { 33049 | case_stmt(0) case_stmt(1) 33050 | case_stmt(2) 33051 | 33052 | assert(arg.size() == ((2 * 3) + 1)); 33053 | 33054 | return arg.back().first->value(); 33055 | } 33056 | }; 33057 | 33058 | struct switch_impl_4 33059 | { 33060 | static inline T process(const arg_list_t& arg) 33061 | { 33062 | case_stmt(0) case_stmt(1) 33063 | case_stmt(2) case_stmt(3) 33064 | 33065 | assert(arg.size() == ((2 * 4) + 1)); 33066 | 33067 | return arg.back().first->value(); 33068 | } 33069 | }; 33070 | 33071 | struct switch_impl_5 33072 | { 33073 | static inline T process(const arg_list_t& arg) 33074 | { 33075 | case_stmt(0) case_stmt(1) 33076 | case_stmt(2) case_stmt(3) 33077 | case_stmt(4) 33078 | 33079 | assert(arg.size() == ((2 * 5) + 1)); 33080 | 33081 | return arg.back().first->value(); 33082 | } 33083 | }; 33084 | 33085 | struct switch_impl_6 33086 | { 33087 | static inline T process(const arg_list_t& arg) 33088 | { 33089 | case_stmt(0) case_stmt(1) 33090 | case_stmt(2) case_stmt(3) 33091 | case_stmt(4) case_stmt(5) 33092 | 33093 | assert(arg.size() == ((2 * 6) + 1)); 33094 | 33095 | return arg.back().first->value(); 33096 | } 33097 | }; 33098 | 33099 | struct switch_impl_7 33100 | { 33101 | static inline T process(const arg_list_t& arg) 33102 | { 33103 | case_stmt(0) case_stmt(1) 33104 | case_stmt(2) case_stmt(3) 33105 | case_stmt(4) case_stmt(5) 33106 | case_stmt(6) 33107 | 33108 | assert(arg.size() == ((2 * 7) + 1)); 33109 | 33110 | return arg.back().first->value(); 33111 | } 33112 | }; 33113 | 33114 | #undef case_stmt 33115 | }; 33116 | 33117 | template <typename Allocator, 33118 | template <typename, typename> class Sequence> 33119 | inline expression_node_ptr switch_statement(Sequence<expression_node_ptr,Allocator>& arg_list, const bool default_statement_present) 33120 | { 33121 | if (arg_list.empty()) 33122 | return error_node(); 33123 | else if ( 33124 | !all_nodes_valid(arg_list) || 33125 | (!default_statement_present && (arg_list.size() < 2)) 33126 | ) 33127 | { 33128 | details::free_all_nodes(*node_allocator_,arg_list); 33129 | 33130 | return error_node(); 33131 | } 33132 | else if (is_constant_foldable(arg_list)) 33133 | return const_optimise_switch(arg_list); 33134 | 33135 | switch ((arg_list.size() - 1) / 2) 33136 | { 33137 | #define case_stmt(N) \ 33138 | case N : \ 33139 | return node_allocator_-> \ 33140 | allocate<details::switch_n_node \ 33141 | <Type,typename switch_nodes::switch_impl_##N > >(arg_list); \ 33142 | 33143 | case_stmt(1) 33144 | case_stmt(2) 33145 | case_stmt(3) 33146 | case_stmt(4) 33147 | case_stmt(5) 33148 | case_stmt(6) 33149 | case_stmt(7) 33150 | #undef case_stmt 33151 | 33152 | default : return node_allocator_->allocate<details::switch_node<Type> >(arg_list); 33153 | } 33154 | } 33155 | 33156 | template <typename Allocator, 33157 | template <typename, typename> class Sequence> 33158 | inline expression_node_ptr multi_switch_statement(Sequence<expression_node_ptr,Allocator>& arg_list) 33159 | { 33160 | if (!all_nodes_valid(arg_list)) 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_mswitch(arg_list); 33168 | else 33169 | return node_allocator_->allocate<details::multi_switch_node<Type> >(arg_list); 33170 | } 33171 | 33172 | inline expression_node_ptr assert_call(expression_node_ptr& assert_condition, 33173 | expression_node_ptr& assert_message, 33174 | const assert_check::assert_context& context) 33175 | { 33176 | typedef details::assert_node<Type> alloc_type; 33177 | 33178 | expression_node_ptr result = node_allocator_->allocate_rrrr<alloc_type> 33179 | (assert_condition, assert_message, parser_->assert_check_, context); 33180 | 33181 | if (result && result->valid()) 33182 | { 33183 | parser_->state_.activate_side_effect("assert_call()"); 33184 | return result; 33185 | } 33186 | 33187 | details::free_node(*node_allocator_, result ); 33188 | details::free_node(*node_allocator_, assert_condition); 33189 | details::free_node(*node_allocator_, assert_message ); 33190 | 33191 | return error_node(); 33192 | } 33193 | 33194 | #define unary_opr_switch_statements \ 33195 | case_stmt(details::e_abs , details::abs_op ) \ 33196 | case_stmt(details::e_acos , details::acos_op ) \ 33197 | case_stmt(details::e_acosh , details::acosh_op) \ 33198 | case_stmt(details::e_asin , details::asin_op ) \ 33199 | case_stmt(details::e_asinh , details::asinh_op) \ 33200 | case_stmt(details::e_atan , details::atan_op ) \ 33201 | case_stmt(details::e_atanh , details::atanh_op) \ 33202 | case_stmt(details::e_ceil , details::ceil_op ) \ 33203 | case_stmt(details::e_cos , details::cos_op ) \ 33204 | case_stmt(details::e_cosh , details::cosh_op ) \ 33205 | case_stmt(details::e_exp , details::exp_op ) \ 33206 | case_stmt(details::e_expm1 , details::expm1_op) \ 33207 | case_stmt(details::e_floor , details::floor_op) \ 33208 | case_stmt(details::e_log , details::log_op ) \ 33209 | case_stmt(details::e_log10 , details::log10_op) \ 33210 | case_stmt(details::e_log2 , details::log2_op ) \ 33211 | case_stmt(details::e_log1p , details::log1p_op) \ 33212 | case_stmt(details::e_neg , details::neg_op ) \ 33213 | case_stmt(details::e_pos , details::pos_op ) \ 33214 | case_stmt(details::e_round , details::round_op) \ 33215 | case_stmt(details::e_sin , details::sin_op ) \ 33216 | case_stmt(details::e_sinc , details::sinc_op ) \ 33217 | case_stmt(details::e_sinh , details::sinh_op ) \ 33218 | case_stmt(details::e_sqrt , details::sqrt_op ) \ 33219 | case_stmt(details::e_tan , details::tan_op ) \ 33220 | case_stmt(details::e_tanh , details::tanh_op ) \ 33221 | case_stmt(details::e_cot , details::cot_op ) \ 33222 | case_stmt(details::e_sec , details::sec_op ) \ 33223 | case_stmt(details::e_csc , details::csc_op ) \ 33224 | case_stmt(details::e_r2d , details::r2d_op ) \ 33225 | case_stmt(details::e_d2r , details::d2r_op ) \ 33226 | case_stmt(details::e_d2g , details::d2g_op ) \ 33227 | case_stmt(details::e_g2d , details::g2d_op ) \ 33228 | case_stmt(details::e_notl , details::notl_op ) \ 33229 | case_stmt(details::e_sgn , details::sgn_op ) \ 33230 | case_stmt(details::e_erf , details::erf_op ) \ 33231 | case_stmt(details::e_erfc , details::erfc_op ) \ 33232 | case_stmt(details::e_ncdf , details::ncdf_op ) \ 33233 | case_stmt(details::e_frac , details::frac_op ) \ 33234 | case_stmt(details::e_trunc , details::trunc_op) \ 33235 | 33236 | inline expression_node_ptr synthesize_uv_expression(const details::operator_type& operation, 33237 | expression_node_ptr (&branch)[1]) 33238 | { 33239 | T& v = static_cast<details::variable_node<T>*>(branch[0])->ref(); 33240 | 33241 | switch (operation) 33242 | { 33243 | #define case_stmt(op0, op1) \ 33244 | case op0 : return node_allocator_-> \ 33245 | allocate<typename details::unary_variable_node<Type,op1<Type> > >(v); \ 33246 | 33247 | unary_opr_switch_statements 33248 | #undef case_stmt 33249 | default : return error_node(); 33250 | } 33251 | } 33252 | 33253 | inline expression_node_ptr synthesize_uvec_expression(const details::operator_type& operation, 33254 | expression_node_ptr (&branch)[1]) 33255 | { 33256 | switch (operation) 33257 | { 33258 | #define case_stmt(op0, op1) \ 33259 | case op0 : return node_allocator_-> \ 33260 | allocate<typename details::unary_vector_node<Type,op1<Type> > > \ 33261 | (operation, branch[0]); \ 33262 | 33263 | unary_opr_switch_statements 33264 | #undef case_stmt 33265 | default : return error_node(); 33266 | } 33267 | } 33268 | 33269 | inline expression_node_ptr synthesize_unary_expression(const details::operator_type& operation, 33270 | expression_node_ptr (&branch)[1]) 33271 | { 33272 | switch (operation) 33273 | { 33274 | #define case_stmt(op0, op1) \ 33275 | case op0 : return node_allocator_-> \ 33276 | allocate<typename details::unary_branch_node<Type,op1<Type> > >(branch[0]); \ 33277 | 33278 | unary_opr_switch_statements 33279 | #undef case_stmt 33280 | default : return error_node(); 33281 | } 33282 | } 33283 | 33284 | inline expression_node_ptr const_optimise_sf3(const details::operator_type& operation, 33285 | expression_node_ptr (&branch)[3]) 33286 | { 33287 | expression_node_ptr temp_node = error_node(); 33288 | 33289 | switch (operation) 33290 | { 33291 | #define case_stmt(op) \ 33292 | case details::e_sf##op : temp_node = node_allocator_-> \ 33293 | allocate<details::sf3_node<Type,details::sf##op##_op<Type> > > \ 33294 | (operation, branch); \ 33295 | break; \ 33296 | 33297 | case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03) 33298 | case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07) 33299 | case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11) 33300 | case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15) 33301 | case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19) 33302 | case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23) 33303 | case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27) 33304 | case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31) 33305 | case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35) 33306 | case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39) 33307 | case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43) 33308 | case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47) 33309 | #undef case_stmt 33310 | default : return error_node(); 33311 | } 33312 | 33313 | assert(temp_node); 33314 | 33315 | const T v = temp_node->value(); 33316 | 33317 | details::free_node(*node_allocator_,temp_node); 33318 | 33319 | return node_allocator_->allocate<literal_node_t>(v); 33320 | } 33321 | 33322 | inline expression_node_ptr varnode_optimise_sf3(const details::operator_type& operation, expression_node_ptr (&branch)[3]) 33323 | { 33324 | typedef details::variable_node<Type>* variable_ptr; 33325 | 33326 | const Type& v0 = static_cast<variable_ptr>(branch[0])->ref(); 33327 | const Type& v1 = static_cast<variable_ptr>(branch[1])->ref(); 33328 | const Type& v2 = static_cast<variable_ptr>(branch[2])->ref(); 33329 | 33330 | switch (operation) 33331 | { 33332 | #define case_stmt(op) \ 33333 | case details::e_sf##op : return node_allocator_-> \ 33334 | allocate_rrr<details::sf3_var_node<Type,details::sf##op##_op<Type> > > \ 33335 | (v0, v1, v2); \ 33336 | 33337 | case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03) 33338 | case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07) 33339 | case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11) 33340 | case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15) 33341 | case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19) 33342 | case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23) 33343 | case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27) 33344 | case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31) 33345 | case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35) 33346 | case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39) 33347 | case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43) 33348 | case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47) 33349 | #undef case_stmt 33350 | default : return error_node(); 33351 | } 33352 | } 33353 | 33354 | inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[3]) 33355 | { 33356 | if (!all_nodes_valid(branch)) 33357 | return error_node(); 33358 | else if (is_constant_foldable(branch)) 33359 | return const_optimise_sf3(operation,branch); 33360 | else if (all_nodes_variables(branch)) 33361 | return varnode_optimise_sf3(operation,branch); 33362 | else 33363 | { 33364 | switch (operation) 33365 | { 33366 | #define case_stmt(op) \ 33367 | case details::e_sf##op : return node_allocator_-> \ 33368 | allocate<details::sf3_node<Type,details::sf##op##_op<Type> > > \ 33369 | (operation, branch); \ 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 | 33389 | inline expression_node_ptr const_optimise_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4]) 33390 | { 33391 | expression_node_ptr temp_node = error_node(); 33392 | 33393 | switch (operation) 33394 | { 33395 | #define case_stmt(op) \ 33396 | case details::e_sf##op : temp_node = node_allocator_-> \ 33397 | allocate<details::sf4_node<Type,details::sf##op##_op<Type> > > \ 33398 | (operation, branch); \ 33399 | break; \ 33400 | 33401 | case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51) 33402 | case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55) 33403 | case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59) 33404 | case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63) 33405 | case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67) 33406 | case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71) 33407 | case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75) 33408 | case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79) 33409 | case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83) 33410 | case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87) 33411 | case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91) 33412 | case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95) 33413 | case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99) 33414 | #undef case_stmt 33415 | default : return error_node(); 33416 | } 33417 | 33418 | assert(temp_node); 33419 | 33420 | const T v = temp_node->value(); 33421 | 33422 | details::free_node(*node_allocator_,temp_node); 33423 | 33424 | return node_allocator_->allocate<literal_node_t>(v); 33425 | } 33426 | 33427 | inline expression_node_ptr varnode_optimise_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4]) 33428 | { 33429 | typedef details::variable_node<Type>* variable_ptr; 33430 | 33431 | const Type& v0 = static_cast<variable_ptr>(branch[0])->ref(); 33432 | const Type& v1 = static_cast<variable_ptr>(branch[1])->ref(); 33433 | const Type& v2 = static_cast<variable_ptr>(branch[2])->ref(); 33434 | const Type& v3 = static_cast<variable_ptr>(branch[3])->ref(); 33435 | 33436 | switch (operation) 33437 | { 33438 | #define case_stmt(op) \ 33439 | case details::e_sf##op : return node_allocator_-> \ 33440 | allocate_rrrr<details::sf4_var_node<Type,details::sf##op##_op<Type> > > \ 33441 | (v0, v1, v2, v3); \ 33442 | 33443 | case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51) 33444 | case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55) 33445 | case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59) 33446 | case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63) 33447 | case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67) 33448 | case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71) 33449 | case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75) 33450 | case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79) 33451 | case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83) 33452 | case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87) 33453 | case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91) 33454 | case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95) 33455 | case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99) 33456 | #undef case_stmt 33457 | default : return error_node(); 33458 | } 33459 | } 33460 | 33461 | inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[4]) 33462 | { 33463 | if (!all_nodes_valid(branch)) 33464 | return error_node(); 33465 | else if (is_constant_foldable(branch)) 33466 | return const_optimise_sf4(operation,branch); 33467 | else if (all_nodes_variables(branch)) 33468 | return varnode_optimise_sf4(operation,branch); 33469 | switch (operation) 33470 | { 33471 | #define case_stmt(op) \ 33472 | case details::e_sf##op : return node_allocator_-> \ 33473 | allocate<details::sf4_node<Type,details::sf##op##_op<Type> > > \ 33474 | (operation, branch); \ 33475 | 33476 | case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51) 33477 | case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55) 33478 | case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59) 33479 | case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63) 33480 | case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67) 33481 | case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71) 33482 | case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75) 33483 | case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79) 33484 | case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83) 33485 | case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87) 33486 | case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91) 33487 | case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95) 33488 | case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99) 33489 | #undef case_stmt 33490 | default : return error_node(); 33491 | } 33492 | } 33493 | 33494 | template <typename Allocator, 33495 | template <typename, typename> class Sequence> 33496 | inline expression_node_ptr const_optimise_varargfunc(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list) 33497 | { 33498 | expression_node_ptr temp_node = error_node(); 33499 | 33500 | switch (operation) 33501 | { 33502 | #define case_stmt(op0, op1) \ 33503 | case op0 : temp_node = node_allocator_-> \ 33504 | allocate<details::vararg_node<Type,op1<Type> > > \ 33505 | (arg_list); \ 33506 | break; \ 33507 | 33508 | case_stmt(details::e_sum , details::vararg_add_op ) 33509 | case_stmt(details::e_prod , details::vararg_mul_op ) 33510 | case_stmt(details::e_avg , details::vararg_avg_op ) 33511 | case_stmt(details::e_min , details::vararg_min_op ) 33512 | case_stmt(details::e_max , details::vararg_max_op ) 33513 | case_stmt(details::e_mand , details::vararg_mand_op ) 33514 | case_stmt(details::e_mor , details::vararg_mor_op ) 33515 | case_stmt(details::e_multi , details::vararg_multi_op) 33516 | #undef case_stmt 33517 | default : return error_node(); 33518 | } 33519 | 33520 | const T v = temp_node->value(); 33521 | 33522 | details::free_node(*node_allocator_,temp_node); 33523 | 33524 | return node_allocator_->allocate<literal_node_t>(v); 33525 | } 33526 | 33527 | inline bool special_one_parameter_vararg(const details::operator_type& operation) const 33528 | { 33529 | return ( 33530 | (details::e_sum == operation) || 33531 | (details::e_prod == operation) || 33532 | (details::e_avg == operation) || 33533 | (details::e_min == operation) || 33534 | (details::e_max == operation) 33535 | ); 33536 | } 33537 | 33538 | template <typename Allocator, 33539 | template <typename, typename> class Sequence> 33540 | inline expression_node_ptr varnode_optimise_varargfunc(const details::operator_type& operation, 33541 | Sequence<expression_node_ptr,Allocator>& arg_list) 33542 | { 33543 | switch (operation) 33544 | { 33545 | #define case_stmt(op0, op1) \ 33546 | case op0 : return node_allocator_-> \ 33547 | allocate<details::vararg_varnode<Type,op1<Type> > >(arg_list); \ 33548 | 33549 | case_stmt(details::e_sum , details::vararg_add_op ) 33550 | case_stmt(details::e_prod , details::vararg_mul_op ) 33551 | case_stmt(details::e_avg , details::vararg_avg_op ) 33552 | case_stmt(details::e_min , details::vararg_min_op ) 33553 | case_stmt(details::e_max , details::vararg_max_op ) 33554 | case_stmt(details::e_mand , details::vararg_mand_op ) 33555 | case_stmt(details::e_mor , details::vararg_mor_op ) 33556 | case_stmt(details::e_multi , details::vararg_multi_op) 33557 | #undef case_stmt 33558 | default : return error_node(); 33559 | } 33560 | } 33561 | 33562 | template <typename Allocator, 33563 | template <typename, typename> class Sequence> 33564 | inline expression_node_ptr vectorize_func(const details::operator_type& operation, 33565 | Sequence<expression_node_ptr,Allocator>& arg_list) 33566 | { 33567 | if (1 == arg_list.size()) 33568 | { 33569 | switch (operation) 33570 | { 33571 | #define case_stmt(op0, op1) \ 33572 | case op0 : return node_allocator_-> \ 33573 | allocate<details::vectorize_node<Type,op1<Type> > >(arg_list[0]); \ 33574 | 33575 | case_stmt(details::e_sum , details::vec_add_op) 33576 | case_stmt(details::e_prod , details::vec_mul_op) 33577 | case_stmt(details::e_avg , details::vec_avg_op) 33578 | case_stmt(details::e_min , details::vec_min_op) 33579 | case_stmt(details::e_max , details::vec_max_op) 33580 | #undef case_stmt 33581 | default : return error_node(); 33582 | } 33583 | } 33584 | else 33585 | return error_node(); 33586 | } 33587 | 33588 | template <typename Allocator, 33589 | template <typename, typename> class Sequence> 33590 | inline expression_node_ptr vararg_function(const details::operator_type& operation, 33591 | Sequence<expression_node_ptr,Allocator>& arg_list) 33592 | { 33593 | if (!all_nodes_valid(arg_list)) 33594 | { 33595 | details::free_all_nodes(*node_allocator_,arg_list); 33596 | 33597 | return error_node(); 33598 | } 33599 | else if (is_constant_foldable(arg_list)) 33600 | return const_optimise_varargfunc(operation,arg_list); 33601 | else if ((1 == arg_list.size()) && details::is_ivector_node(arg_list[0])) 33602 | return vectorize_func(operation,arg_list); 33603 | else if ((1 == arg_list.size()) && special_one_parameter_vararg(operation)) 33604 | return arg_list[0]; 33605 | else if (all_nodes_variables(arg_list)) 33606 | return varnode_optimise_varargfunc(operation,arg_list); 33607 | 33608 | #ifndef exprtk_disable_string_capabilities 33609 | if (details::e_smulti == operation) 33610 | { 33611 | expression_node_ptr result = node_allocator_-> 33612 | allocate<details::str_vararg_node<Type,details::vararg_multi_op<Type> > >(arg_list); 33613 | if (result && result->valid()) 33614 | { 33615 | return result; 33616 | } 33617 | 33618 | parser_->set_error(parser_error::make_error( 33619 | parser_error::e_synthesis, 33620 | token_t(), 33621 | "ERR261 - Failed to synthesize node: str_vararg_node<vararg_multi_op>", 33622 | exprtk_error_location)); 33623 | 33624 | details::free_node(*node_allocator_, result); 33625 | } 33626 | else 33627 | #endif 33628 | { 33629 | expression_node_ptr result = error_node(); 33630 | 33631 | switch (operation) 33632 | { 33633 | #define case_stmt(op0, op1) \ 33634 | case op0 : result = node_allocator_-> \ 33635 | allocate<details::vararg_node<Type,op1<Type> > >(arg_list); \ 33636 | break; \ 33637 | 33638 | case_stmt(details::e_sum , details::vararg_add_op ) 33639 | case_stmt(details::e_prod , details::vararg_mul_op ) 33640 | case_stmt(details::e_avg , details::vararg_avg_op ) 33641 | case_stmt(details::e_min , details::vararg_min_op ) 33642 | case_stmt(details::e_max , details::vararg_max_op ) 33643 | case_stmt(details::e_mand , details::vararg_mand_op ) 33644 | case_stmt(details::e_mor , details::vararg_mor_op ) 33645 | case_stmt(details::e_multi , details::vararg_multi_op) 33646 | #undef case_stmt 33647 | default : return error_node(); 33648 | } 33649 | 33650 | if (result && result->valid()) 33651 | { 33652 | return result; 33653 | } 33654 | 33655 | parser_->set_error(parser_error::make_error( 33656 | parser_error::e_synthesis, 33657 | token_t(), 33658 | "ERR262 - Failed to synthesize node: vararg_node", 33659 | exprtk_error_location)); 33660 | 33661 | details::free_node(*node_allocator_, result); 33662 | } 33663 | 33664 | return error_node(); 33665 | } 33666 | 33667 | template <std::size_t N> 33668 | inline expression_node_ptr function(ifunction_t* f, expression_node_ptr (&b)[N]) 33669 | { 33670 | typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t; 33671 | expression_node_ptr result = synthesize_expression<function_N_node_t,N>(f,b); 33672 | 33673 | if (0 == result) 33674 | return error_node(); 33675 | else 33676 | { 33677 | // Can the function call be completely optimised? 33678 | if (details::is_constant_node(result)) 33679 | return result; 33680 | else if (!all_nodes_valid(b)) 33681 | { 33682 | details::free_node(*node_allocator_,result); 33683 | std::fill_n(b, N, reinterpret_cast<expression_node_ptr>(0)); 33684 | 33685 | return error_node(); 33686 | } 33687 | else if (N != f->param_count) 33688 | { 33689 | details::free_node(*node_allocator_,result); 33690 | std::fill_n(b, N, reinterpret_cast<expression_node_ptr>(0)); 33691 | 33692 | return error_node(); 33693 | } 33694 | 33695 | function_N_node_t* func_node_ptr = reinterpret_cast<function_N_node_t*>(result); 33696 | 33697 | if (!func_node_ptr->init_branches(b)) 33698 | { 33699 | details::free_node(*node_allocator_,result); 33700 | std::fill_n(b, N, reinterpret_cast<expression_node_ptr>(0)); 33701 | 33702 | return error_node(); 33703 | } 33704 | 33705 | if (result && result->valid()) 33706 | { 33707 | return result; 33708 | } 33709 | 33710 | parser_->set_error(parser_error::make_error( 33711 | parser_error::e_synthesis, 33712 | token_t(), 33713 | "ERR263 - Failed to synthesize node: function_N_node_t", 33714 | exprtk_error_location)); 33715 | 33716 | details::free_node(*node_allocator_, result); 33717 | return error_node(); 33718 | } 33719 | } 33720 | 33721 | inline expression_node_ptr function(ifunction_t* f) 33722 | { 33723 | typedef typename details::function_N_node<Type,ifunction_t,0> function_N_node_t; 33724 | return node_allocator_->allocate<function_N_node_t>(f); 33725 | } 33726 | 33727 | inline expression_node_ptr vararg_function_call(ivararg_function_t* vaf, 33728 | std::vector<expression_node_ptr>& arg_list) 33729 | { 33730 | if (!all_nodes_valid(arg_list)) 33731 | { 33732 | details::free_all_nodes(*node_allocator_,arg_list); 33733 | 33734 | return error_node(); 33735 | } 33736 | 33737 | typedef details::vararg_function_node<Type,ivararg_function_t> alloc_type; 33738 | 33739 | expression_node_ptr result = node_allocator_->allocate<alloc_type>(vaf,arg_list); 33740 | 33741 | if ( 33742 | !arg_list.empty() && 33743 | !vaf->has_side_effects() && 33744 | is_constant_foldable(arg_list) 33745 | ) 33746 | { 33747 | const Type v = result->value(); 33748 | details::free_node(*node_allocator_,result); 33749 | result = node_allocator_->allocate<literal_node_t>(v); 33750 | } 33751 | 33752 | parser_->state_.activate_side_effect("vararg_function_call()"); 33753 | 33754 | if (result && result->valid()) 33755 | { 33756 | return result; 33757 | } 33758 | 33759 | parser_->set_error(parser_error::make_error( 33760 | parser_error::e_synthesis, 33761 | token_t(), 33762 | "ERR264 - Failed to synthesize node: vararg_function_node<ivararg_function_t>", 33763 | exprtk_error_location)); 33764 | 33765 | details::free_node(*node_allocator_, result); 33766 | return error_node(); 33767 | } 33768 | 33769 | inline expression_node_ptr generic_function_call(igeneric_function_t* gf, 33770 | std::vector<expression_node_ptr>& arg_list, 33771 | const std::size_t& param_seq_index = std::numeric_limits<std::size_t>::max()) 33772 | { 33773 | if (!all_nodes_valid(arg_list)) 33774 | { 33775 | details::free_all_nodes(*node_allocator_,arg_list); 33776 | return error_node(); 33777 | } 33778 | 33779 | typedef details::generic_function_node <Type,igeneric_function_t> alloc_type1; 33780 | typedef details::multimode_genfunction_node<Type,igeneric_function_t> alloc_type2; 33781 | 33782 | const std::size_t no_psi = std::numeric_limits<std::size_t>::max(); 33783 | 33784 | expression_node_ptr result = error_node(); 33785 | std::string node_name = "Unknown" 33786 | 33787 | if (no_psi == param_seq_index) 33788 | { 33789 | result = node_allocator_->allocate<alloc_type1>(arg_list,gf); 33790 | node_name = "generic_function_node<igeneric_function_t>" 33791 | } 33792 | else 33793 | { 33794 | result = node_allocator_->allocate<alloc_type2>(gf, param_seq_index, arg_list); 33795 | node_name = "multimode_genfunction_node<igeneric_function_t>" 33796 | } 33797 | 33798 | alloc_type1* genfunc_node_ptr = static_cast<alloc_type1*>(result); 33799 | 33800 | assert(genfunc_node_ptr); 33801 | 33802 | if ( 33803 | !arg_list.empty() && 33804 | !gf->has_side_effects() && 33805 | parser_->state_.type_check_enabled && 33806 | is_constant_foldable(arg_list) 33807 | ) 33808 | { 33809 | genfunc_node_ptr->init_branches(); 33810 | 33811 | const Type v = result->value(); 33812 | 33813 | details::free_node(*node_allocator_,result); 33814 | 33815 | return node_allocator_->allocate<literal_node_t>(v); 33816 | } 33817 | else if (genfunc_node_ptr->init_branches()) 33818 | { 33819 | if (result && result->valid()) 33820 | { 33821 | parser_->state_.activate_side_effect("generic_function_call()"); 33822 | return result; 33823 | } 33824 | 33825 | parser_->set_error(parser_error::make_error( 33826 | parser_error::e_synthesis, 33827 | token_t(), 33828 | "ERR265 - Failed to synthesize node: " + node_name, 33829 | exprtk_error_location)); 33830 | 33831 | details::free_node(*node_allocator_, result); 33832 | return error_node(); 33833 | } 33834 | else 33835 | { 33836 | details::free_node(*node_allocator_, result); 33837 | details::free_all_nodes(*node_allocator_, arg_list); 33838 | 33839 | return error_node(); 33840 | } 33841 | } 33842 | 33843 | #ifndef exprtk_disable_string_capabilities 33844 | inline expression_node_ptr string_function_call(igeneric_function_t* gf, 33845 | std::vector<expression_node_ptr>& arg_list, 33846 | const std::size_t& param_seq_index = std::numeric_limits<std::size_t>::max()) 33847 | { 33848 | if (!all_nodes_valid(arg_list)) 33849 | { 33850 | details::free_all_nodes(*node_allocator_,arg_list); 33851 | return error_node(); 33852 | } 33853 | 33854 | typedef details::string_function_node <Type,igeneric_function_t> alloc_type1; 33855 | typedef details::multimode_strfunction_node<Type,igeneric_function_t> alloc_type2; 33856 | 33857 | const std::size_t no_psi = std::numeric_limits<std::size_t>::max(); 33858 | 33859 | expression_node_ptr result = error_node(); 33860 | std::string node_name = "Unknown" 33861 | 33862 | if (no_psi == param_seq_index) 33863 | { 33864 | result = node_allocator_->allocate<alloc_type1>(gf,arg_list); 33865 | node_name = "string_function_node<igeneric_function_t>" 33866 | } 33867 | else 33868 | { 33869 | result = node_allocator_->allocate<alloc_type2>(gf, param_seq_index, arg_list); 33870 | node_name = "multimode_strfunction_node<igeneric_function_t>" 33871 | } 33872 | 33873 | alloc_type1* strfunc_node_ptr = static_cast<alloc_type1*>(result); 33874 | 33875 | assert(strfunc_node_ptr); 33876 | 33877 | if ( 33878 | !arg_list.empty() && 33879 | !gf->has_side_effects() && 33880 | is_constant_foldable(arg_list) 33881 | ) 33882 | { 33883 | strfunc_node_ptr->init_branches(); 33884 | 33885 | const Type v = result->value(); 33886 | 33887 | details::free_node(*node_allocator_,result); 33888 | 33889 | return node_allocator_->allocate<literal_node_t>(v); 33890 | } 33891 | else if (strfunc_node_ptr->init_branches()) 33892 | { 33893 | if (result && result->valid()) 33894 | { 33895 | parser_->state_.activate_side_effect("string_function_call()"); 33896 | return result; 33897 | } 33898 | 33899 | parser_->set_error(parser_error::make_error( 33900 | parser_error::e_synthesis, 33901 | token_t(), 33902 | "ERR266 - Failed to synthesize node: " + node_name, 33903 | exprtk_error_location)); 33904 | 33905 | details::free_node(*node_allocator_, result); 33906 | return error_node(); 33907 | } 33908 | else 33909 | { 33910 | details::free_node (*node_allocator_,result ); 33911 | details::free_all_nodes(*node_allocator_,arg_list); 33912 | 33913 | return error_node(); 33914 | } 33915 | } 33916 | #endif 33917 | 33918 | #ifndef exprtk_disable_return_statement 33919 | inline expression_node_ptr return_call(std::vector<expression_node_ptr>& arg_list) 33920 | { 33921 | if (!all_nodes_valid(arg_list)) 33922 | { 33923 | details::free_all_nodes(*node_allocator_,arg_list); 33924 | return error_node(); 33925 | } 33926 | 33927 | typedef details::return_node<Type> alloc_type; 33928 | 33929 | expression_node_ptr result = node_allocator_-> 33930 | allocate_rr<alloc_type>(arg_list,parser_->results_ctx()); 33931 | 33932 | alloc_type* return_node_ptr = static_cast<alloc_type*>(result); 33933 | 33934 | assert(return_node_ptr); 33935 | 33936 | if (return_node_ptr->init_branches()) 33937 | { 33938 | if (result && result->valid()) 33939 | { 33940 | parser_->state_.activate_side_effect("return_call()"); 33941 | return result; 33942 | } 33943 | 33944 | parser_->set_error(parser_error::make_error( 33945 | parser_error::e_synthesis, 33946 | token_t(), 33947 | "ERR267 - Failed to synthesize node: return_node", 33948 | exprtk_error_location)); 33949 | 33950 | details::free_node(*node_allocator_, result); 33951 | return error_node(); 33952 | } 33953 | else 33954 | { 33955 | details::free_node (*node_allocator_, result ); 33956 | details::free_all_nodes(*node_allocator_, arg_list); 33957 | 33958 | return error_node(); 33959 | } 33960 | } 33961 | 33962 | inline expression_node_ptr return_envelope(expression_node_ptr body, 33963 | results_context_t* rc, 33964 | bool*& return_invoked) 33965 | { 33966 | typedef details::return_envelope_node<Type> alloc_type; 33967 | 33968 | expression_node_ptr result = node_allocator_-> 33969 | allocate_cr<alloc_type>(body,(*rc)); 33970 | 33971 | return_invoked = static_cast<alloc_type*>(result)->retinvk_ptr(); 33972 | 33973 | return result; 33974 | } 33975 | #else 33976 | inline expression_node_ptr return_call(std::vector<expression_node_ptr>&) 33977 | { 33978 | return error_node(); 33979 | } 33980 | 33981 | inline expression_node_ptr return_envelope(expression_node_ptr, 33982 | results_context_t*, 33983 | bool*&) 33984 | { 33985 | return error_node(); 33986 | } 33987 | #endif 33988 | 33989 | inline expression_node_ptr vector_element(const std::string& symbol, 33990 | vector_holder_ptr vector_base, 33991 | expression_node_ptr vec_node, 33992 | expression_node_ptr index) 33993 | { 33994 | expression_node_ptr result = error_node(); 33995 | std::string node_name = "Unknown" 33996 | 33997 | if (details::is_constant_node(index)) 33998 | { 33999 | const std::size_t vec_index = static_cast<std::size_t>(details::numeric::to_int64(index->value())); 34000 | 34001 | details::free_node(*node_allocator_,index); 34002 | 34003 | if (vec_index >= vector_base->size()) 34004 | { 34005 | parser_->set_error(parser_error::make_error( 34006 | parser_error::e_parser, 34007 | token_t(), 34008 | "ERR268 - Index of " + details::to_str(vec_index) + " out of range for " 34009 | "vector '" + symbol + "' of size " + details::to_str(vector_base->size()), 34010 | exprtk_error_location)); 34011 | 34012 | details::free_node(*node_allocator_,vec_node); 34013 | 34014 | return error_node(); 34015 | } 34016 | 34017 | if (vector_base->rebaseable()) 34018 | { 34019 | vector_access_runtime_check_ptr rtc = get_vector_access_runtime_check(); 34020 | 34021 | result = (rtc) ? 34022 | node_allocator_->allocate<rebasevector_celem_rtc_node_t>(vec_node, vec_index, vector_base, rtc) : 34023 | node_allocator_->allocate<rebasevector_celem_node_t >(vec_node, vec_index, vector_base ) ; 34024 | 34025 | node_name = (rtc) ? 34026 | "rebasevector_elem_rtc_node_t" : 34027 | "rebasevector_elem_node_t" ; 34028 | 34029 | if (result && result->valid()) 34030 | { 34031 | return result; 34032 | } 34033 | 34034 | parser_->set_error(parser_error::make_error( 34035 | parser_error::e_synthesis, 34036 | token_t(), 34037 | "ERR269 - Failed to synthesize node: " + node_name + " for vector: " + symbol, 34038 | exprtk_error_location)); 34039 | 34040 | details::free_node(*node_allocator_, result); 34041 | return error_node(); 34042 | } 34043 | else if (details::is_ivector_node(vec_node) && !details::is_vector_node(vec_node)) 34044 | { 34045 | vector_access_runtime_check_ptr rtc = get_vector_access_runtime_check(); 34046 | 34047 | result = (rtc) ? 34048 | node_allocator_->allocate<vector_celem_rtc_node_t>(vec_node, vec_index, vector_base, rtc) : 34049 | node_allocator_->allocate<vector_celem_node_t >(vec_node, vec_index, vector_base ) ; 34050 | 34051 | node_name = (rtc) ? 34052 | "vector_elem_rtc_node_t" : 34053 | "vector_elem_node_t" ; 34054 | 34055 | if (result && result->valid()) 34056 | { 34057 | return result; 34058 | } 34059 | 34060 | parser_->set_error(parser_error::make_error( 34061 | parser_error::e_synthesis, 34062 | token_t(), 34063 | "ERR270 - Failed to synthesize node: " + node_name + " for vector: " + symbol, 34064 | exprtk_error_location)); 34065 | 34066 | details::free_node(*node_allocator_, result); 34067 | return error_node(); 34068 | } 34069 | 34070 | const scope_element& se = parser_->sem_.get_element(symbol,vec_index); 34071 | 34072 | if (se.index == vec_index) 34073 | { 34074 | result = se.var_node; 34075 | details::free_node(*node_allocator_,vec_node); 34076 | } 34077 | else 34078 | { 34079 | scope_element nse; 34080 | nse.name = symbol; 34081 | nse.active = true; 34082 | nse.ref_count = 1; 34083 | nse.type = scope_element::e_vecelem; 34084 | nse.index = vec_index; 34085 | nse.depth = parser_->state_.scope_depth; 34086 | nse.data = 0; 34087 | nse.var_node = node_allocator_->allocate<variable_node_t>((*(*vector_base)[vec_index])); 34088 | 34089 | if (!parser_->sem_.add_element(nse)) 34090 | { 34091 | parser_->set_synthesis_error("Failed to add new local vector element to SEM [1]"); 34092 | 34093 | parser_->sem_.free_element(nse); 34094 | 34095 | result = error_node(); 34096 | } 34097 | 34098 | assert(parser_->sem_.total_local_symb_size_bytes() <= parser_->settings().max_total_local_symbol_size_bytes()); 34099 | 34100 | details::free_node(*node_allocator_,vec_node); 34101 | 34102 | exprtk_debug(("vector_element() - INFO - Added new local vector element: %s\n", nse.name.c_str())); 34103 | 34104 | parser_->state_.activate_side_effect("vector_element()"); 34105 | 34106 | result = nse.var_node; 34107 | node_name = "variable_node_t" 34108 | } 34109 | } 34110 | else 34111 | { 34112 | vector_access_runtime_check_ptr rtc = get_vector_access_runtime_check(); 34113 | 34114 | if (vector_base->rebaseable()) 34115 | { 34116 | result = (rtc) ? 34117 | node_allocator_->allocate<rebasevector_elem_rtc_node_t>(vec_node, index, vector_base, rtc) : 34118 | node_allocator_->allocate<rebasevector_elem_node_t >(vec_node, index, vector_base ) ; 34119 | 34120 | node_name = (rtc) ? 34121 | "rebasevector_elem_rtc_node_t" : 34122 | "rebasevector_elem_node_t" ; 34123 | } 34124 | else 34125 | { 34126 | result = rtc ? 34127 | node_allocator_->allocate<vector_elem_rtc_node_t>(vec_node, index, vector_base, rtc) : 34128 | node_allocator_->allocate<vector_elem_node_t >(vec_node, index, vector_base ) ; 34129 | 34130 | node_name = (rtc) ? 34131 | "vector_elem_rtc_node_t" : 34132 | "vector_elem_node_t" ; 34133 | } 34134 | } 34135 | 34136 | if (result && result->valid()) 34137 | { 34138 | return result; 34139 | } 34140 | 34141 | parser_->set_error(parser_error::make_error( 34142 | parser_error::e_synthesis, 34143 | token_t(), 34144 | "ERR271 - Failed to synthesize node: " + node_name, 34145 | exprtk_error_location)); 34146 | 34147 | details::free_node(*node_allocator_, result); 34148 | return error_node(); 34149 | } 34150 | 34151 | private: 34152 | 34153 | template <std::size_t N, typename NodePtr> 34154 | inline bool is_constant_foldable(NodePtr (&b)[N]) const 34155 | { 34156 | for (std::size_t i = 0; i < N; ++i) 34157 | { 34158 | if (0 == b[i]) 34159 | return false; 34160 | else if (!details::is_constant_node(b[i])) 34161 | return false; 34162 | } 34163 | 34164 | return true; 34165 | } 34166 | 34167 | template <typename NodePtr, 34168 | typename Allocator, 34169 | template <typename, typename> class Sequence> 34170 | inline bool is_constant_foldable(const Sequence<NodePtr,Allocator>& b) const 34171 | { 34172 | for (std::size_t i = 0; i < b.size(); ++i) 34173 | { 34174 | if (0 == b[i]) 34175 | return false; 34176 | else if (!details::is_constant_node(b[i])) 34177 | return false; 34178 | } 34179 | 34180 | return true; 34181 | } 34182 | 34183 | void lodge_assignment(symbol_type cst, expression_node_ptr node) 34184 | { 34185 | parser_->state_.activate_side_effect("lodge_assignment()"); 34186 | 34187 | if (!parser_->dec_.collect_assignments()) 34188 | return; 34189 | 34190 | std::string symbol_name; 34191 | 34192 | switch (cst) 34193 | { 34194 | case e_st_variable : symbol_name = parser_->symtab_store_ 34195 | .get_variable_name(node); 34196 | break; 34197 | 34198 | #ifndef exprtk_disable_string_capabilities 34199 | case e_st_string : symbol_name = parser_->symtab_store_ 34200 | .get_stringvar_name(node); 34201 | break; 34202 | #endif 34203 | 34204 | case e_st_vector : { 34205 | typedef details::vector_holder<T> vector_holder_t; 34206 | 34207 | vector_holder_t& vh = static_cast<vector_node_t*>(node)->vec_holder(); 34208 | 34209 | symbol_name = parser_->symtab_store_.get_vector_name(&vh); 34210 | } 34211 | break; 34212 | 34213 | case e_st_vecelem : { 34214 | typedef details::vector_holder<T> vector_holder_t; 34215 | 34216 | vector_holder_t& vh = static_cast<vector_elem_node_t*>(node)->vec_holder(); 34217 | 34218 | symbol_name = parser_->symtab_store_.get_vector_name(&vh); 34219 | 34220 | cst = e_st_vector; 34221 | } 34222 | break; 34223 | 34224 | default : return; 34225 | } 34226 | 34227 | if (!symbol_name.empty()) 34228 | { 34229 | parser_->dec_.add_assignment(symbol_name,cst); 34230 | } 34231 | } 34232 | 34233 | const void* base_ptr(expression_node_ptr node) 34234 | { 34235 | if (node) 34236 | { 34237 | switch (node->type()) 34238 | { 34239 | case details::expression_node<T>::e_variable: 34240 | return reinterpret_cast<const void*>(&static_cast<variable_node_t*>(node)->ref()); 34241 | 34242 | case details::expression_node<T>::e_vecelem: 34243 | return reinterpret_cast<const void*>(&static_cast<vector_elem_node_t*>(node)->ref()); 34244 | 34245 | case details::expression_node<T>::e_veccelem: 34246 | return reinterpret_cast<const void*>(&static_cast<vector_celem_node_t*>(node)->ref()); 34247 | 34248 | case details::expression_node<T>::e_vecelemrtc: 34249 | return reinterpret_cast<const void*>(&static_cast<vector_elem_rtc_node_t*>(node)->ref()); 34250 | 34251 | case details::expression_node<T>::e_veccelemrtc: 34252 | return reinterpret_cast<const void*>(&static_cast<vector_celem_rtc_node_t*>(node)->ref()); 34253 | 34254 | case details::expression_node<T>::e_rbvecelem: 34255 | return reinterpret_cast<const void*>(&static_cast<rebasevector_elem_node_t*>(node)->ref()); 34256 | 34257 | case details::expression_node<T>::e_rbvecelemrtc: 34258 | return reinterpret_cast<const void*>(&static_cast<rebasevector_elem_rtc_node_t*>(node)->ref()); 34259 | 34260 | case details::expression_node<T>::e_rbveccelem: 34261 | return reinterpret_cast<const void*>(&static_cast<rebasevector_celem_node_t*>(node)->ref()); 34262 | 34263 | case details::expression_node<T>::e_rbveccelemrtc: 34264 | return reinterpret_cast<const void*>(&static_cast<rebasevector_celem_rtc_node_t*>(node)->ref()); 34265 | 34266 | case details::expression_node<T>::e_vector: 34267 | return reinterpret_cast<const void*>(static_cast<vector_node_t*>(node)->vec_holder().data()); 34268 | 34269 | #ifndef exprtk_disable_string_capabilities 34270 | case details::expression_node<T>::e_stringvar: 34271 | return reinterpret_cast<const void*>((static_cast<stringvar_node_t*>(node)->base())); 34272 | 34273 | case details::expression_node<T>::e_stringvarrng: 34274 | return reinterpret_cast<const void*>((static_cast<string_range_node_t*>(node)->base())); 34275 | #endif 34276 | default : return reinterpret_cast<const void*>(0); 34277 | } 34278 | } 34279 | 34280 | return reinterpret_cast<const void*>(0); 34281 | } 34282 | 34283 | bool assign_immutable_symbol(expression_node_ptr node) 34284 | { 34285 | interval_t interval; 34286 | const void* baseptr_addr = base_ptr(node); 34287 | 34288 | exprtk_debug(("assign_immutable_symbol - base ptr addr: %p\n", baseptr_addr)); 34289 | 34290 | if (parser_->immutable_memory_map_.in_interval(baseptr_addr,interval)) 34291 | { 34292 | typename immutable_symtok_map_t::iterator itr = parser_->immutable_symtok_map_.find(interval); 34293 | 34294 | if (parser_->immutable_symtok_map_.end() != itr) 34295 | { 34296 | token_t& token = itr->second; 34297 | parser_->set_error(parser_error::make_error( 34298 | parser_error::e_parser, 34299 | token, 34300 | "ERR272 - Symbol '" + token.value + "' cannot be assigned-to as it is immutable.", 34301 | exprtk_error_location)); 34302 | } 34303 | else 34304 | parser_->set_synthesis_error("Unable to assign symbol is immutable."); 34305 | 34306 | return true; 34307 | } 34308 | 34309 | return false; 34310 | } 34311 | 34312 | inline expression_node_ptr synthesize_assignment_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2]) 34313 | { 34314 | if (assign_immutable_symbol(branch[0])) 34315 | { 34316 | return error_node(); 34317 | } 34318 | else if (details::is_variable_node(branch[0])) 34319 | { 34320 | lodge_assignment(e_st_variable,branch[0]); 34321 | return synthesize_expression<assignment_node_t,2>(operation,branch); 34322 | } 34323 | else if (details::is_vector_elem_node(branch[0]) || details::is_vector_celem_node(branch[0])) 34324 | { 34325 | lodge_assignment(e_st_vecelem,branch[0]); 34326 | return synthesize_expression<assignment_vec_elem_node_t, 2>(operation, branch); 34327 | } 34328 | else if (details::is_vector_elem_rtc_node(branch[0]) || details::is_vector_celem_rtc_node(branch[0])) 34329 | { 34330 | lodge_assignment(e_st_vecelem,branch[0]); 34331 | return synthesize_expression<assignment_vec_elem_rtc_node_t, 2>(operation, branch); 34332 | } 34333 | else if (details::is_rebasevector_elem_node(branch[0])) 34334 | { 34335 | lodge_assignment(e_st_vecelem,branch[0]); 34336 | return synthesize_expression<assignment_rebasevec_elem_node_t, 2>(operation, branch); 34337 | } 34338 | else if (details::is_rebasevector_elem_rtc_node(branch[0])) 34339 | { 34340 | lodge_assignment(e_st_vecelem,branch[0]); 34341 | return synthesize_expression<assignment_rebasevec_elem_rtc_node_t, 2>(operation, branch); 34342 | } 34343 | else if (details::is_rebasevector_celem_node(branch[0])) 34344 | { 34345 | lodge_assignment(e_st_vecelem,branch[0]); 34346 | return synthesize_expression<assignment_rebasevec_celem_node_t, 2>(operation, branch); 34347 | } 34348 | #ifndef exprtk_disable_string_capabilities 34349 | else if (details::is_string_node(branch[0])) 34350 | { 34351 | lodge_assignment(e_st_string,branch[0]); 34352 | return synthesize_expression<assignment_string_node_t,2>(operation, branch); 34353 | } 34354 | else if (details::is_string_range_node(branch[0])) 34355 | { 34356 | lodge_assignment(e_st_string,branch[0]); 34357 | return synthesize_expression<assignment_string_range_node_t,2>(operation, branch); 34358 | } 34359 | #endif 34360 | else if (details::is_vector_node(branch[0])) 34361 | { 34362 | lodge_assignment(e_st_vector,branch[0]); 34363 | 34364 | if (details::is_ivector_node(branch[1])) 34365 | return synthesize_expression<assignment_vecvec_node_t,2>(operation, branch); 34366 | else 34367 | return synthesize_expression<assignment_vec_node_t,2>(operation, branch); 34368 | } 34369 | else if (details::is_literal_node(branch[0])) 34370 | { 34371 | parser_->set_error(parser_error::make_error( 34372 | parser_error::e_syntax, 34373 | parser_->current_state().token, 34374 | "ERR273 - Cannot assign value to const variable", 34375 | exprtk_error_location)); 34376 | 34377 | return error_node(); 34378 | } 34379 | else 34380 | { 34381 | parser_->set_error(parser_error::make_error( 34382 | parser_error::e_syntax, 34383 | parser_->current_state().token, 34384 | "ERR274 - Invalid branches for assignment operator '" + details::to_str(operation) + "'", 34385 | exprtk_error_location)); 34386 | 34387 | return error_node(); 34388 | } 34389 | } 34390 | 34391 | inline expression_node_ptr synthesize_assignment_operation_expression(const details::operator_type& operation, 34392 | expression_node_ptr (&branch)[2]) 34393 | { 34394 | if (assign_immutable_symbol(branch[0])) 34395 | { 34396 | return error_node(); 34397 | } 34398 | 34399 | expression_node_ptr result = error_node(); 34400 | std::string node_name = "Unknown" 34401 | 34402 | if (details::is_variable_node(branch[0])) 34403 | { 34404 | lodge_assignment(e_st_variable,branch[0]); 34405 | 34406 | switch (operation) 34407 | { 34408 | #define case_stmt(op0, op1) \ 34409 | case op0 : result = node_allocator_-> \ 34410 | template allocate_rrr<typename details::assignment_op_node<Type,op1<Type> > > \ 34411 | (operation, branch[0], branch[1]); \ 34412 | node_name = "assignment_op_node" \ 34413 | break; \ 34414 | 34415 | case_stmt(details::e_addass , details::add_op) 34416 | case_stmt(details::e_subass , details::sub_op) 34417 | case_stmt(details::e_mulass , details::mul_op) 34418 | case_stmt(details::e_divass , details::div_op) 34419 | case_stmt(details::e_modass , details::mod_op) 34420 | #undef case_stmt 34421 | default : return error_node(); 34422 | } 34423 | } 34424 | else if (details::is_vector_elem_node(branch[0])) 34425 | { 34426 | lodge_assignment(e_st_vecelem,branch[0]); 34427 | 34428 | switch (operation) 34429 | { 34430 | #define case_stmt(op0, op1) \ 34431 | case op0 : result = node_allocator_-> \ 34432 | template allocate_rrr<typename details::assignment_vec_elem_op_node<Type,op1<Type> > > \ 34433 | (operation, branch[0], branch[1]); \ 34434 | node_name = "assignment_vec_elem_op_node" \ 34435 | break; \ 34436 | 34437 | case_stmt(details::e_addass , details::add_op) 34438 | case_stmt(details::e_subass , details::sub_op) 34439 | case_stmt(details::e_mulass , details::mul_op) 34440 | case_stmt(details::e_divass , details::div_op) 34441 | case_stmt(details::e_modass , details::mod_op) 34442 | #undef case_stmt 34443 | default : return error_node(); 34444 | } 34445 | } 34446 | else if (details::is_vector_elem_rtc_node(branch[0])) 34447 | { 34448 | lodge_assignment(e_st_vecelem,branch[0]); 34449 | 34450 | switch (operation) 34451 | { 34452 | #define case_stmt(op0, op1) \ 34453 | case op0 : result = node_allocator_-> \ 34454 | template allocate_rrr<typename details::assignment_vec_elem_op_rtc_node<Type,op1<Type> > > \ 34455 | (operation, branch[0], branch[1]); \ 34456 | node_name = "assignment_vec_elem_op_rtc_node" \ 34457 | break; \ 34458 | 34459 | case_stmt(details::e_addass , details::add_op) 34460 | case_stmt(details::e_subass , details::sub_op) 34461 | case_stmt(details::e_mulass , details::mul_op) 34462 | case_stmt(details::e_divass , details::div_op) 34463 | case_stmt(details::e_modass , details::mod_op) 34464 | #undef case_stmt 34465 | default : return error_node(); 34466 | } 34467 | } 34468 | else if (details::is_vector_celem_rtc_node(branch[0])) 34469 | { 34470 | lodge_assignment(e_st_vecelem,branch[0]); 34471 | 34472 | switch (operation) 34473 | { 34474 | #define case_stmt(op0, op1) \ 34475 | case op0 : result = node_allocator_-> \ 34476 | template allocate_rrr<typename details::assignment_vec_celem_op_rtc_node<Type,op1<Type> > > \ 34477 | (operation, branch[0], branch[1]); \ 34478 | node_name = "assignment_vec_celem_op_rtc_node" \ 34479 | break; \ 34480 | 34481 | case_stmt(details::e_addass , details::add_op) 34482 | case_stmt(details::e_subass , details::sub_op) 34483 | case_stmt(details::e_mulass , details::mul_op) 34484 | case_stmt(details::e_divass , details::div_op) 34485 | case_stmt(details::e_modass , details::mod_op) 34486 | #undef case_stmt 34487 | default : return error_node(); 34488 | } 34489 | } 34490 | else if (details::is_rebasevector_elem_node(branch[0])) 34491 | { 34492 | lodge_assignment(e_st_vecelem,branch[0]); 34493 | 34494 | switch (operation) 34495 | { 34496 | #define case_stmt(op0, op1) \ 34497 | case op0 : result = node_allocator_-> \ 34498 | template allocate_rrr<typename details::assignment_rebasevec_elem_op_node<Type,op1<Type> > > \ 34499 | (operation, branch[0], branch[1]); \ 34500 | node_name = "assignment_rebasevec_elem_op_node" \ 34501 | break; \ 34502 | 34503 | case_stmt(details::e_addass , details::add_op) 34504 | case_stmt(details::e_subass , details::sub_op) 34505 | case_stmt(details::e_mulass , details::mul_op) 34506 | case_stmt(details::e_divass , details::div_op) 34507 | case_stmt(details::e_modass , details::mod_op) 34508 | #undef case_stmt 34509 | default : return error_node(); 34510 | } 34511 | } 34512 | else if (details::is_rebasevector_celem_node(branch[0])) 34513 | { 34514 | lodge_assignment(e_st_vecelem,branch[0]); 34515 | 34516 | switch (operation) 34517 | { 34518 | #define case_stmt(op0, op1) \ 34519 | case op0 : result = node_allocator_-> \ 34520 | template allocate_rrr<typename details::assignment_rebasevec_celem_op_node<Type,op1<Type> > > \ 34521 | (operation, branch[0], branch[1]); \ 34522 | node_name = "assignment_rebasevec_celem_op_node" \ 34523 | break; \ 34524 | 34525 | case_stmt(details::e_addass , details::add_op) 34526 | case_stmt(details::e_subass , details::sub_op) 34527 | case_stmt(details::e_mulass , details::mul_op) 34528 | case_stmt(details::e_divass , details::div_op) 34529 | case_stmt(details::e_modass , details::mod_op) 34530 | #undef case_stmt 34531 | default : return error_node(); 34532 | } 34533 | } 34534 | else if (details::is_rebasevector_elem_rtc_node(branch[0])) 34535 | { 34536 | lodge_assignment(e_st_vecelem,branch[0]); 34537 | 34538 | switch (operation) 34539 | { 34540 | #define case_stmt(op0, op1) \ 34541 | case op0 : result = node_allocator_-> \ 34542 | template allocate_rrr<typename details::assignment_rebasevec_elem_op_rtc_node<Type,op1<Type> > > \ 34543 | (operation, branch[0], branch[1]); \ 34544 | node_name = "assignment_rebasevec_elem_op_rtc_node" \ 34545 | break; \ 34546 | 34547 | case_stmt(details::e_addass , details::add_op) 34548 | case_stmt(details::e_subass , details::sub_op) 34549 | case_stmt(details::e_mulass , details::mul_op) 34550 | case_stmt(details::e_divass , details::div_op) 34551 | case_stmt(details::e_modass , details::mod_op) 34552 | #undef case_stmt 34553 | default : return error_node(); 34554 | } 34555 | } 34556 | else if (details::is_rebasevector_celem_rtc_node(branch[0])) 34557 | { 34558 | lodge_assignment(e_st_vecelem,branch[0]); 34559 | 34560 | switch (operation) 34561 | { 34562 | #define case_stmt(op0, op1) \ 34563 | case op0 : result = node_allocator_-> \ 34564 | template allocate_rrr<typename details::assignment_rebasevec_celem_op_rtc_node<Type,op1<Type> > > \ 34565 | (operation, branch[0], branch[1]); \ 34566 | node_name = "assignment_rebasevec_celem_op_rtc_node" \ 34567 | break; \ 34568 | 34569 | case_stmt(details::e_addass , details::add_op) 34570 | case_stmt(details::e_subass , details::sub_op) 34571 | case_stmt(details::e_mulass , details::mul_op) 34572 | case_stmt(details::e_divass , details::div_op) 34573 | case_stmt(details::e_modass , details::mod_op) 34574 | #undef case_stmt 34575 | default : return error_node(); 34576 | } 34577 | } 34578 | else if (details::is_vector_node(branch[0])) 34579 | { 34580 | lodge_assignment(e_st_vector,branch[0]); 34581 | 34582 | if (details::is_ivector_node(branch[1])) 34583 | { 34584 | switch (operation) 34585 | { 34586 | #define case_stmt(op0, op1) \ 34587 | case op0 : result = node_allocator_-> \ 34588 | template allocate_rrr<typename details::assignment_vecvec_op_node<Type,op1<Type> > > \ 34589 | (operation, branch[0], branch[1]); \ 34590 | node_name = "assignment_rebasevec_celem_op_node" \ 34591 | break; \ 34592 | 34593 | case_stmt(details::e_addass , details::add_op) 34594 | case_stmt(details::e_subass , details::sub_op) 34595 | case_stmt(details::e_mulass , details::mul_op) 34596 | case_stmt(details::e_divass , details::div_op) 34597 | case_stmt(details::e_modass , details::mod_op) 34598 | #undef case_stmt 34599 | default : return error_node(); 34600 | } 34601 | } 34602 | else 34603 | { 34604 | switch (operation) 34605 | { 34606 | #define case_stmt(op0, op1) \ 34607 | case op0 : result = node_allocator_-> \ 34608 | template allocate_rrr<typename details::assignment_vec_op_node<Type,op1<Type> > > \ 34609 | (operation, branch[0], branch[1]); \ 34610 | node_name = "assignment_vec_op_node" \ 34611 | break; \ 34612 | 34613 | case_stmt(details::e_addass , details::add_op) 34614 | case_stmt(details::e_subass , details::sub_op) 34615 | case_stmt(details::e_mulass , details::mul_op) 34616 | case_stmt(details::e_divass , details::div_op) 34617 | case_stmt(details::e_modass , details::mod_op) 34618 | #undef case_stmt 34619 | default : return error_node(); 34620 | } 34621 | } 34622 | } 34623 | #ifndef exprtk_disable_string_capabilities 34624 | else if ( 34625 | (details::e_addass == operation) && 34626 | details::is_string_node(branch[0]) 34627 | ) 34628 | { 34629 | typedef details::assignment_string_node<T,details::asn_addassignment> addass_t; 34630 | 34631 | lodge_assignment(e_st_string,branch[0]); 34632 | 34633 | result = synthesize_expression<addass_t,2>(operation,branch); 34634 | node_name = "assignment_string_node<T,details::asn_addassignment>" 34635 | } 34636 | #endif 34637 | else 34638 | { 34639 | parser_->set_error(parser_error::make_error( 34640 | parser_error::e_syntax, 34641 | parser_->current_state().token, 34642 | "ERR275 - Invalid branches for assignment operator '" + details::to_str(operation) + "'", 34643 | exprtk_error_location)); 34644 | 34645 | return error_node(); 34646 | } 34647 | 34648 | if (result && result->valid()) 34649 | { 34650 | return result; 34651 | } 34652 | 34653 | parser_->set_error(parser_error::make_error( 34654 | parser_error::e_synthesis, 34655 | token_t(), 34656 | "ERR276 - Failed to synthesize node: " + node_name, 34657 | exprtk_error_location)); 34658 | 34659 | details::free_node(*node_allocator_, result); 34660 | return error_node(); 34661 | } 34662 | 34663 | inline expression_node_ptr synthesize_veceqineqlogic_operation_expression(const details::operator_type& operation, 34664 | expression_node_ptr (&branch)[2]) 34665 | { 34666 | const bool is_b0_ivec = details::is_ivector_node(branch[0]); 34667 | const bool is_b1_ivec = details::is_ivector_node(branch[1]); 34668 | 34669 | #define batch_eqineq_logic_case \ 34670 | case_stmt(details::e_lt , details::lt_op ) \ 34671 | case_stmt(details::e_lte , details::lte_op ) \ 34672 | case_stmt(details::e_gt , details::gt_op ) \ 34673 | case_stmt(details::e_gte , details::gte_op ) \ 34674 | case_stmt(details::e_eq , details::eq_op ) \ 34675 | case_stmt(details::e_ne , details::ne_op ) \ 34676 | case_stmt(details::e_equal , details::equal_op) \ 34677 | case_stmt(details::e_and , details::and_op ) \ 34678 | case_stmt(details::e_nand , details::nand_op ) \ 34679 | case_stmt(details::e_or , details::or_op ) \ 34680 | case_stmt(details::e_nor , details::nor_op ) \ 34681 | case_stmt(details::e_xor , details::xor_op ) \ 34682 | case_stmt(details::e_xnor , details::xnor_op ) \ 34683 | 34684 | expression_node_ptr result = error_node(); 34685 | std::string node_name = "Unknown" 34686 | 34687 | if (is_b0_ivec && is_b1_ivec) 34688 | { 34689 | switch (operation) 34690 | { 34691 | #define case_stmt(op0, op1) \ 34692 | case op0 : result = node_allocator_-> \ 34693 | template allocate_rrr<typename details::vec_binop_vecvec_node<Type,op1<Type> > > \ 34694 | (operation, branch[0], branch[1]); \ 34695 | node_name = "vec_binop_vecvec_node" \ 34696 | break; \ 34697 | 34698 | batch_eqineq_logic_case 34699 | #undef case_stmt 34700 | default : return error_node(); 34701 | } 34702 | } 34703 | else if (is_b0_ivec && !is_b1_ivec) 34704 | { 34705 | switch (operation) 34706 | { 34707 | #define case_stmt(op0, op1) \ 34708 | case op0 : result = node_allocator_-> \ 34709 | template allocate_rrr<typename details::vec_binop_vecval_node<Type,op1<Type> > > \ 34710 | (operation, branch[0], branch[1]); \ 34711 | node_name = "vec_binop_vecval_node" \ 34712 | break; \ 34713 | 34714 | batch_eqineq_logic_case 34715 | #undef case_stmt 34716 | default : return error_node(); 34717 | } 34718 | } 34719 | else if (!is_b0_ivec && is_b1_ivec) 34720 | { 34721 | switch (operation) 34722 | { 34723 | #define case_stmt(op0, op1) \ 34724 | case op0 : result = node_allocator_-> \ 34725 | template allocate_rrr<typename details::vec_binop_valvec_node<Type,op1<Type> > > \ 34726 | (operation, branch[0], branch[1]); \ 34727 | node_name = "vec_binop_valvec_node" \ 34728 | break; \ 34729 | 34730 | batch_eqineq_logic_case 34731 | #undef case_stmt 34732 | default : return error_node(); 34733 | } 34734 | } 34735 | else 34736 | return error_node(); 34737 | 34738 | if (result && result->valid()) 34739 | { 34740 | return result; 34741 | } 34742 | 34743 | parser_->set_error(parser_error::make_error( 34744 | parser_error::e_synthesis, 34745 | token_t(), 34746 | "ERR277 - Failed to synthesize node: " + node_name, 34747 | exprtk_error_location)); 34748 | 34749 | details::free_node(*node_allocator_, result); 34750 | return error_node(); 34751 | 34752 | #undef batch_eqineq_logic_case 34753 | } 34754 | 34755 | inline expression_node_ptr synthesize_vecarithmetic_operation_expression(const details::operator_type& operation, 34756 | expression_node_ptr (&branch)[2]) 34757 | { 34758 | const bool is_b0_ivec = details::is_ivector_node(branch[0]); 34759 | const bool is_b1_ivec = details::is_ivector_node(branch[1]); 34760 | 34761 | #define vector_ops \ 34762 | case_stmt(details::e_add , details::add_op) \ 34763 | case_stmt(details::e_sub , details::sub_op) \ 34764 | case_stmt(details::e_mul , details::mul_op) \ 34765 | case_stmt(details::e_div , details::div_op) \ 34766 | case_stmt(details::e_mod , details::mod_op) \ 34767 | 34768 | expression_node_ptr result = error_node(); 34769 | std::string node_name = "Unknown" 34770 | 34771 | if (is_b0_ivec && is_b1_ivec) 34772 | { 34773 | switch (operation) 34774 | { 34775 | #define case_stmt(op0, op1) \ 34776 | case op0 : result = node_allocator_-> \ 34777 | template allocate_rrr<typename details::vec_binop_vecvec_node<Type,op1<Type> > > \ 34778 | (operation, branch[0], branch[1]); \ 34779 | node_name = "vec_binop_vecvec_node" \ 34780 | break; \ 34781 | 34782 | vector_ops 34783 | case_stmt(details::e_pow,details:: pow_op) 34784 | #undef case_stmt 34785 | default : return error_node(); 34786 | } 34787 | } 34788 | else if (is_b0_ivec && !is_b1_ivec) 34789 | { 34790 | switch (operation) 34791 | { 34792 | #define case_stmt(op0, op1) \ 34793 | case op0 : result = node_allocator_-> \ 34794 | template allocate_rrr<typename details::vec_binop_vecval_node<Type,op1<Type> > > \ 34795 | (operation, branch[0], branch[1]); \ 34796 | node_name = "vec_binop_vecval_node(b0ivec,!b1ivec)" \ 34797 | break; \ 34798 | 34799 | vector_ops 34800 | case_stmt(details::e_pow,details:: pow_op) 34801 | #undef case_stmt 34802 | default : return error_node(); 34803 | } 34804 | } 34805 | else 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_valvec_node<Type,op1<Type> > > \ 34812 | (operation, branch[0], branch[1]); \ 34813 | node_name = "vec_binop_vecval_node(!b0ivec,b1ivec)" \ 34814 | break; \ 34815 | 34816 | vector_ops 34817 | #undef case_stmt 34818 | default : return error_node(); 34819 | } 34820 | } 34821 | else 34822 | return error_node(); 34823 | 34824 | if (result && result->valid()) 34825 | { 34826 | return result; 34827 | } 34828 | 34829 | parser_->set_error(parser_error::make_error( 34830 | parser_error::e_synthesis, 34831 | token_t(), 34832 | "ERR278 - Failed to synthesize node: " + node_name, 34833 | exprtk_error_location)); 34834 | 34835 | details::free_node(*node_allocator_, result); 34836 | return error_node(); 34837 | 34838 | #undef vector_ops 34839 | } 34840 | 34841 | inline expression_node_ptr synthesize_swap_expression(expression_node_ptr (&branch)[2]) 34842 | { 34843 | const bool v0_is_ivar = details::is_ivariable_node(branch[0]); 34844 | const bool v1_is_ivar = details::is_ivariable_node(branch[1]); 34845 | 34846 | const bool v0_is_ivec = details::is_ivector_node (branch[0]); 34847 | const bool v1_is_ivec = details::is_ivector_node (branch[1]); 34848 | 34849 | #ifndef exprtk_disable_string_capabilities 34850 | const bool v0_is_str = details::is_generally_string_node(branch[0]); 34851 | const bool v1_is_str = details::is_generally_string_node(branch[1]); 34852 | #endif 34853 | 34854 | expression_node_ptr result = error_node(); 34855 | std::string node_name = "Unknown" 34856 | 34857 | if (v0_is_ivar && v1_is_ivar) 34858 | { 34859 | typedef details::variable_node<T>* variable_node_ptr; 34860 | 34861 | variable_node_ptr v0 = variable_node_ptr(0); 34862 | variable_node_ptr v1 = variable_node_ptr(0); 34863 | 34864 | if ( 34865 | (0 != (v0 = dynamic_cast<variable_node_ptr>(branch[0]))) && 34866 | (0 != (v1 = dynamic_cast<variable_node_ptr>(branch[1]))) 34867 | ) 34868 | { 34869 | result = node_allocator_->allocate<details::swap_node<T> >(v0,v1); 34870 | node_name = "swap_node" 34871 | } 34872 | else 34873 | { 34874 | result = node_allocator_->allocate<details::swap_generic_node<T> >(branch[0],branch[1]); 34875 | node_name = "swap_generic_node" 34876 | } 34877 | } 34878 | else if (v0_is_ivec && v1_is_ivec) 34879 | { 34880 | result = node_allocator_->allocate<details::swap_vecvec_node<T> >(branch[0],branch[1]); 34881 | node_name = "swap_vecvec_node" 34882 | } 34883 | #ifndef exprtk_disable_string_capabilities 34884 | else if (v0_is_str && v1_is_str) 34885 | { 34886 | if (is_string_node(branch[0]) && is_string_node(branch[1])) 34887 | { 34888 | result = node_allocator_->allocate<details::swap_string_node<T> > 34889 | (branch[0], branch[1]); 34890 | node_name = "swap_string_node" 34891 | } 34892 | else 34893 | { 34894 | result = node_allocator_->allocate<details::swap_genstrings_node<T> > 34895 | (branch[0], branch[1]); 34896 | node_name = "swap_genstrings_node" 34897 | } 34898 | } 34899 | #endif 34900 | else 34901 | { 34902 | parser_->set_synthesis_error("Only variables, strings, vectors or vector elements can be swapped"); 34903 | return error_node(); 34904 | } 34905 | 34906 | if (result && result->valid()) 34907 | { 34908 | parser_->state_.activate_side_effect("synthesize_swap_expression()"); 34909 | return result; 34910 | } 34911 | 34912 | parser_->set_error(parser_error::make_error( 34913 | parser_error::e_synthesis, 34914 | token_t(), 34915 | "ERR279 - Failed to synthesize node: " + node_name, 34916 | exprtk_error_location)); 34917 | 34918 | details::free_node(*node_allocator_, result); 34919 | return error_node(); 34920 | } 34921 | 34922 | #ifndef exprtk_disable_sc_andor 34923 | inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2]) 34924 | { 34925 | expression_node_ptr result = error_node(); 34926 | 34927 | if (details::is_constant_node(branch[0])) 34928 | { 34929 | if ( 34930 | (details::e_scand == operation) && 34931 | std::equal_to<T>()(T(0),branch[0]->value()) 34932 | ) 34933 | result = node_allocator_->allocate_c<literal_node_t>(T(0)); 34934 | else if ( 34935 | (details::e_scor == operation) && 34936 | std::not_equal_to<T>()(T(0),branch[0]->value()) 34937 | ) 34938 | result = node_allocator_->allocate_c<literal_node_t>(T(1)); 34939 | } 34940 | 34941 | if (details::is_constant_node(branch[1]) && (0 == result)) 34942 | { 34943 | if ( 34944 | (details::e_scand == operation) && 34945 | std::equal_to<T>()(T(0),branch[1]->value()) 34946 | ) 34947 | result = node_allocator_->allocate_c<literal_node_t>(T(0)); 34948 | else if ( 34949 | (details::e_scor == operation) && 34950 | std::not_equal_to<T>()(T(0),branch[1]->value()) 34951 | ) 34952 | result = node_allocator_->allocate_c<literal_node_t>(T(1)); 34953 | } 34954 | 34955 | if (result) 34956 | { 34957 | details::free_node(*node_allocator_, branch[0]); 34958 | details::free_node(*node_allocator_, branch[1]); 34959 | 34960 | return result; 34961 | } 34962 | else if (details::e_scand == operation) 34963 | { 34964 | return synthesize_expression<scand_node_t,2>(operation, branch); 34965 | } 34966 | else if (details::e_scor == operation) 34967 | { 34968 | return synthesize_expression<scor_node_t,2>(operation, branch); 34969 | } 34970 | else 34971 | return error_node(); 34972 | } 34973 | #else 34974 | inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type&, expression_node_ptr (&)[2]) 34975 | { 34976 | return error_node(); 34977 | } 34978 | #endif 34979 | 34980 | #define basic_opr_switch_statements \ 34981 | case_stmt(details::e_add , details::add_op) \ 34982 | case_stmt(details::e_sub , details::sub_op) \ 34983 | case_stmt(details::e_mul , details::mul_op) \ 34984 | case_stmt(details::e_div , details::div_op) \ 34985 | case_stmt(details::e_mod , details::mod_op) \ 34986 | case_stmt(details::e_pow , details::pow_op) \ 34987 | 34988 | #define extended_opr_switch_statements \ 34989 | case_stmt(details::e_lt , details::lt_op ) \ 34990 | case_stmt(details::e_lte , details::lte_op ) \ 34991 | case_stmt(details::e_gt , details::gt_op ) \ 34992 | case_stmt(details::e_gte , details::gte_op ) \ 34993 | case_stmt(details::e_eq , details::eq_op ) \ 34994 | case_stmt(details::e_ne , details::ne_op ) \ 34995 | case_stmt(details::e_and , details::and_op ) \ 34996 | case_stmt(details::e_nand , details::nand_op) \ 34997 | case_stmt(details::e_or , details::or_op ) \ 34998 | case_stmt(details::e_nor , details::nor_op ) \ 34999 | case_stmt(details::e_xor , details::xor_op ) \ 35000 | case_stmt(details::e_xnor , details::xnor_op) \ 35001 | 35002 | #ifndef exprtk_disable_cardinal_pow_optimisation 35003 | template <typename TType, template <typename, typename> class IPowNode> 35004 | inline expression_node_ptr cardinal_pow_optimisation_impl(const TType& v, const unsigned int& p) 35005 | { 35006 | switch (p) 35007 | { 35008 | #define case_stmt(cp) \ 35009 | case cp : return node_allocator_-> \ 35010 | allocate<IPowNode<T,details::numeric::fast_exp<T,cp> > >(v); \ 35011 | 35012 | case_stmt( 1) case_stmt( 2) case_stmt( 3) case_stmt( 4) 35013 | case_stmt( 5) case_stmt( 6) case_stmt( 7) case_stmt( 8) 35014 | case_stmt( 9) case_stmt(10) case_stmt(11) case_stmt(12) 35015 | case_stmt(13) case_stmt(14) case_stmt(15) case_stmt(16) 35016 | case_stmt(17) case_stmt(18) case_stmt(19) case_stmt(20) 35017 | case_stmt(21) case_stmt(22) case_stmt(23) case_stmt(24) 35018 | case_stmt(25) case_stmt(26) case_stmt(27) case_stmt(28) 35019 | case_stmt(29) case_stmt(30) case_stmt(31) case_stmt(32) 35020 | case_stmt(33) case_stmt(34) case_stmt(35) case_stmt(36) 35021 | case_stmt(37) case_stmt(38) case_stmt(39) case_stmt(40) 35022 | case_stmt(41) case_stmt(42) case_stmt(43) case_stmt(44) 35023 | case_stmt(45) case_stmt(46) case_stmt(47) case_stmt(48) 35024 | case_stmt(49) case_stmt(50) case_stmt(51) case_stmt(52) 35025 | case_stmt(53) case_stmt(54) case_stmt(55) case_stmt(56) 35026 | case_stmt(57) case_stmt(58) case_stmt(59) case_stmt(60) 35027 | #undef case_stmt 35028 | default : return error_node(); 35029 | } 35030 | } 35031 | 35032 | inline expression_node_ptr cardinal_pow_optimisation(const T& v, const T& c) 35033 | { 35034 | const bool not_recipricol = (c >= T(0)); 35035 | const unsigned int p = static_cast<unsigned int>(details::numeric::to_int32(details::numeric::abs(c))); 35036 | 35037 | if (0 == p) 35038 | return node_allocator_->allocate_c<literal_node_t>(T(1)); 35039 | else if (std::equal_to<T>()(T(2),c)) 35040 | { 35041 | return node_allocator_-> 35042 | template allocate_rr<typename details::vov_node<Type,details::mul_op<Type> > >(v,v); 35043 | } 35044 | else 35045 | { 35046 | if (not_recipricol) 35047 | return cardinal_pow_optimisation_impl<T,details::ipow_node>(v,p); 35048 | else 35049 | return cardinal_pow_optimisation_impl<T,details::ipowinv_node>(v,p); 35050 | } 35051 | } 35052 | 35053 | inline bool cardinal_pow_optimisable(const details::operator_type& operation, const T& c) const 35054 | { 35055 | return (details::e_pow == operation) && (details::numeric::abs(c) <= T(60)) && details::numeric::is_integer(c); 35056 | } 35057 | 35058 | inline expression_node_ptr cardinal_pow_optimisation(expression_node_ptr (&branch)[2]) 35059 | { 35060 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 35061 | const bool not_recipricol = (c >= T(0)); 35062 | const unsigned int p = static_cast<unsigned int>(details::numeric::to_int32(details::numeric::abs(c))); 35063 | 35064 | node_allocator_->free(branch[1]); 35065 | 35066 | if (0 == p) 35067 | { 35068 | details::free_all_nodes(*node_allocator_, branch); 35069 | 35070 | return node_allocator_->allocate_c<literal_node_t>(T(1)); 35071 | } 35072 | else if (not_recipricol) 35073 | return cardinal_pow_optimisation_impl<expression_node_ptr,details::bipow_node>(branch[0],p); 35074 | else 35075 | return cardinal_pow_optimisation_impl<expression_node_ptr,details::bipowinv_node>(branch[0],p); 35076 | } 35077 | #else 35078 | inline expression_node_ptr cardinal_pow_optimisation(T&, const T&) 35079 | { 35080 | return error_node(); 35081 | } 35082 | 35083 | inline bool cardinal_pow_optimisable(const details::operator_type&, const T&) 35084 | { 35085 | return false; 35086 | } 35087 | 35088 | inline expression_node_ptr cardinal_pow_optimisation(expression_node_ptr(&)[2]) 35089 | { 35090 | return error_node(); 35091 | } 35092 | #endif 35093 | 35094 | struct synthesize_binary_ext_expression 35095 | { 35096 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 35097 | const details::operator_type& operation, 35098 | expression_node_ptr (&branch)[2]) 35099 | { 35100 | const bool left_neg = is_neg_unary_node(branch[0]); 35101 | const bool right_neg = is_neg_unary_node(branch[1]); 35102 | 35103 | if (left_neg && right_neg) 35104 | { 35105 | if ( 35106 | (details::e_add == operation) || 35107 | (details::e_sub == operation) || 35108 | (details::e_mul == operation) || 35109 | (details::e_div == operation) 35110 | ) 35111 | { 35112 | if ( 35113 | !expr_gen.parser_->simplify_unary_negation_branch(branch[0]) || 35114 | !expr_gen.parser_->simplify_unary_negation_branch(branch[1]) 35115 | ) 35116 | { 35117 | details::free_all_nodes(*expr_gen.node_allocator_,branch); 35118 | 35119 | return error_node(); 35120 | } 35121 | } 35122 | 35123 | switch (operation) 35124 | { 35125 | // -f(x + 1) + -g(y + 1) --> -(f(x + 1) + g(y + 1)) 35126 | case details::e_add : return expr_gen(details::e_neg, 35127 | expr_gen.node_allocator_-> 35128 | template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > > 35129 | (branch[0],branch[1])); 35130 | 35131 | // -f(x + 1) - -g(y + 1) --> g(y + 1) - f(x + 1) 35132 | case details::e_sub : return expr_gen.node_allocator_-> 35133 | template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > > 35134 | (branch[1],branch[0]); 35135 | 35136 | default : break; 35137 | } 35138 | } 35139 | else if (left_neg && !right_neg) 35140 | { 35141 | if ( 35142 | (details::e_add == operation) || 35143 | (details::e_sub == operation) || 35144 | (details::e_mul == operation) || 35145 | (details::e_div == operation) 35146 | ) 35147 | { 35148 | if (!expr_gen.parser_->simplify_unary_negation_branch(branch[0])) 35149 | { 35150 | details::free_all_nodes(*expr_gen.node_allocator_,branch); 35151 | 35152 | return error_node(); 35153 | } 35154 | 35155 | switch (operation) 35156 | { 35157 | // -f(x + 1) + g(y + 1) --> g(y + 1) - f(x + 1) 35158 | case details::e_add : return expr_gen.node_allocator_-> 35159 | template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > > 35160 | (branch[1], branch[0]); 35161 | 35162 | // -f(x + 1) - g(y + 1) --> -(f(x + 1) + g(y + 1)) 35163 | case details::e_sub : return expr_gen(details::e_neg, 35164 | expr_gen.node_allocator_-> 35165 | template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > > 35166 | (branch[0], branch[1])); 35167 | 35168 | // -f(x + 1) * g(y + 1) --> -(f(x + 1) * g(y + 1)) 35169 | case details::e_mul : return expr_gen(details::e_neg, 35170 | expr_gen.node_allocator_-> 35171 | template allocate<typename details::binary_ext_node<Type,details::mul_op<Type> > > 35172 | (branch[0], branch[1])); 35173 | 35174 | // -f(x + 1) / g(y + 1) --> -(f(x + 1) / g(y + 1)) 35175 | case details::e_div : return expr_gen(details::e_neg, 35176 | expr_gen.node_allocator_-> 35177 | template allocate<typename details::binary_ext_node<Type,details::div_op<Type> > > 35178 | (branch[0], branch[1])); 35179 | 35180 | default : return error_node(); 35181 | } 35182 | } 35183 | } 35184 | else if (!left_neg && right_neg) 35185 | { 35186 | if ( 35187 | (details::e_add == operation) || 35188 | (details::e_sub == operation) || 35189 | (details::e_mul == operation) || 35190 | (details::e_div == operation) 35191 | ) 35192 | { 35193 | if (!expr_gen.parser_->simplify_unary_negation_branch(branch[1])) 35194 | { 35195 | details::free_all_nodes(*expr_gen.node_allocator_,branch); 35196 | 35197 | return error_node(); 35198 | } 35199 | 35200 | switch (operation) 35201 | { 35202 | // f(x + 1) + -g(y + 1) --> f(x + 1) - g(y + 1) 35203 | case details::e_add : return expr_gen.node_allocator_-> 35204 | template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > > 35205 | (branch[0], branch[1]); 35206 | 35207 | // f(x + 1) - - g(y + 1) --> f(x + 1) + g(y + 1) 35208 | case details::e_sub : return expr_gen.node_allocator_-> 35209 | template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > > 35210 | (branch[0], branch[1]); 35211 | 35212 | // f(x + 1) * -g(y + 1) --> -(f(x + 1) * g(y + 1)) 35213 | case details::e_mul : return expr_gen(details::e_neg, 35214 | expr_gen.node_allocator_-> 35215 | template allocate<typename details::binary_ext_node<Type,details::mul_op<Type> > > 35216 | (branch[0], branch[1])); 35217 | 35218 | // f(x + 1) / -g(y + 1) --> -(f(x + 1) / g(y + 1)) 35219 | case details::e_div : return expr_gen(details::e_neg, 35220 | expr_gen.node_allocator_-> 35221 | template allocate<typename details::binary_ext_node<Type,details::div_op<Type> > > 35222 | (branch[0], branch[1])); 35223 | 35224 | default : return error_node(); 35225 | } 35226 | } 35227 | } 35228 | 35229 | switch (operation) 35230 | { 35231 | #define case_stmt(op0, op1) \ 35232 | case op0 : return expr_gen.node_allocator_-> \ 35233 | template allocate<typename details::binary_ext_node<Type,op1<Type> > > \ 35234 | (branch[0], branch[1]); \ 35235 | 35236 | basic_opr_switch_statements 35237 | extended_opr_switch_statements 35238 | #undef case_stmt 35239 | default : return error_node(); 35240 | } 35241 | } 35242 | }; 35243 | 35244 | struct synthesize_vob_expression 35245 | { 35246 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 35247 | const details::operator_type& operation, 35248 | expression_node_ptr (&branch)[2]) 35249 | { 35250 | const Type& v = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 35251 | 35252 | #ifndef exprtk_disable_enhanced_features 35253 | if (details::is_sf3ext_node(branch[1])) 35254 | { 35255 | expression_node_ptr result = error_node(); 35256 | 35257 | const bool synthesis_result = 35258 | synthesize_sf4ext_expression::template compile_right<vtype> 35259 | (expr_gen, v, operation, branch[1], result); 35260 | 35261 | if (synthesis_result) 35262 | { 35263 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35264 | return result; 35265 | } 35266 | } 35267 | #endif 35268 | 35269 | if ( 35270 | (details::e_mul == operation) || 35271 | (details::e_div == operation) 35272 | ) 35273 | { 35274 | if (details::is_uv_node(branch[1])) 35275 | { 35276 | typedef details::uv_base_node<Type>* uvbn_ptr_t; 35277 | 35278 | details::operator_type o = static_cast<uvbn_ptr_t>(branch[1])->operation(); 35279 | 35280 | if (details::e_neg == o) 35281 | { 35282 | const Type& v1 = static_cast<uvbn_ptr_t>(branch[1])->v(); 35283 | 35284 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35285 | 35286 | switch (operation) 35287 | { 35288 | case details::e_mul : return expr_gen(details::e_neg, 35289 | expr_gen.node_allocator_-> 35290 | template allocate_rr<typename details:: 35291 | vov_node<Type,details::mul_op<Type> > >(v,v1)); 35292 | 35293 | case details::e_div : return expr_gen(details::e_neg, 35294 | expr_gen.node_allocator_-> 35295 | template allocate_rr<typename details:: 35296 | vov_node<Type,details::div_op<Type> > >(v,v1)); 35297 | 35298 | default : break; 35299 | } 35300 | } 35301 | } 35302 | } 35303 | 35304 | switch (operation) 35305 | { 35306 | #define case_stmt(op0, op1) \ 35307 | case op0 : return expr_gen.node_allocator_-> \ 35308 | template allocate_rc<typename details::vob_node<Type,op1<Type> > > \ 35309 | (v, branch[1]); \ 35310 | 35311 | basic_opr_switch_statements 35312 | extended_opr_switch_statements 35313 | #undef case_stmt 35314 | default : return error_node(); 35315 | } 35316 | } 35317 | }; 35318 | 35319 | struct synthesize_bov_expression 35320 | { 35321 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 35322 | const details::operator_type& operation, 35323 | expression_node_ptr (&branch)[2]) 35324 | { 35325 | const Type& v = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 35326 | 35327 | #ifndef exprtk_disable_enhanced_features 35328 | if (details::is_sf3ext_node(branch[0])) 35329 | { 35330 | expression_node_ptr result = error_node(); 35331 | 35332 | const bool synthesis_result = 35333 | synthesize_sf4ext_expression::template compile_left<vtype> 35334 | (expr_gen, v, operation, branch[0], result); 35335 | 35336 | if (synthesis_result) 35337 | { 35338 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35339 | 35340 | return result; 35341 | } 35342 | } 35343 | #endif 35344 | 35345 | if ( 35346 | (details::e_add == operation) || 35347 | (details::e_sub == operation) || 35348 | (details::e_mul == operation) || 35349 | (details::e_div == operation) 35350 | ) 35351 | { 35352 | if (details::is_uv_node(branch[0])) 35353 | { 35354 | typedef details::uv_base_node<Type>* uvbn_ptr_t; 35355 | 35356 | details::operator_type o = static_cast<uvbn_ptr_t>(branch[0])->operation(); 35357 | 35358 | if (details::e_neg == o) 35359 | { 35360 | const Type& v0 = static_cast<uvbn_ptr_t>(branch[0])->v(); 35361 | 35362 | details::free_node(*expr_gen.node_allocator_,branch[0]); 35363 | 35364 | switch (operation) 35365 | { 35366 | case details::e_add : return expr_gen.node_allocator_-> 35367 | template allocate_rr<typename details:: 35368 | vov_node<Type,details::sub_op<Type> > >(v,v0); 35369 | 35370 | case details::e_sub : return expr_gen(details::e_neg, 35371 | expr_gen.node_allocator_-> 35372 | template allocate_rr<typename details:: 35373 | vov_node<Type,details::add_op<Type> > >(v0,v)); 35374 | 35375 | case details::e_mul : return expr_gen(details::e_neg, 35376 | expr_gen.node_allocator_-> 35377 | template allocate_rr<typename details:: 35378 | vov_node<Type,details::mul_op<Type> > >(v0,v)); 35379 | 35380 | case details::e_div : return expr_gen(details::e_neg, 35381 | expr_gen.node_allocator_-> 35382 | template allocate_rr<typename details:: 35383 | vov_node<Type,details::div_op<Type> > >(v0,v)); 35384 | default : break; 35385 | } 35386 | } 35387 | } 35388 | } 35389 | 35390 | switch (operation) 35391 | { 35392 | #define case_stmt(op0, op1) \ 35393 | case op0 : return expr_gen.node_allocator_-> \ 35394 | template allocate_cr<typename details::bov_node<Type,op1<Type> > > \ 35395 | (branch[0], v); \ 35396 | 35397 | basic_opr_switch_statements 35398 | extended_opr_switch_statements 35399 | #undef case_stmt 35400 | default : return error_node(); 35401 | } 35402 | } 35403 | }; 35404 | 35405 | struct synthesize_cob_expression 35406 | { 35407 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 35408 | const details::operator_type& operation, 35409 | expression_node_ptr (&branch)[2]) 35410 | { 35411 | const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); 35412 | 35413 | details::free_node(*expr_gen.node_allocator_,branch[0]); 35414 | 35415 | if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation)) 35416 | { 35417 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35418 | 35419 | return expr_gen(T(0)); 35420 | } 35421 | else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation)) 35422 | { 35423 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35424 | 35425 | return expr_gen(T(0)); 35426 | } 35427 | else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation)) 35428 | return branch[1]; 35429 | else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation)) 35430 | return branch[1]; 35431 | 35432 | if (details::is_cob_node(branch[1])) 35433 | { 35434 | // Simplify expressions of the form: 35435 | // 1. (1 * (2 * (3 * (4 * (5 * (6 * (7 * (8 * (9 + x))))))))) --> 40320 * (9 + x) 35436 | // 2. (1 + (2 + (3 + (4 + (5 + (6 + (7 + (8 + (9 + x))))))))) --> 45 + x 35437 | if ( 35438 | (details::e_mul == operation) || 35439 | (details::e_add == operation) 35440 | ) 35441 | { 35442 | details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]); 35443 | 35444 | if (operation == cobnode->operation()) 35445 | { 35446 | switch (operation) 35447 | { 35448 | case details::e_add : cobnode->set_c(c + cobnode->c()); break; 35449 | case details::e_mul : cobnode->set_c(c * cobnode->c()); break; 35450 | default : return error_node(); 35451 | } 35452 | 35453 | return cobnode; 35454 | } 35455 | } 35456 | 35457 | if (operation == details::e_mul) 35458 | { 35459 | details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]); 35460 | details::operator_type cob_opr = cobnode->operation(); 35461 | 35462 | if ( 35463 | (details::e_div == cob_opr) || 35464 | (details::e_mul == cob_opr) 35465 | ) 35466 | { 35467 | switch (cob_opr) 35468 | { 35469 | case details::e_div : cobnode->set_c(c * cobnode->c()); break; 35470 | case details::e_mul : cobnode->set_c(cobnode->c() / c); break; 35471 | default : return error_node(); 35472 | } 35473 | 35474 | return cobnode; 35475 | } 35476 | } 35477 | else if (operation == details::e_div) 35478 | { 35479 | details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]); 35480 | details::operator_type cob_opr = cobnode->operation(); 35481 | 35482 | if ( 35483 | (details::e_div == cob_opr) || 35484 | (details::e_mul == cob_opr) 35485 | ) 35486 | { 35487 | details::expression_node<Type>* new_cobnode = error_node(); 35488 | 35489 | switch (cob_opr) 35490 | { 35491 | case details::e_div : new_cobnode = expr_gen.node_allocator_-> 35492 | template allocate_tt<typename details::cob_node<Type,details::mul_op<Type> > > 35493 | (c / cobnode->c(), cobnode->move_branch(0)); 35494 | break; 35495 | 35496 | case details::e_mul : new_cobnode = expr_gen.node_allocator_-> 35497 | template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > > 35498 | (c / cobnode->c(), cobnode->move_branch(0)); 35499 | break; 35500 | 35501 | default : return error_node(); 35502 | } 35503 | 35504 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35505 | 35506 | return new_cobnode; 35507 | } 35508 | } 35509 | } 35510 | #ifndef exprtk_disable_enhanced_features 35511 | else if (details::is_sf3ext_node(branch[1])) 35512 | { 35513 | expression_node_ptr result = error_node(); 35514 | 35515 | const bool synthesis_result = 35516 | synthesize_sf4ext_expression::template compile_right<ctype> 35517 | (expr_gen, c, operation, branch[1], result); 35518 | 35519 | if (synthesis_result) 35520 | { 35521 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35522 | 35523 | return result; 35524 | } 35525 | } 35526 | #endif 35527 | 35528 | switch (operation) 35529 | { 35530 | #define case_stmt(op0, op1) \ 35531 | case op0 : return expr_gen.node_allocator_-> \ 35532 | template allocate_tt<typename details::cob_node<Type,op1<Type> > > \ 35533 | (c, branch[1]); \ 35534 | 35535 | basic_opr_switch_statements 35536 | extended_opr_switch_statements 35537 | #undef case_stmt 35538 | default : return error_node(); 35539 | } 35540 | } 35541 | }; 35542 | 35543 | struct synthesize_boc_expression 35544 | { 35545 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 35546 | const details::operator_type& operation, 35547 | expression_node_ptr (&branch)[2]) 35548 | { 35549 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 35550 | 35551 | details::free_node(*(expr_gen.node_allocator_), branch[1]); 35552 | 35553 | if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation)) 35554 | { 35555 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35556 | 35557 | return expr_gen(T(0)); 35558 | } 35559 | else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation)) 35560 | { 35561 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35562 | 35563 | return expr_gen(std::numeric_limits<T>::quiet_NaN()); 35564 | } 35565 | else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation)) 35566 | return branch[0]; 35567 | else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation)) 35568 | return branch[0]; 35569 | 35570 | if (details::is_boc_node(branch[0])) 35571 | { 35572 | // Simplify expressions of the form: 35573 | // 1. (((((((((x + 9) * 8) * 7) * 6) * 5) * 4) * 3) * 2) * 1) --> (x + 9) * 40320 35574 | // 2. (((((((((x + 9) + 8) + 7) + 6) + 5) + 4) + 3) + 2) + 1) --> x + 45 35575 | if ( 35576 | (details::e_mul == operation) || 35577 | (details::e_add == operation) 35578 | ) 35579 | { 35580 | details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]); 35581 | 35582 | if (operation == bocnode->operation()) 35583 | { 35584 | switch (operation) 35585 | { 35586 | case details::e_add : bocnode->set_c(c + bocnode->c()); break; 35587 | case details::e_mul : bocnode->set_c(c * bocnode->c()); break; 35588 | default : return error_node(); 35589 | } 35590 | 35591 | return bocnode; 35592 | } 35593 | } 35594 | else if (operation == details::e_div) 35595 | { 35596 | details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]); 35597 | details::operator_type boc_opr = bocnode->operation(); 35598 | 35599 | if ( 35600 | (details::e_div == boc_opr) || 35601 | (details::e_mul == boc_opr) 35602 | ) 35603 | { 35604 | switch (boc_opr) 35605 | { 35606 | case details::e_div : bocnode->set_c(c * bocnode->c()); break; 35607 | case details::e_mul : bocnode->set_c(bocnode->c() / c); break; 35608 | default : return error_node(); 35609 | } 35610 | 35611 | return bocnode; 35612 | } 35613 | } 35614 | else if (operation == details::e_pow) 35615 | { 35616 | // (v ^ c0) ^ c1 --> v ^(c0 * c1) 35617 | details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]); 35618 | details::operator_type boc_opr = bocnode->operation(); 35619 | 35620 | if (details::e_pow == boc_opr) 35621 | { 35622 | bocnode->set_c(bocnode->c() * c); 35623 | 35624 | return bocnode; 35625 | } 35626 | } 35627 | } 35628 | 35629 | #ifndef exprtk_disable_enhanced_features 35630 | if (details::is_sf3ext_node(branch[0])) 35631 | { 35632 | expression_node_ptr result = error_node(); 35633 | 35634 | const bool synthesis_result = 35635 | synthesize_sf4ext_expression::template compile_left<ctype> 35636 | (expr_gen, c, operation, branch[0], result); 35637 | 35638 | if (synthesis_result) 35639 | { 35640 | free_node(*expr_gen.node_allocator_, branch[0]); 35641 | 35642 | return result; 35643 | } 35644 | } 35645 | #endif 35646 | 35647 | switch (operation) 35648 | { 35649 | #define case_stmt(op0, op1) \ 35650 | case op0 : return expr_gen.node_allocator_-> \ 35651 | template allocate_cr<typename details::boc_node<Type,op1<Type> > > \ 35652 | (branch[0], c); \ 35653 | 35654 | basic_opr_switch_statements 35655 | extended_opr_switch_statements 35656 | #undef case_stmt 35657 | default : return error_node(); 35658 | } 35659 | } 35660 | }; 35661 | 35662 | struct synthesize_cocob_expression 35663 | { 35664 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 35665 | const details::operator_type& operation, 35666 | expression_node_ptr (&branch)[2]) 35667 | { 35668 | expression_node_ptr result = error_node(); 35669 | 35670 | // (cob) o c --> cob 35671 | if (details::is_cob_node(branch[0])) 35672 | { 35673 | details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[0]); 35674 | 35675 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 35676 | 35677 | if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation)) 35678 | { 35679 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35680 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35681 | 35682 | return expr_gen(T(0)); 35683 | } 35684 | else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation)) 35685 | { 35686 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35687 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35688 | 35689 | return expr_gen(T(std::numeric_limits<T>::quiet_NaN())); 35690 | } 35691 | else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation)) 35692 | { 35693 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35694 | 35695 | return branch[0]; 35696 | } 35697 | else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation)) 35698 | { 35699 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35700 | 35701 | return branch[0]; 35702 | } 35703 | else if (std::equal_to<T>()(T(1),c) && (details::e_div == operation)) 35704 | { 35705 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35706 | 35707 | return branch[0]; 35708 | } 35709 | 35710 | const bool op_addsub = (details::e_add == cobnode->operation()) || 35711 | (details::e_sub == cobnode->operation()) ; 35712 | 35713 | if (op_addsub) 35714 | { 35715 | switch (operation) 35716 | { 35717 | case details::e_add : cobnode->set_c(cobnode->c() + c); break; 35718 | case details::e_sub : cobnode->set_c(cobnode->c() - c); break; 35719 | default : return error_node(); 35720 | } 35721 | 35722 | result = cobnode; 35723 | } 35724 | else if (details::e_mul == cobnode->operation()) 35725 | { 35726 | switch (operation) 35727 | { 35728 | case details::e_mul : cobnode->set_c(cobnode->c() * c); break; 35729 | case details::e_div : cobnode->set_c(cobnode->c() / c); break; 35730 | default : return error_node(); 35731 | } 35732 | 35733 | result = cobnode; 35734 | } 35735 | else if (details::e_div == cobnode->operation()) 35736 | { 35737 | if (details::e_mul == operation) 35738 | { 35739 | cobnode->set_c(cobnode->c() * c); 35740 | result = cobnode; 35741 | } 35742 | else if (details::e_div == operation) 35743 | { 35744 | result = expr_gen.node_allocator_-> 35745 | template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > > 35746 | (cobnode->c() / c, cobnode->move_branch(0)); 35747 | 35748 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35749 | } 35750 | } 35751 | 35752 | if (result) 35753 | { 35754 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35755 | } 35756 | } 35757 | 35758 | // c o (cob) --> cob 35759 | else if (details::is_cob_node(branch[1])) 35760 | { 35761 | details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]); 35762 | 35763 | const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); 35764 | 35765 | if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation)) 35766 | { 35767 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35768 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35769 | 35770 | return expr_gen(T(0)); 35771 | } 35772 | else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation)) 35773 | { 35774 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35775 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35776 | 35777 | return expr_gen(T(0)); 35778 | } 35779 | else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation)) 35780 | { 35781 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35782 | 35783 | return branch[1]; 35784 | } 35785 | else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation)) 35786 | { 35787 | details::free_node(*expr_gen.node_allocator_, branch[0]); 35788 | 35789 | return branch[1]; 35790 | } 35791 | 35792 | if (details::e_add == cobnode->operation()) 35793 | { 35794 | if (details::e_add == operation) 35795 | { 35796 | cobnode->set_c(c + cobnode->c()); 35797 | result = cobnode; 35798 | } 35799 | else if (details::e_sub == operation) 35800 | { 35801 | result = expr_gen.node_allocator_-> 35802 | template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > > 35803 | (c - cobnode->c(), cobnode->move_branch(0)); 35804 | 35805 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35806 | } 35807 | } 35808 | else if (details::e_sub == cobnode->operation()) 35809 | { 35810 | if (details::e_add == operation) 35811 | { 35812 | cobnode->set_c(c + cobnode->c()); 35813 | result = cobnode; 35814 | } 35815 | else if (details::e_sub == operation) 35816 | { 35817 | result = expr_gen.node_allocator_-> 35818 | template allocate_tt<typename details::cob_node<Type,details::add_op<Type> > > 35819 | (c - cobnode->c(), cobnode->move_branch(0)); 35820 | 35821 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35822 | } 35823 | } 35824 | else if (details::e_mul == cobnode->operation()) 35825 | { 35826 | if (details::e_mul == operation) 35827 | { 35828 | cobnode->set_c(c * cobnode->c()); 35829 | result = cobnode; 35830 | } 35831 | else if (details::e_div == operation) 35832 | { 35833 | result = expr_gen.node_allocator_-> 35834 | template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > > 35835 | (c / cobnode->c(), cobnode->move_branch(0)); 35836 | 35837 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35838 | } 35839 | } 35840 | else if (details::e_div == cobnode->operation()) 35841 | { 35842 | if (details::e_mul == operation) 35843 | { 35844 | cobnode->set_c(c * cobnode->c()); 35845 | result = cobnode; 35846 | } 35847 | else if (details::e_div == operation) 35848 | { 35849 | result = expr_gen.node_allocator_-> 35850 | template allocate_tt<typename details::cob_node<Type,details::mul_op<Type> > > 35851 | (c / cobnode->c(), cobnode->move_branch(0)); 35852 | 35853 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35854 | } 35855 | } 35856 | 35857 | if (result) 35858 | { 35859 | details::free_node(*expr_gen.node_allocator_,branch[0]); 35860 | } 35861 | } 35862 | 35863 | return result; 35864 | } 35865 | }; 35866 | 35867 | struct synthesize_coboc_expression 35868 | { 35869 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 35870 | const details::operator_type& operation, 35871 | expression_node_ptr (&branch)[2]) 35872 | { 35873 | expression_node_ptr result = error_node(); 35874 | 35875 | // (boc) o c --> boc 35876 | if (details::is_boc_node(branch[0])) 35877 | { 35878 | details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]); 35879 | 35880 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 35881 | 35882 | if (details::e_add == bocnode->operation()) 35883 | { 35884 | switch (operation) 35885 | { 35886 | case details::e_add : bocnode->set_c(bocnode->c() + c); break; 35887 | case details::e_sub : bocnode->set_c(bocnode->c() - c); break; 35888 | default : return error_node(); 35889 | } 35890 | 35891 | result = bocnode; 35892 | } 35893 | else if (details::e_mul == bocnode->operation()) 35894 | { 35895 | switch (operation) 35896 | { 35897 | case details::e_mul : bocnode->set_c(bocnode->c() * c); break; 35898 | case details::e_div : bocnode->set_c(bocnode->c() / c); break; 35899 | default : return error_node(); 35900 | } 35901 | 35902 | result = bocnode; 35903 | } 35904 | else if (details::e_sub == bocnode->operation()) 35905 | { 35906 | if (details::e_add == operation) 35907 | { 35908 | result = expr_gen.node_allocator_-> 35909 | template allocate_tt<typename details::boc_node<Type,details::add_op<Type> > > 35910 | (bocnode->move_branch(0), c - bocnode->c()); 35911 | 35912 | details::free_node(*expr_gen.node_allocator_,branch[0]); 35913 | } 35914 | else if (details::e_sub == operation) 35915 | { 35916 | bocnode->set_c(bocnode->c() + c); 35917 | result = bocnode; 35918 | } 35919 | } 35920 | else if (details::e_div == bocnode->operation()) 35921 | { 35922 | switch (operation) 35923 | { 35924 | case details::e_div : bocnode->set_c(bocnode->c() * c); break; 35925 | case details::e_mul : bocnode->set_c(bocnode->c() / c); break; 35926 | default : return error_node(); 35927 | } 35928 | 35929 | result = bocnode; 35930 | } 35931 | 35932 | if (result) 35933 | { 35934 | details::free_node(*expr_gen.node_allocator_, branch[1]); 35935 | } 35936 | } 35937 | 35938 | // c o (boc) --> boc 35939 | else if (details::is_boc_node(branch[1])) 35940 | { 35941 | details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[1]); 35942 | 35943 | const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); 35944 | 35945 | if (details::e_add == bocnode->operation()) 35946 | { 35947 | if (details::e_add == operation) 35948 | { 35949 | bocnode->set_c(c + bocnode->c()); 35950 | result = bocnode; 35951 | } 35952 | else if (details::e_sub == operation) 35953 | { 35954 | result = expr_gen.node_allocator_-> 35955 | template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > > 35956 | (c - bocnode->c(), bocnode->move_branch(0)); 35957 | 35958 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35959 | } 35960 | } 35961 | else if (details::e_sub == bocnode->operation()) 35962 | { 35963 | if (details::e_add == operation) 35964 | { 35965 | result = expr_gen.node_allocator_-> 35966 | template allocate_tt<typename details::boc_node<Type,details::add_op<Type> > > 35967 | (bocnode->move_branch(0), c - bocnode->c()); 35968 | 35969 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35970 | } 35971 | else if (details::e_sub == operation) 35972 | { 35973 | result = expr_gen.node_allocator_-> 35974 | template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > > 35975 | (c + bocnode->c(), bocnode->move_branch(0)); 35976 | 35977 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35978 | } 35979 | } 35980 | else if (details::e_mul == bocnode->operation()) 35981 | { 35982 | if (details::e_mul == operation) 35983 | { 35984 | bocnode->set_c(c * bocnode->c()); 35985 | result = bocnode; 35986 | } 35987 | else if (details::e_div == operation) 35988 | { 35989 | result = expr_gen.node_allocator_-> 35990 | template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > > 35991 | (c / bocnode->c(), bocnode->move_branch(0)); 35992 | 35993 | details::free_node(*expr_gen.node_allocator_,branch[1]); 35994 | } 35995 | } 35996 | else if (details::e_div == bocnode->operation()) 35997 | { 35998 | if (details::e_mul == operation) 35999 | { 36000 | bocnode->set_c(bocnode->c() / c); 36001 | result = bocnode; 36002 | } 36003 | else if (details::e_div == operation) 36004 | { 36005 | result = expr_gen.node_allocator_-> 36006 | template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > > 36007 | (c * bocnode->c(), bocnode->move_branch(0)); 36008 | 36009 | details::free_node(*expr_gen.node_allocator_,branch[1]); 36010 | } 36011 | } 36012 | 36013 | if (result) 36014 | { 36015 | details::free_node(*expr_gen.node_allocator_,branch[0]); 36016 | } 36017 | } 36018 | 36019 | return result; 36020 | } 36021 | }; 36022 | 36023 | #ifndef exprtk_disable_enhanced_features 36024 | inline bool synthesize_expression(const details::operator_type& operation, 36025 | expression_node_ptr (&branch)[2], 36026 | expression_node_ptr& result) 36027 | { 36028 | result = error_node(); 36029 | 36030 | if (!operation_optimisable(operation)) 36031 | return false; 36032 | 36033 | const std::string node_id = branch_to_id(branch); 36034 | 36035 | const typename synthesize_map_t::iterator itr = synthesize_map_.find(node_id); 36036 | 36037 | if (synthesize_map_.end() != itr) 36038 | { 36039 | result = itr->second((*this), operation, branch); 36040 | 36041 | return true; 36042 | } 36043 | else 36044 | return false; 36045 | } 36046 | 36047 | struct synthesize_vov_expression 36048 | { 36049 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36050 | const details::operator_type& operation, 36051 | expression_node_ptr (&branch)[2]) 36052 | { 36053 | const Type& v1 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 36054 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 36055 | 36056 | switch (operation) 36057 | { 36058 | #define case_stmt(op0, op1) \ 36059 | case op0 : return expr_gen.node_allocator_-> \ 36060 | template allocate_rr<typename details::vov_node<Type,op1<Type> > > \ 36061 | (v1, v2); \ 36062 | 36063 | basic_opr_switch_statements 36064 | extended_opr_switch_statements 36065 | #undef case_stmt 36066 | default : return error_node(); 36067 | } 36068 | } 36069 | }; 36070 | 36071 | struct synthesize_cov_expression 36072 | { 36073 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36074 | const details::operator_type& operation, 36075 | expression_node_ptr (&branch)[2]) 36076 | { 36077 | const Type c = static_cast<details::literal_node<Type>*> (branch[0])->value(); 36078 | const Type& v = static_cast<details::variable_node<Type>*>(branch[1])->ref (); 36079 | 36080 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 36081 | 36082 | if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation)) 36083 | return expr_gen(T(0)); 36084 | else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation)) 36085 | return expr_gen(T(0)); 36086 | else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation)) 36087 | return static_cast<details::variable_node<Type>*>(branch[1]); 36088 | else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation)) 36089 | return static_cast<details::variable_node<Type>*>(branch[1]); 36090 | 36091 | switch (operation) 36092 | { 36093 | #define case_stmt(op0, op1) \ 36094 | case op0 : return expr_gen.node_allocator_-> \ 36095 | template allocate_cr<typename details::cov_node<Type,op1<Type> > > \ 36096 | (c, v); \ 36097 | 36098 | basic_opr_switch_statements 36099 | extended_opr_switch_statements 36100 | #undef case_stmt 36101 | default : return error_node(); 36102 | } 36103 | } 36104 | }; 36105 | 36106 | struct synthesize_voc_expression 36107 | { 36108 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36109 | const details::operator_type& operation, 36110 | expression_node_ptr (&branch)[2]) 36111 | { 36112 | const Type& v = static_cast<details::variable_node<Type>*>(branch[0])->ref (); 36113 | const Type c = static_cast<details::literal_node<Type>*> (branch[1])->value(); 36114 | 36115 | details::free_node(*(expr_gen.node_allocator_), branch[1]); 36116 | 36117 | if (expr_gen.cardinal_pow_optimisable(operation,c)) 36118 | { 36119 | if (std::equal_to<T>()(T(1),c)) 36120 | return branch[0]; 36121 | else 36122 | return expr_gen.cardinal_pow_optimisation(v,c); 36123 | } 36124 | else if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation)) 36125 | return expr_gen(T(0)); 36126 | else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation)) 36127 | return expr_gen(std::numeric_limits<T>::quiet_NaN()); 36128 | else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation)) 36129 | return static_cast<details::variable_node<Type>*>(branch[0]); 36130 | else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation)) 36131 | return static_cast<details::variable_node<Type>*>(branch[0]); 36132 | else if (std::equal_to<T>()(T(1),c) && (details::e_div == operation)) 36133 | return static_cast<details::variable_node<Type>*>(branch[0]); 36134 | 36135 | switch (operation) 36136 | { 36137 | #define case_stmt(op0, op1) \ 36138 | case op0 : return expr_gen.node_allocator_-> \ 36139 | template allocate_rc<typename details::voc_node<Type,op1<Type> > > \ 36140 | (v, c); \ 36141 | 36142 | basic_opr_switch_statements 36143 | extended_opr_switch_statements 36144 | #undef case_stmt 36145 | default : return error_node(); 36146 | } 36147 | } 36148 | }; 36149 | 36150 | struct synthesize_sf3ext_expression 36151 | { 36152 | template <typename T0, typename T1, typename T2> 36153 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36154 | const details::operator_type& sf3opr, 36155 | T0 t0, T1 t1, T2 t2) 36156 | { 36157 | switch (sf3opr) 36158 | { 36159 | #define case_stmt(op) \ 36160 | case details::e_sf##op : return details::T0oT1oT2_sf3ext<T,T0,T1,T2,details::sf##op##_op<Type> >:: \ 36161 | allocate(*(expr_gen.node_allocator_), t0, t1, t2); \ 36162 | 36163 | case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03) 36164 | case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07) 36165 | case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11) 36166 | case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15) 36167 | case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19) 36168 | case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23) 36169 | case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27) 36170 | case_stmt(28) case_stmt(29) case_stmt(30) 36171 | #undef case_stmt 36172 | default : return error_node(); 36173 | } 36174 | } 36175 | 36176 | template <typename T0, typename T1, typename T2> 36177 | static inline bool compile(expression_generator<Type>& expr_gen, const std::string& id, 36178 | T0 t0, T1 t1, T2 t2, 36179 | expression_node_ptr& result) 36180 | { 36181 | details::operator_type sf3opr; 36182 | 36183 | if (!expr_gen.sf3_optimisable(id,sf3opr)) 36184 | return false; 36185 | else 36186 | result = synthesize_sf3ext_expression::template process<T0, T1, T2> 36187 | (expr_gen, sf3opr, t0, t1, t2); 36188 | 36189 | return true; 36190 | } 36191 | }; 36192 | 36193 | struct synthesize_sf4ext_expression 36194 | { 36195 | template <typename T0, typename T1, typename T2, typename T3> 36196 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36197 | const details::operator_type& sf4opr, 36198 | T0 t0, T1 t1, T2 t2, T3 t3) 36199 | { 36200 | switch (sf4opr) 36201 | { 36202 | #define case_stmt0(op) \ 36203 | case details::e_sf##op : return details::T0oT1oT2oT3_sf4ext<Type,T0,T1,T2,T3,details::sf##op##_op<Type> >:: \ 36204 | allocate(*(expr_gen.node_allocator_), t0, t1, t2, t3); \ 36205 | 36206 | #define case_stmt1(op) \ 36207 | case details::e_sf4ext##op : return details::T0oT1oT2oT3_sf4ext<Type,T0,T1,T2,T3,details::sfext##op##_op<Type> >:: \ 36208 | allocate(*(expr_gen.node_allocator_), t0, t1, t2, t3); \ 36209 | 36210 | case_stmt0(48) case_stmt0(49) case_stmt0(50) case_stmt0(51) 36211 | case_stmt0(52) case_stmt0(53) case_stmt0(54) case_stmt0(55) 36212 | case_stmt0(56) case_stmt0(57) case_stmt0(58) case_stmt0(59) 36213 | case_stmt0(60) case_stmt0(61) case_stmt0(62) case_stmt0(63) 36214 | case_stmt0(64) case_stmt0(65) case_stmt0(66) case_stmt0(67) 36215 | case_stmt0(68) case_stmt0(69) case_stmt0(70) case_stmt0(71) 36216 | case_stmt0(72) case_stmt0(73) case_stmt0(74) case_stmt0(75) 36217 | case_stmt0(76) case_stmt0(77) case_stmt0(78) case_stmt0(79) 36218 | case_stmt0(80) case_stmt0(81) case_stmt0(82) case_stmt0(83) 36219 | 36220 | case_stmt1(00) case_stmt1(01) case_stmt1(02) case_stmt1(03) 36221 | case_stmt1(04) case_stmt1(05) case_stmt1(06) case_stmt1(07) 36222 | case_stmt1(08) case_stmt1(09) case_stmt1(10) case_stmt1(11) 36223 | case_stmt1(12) case_stmt1(13) case_stmt1(14) case_stmt1(15) 36224 | case_stmt1(16) case_stmt1(17) case_stmt1(18) case_stmt1(19) 36225 | case_stmt1(20) case_stmt1(21) case_stmt1(22) case_stmt1(23) 36226 | case_stmt1(24) case_stmt1(25) case_stmt1(26) case_stmt1(27) 36227 | case_stmt1(28) case_stmt1(29) case_stmt1(30) case_stmt1(31) 36228 | case_stmt1(32) case_stmt1(33) case_stmt1(34) case_stmt1(35) 36229 | case_stmt1(36) case_stmt1(37) case_stmt1(38) case_stmt1(39) 36230 | case_stmt1(40) case_stmt1(41) case_stmt1(42) case_stmt1(43) 36231 | case_stmt1(44) case_stmt1(45) case_stmt1(46) case_stmt1(47) 36232 | case_stmt1(48) case_stmt1(49) case_stmt1(50) case_stmt1(51) 36233 | case_stmt1(52) case_stmt1(53) case_stmt1(54) case_stmt1(55) 36234 | case_stmt1(56) case_stmt1(57) case_stmt1(58) case_stmt1(59) 36235 | case_stmt1(60) case_stmt1(61) 36236 | 36237 | #undef case_stmt0 36238 | #undef case_stmt1 36239 | default : return error_node(); 36240 | } 36241 | } 36242 | 36243 | template <typename T0, typename T1, typename T2, typename T3> 36244 | static inline bool compile(expression_generator<Type>& expr_gen, const std::string& id, 36245 | T0 t0, T1 t1, T2 t2, T3 t3, 36246 | expression_node_ptr& result) 36247 | { 36248 | details::operator_type sf4opr; 36249 | 36250 | if (!expr_gen.sf4_optimisable(id,sf4opr)) 36251 | return false; 36252 | else 36253 | result = synthesize_sf4ext_expression::template process<T0, T1, T2, T3> 36254 | (expr_gen, sf4opr, t0, t1, t2, t3); 36255 | 36256 | return true; 36257 | } 36258 | 36259 | // T o (sf3ext) 36260 | template <typename ExternalType> 36261 | static inline bool compile_right(expression_generator<Type>& expr_gen, 36262 | ExternalType t, 36263 | const details::operator_type& operation, 36264 | expression_node_ptr& sf3node, 36265 | expression_node_ptr& result) 36266 | { 36267 | if (!details::is_sf3ext_node(sf3node)) 36268 | return false; 36269 | 36270 | typedef details::T0oT1oT2_base_node<Type>* sf3ext_base_ptr; 36271 | 36272 | sf3ext_base_ptr n = static_cast<sf3ext_base_ptr>(sf3node); 36273 | const std::string id = "t" + expr_gen.to_str(operation) + "(" + n->type_id() + ")" 36274 | 36275 | switch (n->type()) 36276 | { 36277 | case details::expression_node<Type>::e_covoc : return compile_right_impl 36278 | <typename covoc_t::sf3_type_node,ExternalType, ctype, vtype, ctype> 36279 | (expr_gen, id, t, sf3node, result); 36280 | 36281 | case details::expression_node<Type>::e_covov : return compile_right_impl 36282 | <typename covov_t::sf3_type_node,ExternalType, ctype, vtype, vtype> 36283 | (expr_gen, id, t, sf3node, result); 36284 | 36285 | case details::expression_node<Type>::e_vocov : return compile_right_impl 36286 | <typename vocov_t::sf3_type_node,ExternalType, vtype, ctype, vtype> 36287 | (expr_gen, id, t, sf3node, result); 36288 | 36289 | case details::expression_node<Type>::e_vovoc : return compile_right_impl 36290 | <typename vovoc_t::sf3_type_node,ExternalType, vtype, vtype, ctype> 36291 | (expr_gen, id, t, sf3node, result); 36292 | 36293 | case details::expression_node<Type>::e_vovov : return compile_right_impl 36294 | <typename vovov_t::sf3_type_node,ExternalType, vtype, vtype, vtype> 36295 | (expr_gen, id, t, sf3node, result); 36296 | 36297 | default : return false; 36298 | } 36299 | } 36300 | 36301 | // (sf3ext) o T 36302 | template <typename ExternalType> 36303 | static inline bool compile_left(expression_generator<Type>& expr_gen, 36304 | ExternalType t, 36305 | const details::operator_type& operation, 36306 | expression_node_ptr& sf3node, 36307 | expression_node_ptr& result) 36308 | { 36309 | if (!details::is_sf3ext_node(sf3node)) 36310 | return false; 36311 | 36312 | typedef details::T0oT1oT2_base_node<Type>* sf3ext_base_ptr; 36313 | 36314 | sf3ext_base_ptr n = static_cast<sf3ext_base_ptr>(sf3node); 36315 | 36316 | const std::string id = "(" + n->type_id() + ")" + expr_gen.to_str(operation) + "t" 36317 | 36318 | switch (n->type()) 36319 | { 36320 | case details::expression_node<Type>::e_covoc : return compile_left_impl 36321 | <typename covoc_t::sf3_type_node,ExternalType, ctype, vtype, ctype> 36322 | (expr_gen, id, t, sf3node, result); 36323 | 36324 | case details::expression_node<Type>::e_covov : return compile_left_impl 36325 | <typename covov_t::sf3_type_node,ExternalType, ctype, vtype, vtype> 36326 | (expr_gen, id, t, sf3node, result); 36327 | 36328 | case details::expression_node<Type>::e_vocov : return compile_left_impl 36329 | <typename vocov_t::sf3_type_node,ExternalType, vtype, ctype, vtype> 36330 | (expr_gen, id, t, sf3node, result); 36331 | 36332 | case details::expression_node<Type>::e_vovoc : return compile_left_impl 36333 | <typename vovoc_t::sf3_type_node,ExternalType, vtype, vtype, ctype> 36334 | (expr_gen, id, t, sf3node, result); 36335 | 36336 | case details::expression_node<Type>::e_vovov : return compile_left_impl 36337 | <typename vovov_t::sf3_type_node,ExternalType, vtype, vtype, vtype> 36338 | (expr_gen, id, t, sf3node, result); 36339 | 36340 | default : return false; 36341 | } 36342 | } 36343 | 36344 | template <typename SF3TypeNode, typename ExternalType, typename T0, typename T1, typename T2> 36345 | static inline bool compile_right_impl(expression_generator<Type>& expr_gen, 36346 | const std::string& id, 36347 | ExternalType t, 36348 | expression_node_ptr& node, 36349 | expression_node_ptr& result) 36350 | { 36351 | SF3TypeNode* n = dynamic_cast<SF3TypeNode*>(node); 36352 | 36353 | if (n) 36354 | { 36355 | T0 t0 = n->t0(); 36356 | T1 t1 = n->t1(); 36357 | T2 t2 = n->t2(); 36358 | 36359 | return synthesize_sf4ext_expression::template compile<ExternalType, T0, T1, T2> 36360 | (expr_gen, id, t, t0, t1, t2, result); 36361 | } 36362 | else 36363 | return false; 36364 | } 36365 | 36366 | template <typename SF3TypeNode, typename ExternalType, typename T0, typename T1, typename T2> 36367 | static inline bool compile_left_impl(expression_generator<Type>& expr_gen, 36368 | const std::string& id, 36369 | ExternalType t, 36370 | expression_node_ptr& node, 36371 | expression_node_ptr& result) 36372 | { 36373 | SF3TypeNode* n = dynamic_cast<SF3TypeNode*>(node); 36374 | 36375 | if (n) 36376 | { 36377 | T0 t0 = n->t0(); 36378 | T1 t1 = n->t1(); 36379 | T2 t2 = n->t2(); 36380 | 36381 | return synthesize_sf4ext_expression::template compile<T0, T1, T2, ExternalType> 36382 | (expr_gen, id, t0, t1, t2, t, result); 36383 | } 36384 | else 36385 | return false; 36386 | } 36387 | }; 36388 | 36389 | struct synthesize_vovov_expression0 36390 | { 36391 | typedef typename vovov_t::type0 node_type; 36392 | typedef typename vovov_t::sf3_type sf3_type; 36393 | 36394 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36395 | const details::operator_type& operation, 36396 | expression_node_ptr (&branch)[2]) 36397 | { 36398 | // (v0 o0 v1) o1 (v2) 36399 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]); 36400 | const Type& v0 = vov->v0(); 36401 | const Type& v1 = vov->v1(); 36402 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 36403 | const details::operator_type o0 = vov->operation(); 36404 | const details::operator_type o1 = operation; 36405 | 36406 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 36407 | 36408 | expression_node_ptr result = error_node(); 36409 | 36410 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36411 | { 36412 | // (v0 / v1) / v2 --> (vovov) v0 / (v1 * v2) 36413 | if ((details::e_div == o0) && (details::e_div == o1)) 36414 | { 36415 | const bool synthesis_result = 36416 | synthesize_sf3ext_expression:: 36417 | template compile<vtype, vtype, vtype>(expr_gen, "t/(t*t)", v0, v1, v2, result); 36418 | 36419 | exprtk_debug(("(v0 / v1) / v2 --> (vovov) v0 / (v1 * v2)\n")); 36420 | 36421 | return (synthesis_result) ? result : error_node(); 36422 | } 36423 | } 36424 | 36425 | const bool synthesis_result = 36426 | synthesize_sf3ext_expression::template compile<vtype, vtype, vtype> 36427 | (expr_gen, id(expr_gen, o0, o1), v0, v1, v2, result); 36428 | 36429 | if (synthesis_result) 36430 | return result; 36431 | 36432 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36433 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36434 | 36435 | if (!expr_gen.valid_operator(o0,f0)) 36436 | return error_node(); 36437 | else if (!expr_gen.valid_operator(o1,f1)) 36438 | return error_node(); 36439 | else 36440 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, f0, f1); 36441 | } 36442 | 36443 | static inline std::string id(expression_generator<Type>& expr_gen, 36444 | const details::operator_type o0, 36445 | const details::operator_type o1) 36446 | { 36447 | return details::build_string() 36448 | << "(t" << expr_gen.to_str(o0) 36449 | << "t)" << expr_gen.to_str(o1) 36450 | << "t" 36451 | } 36452 | }; 36453 | 36454 | struct synthesize_vovov_expression1 36455 | { 36456 | typedef typename vovov_t::type1 node_type; 36457 | typedef typename vovov_t::sf3_type sf3_type; 36458 | 36459 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36460 | const details::operator_type& operation, 36461 | expression_node_ptr (&branch)[2]) 36462 | { 36463 | // (v0) o0 (v1 o1 v2) 36464 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]); 36465 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 36466 | const Type& v1 = vov->v0(); 36467 | const Type& v2 = vov->v1(); 36468 | const details::operator_type o0 = operation; 36469 | const details::operator_type o1 = vov->operation(); 36470 | 36471 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 36472 | 36473 | expression_node_ptr result = error_node(); 36474 | 36475 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36476 | { 36477 | // v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1 36478 | if ((details::e_div == o0) && (details::e_div == o1)) 36479 | { 36480 | const bool synthesis_result = 36481 | synthesize_sf3ext_expression:: 36482 | template compile<vtype, vtype, vtype>(expr_gen, "(t*t)/t", v0, v2, v1, result); 36483 | 36484 | exprtk_debug(("v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1\n")); 36485 | 36486 | return (synthesis_result) ? result : error_node(); 36487 | } 36488 | } 36489 | 36490 | const bool synthesis_result = 36491 | synthesize_sf3ext_expression::template compile<vtype, vtype, vtype> 36492 | (expr_gen, id(expr_gen, o0, o1), v0, v1, v2, result); 36493 | 36494 | if (synthesis_result) 36495 | return result; 36496 | 36497 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36498 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36499 | 36500 | if (!expr_gen.valid_operator(o0,f0)) 36501 | return error_node(); 36502 | else if (!expr_gen.valid_operator(o1,f1)) 36503 | return error_node(); 36504 | else 36505 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, f0, f1); 36506 | } 36507 | 36508 | static inline std::string id(expression_generator<Type>& expr_gen, 36509 | const details::operator_type o0, 36510 | const details::operator_type o1) 36511 | { 36512 | return details::build_string() 36513 | << "t" << expr_gen.to_str(o0) 36514 | << "(t" << expr_gen.to_str(o1) 36515 | << "t)" 36516 | } 36517 | }; 36518 | 36519 | struct synthesize_vovoc_expression0 36520 | { 36521 | typedef typename vovoc_t::type0 node_type; 36522 | typedef typename vovoc_t::sf3_type sf3_type; 36523 | 36524 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36525 | const details::operator_type& operation, 36526 | expression_node_ptr (&branch)[2]) 36527 | { 36528 | // (v0 o0 v1) o1 (c) 36529 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]); 36530 | const Type& v0 = vov->v0(); 36531 | const Type& v1 = vov->v1(); 36532 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 36533 | const details::operator_type o0 = vov->operation(); 36534 | const details::operator_type o1 = operation; 36535 | 36536 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 36537 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 36538 | 36539 | expression_node_ptr result = error_node(); 36540 | 36541 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36542 | { 36543 | // (v0 / v1) / c --> (vovoc) v0 / (v1 * c) 36544 | if ((details::e_div == o0) && (details::e_div == o1)) 36545 | { 36546 | const bool synthesis_result = 36547 | synthesize_sf3ext_expression:: 36548 | template compile<vtype, vtype, ctype>(expr_gen, "t/(t*t)", v0, v1, c, result); 36549 | 36550 | exprtk_debug(("(v0 / v1) / c --> (vovoc) v0 / (v1 * c)\n")); 36551 | 36552 | return (synthesis_result) ? result : error_node(); 36553 | } 36554 | } 36555 | 36556 | const bool synthesis_result = 36557 | synthesize_sf3ext_expression::template compile<vtype, vtype, ctype> 36558 | (expr_gen, id(expr_gen, o0, o1), v0, v1, c, result); 36559 | 36560 | if (synthesis_result) 36561 | return result; 36562 | 36563 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36564 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36565 | 36566 | if (!expr_gen.valid_operator(o0,f0)) 36567 | return error_node(); 36568 | else if (!expr_gen.valid_operator(o1,f1)) 36569 | return error_node(); 36570 | else 36571 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, f0, f1); 36572 | } 36573 | 36574 | static inline std::string id(expression_generator<Type>& expr_gen, 36575 | const details::operator_type o0, 36576 | const details::operator_type o1) 36577 | { 36578 | return details::build_string() 36579 | << "(t" << expr_gen.to_str(o0) 36580 | << "t)" << expr_gen.to_str(o1) 36581 | << "t" 36582 | } 36583 | }; 36584 | 36585 | struct synthesize_vovoc_expression1 36586 | { 36587 | typedef typename vovoc_t::type1 node_type; 36588 | typedef typename vovoc_t::sf3_type sf3_type; 36589 | 36590 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36591 | const details::operator_type& operation, 36592 | expression_node_ptr (&branch)[2]) 36593 | { 36594 | // (v0) o0 (v1 o1 c) 36595 | const details::voc_base_node<Type>* voc = static_cast<const details::voc_base_node<Type>*>(branch[1]); 36596 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 36597 | const Type& v1 = voc->v(); 36598 | const Type c = voc->c(); 36599 | const details::operator_type o0 = operation; 36600 | const details::operator_type o1 = voc->operation(); 36601 | 36602 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 36603 | 36604 | expression_node_ptr result = error_node(); 36605 | 36606 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36607 | { 36608 | // v0 / (v1 / c) --> (vocov) (v0 * c) / v1 36609 | if ((details::e_div == o0) && (details::e_div == o1)) 36610 | { 36611 | const bool synthesis_result = 36612 | synthesize_sf3ext_expression:: 36613 | template compile<vtype, ctype, vtype>(expr_gen, "(t*t)/t", v0, c, v1, result); 36614 | 36615 | exprtk_debug(("v0 / (v1 / c) --> (vocov) (v0 * c) / v1\n")); 36616 | 36617 | return (synthesis_result) ? result : error_node(); 36618 | } 36619 | } 36620 | 36621 | const bool synthesis_result = 36622 | synthesize_sf3ext_expression::template compile<vtype, vtype, ctype> 36623 | (expr_gen, id(expr_gen, o0, o1), v0, v1, c, result); 36624 | 36625 | if (synthesis_result) 36626 | return result; 36627 | 36628 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36629 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36630 | 36631 | if (!expr_gen.valid_operator(o0,f0)) 36632 | return error_node(); 36633 | else if (!expr_gen.valid_operator(o1,f1)) 36634 | return error_node(); 36635 | else 36636 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, f0, f1); 36637 | } 36638 | 36639 | static inline std::string id(expression_generator<Type>& expr_gen, 36640 | const details::operator_type o0, 36641 | const details::operator_type o1) 36642 | { 36643 | return details::build_string() 36644 | << "t" << expr_gen.to_str(o0) 36645 | << "(t" << expr_gen.to_str(o1) 36646 | << "t)" 36647 | } 36648 | }; 36649 | 36650 | struct synthesize_vocov_expression0 36651 | { 36652 | typedef typename vocov_t::type0 node_type; 36653 | typedef typename vocov_t::sf3_type sf3_type; 36654 | 36655 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36656 | const details::operator_type& operation, 36657 | expression_node_ptr (&branch)[2]) 36658 | { 36659 | // (v0 o0 c) o1 (v1) 36660 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]); 36661 | const Type& v0 = voc->v(); 36662 | const Type c = voc->c(); 36663 | const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 36664 | const details::operator_type o0 = voc->operation(); 36665 | const details::operator_type o1 = operation; 36666 | 36667 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 36668 | 36669 | expression_node_ptr result = error_node(); 36670 | 36671 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36672 | { 36673 | // (v0 / c) / v1 --> (vovoc) v0 / (v1 * c) 36674 | if ((details::e_div == o0) && (details::e_div == o1)) 36675 | { 36676 | const bool synthesis_result = 36677 | synthesize_sf3ext_expression:: 36678 | template compile<vtype, vtype, ctype>(expr_gen, "t/(t*t)", v0, v1, c, result); 36679 | 36680 | exprtk_debug(("(v0 / c) / v1 --> (vovoc) v0 / (v1 * c)\n")); 36681 | 36682 | return (synthesis_result) ? result : error_node(); 36683 | } 36684 | } 36685 | 36686 | const bool synthesis_result = 36687 | synthesize_sf3ext_expression::template compile<vtype, ctype, vtype> 36688 | (expr_gen, id(expr_gen, o0, o1), v0, c, v1, result); 36689 | 36690 | if (synthesis_result) 36691 | return result; 36692 | 36693 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36694 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36695 | 36696 | if (!expr_gen.valid_operator(o0,f0)) 36697 | return error_node(); 36698 | else if (!expr_gen.valid_operator(o1,f1)) 36699 | return error_node(); 36700 | else 36701 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, f0, f1); 36702 | } 36703 | 36704 | static inline std::string id(expression_generator<Type>& expr_gen, 36705 | const details::operator_type o0, 36706 | const details::operator_type o1) 36707 | { 36708 | return details::build_string() 36709 | << "(t" << expr_gen.to_str(o0) 36710 | << "t)" << expr_gen.to_str(o1) 36711 | << "t" 36712 | } 36713 | }; 36714 | 36715 | struct synthesize_vocov_expression1 36716 | { 36717 | typedef typename vocov_t::type1 node_type; 36718 | typedef typename vocov_t::sf3_type sf3_type; 36719 | 36720 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36721 | const details::operator_type& operation, 36722 | expression_node_ptr (&branch)[2]) 36723 | { 36724 | // (v0) o0 (c o1 v1) 36725 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]); 36726 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 36727 | const Type c = cov->c(); 36728 | const Type& v1 = cov->v(); 36729 | const details::operator_type o0 = operation; 36730 | const details::operator_type o1 = cov->operation(); 36731 | 36732 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 36733 | 36734 | expression_node_ptr result = error_node(); 36735 | 36736 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36737 | { 36738 | // v0 / (c / v1) --> (vovoc) (v0 * v1) / c 36739 | if ((details::e_div == o0) && (details::e_div == o1)) 36740 | { 36741 | const bool synthesis_result = 36742 | synthesize_sf3ext_expression:: 36743 | template compile<vtype, vtype, ctype>(expr_gen, "(t*t)/t", v0, v1, c, result); 36744 | 36745 | exprtk_debug(("v0 / (c / v1) --> (vovoc) (v0 * v1) / c\n")); 36746 | 36747 | return (synthesis_result) ? result : error_node(); 36748 | } 36749 | } 36750 | 36751 | const bool synthesis_result = 36752 | synthesize_sf3ext_expression::template compile<vtype, ctype, vtype> 36753 | (expr_gen, id(expr_gen, o0, o1), v0, c, v1, result); 36754 | 36755 | if (synthesis_result) 36756 | return result; 36757 | 36758 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36759 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36760 | 36761 | if (!expr_gen.valid_operator(o0,f0)) 36762 | return error_node(); 36763 | else if (!expr_gen.valid_operator(o1,f1)) 36764 | return error_node(); 36765 | else 36766 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, f0, f1); 36767 | } 36768 | 36769 | static inline std::string id(expression_generator<Type>& expr_gen, 36770 | const details::operator_type o0, 36771 | const details::operator_type o1) 36772 | { 36773 | return details::build_string() 36774 | << "t" << expr_gen.to_str(o0) 36775 | << "(t" << expr_gen.to_str(o1) 36776 | << "t)" 36777 | } 36778 | }; 36779 | 36780 | struct synthesize_covov_expression0 36781 | { 36782 | typedef typename covov_t::type0 node_type; 36783 | typedef typename covov_t::sf3_type sf3_type; 36784 | 36785 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36786 | const details::operator_type& operation, 36787 | expression_node_ptr (&branch)[2]) 36788 | { 36789 | // (c o0 v0) o1 (v1) 36790 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]); 36791 | const Type c = cov->c(); 36792 | const Type& v0 = cov->v(); 36793 | const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 36794 | const details::operator_type o0 = cov->operation(); 36795 | const details::operator_type o1 = operation; 36796 | 36797 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 36798 | 36799 | expression_node_ptr result = error_node(); 36800 | 36801 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36802 | { 36803 | // (c / v0) / v1 --> (covov) c / (v0 * v1) 36804 | if ((details::e_div == o0) && (details::e_div == o1)) 36805 | { 36806 | const bool synthesis_result = 36807 | synthesize_sf3ext_expression:: 36808 | template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", c, v0, v1, result); 36809 | 36810 | exprtk_debug(("(c / v0) / v1 --> (covov) c / (v0 * v1)\n")); 36811 | 36812 | return (synthesis_result) ? result : error_node(); 36813 | } 36814 | } 36815 | 36816 | const bool synthesis_result = 36817 | synthesize_sf3ext_expression::template compile<ctype, vtype, vtype> 36818 | (expr_gen, id(expr_gen, o0, o1), c, v0, v1, result); 36819 | 36820 | if (synthesis_result) 36821 | return result; 36822 | 36823 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36824 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36825 | 36826 | if (!expr_gen.valid_operator(o0,f0)) 36827 | return error_node(); 36828 | else if (!expr_gen.valid_operator(o1,f1)) 36829 | return error_node(); 36830 | else 36831 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, f0, f1); 36832 | } 36833 | 36834 | static inline std::string id(expression_generator<Type>& expr_gen, 36835 | const details::operator_type o0, 36836 | const details::operator_type o1) 36837 | { 36838 | return details::build_string() 36839 | << "(t" << expr_gen.to_str(o0) 36840 | << "t)" << expr_gen.to_str(o1) 36841 | << "t" 36842 | } 36843 | }; 36844 | 36845 | struct synthesize_covov_expression1 36846 | { 36847 | typedef typename covov_t::type1 node_type; 36848 | typedef typename covov_t::sf3_type sf3_type; 36849 | 36850 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36851 | const details::operator_type& operation, 36852 | expression_node_ptr (&branch)[2]) 36853 | { 36854 | // (c) o0 (v0 o1 v1) 36855 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]); 36856 | const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); 36857 | const Type& v0 = vov->v0(); 36858 | const Type& v1 = vov->v1(); 36859 | const details::operator_type o0 = operation; 36860 | const details::operator_type o1 = vov->operation(); 36861 | 36862 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 36863 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 36864 | 36865 | expression_node_ptr result = error_node(); 36866 | 36867 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36868 | { 36869 | // c / (v0 / v1) --> (covov) (c * v1) / v0 36870 | if ((details::e_div == o0) && (details::e_div == o1)) 36871 | { 36872 | const bool synthesis_result = 36873 | synthesize_sf3ext_expression:: 36874 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", c, v1, v0, result); 36875 | 36876 | exprtk_debug(("c / (v0 / v1) --> (covov) (c * v1) / v0\n")); 36877 | 36878 | return (synthesis_result) ? result : error_node(); 36879 | } 36880 | } 36881 | 36882 | const bool synthesis_result = 36883 | synthesize_sf3ext_expression::template compile<ctype, vtype, vtype> 36884 | (expr_gen, id(expr_gen, o0, o1), c, v0, v1, result); 36885 | 36886 | if (synthesis_result) 36887 | return result; 36888 | 36889 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 36890 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 36891 | 36892 | if (!expr_gen.valid_operator(o0,f0)) 36893 | return error_node(); 36894 | else if (!expr_gen.valid_operator(o1,f1)) 36895 | return error_node(); 36896 | else 36897 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, f0, f1); 36898 | } 36899 | 36900 | static inline std::string id(expression_generator<Type>& expr_gen, 36901 | const details::operator_type o0, 36902 | const details::operator_type o1) 36903 | { 36904 | return details::build_string() 36905 | << "t" << expr_gen.to_str(o0) 36906 | << "(t" << expr_gen.to_str(o1) 36907 | << "t)" 36908 | } 36909 | }; 36910 | 36911 | struct synthesize_covoc_expression0 36912 | { 36913 | typedef typename covoc_t::type0 node_type; 36914 | typedef typename covoc_t::sf3_type sf3_type; 36915 | 36916 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 36917 | const details::operator_type& operation, 36918 | expression_node_ptr (&branch)[2]) 36919 | { 36920 | // (c0 o0 v) o1 (c1) 36921 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]); 36922 | const Type c0 = cov->c(); 36923 | const Type& v = cov->v(); 36924 | const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); 36925 | const details::operator_type o0 = cov->operation(); 36926 | const details::operator_type o1 = operation; 36927 | 36928 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 36929 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 36930 | 36931 | expression_node_ptr result = error_node(); 36932 | 36933 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 36934 | { 36935 | // (c0 + v) + c1 --> (cov) (c0 + c1) + v 36936 | if ((details::e_add == o0) && (details::e_add == o1)) 36937 | { 36938 | exprtk_debug(("(c0 + v) + c1 --> (cov) (c0 + c1) + v\n")); 36939 | 36940 | return expr_gen.node_allocator_-> 36941 | template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v); 36942 | } 36943 | // (c0 + v) - c1 --> (cov) (c0 - c1) + v 36944 | else if ((details::e_add == o0) && (details::e_sub == o1)) 36945 | { 36946 | exprtk_debug(("(c0 + v) - c1 --> (cov) (c0 - c1) + v\n")); 36947 | 36948 | return expr_gen.node_allocator_-> 36949 | template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v); 36950 | } 36951 | // (c0 - v) + c1 --> (cov) (c0 + c1) - v 36952 | else if ((details::e_sub == o0) && (details::e_add == o1)) 36953 | { 36954 | exprtk_debug(("(c0 - v) + c1 --> (cov) (c0 + c1) - v\n")); 36955 | 36956 | return expr_gen.node_allocator_-> 36957 | template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v); 36958 | } 36959 | // (c0 - v) - c1 --> (cov) (c0 - c1) - v 36960 | else if ((details::e_sub == o0) && (details::e_sub == o1)) 36961 | { 36962 | exprtk_debug(("(c0 - v) - c1 --> (cov) (c0 - c1) - v\n")); 36963 | 36964 | return expr_gen.node_allocator_-> 36965 | template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v); 36966 | } 36967 | // (c0 * v) * c1 --> (cov) (c0 * c1) * v 36968 | else if ((details::e_mul == o0) && (details::e_mul == o1)) 36969 | { 36970 | exprtk_debug(("(c0 * v) * c1 --> (cov) (c0 * c1) * v\n")); 36971 | 36972 | return expr_gen.node_allocator_-> 36973 | template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v); 36974 | } 36975 | // (c0 * v) / c1 --> (cov) (c0 / c1) * v 36976 | else if ((details::e_mul == o0) && (details::e_div == o1)) 36977 | { 36978 | exprtk_debug(("(c0 * v) / c1 --> (cov) (c0 / c1) * v\n")); 36979 | 36980 | return expr_gen.node_allocator_-> 36981 | template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v); 36982 | } 36983 | // (c0 / v) * c1 --> (cov) (c0 * c1) / v 36984 | else if ((details::e_div == o0) && (details::e_mul == o1)) 36985 | { 36986 | exprtk_debug(("(c0 / v) * c1 --> (cov) (c0 * c1) / v\n")); 36987 | 36988 | return expr_gen.node_allocator_-> 36989 | template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v); 36990 | } 36991 | // (c0 / v) / c1 --> (cov) (c0 / c1) / v 36992 | else if ((details::e_div == o0) && (details::e_div == o1)) 36993 | { 36994 | exprtk_debug(("(c0 / v) / c1 --> (cov) (c0 / c1) / v\n")); 36995 | 36996 | return expr_gen.node_allocator_-> 36997 | template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v); 36998 | } 36999 | } 37000 | 37001 | const bool synthesis_result = 37002 | synthesize_sf3ext_expression::template compile<ctype, vtype, ctype> 37003 | (expr_gen, id(expr_gen, o0, o1), c0, v, c1, result); 37004 | 37005 | if (synthesis_result) 37006 | return result; 37007 | 37008 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37009 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37010 | 37011 | if (!expr_gen.valid_operator(o0,f0)) 37012 | return error_node(); 37013 | else if (!expr_gen.valid_operator(o1,f1)) 37014 | return error_node(); 37015 | else 37016 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v, c1, f0, f1); 37017 | } 37018 | 37019 | static inline std::string id(expression_generator<Type>& expr_gen, 37020 | const details::operator_type o0, 37021 | const details::operator_type o1) 37022 | { 37023 | return details::build_string() 37024 | << "(t" << expr_gen.to_str(o0) 37025 | << "t)" << expr_gen.to_str(o1) 37026 | << "t" 37027 | } 37028 | }; 37029 | 37030 | struct synthesize_covoc_expression1 37031 | { 37032 | typedef typename covoc_t::type1 node_type; 37033 | typedef typename covoc_t::sf3_type sf3_type; 37034 | 37035 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37036 | const details::operator_type& operation, 37037 | expression_node_ptr (&branch)[2]) 37038 | { 37039 | // (c0) o0 (v o1 c1) 37040 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]); 37041 | const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); 37042 | const Type& v = voc->v(); 37043 | const Type c1 = voc->c(); 37044 | const details::operator_type o0 = operation; 37045 | const details::operator_type o1 = voc->operation(); 37046 | 37047 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37048 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37049 | 37050 | expression_node_ptr result = error_node(); 37051 | 37052 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37053 | { 37054 | // (c0) + (v + c1) --> (cov) (c0 + c1) + v 37055 | if ((details::e_add == o0) && (details::e_add == o1)) 37056 | { 37057 | exprtk_debug(("(c0) + (v + c1) --> (cov) (c0 + c1) + v\n")); 37058 | 37059 | return expr_gen.node_allocator_-> 37060 | template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v); 37061 | } 37062 | // (c0) + (v - c1) --> (cov) (c0 - c1) + v 37063 | else if ((details::e_add == o0) && (details::e_sub == o1)) 37064 | { 37065 | exprtk_debug(("(c0) + (v - c1) --> (cov) (c0 - c1) + v\n")); 37066 | 37067 | return expr_gen.node_allocator_-> 37068 | template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v); 37069 | } 37070 | // (c0) - (v + c1) --> (cov) (c0 - c1) - v 37071 | else if ((details::e_sub == o0) && (details::e_add == o1)) 37072 | { 37073 | exprtk_debug(("(c0) - (v + c1) --> (cov) (c0 - c1) - v\n")); 37074 | 37075 | return expr_gen.node_allocator_-> 37076 | template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v); 37077 | } 37078 | // (c0) - (v - c1) --> (cov) (c0 + c1) - v 37079 | else if ((details::e_sub == o0) && (details::e_sub == o1)) 37080 | { 37081 | exprtk_debug(("(c0) - (v - c1) --> (cov) (c0 + c1) - v\n")); 37082 | 37083 | return expr_gen.node_allocator_-> 37084 | template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v); 37085 | } 37086 | // (c0) * (v * c1) --> (voc) v * (c0 * c1) 37087 | else if ((details::e_mul == o0) && (details::e_mul == o1)) 37088 | { 37089 | exprtk_debug(("(c0) * (v * c1) --> (voc) v * (c0 * c1)\n")); 37090 | 37091 | return expr_gen.node_allocator_-> 37092 | template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v); 37093 | } 37094 | // (c0) * (v / c1) --> (cov) (c0 / c1) * v 37095 | else if ((details::e_mul == o0) && (details::e_div == o1)) 37096 | { 37097 | exprtk_debug(("(c0) * (v / c1) --> (cov) (c0 / c1) * v\n")); 37098 | 37099 | return expr_gen.node_allocator_-> 37100 | template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v); 37101 | } 37102 | // (c0) / (v * c1) --> (cov) (c0 / c1) / v 37103 | else if ((details::e_div == o0) && (details::e_mul == o1)) 37104 | { 37105 | exprtk_debug(("(c0) / (v * c1) --> (cov) (c0 / c1) / v\n")); 37106 | 37107 | return expr_gen.node_allocator_-> 37108 | template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v); 37109 | } 37110 | // (c0) / (v / c1) --> (cov) (c0 * c1) / v 37111 | else if ((details::e_div == o0) && (details::e_div == o1)) 37112 | { 37113 | exprtk_debug(("(c0) / (v / c1) --> (cov) (c0 * c1) / v\n")); 37114 | 37115 | return expr_gen.node_allocator_-> 37116 | template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v); 37117 | } 37118 | } 37119 | 37120 | const bool synthesis_result = 37121 | synthesize_sf3ext_expression::template compile<ctype, vtype, ctype> 37122 | (expr_gen, id(expr_gen, o0, o1), c0, v, c1, result); 37123 | 37124 | if (synthesis_result) 37125 | return result; 37126 | 37127 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37128 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37129 | 37130 | if (!expr_gen.valid_operator(o0,f0)) 37131 | return error_node(); 37132 | else if (!expr_gen.valid_operator(o1,f1)) 37133 | return error_node(); 37134 | else 37135 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v, c1, f0, f1); 37136 | } 37137 | 37138 | static inline std::string id(expression_generator<Type>& expr_gen, 37139 | const details::operator_type o0, 37140 | const details::operator_type o1) 37141 | { 37142 | return details::build_string() 37143 | << "t" << expr_gen.to_str(o0) 37144 | << "(t" << expr_gen.to_str(o1) 37145 | << "t)" 37146 | } 37147 | }; 37148 | 37149 | struct synthesize_cocov_expression0 37150 | { 37151 | typedef typename cocov_t::type0 node_type; 37152 | static inline expression_node_ptr process(expression_generator<Type>&, 37153 | const details::operator_type&, 37154 | expression_node_ptr (&)[2]) 37155 | { 37156 | // (c0 o0 c1) o1 (v) - Not possible. 37157 | return error_node(); 37158 | } 37159 | }; 37160 | 37161 | struct synthesize_cocov_expression1 37162 | { 37163 | typedef typename cocov_t::type1 node_type; 37164 | typedef typename cocov_t::sf3_type sf3_type; 37165 | 37166 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37167 | const details::operator_type& operation, 37168 | expression_node_ptr (&branch)[2]) 37169 | { 37170 | // (c0) o0 (c1 o1 v) 37171 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]); 37172 | const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); 37173 | const Type c1 = cov->c(); 37174 | const Type& v = cov->v(); 37175 | const details::operator_type o0 = operation; 37176 | const details::operator_type o1 = cov->operation(); 37177 | 37178 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37179 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37180 | 37181 | expression_node_ptr result = error_node(); 37182 | 37183 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37184 | { 37185 | // (c0) + (c1 + v) --> (cov) (c0 + c1) + v 37186 | if ((details::e_add == o0) && (details::e_add == o1)) 37187 | { 37188 | exprtk_debug(("(c0) + (c1 + v) --> (cov) (c0 + c1) + v\n")); 37189 | 37190 | return expr_gen.node_allocator_-> 37191 | template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v); 37192 | } 37193 | // (c0) + (c1 - v) --> (cov) (c0 + c1) - v 37194 | else if ((details::e_add == o0) && (details::e_sub == o1)) 37195 | { 37196 | exprtk_debug(("(c0) + (c1 - v) --> (cov) (c0 + c1) - v\n")); 37197 | 37198 | return expr_gen.node_allocator_-> 37199 | template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v); 37200 | } 37201 | // (c0) - (c1 + v) --> (cov) (c0 - c1) - v 37202 | else if ((details::e_sub == o0) && (details::e_add == o1)) 37203 | { 37204 | exprtk_debug(("(c0) - (c1 + v) --> (cov) (c0 - c1) - v\n")); 37205 | 37206 | return expr_gen.node_allocator_-> 37207 | template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v); 37208 | } 37209 | // (c0) - (c1 - v) --> (cov) (c0 - c1) + v 37210 | else if ((details::e_sub == o0) && (details::e_sub == o1)) 37211 | { 37212 | exprtk_debug(("(c0) - (c1 - v) --> (cov) (c0 - c1) + v\n")); 37213 | 37214 | return expr_gen.node_allocator_-> 37215 | template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v); 37216 | } 37217 | // (c0) * (c1 * v) --> (cov) (c0 * c1) * v 37218 | else if ((details::e_mul == o0) && (details::e_mul == o1)) 37219 | { 37220 | exprtk_debug(("(c0) * (c1 * v) --> (cov) (c0 * c1) * v\n")); 37221 | 37222 | return expr_gen.node_allocator_-> 37223 | template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v); 37224 | } 37225 | // (c0) * (c1 / v) --> (cov) (c0 * c1) / v 37226 | else if ((details::e_mul == o0) && (details::e_div == o1)) 37227 | { 37228 | exprtk_debug(("(c0) * (c1 / v) --> (cov) (c0 * c1) / v\n")); 37229 | 37230 | return expr_gen.node_allocator_-> 37231 | template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v); 37232 | } 37233 | // (c0) / (c1 * v) --> (cov) (c0 / c1) / v 37234 | else if ((details::e_div == o0) && (details::e_mul == o1)) 37235 | { 37236 | exprtk_debug(("(c0) / (c1 * v) --> (cov) (c0 / c1) / v\n")); 37237 | 37238 | return expr_gen.node_allocator_-> 37239 | template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v); 37240 | } 37241 | // (c0) / (c1 / v) --> (cov) (c0 / c1) * v 37242 | else if ((details::e_div == o0) && (details::e_div == o1)) 37243 | { 37244 | exprtk_debug(("(c0) / (c1 / v) --> (cov) (c0 / c1) * v\n")); 37245 | 37246 | return expr_gen.node_allocator_-> 37247 | template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v); 37248 | } 37249 | } 37250 | 37251 | const bool synthesis_result = 37252 | synthesize_sf3ext_expression::template compile<ctype, ctype, vtype> 37253 | (expr_gen, id(expr_gen, o0, o1), c0, c1, v, result); 37254 | 37255 | if (synthesis_result) 37256 | return result; 37257 | 37258 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37259 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37260 | 37261 | if (!expr_gen.valid_operator(o0,f0)) 37262 | return error_node(); 37263 | else if (!expr_gen.valid_operator(o1,f1)) 37264 | return error_node(); 37265 | else 37266 | return node_type::allocate(*(expr_gen.node_allocator_), c0, c1, v, f0, f1); 37267 | } 37268 | 37269 | static inline std::string id(expression_generator<Type>& expr_gen, 37270 | const details::operator_type o0, 37271 | const details::operator_type o1) 37272 | { 37273 | return details::build_string() 37274 | << "t" << expr_gen.to_str(o0) 37275 | << "(t" << expr_gen.to_str(o1) 37276 | << "t)" 37277 | } 37278 | }; 37279 | 37280 | struct synthesize_vococ_expression0 37281 | { 37282 | typedef typename vococ_t::type0 node_type; 37283 | typedef typename vococ_t::sf3_type sf3_type; 37284 | 37285 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37286 | const details::operator_type& operation, 37287 | expression_node_ptr (&branch)[2]) 37288 | { 37289 | // (v o0 c0) o1 (c1) 37290 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]); 37291 | const Type& v = voc->v(); 37292 | const Type& c0 = voc->c(); 37293 | const Type& c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); 37294 | const details::operator_type o0 = voc->operation(); 37295 | const details::operator_type o1 = operation; 37296 | 37297 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37298 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37299 | 37300 | expression_node_ptr result = error_node(); 37301 | 37302 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37303 | { 37304 | // (v + c0) + c1 --> (voc) v + (c0 + c1) 37305 | if ((details::e_add == o0) && (details::e_add == o1)) 37306 | { 37307 | exprtk_debug(("(v + c0) + c1 --> (voc) v + (c0 + c1)\n")); 37308 | 37309 | return expr_gen.node_allocator_-> 37310 | template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c0 + c1); 37311 | } 37312 | // (v + c0) - c1 --> (voc) v + (c0 - c1) 37313 | else if ((details::e_add == o0) && (details::e_sub == o1)) 37314 | { 37315 | exprtk_debug(("(v + c0) - c1 --> (voc) v + (c0 - c1)\n")); 37316 | 37317 | return expr_gen.node_allocator_-> 37318 | template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c0 - c1); 37319 | } 37320 | // (v - c0) + c1 --> (voc) v - (c0 + c1) 37321 | else if ((details::e_sub == o0) && (details::e_add == o1)) 37322 | { 37323 | exprtk_debug(("(v - c0) + c1 --> (voc) v - (c0 + c1)\n")); 37324 | 37325 | return expr_gen.node_allocator_-> 37326 | template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c1 - c0); 37327 | } 37328 | // (v - c0) - c1 --> (voc) v - (c0 + c1) 37329 | else if ((details::e_sub == o0) && (details::e_sub == o1)) 37330 | { 37331 | exprtk_debug(("(v - c0) - c1 --> (voc) v - (c0 + c1)\n")); 37332 | 37333 | return expr_gen.node_allocator_-> 37334 | template allocate_rc<typename details::voc_node<Type,details::sub_op<Type> > >(v, c0 + c1); 37335 | } 37336 | // (v * c0) * c1 --> (voc) v * (c0 * c1) 37337 | else if ((details::e_mul == o0) && (details::e_mul == o1)) 37338 | { 37339 | exprtk_debug(("(v * c0) * c1 --> (voc) v * (c0 * c1)\n")); 37340 | 37341 | return expr_gen.node_allocator_-> 37342 | template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c0 * c1); 37343 | } 37344 | // (v * c0) / c1 --> (voc) v * (c0 / c1) 37345 | else if ((details::e_mul == o0) && (details::e_div == o1)) 37346 | { 37347 | exprtk_debug(("(v * c0) / c1 --> (voc) v * (c0 / c1)\n")); 37348 | 37349 | return expr_gen.node_allocator_-> 37350 | template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c0 / c1); 37351 | } 37352 | // (v / c0) * c1 --> (voc) v * (c1 / c0) 37353 | else if ((details::e_div == o0) && (details::e_mul == o1)) 37354 | { 37355 | exprtk_debug(("(v / c0) * c1 --> (voc) v * (c1 / c0)\n")); 37356 | 37357 | return expr_gen.node_allocator_-> 37358 | template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c1 / c0); 37359 | } 37360 | // (v / c0) / c1 --> (voc) v / (c0 * c1) 37361 | else if ((details::e_div == o0) && (details::e_div == o1)) 37362 | { 37363 | exprtk_debug(("(v / c0) / c1 --> (voc) v / (c0 * c1)\n")); 37364 | 37365 | return expr_gen.node_allocator_-> 37366 | template allocate_rc<typename details::voc_node<Type,details::div_op<Type> > >(v, c0 * c1); 37367 | } 37368 | // (v ^ c0) ^ c1 --> (voc) v ^ (c0 * c1) 37369 | else if ((details::e_pow == o0) && (details::e_pow == o1)) 37370 | { 37371 | exprtk_debug(("(v ^ c0) ^ c1 --> (voc) v ^ (c0 * c1)\n")); 37372 | 37373 | return expr_gen.node_allocator_-> 37374 | template allocate_rc<typename details::voc_node<Type,details::pow_op<Type> > >(v, c0 * c1); 37375 | } 37376 | } 37377 | 37378 | const bool synthesis_result = 37379 | synthesize_sf3ext_expression::template compile<vtype, ctype, ctype> 37380 | (expr_gen, id(expr_gen, o0, o1), v, c0, c1, result); 37381 | 37382 | if (synthesis_result) 37383 | return result; 37384 | 37385 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37386 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37387 | 37388 | if (!expr_gen.valid_operator(o0,f0)) 37389 | return error_node(); 37390 | else if (!expr_gen.valid_operator(o1,f1)) 37391 | return error_node(); 37392 | else 37393 | return node_type::allocate(*(expr_gen.node_allocator_), v, c0, c1, f0, f1); 37394 | } 37395 | 37396 | static inline std::string id(expression_generator<Type>& expr_gen, 37397 | const details::operator_type o0, 37398 | const details::operator_type o1) 37399 | { 37400 | return details::build_string() 37401 | << "(t" << expr_gen.to_str(o0) 37402 | << "t)" << expr_gen.to_str(o1) 37403 | << "t" 37404 | } 37405 | }; 37406 | 37407 | struct synthesize_vococ_expression1 37408 | { 37409 | typedef typename vococ_t::type0 node_type; 37410 | 37411 | static inline expression_node_ptr process(expression_generator<Type>&, 37412 | const details::operator_type&, 37413 | expression_node_ptr (&)[2]) 37414 | { 37415 | // (v) o0 (c0 o1 c1) - Not possible. 37416 | exprtk_debug(("(v) o0 (c0 o1 c1) - Not possible.\n")); 37417 | return error_node(); 37418 | } 37419 | }; 37420 | 37421 | struct synthesize_vovovov_expression0 37422 | { 37423 | typedef typename vovovov_t::type0 node_type; 37424 | typedef typename vovovov_t::sf4_type sf4_type; 37425 | typedef typename node_type::T0 T0; 37426 | typedef typename node_type::T1 T1; 37427 | typedef typename node_type::T2 T2; 37428 | typedef typename node_type::T3 T3; 37429 | 37430 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37431 | const details::operator_type& operation, 37432 | expression_node_ptr (&branch)[2]) 37433 | { 37434 | // (v0 o0 v1) o1 (v2 o2 v3) 37435 | const details::vov_base_node<Type>* vov0 = static_cast<details::vov_base_node<Type>*>(branch[0]); 37436 | const details::vov_base_node<Type>* vov1 = static_cast<details::vov_base_node<Type>*>(branch[1]); 37437 | const Type& v0 = vov0->v0(); 37438 | const Type& v1 = vov0->v1(); 37439 | const Type& v2 = vov1->v0(); 37440 | const Type& v3 = vov1->v1(); 37441 | const details::operator_type o0 = vov0->operation(); 37442 | const details::operator_type o1 = operation; 37443 | const details::operator_type o2 = vov1->operation(); 37444 | 37445 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37446 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37447 | 37448 | expression_node_ptr result = error_node(); 37449 | 37450 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37451 | { 37452 | // (v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3) 37453 | if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 37454 | { 37455 | const bool synthesis_result = 37456 | synthesize_sf4ext_expression:: 37457 | template compile<vtype, vtype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, v3, result); 37458 | 37459 | exprtk_debug(("(v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3)\n")); 37460 | 37461 | return (synthesis_result) ? result : error_node(); 37462 | } 37463 | // (v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2) 37464 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 37465 | { 37466 | const bool synthesis_result = 37467 | synthesize_sf4ext_expression:: 37468 | template compile<vtype, vtype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", v0, v3, v1, v2, result); 37469 | 37470 | exprtk_debug(("(v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2)\n")); 37471 | 37472 | return (synthesis_result) ? result : error_node(); 37473 | } 37474 | // (v0 + v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2) 37475 | else if ((details::e_add == o0) && (details::e_div == o1) && (details::e_div == o2)) 37476 | { 37477 | const bool synthesis_result = 37478 | synthesize_sf4ext_expression:: 37479 | template compile<vtype, vtype, vtype, vtype>(expr_gen, "(t+t)*(t/t)", v0, v1, v3, v2, result); 37480 | 37481 | exprtk_debug(("(v0 + v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2)\n")); 37482 | 37483 | return (synthesis_result) ? result : error_node(); 37484 | } 37485 | // (v0 - v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2) 37486 | else if ((details::e_sub == o0) && (details::e_div == o1) && (details::e_div == o2)) 37487 | { 37488 | const bool synthesis_result = 37489 | synthesize_sf4ext_expression:: 37490 | template compile<vtype, vtype, vtype, vtype>(expr_gen, "(t-t)*(t/t)", v0, v1, v3, v2, result); 37491 | 37492 | exprtk_debug(("(v0 - v1) / (v2 / v3) --> (vovovov) (v0 - v1) * (v3 / v2)\n")); 37493 | 37494 | return (synthesis_result) ? result : error_node(); 37495 | } 37496 | // (v0 * v1) / (v2 / v3) --> (vovovov) ((v0 * v1) * v3) / v2 37497 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) 37498 | { 37499 | const bool synthesis_result = 37500 | synthesize_sf4ext_expression:: 37501 | template compile<vtype, vtype, vtype, vtype>(expr_gen, "((t*t)*t)/t", v0, v1, v3, v2, result); 37502 | 37503 | exprtk_debug(("(v0 * v1) / (v2 / v3) --> (vovovov) ((v0 * v1) * v3) / v2\n")); 37504 | 37505 | return (synthesis_result) ? result : error_node(); 37506 | } 37507 | } 37508 | 37509 | const bool synthesis_result = 37510 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 37511 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result); 37512 | 37513 | if (synthesis_result) 37514 | return result; 37515 | 37516 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37517 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37518 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 37519 | 37520 | if (!expr_gen.valid_operator(o0,f0)) 37521 | return error_node(); 37522 | else if (!expr_gen.valid_operator(o1,f1)) 37523 | return error_node(); 37524 | else if (!expr_gen.valid_operator(o2,f2)) 37525 | return error_node(); 37526 | else 37527 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2); 37528 | } 37529 | 37530 | static inline std::string id(expression_generator<Type>& expr_gen, 37531 | const details::operator_type o0, 37532 | const details::operator_type o1, 37533 | const details::operator_type o2) 37534 | { 37535 | return details::build_string() 37536 | << "(t" << expr_gen.to_str(o0) 37537 | << "t)" << expr_gen.to_str(o1) 37538 | << "(t" << expr_gen.to_str(o2) 37539 | << "t)" 37540 | } 37541 | }; 37542 | 37543 | struct synthesize_vovovoc_expression0 37544 | { 37545 | typedef typename vovovoc_t::type0 node_type; 37546 | typedef typename vovovoc_t::sf4_type sf4_type; 37547 | typedef typename node_type::T0 T0; 37548 | typedef typename node_type::T1 T1; 37549 | typedef typename node_type::T2 T2; 37550 | typedef typename node_type::T3 T3; 37551 | 37552 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37553 | const details::operator_type& operation, 37554 | expression_node_ptr (&branch)[2]) 37555 | { 37556 | // (v0 o0 v1) o1 (v2 o2 c) 37557 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]); 37558 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]); 37559 | const Type& v0 = vov->v0(); 37560 | const Type& v1 = vov->v1(); 37561 | const Type& v2 = voc->v (); 37562 | const Type c = voc->c (); 37563 | const details::operator_type o0 = vov->operation(); 37564 | const details::operator_type o1 = operation; 37565 | const details::operator_type o2 = voc->operation(); 37566 | 37567 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37568 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37569 | 37570 | expression_node_ptr result = error_node(); 37571 | 37572 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37573 | { 37574 | // (v0 / v1) * (v2 / c) --> (vovovoc) (v0 * v2) / (v1 * c) 37575 | if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 37576 | { 37577 | const bool synthesis_result = 37578 | synthesize_sf4ext_expression:: 37579 | template compile<vtype, vtype, vtype, ctype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, c, result); 37580 | 37581 | exprtk_debug(("(v0 / v1) * (v2 / c) --> (vovovoc) (v0 * v2) / (v1 * c)\n")); 37582 | 37583 | return (synthesis_result) ? result : error_node(); 37584 | } 37585 | // (v0 / v1) / (v2 / c) --> (vocovov) (v0 * c) / (v1 * v2) 37586 | if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 37587 | { 37588 | const bool synthesis_result = 37589 | synthesize_sf4ext_expression:: 37590 | template compile<vtype, ctype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", v0, c, v1, v2, result); 37591 | 37592 | exprtk_debug(("(v0 / v1) / (v2 / c) --> (vocovov) (v0 * c) / (v1 * v2)\n")); 37593 | 37594 | return (synthesis_result) ? result : error_node(); 37595 | } 37596 | } 37597 | 37598 | const bool synthesis_result = 37599 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 37600 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result); 37601 | 37602 | if (synthesis_result) 37603 | return result; 37604 | 37605 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37606 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37607 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 37608 | 37609 | if (!expr_gen.valid_operator(o0,f0)) 37610 | return error_node(); 37611 | else if (!expr_gen.valid_operator(o1,f1)) 37612 | return error_node(); 37613 | else if (!expr_gen.valid_operator(o2,f2)) 37614 | return error_node(); 37615 | else 37616 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2); 37617 | } 37618 | 37619 | static inline std::string id(expression_generator<Type>& expr_gen, 37620 | const details::operator_type o0, 37621 | const details::operator_type o1, 37622 | const details::operator_type o2) 37623 | { 37624 | return details::build_string() 37625 | << "(t" << expr_gen.to_str(o0) 37626 | << "t)" << expr_gen.to_str(o1) 37627 | << "(t" << expr_gen.to_str(o2) 37628 | << "t)" 37629 | } 37630 | }; 37631 | 37632 | struct synthesize_vovocov_expression0 37633 | { 37634 | typedef typename vovocov_t::type0 node_type; 37635 | typedef typename vovocov_t::sf4_type sf4_type; 37636 | typedef typename node_type::T0 T0; 37637 | typedef typename node_type::T1 T1; 37638 | typedef typename node_type::T2 T2; 37639 | typedef typename node_type::T3 T3; 37640 | 37641 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37642 | const details::operator_type& operation, 37643 | expression_node_ptr (&branch)[2]) 37644 | { 37645 | // (v0 o0 v1) o1 (c o2 v2) 37646 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]); 37647 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]); 37648 | const Type& v0 = vov->v0(); 37649 | const Type& v1 = vov->v1(); 37650 | const Type& v2 = cov->v (); 37651 | const Type c = cov->c (); 37652 | const details::operator_type o0 = vov->operation(); 37653 | const details::operator_type o1 = operation; 37654 | const details::operator_type o2 = cov->operation(); 37655 | 37656 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37657 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37658 | 37659 | expression_node_ptr result = error_node(); 37660 | 37661 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37662 | { 37663 | // (v0 / v1) * (c / v2) --> (vocovov) (v0 * c) / (v1 * v2) 37664 | if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 37665 | { 37666 | const bool synthesis_result = 37667 | synthesize_sf4ext_expression:: 37668 | template compile<vtype, ctype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", v0, c, v1, v2, result); 37669 | 37670 | exprtk_debug(("(v0 / v1) * (c / v2) --> (vocovov) (v0 * c) / (v1 * v2)\n")); 37671 | 37672 | return (synthesis_result) ? result : error_node(); 37673 | } 37674 | // (v0 / v1) / (c / v2) --> (vovovoc) (v0 * v2) / (v1 * c) 37675 | if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 37676 | { 37677 | const bool synthesis_result = 37678 | synthesize_sf4ext_expression:: 37679 | template compile<vtype, vtype, vtype, ctype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, c, result); 37680 | 37681 | exprtk_debug(("(v0 / v1) / (c / v2) --> (vovovoc) (v0 * v2) / (v1 * c)\n")); 37682 | 37683 | return (synthesis_result) ? result : error_node(); 37684 | } 37685 | } 37686 | 37687 | const bool synthesis_result = 37688 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 37689 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result); 37690 | 37691 | if (synthesis_result) 37692 | return result; 37693 | 37694 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37695 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37696 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 37697 | 37698 | if (!expr_gen.valid_operator(o0,f0)) 37699 | return error_node(); 37700 | else if (!expr_gen.valid_operator(o1,f1)) 37701 | return error_node(); 37702 | else if (!expr_gen.valid_operator(o2,f2)) 37703 | return error_node(); 37704 | else 37705 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2); 37706 | } 37707 | 37708 | static inline std::string id(expression_generator<Type>& expr_gen, 37709 | const details::operator_type o0, 37710 | const details::operator_type o1, 37711 | const details::operator_type o2) 37712 | { 37713 | return details::build_string() 37714 | << "(t" << expr_gen.to_str(o0) 37715 | << "t)" << expr_gen.to_str(o1) 37716 | << "(t" << expr_gen.to_str(o2) 37717 | << "t)" 37718 | } 37719 | }; 37720 | 37721 | struct synthesize_vocovov_expression0 37722 | { 37723 | typedef typename vocovov_t::type0 node_type; 37724 | typedef typename vocovov_t::sf4_type sf4_type; 37725 | typedef typename node_type::T0 T0; 37726 | typedef typename node_type::T1 T1; 37727 | typedef typename node_type::T2 T2; 37728 | typedef typename node_type::T3 T3; 37729 | 37730 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37731 | const details::operator_type& operation, 37732 | expression_node_ptr (&branch)[2]) 37733 | { 37734 | // (v0 o0 c) o1 (v1 o2 v2) 37735 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]); 37736 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]); 37737 | const Type c = voc->c (); 37738 | const Type& v0 = voc->v (); 37739 | const Type& v1 = vov->v0(); 37740 | const Type& v2 = vov->v1(); 37741 | const details::operator_type o0 = voc->operation(); 37742 | const details::operator_type o1 = operation; 37743 | const details::operator_type o2 = vov->operation(); 37744 | 37745 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37746 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37747 | 37748 | expression_node_ptr result = error_node(); 37749 | 37750 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37751 | { 37752 | // (v0 / c) * (v1 / v2) --> (vovocov) (v0 * v1) / (c * v2) 37753 | if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 37754 | { 37755 | const bool synthesis_result = 37756 | synthesize_sf4ext_expression:: 37757 | template compile<vtype, vtype, ctype, vtype>(expr_gen, "(t*t)/(t*t)", v0, v1, c, v2, result); 37758 | 37759 | exprtk_debug(("(v0 / c) * (v1 / v2) --> (vovocov) (v0 * v1) / (c * v2)\n")); 37760 | 37761 | return (synthesis_result) ? result : error_node(); 37762 | } 37763 | // (v0 / c) / (v1 / v2) --> (vovocov) (v0 * v2) / (c * v1) 37764 | if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 37765 | { 37766 | const bool synthesis_result = 37767 | synthesize_sf4ext_expression:: 37768 | template compile<vtype, vtype, ctype, vtype>(expr_gen, "(t*t)/(t*t)", v0, v2, c, v1, result); 37769 | 37770 | exprtk_debug(("(v0 / c) / (v1 / v2) --> (vovocov) (v0 * v2) / (c * v1)\n")); 37771 | 37772 | return (synthesis_result) ? result : error_node(); 37773 | } 37774 | } 37775 | 37776 | const bool synthesis_result = 37777 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 37778 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result); 37779 | 37780 | if (synthesis_result) 37781 | return result; 37782 | 37783 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37784 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37785 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 37786 | 37787 | if (!expr_gen.valid_operator(o0,f0)) 37788 | return error_node(); 37789 | else if (!expr_gen.valid_operator(o1,f1)) 37790 | return error_node(); 37791 | else if (!expr_gen.valid_operator(o2,f2)) 37792 | return error_node(); 37793 | else 37794 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2); 37795 | } 37796 | 37797 | static inline std::string id(expression_generator<Type>& expr_gen, 37798 | const details::operator_type o0, 37799 | const details::operator_type o1, 37800 | const details::operator_type o2) 37801 | { 37802 | return details::build_string() 37803 | << "(t" << expr_gen.to_str(o0) 37804 | << "t)" << expr_gen.to_str(o1) 37805 | << "(t" << expr_gen.to_str(o2) 37806 | << "t)" 37807 | } 37808 | }; 37809 | 37810 | struct synthesize_covovov_expression0 37811 | { 37812 | typedef typename covovov_t::type0 node_type; 37813 | typedef typename covovov_t::sf4_type sf4_type; 37814 | typedef typename node_type::T0 T0; 37815 | typedef typename node_type::T1 T1; 37816 | typedef typename node_type::T2 T2; 37817 | typedef typename node_type::T3 T3; 37818 | 37819 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37820 | const details::operator_type& operation, 37821 | expression_node_ptr (&branch)[2]) 37822 | { 37823 | // (c o0 v0) o1 (v1 o2 v2) 37824 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]); 37825 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]); 37826 | const Type c = cov->c (); 37827 | const Type& v0 = cov->v (); 37828 | const Type& v1 = vov->v0(); 37829 | const Type& v2 = vov->v1(); 37830 | const details::operator_type o0 = cov->operation(); 37831 | const details::operator_type o1 = operation; 37832 | const details::operator_type o2 = vov->operation(); 37833 | 37834 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37835 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37836 | 37837 | expression_node_ptr result = error_node(); 37838 | 37839 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37840 | { 37841 | // (c / v0) * (v1 / v2) --> (covovov) (c * v1) / (v0 * v2) 37842 | if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 37843 | { 37844 | const bool synthesis_result = 37845 | synthesize_sf4ext_expression:: 37846 | template compile<ctype, vtype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", c, v1, v0, v2, result); 37847 | 37848 | exprtk_debug(("(c / v0) * (v1 / v2) --> (covovov) (c * v1) / (v0 * v2)\n")); 37849 | 37850 | return (synthesis_result) ? result : error_node(); 37851 | } 37852 | // (c / v0) / (v1 / v2) --> (covovov) (c * v2) / (v0 * v1) 37853 | if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 37854 | { 37855 | const bool synthesis_result = 37856 | synthesize_sf4ext_expression:: 37857 | template compile<ctype, vtype, vtype, vtype>(expr_gen, "(t*t)/(t*t)", c, v2, v0, v1, result); 37858 | 37859 | exprtk_debug(("(c / v0) / (v1 / v2) --> (covovov) (c * v2) / (v0 * v1)\n")); 37860 | 37861 | return (synthesis_result) ? result : error_node(); 37862 | } 37863 | } 37864 | 37865 | const bool synthesis_result = 37866 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 37867 | (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result); 37868 | 37869 | if (synthesis_result) 37870 | return result; 37871 | 37872 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 37873 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 37874 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 37875 | 37876 | if (!expr_gen.valid_operator(o0,f0)) 37877 | return error_node(); 37878 | else if (!expr_gen.valid_operator(o1,f1)) 37879 | return error_node(); 37880 | else if (!expr_gen.valid_operator(o2,f2)) 37881 | return error_node(); 37882 | else 37883 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2); 37884 | } 37885 | 37886 | static inline std::string id(expression_generator<Type>& expr_gen, 37887 | const details::operator_type o0, 37888 | const details::operator_type o1, 37889 | const details::operator_type o2) 37890 | { 37891 | return details::build_string() 37892 | << "(t" << expr_gen.to_str(o0) 37893 | << "t)" << expr_gen.to_str(o1) 37894 | << "(t" << expr_gen.to_str(o2) 37895 | << "t)" 37896 | } 37897 | }; 37898 | 37899 | struct synthesize_covocov_expression0 37900 | { 37901 | typedef typename covocov_t::type0 node_type; 37902 | typedef typename covocov_t::sf4_type sf4_type; 37903 | typedef typename node_type::T0 T0; 37904 | typedef typename node_type::T1 T1; 37905 | typedef typename node_type::T2 T2; 37906 | typedef typename node_type::T3 T3; 37907 | 37908 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 37909 | const details::operator_type& operation, 37910 | expression_node_ptr (&branch)[2]) 37911 | { 37912 | // (c0 o0 v0) o1 (c1 o2 v1) 37913 | const details::cov_base_node<Type>* cov0 = static_cast<details::cov_base_node<Type>*>(branch[0]); 37914 | const details::cov_base_node<Type>* cov1 = static_cast<details::cov_base_node<Type>*>(branch[1]); 37915 | const Type c0 = cov0->c(); 37916 | const Type& v0 = cov0->v(); 37917 | const Type c1 = cov1->c(); 37918 | const Type& v1 = cov1->v(); 37919 | const details::operator_type o0 = cov0->operation(); 37920 | const details::operator_type o1 = operation; 37921 | const details::operator_type o2 = cov1->operation(); 37922 | 37923 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 37924 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 37925 | 37926 | expression_node_ptr result = error_node(); 37927 | 37928 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 37929 | { 37930 | // (c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1 37931 | if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2)) 37932 | { 37933 | const bool synthesis_result = 37934 | synthesize_sf3ext_expression:: 37935 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result); 37936 | 37937 | exprtk_debug(("(c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n")); 37938 | 37939 | return (synthesis_result) ? result : error_node(); 37940 | } 37941 | // (c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1 37942 | else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2)) 37943 | { 37944 | const bool synthesis_result = 37945 | synthesize_sf3ext_expression:: 37946 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result); 37947 | 37948 | exprtk_debug(("(c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n")); 37949 | 37950 | return (synthesis_result) ? result : error_node(); 37951 | } 37952 | // (c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1 37953 | else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2)) 37954 | { 37955 | const bool synthesis_result = 37956 | synthesize_sf3ext_expression:: 37957 | template compile<ctype, vtype, vtype>(expr_gen, "(t-t)+t", (c0 - c1), v0, v1, result); 37958 | 37959 | exprtk_debug(("(c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1\n")); 37960 | 37961 | return (synthesis_result) ? result : error_node(); 37962 | } 37963 | // (c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1 37964 | else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2)) 37965 | { 37966 | const bool synthesis_result = 37967 | synthesize_sf3ext_expression:: 37968 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result); 37969 | 37970 | exprtk_debug(("(c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n")); 37971 | 37972 | return (synthesis_result) ? result : error_node(); 37973 | } 37974 | // (c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1) 37975 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2)) 37976 | { 37977 | const bool synthesis_result = 37978 | synthesize_sf3ext_expression:: 37979 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result); 37980 | 37981 | exprtk_debug(("(c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1)\n")); 37982 | 37983 | return (synthesis_result) ? result : error_node(); 37984 | } 37985 | // (c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1) 37986 | else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 37987 | { 37988 | const bool synthesis_result = 37989 | synthesize_sf3ext_expression:: 37990 | template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", (c0 * c1), v0, v1, result); 37991 | 37992 | exprtk_debug(("(c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1)\n")); 37993 | 37994 | return (synthesis_result) ? result : error_node(); 37995 | } 37996 | // (c0 / v0) / (c1 / v1) --> (covov) ((c0 / c1) * v1) / v0 37997 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 37998 | { 37999 | const bool synthesis_result = 38000 | synthesize_sf3ext_expression:: 38001 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v1, v0, result); 38002 | 38003 | exprtk_debug(("(c0 / v0) / (c1 / v1) --> (covov) ((c0 / c1) * v1) / v0\n")); 38004 | 38005 | return (synthesis_result) ? result : error_node(); 38006 | } 38007 | // (c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1) 38008 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) 38009 | { 38010 | const bool synthesis_result = 38011 | synthesize_sf3ext_expression:: 38012 | template compile<ctype, vtype, vtype>(expr_gen, "t*(t*t)", (c0 / c1), v0, v1, result); 38013 | 38014 | exprtk_debug(("(c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n")); 38015 | 38016 | return (synthesis_result) ? result : error_node(); 38017 | } 38018 | // (c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1) 38019 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38020 | { 38021 | const bool synthesis_result = 38022 | synthesize_sf3ext_expression:: 38023 | template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", (c0 / c1), v0, v1, result); 38024 | 38025 | exprtk_debug(("(c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1)\n")); 38026 | 38027 | return (synthesis_result) ? result : error_node(); 38028 | } 38029 | // (c * v0) +/- (c * v1) --> (covov) c * (v0 +/- v1) 38030 | else if ( 38031 | (std::equal_to<T>()(c0,c1)) && 38032 | (details::e_mul == o0) && 38033 | (details::e_mul == o2) && 38034 | ( 38035 | (details::e_add == o1) || 38036 | (details::e_sub == o1) 38037 | ) 38038 | ) 38039 | { 38040 | std::string specfunc; 38041 | 38042 | switch (o1) 38043 | { 38044 | case details::e_add : specfunc = "t*(t+t)" break; 38045 | case details::e_sub : specfunc = "t*(t-t)" break; 38046 | default : return error_node(); 38047 | } 38048 | 38049 | const bool synthesis_result = 38050 | synthesize_sf3ext_expression:: 38051 | template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result); 38052 | 38053 | exprtk_debug(("(c * v0) +/- (c * v1) --> (covov) c * (v0 +/- v1)\n")); 38054 | 38055 | return (synthesis_result) ? result : error_node(); 38056 | } 38057 | } 38058 | 38059 | const bool synthesis_result = 38060 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38061 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result); 38062 | 38063 | if (synthesis_result) 38064 | return result; 38065 | 38066 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38067 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 38068 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 38069 | 38070 | if (!expr_gen.valid_operator(o0,f0)) 38071 | return error_node(); 38072 | else if (!expr_gen.valid_operator(o1,f1)) 38073 | return error_node(); 38074 | else if (!expr_gen.valid_operator(o2,f2)) 38075 | return error_node(); 38076 | else 38077 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2); 38078 | } 38079 | 38080 | static inline std::string id(expression_generator<Type>& expr_gen, 38081 | const details::operator_type o0, 38082 | const details::operator_type o1, 38083 | const details::operator_type o2) 38084 | { 38085 | return details::build_string() 38086 | << "(t" << expr_gen.to_str(o0) 38087 | << "t)" << expr_gen.to_str(o1) 38088 | << "(t" << expr_gen.to_str(o2) 38089 | << "t)" 38090 | } 38091 | }; 38092 | 38093 | struct synthesize_vocovoc_expression0 38094 | { 38095 | typedef typename vocovoc_t::type0 node_type; 38096 | typedef typename vocovoc_t::sf4_type sf4_type; 38097 | typedef typename node_type::T0 T0; 38098 | typedef typename node_type::T1 T1; 38099 | typedef typename node_type::T2 T2; 38100 | typedef typename node_type::T3 T3; 38101 | 38102 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38103 | const details::operator_type& operation, 38104 | expression_node_ptr (&branch)[2]) 38105 | { 38106 | // (v0 o0 c0) o1 (v1 o2 c1) 38107 | const details::voc_base_node<Type>* voc0 = static_cast<details::voc_base_node<Type>*>(branch[0]); 38108 | const details::voc_base_node<Type>* voc1 = static_cast<details::voc_base_node<Type>*>(branch[1]); 38109 | const Type c0 = voc0->c(); 38110 | const Type& v0 = voc0->v(); 38111 | const Type c1 = voc1->c(); 38112 | const Type& v1 = voc1->v(); 38113 | const details::operator_type o0 = voc0->operation(); 38114 | const details::operator_type o1 = operation; 38115 | const details::operator_type o2 = voc1->operation(); 38116 | 38117 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 38118 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38119 | 38120 | expression_node_ptr result = error_node(); 38121 | 38122 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 38123 | { 38124 | // (v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1 38125 | if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2)) 38126 | { 38127 | const bool synthesis_result = 38128 | synthesize_sf3ext_expression:: 38129 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result); 38130 | 38131 | exprtk_debug(("(v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n")); 38132 | 38133 | return (synthesis_result) ? result : error_node(); 38134 | } 38135 | // (v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1 38136 | else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2)) 38137 | { 38138 | const bool synthesis_result = 38139 | synthesize_sf3ext_expression:: 38140 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result); 38141 | 38142 | exprtk_debug(("(v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n")); 38143 | 38144 | return (synthesis_result) ? result : error_node(); 38145 | } 38146 | // (v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1 38147 | else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2)) 38148 | { 38149 | const bool synthesis_result = 38150 | synthesize_sf3ext_expression:: 38151 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c1 - c0), v0, v1, result); 38152 | 38153 | exprtk_debug(("(v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1\n")); 38154 | 38155 | return (synthesis_result) ? result : error_node(); 38156 | } 38157 | // (v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1 38158 | else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2)) 38159 | { 38160 | const bool synthesis_result = 38161 | synthesize_sf3ext_expression:: 38162 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result); 38163 | 38164 | exprtk_debug(("(v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n")); 38165 | 38166 | return (synthesis_result) ? result : error_node(); 38167 | } 38168 | // (v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1) 38169 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38170 | { 38171 | const bool synthesis_result = 38172 | synthesize_sf3ext_expression:: 38173 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result); 38174 | 38175 | exprtk_debug(("(v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n")); 38176 | 38177 | return (synthesis_result) ? result : error_node(); 38178 | } 38179 | // (v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1 38180 | else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 38181 | { 38182 | const bool synthesis_result = 38183 | synthesize_sf3ext_expression:: 38184 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", Type(1) / (c0 * c1), v0, v1, result); 38185 | 38186 | exprtk_debug(("(v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1\n")); 38187 | 38188 | return (synthesis_result) ? result : error_node(); 38189 | } 38190 | // (v0 / c0) / (v1 / c1) --> (covov) ((c1 / c0) * v0) / v1 38191 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 38192 | { 38193 | const bool synthesis_result = 38194 | synthesize_sf3ext_expression:: 38195 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c1 / c0), v0, v1, result); 38196 | 38197 | exprtk_debug(("(v0 / c0) / (v1 / c1) --> (covov) ((c1 / c0) * v0) / v1\n")); 38198 | 38199 | return (synthesis_result) ? result : error_node(); 38200 | } 38201 | // (v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1) 38202 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) 38203 | { 38204 | const bool synthesis_result = 38205 | synthesize_sf3ext_expression:: 38206 | template compile<ctype, vtype, vtype>(expr_gen, "t*(t/t)", (c0 * c1), v0, v1, result); 38207 | 38208 | exprtk_debug(("(v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n")); 38209 | 38210 | return (synthesis_result) ? result : error_node(); 38211 | } 38212 | // (v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1 38213 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38214 | { 38215 | const bool synthesis_result = 38216 | synthesize_sf3ext_expression:: 38217 | template compile<ctype, vtype, vtype>(expr_gen, "t*(t/t)", Type(1) / (c0 * c1), v0, v1, result); 38218 | 38219 | exprtk_debug(("(v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1\n")); 38220 | 38221 | return (synthesis_result) ? result : error_node(); 38222 | } 38223 | // (v0 / c0) * (v1 + c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 + c1) 38224 | else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_add == o2)) 38225 | { 38226 | const bool synthesis_result = 38227 | synthesize_sf4ext_expression:: 38228 | template compile<vtype, ctype, vtype, ctype>(expr_gen, "(t*t)*(t+t)", v0, T(1) / c0, v1, c1, result); 38229 | 38230 | exprtk_debug(("(v0 / c0) * (v1 + c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 + c1)\n")); 38231 | 38232 | return (synthesis_result) ? result : error_node(); 38233 | } 38234 | // (v0 / c0) * (v1 - c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 - c1) 38235 | else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_sub == o2)) 38236 | { 38237 | const bool synthesis_result = 38238 | synthesize_sf4ext_expression:: 38239 | template compile<vtype, ctype, vtype, ctype>(expr_gen, "(t*t)*(t-t)", v0, T(1) / c0, v1, c1, result); 38240 | 38241 | exprtk_debug(("(v0 / c0) * (v1 - c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 - c1)\n")); 38242 | 38243 | return (synthesis_result) ? result : error_node(); 38244 | } 38245 | // (v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1) 38246 | else if ( 38247 | (std::equal_to<T>()(c0,c1)) && 38248 | (details::e_mul == o0) && 38249 | (details::e_mul == o2) && 38250 | ( 38251 | (details::e_add == o1) || 38252 | (details::e_sub == o1) 38253 | ) 38254 | ) 38255 | { 38256 | std::string specfunc; 38257 | 38258 | switch (o1) 38259 | { 38260 | case details::e_add : specfunc = "t*(t+t)" break; 38261 | case details::e_sub : specfunc = "t*(t-t)" break; 38262 | default : return error_node(); 38263 | } 38264 | 38265 | const bool synthesis_result = 38266 | synthesize_sf3ext_expression:: 38267 | template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result); 38268 | 38269 | exprtk_debug(("(v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n")); 38270 | 38271 | return (synthesis_result) ? result : error_node(); 38272 | } 38273 | // (v0 / c) +/- (v1 / c) --> (vovoc) (v0 +/- v1) / c 38274 | else if ( 38275 | (std::equal_to<T>()(c0,c1)) && 38276 | (details::e_div == o0) && 38277 | (details::e_div == o2) && 38278 | ( 38279 | (details::e_add == o1) || 38280 | (details::e_sub == o1) 38281 | ) 38282 | ) 38283 | { 38284 | std::string specfunc; 38285 | 38286 | switch (o1) 38287 | { 38288 | case details::e_add : specfunc = "(t+t)/t" break; 38289 | case details::e_sub : specfunc = "(t-t)/t" break; 38290 | default : return error_node(); 38291 | } 38292 | 38293 | const bool synthesis_result = 38294 | synthesize_sf3ext_expression:: 38295 | template compile<vtype, vtype, ctype>(expr_gen, specfunc, v0, v1, c0, result); 38296 | 38297 | exprtk_debug(("(v0 / c) +/- (v1 / c) --> (vovoc) (v0 +/- v1) / c\n")); 38298 | 38299 | return (synthesis_result) ? result : error_node(); 38300 | } 38301 | } 38302 | 38303 | const bool synthesis_result = 38304 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38305 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result); 38306 | 38307 | if (synthesis_result) 38308 | return result; 38309 | 38310 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38311 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 38312 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 38313 | 38314 | if (!expr_gen.valid_operator(o0,f0)) 38315 | return error_node(); 38316 | else if (!expr_gen.valid_operator(o1,f1)) 38317 | return error_node(); 38318 | else if (!expr_gen.valid_operator(o2,f2)) 38319 | return error_node(); 38320 | else 38321 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2); 38322 | } 38323 | 38324 | static inline std::string id(expression_generator<Type>& expr_gen, 38325 | const details::operator_type o0, 38326 | const details::operator_type o1, 38327 | const details::operator_type o2) 38328 | { 38329 | return details::build_string() 38330 | << "(t" << expr_gen.to_str(o0) 38331 | << "t)" << expr_gen.to_str(o1) 38332 | << "(t" << expr_gen.to_str(o2) 38333 | << "t)" 38334 | } 38335 | }; 38336 | 38337 | struct synthesize_covovoc_expression0 38338 | { 38339 | typedef typename covovoc_t::type0 node_type; 38340 | typedef typename covovoc_t::sf4_type sf4_type; 38341 | typedef typename node_type::T0 T0; 38342 | typedef typename node_type::T1 T1; 38343 | typedef typename node_type::T2 T2; 38344 | typedef typename node_type::T3 T3; 38345 | 38346 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38347 | const details::operator_type& operation, 38348 | expression_node_ptr (&branch)[2]) 38349 | { 38350 | // (c0 o0 v0) o1 (v1 o2 c1) 38351 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]); 38352 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]); 38353 | const Type c0 = cov->c(); 38354 | const Type& v0 = cov->v(); 38355 | const Type c1 = voc->c(); 38356 | const Type& v1 = voc->v(); 38357 | const details::operator_type o0 = cov->operation(); 38358 | const details::operator_type o1 = operation; 38359 | const details::operator_type o2 = voc->operation(); 38360 | 38361 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 38362 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38363 | 38364 | expression_node_ptr result = error_node(); 38365 | 38366 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 38367 | { 38368 | // (c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1 38369 | if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2)) 38370 | { 38371 | const bool synthesis_result = 38372 | synthesize_sf3ext_expression:: 38373 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result); 38374 | 38375 | exprtk_debug(("(c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n")); 38376 | 38377 | return (synthesis_result) ? result : error_node(); 38378 | } 38379 | // (c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1 38380 | else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2)) 38381 | { 38382 | const bool synthesis_result = 38383 | synthesize_sf3ext_expression:: 38384 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result); 38385 | 38386 | exprtk_debug(("(c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n")); 38387 | 38388 | return (synthesis_result) ? result : error_node(); 38389 | } 38390 | // (c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1 38391 | else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2)) 38392 | { 38393 | const bool synthesis_result = 38394 | synthesize_sf3ext_expression:: 38395 | template compile<ctype, vtype, vtype>(expr_gen, "t-(t+t)", (c0 + c1), v0, v1, result); 38396 | 38397 | exprtk_debug(("(c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1\n")); 38398 | 38399 | return (synthesis_result) ? result : error_node(); 38400 | } 38401 | // (c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1 38402 | else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2)) 38403 | { 38404 | const bool synthesis_result = 38405 | synthesize_sf3ext_expression:: 38406 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result); 38407 | 38408 | exprtk_debug(("(c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n")); 38409 | 38410 | return (synthesis_result) ? result : error_node(); 38411 | } 38412 | // (c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1) 38413 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38414 | { 38415 | const bool synthesis_result = 38416 | synthesize_sf3ext_expression:: 38417 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result); 38418 | 38419 | exprtk_debug(("(c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n")); 38420 | 38421 | return (synthesis_result) ? result : error_node(); 38422 | } 38423 | // (c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0) 38424 | else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 38425 | { 38426 | const bool synthesis_result = 38427 | synthesize_sf3ext_expression:: 38428 | template compile<ctype, vtype, vtype>(expr_gen, "t*(t/t)", (c0 / c1), v1, v0, result); 38429 | 38430 | exprtk_debug(("(c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0)\n")); 38431 | 38432 | return (synthesis_result) ? result : error_node(); 38433 | } 38434 | // (c0 / v0) / (v1 / c1) --> (covov) (c0 * c1) / (v0 * v1) 38435 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 38436 | { 38437 | const bool synthesis_result = 38438 | synthesize_sf3ext_expression:: 38439 | template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", (c0 * c1), v0, v1, result); 38440 | 38441 | exprtk_debug(("(c0 / v0) / (v1 / c1) --> (covov) (c0 * c1) / (v0 * v1)\n")); 38442 | 38443 | return (synthesis_result) ? result : error_node(); 38444 | } 38445 | // (c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1) 38446 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) 38447 | { 38448 | const bool synthesis_result = 38449 | synthesize_sf3ext_expression:: 38450 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 * c1), v0, v1, result); 38451 | 38452 | exprtk_debug(("(c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n")); 38453 | 38454 | return (synthesis_result) ? result : error_node(); 38455 | } 38456 | // (c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1) 38457 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38458 | { 38459 | const bool synthesis_result = 38460 | synthesize_sf3ext_expression:: 38461 | template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", (c0 / c1), v0, v1, result); 38462 | 38463 | exprtk_debug(("(c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1)\n")); 38464 | 38465 | return (synthesis_result) ? result : error_node(); 38466 | } 38467 | // (c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1) 38468 | else if ( 38469 | (std::equal_to<T>()(c0,c1)) && 38470 | (details::e_mul == o0) && 38471 | (details::e_mul == o2) && 38472 | ( 38473 | (details::e_add == o1) || 38474 | (details::e_sub == o1) 38475 | ) 38476 | ) 38477 | { 38478 | std::string specfunc; 38479 | 38480 | switch (o1) 38481 | { 38482 | case details::e_add : specfunc = "t*(t+t)" break; 38483 | case details::e_sub : specfunc = "t*(t-t)" break; 38484 | default : return error_node(); 38485 | } 38486 | 38487 | const bool synthesis_result = 38488 | synthesize_sf3ext_expression:: 38489 | template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result); 38490 | 38491 | exprtk_debug(("(c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n")); 38492 | 38493 | return (synthesis_result) ? result : error_node(); 38494 | } 38495 | } 38496 | 38497 | const bool synthesis_result = 38498 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38499 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result); 38500 | 38501 | if (synthesis_result) 38502 | return result; 38503 | 38504 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38505 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 38506 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 38507 | 38508 | if (!expr_gen.valid_operator(o0,f0)) 38509 | return error_node(); 38510 | else if (!expr_gen.valid_operator(o1,f1)) 38511 | return error_node(); 38512 | else if (!expr_gen.valid_operator(o2,f2)) 38513 | return error_node(); 38514 | else 38515 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2); 38516 | } 38517 | 38518 | static inline std::string id(expression_generator<Type>& expr_gen, 38519 | const details::operator_type o0, 38520 | const details::operator_type o1, 38521 | const details::operator_type o2) 38522 | { 38523 | return details::build_string() 38524 | << "(t" << expr_gen.to_str(o0) 38525 | << "t)" << expr_gen.to_str(o1) 38526 | << "(t" << expr_gen.to_str(o2) 38527 | << "t)" 38528 | } 38529 | }; 38530 | 38531 | struct synthesize_vococov_expression0 38532 | { 38533 | typedef typename vococov_t::type0 node_type; 38534 | typedef typename vococov_t::sf4_type sf4_type; 38535 | typedef typename node_type::T0 T0; 38536 | typedef typename node_type::T1 T1; 38537 | typedef typename node_type::T2 T2; 38538 | typedef typename node_type::T3 T3; 38539 | 38540 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38541 | const details::operator_type& operation, 38542 | expression_node_ptr (&branch)[2]) 38543 | { 38544 | // (v0 o0 c0) o1 (c1 o2 v1) 38545 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]); 38546 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]); 38547 | const Type c0 = voc->c(); 38548 | const Type& v0 = voc->v(); 38549 | const Type c1 = cov->c(); 38550 | const Type& v1 = cov->v(); 38551 | const details::operator_type o0 = voc->operation(); 38552 | const details::operator_type o1 = operation; 38553 | const details::operator_type o2 = cov->operation(); 38554 | 38555 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 38556 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38557 | 38558 | expression_node_ptr result = error_node(); 38559 | 38560 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) 38561 | { 38562 | // (v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1 38563 | if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2)) 38564 | { 38565 | const bool synthesis_result = 38566 | synthesize_sf3ext_expression:: 38567 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result); 38568 | 38569 | exprtk_debug(("(v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n")); 38570 | 38571 | return (synthesis_result) ? result : error_node(); 38572 | } 38573 | // (v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1 38574 | else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2)) 38575 | { 38576 | const bool synthesis_result = 38577 | synthesize_sf3ext_expression:: 38578 | template compile<ctype, vtype, vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result); 38579 | 38580 | exprtk_debug(("(v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n")); 38581 | 38582 | return (synthesis_result) ? result : error_node(); 38583 | } 38584 | // (v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0) 38585 | else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2)) 38586 | { 38587 | const bool synthesis_result = 38588 | synthesize_sf3ext_expression:: 38589 | template compile<vtype, vtype, ctype>(expr_gen, "(t+t)-t", v0, v1, (c1 + c0), result); 38590 | 38591 | exprtk_debug(("(v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0)\n")); 38592 | 38593 | return (synthesis_result) ? result : error_node(); 38594 | } 38595 | // (v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1 38596 | else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2)) 38597 | { 38598 | const bool synthesis_result = 38599 | synthesize_sf3ext_expression:: 38600 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result); 38601 | 38602 | exprtk_debug(("(v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n")); 38603 | 38604 | return (synthesis_result) ? result : error_node(); 38605 | } 38606 | // (v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1) 38607 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38608 | { 38609 | const bool synthesis_result = 38610 | synthesize_sf3ext_expression:: 38611 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result); 38612 | 38613 | exprtk_debug(("(v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1)\n")); 38614 | 38615 | return (synthesis_result) ? result : error_node(); 38616 | } 38617 | // (v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1) 38618 | else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) 38619 | { 38620 | const bool synthesis_result = 38621 | synthesize_sf3ext_expression:: 38622 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", (c1 / c0), v0, v1, result); 38623 | 38624 | exprtk_debug(("(v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1)\n")); 38625 | 38626 | return (synthesis_result) ? result : error_node(); 38627 | } 38628 | // (v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1) 38629 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) 38630 | { 38631 | const bool synthesis_result = 38632 | synthesize_sf3ext_expression:: 38633 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)*t", (c0 / c1), v0, v1, result); 38634 | 38635 | exprtk_debug(("(v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n")); 38636 | 38637 | return (synthesis_result) ? result : error_node(); 38638 | } 38639 | // (v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1) 38640 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2)) 38641 | { 38642 | const bool synthesis_result = 38643 | synthesize_sf3ext_expression:: 38644 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", Type(1) / (c0 * c1), v0, v1, result); 38645 | 38646 | exprtk_debug(("(v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1)\n")); 38647 | 38648 | return (synthesis_result) ? result : error_node(); 38649 | } 38650 | // (v0 / c0) / (c1 / v1) --> (vovoc) (v0 * v1) * (1 / (c0 * c1)) 38651 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) 38652 | { 38653 | const bool synthesis_result = 38654 | synthesize_sf3ext_expression:: 38655 | template compile<vtype, vtype, ctype>(expr_gen, "(t*t)*t", v0, v1, Type(1) / (c0 * c1), result); 38656 | 38657 | exprtk_debug(("(v0 / c0) / (c1 / v1) --> (vovoc) (v0 * v1) * (1 / (c0 * c1))\n")); 38658 | 38659 | return (synthesis_result) ? result : error_node(); 38660 | } 38661 | // (v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1) 38662 | else if ( 38663 | (std::equal_to<T>()(c0,c1)) && 38664 | (details::e_mul == o0) && 38665 | (details::e_mul == o2) && 38666 | ( 38667 | (details::e_add == o1) || (details::e_sub == o1) 38668 | ) 38669 | ) 38670 | { 38671 | std::string specfunc; 38672 | 38673 | switch (o1) 38674 | { 38675 | case details::e_add : specfunc = "t*(t+t)" break; 38676 | case details::e_sub : specfunc = "t*(t-t)" break; 38677 | default : return error_node(); 38678 | } 38679 | 38680 | const bool synthesis_result = 38681 | synthesize_sf3ext_expression:: 38682 | template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result); 38683 | 38684 | exprtk_debug(("(v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1)\n")); 38685 | 38686 | return (synthesis_result) ? result : error_node(); 38687 | } 38688 | } 38689 | 38690 | const bool synthesis_result = 38691 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38692 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result); 38693 | 38694 | if (synthesis_result) 38695 | return result; 38696 | 38697 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38698 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); 38699 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 38700 | 38701 | if (!expr_gen.valid_operator(o0,f0)) 38702 | return error_node(); 38703 | else if (!expr_gen.valid_operator(o1,f1)) 38704 | return error_node(); 38705 | else if (!expr_gen.valid_operator(o2,f2)) 38706 | return error_node(); 38707 | else 38708 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2); 38709 | } 38710 | 38711 | static inline std::string id(expression_generator<Type>& expr_gen, 38712 | const details::operator_type o0, 38713 | const details::operator_type o1, 38714 | const details::operator_type o2) 38715 | { 38716 | return details::build_string() 38717 | << "(t" << expr_gen.to_str(o0) 38718 | << "t)" << expr_gen.to_str(o1) 38719 | << "(t" << expr_gen.to_str(o2) 38720 | << "t)" 38721 | } 38722 | }; 38723 | 38724 | struct synthesize_vovovov_expression1 38725 | { 38726 | typedef typename vovovov_t::type1 node_type; 38727 | typedef typename vovovov_t::sf4_type sf4_type; 38728 | typedef typename node_type::T0 T0; 38729 | typedef typename node_type::T1 T1; 38730 | typedef typename node_type::T2 T2; 38731 | typedef typename node_type::T3 T3; 38732 | 38733 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38734 | const details::operator_type& operation, 38735 | expression_node_ptr (&branch)[2]) 38736 | { 38737 | // v0 o0 (v1 o1 (v2 o2 v3)) 38738 | typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t; 38739 | 38740 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]); 38741 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 38742 | const Type& v1 = vovov->t0(); 38743 | const Type& v2 = vovov->t1(); 38744 | const Type& v3 = vovov->t2(); 38745 | const details::operator_type o0 = operation; 38746 | const details::operator_type o1 = expr_gen.get_operator(vovov->f0()); 38747 | const details::operator_type o2 = expr_gen.get_operator(vovov->f1()); 38748 | 38749 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38750 | binary_functor_t f1 = vovov->f0(); 38751 | binary_functor_t f2 = vovov->f1(); 38752 | 38753 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38754 | 38755 | expression_node_ptr result = error_node(); 38756 | 38757 | const bool synthesis_result = 38758 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38759 | (expr_gen,id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result); 38760 | 38761 | if (synthesis_result) 38762 | return result; 38763 | else if (!expr_gen.valid_operator(o0,f0)) 38764 | return error_node(); 38765 | 38766 | exprtk_debug(("v0 o0 (v1 o1 (v2 o2 v3))\n")); 38767 | 38768 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2); 38769 | } 38770 | 38771 | static inline std::string id(expression_generator<Type>& expr_gen, 38772 | const details::operator_type o0, 38773 | const details::operator_type o1, 38774 | const details::operator_type o2) 38775 | { 38776 | return details::build_string() 38777 | << "t" << expr_gen.to_str(o0) 38778 | << "(t" << expr_gen.to_str(o1) 38779 | << "(t" << expr_gen.to_str(o2) 38780 | << "t))" 38781 | } 38782 | }; 38783 | 38784 | struct synthesize_vovovoc_expression1 38785 | { 38786 | typedef typename vovovoc_t::type1 node_type; 38787 | typedef typename vovovoc_t::sf4_type sf4_type; 38788 | typedef typename node_type::T0 T0; 38789 | typedef typename node_type::T1 T1; 38790 | typedef typename node_type::T2 T2; 38791 | typedef typename node_type::T3 T3; 38792 | 38793 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38794 | const details::operator_type& operation, 38795 | expression_node_ptr (&branch)[2]) 38796 | { 38797 | // v0 o0 (v1 o1 (v2 o2 c)) 38798 | typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t; 38799 | 38800 | const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]); 38801 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 38802 | const Type& v1 = vovoc->t0(); 38803 | const Type& v2 = vovoc->t1(); 38804 | const Type c = vovoc->t2(); 38805 | const details::operator_type o0 = operation; 38806 | const details::operator_type o1 = expr_gen.get_operator(vovoc->f0()); 38807 | const details::operator_type o2 = expr_gen.get_operator(vovoc->f1()); 38808 | 38809 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38810 | binary_functor_t f1 = vovoc->f0(); 38811 | binary_functor_t f2 = vovoc->f1(); 38812 | 38813 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38814 | 38815 | expression_node_ptr result = error_node(); 38816 | 38817 | const bool synthesis_result = 38818 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38819 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result); 38820 | 38821 | if (synthesis_result) 38822 | return result; 38823 | else if (!expr_gen.valid_operator(o0,f0)) 38824 | return error_node(); 38825 | 38826 | exprtk_debug(("v0 o0 (v1 o1 (v2 o2 c))\n")); 38827 | 38828 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2); 38829 | } 38830 | 38831 | static inline std::string id(expression_generator<Type>& expr_gen, 38832 | const details::operator_type o0, 38833 | const details::operator_type o1, 38834 | const details::operator_type o2) 38835 | { 38836 | return details::build_string() 38837 | << "t" << expr_gen.to_str(o0) 38838 | << "(t" << expr_gen.to_str(o1) 38839 | << "(t" << expr_gen.to_str(o2) 38840 | << "t))" 38841 | } 38842 | }; 38843 | 38844 | struct synthesize_vovocov_expression1 38845 | { 38846 | typedef typename vovocov_t::type1 node_type; 38847 | typedef typename vovocov_t::sf4_type sf4_type; 38848 | typedef typename node_type::T0 T0; 38849 | typedef typename node_type::T1 T1; 38850 | typedef typename node_type::T2 T2; 38851 | typedef typename node_type::T3 T3; 38852 | 38853 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38854 | const details::operator_type& operation, 38855 | expression_node_ptr (&branch)[2]) 38856 | { 38857 | // v0 o0 (v1 o1 (c o2 v2)) 38858 | typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t; 38859 | 38860 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]); 38861 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 38862 | const Type& v1 = vocov->t0(); 38863 | const Type c = vocov->t1(); 38864 | const Type& v2 = vocov->t2(); 38865 | const details::operator_type o0 = operation; 38866 | const details::operator_type o1 = expr_gen.get_operator(vocov->f0()); 38867 | const details::operator_type o2 = expr_gen.get_operator(vocov->f1()); 38868 | 38869 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38870 | binary_functor_t f1 = vocov->f0(); 38871 | binary_functor_t f2 = vocov->f1(); 38872 | 38873 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38874 | 38875 | expression_node_ptr result = error_node(); 38876 | 38877 | const bool synthesis_result = 38878 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38879 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result); 38880 | 38881 | if (synthesis_result) 38882 | return result; 38883 | if (!expr_gen.valid_operator(o0,f0)) 38884 | return error_node(); 38885 | 38886 | exprtk_debug(("v0 o0 (v1 o1 (c o2 v2))\n")); 38887 | 38888 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2); 38889 | } 38890 | 38891 | static inline std::string id(expression_generator<Type>& expr_gen, 38892 | const details::operator_type o0, 38893 | const details::operator_type o1, 38894 | const details::operator_type o2) 38895 | { 38896 | return details::build_string() 38897 | << "t" << expr_gen.to_str(o0) 38898 | << "(t" << expr_gen.to_str(o1) 38899 | << "(t" << expr_gen.to_str(o2) 38900 | << "t))" 38901 | } 38902 | }; 38903 | 38904 | struct synthesize_vocovov_expression1 38905 | { 38906 | typedef typename vocovov_t::type1 node_type; 38907 | typedef typename vocovov_t::sf4_type sf4_type; 38908 | typedef typename node_type::T0 T0; 38909 | typedef typename node_type::T1 T1; 38910 | typedef typename node_type::T2 T2; 38911 | typedef typename node_type::T3 T3; 38912 | 38913 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38914 | const details::operator_type& operation, 38915 | expression_node_ptr (&branch)[2]) 38916 | { 38917 | // v0 o0 (c o1 (v1 o2 v2)) 38918 | typedef typename synthesize_covov_expression1::node_type lcl_covov_t; 38919 | 38920 | const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[1]); 38921 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 38922 | const Type c = covov->t0(); 38923 | const Type& v1 = covov->t1(); 38924 | const Type& v2 = covov->t2(); 38925 | const details::operator_type o0 = operation; 38926 | const details::operator_type o1 = expr_gen.get_operator(covov->f0()); 38927 | const details::operator_type o2 = expr_gen.get_operator(covov->f1()); 38928 | 38929 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38930 | binary_functor_t f1 = covov->f0(); 38931 | binary_functor_t f2 = covov->f1(); 38932 | 38933 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38934 | 38935 | expression_node_ptr result = error_node(); 38936 | 38937 | const bool synthesis_result = 38938 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 38939 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result); 38940 | 38941 | if (synthesis_result) 38942 | return result; 38943 | else if (!expr_gen.valid_operator(o0,f0)) 38944 | return error_node(); 38945 | 38946 | exprtk_debug(("v0 o0 (c o1 (v1 o2 v2))\n")); 38947 | 38948 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2); 38949 | } 38950 | 38951 | static inline std::string id(expression_generator<Type>& expr_gen, 38952 | const details::operator_type o0, 38953 | const details::operator_type o1, 38954 | const details::operator_type o2) 38955 | { 38956 | return details::build_string() 38957 | << "t" << expr_gen.to_str(o0) 38958 | << "(t" << expr_gen.to_str(o1) 38959 | << "(t" << expr_gen.to_str(o2) 38960 | << "t))" 38961 | } 38962 | }; 38963 | 38964 | struct synthesize_covovov_expression1 38965 | { 38966 | typedef typename covovov_t::type1 node_type; 38967 | typedef typename covovov_t::sf4_type sf4_type; 38968 | typedef typename node_type::T0 T0; 38969 | typedef typename node_type::T1 T1; 38970 | typedef typename node_type::T2 T2; 38971 | typedef typename node_type::T3 T3; 38972 | 38973 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 38974 | const details::operator_type& operation, 38975 | expression_node_ptr (&branch)[2]) 38976 | { 38977 | // c o0 (v0 o1 (v1 o2 v2)) 38978 | typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t; 38979 | 38980 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]); 38981 | const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); 38982 | const Type& v0 = vovov->t0(); 38983 | const Type& v1 = vovov->t1(); 38984 | const Type& v2 = vovov->t2(); 38985 | const details::operator_type o0 = operation; 38986 | const details::operator_type o1 = expr_gen.get_operator(vovov->f0()); 38987 | const details::operator_type o2 = expr_gen.get_operator(vovov->f1()); 38988 | 38989 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 38990 | binary_functor_t f1 = vovov->f0(); 38991 | binary_functor_t f2 = vovov->f1(); 38992 | 38993 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 38994 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 38995 | 38996 | expression_node_ptr result = error_node(); 38997 | 38998 | const bool synthesis_result = 38999 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39000 | (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result); 39001 | 39002 | if (synthesis_result) 39003 | return result; 39004 | if (!expr_gen.valid_operator(o0,f0)) 39005 | return error_node(); 39006 | 39007 | exprtk_debug(("c o0 (v0 o1 (v1 o2 v2))\n")); 39008 | 39009 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2); 39010 | } 39011 | 39012 | static inline std::string id(expression_generator<Type>& expr_gen, 39013 | const details::operator_type o0, 39014 | const details::operator_type o1, 39015 | const details::operator_type o2) 39016 | { 39017 | return details::build_string() 39018 | << "t" << expr_gen.to_str(o0) 39019 | << "(t" << expr_gen.to_str(o1) 39020 | << "(t" << expr_gen.to_str(o2) 39021 | << "t))" 39022 | } 39023 | }; 39024 | 39025 | struct synthesize_covocov_expression1 39026 | { 39027 | typedef typename covocov_t::type1 node_type; 39028 | typedef typename covocov_t::sf4_type sf4_type; 39029 | typedef typename node_type::T0 T0; 39030 | typedef typename node_type::T1 T1; 39031 | typedef typename node_type::T2 T2; 39032 | typedef typename node_type::T3 T3; 39033 | 39034 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39035 | const details::operator_type& operation, 39036 | expression_node_ptr (&branch)[2]) 39037 | { 39038 | // c0 o0 (v0 o1 (c1 o2 v1)) 39039 | typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t; 39040 | 39041 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]); 39042 | const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); 39043 | const Type& v0 = vocov->t0(); 39044 | const Type c1 = vocov->t1(); 39045 | const Type& v1 = vocov->t2(); 39046 | const details::operator_type o0 = operation; 39047 | const details::operator_type o1 = expr_gen.get_operator(vocov->f0()); 39048 | const details::operator_type o2 = expr_gen.get_operator(vocov->f1()); 39049 | 39050 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39051 | binary_functor_t f1 = vocov->f0(); 39052 | binary_functor_t f2 = vocov->f1(); 39053 | 39054 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39055 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39056 | 39057 | expression_node_ptr result = error_node(); 39058 | 39059 | const bool synthesis_result = 39060 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39061 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result); 39062 | 39063 | if (synthesis_result) 39064 | return result; 39065 | else if (!expr_gen.valid_operator(o0,f0)) 39066 | return error_node(); 39067 | 39068 | exprtk_debug(("c0 o0 (v0 o1 (c1 o2 v1))\n")); 39069 | 39070 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2); 39071 | } 39072 | 39073 | static inline std::string id(expression_generator<Type>& expr_gen, 39074 | const details::operator_type o0, 39075 | const details::operator_type o1, 39076 | const details::operator_type o2) 39077 | { 39078 | return details::build_string() 39079 | << "t" << expr_gen.to_str(o0) 39080 | << "(t" << expr_gen.to_str(o1) 39081 | << "(t" << expr_gen.to_str(o2) 39082 | << "t))" 39083 | } 39084 | }; 39085 | 39086 | struct synthesize_vocovoc_expression1 39087 | { 39088 | typedef typename vocovoc_t::type1 node_type; 39089 | typedef typename vocovoc_t::sf4_type sf4_type; 39090 | typedef typename node_type::T0 T0; 39091 | typedef typename node_type::T1 T1; 39092 | typedef typename node_type::T2 T2; 39093 | typedef typename node_type::T3 T3; 39094 | 39095 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39096 | const details::operator_type& operation, 39097 | expression_node_ptr (&branch)[2]) 39098 | { 39099 | // v0 o0 (c0 o1 (v1 o2 c2)) 39100 | typedef typename synthesize_covoc_expression1::node_type lcl_covoc_t; 39101 | 39102 | const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[1]); 39103 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39104 | const Type c0 = covoc->t0(); 39105 | const Type& v1 = covoc->t1(); 39106 | const Type c1 = covoc->t2(); 39107 | const details::operator_type o0 = operation; 39108 | const details::operator_type o1 = expr_gen.get_operator(covoc->f0()); 39109 | const details::operator_type o2 = expr_gen.get_operator(covoc->f1()); 39110 | 39111 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39112 | binary_functor_t f1 = covoc->f0(); 39113 | binary_functor_t f2 = covoc->f1(); 39114 | 39115 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39116 | 39117 | expression_node_ptr result = error_node(); 39118 | 39119 | const bool synthesis_result = 39120 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39121 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result); 39122 | 39123 | if (synthesis_result) 39124 | return result; 39125 | else if (!expr_gen.valid_operator(o0,f0)) 39126 | return error_node(); 39127 | 39128 | exprtk_debug(("v0 o0 (c0 o1 (v1 o2 c2))\n")); 39129 | 39130 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2); 39131 | } 39132 | 39133 | static inline std::string id(expression_generator<Type>& expr_gen, 39134 | const details::operator_type o0, 39135 | const details::operator_type o1, 39136 | const details::operator_type o2) 39137 | { 39138 | return details::build_string() 39139 | << "t" << expr_gen.to_str(o0) 39140 | << "(t" << expr_gen.to_str(o1) 39141 | << "(t" << expr_gen.to_str(o2) 39142 | << "t))" 39143 | } 39144 | }; 39145 | 39146 | struct synthesize_covovoc_expression1 39147 | { 39148 | typedef typename covovoc_t::type1 node_type; 39149 | typedef typename covovoc_t::sf4_type sf4_type; 39150 | typedef typename node_type::T0 T0; 39151 | typedef typename node_type::T1 T1; 39152 | typedef typename node_type::T2 T2; 39153 | typedef typename node_type::T3 T3; 39154 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39155 | const details::operator_type& operation, 39156 | expression_node_ptr (&branch)[2]) 39157 | { 39158 | // c0 o0 (v0 o1 (v1 o2 c1)) 39159 | typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t; 39160 | 39161 | const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]); 39162 | const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); 39163 | const Type& v0 = vovoc->t0(); 39164 | const Type& v1 = vovoc->t1(); 39165 | const Type c1 = vovoc->t2(); 39166 | const details::operator_type o0 = operation; 39167 | const details::operator_type o1 = expr_gen.get_operator(vovoc->f0()); 39168 | const details::operator_type o2 = expr_gen.get_operator(vovoc->f1()); 39169 | 39170 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39171 | binary_functor_t f1 = vovoc->f0(); 39172 | binary_functor_t f2 = vovoc->f1(); 39173 | 39174 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39175 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39176 | 39177 | expression_node_ptr result = error_node(); 39178 | 39179 | const bool synthesis_result = 39180 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39181 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result); 39182 | 39183 | if (synthesis_result) 39184 | return result; 39185 | else if (!expr_gen.valid_operator(o0,f0)) 39186 | return error_node(); 39187 | 39188 | exprtk_debug(("c0 o0 (v0 o1 (v1 o2 c1))\n")); 39189 | 39190 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2); 39191 | } 39192 | 39193 | static inline std::string id(expression_generator<Type>& expr_gen, 39194 | const details::operator_type o0, 39195 | const details::operator_type o1, 39196 | const details::operator_type o2) 39197 | { 39198 | return details::build_string() 39199 | << "t" << expr_gen.to_str(o0) 39200 | << "(t" << expr_gen.to_str(o1) 39201 | << "(t" << expr_gen.to_str(o2) 39202 | << "t))" 39203 | } 39204 | }; 39205 | 39206 | struct synthesize_vococov_expression1 39207 | { 39208 | typedef typename vococov_t::type1 node_type; 39209 | typedef typename vococov_t::sf4_type sf4_type; 39210 | typedef typename node_type::T0 T0; 39211 | typedef typename node_type::T1 T1; 39212 | typedef typename node_type::T2 T2; 39213 | typedef typename node_type::T3 T3; 39214 | 39215 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39216 | const details::operator_type& operation, 39217 | expression_node_ptr (&branch)[2]) 39218 | { 39219 | // v0 o0 (c0 o1 (c1 o2 v1)) 39220 | typedef typename synthesize_cocov_expression1::node_type lcl_cocov_t; 39221 | 39222 | const lcl_cocov_t* cocov = static_cast<const lcl_cocov_t*>(branch[1]); 39223 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39224 | const Type c0 = cocov->t0(); 39225 | const Type c1 = cocov->t1(); 39226 | const Type& v1 = cocov->t2(); 39227 | const details::operator_type o0 = operation; 39228 | const details::operator_type o1 = expr_gen.get_operator(cocov->f0()); 39229 | const details::operator_type o2 = expr_gen.get_operator(cocov->f1()); 39230 | 39231 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39232 | binary_functor_t f1 = cocov->f0(); 39233 | binary_functor_t f2 = cocov->f1(); 39234 | 39235 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39236 | 39237 | expression_node_ptr result = error_node(); 39238 | 39239 | const bool synthesis_result = 39240 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39241 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result); 39242 | 39243 | if (synthesis_result) 39244 | return result; 39245 | else if (!expr_gen.valid_operator(o0,f0)) 39246 | return error_node(); 39247 | 39248 | exprtk_debug(("v0 o0 (c0 o1 (c1 o2 v1))\n")); 39249 | 39250 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2); 39251 | } 39252 | 39253 | static inline std::string id(expression_generator<Type>& expr_gen, 39254 | const details::operator_type o0, 39255 | const details::operator_type o1, 39256 | const details::operator_type o2) 39257 | { 39258 | return details::build_string() 39259 | << "t" << expr_gen.to_str(o0) 39260 | << "(t" << expr_gen.to_str(o1) 39261 | << "(t" << expr_gen.to_str(o2) 39262 | << "t))" 39263 | } 39264 | }; 39265 | 39266 | struct synthesize_vovovov_expression2 39267 | { 39268 | typedef typename vovovov_t::type2 node_type; 39269 | typedef typename vovovov_t::sf4_type sf4_type; 39270 | typedef typename node_type::T0 T0; 39271 | typedef typename node_type::T1 T1; 39272 | typedef typename node_type::T2 T2; 39273 | typedef typename node_type::T3 T3; 39274 | 39275 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39276 | const details::operator_type& operation, 39277 | expression_node_ptr (&branch)[2]) 39278 | { 39279 | // v0 o0 ((v1 o1 v2) o2 v3) 39280 | typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t; 39281 | 39282 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]); 39283 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39284 | const Type& v1 = vovov->t0(); 39285 | const Type& v2 = vovov->t1(); 39286 | const Type& v3 = vovov->t2(); 39287 | const details::operator_type o0 = operation; 39288 | const details::operator_type o1 = expr_gen.get_operator(vovov->f0()); 39289 | const details::operator_type o2 = expr_gen.get_operator(vovov->f1()); 39290 | 39291 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39292 | binary_functor_t f1 = vovov->f0(); 39293 | binary_functor_t f2 = vovov->f1(); 39294 | 39295 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39296 | 39297 | expression_node_ptr result = error_node(); 39298 | 39299 | const bool synthesis_result = 39300 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39301 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result); 39302 | 39303 | if (synthesis_result) 39304 | return result; 39305 | else if (!expr_gen.valid_operator(o0,f0)) 39306 | return error_node(); 39307 | 39308 | exprtk_debug(("v0 o0 ((v1 o1 v2) o2 v3)\n")); 39309 | 39310 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2); 39311 | } 39312 | 39313 | static inline std::string id(expression_generator<Type>& expr_gen, 39314 | const details::operator_type o0, 39315 | const details::operator_type o1, 39316 | const details::operator_type o2) 39317 | { 39318 | return details::build_string() 39319 | << "t" << expr_gen.to_str(o0) 39320 | << "((t" << expr_gen.to_str(o1) 39321 | << "t)" << expr_gen.to_str(o2) 39322 | << "t)" 39323 | } 39324 | }; 39325 | 39326 | struct synthesize_vovovoc_expression2 39327 | { 39328 | typedef typename vovovoc_t::type2 node_type; 39329 | typedef typename vovovoc_t::sf4_type sf4_type; 39330 | typedef typename node_type::T0 T0; 39331 | typedef typename node_type::T1 T1; 39332 | typedef typename node_type::T2 T2; 39333 | typedef typename node_type::T3 T3; 39334 | 39335 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39336 | const details::operator_type& operation, 39337 | expression_node_ptr (&branch)[2]) 39338 | { 39339 | // v0 o0 ((v1 o1 v2) o2 c) 39340 | typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t; 39341 | 39342 | const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]); 39343 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39344 | const Type& v1 = vovoc->t0(); 39345 | const Type& v2 = vovoc->t1(); 39346 | const Type c = vovoc->t2(); 39347 | const details::operator_type o0 = operation; 39348 | const details::operator_type o1 = expr_gen.get_operator(vovoc->f0()); 39349 | const details::operator_type o2 = expr_gen.get_operator(vovoc->f1()); 39350 | 39351 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39352 | binary_functor_t f1 = vovoc->f0(); 39353 | binary_functor_t f2 = vovoc->f1(); 39354 | 39355 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39356 | 39357 | expression_node_ptr result = error_node(); 39358 | 39359 | const bool synthesis_result = 39360 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39361 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result); 39362 | 39363 | if (synthesis_result) 39364 | return result; 39365 | else if (!expr_gen.valid_operator(o0,f0)) 39366 | return error_node(); 39367 | 39368 | exprtk_debug(("v0 o0 ((v1 o1 v2) o2 c)\n")); 39369 | 39370 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2); 39371 | } 39372 | 39373 | static inline std::string id(expression_generator<Type>& expr_gen, 39374 | const details::operator_type o0, 39375 | const details::operator_type o1, 39376 | const details::operator_type o2) 39377 | { 39378 | return details::build_string() 39379 | << "t" << expr_gen.to_str(o0) 39380 | << "((t" << expr_gen.to_str(o1) 39381 | << "t)" << expr_gen.to_str(o2) 39382 | << "t)" 39383 | } 39384 | }; 39385 | 39386 | struct synthesize_vovocov_expression2 39387 | { 39388 | typedef typename vovocov_t::type2 node_type; 39389 | typedef typename vovocov_t::sf4_type sf4_type; 39390 | typedef typename node_type::T0 T0; 39391 | typedef typename node_type::T1 T1; 39392 | typedef typename node_type::T2 T2; 39393 | typedef typename node_type::T3 T3; 39394 | 39395 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39396 | const details::operator_type& operation, 39397 | expression_node_ptr (&branch)[2]) 39398 | { 39399 | // v0 o0 ((v1 o1 c) o2 v2) 39400 | typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t; 39401 | 39402 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]); 39403 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39404 | const Type& v1 = vocov->t0(); 39405 | const Type c = vocov->t1(); 39406 | const Type& v2 = vocov->t2(); 39407 | const details::operator_type o0 = operation; 39408 | const details::operator_type o1 = expr_gen.get_operator(vocov->f0()); 39409 | const details::operator_type o2 = expr_gen.get_operator(vocov->f1()); 39410 | 39411 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39412 | binary_functor_t f1 = vocov->f0(); 39413 | binary_functor_t f2 = vocov->f1(); 39414 | 39415 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39416 | 39417 | expression_node_ptr result = error_node(); 39418 | 39419 | const bool synthesis_result = 39420 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39421 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result); 39422 | 39423 | if (synthesis_result) 39424 | return result; 39425 | else if (!expr_gen.valid_operator(o0,f0)) 39426 | return error_node(); 39427 | 39428 | exprtk_debug(("v0 o0 ((v1 o1 c) o2 v2)\n")); 39429 | 39430 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2); 39431 | } 39432 | 39433 | static inline std::string id(expression_generator<Type>& expr_gen, 39434 | const details::operator_type o0, 39435 | const details::operator_type o1, 39436 | const details::operator_type o2) 39437 | { 39438 | return details::build_string() 39439 | << "t" << expr_gen.to_str(o0) 39440 | << "((t" << expr_gen.to_str(o1) 39441 | << "t)" << expr_gen.to_str(o2) 39442 | << "t)" 39443 | } 39444 | }; 39445 | 39446 | struct synthesize_vocovov_expression2 39447 | { 39448 | typedef typename vocovov_t::type2 node_type; 39449 | typedef typename vocovov_t::sf4_type sf4_type; 39450 | typedef typename node_type::T0 T0; 39451 | typedef typename node_type::T1 T1; 39452 | typedef typename node_type::T2 T2; 39453 | typedef typename node_type::T3 T3; 39454 | 39455 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39456 | const details::operator_type& operation, 39457 | expression_node_ptr (&branch)[2]) 39458 | { 39459 | // v0 o0 ((c o1 v1) o2 v2) 39460 | typedef typename synthesize_covov_expression0::node_type lcl_covov_t; 39461 | 39462 | const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[1]); 39463 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39464 | const Type c = covov->t0(); 39465 | const Type& v1 = covov->t1(); 39466 | const Type& v2 = covov->t2(); 39467 | const details::operator_type o0 = operation; 39468 | const details::operator_type o1 = expr_gen.get_operator(covov->f0()); 39469 | const details::operator_type o2 = expr_gen.get_operator(covov->f1()); 39470 | 39471 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39472 | binary_functor_t f1 = covov->f0(); 39473 | binary_functor_t f2 = covov->f1(); 39474 | 39475 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39476 | 39477 | expression_node_ptr result = error_node(); 39478 | 39479 | const bool synthesis_result = 39480 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39481 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result); 39482 | 39483 | if (synthesis_result) 39484 | return result; 39485 | else if (!expr_gen.valid_operator(o0,f0)) 39486 | return error_node(); 39487 | 39488 | exprtk_debug(("v0 o0 ((c o1 v1) o2 v2)\n")); 39489 | 39490 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2); 39491 | } 39492 | 39493 | static inline std::string id(expression_generator<Type>& expr_gen, 39494 | const details::operator_type o0, 39495 | const details::operator_type o1, 39496 | const details::operator_type o2) 39497 | { 39498 | return details::build_string() 39499 | << "t" << expr_gen.to_str(o0) 39500 | << "((t" << expr_gen.to_str(o1) 39501 | << "t)" << expr_gen.to_str(o2) 39502 | << "t)" 39503 | } 39504 | }; 39505 | 39506 | struct synthesize_covovov_expression2 39507 | { 39508 | typedef typename covovov_t::type2 node_type; 39509 | typedef typename covovov_t::sf4_type sf4_type; 39510 | typedef typename node_type::T0 T0; 39511 | typedef typename node_type::T1 T1; 39512 | typedef typename node_type::T2 T2; 39513 | typedef typename node_type::T3 T3; 39514 | 39515 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39516 | const details::operator_type& operation, 39517 | expression_node_ptr (&branch)[2]) 39518 | { 39519 | // c o0 ((v1 o1 v2) o2 v3) 39520 | typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t; 39521 | 39522 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]); 39523 | const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); 39524 | const Type& v0 = vovov->t0(); 39525 | const Type& v1 = vovov->t1(); 39526 | const Type& v2 = vovov->t2(); 39527 | const details::operator_type o0 = operation; 39528 | const details::operator_type o1 = expr_gen.get_operator(vovov->f0()); 39529 | const details::operator_type o2 = expr_gen.get_operator(vovov->f1()); 39530 | 39531 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39532 | binary_functor_t f1 = vovov->f0(); 39533 | binary_functor_t f2 = vovov->f1(); 39534 | 39535 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39536 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39537 | 39538 | expression_node_ptr result = error_node(); 39539 | 39540 | const bool synthesis_result = 39541 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39542 | (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result); 39543 | 39544 | if (synthesis_result) 39545 | return result; 39546 | else if (!expr_gen.valid_operator(o0,f0)) 39547 | return error_node(); 39548 | 39549 | exprtk_debug(("c o0 ((v1 o1 v2) o2 v3)\n")); 39550 | 39551 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2); 39552 | } 39553 | 39554 | static inline std::string id(expression_generator<Type>& expr_gen, 39555 | const details::operator_type o0, 39556 | const details::operator_type o1, 39557 | const details::operator_type o2) 39558 | { 39559 | return details::build_string() 39560 | << "t" << expr_gen.to_str(o0) 39561 | << "((t" << expr_gen.to_str(o1) 39562 | << "t)" << expr_gen.to_str(o2) 39563 | << "t)" 39564 | } 39565 | }; 39566 | 39567 | struct synthesize_covocov_expression2 39568 | { 39569 | typedef typename covocov_t::type2 node_type; 39570 | typedef typename covocov_t::sf4_type sf4_type; 39571 | typedef typename node_type::T0 T0; 39572 | typedef typename node_type::T1 T1; 39573 | typedef typename node_type::T2 T2; 39574 | typedef typename node_type::T3 T3; 39575 | 39576 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39577 | const details::operator_type& operation, 39578 | expression_node_ptr (&branch)[2]) 39579 | { 39580 | // c0 o0 ((v0 o1 c1) o2 v1) 39581 | typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t; 39582 | 39583 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]); 39584 | const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); 39585 | const Type& v0 = vocov->t0(); 39586 | const Type c1 = vocov->t1(); 39587 | const Type& v1 = vocov->t2(); 39588 | const details::operator_type o0 = operation; 39589 | const details::operator_type o1 = expr_gen.get_operator(vocov->f0()); 39590 | const details::operator_type o2 = expr_gen.get_operator(vocov->f1()); 39591 | 39592 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39593 | binary_functor_t f1 = vocov->f0(); 39594 | binary_functor_t f2 = vocov->f1(); 39595 | 39596 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39597 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39598 | 39599 | expression_node_ptr result = error_node(); 39600 | 39601 | const bool synthesis_result = 39602 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39603 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result); 39604 | 39605 | if (synthesis_result) 39606 | return result; 39607 | else if (!expr_gen.valid_operator(o0,f0)) 39608 | return error_node(); 39609 | 39610 | exprtk_debug(("c0 o0 ((v0 o1 c1) o2 v1)\n")); 39611 | 39612 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2); 39613 | } 39614 | 39615 | static inline std::string id(expression_generator<Type>& expr_gen, 39616 | const details::operator_type o0, 39617 | const details::operator_type o1, 39618 | const details::operator_type o2) 39619 | { 39620 | return details::build_string() 39621 | << "t" << expr_gen.to_str(o0) 39622 | << "((t" << expr_gen.to_str(o1) 39623 | << "t)" << expr_gen.to_str(o2) 39624 | << "t)" 39625 | } 39626 | }; 39627 | 39628 | struct synthesize_vocovoc_expression2 39629 | { 39630 | typedef typename vocovoc_t::type2 node_type; 39631 | typedef typename vocovoc_t::sf4_type sf4_type; 39632 | typedef typename node_type::T0 T0; 39633 | typedef typename node_type::T1 T1; 39634 | typedef typename node_type::T2 T2; 39635 | typedef typename node_type::T3 T3; 39636 | 39637 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39638 | const details::operator_type& operation, 39639 | expression_node_ptr (&branch)[2]) 39640 | { 39641 | // v0 o0 ((c0 o1 v1) o2 c1) 39642 | typedef typename synthesize_covoc_expression0::node_type lcl_covoc_t; 39643 | 39644 | const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[1]); 39645 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); 39646 | const Type c0 = covoc->t0(); 39647 | const Type& v1 = covoc->t1(); 39648 | const Type c1 = covoc->t2(); 39649 | const details::operator_type o0 = operation; 39650 | const details::operator_type o1 = expr_gen.get_operator(covoc->f0()); 39651 | const details::operator_type o2 = expr_gen.get_operator(covoc->f1()); 39652 | 39653 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39654 | binary_functor_t f1 = covoc->f0(); 39655 | binary_functor_t f2 = covoc->f1(); 39656 | 39657 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39658 | 39659 | expression_node_ptr result = error_node(); 39660 | 39661 | const bool synthesis_result = 39662 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39663 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result); 39664 | 39665 | if (synthesis_result) 39666 | return result; 39667 | else if (!expr_gen.valid_operator(o0,f0)) 39668 | return error_node(); 39669 | 39670 | exprtk_debug(("v0 o0 ((c0 o1 v1) o2 c1)\n")); 39671 | 39672 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2); 39673 | } 39674 | 39675 | static inline std::string id(expression_generator<Type>& expr_gen, 39676 | const details::operator_type o0, 39677 | const details::operator_type o1, 39678 | const details::operator_type o2) 39679 | { 39680 | return details::build_string() 39681 | << "t" << expr_gen.to_str(o0) 39682 | << "((t" << expr_gen.to_str(o1) 39683 | << "t)" << expr_gen.to_str(o2) 39684 | << "t)" 39685 | } 39686 | }; 39687 | 39688 | struct synthesize_covovoc_expression2 39689 | { 39690 | typedef typename covovoc_t::type2 node_type; 39691 | typedef typename covovoc_t::sf4_type sf4_type; 39692 | typedef typename node_type::T0 T0; 39693 | typedef typename node_type::T1 T1; 39694 | typedef typename node_type::T2 T2; 39695 | typedef typename node_type::T3 T3; 39696 | 39697 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39698 | const details::operator_type& operation, 39699 | expression_node_ptr (&branch)[2]) 39700 | { 39701 | // c0 o0 ((v0 o1 v1) o2 c1) 39702 | typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t; 39703 | 39704 | const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]); 39705 | const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); 39706 | const Type& v0 = vovoc->t0(); 39707 | const Type& v1 = vovoc->t1(); 39708 | const Type c1 = vovoc->t2(); 39709 | const details::operator_type o0 = operation; 39710 | const details::operator_type o1 = expr_gen.get_operator(vovoc->f0()); 39711 | const details::operator_type o2 = expr_gen.get_operator(vovoc->f1()); 39712 | 39713 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); 39714 | binary_functor_t f1 = vovoc->f0(); 39715 | binary_functor_t f2 = vovoc->f1(); 39716 | 39717 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39718 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39719 | 39720 | expression_node_ptr result = error_node(); 39721 | 39722 | const bool synthesis_result = 39723 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39724 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result); 39725 | 39726 | if (synthesis_result) 39727 | return result; 39728 | else if (!expr_gen.valid_operator(o0,f0)) 39729 | return error_node(); 39730 | 39731 | exprtk_debug(("c0 o0 ((v0 o1 v1) o2 c1)\n")); 39732 | 39733 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2); 39734 | } 39735 | 39736 | static inline std::string id(expression_generator<Type>& expr_gen, 39737 | const details::operator_type o0, 39738 | const details::operator_type o1, 39739 | const details::operator_type o2) 39740 | { 39741 | return details::build_string() 39742 | << "t" << expr_gen.to_str(o0) 39743 | << "((t" << expr_gen.to_str(o1) 39744 | << "t)" << expr_gen.to_str(o2) 39745 | << "t)" 39746 | } 39747 | }; 39748 | 39749 | struct synthesize_vococov_expression2 39750 | { 39751 | typedef typename vococov_t::type2 node_type; 39752 | static inline expression_node_ptr process(expression_generator<Type>&, 39753 | const details::operator_type&, 39754 | expression_node_ptr (&)[2]) 39755 | { 39756 | // v0 o0 ((c0 o1 c1) o2 v1) - Not possible 39757 | exprtk_debug(("v0 o0 ((c0 o1 c1) o2 v1) - Not possible\n")); 39758 | return error_node(); 39759 | } 39760 | 39761 | static inline std::string id(expression_generator<Type>&, 39762 | const details::operator_type, 39763 | const details::operator_type, 39764 | const details::operator_type) 39765 | { 39766 | return "INVALID" 39767 | } 39768 | }; 39769 | 39770 | struct synthesize_vovovov_expression3 39771 | { 39772 | typedef typename vovovov_t::type3 node_type; 39773 | typedef typename vovovov_t::sf4_type sf4_type; 39774 | typedef typename node_type::T0 T0; 39775 | typedef typename node_type::T1 T1; 39776 | typedef typename node_type::T2 T2; 39777 | typedef typename node_type::T3 T3; 39778 | 39779 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39780 | const details::operator_type& operation, 39781 | expression_node_ptr (&branch)[2]) 39782 | { 39783 | // ((v0 o0 v1) o1 v2) o2 v3 39784 | typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t; 39785 | 39786 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]); 39787 | const Type& v0 = vovov->t0(); 39788 | const Type& v1 = vovov->t1(); 39789 | const Type& v2 = vovov->t2(); 39790 | const Type& v3 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 39791 | const details::operator_type o0 = expr_gen.get_operator(vovov->f0()); 39792 | const details::operator_type o1 = expr_gen.get_operator(vovov->f1()); 39793 | const details::operator_type o2 = operation; 39794 | 39795 | binary_functor_t f0 = vovov->f0(); 39796 | binary_functor_t f1 = vovov->f1(); 39797 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 39798 | 39799 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39800 | 39801 | expression_node_ptr result = error_node(); 39802 | 39803 | const bool synthesis_result = 39804 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39805 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result); 39806 | 39807 | if (synthesis_result) 39808 | return result; 39809 | else if (!expr_gen.valid_operator(o2,f2)) 39810 | return error_node(); 39811 | 39812 | exprtk_debug(("((v0 o0 v1) o1 v2) o2 v3\n")); 39813 | 39814 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2); 39815 | } 39816 | 39817 | static inline std::string id(expression_generator<Type>& expr_gen, 39818 | const details::operator_type o0, 39819 | const details::operator_type o1, 39820 | const details::operator_type o2) 39821 | { 39822 | return details::build_string() 39823 | << "((t" << expr_gen.to_str(o0) 39824 | << "t)" << expr_gen.to_str(o1) 39825 | << "t)" << expr_gen.to_str(o2) 39826 | << "t" 39827 | } 39828 | }; 39829 | 39830 | struct synthesize_vovovoc_expression3 39831 | { 39832 | typedef typename vovovoc_t::type3 node_type; 39833 | typedef typename vovovoc_t::sf4_type sf4_type; 39834 | typedef typename node_type::T0 T0; 39835 | typedef typename node_type::T1 T1; 39836 | typedef typename node_type::T2 T2; 39837 | typedef typename node_type::T3 T3; 39838 | 39839 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39840 | const details::operator_type& operation, 39841 | expression_node_ptr (&branch)[2]) 39842 | { 39843 | // ((v0 o0 v1) o1 v2) o2 c 39844 | typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t; 39845 | 39846 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]); 39847 | const Type& v0 = vovov->t0(); 39848 | const Type& v1 = vovov->t1(); 39849 | const Type& v2 = vovov->t2(); 39850 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 39851 | const details::operator_type o0 = expr_gen.get_operator(vovov->f0()); 39852 | const details::operator_type o1 = expr_gen.get_operator(vovov->f1()); 39853 | const details::operator_type o2 = operation; 39854 | 39855 | binary_functor_t f0 = vovov->f0(); 39856 | binary_functor_t f1 = vovov->f1(); 39857 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 39858 | 39859 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39860 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 39861 | 39862 | expression_node_ptr result = error_node(); 39863 | 39864 | const bool synthesis_result = 39865 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39866 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result); 39867 | 39868 | if (synthesis_result) 39869 | return result; 39870 | else if (!expr_gen.valid_operator(o2,f2)) 39871 | return error_node(); 39872 | 39873 | exprtk_debug(("((v0 o0 v1) o1 v2) o2 c\n")); 39874 | 39875 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2); 39876 | } 39877 | 39878 | static inline std::string id(expression_generator<Type>& expr_gen, 39879 | const details::operator_type o0, 39880 | const details::operator_type o1, 39881 | const details::operator_type o2) 39882 | { 39883 | return details::build_string() 39884 | << "((t" << expr_gen.to_str(o0) 39885 | << "t)" << expr_gen.to_str(o1) 39886 | << "t)" << expr_gen.to_str(o2) 39887 | << "t" 39888 | } 39889 | }; 39890 | 39891 | struct synthesize_vovocov_expression3 39892 | { 39893 | typedef typename vovocov_t::type3 node_type; 39894 | typedef typename vovocov_t::sf4_type sf4_type; 39895 | typedef typename node_type::T0 T0; 39896 | typedef typename node_type::T1 T1; 39897 | typedef typename node_type::T2 T2; 39898 | typedef typename node_type::T3 T3; 39899 | 39900 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39901 | const details::operator_type& operation, 39902 | expression_node_ptr (&branch)[2]) 39903 | { 39904 | // ((v0 o0 v1) o1 c) o2 v2 39905 | typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t; 39906 | 39907 | const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[0]); 39908 | const Type& v0 = vovoc->t0(); 39909 | const Type& v1 = vovoc->t1(); 39910 | const Type c = vovoc->t2(); 39911 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 39912 | const details::operator_type o0 = expr_gen.get_operator(vovoc->f0()); 39913 | const details::operator_type o1 = expr_gen.get_operator(vovoc->f1()); 39914 | const details::operator_type o2 = operation; 39915 | 39916 | binary_functor_t f0 = vovoc->f0(); 39917 | binary_functor_t f1 = vovoc->f1(); 39918 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 39919 | 39920 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39921 | 39922 | expression_node_ptr result = error_node(); 39923 | 39924 | const bool synthesis_result = 39925 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39926 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result); 39927 | 39928 | if (synthesis_result) 39929 | return result; 39930 | else if (!expr_gen.valid_operator(o2,f2)) 39931 | return error_node(); 39932 | 39933 | exprtk_debug(("((v0 o0 v1) o1 c) o2 v2\n")); 39934 | 39935 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2); 39936 | } 39937 | 39938 | static inline std::string id(expression_generator<Type>& expr_gen, 39939 | const details::operator_type o0, 39940 | const details::operator_type o1, 39941 | const details::operator_type o2) 39942 | { 39943 | return details::build_string() 39944 | << "((t" << expr_gen.to_str(o0) 39945 | << "t)" << expr_gen.to_str(o1) 39946 | << "t)" << expr_gen.to_str(o2) 39947 | << "t" 39948 | } 39949 | }; 39950 | 39951 | struct synthesize_vocovov_expression3 39952 | { 39953 | typedef typename vocovov_t::type3 node_type; 39954 | typedef typename vocovov_t::sf4_type sf4_type; 39955 | typedef typename node_type::T0 T0; 39956 | typedef typename node_type::T1 T1; 39957 | typedef typename node_type::T2 T2; 39958 | typedef typename node_type::T3 T3; 39959 | 39960 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 39961 | const details::operator_type& operation, 39962 | expression_node_ptr (&branch)[2]) 39963 | { 39964 | // ((v0 o0 c) o1 v1) o2 v2 39965 | typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t; 39966 | 39967 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]); 39968 | const Type& v0 = vocov->t0(); 39969 | const Type c = vocov->t1(); 39970 | const Type& v1 = vocov->t2(); 39971 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 39972 | const details::operator_type o0 = expr_gen.get_operator(vocov->f0()); 39973 | const details::operator_type o1 = expr_gen.get_operator(vocov->f1()); 39974 | const details::operator_type o2 = operation; 39975 | 39976 | binary_functor_t f0 = vocov->f0(); 39977 | binary_functor_t f1 = vocov->f1(); 39978 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 39979 | 39980 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 39981 | 39982 | expression_node_ptr result = error_node(); 39983 | 39984 | const bool synthesis_result = 39985 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 39986 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result); 39987 | 39988 | if (synthesis_result) 39989 | return result; 39990 | else if (!expr_gen.valid_operator(o2,f2)) 39991 | return error_node(); 39992 | 39993 | exprtk_debug(("((v0 o0 c) o1 v1) o2 v2\n")); 39994 | 39995 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2); 39996 | } 39997 | 39998 | static inline std::string id(expression_generator<Type>& expr_gen, 39999 | const details::operator_type o0, 40000 | const details::operator_type o1, 40001 | const details::operator_type o2) 40002 | { 40003 | return details::build_string() 40004 | << "((t" << expr_gen.to_str(o0) 40005 | << "t)" << expr_gen.to_str(o1) 40006 | << "t)" << expr_gen.to_str(o2) 40007 | << "t" 40008 | } 40009 | }; 40010 | 40011 | struct synthesize_covovov_expression3 40012 | { 40013 | typedef typename covovov_t::type3 node_type; 40014 | typedef typename covovov_t::sf4_type sf4_type; 40015 | typedef typename node_type::T0 T0; 40016 | typedef typename node_type::T1 T1; 40017 | typedef typename node_type::T2 T2; 40018 | typedef typename node_type::T3 T3; 40019 | 40020 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40021 | const details::operator_type& operation, 40022 | expression_node_ptr (&branch)[2]) 40023 | { 40024 | // ((c o0 v0) o1 v1) o2 v2 40025 | typedef typename synthesize_covov_expression0::node_type lcl_covov_t; 40026 | 40027 | const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]); 40028 | const Type c = covov->t0(); 40029 | const Type& v0 = covov->t1(); 40030 | const Type& v1 = covov->t2(); 40031 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40032 | const details::operator_type o0 = expr_gen.get_operator(covov->f0()); 40033 | const details::operator_type o1 = expr_gen.get_operator(covov->f1()); 40034 | const details::operator_type o2 = operation; 40035 | 40036 | binary_functor_t f0 = covov->f0(); 40037 | binary_functor_t f1 = covov->f1(); 40038 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40039 | 40040 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40041 | 40042 | expression_node_ptr result = error_node(); 40043 | 40044 | const bool synthesis_result = 40045 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40046 | (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result); 40047 | 40048 | if (synthesis_result) 40049 | return result; 40050 | else if (!expr_gen.valid_operator(o2,f2)) 40051 | return error_node(); 40052 | 40053 | exprtk_debug(("((c o0 v0) o1 v1) o2 v2\n")); 40054 | 40055 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2); 40056 | } 40057 | 40058 | static inline std::string id(expression_generator<Type>& expr_gen, 40059 | const details::operator_type o0, 40060 | const details::operator_type o1, 40061 | const details::operator_type o2) 40062 | { 40063 | return details::build_string() 40064 | << "((t" << expr_gen.to_str(o0) 40065 | << "t)" << expr_gen.to_str(o1) 40066 | << "t)" << expr_gen.to_str(o2) 40067 | << "t" 40068 | } 40069 | }; 40070 | 40071 | struct synthesize_covocov_expression3 40072 | { 40073 | typedef typename covocov_t::type3 node_type; 40074 | typedef typename covocov_t::sf4_type sf4_type; 40075 | typedef typename node_type::T0 T0; 40076 | typedef typename node_type::T1 T1; 40077 | typedef typename node_type::T2 T2; 40078 | typedef typename node_type::T3 T3; 40079 | 40080 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40081 | const details::operator_type& operation, 40082 | expression_node_ptr (&branch)[2]) 40083 | { 40084 | // ((c0 o0 v0) o1 c1) o2 v1 40085 | typedef typename synthesize_covoc_expression0::node_type lcl_covoc_t; 40086 | 40087 | const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[0]); 40088 | const Type c0 = covoc->t0(); 40089 | const Type& v0 = covoc->t1(); 40090 | const Type c1 = covoc->t2(); 40091 | const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40092 | const details::operator_type o0 = expr_gen.get_operator(covoc->f0()); 40093 | const details::operator_type o1 = expr_gen.get_operator(covoc->f1()); 40094 | const details::operator_type o2 = operation; 40095 | 40096 | binary_functor_t f0 = covoc->f0(); 40097 | binary_functor_t f1 = covoc->f1(); 40098 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40099 | 40100 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40101 | 40102 | expression_node_ptr result = error_node(); 40103 | 40104 | const bool synthesis_result = 40105 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40106 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result); 40107 | 40108 | if (synthesis_result) 40109 | return result; 40110 | else if (!expr_gen.valid_operator(o2,f2)) 40111 | return error_node(); 40112 | 40113 | exprtk_debug(("((c0 o0 v0) o1 c1) o2 v1\n")); 40114 | 40115 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2); 40116 | } 40117 | 40118 | static inline std::string id(expression_generator<Type>& expr_gen, 40119 | const details::operator_type o0, 40120 | const details::operator_type o1, 40121 | const details::operator_type o2) 40122 | { 40123 | return details::build_string() 40124 | << "((t" << expr_gen.to_str(o0) 40125 | << "t)" << expr_gen.to_str(o1) 40126 | << "t)" << expr_gen.to_str(o2) 40127 | << "t" 40128 | } 40129 | }; 40130 | 40131 | struct synthesize_vocovoc_expression3 40132 | { 40133 | typedef typename vocovoc_t::type3 node_type; 40134 | typedef typename vocovoc_t::sf4_type sf4_type; 40135 | typedef typename node_type::T0 T0; 40136 | typedef typename node_type::T1 T1; 40137 | typedef typename node_type::T2 T2; 40138 | typedef typename node_type::T3 T3; 40139 | 40140 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40141 | const details::operator_type& operation, 40142 | expression_node_ptr (&branch)[2]) 40143 | { 40144 | // ((v0 o0 c0) o1 v1) o2 c1 40145 | typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t; 40146 | 40147 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]); 40148 | const Type& v0 = vocov->t0(); 40149 | const Type c0 = vocov->t1(); 40150 | const Type& v1 = vocov->t2(); 40151 | const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); 40152 | const details::operator_type o0 = expr_gen.get_operator(vocov->f0()); 40153 | const details::operator_type o1 = expr_gen.get_operator(vocov->f1()); 40154 | const details::operator_type o2 = operation; 40155 | 40156 | binary_functor_t f0 = vocov->f0(); 40157 | binary_functor_t f1 = vocov->f1(); 40158 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40159 | 40160 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40161 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 40162 | 40163 | expression_node_ptr result = error_node(); 40164 | 40165 | const bool synthesis_result = 40166 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40167 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result); 40168 | 40169 | if (synthesis_result) 40170 | return result; 40171 | else if (!expr_gen.valid_operator(o2,f2)) 40172 | return error_node(); 40173 | 40174 | exprtk_debug(("((v0 o0 c0) o1 v1) o2 c1\n")); 40175 | 40176 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2); 40177 | } 40178 | 40179 | static inline std::string id(expression_generator<Type>& expr_gen, 40180 | const details::operator_type o0, 40181 | const details::operator_type o1, 40182 | const details::operator_type o2) 40183 | { 40184 | return details::build_string() 40185 | << "((t" << expr_gen.to_str(o0) 40186 | << "t)" << expr_gen.to_str(o1) 40187 | << "t)" << expr_gen.to_str(o2) 40188 | << "t" 40189 | } 40190 | }; 40191 | 40192 | struct synthesize_covovoc_expression3 40193 | { 40194 | typedef typename covovoc_t::type3 node_type; 40195 | typedef typename covovoc_t::sf4_type sf4_type; 40196 | typedef typename node_type::T0 T0; 40197 | typedef typename node_type::T1 T1; 40198 | typedef typename node_type::T2 T2; 40199 | typedef typename node_type::T3 T3; 40200 | 40201 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40202 | const details::operator_type& operation, 40203 | expression_node_ptr (&branch)[2]) 40204 | { 40205 | // ((c0 o0 v0) o1 v1) o2 c1 40206 | typedef typename synthesize_covov_expression0::node_type lcl_covov_t; 40207 | 40208 | const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]); 40209 | const Type c0 = covov->t0(); 40210 | const Type& v0 = covov->t1(); 40211 | const Type& v1 = covov->t2(); 40212 | const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); 40213 | const details::operator_type o0 = expr_gen.get_operator(covov->f0()); 40214 | const details::operator_type o1 = expr_gen.get_operator(covov->f1()); 40215 | const details::operator_type o2 = operation; 40216 | 40217 | binary_functor_t f0 = covov->f0(); 40218 | binary_functor_t f1 = covov->f1(); 40219 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40220 | 40221 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40222 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 40223 | 40224 | expression_node_ptr result = error_node(); 40225 | 40226 | const bool synthesis_result = 40227 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40228 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result); 40229 | 40230 | if (synthesis_result) 40231 | return result; 40232 | else if (!expr_gen.valid_operator(o2,f2)) 40233 | return error_node(); 40234 | 40235 | exprtk_debug(("((c0 o0 v0) o1 v1) o2 c1\n")); 40236 | 40237 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2); 40238 | } 40239 | 40240 | static inline std::string id(expression_generator<Type>& expr_gen, 40241 | const details::operator_type o0, 40242 | const details::operator_type o1, 40243 | const details::operator_type o2) 40244 | { 40245 | return details::build_string() 40246 | << "((t" << expr_gen.to_str(o0) 40247 | << "t)" << expr_gen.to_str(o1) 40248 | << "t)" << expr_gen.to_str(o2) 40249 | << "t" 40250 | } 40251 | }; 40252 | 40253 | struct synthesize_vococov_expression3 40254 | { 40255 | typedef typename vococov_t::type3 node_type; 40256 | typedef typename vococov_t::sf4_type sf4_type; 40257 | typedef typename node_type::T0 T0; 40258 | typedef typename node_type::T1 T1; 40259 | typedef typename node_type::T2 T2; 40260 | typedef typename node_type::T3 T3; 40261 | 40262 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40263 | const details::operator_type& operation, 40264 | expression_node_ptr (&branch)[2]) 40265 | { 40266 | // ((v0 o0 c0) o1 c1) o2 v1 40267 | typedef typename synthesize_vococ_expression0::node_type lcl_vococ_t; 40268 | 40269 | const lcl_vococ_t* vococ = static_cast<const lcl_vococ_t*>(branch[0]); 40270 | const Type& v0 = vococ->t0(); 40271 | const Type c0 = vococ->t1(); 40272 | const Type c1 = vococ->t2(); 40273 | const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40274 | const details::operator_type o0 = expr_gen.get_operator(vococ->f0()); 40275 | const details::operator_type o1 = expr_gen.get_operator(vococ->f1()); 40276 | const details::operator_type o2 = operation; 40277 | 40278 | binary_functor_t f0 = vococ->f0(); 40279 | binary_functor_t f1 = vococ->f1(); 40280 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40281 | 40282 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40283 | 40284 | expression_node_ptr result = error_node(); 40285 | 40286 | const bool synthesis_result = 40287 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40288 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result); 40289 | 40290 | if (synthesis_result) 40291 | return result; 40292 | else if (!expr_gen.valid_operator(o2,f2)) 40293 | return error_node(); 40294 | 40295 | exprtk_debug(("((v0 o0 c0) o1 c1) o2 v1\n")); 40296 | 40297 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2); 40298 | } 40299 | 40300 | static inline std::string id(expression_generator<Type>& expr_gen, 40301 | const details::operator_type o0, 40302 | const details::operator_type o1, 40303 | const details::operator_type o2) 40304 | { 40305 | return details::build_string() 40306 | << "((t" << expr_gen.to_str(o0) 40307 | << "t)" << expr_gen.to_str(o1) 40308 | << "t)" << expr_gen.to_str(o2) 40309 | << "t" 40310 | } 40311 | }; 40312 | 40313 | struct synthesize_vovovov_expression4 40314 | { 40315 | typedef typename vovovov_t::type4 node_type; 40316 | typedef typename vovovov_t::sf4_type sf4_type; 40317 | typedef typename node_type::T0 T0; 40318 | typedef typename node_type::T1 T1; 40319 | typedef typename node_type::T2 T2; 40320 | typedef typename node_type::T3 T3; 40321 | 40322 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40323 | const details::operator_type& operation, 40324 | expression_node_ptr (&branch)[2]) 40325 | { 40326 | // (v0 o0 (v1 o1 v2)) o2 v3 40327 | typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t; 40328 | 40329 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]); 40330 | const Type& v0 = vovov->t0(); 40331 | const Type& v1 = vovov->t1(); 40332 | const Type& v2 = vovov->t2(); 40333 | const Type& v3 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40334 | const details::operator_type o0 = expr_gen.get_operator(vovov->f0()); 40335 | const details::operator_type o1 = expr_gen.get_operator(vovov->f1()); 40336 | const details::operator_type o2 = operation; 40337 | 40338 | binary_functor_t f0 = vovov->f0(); 40339 | binary_functor_t f1 = vovov->f1(); 40340 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40341 | 40342 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40343 | 40344 | expression_node_ptr result = error_node(); 40345 | 40346 | const bool synthesis_result = 40347 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40348 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result); 40349 | 40350 | if (synthesis_result) 40351 | return result; 40352 | else if (!expr_gen.valid_operator(o2,f2)) 40353 | return error_node(); 40354 | 40355 | exprtk_debug(("(v0 o0 (v1 o1 v2)) o2 v3\n")); 40356 | 40357 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2); 40358 | } 40359 | 40360 | static inline std::string id(expression_generator<Type>& expr_gen, 40361 | const details::operator_type o0, 40362 | const details::operator_type o1, 40363 | const details::operator_type o2) 40364 | { 40365 | return details::build_string() 40366 | << "(t" << expr_gen.to_str(o0) 40367 | << "(t" << expr_gen.to_str(o1) 40368 | << "t)" << expr_gen.to_str(o2) 40369 | << "t" 40370 | } 40371 | }; 40372 | 40373 | struct synthesize_vovovoc_expression4 40374 | { 40375 | typedef typename vovovoc_t::type4 node_type; 40376 | typedef typename vovovoc_t::sf4_type sf4_type; 40377 | typedef typename node_type::T0 T0; 40378 | typedef typename node_type::T1 T1; 40379 | typedef typename node_type::T2 T2; 40380 | typedef typename node_type::T3 T3; 40381 | 40382 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40383 | const details::operator_type& operation, 40384 | expression_node_ptr (&branch)[2]) 40385 | { 40386 | // ((v0 o0 (v1 o1 v2)) o2 c) 40387 | typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t; 40388 | 40389 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]); 40390 | const Type& v0 = vovov->t0(); 40391 | const Type& v1 = vovov->t1(); 40392 | const Type& v2 = vovov->t2(); 40393 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); 40394 | const details::operator_type o0 = expr_gen.get_operator(vovov->f0()); 40395 | const details::operator_type o1 = expr_gen.get_operator(vovov->f1()); 40396 | const details::operator_type o2 = operation; 40397 | 40398 | binary_functor_t f0 = vovov->f0(); 40399 | binary_functor_t f1 = vovov->f1(); 40400 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40401 | 40402 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40403 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 40404 | 40405 | expression_node_ptr result = error_node(); 40406 | 40407 | const bool synthesis_result = 40408 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40409 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result); 40410 | 40411 | if (synthesis_result) 40412 | return result; 40413 | else if (!expr_gen.valid_operator(o2,f2)) 40414 | return error_node(); 40415 | 40416 | exprtk_debug(("((v0 o0 (v1 o1 v2)) o2 c)\n")); 40417 | 40418 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2); 40419 | } 40420 | 40421 | static inline std::string id(expression_generator<Type>& expr_gen, 40422 | const details::operator_type o0, 40423 | const details::operator_type o1, 40424 | const details::operator_type o2) 40425 | { 40426 | return details::build_string() 40427 | << "(t" << expr_gen.to_str(o0) 40428 | << "(t" << expr_gen.to_str(o1) 40429 | << "t)" << expr_gen.to_str(o2) 40430 | << "t" 40431 | } 40432 | }; 40433 | 40434 | struct synthesize_vovocov_expression4 40435 | { 40436 | typedef typename vovocov_t::type4 node_type; 40437 | typedef typename vovocov_t::sf4_type sf4_type; 40438 | typedef typename node_type::T0 T0; 40439 | typedef typename node_type::T1 T1; 40440 | typedef typename node_type::T2 T2; 40441 | typedef typename node_type::T3 T3; 40442 | 40443 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40444 | const details::operator_type& operation, 40445 | expression_node_ptr (&branch)[2]) 40446 | { 40447 | // ((v0 o0 (v1 o1 c)) o2 v1) 40448 | typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t; 40449 | 40450 | const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[0]); 40451 | const Type& v0 = vovoc->t0(); 40452 | const Type& v1 = vovoc->t1(); 40453 | const Type c = vovoc->t2(); 40454 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40455 | const details::operator_type o0 = expr_gen.get_operator(vovoc->f0()); 40456 | const details::operator_type o1 = expr_gen.get_operator(vovoc->f1()); 40457 | const details::operator_type o2 = operation; 40458 | 40459 | binary_functor_t f0 = vovoc->f0(); 40460 | binary_functor_t f1 = vovoc->f1(); 40461 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40462 | 40463 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40464 | 40465 | expression_node_ptr result = error_node(); 40466 | 40467 | const bool synthesis_result = 40468 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40469 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result); 40470 | 40471 | if (synthesis_result) 40472 | return result; 40473 | else if (!expr_gen.valid_operator(o2,f2)) 40474 | return error_node(); 40475 | 40476 | exprtk_debug(("((v0 o0 (v1 o1 c)) o2 v1)\n")); 40477 | 40478 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2); 40479 | } 40480 | 40481 | static inline std::string id(expression_generator<Type>& expr_gen, 40482 | const details::operator_type o0, 40483 | const details::operator_type o1, 40484 | const details::operator_type o2) 40485 | { 40486 | return details::build_string() 40487 | << "(t" << expr_gen.to_str(o0) 40488 | << "(t" << expr_gen.to_str(o1) 40489 | << "t)" << expr_gen.to_str(o2) 40490 | << "t" 40491 | } 40492 | }; 40493 | 40494 | struct synthesize_vocovov_expression4 40495 | { 40496 | typedef typename vocovov_t::type4 node_type; 40497 | typedef typename vocovov_t::sf4_type sf4_type; 40498 | typedef typename node_type::T0 T0; 40499 | typedef typename node_type::T1 T1; 40500 | typedef typename node_type::T2 T2; 40501 | typedef typename node_type::T3 T3; 40502 | 40503 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40504 | const details::operator_type& operation, 40505 | expression_node_ptr (&branch)[2]) 40506 | { 40507 | // ((v0 o0 (c o1 v1)) o2 v2) 40508 | typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t; 40509 | 40510 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]); 40511 | const Type& v0 = vocov->t0(); 40512 | const Type c = vocov->t1(); 40513 | const Type& v1 = vocov->t2(); 40514 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40515 | const details::operator_type o0 = expr_gen.get_operator(vocov->f0()); 40516 | const details::operator_type o1 = expr_gen.get_operator(vocov->f1()); 40517 | const details::operator_type o2 = operation; 40518 | 40519 | binary_functor_t f0 = vocov->f0(); 40520 | binary_functor_t f1 = vocov->f1(); 40521 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40522 | 40523 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40524 | expression_node_ptr result = error_node(); 40525 | 40526 | const bool synthesis_result = 40527 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40528 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result); 40529 | 40530 | if (synthesis_result) 40531 | return result; 40532 | else if (!expr_gen.valid_operator(o2,f2)) 40533 | return error_node(); 40534 | 40535 | exprtk_debug(("((v0 o0 (c o1 v1)) o2 v2)\n")); 40536 | 40537 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2); 40538 | } 40539 | 40540 | static inline std::string id(expression_generator<Type>& expr_gen, 40541 | const details::operator_type o0, 40542 | const details::operator_type o1, 40543 | const details::operator_type o2) 40544 | { 40545 | return details::build_string() 40546 | << "(t" << expr_gen.to_str(o0) 40547 | << "(t" << expr_gen.to_str(o1) 40548 | << "t)" << expr_gen.to_str(o2) 40549 | << "t" 40550 | } 40551 | }; 40552 | 40553 | struct synthesize_covovov_expression4 40554 | { 40555 | typedef typename covovov_t::type4 node_type; 40556 | typedef typename covovov_t::sf4_type sf4_type; 40557 | typedef typename node_type::T0 T0; 40558 | typedef typename node_type::T1 T1; 40559 | typedef typename node_type::T2 T2; 40560 | typedef typename node_type::T3 T3; 40561 | 40562 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40563 | const details::operator_type& operation, 40564 | expression_node_ptr (&branch)[2]) 40565 | { 40566 | // ((c o0 (v0 o1 v1)) o2 v2) 40567 | typedef typename synthesize_covov_expression1::node_type lcl_covov_t; 40568 | 40569 | const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]); 40570 | const Type c = covov->t0(); 40571 | const Type& v0 = covov->t1(); 40572 | const Type& v1 = covov->t2(); 40573 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40574 | const details::operator_type o0 = expr_gen.get_operator(covov->f0()); 40575 | const details::operator_type o1 = expr_gen.get_operator(covov->f1()); 40576 | const details::operator_type o2 = operation; 40577 | 40578 | binary_functor_t f0 = covov->f0(); 40579 | binary_functor_t f1 = covov->f1(); 40580 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40581 | 40582 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40583 | 40584 | expression_node_ptr result = error_node(); 40585 | 40586 | const bool synthesis_result = 40587 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40588 | (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result); 40589 | 40590 | if (synthesis_result) 40591 | return result; 40592 | else if (!expr_gen.valid_operator(o2,f2)) 40593 | return error_node(); 40594 | 40595 | exprtk_debug(("((c o0 (v0 o1 v1)) o2 v2)\n")); 40596 | 40597 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2); 40598 | } 40599 | 40600 | static inline std::string id(expression_generator<Type>& expr_gen, 40601 | const details::operator_type o0, 40602 | const details::operator_type o1, 40603 | const details::operator_type o2) 40604 | { 40605 | return details::build_string() 40606 | << "(t" << expr_gen.to_str(o0) 40607 | << "(t" << expr_gen.to_str(o1) 40608 | << "t)" << expr_gen.to_str(o2) 40609 | << "t" 40610 | } 40611 | }; 40612 | 40613 | struct synthesize_covocov_expression4 40614 | { 40615 | typedef typename covocov_t::type4 node_type; 40616 | typedef typename covocov_t::sf4_type sf4_type; 40617 | typedef typename node_type::T0 T0; 40618 | typedef typename node_type::T1 T1; 40619 | typedef typename node_type::T2 T2; 40620 | typedef typename node_type::T3 T3; 40621 | 40622 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40623 | const details::operator_type& operation, 40624 | expression_node_ptr (&branch)[2]) 40625 | { 40626 | // ((c0 o0 (v0 o1 c1)) o2 v1) 40627 | typedef typename synthesize_covoc_expression1::node_type lcl_covoc_t; 40628 | 40629 | const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[0]); 40630 | const Type c0 = covoc->t0(); 40631 | const Type& v0 = covoc->t1(); 40632 | const Type c1 = covoc->t2(); 40633 | const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); 40634 | const details::operator_type o0 = expr_gen.get_operator(covoc->f0()); 40635 | const details::operator_type o1 = expr_gen.get_operator(covoc->f1()); 40636 | const details::operator_type o2 = operation; 40637 | 40638 | binary_functor_t f0 = covoc->f0(); 40639 | binary_functor_t f1 = covoc->f1(); 40640 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40641 | 40642 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40643 | 40644 | expression_node_ptr result = error_node(); 40645 | 40646 | const bool synthesis_result = 40647 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40648 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result); 40649 | 40650 | if (synthesis_result) 40651 | return result; 40652 | else if (!expr_gen.valid_operator(o2,f2)) 40653 | return error_node(); 40654 | 40655 | exprtk_debug(("((c0 o0 (v0 o1 c1)) o2 v1)\n")); 40656 | 40657 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2); 40658 | } 40659 | 40660 | static inline std::string id(expression_generator<Type>& expr_gen, 40661 | const details::operator_type o0, 40662 | const details::operator_type o1, 40663 | const details::operator_type o2) 40664 | { 40665 | return details::build_string() 40666 | << "(t" << expr_gen.to_str(o0) 40667 | << "(t" << expr_gen.to_str(o1) 40668 | << "t)" << expr_gen.to_str(o2) 40669 | << "t" 40670 | } 40671 | }; 40672 | 40673 | struct synthesize_vocovoc_expression4 40674 | { 40675 | typedef typename vocovoc_t::type4 node_type; 40676 | typedef typename vocovoc_t::sf4_type sf4_type; 40677 | typedef typename node_type::T0 T0; 40678 | typedef typename node_type::T1 T1; 40679 | typedef typename node_type::T2 T2; 40680 | typedef typename node_type::T3 T3; 40681 | 40682 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40683 | const details::operator_type& operation, 40684 | expression_node_ptr (&branch)[2]) 40685 | { 40686 | // ((v0 o0 (c0 o1 v1)) o2 c1) 40687 | typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t; 40688 | 40689 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]); 40690 | const Type& v0 = vocov->t0(); 40691 | const Type c0 = vocov->t1(); 40692 | const Type& v1 = vocov->t2(); 40693 | const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); 40694 | const details::operator_type o0 = expr_gen.get_operator(vocov->f0()); 40695 | const details::operator_type o1 = expr_gen.get_operator(vocov->f1()); 40696 | const details::operator_type o2 = operation; 40697 | 40698 | binary_functor_t f0 = vocov->f0(); 40699 | binary_functor_t f1 = vocov->f1(); 40700 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40701 | 40702 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40703 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 40704 | 40705 | expression_node_ptr result = error_node(); 40706 | 40707 | const bool synthesis_result = 40708 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40709 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result); 40710 | 40711 | if (synthesis_result) 40712 | return result; 40713 | else if (!expr_gen.valid_operator(o2,f2)) 40714 | return error_node(); 40715 | 40716 | exprtk_debug(("((v0 o0 (c0 o1 v1)) o2 c1)\n")); 40717 | 40718 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2); 40719 | } 40720 | 40721 | static inline std::string id(expression_generator<Type>& expr_gen, 40722 | const details::operator_type o0, 40723 | const details::operator_type o1, 40724 | const details::operator_type o2) 40725 | { 40726 | return details::build_string() 40727 | << "(t" << expr_gen.to_str(o0) 40728 | << "(t" << expr_gen.to_str(o1) 40729 | << "t)" << expr_gen.to_str(o2) 40730 | << "t" 40731 | } 40732 | }; 40733 | 40734 | struct synthesize_covovoc_expression4 40735 | { 40736 | typedef typename covovoc_t::type4 node_type; 40737 | typedef typename covovoc_t::sf4_type sf4_type; 40738 | typedef typename node_type::T0 T0; 40739 | typedef typename node_type::T1 T1; 40740 | typedef typename node_type::T2 T2; 40741 | typedef typename node_type::T3 T3; 40742 | 40743 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, 40744 | const details::operator_type& operation, 40745 | expression_node_ptr (&branch)[2]) 40746 | { 40747 | // ((c0 o0 (v0 o1 v1)) o2 c1) 40748 | typedef typename synthesize_covov_expression1::node_type lcl_covov_t; 40749 | 40750 | const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]); 40751 | const Type c0 = covov->t0(); 40752 | const Type& v0 = covov->t1(); 40753 | const Type& v1 = covov->t2(); 40754 | const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); 40755 | const details::operator_type o0 = expr_gen.get_operator(covov->f0()); 40756 | const details::operator_type o1 = expr_gen.get_operator(covov->f1()); 40757 | const details::operator_type o2 = operation; 40758 | 40759 | binary_functor_t f0 = covov->f0(); 40760 | binary_functor_t f1 = covov->f1(); 40761 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); 40762 | 40763 | details::free_node(*(expr_gen.node_allocator_),branch[0]); 40764 | details::free_node(*(expr_gen.node_allocator_),branch[1]); 40765 | 40766 | expression_node_ptr result = error_node(); 40767 | 40768 | const bool synthesis_result = 40769 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> 40770 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result); 40771 | 40772 | if (synthesis_result) 40773 | return result; 40774 | else if (!expr_gen.valid_operator(o2,f2)) 40775 | return error_node(); 40776 | 40777 | exprtk_debug(("((c0 o0 (v0 o1 v1)) o2 c1)\n")); 40778 | 40779 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2); 40780 | } 40781 | 40782 | static inline std::string id(expression_generator<Type>& expr_gen, 40783 | const details::operator_type o0, 40784 | const details::operator_type o1, 40785 | const details::operator_type o2) 40786 | { 40787 | return details::build_string() 40788 | << "(t" << expr_gen.to_str(o0) 40789 | << "(t" << expr_gen.to_str(o1) 40790 | << "t)" << expr_gen.to_str(o2) 40791 | << "t" 40792 | } 40793 | }; 40794 | 40795 | struct synthesize_vococov_expression4 40796 | { 40797 | typedef typename vococov_t::type4 node_type; 40798 | static inline expression_node_ptr process(expression_generator<Type>&, 40799 | const details::operator_type&, 40800 | expression_node_ptr (&)[2]) 40801 | { 40802 | // ((v0 o0 (c0 o1 c1)) o2 v1) - Not possible 40803 | exprtk_debug(("((v0 o0 (c0 o1 c1)) o2 v1) - Not possible\n")); 40804 | return error_node(); 40805 | } 40806 | 40807 | static inline std::string id(expression_generator<Type>&, 40808 | const details::operator_type, 40809 | const details::operator_type, 40810 | const details::operator_type) 40811 | { 40812 | return "INVALID" 40813 | } 40814 | }; 40815 | #endif 40816 | 40817 | inline expression_node_ptr synthesize_uvouv_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2]) 40818 | { 40819 | // Definition: uv o uv 40820 | details::operator_type o0 = static_cast<details::uv_base_node<Type>*>(branch[0])->operation(); 40821 | details::operator_type o1 = static_cast<details::uv_base_node<Type>*>(branch[1])->operation(); 40822 | const Type& v0 = static_cast<details::uv_base_node<Type>*>(branch[0])->v(); 40823 | const Type& v1 = static_cast<details::uv_base_node<Type>*>(branch[1])->v(); 40824 | unary_functor_t u0 = reinterpret_cast<unary_functor_t> (0); 40825 | unary_functor_t u1 = reinterpret_cast<unary_functor_t> (0); 40826 | binary_functor_t f = reinterpret_cast<binary_functor_t>(0); 40827 | 40828 | if (!valid_operator(o0,u0)) 40829 | return error_node(); 40830 | else if (!valid_operator(o1,u1)) 40831 | return error_node(); 40832 | else if (!valid_operator(operation,f)) 40833 | return error_node(); 40834 | 40835 | expression_node_ptr result = error_node(); 40836 | 40837 | if ( 40838 | (details::e_neg == o0) && 40839 | (details::e_neg == o1) 40840 | ) 40841 | { 40842 | switch (operation) 40843 | { 40844 | // (-v0 + -v1) --> -(v0 + v1) 40845 | case details::e_add : result = (*this)(details::e_neg, 40846 | node_allocator_-> 40847 | allocate_rr<typename details:: 40848 | vov_node<Type,details::add_op<Type> > >(v0, v1)); 40849 | exprtk_debug(("(-v0 + -v1) --> -(v0 + v1)\n")); 40850 | break; 40851 | 40852 | // (-v0 - -v1) --> (v1 - v0) 40853 | case details::e_sub : result = node_allocator_-> 40854 | allocate_rr<typename details:: 40855 | vov_node<Type,details::sub_op<Type> > >(v1, v0); 40856 | exprtk_debug(("(-v0 - -v1) --> (v1 - v0)\n")); 40857 | break; 40858 | 40859 | // (-v0 * -v1) --> (v0 * v1) 40860 | case details::e_mul : result = node_allocator_-> 40861 | allocate_rr<typename details:: 40862 | vov_node<Type,details::mul_op<Type> > >(v0, v1); 40863 | exprtk_debug(("(-v0 * -v1) --> (v0 * v1)\n")); 40864 | break; 40865 | 40866 | // (-v0 / -v1) --> (v0 / v1) 40867 | case details::e_div : result = node_allocator_-> 40868 | allocate_rr<typename details:: 40869 | vov_node<Type,details::div_op<Type> > >(v0, v1); 40870 | exprtk_debug(("(-v0 / -v1) --> (v0 / v1)\n")); 40871 | break; 40872 | 40873 | default : break; 40874 | } 40875 | } 40876 | 40877 | if (0 == result) 40878 | { 40879 | result = node_allocator_-> 40880 | allocate_rrrrr<typename details::uvouv_node<Type> >(v0, v1, u0, u1, f); 40881 | } 40882 | 40883 | details::free_all_nodes(*node_allocator_,branch); 40884 | return result; 40885 | } 40886 | 40887 | #undef basic_opr_switch_statements 40888 | #undef extended_opr_switch_statements 40889 | #undef unary_opr_switch_statements 40890 | 40891 | #ifndef exprtk_disable_string_capabilities 40892 | 40893 | #define string_opr_switch_statements \ 40894 | case_stmt(details::e_lt , details::lt_op ) \ 40895 | case_stmt(details::e_lte , details::lte_op ) \ 40896 | case_stmt(details::e_gt , details::gt_op ) \ 40897 | case_stmt(details::e_gte , details::gte_op ) \ 40898 | case_stmt(details::e_eq , details::eq_op ) \ 40899 | case_stmt(details::e_ne , details::ne_op ) \ 40900 | case_stmt(details::e_in , details::in_op ) \ 40901 | case_stmt(details::e_like , details::like_op ) \ 40902 | case_stmt(details::e_ilike , details::ilike_op) \ 40903 | 40904 | template <typename T0, typename T1> 40905 | inline expression_node_ptr synthesize_str_xrox_expression_impl(const details::operator_type& opr, 40906 | T0 s0, T1 s1, 40907 | range_t rp0) 40908 | { 40909 | switch (opr) 40910 | { 40911 | #define case_stmt(op0, op1) \ 40912 | case op0 : return node_allocator_-> \ 40913 | allocate_ttt<typename details::str_xrox_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \ 40914 | (s0, s1, rp0); \ 40915 | 40916 | string_opr_switch_statements 40917 | #undef case_stmt 40918 | default : return error_node(); 40919 | } 40920 | } 40921 | 40922 | template <typename T0, typename T1> 40923 | inline expression_node_ptr synthesize_str_xoxr_expression_impl(const details::operator_type& opr, 40924 | T0 s0, T1 s1, 40925 | range_t rp1) 40926 | { 40927 | switch (opr) 40928 | { 40929 | #define case_stmt(op0, op1) \ 40930 | case op0 : return node_allocator_-> \ 40931 | allocate_ttt<typename details::str_xoxr_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \ 40932 | (s0, s1, rp1); \ 40933 | 40934 | string_opr_switch_statements 40935 | #undef case_stmt 40936 | default : return error_node(); 40937 | } 40938 | } 40939 | 40940 | template <typename T0, typename T1> 40941 | inline expression_node_ptr synthesize_str_xroxr_expression_impl(const details::operator_type& opr, 40942 | T0 s0, T1 s1, 40943 | range_t rp0, range_t rp1) 40944 | { 40945 | switch (opr) 40946 | { 40947 | #define case_stmt(op0, op1) \ 40948 | case op0 : return node_allocator_-> \ 40949 | allocate_tttt<typename details::str_xroxr_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \ 40950 | (s0, s1, rp0, rp1); \ 40951 | 40952 | string_opr_switch_statements 40953 | #undef case_stmt 40954 | default : return error_node(); 40955 | } 40956 | } 40957 | 40958 | template <typename T0, typename T1> 40959 | inline expression_node_ptr synthesize_sos_expression_impl(const details::operator_type& opr, T0 s0, T1 s1) 40960 | { 40961 | switch (opr) 40962 | { 40963 | #define case_stmt(op0, op1) \ 40964 | case op0 : return node_allocator_-> \ 40965 | allocate_tt<typename details::sos_node<Type,T0,T1,op1<Type> >,T0,T1>(s0, s1); \ 40966 | 40967 | string_opr_switch_statements 40968 | #undef case_stmt 40969 | default : return error_node(); 40970 | } 40971 | } 40972 | 40973 | inline expression_node_ptr synthesize_sos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 40974 | { 40975 | std::string& s0 = static_cast<details::stringvar_node<Type>*>(branch[0])->ref(); 40976 | std::string& s1 = static_cast<details::stringvar_node<Type>*>(branch[1])->ref(); 40977 | 40978 | return synthesize_sos_expression_impl<std::string&,std::string&>(opr, s0, s1); 40979 | } 40980 | 40981 | inline expression_node_ptr synthesize_sros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 40982 | { 40983 | std::string& s0 = static_cast<details::string_range_node<Type>*>(branch[0])->ref (); 40984 | std::string& s1 = static_cast<details::stringvar_node<Type>*> (branch[1])->ref (); 40985 | range_t rp0 = static_cast<details::string_range_node<Type>*>(branch[0])->range(); 40986 | 40987 | static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear(); 40988 | 40989 | details::free_node(*node_allocator_,branch[0]); 40990 | 40991 | return synthesize_str_xrox_expression_impl<std::string&,std::string&>(opr, s0, s1, rp0); 40992 | } 40993 | 40994 | inline expression_node_ptr synthesize_sosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 40995 | { 40996 | std::string& s0 = static_cast<details::stringvar_node<Type>*> (branch[0])->ref (); 40997 | std::string& s1 = static_cast<details::string_range_node<Type>*>(branch[1])->ref (); 40998 | range_t rp1 = static_cast<details::string_range_node<Type>*>(branch[1])->range(); 40999 | 41000 | static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear(); 41001 | 41002 | details::free_node(*node_allocator_,branch[1]); 41003 | 41004 | return synthesize_str_xoxr_expression_impl<std::string&,std::string&>(opr, s0, s1, rp1); 41005 | } 41006 | 41007 | inline expression_node_ptr synthesize_socsr_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::const_string_range_node<Type>*>(branch[1])->str (); 41011 | range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range(); 41012 | 41013 | static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear(); 41014 | 41015 | details::free_node(*node_allocator_,branch[1]); 41016 | 41017 | return synthesize_str_xoxr_expression_impl<std::string&, const std::string>(opr, s0, s1, rp1); 41018 | } 41019 | 41020 | inline expression_node_ptr synthesize_srosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41021 | { 41022 | std::string& s0 = static_cast<details::string_range_node<Type>*>(branch[0])->ref (); 41023 | std::string& s1 = static_cast<details::string_range_node<Type>*>(branch[1])->ref (); 41024 | range_t rp0 = static_cast<details::string_range_node<Type>*>(branch[0])->range(); 41025 | range_t rp1 = static_cast<details::string_range_node<Type>*>(branch[1])->range(); 41026 | 41027 | static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear(); 41028 | static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear(); 41029 | 41030 | details::free_node(*node_allocator_,branch[0]); 41031 | details::free_node(*node_allocator_,branch[1]); 41032 | 41033 | return synthesize_str_xroxr_expression_impl<std::string&,std::string&>(opr, s0, s1, rp0, rp1); 41034 | } 41035 | 41036 | inline expression_node_ptr synthesize_socs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41037 | { 41038 | std::string& s0 = static_cast< details::stringvar_node<Type>*>(branch[0])->ref(); 41039 | std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str(); 41040 | 41041 | details::free_node(*node_allocator_,branch[1]); 41042 | 41043 | return synthesize_sos_expression_impl<std::string&, const std::string>(opr, s0, s1); 41044 | } 41045 | 41046 | inline expression_node_ptr synthesize_csos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41047 | { 41048 | std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str(); 41049 | std::string& s1 = static_cast<details::stringvar_node<Type>* >(branch[1])->ref(); 41050 | 41051 | details::free_node(*node_allocator_,branch[0]); 41052 | 41053 | return synthesize_sos_expression_impl<const std::string,std::string&>(opr, s0, s1); 41054 | } 41055 | 41056 | inline expression_node_ptr synthesize_csosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41057 | { 41058 | std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str (); 41059 | std::string& s1 = static_cast<details::string_range_node<Type>* >(branch[1])->ref (); 41060 | range_t rp1 = static_cast<details::string_range_node<Type>* >(branch[1])->range(); 41061 | 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_xoxr_expression_impl<const std::string,std::string&>(opr, s0, s1, rp1); 41068 | } 41069 | 41070 | inline expression_node_ptr synthesize_srocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41071 | { 41072 | std::string& s0 = static_cast<details::string_range_node<Type>* >(branch[0])->ref (); 41073 | std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str (); 41074 | range_t rp0 = static_cast<details::string_range_node<Type>* >(branch[0])->range(); 41075 | 41076 | static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear(); 41077 | 41078 | details::free_node(*node_allocator_,branch[0]); 41079 | details::free_node(*node_allocator_,branch[1]); 41080 | 41081 | return synthesize_str_xrox_expression_impl<std::string&, const std::string>(opr, s0, s1, rp0); 41082 | } 41083 | 41084 | inline expression_node_ptr synthesize_srocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41085 | { 41086 | std::string& s0 = static_cast<details::string_range_node<Type>* >(branch[0])->ref (); 41087 | std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str (); 41088 | range_t rp0 = static_cast<details::string_range_node<Type>* >(branch[0])->range(); 41089 | range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range(); 41090 | 41091 | static_cast<details::string_range_node<Type>*> (branch[0])->range_ref().clear(); 41092 | static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear(); 41093 | 41094 | details::free_node(*node_allocator_,branch[0]); 41095 | details::free_node(*node_allocator_,branch[1]); 41096 | 41097 | return synthesize_str_xroxr_expression_impl<std::string&, const std::string>(opr, s0, s1, rp0, rp1); 41098 | } 41099 | 41100 | inline expression_node_ptr synthesize_csocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41101 | { 41102 | const std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str(); 41103 | const std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str(); 41104 | 41105 | expression_node_ptr result = error_node(); 41106 | 41107 | if (details::e_add == opr) 41108 | result = node_allocator_->allocate_c<details::string_literal_node<Type> >(s0 + s1); 41109 | else if (details::e_in == opr) 41110 | result = node_allocator_->allocate_c<details::literal_node<Type> >(details::in_op <Type>::process(s0,s1)); 41111 | else if (details::e_like == opr) 41112 | result = node_allocator_->allocate_c<details::literal_node<Type> >(details::like_op <Type>::process(s0,s1)); 41113 | else if (details::e_ilike == opr) 41114 | result = node_allocator_->allocate_c<details::literal_node<Type> >(details::ilike_op<Type>::process(s0,s1)); 41115 | else 41116 | { 41117 | expression_node_ptr temp = synthesize_sos_expression_impl<const std::string, const std::string>(opr, s0, s1); 41118 | 41119 | const Type v = temp->value(); 41120 | 41121 | details::free_node(*node_allocator_,temp); 41122 | 41123 | result = node_allocator_->allocate<literal_node_t>(v); 41124 | } 41125 | 41126 | details::free_all_nodes(*node_allocator_,branch); 41127 | 41128 | return result; 41129 | } 41130 | 41131 | inline expression_node_ptr synthesize_csocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41132 | { 41133 | const std::string s0 = static_cast<details::string_literal_node<Type>* >(branch[0])->str (); 41134 | std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str (); 41135 | range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range(); 41136 | 41137 | static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear(); 41138 | 41139 | details::free_node(*node_allocator_,branch[0]); 41140 | details::free_node(*node_allocator_,branch[1]); 41141 | 41142 | return synthesize_str_xoxr_expression_impl<const std::string, const std::string>(opr, s0, s1, rp1); 41143 | } 41144 | 41145 | inline expression_node_ptr synthesize_csros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41146 | { 41147 | std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str (); 41148 | std::string& s1 = static_cast<details::stringvar_node<Type>* >(branch[1])->ref (); 41149 | range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range(); 41150 | 41151 | static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear(); 41152 | 41153 | details::free_node(*node_allocator_,branch[0]); 41154 | 41155 | return synthesize_str_xrox_expression_impl<const std::string,std::string&>(opr, s0, s1, rp0); 41156 | } 41157 | 41158 | inline expression_node_ptr synthesize_csrosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41159 | { 41160 | const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str (); 41161 | std::string& s1 = static_cast<details::string_range_node<Type>* >(branch[1])->ref (); 41162 | const range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range(); 41163 | const range_t rp1 = static_cast<details::string_range_node<Type>* >(branch[1])->range(); 41164 | 41165 | static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear(); 41166 | static_cast<details::string_range_node<Type>*> (branch[1])->range_ref().clear(); 41167 | 41168 | details::free_node(*node_allocator_,branch[0]); 41169 | details::free_node(*node_allocator_,branch[1]); 41170 | 41171 | return synthesize_str_xroxr_expression_impl<const std::string,std::string&>(opr, s0, s1, rp0, rp1); 41172 | } 41173 | 41174 | inline expression_node_ptr synthesize_csrocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41175 | { 41176 | const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str (); 41177 | const std::string s1 = static_cast<details::string_literal_node<Type>* >(branch[1])->str (); 41178 | const range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range(); 41179 | 41180 | static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear(); 41181 | 41182 | details::free_all_nodes(*node_allocator_,branch); 41183 | 41184 | return synthesize_str_xrox_expression_impl<const std::string,std::string>(opr, s0, s1, rp0); 41185 | } 41186 | 41187 | inline expression_node_ptr synthesize_csrocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41188 | { 41189 | const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str (); 41190 | const std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str (); 41191 | const range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range(); 41192 | const range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range(); 41193 | 41194 | static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear(); 41195 | static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear(); 41196 | 41197 | details::free_all_nodes(*node_allocator_,branch); 41198 | 41199 | return synthesize_str_xroxr_expression_impl<const std::string, const std::string>(opr, s0, s1, rp0, rp1); 41200 | } 41201 | 41202 | inline expression_node_ptr synthesize_strogen_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41203 | { 41204 | switch (opr) 41205 | { 41206 | #define case_stmt(op0, op1) \ 41207 | case op0 : return node_allocator_-> \ 41208 | allocate_ttt<typename details::str_sogens_node<Type,op1<Type> > > \ 41209 | (opr, branch[0], branch[1]); \ 41210 | 41211 | string_opr_switch_statements 41212 | #undef case_stmt 41213 | default : return error_node(); 41214 | } 41215 | } 41216 | 41217 | #undef string_opr_switch_statements 41218 | #endif 41219 | 41220 | #ifndef exprtk_disable_string_capabilities 41221 | inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) 41222 | { 41223 | if ((0 == branch[0]) || (0 == branch[1])) 41224 | { 41225 | details::free_all_nodes(*node_allocator_,branch); 41226 | 41227 | return error_node(); 41228 | } 41229 | 41230 | const bool b0_is_s = details::is_string_node (branch[0]); 41231 | const bool b0_is_cs = details::is_const_string_node (branch[0]); 41232 | const bool b0_is_sr = details::is_string_range_node (branch[0]); 41233 | const bool b0_is_csr = details::is_const_string_range_node(branch[0]); 41234 | 41235 | const bool b1_is_s = details::is_string_node (branch[1]); 41236 | const bool b1_is_cs = details::is_const_string_node (branch[1]); 41237 | const bool b1_is_sr = details::is_string_range_node (branch[1]); 41238 | const bool b1_is_csr = details::is_const_string_range_node(branch[1]); 41239 | 41240 | const bool b0_is_gen = details::is_string_assignment_node (branch[0]) || 41241 | details::is_genricstring_range_node(branch[0]) || 41242 | details::is_string_concat_node (branch[0]) || 41243 | details::is_string_function_node (branch[0]) || 41244 | details::is_string_condition_node (branch[0]) || 41245 | details::is_string_ccondition_node (branch[0]) || 41246 | details::is_string_vararg_node (branch[0]) ; 41247 | 41248 | const bool b1_is_gen = details::is_string_assignment_node (branch[1]) || 41249 | details::is_genricstring_range_node(branch[1]) || 41250 | details::is_string_concat_node (branch[1]) || 41251 | details::is_string_function_node (branch[1]) || 41252 | details::is_string_condition_node (branch[1]) || 41253 | details::is_string_ccondition_node (branch[1]) || 41254 | details::is_string_vararg_node (branch[1]) ; 41255 | 41256 | if (details::e_add == opr) 41257 | { 41258 | if (!b0_is_cs || !b1_is_cs) 41259 | { 41260 | return synthesize_expression<string_concat_node_t,2>(opr,branch); 41261 | } 41262 | } 41263 | 41264 | if (b0_is_gen || b1_is_gen) 41265 | { 41266 | return synthesize_strogen_expression(opr,branch); 41267 | } 41268 | else if (b0_is_s) 41269 | { 41270 | if (b1_is_s ) return synthesize_sos_expression (opr,branch); 41271 | else if (b1_is_cs ) return synthesize_socs_expression (opr,branch); 41272 | else if (b1_is_sr ) return synthesize_sosr_expression (opr,branch); 41273 | else if (b1_is_csr) return synthesize_socsr_expression (opr,branch); 41274 | } 41275 | else if (b0_is_cs) 41276 | { 41277 | if (b1_is_s ) return synthesize_csos_expression (opr,branch); 41278 | else if (b1_is_cs ) return synthesize_csocs_expression (opr,branch); 41279 | else if (b1_is_sr ) return synthesize_csosr_expression (opr,branch); 41280 | else if (b1_is_csr) return synthesize_csocsr_expression(opr,branch); 41281 | } 41282 | else if (b0_is_sr) 41283 | { 41284 | if (b1_is_s ) return synthesize_sros_expression (opr,branch); 41285 | else if (b1_is_sr ) return synthesize_srosr_expression (opr,branch); 41286 | else if (b1_is_cs ) return synthesize_srocs_expression (opr,branch); 41287 | else if (b1_is_csr) return synthesize_srocsr_expression(opr,branch); 41288 | } 41289 | else if (b0_is_csr) 41290 | { 41291 | if (b1_is_s ) return synthesize_csros_expression (opr,branch); 41292 | else if (b1_is_sr ) return synthesize_csrosr_expression (opr,branch); 41293 | else if (b1_is_cs ) return synthesize_csrocs_expression (opr,branch); 41294 | else if (b1_is_csr) return synthesize_csrocsr_expression(opr,branch); 41295 | } 41296 | 41297 | return error_node(); 41298 | } 41299 | #else 41300 | inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&branch)[2]) 41301 | { 41302 | details::free_all_nodes(*node_allocator_,branch); 41303 | return error_node(); 41304 | } 41305 | #endif 41306 | 41307 | #ifndef exprtk_disable_string_capabilities 41308 | inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[3]) 41309 | { 41310 | if (details::e_inrange != opr) 41311 | return error_node(); 41312 | else if ((0 == branch[0]) || (0 == branch[1]) || (0 == branch[2])) 41313 | { 41314 | details::free_all_nodes(*node_allocator_,branch); 41315 | 41316 | return error_node(); 41317 | } 41318 | else if ( 41319 | details::is_const_string_node(branch[0]) && 41320 | details::is_const_string_node(branch[1]) && 41321 | details::is_const_string_node(branch[2]) 41322 | ) 41323 | { 41324 | const std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str(); 41325 | const std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str(); 41326 | const std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str(); 41327 | 41328 | const Type v = (((s0 <= s1) && (s1 <= s2)) ? Type(1) : Type(0)); 41329 | 41330 | details::free_all_nodes(*node_allocator_,branch); 41331 | 41332 | return node_allocator_->allocate_c<details::literal_node<Type> >(v); 41333 | } 41334 | else if ( 41335 | details::is_string_node(branch[0]) && 41336 | details::is_string_node(branch[1]) && 41337 | details::is_string_node(branch[2]) 41338 | ) 41339 | { 41340 | std::string& s0 = static_cast<details::stringvar_node<Type>*>(branch[0])->ref(); 41341 | std::string& s1 = static_cast<details::stringvar_node<Type>*>(branch[1])->ref(); 41342 | std::string& s2 = static_cast<details::stringvar_node<Type>*>(branch[2])->ref(); 41343 | 41344 | typedef typename details::sosos_node<Type, std::string&, std::string&, std::string&, details::inrange_op<Type> > inrange_t; 41345 | 41346 | return node_allocator_->allocate_type<inrange_t, std::string&, std::string&, std::string&>(s0, s1, s2); 41347 | } 41348 | else if ( 41349 | details::is_const_string_node(branch[0]) && 41350 | details::is_string_node(branch[1]) && 41351 | details::is_const_string_node(branch[2]) 41352 | ) 41353 | { 41354 | std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str(); 41355 | std::string& s1 = static_cast<details::stringvar_node<Type>* >(branch[1])->ref(); 41356 | std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str(); 41357 | 41358 | typedef typename details::sosos_node<Type, std::string, std::string&, std::string, details::inrange_op<Type> > inrange_t; 41359 | 41360 | details::free_node(*node_allocator_,branch[0]); 41361 | details::free_node(*node_allocator_,branch[2]); 41362 | 41363 | return node_allocator_->allocate_type<inrange_t, std::string, std::string&, std::string>(s0, s1, s2); 41364 | } 41365 | else if ( 41366 | details::is_string_node(branch[0]) && 41367 | details::is_const_string_node(branch[1]) && 41368 | details::is_string_node(branch[2]) 41369 | ) 41370 | { 41371 | std::string& s0 = static_cast<details::stringvar_node<Type>* >(branch[0])->ref(); 41372 | std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str(); 41373 | std::string& s2 = static_cast<details::stringvar_node<Type>* >(branch[2])->ref(); 41374 | 41375 | typedef typename details::sosos_node<Type, std::string&, std::string, std::string&, details::inrange_op<Type> > inrange_t; 41376 | 41377 | details::free_node(*node_allocator_,branch[1]); 41378 | 41379 | return node_allocator_->allocate_type<inrange_t, std::string&, std::string, std::string&>(s0, s1, s2); 41380 | } 41381 | else if ( 41382 | details::is_string_node(branch[0]) && 41383 | details::is_string_node(branch[1]) && 41384 | details::is_const_string_node(branch[2]) 41385 | ) 41386 | { 41387 | std::string& s0 = static_cast<details::stringvar_node<Type>* >(branch[0])->ref(); 41388 | std::string& s1 = static_cast<details::stringvar_node<Type>* >(branch[1])->ref(); 41389 | std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str(); 41390 | 41391 | typedef typename details::sosos_node<Type, std::string&, std::string&, std::string, details::inrange_op<Type> > inrange_t; 41392 | 41393 | details::free_node(*node_allocator_,branch[2]); 41394 | 41395 | return node_allocator_->allocate_type<inrange_t, std::string&, std::string&, std::string>(s0, s1, s2); 41396 | } 41397 | else if ( 41398 | details::is_const_string_node(branch[0]) && 41399 | details:: is_string_node(branch[1]) && 41400 | details:: is_string_node(branch[2]) 41401 | ) 41402 | { 41403 | std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str(); 41404 | std::string& s1 = static_cast<details::stringvar_node<Type>* >(branch[1])->ref(); 41405 | std::string& s2 = static_cast<details::stringvar_node<Type>* >(branch[2])->ref(); 41406 | 41407 | typedef typename details::sosos_node<Type, std::string, std::string&, std::string&, details::inrange_op<Type> > inrange_t; 41408 | 41409 | details::free_node(*node_allocator_,branch[0]); 41410 | 41411 | return node_allocator_->allocate_type<inrange_t, std::string, std::string&, std::string&>(s0, s1, s2); 41412 | } 41413 | else 41414 | return error_node(); 41415 | } 41416 | #else 41417 | inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&branch)[3]) 41418 | { 41419 | details::free_all_nodes(*node_allocator_,branch); 41420 | return error_node(); 41421 | } 41422 | #endif 41423 | 41424 | inline expression_node_ptr synthesize_null_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2]) 41425 | { 41426 | /* 41427 | Note: The following are the type promotion rules 41428 | that relate to operations that include 'null': 41429 | 0. null ==/!= null --> true false 41430 | 1. null operation null --> null 41431 | 2. x ==/!= null --> true/false 41432 | 3. null ==/!= x --> true/false 41433 | 4. x operation null --> x 41434 | 5. null operation x --> x 41435 | */ 41436 | 41437 | typedef typename details::null_eq_node<T> nulleq_node_t; 41438 | 41439 | const bool b0_null = details::is_null_node(branch[0]); 41440 | const bool b1_null = details::is_null_node(branch[1]); 41441 | 41442 | if (b0_null && b1_null) 41443 | { 41444 | expression_node_ptr result = error_node(); 41445 | 41446 | if (details::e_eq == operation) 41447 | result = node_allocator_->allocate_c<literal_node_t>(T(1)); 41448 | else if (details::e_ne == operation) 41449 | result = node_allocator_->allocate_c<literal_node_t>(T(0)); 41450 | 41451 | if (result) 41452 | { 41453 | details::free_node(*node_allocator_,branch[0]); 41454 | details::free_node(*node_allocator_,branch[1]); 41455 | 41456 | return result; 41457 | } 41458 | 41459 | details::free_node(*node_allocator_,branch[1]); 41460 | 41461 | return branch[0]; 41462 | } 41463 | else if (details::e_eq == operation) 41464 | { 41465 | expression_node_ptr result = node_allocator_-> 41466 | allocate_rc<nulleq_node_t>(branch[b0_null ? 0 : 1],true); 41467 | 41468 | details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]); 41469 | 41470 | return result; 41471 | } 41472 | else if (details::e_ne == operation) 41473 | { 41474 | expression_node_ptr result = node_allocator_-> 41475 | allocate_rc<nulleq_node_t>(branch[b0_null ? 0 : 1],false); 41476 | 41477 | details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]); 41478 | 41479 | return result; 41480 | } 41481 | else if (b0_null) 41482 | { 41483 | details::free_node(*node_allocator_,branch[0]); 41484 | branch[0] = branch[1]; 41485 | branch[1] = error_node(); 41486 | } 41487 | else if (b1_null) 41488 | { 41489 | details::free_node(*node_allocator_,branch[1]); 41490 | branch[1] = error_node(); 41491 | } 41492 | 41493 | if ( 41494 | (details::e_add == operation) || (details::e_sub == operation) || 41495 | (details::e_mul == operation) || (details::e_div == operation) || 41496 | (details::e_mod == operation) || (details::e_pow == operation) 41497 | ) 41498 | { 41499 | return branch[0]; 41500 | } 41501 | 41502 | details::free_node(*node_allocator_, branch[0]); 41503 | 41504 | if ( 41505 | (details::e_lt == operation) || (details::e_lte == operation) || 41506 | (details::e_gt == operation) || (details::e_gte == operation) || 41507 | (details::e_and == operation) || (details::e_nand == operation) || 41508 | (details::e_or == operation) || (details::e_nor == operation) || 41509 | (details::e_xor == operation) || (details::e_xnor == operation) || 41510 | (details::e_in == operation) || (details::e_like == operation) || 41511 | (details::e_ilike == operation) 41512 | ) 41513 | { 41514 | return node_allocator_->allocate_c<literal_node_t>(T(0)); 41515 | } 41516 | 41517 | return node_allocator_->allocate<details::null_node<Type> >(); 41518 | } 41519 | 41520 | template <typename NodeType, std::size_t N> 41521 | inline expression_node_ptr synthesize_expression(const details::operator_type& operation, expression_node_ptr (&branch)[N]) 41522 | { 41523 | if ( 41524 | (details::e_in == operation) || 41525 | (details::e_like == operation) || 41526 | (details::e_ilike == operation) 41527 | ) 41528 | { 41529 | free_all_nodes(*node_allocator_,branch); 41530 | 41531 | return error_node(); 41532 | } 41533 | else if (!details::all_nodes_valid<N>(branch)) 41534 | { 41535 | free_all_nodes(*node_allocator_,branch); 41536 | 41537 | return error_node(); 41538 | } 41539 | else if ((details::e_default != operation)) 41540 | { 41541 | // Attempt simple constant folding optimisation. 41542 | expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(operation,branch); 41543 | 41544 | if (is_constant_foldable<N>(branch)) 41545 | { 41546 | const Type v = expression_point->value(); 41547 | details::free_node(*node_allocator_,expression_point); 41548 | 41549 | return node_allocator_->allocate<literal_node_t>(v); 41550 | } 41551 | 41552 | if (expression_point && expression_point->valid()) 41553 | { 41554 | return expression_point; 41555 | } 41556 | 41557 | parser_->set_error(parser_error::make_error( 41558 | parser_error::e_parser, 41559 | token_t(), 41560 | "ERR280 - Failed to synthesize node: NodeType", 41561 | exprtk_error_location)); 41562 | 41563 | details::free_node(*node_allocator_, expression_point); 41564 | } 41565 | 41566 | return error_node(); 41567 | } 41568 | 41569 | template <typename NodeType, std::size_t N> 41570 | inline expression_node_ptr synthesize_expression(F* f, expression_node_ptr (&branch)[N]) 41571 | { 41572 | if (!details::all_nodes_valid<N>(branch)) 41573 | { 41574 | free_all_nodes(*node_allocator_,branch); 41575 | 41576 | return error_node(); 41577 | } 41578 | 41579 | typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t; 41580 | 41581 | // Attempt simple constant folding optimisation. 41582 | 41583 | expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(f); 41584 | function_N_node_t* func_node_ptr = dynamic_cast<function_N_node_t*>(expression_point); 41585 | 41586 | if (0 == func_node_ptr) 41587 | { 41588 | free_all_nodes(*node_allocator_,branch); 41589 | 41590 | return error_node(); 41591 | } 41592 | else 41593 | func_node_ptr->init_branches(branch); 41594 | 41595 | if (is_constant_foldable<N>(branch) && !f->has_side_effects()) 41596 | { 41597 | Type v = expression_point->value(); 41598 | details::free_node(*node_allocator_,expression_point); 41599 | 41600 | return node_allocator_->allocate<literal_node_t>(v); 41601 | } 41602 | 41603 | parser_->state_.activate_side_effect("synthesize_expression(function<NT,N>)"); 41604 | 41605 | return expression_point; 41606 | } 41607 | 41608 | bool strength_reduction_enabled_; 41609 | details::node_allocator* node_allocator_; 41610 | synthesize_map_t synthesize_map_; 41611 | unary_op_map_t* unary_op_map_; 41612 | binary_op_map_t* binary_op_map_; 41613 | inv_binary_op_map_t* inv_binary_op_map_; 41614 | sf3_map_t* sf3_map_; 41615 | sf4_map_t* sf4_map_; 41616 | parser_t* parser_; 41617 | }; // class expression_generator 41618 | 41619 | inline void set_error(const parser_error::type& error_type) 41620 | { 41621 | error_list_.push_back(error_type); 41622 | } 41623 | 41624 | inline void remove_last_error() 41625 | { 41626 | if (!error_list_.empty()) 41627 | { 41628 | error_list_.pop_back(); 41629 | } 41630 | } 41631 | 41632 | inline void set_synthesis_error(const std::string& synthesis_error_message) 41633 | { 41634 | if (synthesis_error_.empty()) 41635 | { 41636 | synthesis_error_ = synthesis_error_message; 41637 | } 41638 | } 41639 | 41640 | inline void register_local_vars(expression<T>& e) 41641 | { 41642 | for (std::size_t i = 0; i < sem_.size(); ++i) 41643 | { 41644 | scope_element& se = sem_.get_element(i); 41645 | 41646 | exprtk_debug(("register_local_vars() - se[%s]\n", se.name.c_str())); 41647 | 41648 | if ( 41649 | (scope_element::e_variable == se.type) || 41650 | (scope_element::e_literal == se.type) || 41651 | (scope_element::e_vecelem == se.type) 41652 | ) 41653 | { 41654 | if (se.var_node) 41655 | { 41656 | e.register_local_var(se.var_node); 41657 | } 41658 | 41659 | if (se.data) 41660 | { 41661 | e.register_local_data(se.data, 1, 0); 41662 | } 41663 | } 41664 | else if (scope_element::e_vector == se.type) 41665 | { 41666 | if (se.vec_node) 41667 | { 41668 | e.register_local_var(se.vec_node); 41669 | } 41670 | 41671 | if (se.data) 41672 | { 41673 | e.register_local_data(se.data, se.size, 1); 41674 | } 41675 | } 41676 | #ifndef exprtk_disable_string_capabilities 41677 | else if (scope_element::e_string == se.type) 41678 | { 41679 | if (se.str_node) 41680 | { 41681 | e.register_local_var(se.str_node); 41682 | } 41683 | 41684 | if (se.data) 41685 | { 41686 | e.register_local_data(se.data, se.size, 2); 41687 | } 41688 | } 41689 | #endif 41690 | 41691 | se.var_node = 0; 41692 | se.vec_node = 0; 41693 | #ifndef exprtk_disable_string_capabilities 41694 | se.str_node = 0; 41695 | #endif 41696 | se.data = 0; 41697 | se.ref_count = 0; 41698 | se.active = false; 41699 | } 41700 | } 41701 | 41702 | inline void register_return_results(expression<T>& e) 41703 | { 41704 | e.register_return_results(results_context_); 41705 | results_context_ = 0; 41706 | } 41707 | 41708 | inline void load_unary_operations_map(unary_op_map_t& m) 41709 | { 41710 | #define register_unary_op(Op, UnaryFunctor) \ 41711 | m.insert(std::make_pair(Op,UnaryFunctor<T>::process)); \ 41712 | 41713 | register_unary_op(details::e_abs , details::abs_op ) 41714 | register_unary_op(details::e_acos , details::acos_op ) 41715 | register_unary_op(details::e_acosh , details::acosh_op) 41716 | register_unary_op(details::e_asin , details::asin_op ) 41717 | register_unary_op(details::e_asinh , details::asinh_op) 41718 | register_unary_op(details::e_atanh , details::atanh_op) 41719 | register_unary_op(details::e_ceil , details::ceil_op ) 41720 | register_unary_op(details::e_cos , details::cos_op ) 41721 | register_unary_op(details::e_cosh , details::cosh_op ) 41722 | register_unary_op(details::e_exp , details::exp_op ) 41723 | register_unary_op(details::e_expm1 , details::expm1_op) 41724 | register_unary_op(details::e_floor , details::floor_op) 41725 | register_unary_op(details::e_log , details::log_op ) 41726 | register_unary_op(details::e_log10 , details::log10_op) 41727 | register_unary_op(details::e_log2 , details::log2_op ) 41728 | register_unary_op(details::e_log1p , details::log1p_op) 41729 | register_unary_op(details::e_neg , details::neg_op ) 41730 | register_unary_op(details::e_pos , details::pos_op ) 41731 | register_unary_op(details::e_round , details::round_op) 41732 | register_unary_op(details::e_sin , details::sin_op ) 41733 | register_unary_op(details::e_sinc , details::sinc_op ) 41734 | register_unary_op(details::e_sinh , details::sinh_op ) 41735 | register_unary_op(details::e_sqrt , details::sqrt_op ) 41736 | register_unary_op(details::e_tan , details::tan_op ) 41737 | register_unary_op(details::e_tanh , details::tanh_op ) 41738 | register_unary_op(details::e_cot , details::cot_op ) 41739 | register_unary_op(details::e_sec , details::sec_op ) 41740 | register_unary_op(details::e_csc , details::csc_op ) 41741 | register_unary_op(details::e_r2d , details::r2d_op ) 41742 | register_unary_op(details::e_d2r , details::d2r_op ) 41743 | register_unary_op(details::e_d2g , details::d2g_op ) 41744 | register_unary_op(details::e_g2d , details::g2d_op ) 41745 | register_unary_op(details::e_notl , details::notl_op ) 41746 | register_unary_op(details::e_sgn , details::sgn_op ) 41747 | register_unary_op(details::e_erf , details::erf_op ) 41748 | register_unary_op(details::e_erfc , details::erfc_op ) 41749 | register_unary_op(details::e_ncdf , details::ncdf_op ) 41750 | register_unary_op(details::e_frac , details::frac_op ) 41751 | register_unary_op(details::e_trunc , details::trunc_op) 41752 | #undef register_unary_op 41753 | } 41754 | 41755 | inline void load_binary_operations_map(binary_op_map_t& m) 41756 | { 41757 | typedef typename binary_op_map_t::value_type value_type; 41758 | 41759 | #define register_binary_op(Op, BinaryFunctor) \ 41760 | m.insert(value_type(Op,BinaryFunctor<T>::process)); \ 41761 | 41762 | register_binary_op(details::e_add , details::add_op ) 41763 | register_binary_op(details::e_sub , details::sub_op ) 41764 | register_binary_op(details::e_mul , details::mul_op ) 41765 | register_binary_op(details::e_div , details::div_op ) 41766 | register_binary_op(details::e_mod , details::mod_op ) 41767 | register_binary_op(details::e_pow , details::pow_op ) 41768 | register_binary_op(details::e_lt , details::lt_op ) 41769 | register_binary_op(details::e_lte , details::lte_op ) 41770 | register_binary_op(details::e_gt , details::gt_op ) 41771 | register_binary_op(details::e_gte , details::gte_op ) 41772 | register_binary_op(details::e_eq , details::eq_op ) 41773 | register_binary_op(details::e_ne , details::ne_op ) 41774 | register_binary_op(details::e_and , details::and_op ) 41775 | register_binary_op(details::e_nand , details::nand_op) 41776 | register_binary_op(details::e_or , details::or_op ) 41777 | register_binary_op(details::e_nor , details::nor_op ) 41778 | register_binary_op(details::e_xor , details::xor_op ) 41779 | register_binary_op(details::e_xnor , details::xnor_op) 41780 | #undef register_binary_op 41781 | } 41782 | 41783 | inline void load_inv_binary_operations_map(inv_binary_op_map_t& m) 41784 | { 41785 | typedef typename inv_binary_op_map_t::value_type value_type; 41786 | 41787 | #define register_binary_op(Op, BinaryFunctor) \ 41788 | m.insert(value_type(BinaryFunctor<T>::process,Op)); \ 41789 | 41790 | register_binary_op(details::e_add , details::add_op ) 41791 | register_binary_op(details::e_sub , details::sub_op ) 41792 | register_binary_op(details::e_mul , details::mul_op ) 41793 | register_binary_op(details::e_div , details::div_op ) 41794 | register_binary_op(details::e_mod , details::mod_op ) 41795 | register_binary_op(details::e_pow , details::pow_op ) 41796 | register_binary_op(details::e_lt , details::lt_op ) 41797 | register_binary_op(details::e_lte , details::lte_op ) 41798 | register_binary_op(details::e_gt , details::gt_op ) 41799 | register_binary_op(details::e_gte , details::gte_op ) 41800 | register_binary_op(details::e_eq , details::eq_op ) 41801 | register_binary_op(details::e_ne , details::ne_op ) 41802 | register_binary_op(details::e_and , details::and_op ) 41803 | register_binary_op(details::e_nand , details::nand_op) 41804 | register_binary_op(details::e_or , details::or_op ) 41805 | register_binary_op(details::e_nor , details::nor_op ) 41806 | register_binary_op(details::e_xor , details::xor_op ) 41807 | register_binary_op(details::e_xnor , details::xnor_op) 41808 | #undef register_binary_op 41809 | } 41810 | 41811 | inline void load_sf3_map(sf3_map_t& sf3_map) 41812 | { 41813 | typedef std::pair<trinary_functor_t,details::operator_type> pair_t; 41814 | 41815 | #define register_sf3(Op) \ 41816 | sf3_map[details::sf##Op##_op<T>::id()] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \ 41817 | 41818 | register_sf3(00) register_sf3(01) register_sf3(02) register_sf3(03) 41819 | register_sf3(04) register_sf3(05) register_sf3(06) register_sf3(07) 41820 | register_sf3(08) register_sf3(09) register_sf3(10) register_sf3(11) 41821 | register_sf3(12) register_sf3(13) register_sf3(14) register_sf3(15) 41822 | register_sf3(16) register_sf3(17) register_sf3(18) register_sf3(19) 41823 | register_sf3(20) register_sf3(21) register_sf3(22) register_sf3(23) 41824 | register_sf3(24) register_sf3(25) register_sf3(26) register_sf3(27) 41825 | register_sf3(28) register_sf3(29) register_sf3(30) 41826 | #undef register_sf3 41827 | 41828 | #define register_sf3_extid(Id, Op) \ 41829 | sf3_map[Id] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \ 41830 | 41831 | register_sf3_extid("(t-t)-t",23) // (t-t)-t --> t-(t+t) 41832 | #undef register_sf3_extid 41833 | } 41834 | 41835 | inline void load_sf4_map(sf4_map_t& sf4_map) 41836 | { 41837 | typedef std::pair<quaternary_functor_t,details::operator_type> pair_t; 41838 | 41839 | #define register_sf4(Op) \ 41840 | sf4_map[details::sf##Op##_op<T>::id()] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \ 41841 | 41842 | register_sf4(48) register_sf4(49) register_sf4(50) register_sf4(51) 41843 | register_sf4(52) register_sf4(53) register_sf4(54) register_sf4(55) 41844 | register_sf4(56) register_sf4(57) register_sf4(58) register_sf4(59) 41845 | register_sf4(60) register_sf4(61) register_sf4(62) register_sf4(63) 41846 | register_sf4(64) register_sf4(65) register_sf4(66) register_sf4(67) 41847 | register_sf4(68) register_sf4(69) register_sf4(70) register_sf4(71) 41848 | register_sf4(72) register_sf4(73) register_sf4(74) register_sf4(75) 41849 | register_sf4(76) register_sf4(77) register_sf4(78) register_sf4(79) 41850 | register_sf4(80) register_sf4(81) register_sf4(82) register_sf4(83) 41851 | #undef register_sf4 41852 | 41853 | #define register_sf4ext(Op) \ 41854 | sf4_map[details::sfext##Op##_op<T>::id()] = pair_t(details::sfext##Op##_op<T>::process,details::e_sf4ext##Op); \ 41855 | 41856 | register_sf4ext(00) register_sf4ext(01) register_sf4ext(02) register_sf4ext(03) 41857 | register_sf4ext(04) register_sf4ext(05) register_sf4ext(06) register_sf4ext(07) 41858 | register_sf4ext(08) register_sf4ext(09) register_sf4ext(10) register_sf4ext(11) 41859 | register_sf4ext(12) register_sf4ext(13) register_sf4ext(14) register_sf4ext(15) 41860 | register_sf4ext(16) register_sf4ext(17) register_sf4ext(18) register_sf4ext(19) 41861 | register_sf4ext(20) register_sf4ext(21) register_sf4ext(22) register_sf4ext(23) 41862 | register_sf4ext(24) register_sf4ext(25) register_sf4ext(26) register_sf4ext(27) 41863 | register_sf4ext(28) register_sf4ext(29) register_sf4ext(30) register_sf4ext(31) 41864 | register_sf4ext(32) register_sf4ext(33) register_sf4ext(34) register_sf4ext(35) 41865 | register_sf4ext(36) register_sf4ext(36) register_sf4ext(38) register_sf4ext(39) 41866 | register_sf4ext(40) register_sf4ext(41) register_sf4ext(42) register_sf4ext(43) 41867 | register_sf4ext(44) register_sf4ext(45) register_sf4ext(46) register_sf4ext(47) 41868 | register_sf4ext(48) register_sf4ext(49) register_sf4ext(50) register_sf4ext(51) 41869 | register_sf4ext(52) register_sf4ext(53) register_sf4ext(54) register_sf4ext(55) 41870 | register_sf4ext(56) register_sf4ext(57) register_sf4ext(58) register_sf4ext(59) 41871 | register_sf4ext(60) register_sf4ext(61) 41872 | #undef register_sf4ext 41873 | } 41874 | 41875 | inline results_context_t& results_ctx() 41876 | { 41877 | if (0 == results_context_) 41878 | { 41879 | results_context_ = new results_context_t(); 41880 | } 41881 | 41882 | return (*results_context_); 41883 | } 41884 | 41885 | inline void return_cleanup() 41886 | { 41887 | #ifndef exprtk_disable_return_statement 41888 | if (results_context_) 41889 | { 41890 | delete results_context_; 41891 | results_context_ = 0; 41892 | } 41893 | 41894 | state_.return_stmt_present = false; 41895 | #endif 41896 | } 41897 | 41898 | inline bool valid_settings() 41899 | { 41900 | const std::size_t max_local_vector_size_bytes = sizeof(T) * settings_.max_local_vector_size(); 41901 | 41902 | if (max_local_vector_size_bytes > settings_.max_total_local_symbol_size_bytes()) 41903 | { 41904 | set_error(make_error( 41905 | parser_error::e_parser, 41906 | "ERR281 - Max local vector size of " + details::to_str(max_local_vector_size_bytes) + " bytes " 41907 | "is larger than max total local symbol size of " + details::to_str(settings_.max_total_local_symbol_size_bytes()) + " bytes", 41908 | exprtk_error_location)); 41909 | 41910 | return false; 41911 | } 41912 | 41913 | return true; 41914 | } 41915 | 41916 | private: 41917 | 41918 | parser(const parser<T>&) exprtk_delete; 41919 | parser<T>& operator=(const parser<T>&) exprtk_delete; 41920 | 41921 | settings_store settings_; 41922 | expression_generator<T> expression_generator_; 41923 | details::node_allocator node_allocator_; 41924 | symtab_store symtab_store_; 41925 | dependent_entity_collector dec_; 41926 | std::deque<parser_error::type> error_list_; 41927 | std::deque<bool> brkcnt_list_; 41928 | parser_state state_; 41929 | bool resolve_unknown_symbol_; 41930 | results_context_t* results_context_; 41931 | unknown_symbol_resolver* unknown_symbol_resolver_; 41932 | unknown_symbol_resolver default_usr_; 41933 | base_ops_map_t base_ops_map_; 41934 | unary_op_map_t unary_op_map_; 41935 | binary_op_map_t binary_op_map_; 41936 | inv_binary_op_map_t inv_binary_op_map_; 41937 | sf3_map_t sf3_map_; 41938 | sf4_map_t sf4_map_; 41939 | std::string synthesis_error_; 41940 | scope_element_manager sem_; 41941 | std::vector<state_t> current_state_stack_; 41942 | 41943 | immutable_memory_map_t immutable_memory_map_; 41944 | immutable_symtok_map_t immutable_symtok_map_; 41945 | 41946 | lexer::helper::helper_assembly helper_assembly_; 41947 | 41948 | lexer::helper::commutative_inserter commutative_inserter_; 41949 | lexer::helper::operator_joiner operator_joiner_2_; 41950 | lexer::helper::operator_joiner operator_joiner_3_; 41951 | lexer::helper::symbol_replacer symbol_replacer_; 41952 | lexer::helper::bracket_checker bracket_checker_; 41953 | lexer::helper::numeric_checker<T> numeric_checker_; 41954 | lexer::helper::sequence_validator sequence_validator_; 41955 | lexer::helper::sequence_validator_3tokens sequence_validator_3tkns_; 41956 | 41957 | loop_runtime_check_ptr loop_runtime_check_; 41958 | vector_access_runtime_check_ptr vector_access_runtime_check_; 41959 | compilation_check_ptr compilation_check_ptr_; 41960 | assert_check_ptr assert_check_; 41961 | std::set<std::string> assert_ids_; 41962 | 41963 | template <typename ParserType> 41964 | friend void details::disable_type_checking(ParserType& p); 41965 | }; // class parser 41966 | 41967 | namespace details 41968 | { 41969 | template <typename T> 41970 | struct collector_helper 41971 | { 41972 | typedef exprtk::symbol_table<T> symbol_table_t; 41973 | typedef exprtk::expression<T> expression_t; 41974 | typedef exprtk::parser<T> parser_t; 41975 | typedef typename parser_t::dependent_entity_collector::symbol_t symbol_t; 41976 | typedef typename parser_t::unknown_symbol_resolver usr_t; 41977 | 41978 | struct resolve_as_vector : public usr_t 41979 | { 41980 | typedef exprtk::parser<T> parser_t; 41981 | 41982 | using usr_t::process; 41983 | 41984 | resolve_as_vector() 41985 | : usr_t(usr_t::e_usrmode_extended) 41986 | {} 41987 | 41988 | virtual bool process(const std::string& unknown_symbol, 41989 | symbol_table_t& symbol_table, 41990 | std::string&) exprtk_override 41991 | { 41992 | static T v[1]; 41993 | symbol_table.add_vector(unknown_symbol,v); 41994 | return true; 41995 | } 41996 | }; 41997 | 41998 | static inline bool collection_pass(const std::string& expression_string, 41999 | std::set<std::string>& symbol_set, 42000 | const bool collect_variables, 42001 | const bool collect_functions, 42002 | const bool vector_pass, 42003 | symbol_table_t& ext_symbol_table) 42004 | { 42005 | symbol_table_t symbol_table; 42006 | expression_t expression; 42007 | parser_t parser; 42008 | 42009 | resolve_as_vector vect_resolver; 42010 | 42011 | expression.register_symbol_table(symbol_table ); 42012 | expression.register_symbol_table(ext_symbol_table); 42013 | 42014 | if (vector_pass) 42015 | parser.enable_unknown_symbol_resolver(&vect_resolver); 42016 | else 42017 | parser.enable_unknown_symbol_resolver(); 42018 | 42019 | if (collect_variables) 42020 | parser.dec().collect_variables() = true; 42021 | 42022 | if (collect_functions) 42023 | parser.dec().collect_functions() = true; 42024 | 42025 | bool pass_result = false; 42026 | 42027 | details::disable_type_checking(parser); 42028 | 42029 | if (parser.compile(expression_string, expression)) 42030 | { 42031 | pass_result = true; 42032 | 42033 | std::deque<symbol_t> symb_list; 42034 | parser.dec().symbols(symb_list); 42035 | 42036 | for (std::size_t i = 0; i < symb_list.size(); ++i) 42037 | { 42038 | symbol_set.insert(symb_list[i].first); 42039 | } 42040 | } 42041 | 42042 | return pass_result; 42043 | } 42044 | }; 42045 | } 42046 | 42047 | template <typename Allocator, 42048 | template <typename, typename> class Sequence> 42049 | inline bool collect_variables(const std::string& expression, 42050 | Sequence<std::string, Allocator>& symbol_list) 42051 | { 42052 | typedef double T; 42053 | typedef details::collector_helper<T> collect_t; 42054 | 42055 | collect_t::symbol_table_t null_symbol_table; 42056 | 42057 | std::set<std::string> symbol_set; 42058 | 42059 | const bool variable_pass = collect_t::collection_pass 42060 | (expression, symbol_set, true, false, false, null_symbol_table); 42061 | const bool vector_pass = collect_t::collection_pass 42062 | (expression, symbol_set, true, false, true, null_symbol_table); 42063 | 42064 | if (!variable_pass && !vector_pass) 42065 | return false; 42066 | 42067 | std::set<std::string>::iterator itr = symbol_set.begin(); 42068 | 42069 | while (symbol_set.end() != itr) 42070 | { 42071 | symbol_list.push_back(*itr); 42072 | ++itr; 42073 | } 42074 | 42075 | return true; 42076 | } 42077 | 42078 | template <typename T, 42079 | typename Allocator, 42080 | template <typename, typename> class Sequence> 42081 | inline bool collect_variables(const std::string& expression, 42082 | exprtk::symbol_table<T>& extrnl_symbol_table, 42083 | Sequence<std::string, Allocator>& symbol_list) 42084 | { 42085 | typedef details::collector_helper<T> collect_t; 42086 | 42087 | std::set<std::string> symbol_set; 42088 | 42089 | const bool variable_pass = collect_t::collection_pass 42090 | (expression, symbol_set, true, false, false, extrnl_symbol_table); 42091 | const bool vector_pass = collect_t::collection_pass 42092 | (expression, symbol_set, true, false, true, extrnl_symbol_table); 42093 | 42094 | if (!variable_pass && !vector_pass) 42095 | return false; 42096 | 42097 | std::set<std::string>::iterator itr = symbol_set.begin(); 42098 | 42099 | while (symbol_set.end() != itr) 42100 | { 42101 | symbol_list.push_back(*itr); 42102 | ++itr; 42103 | } 42104 | 42105 | return true; 42106 | } 42107 | 42108 | template <typename Allocator, 42109 | template <typename, typename> class Sequence> 42110 | inline bool collect_functions(const std::string& expression, 42111 | Sequence<std::string, Allocator>& symbol_list) 42112 | { 42113 | typedef double T; 42114 | typedef details::collector_helper<T> collect_t; 42115 | 42116 | collect_t::symbol_table_t null_symbol_table; 42117 | 42118 | std::set<std::string> symbol_set; 42119 | 42120 | const bool variable_pass = collect_t::collection_pass 42121 | (expression, symbol_set, false, true, false, null_symbol_table); 42122 | const bool vector_pass = collect_t::collection_pass 42123 | (expression, symbol_set, false, true, true, null_symbol_table); 42124 | 42125 | if (!variable_pass && !vector_pass) 42126 | return false; 42127 | 42128 | std::set<std::string>::iterator itr = symbol_set.begin(); 42129 | 42130 | while (symbol_set.end() != itr) 42131 | { 42132 | symbol_list.push_back(*itr); 42133 | ++itr; 42134 | } 42135 | 42136 | return true; 42137 | } 42138 | 42139 | template <typename T, 42140 | typename Allocator, 42141 | template <typename, typename> class Sequence> 42142 | inline bool collect_functions(const std::string& expression, 42143 | exprtk::symbol_table<T>& extrnl_symbol_table, 42144 | Sequence<std::string, Allocator>& symbol_list) 42145 | { 42146 | typedef details::collector_helper<T> collect_t; 42147 | 42148 | std::set<std::string> symbol_set; 42149 | 42150 | const bool variable_pass = collect_t::collection_pass 42151 | (expression, symbol_set, false, true, false, extrnl_symbol_table); 42152 | const bool vector_pass = collect_t::collection_pass 42153 | (expression, symbol_set, false, true, true, extrnl_symbol_table); 42154 | 42155 | if (!variable_pass && !vector_pass) 42156 | return false; 42157 | 42158 | std::set<std::string>::iterator itr = symbol_set.begin(); 42159 | 42160 | while (symbol_set.end() != itr) 42161 | { 42162 | symbol_list.push_back(*itr); 42163 | ++itr; 42164 | } 42165 | 42166 | return true; 42167 | } 42168 | 42169 | template <typename T> 42170 | inline T integrate(const expression<T>& e, 42171 | T& x, 42172 | const T& r0, const T& r1, 42173 | const std::size_t number_of_intervals = 1000000) 42174 | { 42175 | if (r0 > r1) 42176 | return T(0); 42177 | 42178 | const T h = (r1 - r0) / (T(2) * number_of_intervals); 42179 | T total_area = T(0); 42180 | 42181 | for (std::size_t i = 0; i < number_of_intervals; ++i) 42182 | { 42183 | x = r0 + T(2) * i * h; 42184 | const T y0 = e.value(); x += h; 42185 | const T y1 = e.value(); x += h; 42186 | const T y2 = e.value(); x += h; 42187 | total_area += h * (y0 + T(4) * y1 + y2) / T(3); 42188 | } 42189 | 42190 | return total_area; 42191 | } 42192 | 42193 | template <typename T> 42194 | inline T integrate(const expression<T>& e, 42195 | const std::string& variable_name, 42196 | const T& r0, const T& r1, 42197 | const std::size_t number_of_intervals = 1000000) 42198 | { 42199 | const symbol_table<T>& sym_table = e.get_symbol_table(); 42200 | 42201 | if (!sym_table.valid()) 42202 | { 42203 | return std::numeric_limits<T>::quiet_NaN(); 42204 | } 42205 | 42206 | details::variable_node<T>* var = sym_table.get_variable(variable_name); 42207 | 42208 | if (var) 42209 | { 42210 | T& x = var->ref(); 42211 | const T x_original = x; 42212 | const T result = integrate(e, x, r0, r1, number_of_intervals); 42213 | x = x_original; 42214 | 42215 | return result; 42216 | } 42217 | 42218 | return std::numeric_limits<T>::quiet_NaN(); 42219 | } 42220 | 42221 | template <typename T> 42222 | inline T derivative(const expression<T>& e, 42223 | T& x, 42224 | const T& h = T(0.00000001)) 42225 | { 42226 | const T x_init = x; 42227 | const T _2h = T(2) * h; 42228 | 42229 | x = x_init + _2h; 42230 | const T y0 = e.value(); 42231 | x = x_init + h; 42232 | const T y1 = e.value(); 42233 | x = x_init - h; 42234 | const T y2 = e.value(); 42235 | x = x_init - _2h; 42236 | const T y3 = e.value(); 42237 | x = x_init; 42238 | 42239 | return (-y0 + T(8) * (y1 - y2) + y3) / (T(12) * h); 42240 | } 42241 | 42242 | template <typename T> 42243 | inline T second_derivative(const expression<T>& e, 42244 | T& x, 42245 | const T& h = T(0.00001)) 42246 | { 42247 | const T x_init = x; 42248 | const T _2h = T(2) * h; 42249 | 42250 | const T y = e.value(); 42251 | x = x_init + _2h; 42252 | const T y0 = e.value(); 42253 | x = x_init + h; 42254 | const T y1 = e.value(); 42255 | x = x_init - h; 42256 | const T y2 = e.value(); 42257 | x = x_init - _2h; 42258 | const T y3 = e.value(); 42259 | x = x_init; 42260 | 42261 | return (-y0 + T(16) * (y1 + y2) - T(30) * y - y3) / (T(12) * h * h); 42262 | } 42263 | 42264 | template <typename T> 42265 | inline T third_derivative(const expression<T>& e, 42266 | T& x, 42267 | const T& h = T(0.0001)) 42268 | { 42269 | const T x_init = x; 42270 | const T _2h = T(2) * h; 42271 | 42272 | x = x_init + _2h; 42273 | const T y0 = e.value(); 42274 | x = x_init + h; 42275 | const T y1 = e.value(); 42276 | x = x_init - h; 42277 | const T y2 = e.value(); 42278 | x = x_init - _2h; 42279 | const T y3 = e.value(); 42280 | x = x_init; 42281 | 42282 | return (y0 + T(2) * (y2 - y1) - y3) / (T(2) * h * h * h); 42283 | } 42284 | 42285 | template <typename T> 42286 | inline T derivative(const expression<T>& e, 42287 | const std::string& variable_name, 42288 | const T& h = T(0.00000001)) 42289 | { 42290 | const symbol_table<T>& sym_table = e.get_symbol_table(); 42291 | 42292 | if (!sym_table.valid()) 42293 | { 42294 | return std::numeric_limits<T>::quiet_NaN(); 42295 | } 42296 | 42297 | details::variable_node<T>* var = sym_table.get_variable(variable_name); 42298 | 42299 | if (var) 42300 | { 42301 | T& x = var->ref(); 42302 | const T x_original = x; 42303 | const T result = derivative(e, x, h); 42304 | x = x_original; 42305 | 42306 | return result; 42307 | } 42308 | 42309 | return std::numeric_limits<T>::quiet_NaN(); 42310 | } 42311 | 42312 | template <typename T> 42313 | inline T second_derivative(const expression<T>& e, 42314 | const std::string& variable_name, 42315 | const T& h = T(0.00001)) 42316 | { 42317 | const symbol_table<T>& sym_table = e.get_symbol_table(); 42318 | 42319 | if (!sym_table.valid()) 42320 | { 42321 | return std::numeric_limits<T>::quiet_NaN(); 42322 | } 42323 | 42324 | details::variable_node<T>* var = sym_table.get_variable(variable_name); 42325 | 42326 | if (var) 42327 | { 42328 | T& x = var->ref(); 42329 | const T x_original = x; 42330 | const T result = second_derivative(e, x, h); 42331 | x = x_original; 42332 | 42333 | return result; 42334 | } 42335 | 42336 | return std::numeric_limits<T>::quiet_NaN(); 42337 | } 42338 | 42339 | template <typename T> 42340 | inline T third_derivative(const expression<T>& e, 42341 | const std::string& variable_name, 42342 | const T& h = T(0.0001)) 42343 | { 42344 | const symbol_table<T>& sym_table = e.get_symbol_table(); 42345 | 42346 | if (!sym_table.valid()) 42347 | { 42348 | return std::numeric_limits<T>::quiet_NaN(); 42349 | } 42350 | 42351 | details::variable_node<T>* var = sym_table.get_variable(variable_name); 42352 | 42353 | if (var) 42354 | { 42355 | T& x = var->ref(); 42356 | const T x_original = x; 42357 | const T result = third_derivative(e, x, h); 42358 | x = x_original; 42359 | 42360 | return result; 42361 | } 42362 | 42363 | return std::numeric_limits<T>::quiet_NaN(); 42364 | } 42365 | 42366 | /* 42367 | Note: The following 'compute' routines are simple helpers, 42368 | for quickly setting up the required pieces of code in order 42369 | to evaluate an expression. By virtue of how they operate 42370 | there will be an overhead with regards to their setup and 42371 | teardown and hence should not be used in time critical 42372 | sections of code. 42373 | Furthermore they only assume a small sub set of variables, 42374 | no string variables or user defined functions. 42375 | */ 42376 | template <typename T> 42377 | inline bool compute(const std::string& expression_string, T& result) 42378 | { 42379 | // No variables 42380 | symbol_table<T> symbol_table; 42381 | symbol_table.add_constants(); 42382 | 42383 | expression<T> expression; 42384 | expression.register_symbol_table(symbol_table); 42385 | 42386 | parser<T> parser; 42387 | 42388 | if (parser.compile(expression_string,expression)) 42389 | { 42390 | result = expression.value(); 42391 | 42392 | return true; 42393 | } 42394 | else 42395 | return false; 42396 | } 42397 | 42398 | template <typename T> 42399 | inline bool compute(const std::string& expression_string, 42400 | const T& x, 42401 | T& result) 42402 | { 42403 | // Only 'x' 42404 | static const std::string x_var("x"); 42405 | 42406 | symbol_table<T> symbol_table; 42407 | symbol_table.add_constants(); 42408 | symbol_table.add_constant(x_var,x); 42409 | 42410 | expression<T> expression; 42411 | expression.register_symbol_table(symbol_table); 42412 | 42413 | parser<T> parser; 42414 | 42415 | if (parser.compile(expression_string,expression)) 42416 | { 42417 | result = expression.value(); 42418 | 42419 | return true; 42420 | } 42421 | else 42422 | return false; 42423 | } 42424 | 42425 | template <typename T> 42426 | inline bool compute(const std::string& expression_string, 42427 | const T&x, const T& y, 42428 | T& result) 42429 | { 42430 | // Only 'x' and 'y' 42431 | static const std::string x_var("x"); 42432 | static const std::string y_var("y"); 42433 | 42434 | symbol_table<T> symbol_table; 42435 | symbol_table.add_constants(); 42436 | symbol_table.add_constant(x_var,x); 42437 | symbol_table.add_constant(y_var,y); 42438 | 42439 | expression<T> expression; 42440 | expression.register_symbol_table(symbol_table); 42441 | 42442 | parser<T> parser; 42443 | 42444 | if (parser.compile(expression_string,expression)) 42445 | { 42446 | result = expression.value(); 42447 | 42448 | return true; 42449 | } 42450 | else 42451 | return false; 42452 | } 42453 | 42454 | template <typename T> 42455 | inline bool compute(const std::string& expression_string, 42456 | const T& x, const T& y, const T& z, 42457 | T& result) 42458 | { 42459 | // Only 'x', 'y' or 'z' 42460 | static const std::string x_var("x"); 42461 | static const std::string y_var("y"); 42462 | static const std::string z_var("z"); 42463 | 42464 | symbol_table<T> symbol_table; 42465 | symbol_table.add_constants(); 42466 | symbol_table.add_constant(x_var,x); 42467 | symbol_table.add_constant(y_var,y); 42468 | symbol_table.add_constant(z_var,z); 42469 | 42470 | expression<T> expression; 42471 | expression.register_symbol_table(symbol_table); 42472 | 42473 | parser<T> parser; 42474 | 42475 | if (parser.compile(expression_string,expression)) 42476 | { 42477 | result = expression.value(); 42478 | 42479 | return true; 42480 | } 42481 | else 42482 | return false; 42483 | } 42484 | 42485 | template <typename T, std::size_t N> 42486 | class polynomial : public ifunction<T> 42487 | { 42488 | private: 42489 | 42490 | template <typename Type, std::size_t NumberOfCoefficients> 42491 | struct poly_impl { }; 42492 | 42493 | template <typename Type> 42494 | struct poly_impl <Type,12> 42495 | { 42496 | static inline T evaluate(const Type x, 42497 | const Type c12, const Type c11, const Type c10, const Type c9, const Type c8, 42498 | const Type c7, const Type c6, const Type c5, const Type c4, const Type c3, 42499 | const Type c2, const Type c1, const Type c0) 42500 | { 42501 | // 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 42502 | 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); 42503 | } 42504 | }; 42505 | 42506 | template <typename Type> 42507 | struct poly_impl <Type,11> 42508 | { 42509 | static inline T evaluate(const Type x, 42510 | const Type c11, const Type c10, const Type c9, const Type c8, const Type c7, 42511 | const Type c6, const Type c5, const Type c4, const Type c3, const Type c2, 42512 | const Type c1, const Type c0) 42513 | { 42514 | // 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 42515 | return (((((((((((c11 * x + c10) * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42516 | } 42517 | }; 42518 | 42519 | template <typename Type> 42520 | struct poly_impl <Type,10> 42521 | { 42522 | static inline T evaluate(const Type x, 42523 | const Type c10, const Type c9, const Type c8, const Type c7, const Type c6, 42524 | const Type c5, const Type c4, const Type c3, const Type c2, const Type c1, 42525 | const Type c0) 42526 | { 42527 | // 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 42528 | return ((((((((((c10 * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42529 | } 42530 | }; 42531 | 42532 | template <typename Type> 42533 | struct poly_impl <Type,9> 42534 | { 42535 | static inline T evaluate(const Type x, 42536 | const Type c9, const Type c8, const Type c7, const Type c6, const Type c5, 42537 | const Type c4, const Type c3, const Type c2, const Type c1, const Type c0) 42538 | { 42539 | // 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 42540 | return (((((((((c9 * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42541 | } 42542 | }; 42543 | 42544 | template <typename Type> 42545 | struct poly_impl <Type,8> 42546 | { 42547 | static inline T evaluate(const Type x, 42548 | const Type c8, const Type c7, const Type c6, const Type c5, const Type c4, 42549 | const Type c3, const Type c2, const Type c1, const Type c0) 42550 | { 42551 | // 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 42552 | return ((((((((c8 * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42553 | } 42554 | }; 42555 | 42556 | template <typename Type> 42557 | struct poly_impl <Type,7> 42558 | { 42559 | static inline T evaluate(const Type x, 42560 | const Type c7, const Type c6, const Type c5, const Type c4, const Type c3, 42561 | const Type c2, const Type c1, const Type c0) 42562 | { 42563 | // 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 42564 | return (((((((c7 * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42565 | } 42566 | }; 42567 | 42568 | template <typename Type> 42569 | struct poly_impl <Type,6> 42570 | { 42571 | static inline T evaluate(const Type x, 42572 | const Type c6, const Type c5, const Type c4, const Type c3, const Type c2, 42573 | const Type c1, const Type c0) 42574 | { 42575 | // p(x) = c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 42576 | return ((((((c6 * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42577 | } 42578 | }; 42579 | 42580 | template <typename Type> 42581 | struct poly_impl <Type,5> 42582 | { 42583 | static inline T evaluate(const Type x, 42584 | const Type c5, const Type c4, const Type c3, const Type c2, 42585 | const Type c1, const Type c0) 42586 | { 42587 | // p(x) = c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 42588 | return (((((c5 * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); 42589 | } 42590 | }; 42591 | 42592 | template <typename Type> 42593 | struct poly_impl <Type,4> 42594 | { 42595 | static inline T evaluate(const Type x, const Type c4, const Type c3, const Type c2, const Type c1, const Type c0) 42596 | { 42597 | // p(x) = c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 42598 | return ((((c4 * x + c3) * x + c2) * x + c1) * x + c0); 42599 | } 42600 | }; 42601 | 42602 | template <typename Type> 42603 | struct poly_impl <Type,3> 42604 | { 42605 | static inline T evaluate(const Type x, const Type c3, const Type c2, const Type c1, const Type c0) 42606 | { 42607 | // p(x) = c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 42608 | return (((c3 * x + c2) * x + c1) * x + c0); 42609 | } 42610 | }; 42611 | 42612 | template <typename Type> 42613 | struct poly_impl <Type,2> 42614 | { 42615 | static inline T evaluate(const Type x, const Type c2, const Type c1, const Type c0) 42616 | { 42617 | // p(x) = c_2x^2 + c_1x^1 + c_0x^0 42618 | return ((c2 * x + c1) * x + c0); 42619 | } 42620 | }; 42621 | 42622 | template <typename Type> 42623 | struct poly_impl <Type,1> 42624 | { 42625 | static inline T evaluate(const Type x, const Type c1, const Type c0) 42626 | { 42627 | // p(x) = c_1x^1 + c_0x^0 42628 | return (c1 * x + c0); 42629 | } 42630 | }; 42631 | 42632 | public: 42633 | 42634 | using ifunction<T>::operator(); 42635 | 42636 | polynomial() 42637 | : ifunction<T>((N+2 <= 20) ? (N + 2) : std::numeric_limits<std::size_t>::max()) 42638 | { 42639 | disable_has_side_effects(*this); 42640 | } 42641 | 42642 | virtual ~polynomial() exprtk_override 42643 | {} 42644 | 42645 | #define poly_rtrn(NN) \ 42646 | return (NN != N) ? std::numeric_limits<T>::quiet_NaN() : 42647 | 42648 | inline virtual T operator() (const T& x, const T& c1, const T& c0) exprtk_override 42649 | { 42650 | poly_rtrn(1) (poly_impl<T,1>::evaluate(x, c1, c0)); 42651 | } 42652 | 42653 | inline virtual T operator() (const T& x, const T& c2, const T& c1, const T& c0) exprtk_override 42654 | { 42655 | poly_rtrn(2) (poly_impl<T,2>::evaluate(x, c2, c1, c0)); 42656 | } 42657 | 42658 | inline virtual T operator() (const T& x, const T& c3, const T& c2, const T& c1, const T& c0) exprtk_override 42659 | { 42660 | poly_rtrn(3) (poly_impl<T,3>::evaluate(x, c3, c2, c1, c0)); 42661 | } 42662 | 42663 | inline virtual T operator() (const T& x, const T& c4, const T& c3, const T& c2, const T& c1, 42664 | const T& c0) exprtk_override 42665 | { 42666 | poly_rtrn(4) (poly_impl<T,4>::evaluate(x, c4, c3, c2, c1, c0)); 42667 | } 42668 | 42669 | inline virtual T operator() (const T& x, const T& c5, const T& c4, const T& c3, const T& c2, 42670 | const T& c1, const T& c0) exprtk_override 42671 | { 42672 | poly_rtrn(5) (poly_impl<T,5>::evaluate(x, c5, c4, c3, c2, c1, c0)); 42673 | } 42674 | 42675 | inline virtual T operator() (const T& x, const T& c6, const T& c5, const T& c4, const T& c3, 42676 | const T& c2, const T& c1, const T& c0) exprtk_override 42677 | { 42678 | poly_rtrn(6) (poly_impl<T,6>::evaluate(x, c6, c5, c4, c3, c2, c1, c0)); 42679 | } 42680 | 42681 | inline virtual T operator() (const T& x, const T& c7, const T& c6, const T& c5, const T& c4, 42682 | const T& c3, const T& c2, const T& c1, const T& c0) exprtk_override 42683 | { 42684 | poly_rtrn(7) (poly_impl<T,7>::evaluate(x, c7, c6, c5, c4, c3, c2, c1, c0)); 42685 | } 42686 | 42687 | inline virtual T operator() (const T& x, const T& c8, const T& c7, const T& c6, const T& c5, 42688 | const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) exprtk_override 42689 | { 42690 | poly_rtrn(8) (poly_impl<T,8>::evaluate(x, c8, c7, c6, c5, c4, c3, c2, c1, c0)); 42691 | } 42692 | 42693 | inline virtual T operator() (const T& x, const T& c9, const T& c8, const T& c7, const T& c6, 42694 | const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, 42695 | const T& c0) exprtk_override 42696 | { 42697 | poly_rtrn(9) (poly_impl<T,9>::evaluate(x, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0)); 42698 | } 42699 | 42700 | inline virtual T operator() (const T& x, const T& c10, const T& c9, const T& c8, const T& c7, 42701 | const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, 42702 | const T& c1, const T& c0) exprtk_override 42703 | { 42704 | poly_rtrn(10) (poly_impl<T,10>::evaluate(x, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0)); 42705 | } 42706 | 42707 | inline virtual T operator() (const T& x, const T& c11, const T& c10, const T& c9, const T& c8, 42708 | const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, 42709 | const T& c2, const T& c1, const T& c0) exprtk_override 42710 | { 42711 | poly_rtrn(11) (poly_impl<T,11>::evaluate(x, c11, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0)); 42712 | } 42713 | 42714 | inline virtual T operator() (const T& x, const T& c12, const T& c11, const T& c10, const T& c9, 42715 | const T& c8, 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(12) (poly_impl<T,12>::evaluate(x, c12, c11, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0)); 42719 | } 42720 | 42721 | #undef poly_rtrn 42722 | 42723 | inline virtual T operator() () exprtk_override 42724 | { 42725 | return std::numeric_limits<T>::quiet_NaN(); 42726 | } 42727 | 42728 | inline virtual T operator() (const T&) exprtk_override 42729 | { 42730 | return std::numeric_limits<T>::quiet_NaN(); 42731 | } 42732 | 42733 | inline virtual T operator() (const T&, const T&) exprtk_override 42734 | { 42735 | return std::numeric_limits<T>::quiet_NaN(); 42736 | } 42737 | }; 42738 | 42739 | template <typename T> 42740 | class function_compositor 42741 | { 42742 | public: 42743 | 42744 | typedef exprtk::expression<T> expression_t; 42745 | typedef exprtk::symbol_table<T> symbol_table_t; 42746 | typedef exprtk::parser<T> parser_t; 42747 | typedef typename parser_t::settings_store settings_t; 42748 | 42749 | struct function 42750 | { 42751 | function() 42752 | {} 42753 | 42754 | explicit function(const std::string& n) 42755 | : name_(n) 42756 | {} 42757 | 42758 | function(const std::string& name, 42759 | const std::string& expression) 42760 | : name_(name) 42761 | , expression_(expression) 42762 | {} 42763 | 42764 | function(const std::string& name, 42765 | const std::string& expression, 42766 | const std::string& v0) 42767 | : name_(name) 42768 | , expression_(expression) 42769 | { 42770 | v_.push_back(v0); 42771 | } 42772 | 42773 | function(const std::string& name, 42774 | const std::string& expression, 42775 | const std::string& v0, const std::string& v1) 42776 | : name_(name) 42777 | , expression_(expression) 42778 | { 42779 | v_.push_back(v0); v_.push_back(v1); 42780 | } 42781 | 42782 | function(const std::string& name, 42783 | const std::string& expression, 42784 | const std::string& v0, const std::string& v1, 42785 | const std::string& v2) 42786 | : name_(name) 42787 | , expression_(expression) 42788 | { 42789 | v_.push_back(v0); v_.push_back(v1); 42790 | v_.push_back(v2); 42791 | } 42792 | 42793 | function(const std::string& name, 42794 | const std::string& expression, 42795 | const std::string& v0, const std::string& v1, 42796 | const std::string& v2, const std::string& v3) 42797 | : name_(name) 42798 | , expression_(expression) 42799 | { 42800 | v_.push_back(v0); v_.push_back(v1); 42801 | v_.push_back(v2); v_.push_back(v3); 42802 | } 42803 | 42804 | function(const std::string& name, 42805 | const std::string& expression, 42806 | const std::string& v0, const std::string& v1, 42807 | const std::string& v2, const std::string& v3, 42808 | const std::string& v4) 42809 | : name_(name) 42810 | , expression_(expression) 42811 | { 42812 | v_.push_back(v0); v_.push_back(v1); 42813 | v_.push_back(v2); v_.push_back(v3); 42814 | v_.push_back(v4); 42815 | } 42816 | 42817 | inline function& name(const std::string& n) 42818 | { 42819 | name_ = n; 42820 | return (*this); 42821 | } 42822 | 42823 | inline function& expression(const std::string& e) 42824 | { 42825 | expression_ = e; 42826 | return (*this); 42827 | } 42828 | 42829 | inline function& var(const std::string& v) 42830 | { 42831 | v_.push_back(v); 42832 | return (*this); 42833 | } 42834 | 42835 | inline function& vars(const std::string& v0, 42836 | const std::string& v1) 42837 | { 42838 | v_.push_back(v0); 42839 | v_.push_back(v1); 42840 | return (*this); 42841 | } 42842 | 42843 | inline function& vars(const std::string& v0, 42844 | const std::string& v1, 42845 | const std::string& v2) 42846 | { 42847 | v_.push_back(v0); 42848 | v_.push_back(v1); 42849 | v_.push_back(v2); 42850 | return (*this); 42851 | } 42852 | 42853 | inline function& vars(const std::string& v0, 42854 | const std::string& v1, 42855 | const std::string& v2, 42856 | const std::string& v3) 42857 | { 42858 | v_.push_back(v0); 42859 | v_.push_back(v1); 42860 | v_.push_back(v2); 42861 | v_.push_back(v3); 42862 | return (*this); 42863 | } 42864 | 42865 | inline function& vars(const std::string& v0, 42866 | const std::string& v1, 42867 | const std::string& v2, 42868 | const std::string& v3, 42869 | const std::string& v4) 42870 | { 42871 | v_.push_back(v0); 42872 | v_.push_back(v1); 42873 | v_.push_back(v2); 42874 | v_.push_back(v3); 42875 | v_.push_back(v4); 42876 | return (*this); 42877 | } 42878 | 42879 | std::string name_; 42880 | std::string expression_; 42881 | std::deque<std::string> v_; 42882 | }; 42883 | 42884 | private: 42885 | 42886 | struct base_func : public exprtk::ifunction<T> 42887 | { 42888 | typedef const T& type; 42889 | typedef exprtk::ifunction<T> function_t; 42890 | typedef std::vector<T*> varref_t; 42891 | typedef std::vector<T> var_t; 42892 | typedef std::vector<std::string> str_t; 42893 | typedef std::pair<T*,std::size_t> lvarref_t; 42894 | typedef std::vector<lvarref_t> lvr_vec_t; 42895 | typedef std::vector<std::string*> lstr_vec_t; 42896 | 42897 | using exprtk::ifunction<T>::operator(); 42898 | 42899 | explicit base_func(const std::size_t& pc = 0) 42900 | : exprtk::ifunction<T>(pc) 42901 | , local_var_stack_size(0) 42902 | , stack_depth(0) 42903 | { 42904 | v.resize(pc); 42905 | } 42906 | 42907 | virtual ~base_func() 42908 | {} 42909 | 42910 | #define exprtk_assign(Index) \ 42911 | (*v[Index]) = v##Index; \ 42912 | 42913 | inline void update(const T& v0) 42914 | { 42915 | exprtk_assign(0) 42916 | } 42917 | 42918 | inline void update(const T& v0, const T& v1) 42919 | { 42920 | exprtk_assign(0) exprtk_assign(1) 42921 | } 42922 | 42923 | inline void update(const T& v0, const T& v1, const T& v2) 42924 | { 42925 | exprtk_assign(0) exprtk_assign(1) 42926 | exprtk_assign(2) 42927 | } 42928 | 42929 | inline void update(const T& v0, const T& v1, const T& v2, const T& v3) 42930 | { 42931 | exprtk_assign(0) exprtk_assign(1) 42932 | exprtk_assign(2) exprtk_assign(3) 42933 | } 42934 | 42935 | inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4) 42936 | { 42937 | exprtk_assign(0) exprtk_assign(1) 42938 | exprtk_assign(2) exprtk_assign(3) 42939 | exprtk_assign(4) 42940 | } 42941 | 42942 | inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5) 42943 | { 42944 | exprtk_assign(0) exprtk_assign(1) 42945 | exprtk_assign(2) exprtk_assign(3) 42946 | exprtk_assign(4) exprtk_assign(5) 42947 | } 42948 | 42949 | #ifdef exprtk_assign 42950 | #undef exprtk_assign 42951 | #endif 42952 | 42953 | inline function_t& setup(expression_t& expr) 42954 | { 42955 | expression = expr; 42956 | 42957 | typedef typename expression_t::control_block ctrlblk_t; 42958 | typedef typename ctrlblk_t::local_data_list_t ldl_t; 42959 | typedef typename ctrlblk_t::data_type data_t; 42960 | typedef typename ldl_t::value_type ldl_value_type; 42961 | 42962 | const ldl_t ldl = expr.local_data_list(); 42963 | 42964 | std::vector<std::pair<std::size_t,data_t> > index_list; 42965 | 42966 | for (std::size_t i = 0; i < ldl.size(); ++i) 42967 | { 42968 | exprtk_debug(("base_func::setup() - element[%02d] type: %s size: %d\n", 42969 | static_cast<int>(i), 42970 | expression_t::control_block::to_str(ldl[i].type).c_str(), 42971 | static_cast<int>(ldl[i].size))); 42972 | 42973 | switch (ldl[i].type) 42974 | { 42975 | case ctrlblk_t::e_unknown : continue; 42976 | case ctrlblk_t::e_expr : continue; 42977 | case ctrlblk_t::e_vecholder : continue; 42978 | default : break; 42979 | } 42980 | 42981 | if (ldl[i].size) 42982 | { 42983 | index_list.push_back(std::make_pair(i,ldl[i].type)); 42984 | } 42985 | } 42986 | 42987 | std::size_t input_param_count = 0; 42988 | 42989 | for (std::size_t i = 0; i < index_list.size(); ++i) 42990 | { 42991 | const std::size_t index = index_list[i].first; 42992 | const ldl_value_type& local_var = ldl[index]; 42993 | 42994 | assert(local_var.pointer); 42995 | 42996 | if (i < (index_list.size() - v.size())) 42997 | { 42998 | if (local_var.type == ctrlblk_t::e_string) 42999 | { 43000 | local_str_vars.push_back( 43001 | reinterpret_cast<std::string*>(local_var.pointer)); 43002 | } 43003 | else if ( 43004 | (local_var.type == ctrlblk_t::e_data ) || 43005 | (local_var.type == ctrlblk_t::e_vecdata) 43006 | ) 43007 | { 43008 | local_vars.push_back(std::make_pair( 43009 | reinterpret_cast<T*>(local_var.pointer), 43010 | local_var.size)); 43011 | 43012 | local_var_stack_size += local_var.size; 43013 | } 43014 | } 43015 | else 43016 | { 43017 | v[input_param_count++] = reinterpret_cast<T*>(local_var.pointer); 43018 | } 43019 | } 43020 | 43021 | clear_stack(); 43022 | 43023 | return (*this); 43024 | } 43025 | 43026 | inline void pre() 43027 | { 43028 | if (stack_depth++) 43029 | { 43030 | if (!v.empty()) 43031 | { 43032 | var_t var_stack(v.size(),T(0)); 43033 | copy(v,var_stack); 43034 | input_params_stack.push_back(var_stack); 43035 | } 43036 | 43037 | if (!local_vars.empty()) 43038 | { 43039 | var_t local_vec_frame(local_var_stack_size,T(0)); 43040 | copy(local_vars,local_vec_frame); 43041 | local_var_stack.push_back(local_vec_frame); 43042 | } 43043 | 43044 | if (!local_str_vars.empty()) 43045 | { 43046 | str_t local_str_frame(local_str_vars.size()); 43047 | copy(local_str_vars,local_str_frame); 43048 | local_str_stack.push_back(local_str_frame); 43049 | } 43050 | } 43051 | } 43052 | 43053 | inline void post() 43054 | { 43055 | if (--stack_depth) 43056 | { 43057 | if (!v.empty()) 43058 | { 43059 | copy(input_params_stack.back(), v); 43060 | input_params_stack.pop_back(); 43061 | } 43062 | 43063 | if (!local_vars.empty()) 43064 | { 43065 | copy(local_var_stack.back(), local_vars); 43066 | local_var_stack.pop_back(); 43067 | } 43068 | 43069 | if (!local_str_vars.empty()) 43070 | { 43071 | copy(local_str_stack.back(), local_str_vars); 43072 | local_str_stack.pop_back(); 43073 | } 43074 | } 43075 | } 43076 | 43077 | void copy(const varref_t& src_v, var_t& dest_v) 43078 | { 43079 | for (std::size_t i = 0; i < src_v.size(); ++i) 43080 | { 43081 | dest_v[i] = (*src_v[i]); 43082 | } 43083 | } 43084 | 43085 | void copy(const lstr_vec_t& src_v, str_t& dest_v) 43086 | { 43087 | for (std::size_t i = 0; i < src_v.size(); ++i) 43088 | { 43089 | dest_v[i] = (*src_v[i]); 43090 | } 43091 | } 43092 | 43093 | void copy(const var_t& src_v, varref_t& dest_v) 43094 | { 43095 | for (std::size_t i = 0; i < src_v.size(); ++i) 43096 | { 43097 | (*dest_v[i]) = src_v[i]; 43098 | } 43099 | } 43100 | 43101 | void copy(const lvr_vec_t& src_v, var_t& dest_v) 43102 | { 43103 | typename var_t::iterator itr = dest_v.begin(); 43104 | typedef typename std::iterator_traits<typename var_t::iterator>::difference_type diff_t; 43105 | 43106 | for (std::size_t i = 0; i < src_v.size(); ++i) 43107 | { 43108 | lvarref_t vr = src_v[i]; 43109 | 43110 | if (1 == vr.second) 43111 | *itr++ = (*vr.first); 43112 | else 43113 | { 43114 | std::copy(vr.first, vr.first + vr.second, itr); 43115 | itr += static_cast<diff_t>(vr.second); 43116 | } 43117 | } 43118 | } 43119 | 43120 | void copy(const var_t& src_v, lvr_vec_t& dest_v) 43121 | { 43122 | typename var_t::const_iterator itr = src_v.begin(); 43123 | typedef typename std::iterator_traits<typename var_t::iterator>::difference_type diff_t; 43124 | 43125 | for (std::size_t i = 0; i < dest_v.size(); ++i) 43126 | { 43127 | lvarref_t& vr = dest_v[i]; 43128 | 43129 | assert(vr.first != 0); 43130 | assert(vr.second > 0); 43131 | 43132 | if (1 == vr.second) 43133 | (*vr.first) = *itr++; 43134 | else 43135 | { 43136 | std::copy(itr, itr + static_cast<diff_t>(vr.second), vr.first); 43137 | itr += static_cast<diff_t>(vr.second); 43138 | } 43139 | } 43140 | } 43141 | 43142 | void copy(const str_t& src_str, lstr_vec_t& dest_str) 43143 | { 43144 | assert(src_str.size() == dest_str.size()); 43145 | 43146 | for (std::size_t i = 0; i < dest_str.size(); ++i) 43147 | { 43148 | *dest_str[i] = src_str[i]; 43149 | } 43150 | } 43151 | 43152 | inline void clear_stack() 43153 | { 43154 | for (std::size_t i = 0; i < v.size(); ++i) 43155 | { 43156 | (*v[i]) = 0; 43157 | } 43158 | } 43159 | 43160 | inline virtual T value(expression_t& e) 43161 | { 43162 | return e.value(); 43163 | } 43164 | 43165 | expression_t expression; 43166 | varref_t v; 43167 | lvr_vec_t local_vars; 43168 | lstr_vec_t local_str_vars; 43169 | std::size_t local_var_stack_size; 43170 | std::size_t stack_depth; 43171 | std::deque<var_t> input_params_stack; 43172 | std::deque<var_t> local_var_stack; 43173 | std::deque<str_t> local_str_stack; 43174 | }; 43175 | 43176 | typedef std::map<std::string,base_func*> funcparam_t; 43177 | 43178 | typedef const T& type; 43179 | 43180 | template <typename BaseFuncType> 43181 | struct scoped_bft 43182 | { 43183 | explicit scoped_bft(BaseFuncType& bft) 43184 | : bft_(bft) 43185 | { 43186 | bft_.pre (); 43187 | } 43188 | 43189 | ~scoped_bft() 43190 | { 43191 | bft_.post(); 43192 | } 43193 | 43194 | BaseFuncType& bft_; 43195 | 43196 | private: 43197 | 43198 | scoped_bft(const scoped_bft&) exprtk_delete; 43199 | scoped_bft& operator=(const scoped_bft&) exprtk_delete; 43200 | }; 43201 | 43202 | struct func_0param : public base_func 43203 | { 43204 | using exprtk::ifunction<T>::operator(); 43205 | 43206 | func_0param() : base_func(0) {} 43207 | 43208 | inline T operator() () exprtk_override 43209 | { 43210 | scoped_bft<func_0param> sb(*this); 43211 | return this->value(base_func::expression); 43212 | } 43213 | }; 43214 | 43215 | struct func_1param : public base_func 43216 | { 43217 | using exprtk::ifunction<T>::operator(); 43218 | 43219 | func_1param() : base_func(1) {} 43220 | 43221 | inline T operator() (type v0) exprtk_override 43222 | { 43223 | scoped_bft<func_1param> sb(*this); 43224 | base_func::update(v0); 43225 | return this->value(base_func::expression); 43226 | } 43227 | }; 43228 | 43229 | struct func_2param : public base_func 43230 | { 43231 | using exprtk::ifunction<T>::operator(); 43232 | 43233 | func_2param() : base_func(2) {} 43234 | 43235 | inline T operator() (type v0, type v1) exprtk_override 43236 | { 43237 | scoped_bft<func_2param> sb(*this); 43238 | base_func::update(v0, v1); 43239 | return this->value(base_func::expression); 43240 | } 43241 | }; 43242 | 43243 | struct func_3param : public base_func 43244 | { 43245 | using exprtk::ifunction<T>::operator(); 43246 | 43247 | func_3param() : base_func(3) {} 43248 | 43249 | inline T operator() (type v0, type v1, type v2) exprtk_override 43250 | { 43251 | scoped_bft<func_3param> sb(*this); 43252 | base_func::update(v0, v1, v2); 43253 | return this->value(base_func::expression); 43254 | } 43255 | }; 43256 | 43257 | struct func_4param : public base_func 43258 | { 43259 | using exprtk::ifunction<T>::operator(); 43260 | 43261 | func_4param() : base_func(4) {} 43262 | 43263 | inline T operator() (type v0, type v1, type v2, type v3) exprtk_override 43264 | { 43265 | scoped_bft<func_4param> sb(*this); 43266 | base_func::update(v0, v1, v2, v3); 43267 | return this->value(base_func::expression); 43268 | } 43269 | }; 43270 | 43271 | struct func_5param : public base_func 43272 | { 43273 | using exprtk::ifunction<T>::operator(); 43274 | 43275 | func_5param() : base_func(5) {} 43276 | 43277 | inline T operator() (type v0, type v1, type v2, type v3, type v4) exprtk_override 43278 | { 43279 | scoped_bft<func_5param> sb(*this); 43280 | base_func::update(v0, v1, v2, v3, v4); 43281 | return this->value(base_func::expression); 43282 | } 43283 | }; 43284 | 43285 | struct func_6param : public base_func 43286 | { 43287 | using exprtk::ifunction<T>::operator(); 43288 | 43289 | func_6param() : base_func(6) {} 43290 | 43291 | inline T operator() (type v0, type v1, type v2, type v3, type v4, type v5) exprtk_override 43292 | { 43293 | scoped_bft<func_6param> sb(*this); 43294 | base_func::update(v0, v1, v2, v3, v4, v5); 43295 | return this->value(base_func::expression); 43296 | } 43297 | }; 43298 | 43299 | static T return_value(expression_t& e) 43300 | { 43301 | typedef exprtk::results_context<T> results_context_t; 43302 | typedef typename results_context_t::type_store_t type_t; 43303 | typedef typename type_t::scalar_view scalar_t; 43304 | 43305 | const T result = e.value(); 43306 | 43307 | if (e.return_invoked()) 43308 | { 43309 | // Due to the post compilation checks, it can be safely 43310 | // assumed that there will be at least one parameter 43311 | // and that the first parameter will always be scalar. 43312 | return scalar_t(e.results()[0])(); 43313 | } 43314 | 43315 | return result; 43316 | } 43317 | 43318 | #define def_fp_retval(N) \ 43319 | struct func_##N##param_retval exprtk_final : public func_##N##param \ 43320 | { \ 43321 | inline T value(expression_t& e) exprtk_override \ 43322 | { \ 43323 | return return_value(e); \ 43324 | } \ 43325 | }; \ 43326 | 43327 | def_fp_retval(0) 43328 | def_fp_retval(1) 43329 | def_fp_retval(2) 43330 | def_fp_retval(3) 43331 | def_fp_retval(4) 43332 | def_fp_retval(5) 43333 | def_fp_retval(6) 43334 | 43335 | #undef def_fp_retval 43336 | 43337 | template <typename Allocator, 43338 | template <typename, typename> class Sequence> 43339 | inline bool add(const std::string& name, 43340 | const std::string& expression, 43341 | const Sequence<std::string,Allocator>& var_list, 43342 | const bool override = false) 43343 | { 43344 | const typename std::map<std::string,expression_t>::iterator itr = expr_map_.find(name); 43345 | 43346 | if (expr_map_.end() != itr) 43347 | { 43348 | if (!override) 43349 | { 43350 | exprtk_debug(("Compositor error(add): function '%s' already defined\n", 43351 | name.c_str())); 43352 | 43353 | return false; 43354 | } 43355 | 43356 | remove(name, var_list.size()); 43357 | } 43358 | 43359 | if (compile_expression(name, expression, var_list)) 43360 | { 43361 | const std::size_t n = var_list.size(); 43362 | 43363 | fp_map_[n][name]->setup(expr_map_[name]); 43364 | 43365 | return true; 43366 | } 43367 | else 43368 | { 43369 | exprtk_debug(("Compositor error(add): Failed to compile function '%s'\n", 43370 | name.c_str())); 43371 | 43372 | return false; 43373 | } 43374 | } 43375 | 43376 | public: 43377 | 43378 | function_compositor() 43379 | : parser_(settings_t::default_compile_all_opts + 43380 | settings_t::e_disable_zero_return) 43381 | , fp_map_(7) 43382 | , load_variables_(false) 43383 | , load_vectors_(false) 43384 | {} 43385 | 43386 | explicit function_compositor(const symbol_table_t& st) 43387 | : symbol_table_(st) 43388 | , parser_(settings_t::default_compile_all_opts + 43389 | settings_t::e_disable_zero_return) 43390 | , fp_map_(7) 43391 | , load_variables_(false) 43392 | , load_vectors_(false) 43393 | {} 43394 | 43395 | ~function_compositor() 43396 | { 43397 | clear(); 43398 | } 43399 | 43400 | inline symbol_table_t& symbol_table() 43401 | { 43402 | return symbol_table_; 43403 | } 43404 | 43405 | inline const symbol_table_t& symbol_table() const 43406 | { 43407 | return symbol_table_; 43408 | } 43409 | 43410 | inline void add_auxiliary_symtab(symbol_table_t& symtab) 43411 | { 43412 | auxiliary_symtab_list_.push_back(&symtab); 43413 | } 43414 | 43415 | void load_variables(const bool load = true) 43416 | { 43417 | load_variables_ = load; 43418 | } 43419 | 43420 | void load_vectors(const bool load = true) 43421 | { 43422 | load_vectors_ = load; 43423 | } 43424 | 43425 | inline void register_loop_runtime_check(loop_runtime_check& lrtchk) 43426 | { 43427 | parser_.register_loop_runtime_check(lrtchk); 43428 | } 43429 | 43430 | inline void register_vector_access_runtime_check(vector_access_runtime_check& vartchk) 43431 | { 43432 | parser_.register_vector_access_runtime_check(vartchk); 43433 | } 43434 | 43435 | inline void register_compilation_timeout_check(compilation_check& compchk) 43436 | { 43437 | parser_.register_compilation_timeout_check(compchk); 43438 | } 43439 | 43440 | inline void clear_loop_runtime_check() 43441 | { 43442 | parser_.clear_loop_runtime_check(); 43443 | } 43444 | 43445 | inline void clear_vector_access_runtime_check() 43446 | { 43447 | parser_.clear_vector_access_runtime_check(); 43448 | } 43449 | 43450 | inline void clear_compilation_timeout_check() 43451 | { 43452 | parser_.clear_compilation_timeout_check(); 43453 | } 43454 | 43455 | void clear() 43456 | { 43457 | symbol_table_.clear(); 43458 | expr_map_ .clear(); 43459 | 43460 | for (std::size_t i = 0; i < fp_map_.size(); ++i) 43461 | { 43462 | typename funcparam_t::iterator itr = fp_map_[i].begin(); 43463 | typename funcparam_t::iterator end = fp_map_[i].end (); 43464 | 43465 | while (itr != end) 43466 | { 43467 | delete itr->second; 43468 | ++itr; 43469 | } 43470 | 43471 | fp_map_[i].clear(); 43472 | } 43473 | 43474 | clear_loop_runtime_check (); 43475 | clear_vector_access_runtime_check(); 43476 | clear_compilation_timeout_check (); 43477 | } 43478 | 43479 | inline bool add(const function& f, const bool override = false) 43480 | { 43481 | return add(f.name_, f.expression_, f.v_,override); 43482 | } 43483 | 43484 | inline std::string error() const 43485 | { 43486 | if (!error_list_.empty()) 43487 | { 43488 | return error_list_[0].diagnostic; 43489 | } 43490 | else 43491 | return std::string("No Error"); 43492 | } 43493 | 43494 | inline std::size_t error_count() const 43495 | { 43496 | return error_list_.size(); 43497 | } 43498 | 43499 | inline parser_error::type get_error(const std::size_t& index) const 43500 | { 43501 | if (index < error_list_.size()) 43502 | { 43503 | return error_list_[index]; 43504 | } 43505 | 43506 | throw std::invalid_argument("compositor::get_error() - Invalid error index specified"); 43507 | } 43508 | 43509 | private: 43510 | 43511 | template <typename Allocator, 43512 | template <typename, typename> class Sequence> 43513 | bool compile_expression(const std::string& name, 43514 | const std::string& expression, 43515 | const Sequence<std::string,Allocator>& input_var_list, 43516 | bool return_present = false) 43517 | { 43518 | expression_t compiled_expression; 43519 | symbol_table_t local_symbol_table; 43520 | 43521 | local_symbol_table.load_from(symbol_table_); 43522 | local_symbol_table.add_constants(); 43523 | 43524 | if (load_variables_) 43525 | { 43526 | local_symbol_table.load_variables_from(symbol_table_); 43527 | } 43528 | 43529 | if (load_vectors_) 43530 | { 43531 | local_symbol_table.load_vectors_from(symbol_table_); 43532 | } 43533 | 43534 | error_list_.clear(); 43535 | 43536 | if (!valid(name,input_var_list.size())) 43537 | { 43538 | parser_error::type error = 43539 | parser_error::make_error( 43540 | parser_error::e_parser, 43541 | lexer::token(), 43542 | "ERR282 - Function '" + name + "' is an invalid overload", 43543 | exprtk_error_location); 43544 | 43545 | error_list_.push_back(error); 43546 | return false; 43547 | } 43548 | 43549 | if (!forward(name, 43550 | input_var_list.size(), 43551 | local_symbol_table, 43552 | return_present)) 43553 | return false; 43554 | 43555 | compiled_expression.register_symbol_table(local_symbol_table); 43556 | 43557 | for (std::size_t i = 0; i < auxiliary_symtab_list_.size(); ++i) 43558 | { 43559 | compiled_expression.register_symbol_table((*auxiliary_symtab_list_[i])); 43560 | } 43561 | 43562 | std::string mod_expression; 43563 | 43564 | for (std::size_t i = 0; i < input_var_list.size(); ++i) 43565 | { 43566 | mod_expression += " var " + input_var_list[i] + "{};\n" 43567 | } 43568 | 43569 | if ( 43570 | ('{' == details::front(expression)) && 43571 | ('}' == details::back (expression)) 43572 | ) 43573 | mod_expression += "~" + expression + "" 43574 | else 43575 | mod_expression += "~{" + expression + "};" 43576 | 43577 | if (!parser_.compile(mod_expression,compiled_expression)) 43578 | { 43579 | exprtk_debug(("Compositor Error: %s\n", parser_.error().c_str())); 43580 | exprtk_debug(("Compositor modified expression: \n%s\n", mod_expression.c_str())); 43581 | 43582 | remove(name,input_var_list.size()); 43583 | 43584 | for (std::size_t err_index = 0; err_index < parser_.error_count(); ++err_index) 43585 | { 43586 | error_list_.push_back(parser_.get_error(err_index)); 43587 | } 43588 | 43589 | return false; 43590 | } 43591 | 43592 | if (!return_present && parser_.dec().return_present()) 43593 | { 43594 | remove(name,input_var_list.size()); 43595 | return compile_expression(name, expression, input_var_list, true); 43596 | } 43597 | 43598 | // Make sure every return point has a scalar as its first parameter 43599 | if (parser_.dec().return_present()) 43600 | { 43601 | typedef std::vector<std::string> str_list_t; 43602 | 43603 | str_list_t ret_param_list = parser_.dec().return_param_type_list(); 43604 | 43605 | for (std::size_t i = 0; i < ret_param_list.size(); ++i) 43606 | { 43607 | const std::string& params = ret_param_list[i]; 43608 | 43609 | if (params.empty() || ('T' != params[0])) 43610 | { 43611 | exprtk_debug(("Compositor Error: Return statement in function '%s' is invalid\n", 43612 | name.c_str())); 43613 | 43614 | remove(name,input_var_list.size()); 43615 | 43616 | return false; 43617 | } 43618 | } 43619 | } 43620 | 43621 | expr_map_[name] = compiled_expression; 43622 | 43623 | exprtk::ifunction<T>& ifunc = (*(fp_map_[input_var_list.size()])[name]); 43624 | 43625 | if (symbol_table_.add_function(name,ifunc)) 43626 | return true; 43627 | else 43628 | { 43629 | exprtk_debug(("Compositor Error: Failed to add function '%s' to symbol table\n", 43630 | name.c_str())); 43631 | return false; 43632 | } 43633 | } 43634 | 43635 | inline bool symbol_used(const std::string& symbol) const 43636 | { 43637 | return ( 43638 | symbol_table_.is_variable (symbol) || 43639 | symbol_table_.is_stringvar (symbol) || 43640 | symbol_table_.is_function (symbol) || 43641 | symbol_table_.is_vector (symbol) || 43642 | symbol_table_.is_vararg_function(symbol) 43643 | ); 43644 | } 43645 | 43646 | inline bool valid(const std::string& name, 43647 | const std::size_t& arg_count) const 43648 | { 43649 | if (arg_count > 6) 43650 | return false; 43651 | else if (symbol_used(name)) 43652 | return false; 43653 | else if (fp_map_[arg_count].end() != fp_map_[arg_count].find(name)) 43654 | return false; 43655 | else 43656 | return true; 43657 | } 43658 | 43659 | inline bool forward(const std::string& name, 43660 | const std::size_t& arg_count, 43661 | symbol_table_t& sym_table, 43662 | const bool ret_present = false) 43663 | { 43664 | switch (arg_count) 43665 | { 43666 | #define case_stmt(N) \ 43667 | case N : (fp_map_[arg_count])[name] = \ 43668 | (!ret_present) ? static_cast<base_func*> \ 43669 | (new func_##N##param) : \ 43670 | static_cast<base_func*> \ 43671 | (new func_##N##param_retval) ; \ 43672 | break; \ 43673 | 43674 | case_stmt(0) case_stmt(1) case_stmt(2) 43675 | case_stmt(3) case_stmt(4) case_stmt(5) 43676 | case_stmt(6) 43677 | #undef case_stmt 43678 | } 43679 | 43680 | exprtk::ifunction<T>& ifunc = (*(fp_map_[arg_count])[name]); 43681 | 43682 | return sym_table.add_function(name,ifunc); 43683 | } 43684 | 43685 | inline void remove(const std::string& name, const std::size_t& arg_count) 43686 | { 43687 | if (arg_count > 6) 43688 | return; 43689 | 43690 | const typename std::map<std::string,expression_t>::iterator em_itr = expr_map_.find(name); 43691 | 43692 | if (expr_map_.end() != em_itr) 43693 | { 43694 | expr_map_.erase(em_itr); 43695 | } 43696 | 43697 | const typename funcparam_t::iterator fp_itr = fp_map_[arg_count].find(name); 43698 | 43699 | if (fp_map_[arg_count].end() != fp_itr) 43700 | { 43701 | delete fp_itr->second; 43702 | fp_map_[arg_count].erase(fp_itr); 43703 | } 43704 | 43705 | symbol_table_.remove_function(name); 43706 | } 43707 | 43708 | private: 43709 | 43710 | symbol_table_t symbol_table_; 43711 | parser_t parser_; 43712 | std::map<std::string,expression_t> expr_map_; 43713 | std::vector<funcparam_t> fp_map_; 43714 | std::vector<symbol_table_t*> auxiliary_symtab_list_; 43715 | std::deque<parser_error::type> error_list_; 43716 | bool load_variables_; 43717 | bool load_vectors_; 43718 | }; // class function_compositor 43719 | 43720 | } // namespace exprtk 43721 | 43722 | #if defined(_MSC_VER) || defined(_WIN32) || defined(__WIN32__) || defined(WIN32) 43723 | # ifndef NOMINMAX 43724 | # define NOMINMAX 43725 | # endif 43726 | # ifndef WIN32_LEAN_AND_MEAN 43727 | # define WIN32_LEAN_AND_MEAN 43728 | # endif 43729 | # include43730 | # include 43731 | #else 43732 | # include 43733 | # include 43734 | # include 43735 | #endif 43736 | 43737 | namespace exprtk 43738 | { 43739 | class timer 43740 | { 43741 | public: 43742 | 43743 | #if defined(_MSC_VER) || defined(_WIN32) || defined(__WIN32__) || defined(WIN32) 43744 | timer() 43745 | : in_use_(false) 43746 | , start_time_{ {0, 0} } 43747 | , stop_time_ { {0, 0} } 43748 | { 43749 | QueryPerformanceFrequency(&clock_frequency_); 43750 | } 43751 | 43752 | inline void start() 43753 | { 43754 | in_use_ = true; 43755 | QueryPerformanceCounter(&start_time_); 43756 | } 43757 | 43758 | inline void stop() 43759 | { 43760 | QueryPerformanceCounter(&stop_time_); 43761 | in_use_ = false; 43762 | } 43763 | 43764 | inline double time() const 43765 | { 43766 | return (1.0 * (stop_time_.QuadPart - start_time_.QuadPart)) / (1.0 * clock_frequency_.QuadPart); 43767 | } 43768 | 43769 | #else 43770 | 43771 | timer() 43772 | : in_use_(false) 43773 | { 43774 | start_time_.tv_sec = 0; 43775 | start_time_.tv_usec = 0; 43776 | 43777 | stop_time_.tv_sec = 0; 43778 | stop_time_.tv_usec = 0; 43779 | } 43780 | 43781 | inline void start() 43782 | { 43783 | in_use_ = true; 43784 | gettimeofday(&start_time_,0); 43785 | } 43786 | 43787 | inline void stop() 43788 | { 43789 | gettimeofday(&stop_time_, 0); 43790 | in_use_ = false; 43791 | } 43792 | 43793 | inline unsigned long long int usec_time() const 43794 | { 43795 | if (!in_use_) 43796 | { 43797 | if (stop_time_.tv_sec >= start_time_.tv_sec) 43798 | { 43799 | return 1000000LLU * static_cast<details::_uint64_t>(stop_time_.tv_sec - start_time_.tv_sec ) + 43800 | static_cast<details::_uint64_t>(stop_time_.tv_usec - start_time_.tv_usec) ; 43801 | } 43802 | else 43803 | return std::numeric_limits<details::_uint64_t>::max(); 43804 | } 43805 | else 43806 | return std::numeric_limits<details::_uint64_t>::max(); 43807 | } 43808 | 43809 | inline double time() const 43810 | { 43811 | return usec_time() * 0.000001; 43812 | } 43813 | 43814 | #endif 43815 | 43816 | inline bool in_use() const 43817 | { 43818 | return in_use_; 43819 | } 43820 | 43821 | private: 43822 | 43823 | bool in_use_; 43824 | 43825 | #if defined(_MSC_VER) || defined(_WIN32) || defined(__WIN32__) || defined(WIN32) 43826 | LARGE_INTEGER start_time_; 43827 | LARGE_INTEGER stop_time_; 43828 | LARGE_INTEGER clock_frequency_; 43829 | #else 43830 | struct timeval start_time_; 43831 | struct timeval stop_time_; 43832 | #endif 43833 | }; 43834 | 43835 | template <typename T> 43836 | struct type_defs 43837 | { 43838 | typedef symbol_table<T> symbol_table_t; 43839 | typedef expression<T> expression_t; 43840 | typedef parser<T> parser_t; 43841 | typedef parser_error::type error_t; 43842 | typedef function_compositor<T> compositor_t; 43843 | typedef typename compositor_t::function function_t; 43844 | }; 43845 | 43846 | } // namespace exprtk 43847 | 43848 | #ifndef exprtk_disable_rtl_io 43849 | namespace exprtk 43850 | { 43851 | namespace rtl { namespace io { namespace details 43852 | { 43853 | template <typename T> 43854 | inline void print_type(const std::string& fmt, 43855 | const T v, 43856 | exprtk::details::numeric::details::real_type_tag) 43857 | { 43858 | #if defined(__clang__) 43859 | #pragma clang diagnostic push 43860 | #pragma clang diagnostic ignored "-Wformat-nonliteral" 43861 | #elif defined(__GNUC__) || defined(__GNUG__) 43862 | #pragma GCC diagnostic push 43863 | #pragma GCC diagnostic ignored "-Wformat-nonliteral" 43864 | #elif defined(_MSC_VER) 43865 | #endif 43866 | 43867 | printf(fmt.c_str(), v); 43868 | 43869 | #if defined(__clang__) 43870 | #pragma clang diagnostic pop 43871 | #elif defined(__GNUC__) || defined(__GNUG__) 43872 | #pragma GCC diagnostic pop 43873 | #elif defined(_MSC_VER) 43874 | #endif 43875 | } 43876 | 43877 | template <typename T> 43878 | struct print_impl 43879 | { 43880 | typedef typename igeneric_function<T>::generic_type generic_type; 43881 | typedef typename igeneric_function<T>::parameter_list_t parameter_list_t; 43882 | typedef typename generic_type::scalar_view scalar_t; 43883 | typedef typename generic_type::vector_view vector_t; 43884 | typedef typename generic_type::string_view string_t; 43885 | typedef typename exprtk::details::numeric::details::number_type<T>::type num_type; 43886 | 43887 | static void process(const std::string& scalar_format, parameter_list_t parameters) 43888 | { 43889 | for (std::size_t i = 0; i < parameters.size(); ++i) 43890 | { 43891 | generic_type& gt = parameters[i]; 43892 | 43893 | switch (gt.type) 43894 | { 43895 | case generic_type::e_scalar : print(scalar_format,scalar_t(gt)); 43896 | break; 43897 | 43898 | case generic_type::e_vector : print(scalar_format,vector_t(gt)); 43899 | break; 43900 | 43901 | case generic_type::e_string : print(string_t(gt)); 43902 | break; 43903 | 43904 | default : continue; 43905 | } 43906 | } 43907 | } 43908 | 43909 | static inline void print(const std::string& scalar_format, const scalar_t& s) 43910 | { 43911 | print_type(scalar_format,s(),num_type()); 43912 | } 43913 | 43914 | static inline void print(const std::string& scalar_format, const vector_t& v) 43915 | { 43916 | for (std::size_t i = 0; i < v.size(); ++i) 43917 | { 43918 | print_type(scalar_format,v[i],num_type()); 43919 | 43920 | if ((i + 1) < v.size()) 43921 | printf(" "); 43922 | } 43923 | } 43924 | 43925 | static inline void print(const string_t& s) 43926 | { 43927 | printf("%s",to_str(s).c_str()); 43928 | } 43929 | }; 43930 | 43931 | } // namespace exprtk::rtl::io::details 43932 | 43933 | template <typename T> 43934 | struct print exprtk_final : public exprtk::igeneric_function<T> 43935 | { 43936 | typedef typename igeneric_function<T>::parameter_list_t parameter_list_t; 43937 | 43938 | using exprtk::igeneric_function<T>::operator(); 43939 | 43940 | explicit print(const std::string& scalar_format = "%10.5f") 43941 | : scalar_format_(scalar_format) 43942 | { 43943 | exprtk::enable_zero_parameters(*this); 43944 | } 43945 | 43946 | inline T operator() (parameter_list_t parameters) exprtk_override 43947 | { 43948 | details::print_impl<T>::process(scalar_format_,parameters); 43949 | return T(0); 43950 | } 43951 | 43952 | std::string scalar_format_; 43953 | }; 43954 | 43955 | template <typename T> 43956 | struct println exprtk_final : public exprtk::igeneric_function<T> 43957 | { 43958 | typedef typename igeneric_function<T>::parameter_list_t parameter_list_t; 43959 | 43960 | using exprtk::igeneric_function<T>::operator(); 43961 | 43962 | explicit println(const std::string& scalar_format = "%10.5f") 43963 | : scalar_format_(scalar_format) 43964 | { 43965 | exprtk::enable_zero_parameters(*this); 43966 | } 43967 | 43968 | inline T operator() (parameter_list_t parameters) exprtk_override 43969 | { 43970 | details::print_impl<T>::process(scalar_format_,parameters); 43971 | printf("\n"); 43972 | return T(0); 43973 | } 43974 | 43975 | std::string scalar_format_; 43976 | }; 43977 | 43978 | template <typename T> 43979 | struct package 43980 | { 43981 | print <T> p; 43982 | println<T> pl; 43983 | 43984 | bool register_package(exprtk::symbol_table<T>& symtab) 43985 | { 43986 | #define exprtk_register_function(FunctionName, FunctionType) \ 43987 | if (!symtab.add_function(FunctionName,FunctionType)) \ 43988 | { \ 43989 | exprtk_debug(( \ 43990 | "exprtk::rtl::io::register_package - Failed to add function: %s\n", \ 43991 | FunctionName)); \ 43992 | return false; \ 43993 | } \ 43994 | 43995 | exprtk_register_function("print" , p ) 43996 | exprtk_register_function("println", pl) 43997 | #undef exprtk_register_function 43998 | 43999 | return true; 44000 | } 44001 | }; 44002 | 44003 | } // namespace exprtk::rtl::io 44004 | } // namespace exprtk::rtl 44005 | } // namespace exprtk 44006 | #endif 44007 | 44008 | #ifndef exprtk_disable_rtl_io_file 44009 | #include 44010 | namespace exprtk 44011 | { 44012 | namespace rtl { namespace io { namespace file { namespace details 44013 | { 44014 | using ::exprtk::details::char_ptr; 44015 | using ::exprtk::details::char_cptr; 44016 | 44017 | enum file_mode 44018 | { 44019 | e_error = 0, 44020 | e_read = 1, 44021 | e_write = 2, 44022 | e_rdwrt = 4 44023 | }; 44024 | 44025 | struct file_descriptor 44026 | { 44027 | file_descriptor(const std::string& fname, const std::string& access) 44028 | : stream_ptr(0) 44029 | , mode(get_file_mode(access)) 44030 | , file_name(fname) 44031 | {} 44032 | 44033 | void* stream_ptr; 44034 | file_mode mode; 44035 | std::string file_name; 44036 | 44037 | bool open() 44038 | { 44039 | if (e_read == mode) 44040 | { 44041 | std::ifstream* stream = new std::ifstream(file_name.c_str(),std::ios::binary); 44042 | 44043 | if (!(*stream)) 44044 | { 44045 | file_name.clear(); 44046 | delete stream; 44047 | 44048 | return false; 44049 | } 44050 | 44051 | stream_ptr = stream; 44052 | 44053 | return true; 44054 | } 44055 | else if (e_write == mode) 44056 | { 44057 | std::ofstream* stream = new std::ofstream(file_name.c_str(),std::ios::binary); 44058 | 44059 | if (!(*stream)) 44060 | { 44061 | file_name.clear(); 44062 | delete stream; 44063 | 44064 | return false; 44065 | } 44066 | 44067 | stream_ptr = stream; 44068 | 44069 | return true; 44070 | } 44071 | else if (e_rdwrt == mode) 44072 | { 44073 | std::fstream* stream = new std::fstream(file_name.c_str(),std::ios::binary); 44074 | 44075 | if (!(*stream)) 44076 | { 44077 | file_name.clear(); 44078 | delete stream; 44079 | 44080 | return false; 44081 | } 44082 | 44083 | stream_ptr = stream; 44084 | 44085 | return true; 44086 | } 44087 | 44088 | return false; 44089 | } 44090 | 44091 | template <typename Stream, typename Ptr> 44092 | void close(Ptr& p) 44093 | { 44094 | Stream* stream = reinterpret_cast<Stream*>(p); 44095 | stream->close(); 44096 | delete stream; 44097 | p = reinterpret_cast<Ptr>(0); 44098 | } 44099 | 44100 | bool close() 44101 | { 44102 | switch (mode) 44103 | { 44104 | case e_read : close<std::ifstream>(stream_ptr); 44105 | break; 44106 | 44107 | case e_write : close<std::ofstream>(stream_ptr); 44108 | break; 44109 | 44110 | case e_rdwrt : close<std::fstream> (stream_ptr); 44111 | break; 44112 | 44113 | default : return false; 44114 | } 44115 | 44116 | return true; 44117 | } 44118 | 44119 | template <typename View> 44120 | bool write(const View& view, const std::size_t amount, const std::size_t offset = 0) 44121 | { 44122 | switch (mode) 44123 | { 44124 | case e_write : reinterpret_cast<std::ofstream*>(stream_ptr)-> 44125 | write(reinterpret_cast<char_cptr>(view.begin() + offset), amount * sizeof(typename View::value_t)); 44126 | break; 44127 | 44128 | case e_rdwrt : reinterpret_cast<std::fstream*>(stream_ptr)-> 44129 | write(reinterpret_cast<char_cptr>(view.begin() + offset) , amount * sizeof(typename View::value_t)); 44130 | break; 44131 | 44132 | default : return false; 44133 | } 44134 | 44135 | return true; 44136 | } 44137 | 44138 | template <typename View> 44139 | bool read(View& view, const std::size_t amount, const std::size_t offset = 0) 44140 | { 44141 | switch (mode) 44142 | { 44143 | case e_read : reinterpret_cast<std::ifstream*>(stream_ptr)-> 44144 | read(reinterpret_cast<char_ptr>(view.begin() + offset), amount * sizeof(typename View::value_t)); 44145 | break; 44146 | 44147 | case e_rdwrt : reinterpret_cast<std::fstream*>(stream_ptr)-> 44148 | read(reinterpret_cast<char_ptr>(view.begin() + offset) , amount * sizeof(typename View::value_t)); 44149 | break; 44150 | 44151 | default : return false; 44152 | } 44153 | 44154 | return true; 44155 | } 44156 | 44157 | bool getline(std::string& s) 44158 | { 44159 | switch (mode) 44160 | { 44161 | case e_read : return (!!std::getline(*reinterpret_cast<std::ifstream*>(stream_ptr),s)); 44162 | case e_rdwrt : return (!!std::getline(*reinterpret_cast<std::fstream* >(stream_ptr),s)); 44163 | default : return false; 44164 | } 44165 | } 44166 | 44167 | bool eof() const 44168 | { 44169 | switch (mode) 44170 | { 44171 | case e_read : return reinterpret_cast<std::ifstream*>(stream_ptr)->eof(); 44172 | case e_write : return reinterpret_cast<std::ofstream*>(stream_ptr)->eof(); 44173 | case e_rdwrt : return reinterpret_cast<std::fstream* >(stream_ptr)->eof(); 44174 | default : return true; 44175 | } 44176 | } 44177 | 44178 | file_mode get_file_mode(const std::string& access) const 44179 | { 44180 | if (access.empty() || access.size() > 2) 44181 | return e_error; 44182 | 44183 | std::size_t w_cnt = 0; 44184 | std::size_t r_cnt = 0; 44185 | 44186 | for (std::size_t i = 0; i < access.size(); ++i) 44187 | { 44188 | switch (std::tolower(access[i])) 44189 | { 44190 | case 'r' : r_cnt++; break; 44191 | case 'w' : w_cnt++; break; 44192 | default : return e_error; 44193 | } 44194 | } 44195 | 44196 | if ((0 == r_cnt) && (0 == w_cnt)) 44197 | return e_error; 44198 | else if ((r_cnt > 1) || (w_cnt > 1)) 44199 | return e_error; 44200 | else if ((1 == r_cnt) && (1 == w_cnt)) 44201 | return e_rdwrt; 44202 | else if (1 == r_cnt) 44203 | return e_read; 44204 | else 44205 | return e_write; 44206 | } 44207 | }; 44208 | 44209 | template <typename T> 44210 | file_descriptor* make_handle(T v) 44211 | { 44212 | const std::size_t fd_size = sizeof(details::file_descriptor*); 44213 | details::file_descriptor* fd = reinterpret_cast<file_descriptor*>(0); 44214 | 44215 | std::memcpy(reinterpret_cast<char_ptr >(&fd), 44216 | reinterpret_cast<char_cptr>(&v ), 44217 | fd_size); 44218 | return fd; 44219 | } 44220 | 44221 | template <typename T> 44222 | void perform_check() 44223 | { 44224 | #ifdef _MSC_VER 44225 | #pragma warning(push) 44226 | #pragma warning(disable: 4127) 44227 | #endif 44228 | if (sizeof(T) < sizeof(void*)) 44229 | { 44230 | throw std::runtime_error("exprtk::rtl::io::file - Error - pointer size larger than holder."); 44231 | } 44232 | #ifdef _MSC_VER 44233 | #pragma warning(pop) 44234 | #endif 44235 | assert(sizeof(T) <= sizeof(void*)); 44236 | } 44237 | 44238 | } // namespace exprtk::rtl::io::file::details 44239 | 44240 | template <typename T> 44241 | class open exprtk_final : public exprtk::igeneric_function<T> 44242 | { 44243 | public: 44244 | 44245 | typedef typename exprtk::igeneric_function<T> igfun_t; 44246 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44247 | typedef typename igfun_t::generic_type generic_type; 44248 | typedef typename generic_type::string_view string_t; 44249 | 44250 | using igfun_t::operator(); 44251 | 44252 | open() 44253 | : exprtk::igeneric_function<T>("S|SS") 44254 | { details::perform_check<T>(); } 44255 | 44256 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44257 | { 44258 | const std::string file_name = to_str(string_t(parameters[0])); 44259 | 44260 | if (file_name.empty()) 44261 | { 44262 | return T(0); 44263 | } 44264 | 44265 | if ((1 == ps_index) && (0 == string_t(parameters[1]).size())) 44266 | { 44267 | return T(0); 44268 | } 44269 | 44270 | const std::string access = 44271 | (0 == ps_index) ? "r" : to_str(string_t(parameters[1])); 44272 | 44273 | details::file_descriptor* fd = new details::file_descriptor(file_name,access); 44274 | 44275 | if (fd->open()) 44276 | { 44277 | T t = T(0); 44278 | 44279 | const std::size_t fd_size = sizeof(details::file_descriptor*); 44280 | 44281 | std::memcpy(reinterpret_cast<char*>(&t ), 44282 | reinterpret_cast<char*>(&fd), 44283 | fd_size); 44284 | return t; 44285 | } 44286 | else 44287 | { 44288 | delete fd; 44289 | return T(0); 44290 | } 44291 | } 44292 | }; 44293 | 44294 | template <typename T> 44295 | struct close exprtk_final : public exprtk::ifunction<T> 44296 | { 44297 | using exprtk::ifunction<T>::operator(); 44298 | 44299 | close() 44300 | : exprtk::ifunction<T>(1) 44301 | { details::perform_check<T>(); } 44302 | 44303 | inline T operator() (const T& v) exprtk_override 44304 | { 44305 | details::file_descriptor* fd = details::make_handle(v); 44306 | 44307 | if (!fd->close()) 44308 | return T(0); 44309 | 44310 | delete fd; 44311 | 44312 | return T(1); 44313 | } 44314 | }; 44315 | 44316 | template <typename T> 44317 | class write exprtk_final : public exprtk::igeneric_function<T> 44318 | { 44319 | public: 44320 | 44321 | typedef typename exprtk::igeneric_function<T> igfun_t; 44322 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44323 | typedef typename igfun_t::generic_type generic_type; 44324 | typedef typename generic_type::string_view string_t; 44325 | typedef typename generic_type::scalar_view scalar_t; 44326 | typedef typename generic_type::vector_view vector_t; 44327 | 44328 | using igfun_t::operator(); 44329 | 44330 | write() 44331 | : igfun_t("TS|TST|TV|TVT") 44332 | { details::perform_check<T>(); } 44333 | 44334 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44335 | { 44336 | details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])()); 44337 | 44338 | switch (ps_index) 44339 | { 44340 | case 0 : { 44341 | const string_t buffer(parameters[1]); 44342 | const std::size_t amount = buffer.size(); 44343 | return T(fd->write(buffer, amount) ? 1 : 0); 44344 | } 44345 | 44346 | case 1 : { 44347 | const string_t buffer(parameters[1]); 44348 | const std::size_t amount = 44349 | std::min(buffer.size(), 44350 | static_cast<std::size_t>(scalar_t(parameters[2])())); 44351 | return T(fd->write(buffer, amount) ? 1 : 0); 44352 | } 44353 | 44354 | case 2 : { 44355 | const vector_t vec(parameters[1]); 44356 | const std::size_t amount = vec.size(); 44357 | return T(fd->write(vec, amount) ? 1 : 0); 44358 | } 44359 | 44360 | case 3 : { 44361 | const vector_t vec(parameters[1]); 44362 | const std::size_t amount = 44363 | std::min(vec.size(), 44364 | static_cast<std::size_t>(scalar_t(parameters[2])())); 44365 | return T(fd->write(vec, amount) ? 1 : 0); 44366 | } 44367 | } 44368 | 44369 | return T(0); 44370 | } 44371 | }; 44372 | 44373 | template <typename T> 44374 | class read exprtk_final : public exprtk::igeneric_function<T> 44375 | { 44376 | public: 44377 | 44378 | typedef typename exprtk::igeneric_function<T> igfun_t; 44379 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44380 | typedef typename igfun_t::generic_type generic_type; 44381 | typedef typename generic_type::string_view string_t; 44382 | typedef typename generic_type::scalar_view scalar_t; 44383 | typedef typename generic_type::vector_view vector_t; 44384 | 44385 | using igfun_t::operator(); 44386 | 44387 | read() 44388 | : igfun_t("TS|TST|TV|TVT") 44389 | { details::perform_check<T>(); } 44390 | 44391 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44392 | { 44393 | details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])()); 44394 | 44395 | switch (ps_index) 44396 | { 44397 | case 0 : { 44398 | string_t buffer(parameters[1]); 44399 | const std::size_t amount = buffer.size(); 44400 | return T(fd->read(buffer,amount) ? 1 : 0); 44401 | } 44402 | 44403 | case 1 : { 44404 | string_t buffer(parameters[1]); 44405 | const std::size_t amount = 44406 | std::min(buffer.size(), 44407 | static_cast<std::size_t>(scalar_t(parameters[2])())); 44408 | return T(fd->read(buffer,amount) ? 1 : 0); 44409 | } 44410 | 44411 | case 2 : { 44412 | vector_t vec(parameters[1]); 44413 | const std::size_t amount = vec.size(); 44414 | return T(fd->read(vec,amount) ? 1 : 0); 44415 | } 44416 | 44417 | case 3 : { 44418 | vector_t vec(parameters[1]); 44419 | const std::size_t amount = 44420 | std::min(vec.size(), 44421 | static_cast<std::size_t>(scalar_t(parameters[2])())); 44422 | return T(fd->read(vec,amount) ? 1 : 0); 44423 | } 44424 | } 44425 | 44426 | return T(0); 44427 | } 44428 | }; 44429 | 44430 | template <typename T> 44431 | class getline exprtk_final : public exprtk::igeneric_function<T> 44432 | { 44433 | public: 44434 | 44435 | typedef typename exprtk::igeneric_function<T> igfun_t; 44436 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44437 | typedef typename igfun_t::generic_type generic_type; 44438 | typedef typename generic_type::string_view string_t; 44439 | typedef typename generic_type::scalar_view scalar_t; 44440 | 44441 | using igfun_t::operator(); 44442 | 44443 | getline() 44444 | : igfun_t("T",igfun_t::e_rtrn_string) 44445 | { details::perform_check<T>(); } 44446 | 44447 | inline T operator() (std::string& result, parameter_list_t parameters) exprtk_override 44448 | { 44449 | details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])()); 44450 | return T(fd->getline(result) ? 1 : 0); 44451 | } 44452 | }; 44453 | 44454 | template <typename T> 44455 | struct eof exprtk_final : public exprtk::ifunction<T> 44456 | { 44457 | using exprtk::ifunction<T>::operator(); 44458 | 44459 | eof() 44460 | : exprtk::ifunction<T>(1) 44461 | { details::perform_check<T>(); } 44462 | 44463 | inline T operator() (const T& v) exprtk_override 44464 | { 44465 | details::file_descriptor* fd = details::make_handle(v); 44466 | return (fd->eof() ? T(1) : T(0)); 44467 | } 44468 | }; 44469 | 44470 | template <typename T> 44471 | struct package 44472 | { 44473 | open <T> o; 44474 | close <T> c; 44475 | write <T> w; 44476 | read <T> r; 44477 | getline<T> g; 44478 | eof <T> e; 44479 | 44480 | bool register_package(exprtk::symbol_table<T>& symtab) 44481 | { 44482 | #define exprtk_register_function(FunctionName, FunctionType) \ 44483 | if (!symtab.add_function(FunctionName,FunctionType)) \ 44484 | { \ 44485 | exprtk_debug(( \ 44486 | "exprtk::rtl::io::file::register_package - Failed to add function: %s\n", \ 44487 | FunctionName)); \ 44488 | return false; \ 44489 | } \ 44490 | 44491 | exprtk_register_function("open" , o) 44492 | exprtk_register_function("close" , c) 44493 | exprtk_register_function("write" , w) 44494 | exprtk_register_function("read" , r) 44495 | exprtk_register_function("getline" , g) 44496 | exprtk_register_function("eof" , e) 44497 | #undef exprtk_register_function 44498 | 44499 | return true; 44500 | } 44501 | }; 44502 | 44503 | } // namespace exprtk::rtl::io::file 44504 | } // namespace exprtk::rtl::io 44505 | } // namespace exprtk::rtl 44506 | } // namespace exprtk 44507 | #endif 44508 | 44509 | #ifndef exprtk_disable_rtl_vecops 44510 | namespace exprtk 44511 | { 44512 | namespace rtl { namespace vecops { 44513 | 44514 | namespace helper 44515 | { 44516 | template <typename Vector> 44517 | inline bool invalid_range(const Vector& v, const std::size_t r0, const std::size_t r1) 44518 | { 44519 | if (r0 > (v.size() - 1)) 44520 | return true; 44521 | else if (r1 > (v.size() - 1)) 44522 | return true; 44523 | else if (r1 < r0) 44524 | return true; 44525 | else 44526 | return false; 44527 | } 44528 | 44529 | template <typename T> 44530 | struct load_vector_range 44531 | { 44532 | typedef typename exprtk::igeneric_function<T> igfun_t; 44533 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44534 | typedef typename igfun_t::generic_type generic_type; 44535 | typedef typename generic_type::scalar_view scalar_t; 44536 | typedef typename generic_type::vector_view vector_t; 44537 | 44538 | static inline bool process(parameter_list_t& parameters, 44539 | std::size_t& r0, std::size_t& r1, 44540 | const std::size_t& r0_prmidx, 44541 | const std::size_t& r1_prmidx, 44542 | const std::size_t vec_idx = 0) 44543 | { 44544 | if (r0_prmidx >= parameters.size()) 44545 | return false; 44546 | 44547 | if (r1_prmidx >= parameters.size()) 44548 | return false; 44549 | 44550 | if (!scalar_t(parameters[r0_prmidx]).to_uint(r0)) 44551 | return false; 44552 | 44553 | if (!scalar_t(parameters[r1_prmidx]).to_uint(r1)) 44554 | return false; 44555 | 44556 | return !invalid_range(vector_t(parameters[vec_idx]), r0, r1); 44557 | } 44558 | }; 44559 | } 44560 | 44561 | namespace details 44562 | { 44563 | template <typename T> 44564 | inline void kahan_sum(T& sum, T& error, const T v) 44565 | { 44566 | const T x = v - error; 44567 | const T y = sum + x; 44568 | error = (y - sum) - x; 44569 | sum = y; 44570 | } 44571 | 44572 | } // namespace exprtk::rtl::details 44573 | 44574 | template <typename T> 44575 | class all_true exprtk_final : public exprtk::igeneric_function<T> 44576 | { 44577 | public: 44578 | 44579 | typedef typename exprtk::igeneric_function<T> igfun_t; 44580 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44581 | typedef typename igfun_t::generic_type generic_type; 44582 | typedef typename generic_type::scalar_view scalar_t; 44583 | typedef typename generic_type::vector_view vector_t; 44584 | 44585 | using igfun_t::operator(); 44586 | 44587 | all_true() 44588 | : exprtk::igeneric_function<T>("V|VTT|T*") 44589 | /* 44590 | Overloads: 44591 | 0. V - vector 44592 | 1. VTT - vector, r0, r1 44593 | 2. T* - T....T 44594 | */ 44595 | {} 44596 | 44597 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44598 | { 44599 | if (2 == ps_index) 44600 | { 44601 | for (std::size_t i = 0; i < parameters.size(); ++i) 44602 | { 44603 | if (scalar_t(parameters[i])() == T(0)) 44604 | { 44605 | return T(0); 44606 | } 44607 | } 44608 | } 44609 | else 44610 | { 44611 | const vector_t vec(parameters[0]); 44612 | 44613 | std::size_t r0 = 0; 44614 | std::size_t r1 = vec.size() - 1; 44615 | 44616 | if ( 44617 | (1 == ps_index) && 44618 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 44619 | ) 44620 | { 44621 | return std::numeric_limits<T>::quiet_NaN(); 44622 | } 44623 | 44624 | for (std::size_t i = r0; i <= r1; ++i) 44625 | { 44626 | if (vec[i] == T(0)) 44627 | { 44628 | return T(0); 44629 | } 44630 | } 44631 | } 44632 | 44633 | return T(1); 44634 | } 44635 | }; 44636 | 44637 | template <typename T> 44638 | class all_false exprtk_final : public exprtk::igeneric_function<T> 44639 | { 44640 | public: 44641 | 44642 | typedef typename exprtk::igeneric_function<T> igfun_t; 44643 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44644 | typedef typename igfun_t::generic_type generic_type; 44645 | typedef typename generic_type::scalar_view scalar_t; 44646 | typedef typename generic_type::vector_view vector_t; 44647 | 44648 | using igfun_t::operator(); 44649 | 44650 | all_false() 44651 | : exprtk::igeneric_function<T>("V|VTT|T*") 44652 | /* 44653 | Overloads: 44654 | 0. V - vector 44655 | 1. VTT - vector, r0, r1 44656 | 2. T* - T....T 44657 | */ 44658 | {} 44659 | 44660 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44661 | { 44662 | if (2 == ps_index) 44663 | { 44664 | for (std::size_t i = 0; i < parameters.size(); ++i) 44665 | { 44666 | if (scalar_t(parameters[i])() != T(0)) 44667 | { 44668 | return T(0); 44669 | } 44670 | } 44671 | } 44672 | else 44673 | { 44674 | const vector_t vec(parameters[0]); 44675 | 44676 | std::size_t r0 = 0; 44677 | std::size_t r1 = vec.size() - 1; 44678 | 44679 | if ( 44680 | (1 == ps_index) && 44681 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 44682 | ) 44683 | { 44684 | return std::numeric_limits<T>::quiet_NaN(); 44685 | } 44686 | 44687 | for (std::size_t i = r0; i <= r1; ++i) 44688 | { 44689 | if (vec[i] != T(0)) 44690 | { 44691 | return T(0); 44692 | } 44693 | } 44694 | } 44695 | 44696 | return T(1); 44697 | } 44698 | }; 44699 | 44700 | template <typename T> 44701 | class any_true exprtk_final : public exprtk::igeneric_function<T> 44702 | { 44703 | public: 44704 | 44705 | typedef typename exprtk::igeneric_function<T> igfun_t; 44706 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44707 | typedef typename igfun_t::generic_type generic_type; 44708 | typedef typename generic_type::scalar_view scalar_t; 44709 | typedef typename generic_type::vector_view vector_t; 44710 | 44711 | using igfun_t::operator(); 44712 | 44713 | any_true() 44714 | : exprtk::igeneric_function<T>("V|VTT|T*") 44715 | /* 44716 | Overloads: 44717 | 0. V - vector 44718 | 1. VTT - vector, r0, r1 44719 | 2. T* - T....T 44720 | */ 44721 | {} 44722 | 44723 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44724 | { 44725 | if (2 == ps_index) 44726 | { 44727 | for (std::size_t i = 0; i < parameters.size(); ++i) 44728 | { 44729 | if (scalar_t(parameters[i])() != T(0)) 44730 | { 44731 | return T(1); 44732 | } 44733 | } 44734 | } 44735 | else 44736 | { 44737 | const vector_t vec(parameters[0]); 44738 | 44739 | std::size_t r0 = 0; 44740 | std::size_t r1 = vec.size() - 1; 44741 | 44742 | if ( 44743 | (1 == ps_index) && 44744 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 44745 | ) 44746 | { 44747 | return std::numeric_limits<T>::quiet_NaN(); 44748 | } 44749 | 44750 | for (std::size_t i = r0; i <= r1; ++i) 44751 | { 44752 | if (vec[i] != T(0)) 44753 | { 44754 | return T(1); 44755 | } 44756 | } 44757 | } 44758 | 44759 | return T(0); 44760 | } 44761 | }; 44762 | 44763 | template <typename T> 44764 | class any_false exprtk_final : public exprtk::igeneric_function<T> 44765 | { 44766 | public: 44767 | 44768 | typedef typename exprtk::igeneric_function<T> igfun_t; 44769 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44770 | typedef typename igfun_t::generic_type generic_type; 44771 | typedef typename generic_type::scalar_view scalar_t; 44772 | typedef typename generic_type::vector_view vector_t; 44773 | 44774 | using igfun_t::operator(); 44775 | 44776 | any_false() 44777 | : exprtk::igeneric_function<T>("V|VTT|T*") 44778 | /* 44779 | Overloads: 44780 | 0. V - vector 44781 | 1. VTT - vector, r0, r1 44782 | 2. T* - T....T 44783 | */ 44784 | {} 44785 | 44786 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44787 | { 44788 | if (2 == ps_index) 44789 | { 44790 | for (std::size_t i = 0; i < parameters.size(); ++i) 44791 | { 44792 | if (scalar_t(parameters[i])() == T(0)) 44793 | { 44794 | return T(1); 44795 | } 44796 | } 44797 | } 44798 | else 44799 | { 44800 | const vector_t vec(parameters[0]); 44801 | 44802 | std::size_t r0 = 0; 44803 | std::size_t r1 = vec.size() - 1; 44804 | 44805 | if ( 44806 | (1 == ps_index) && 44807 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 44808 | ) 44809 | { 44810 | return std::numeric_limits<T>::quiet_NaN(); 44811 | } 44812 | 44813 | for (std::size_t i = r0; i <= r1; ++i) 44814 | { 44815 | if (vec[i] == T(0)) 44816 | { 44817 | return T(1); 44818 | } 44819 | } 44820 | } 44821 | 44822 | return T(0); 44823 | } 44824 | }; 44825 | 44826 | template <typename T> 44827 | class count exprtk_final : public exprtk::igeneric_function<T> 44828 | { 44829 | public: 44830 | 44831 | typedef typename exprtk::igeneric_function<T> igfun_t; 44832 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44833 | typedef typename igfun_t::generic_type generic_type; 44834 | typedef typename generic_type::scalar_view scalar_t; 44835 | typedef typename generic_type::vector_view vector_t; 44836 | 44837 | using igfun_t::operator(); 44838 | 44839 | count() 44840 | : exprtk::igeneric_function<T>("V|VTT|T*") 44841 | /* 44842 | Overloads: 44843 | 0. V - vector 44844 | 1. VTT - vector, r0, r1 44845 | 2. T* - T....T 44846 | */ 44847 | {} 44848 | 44849 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44850 | { 44851 | std::size_t cnt = 0; 44852 | 44853 | if (2 == ps_index) 44854 | { 44855 | for (std::size_t i = 0; i < parameters.size(); ++i) 44856 | { 44857 | if (scalar_t(parameters[i])() != T(0)) ++cnt; 44858 | } 44859 | } 44860 | else 44861 | { 44862 | const vector_t vec(parameters[0]); 44863 | 44864 | std::size_t r0 = 0; 44865 | std::size_t r1 = vec.size() - 1; 44866 | 44867 | if ( 44868 | (1 == ps_index) && 44869 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 44870 | ) 44871 | { 44872 | return std::numeric_limits<T>::quiet_NaN(); 44873 | } 44874 | 44875 | for (std::size_t i = r0; i <= r1; ++i) 44876 | { 44877 | if (vec[i] != T(0)) ++cnt; 44878 | } 44879 | } 44880 | 44881 | return T(cnt); 44882 | } 44883 | }; 44884 | 44885 | template <typename T> 44886 | class copy exprtk_final : public exprtk::igeneric_function<T> 44887 | { 44888 | public: 44889 | 44890 | typedef typename exprtk::igeneric_function<T> igfun_t; 44891 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44892 | typedef typename igfun_t::generic_type generic_type; 44893 | typedef typename generic_type::scalar_view scalar_t; 44894 | typedef typename generic_type::vector_view vector_t; 44895 | 44896 | using igfun_t::operator(); 44897 | 44898 | copy() 44899 | : exprtk::igeneric_function<T>("VV|VTTVTT") 44900 | /* 44901 | Overloads: 44902 | 0. VV - x(vector), y(vector) 44903 | 1. VTTVTT - x(vector), xr0, xr1, y(vector), yr0, yr1, 44904 | */ 44905 | {} 44906 | 44907 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44908 | { 44909 | const vector_t x(parameters[0]); 44910 | vector_t y(parameters[(0 == ps_index) ? 1 : 3]); 44911 | 44912 | std::size_t xr0 = 0; 44913 | std::size_t xr1 = x.size() - 1; 44914 | 44915 | std::size_t yr0 = 0; 44916 | std::size_t yr1 = y.size() - 1; 44917 | 44918 | if (1 == ps_index) 44919 | { 44920 | if ( 44921 | !helper::load_vector_range<T>::process(parameters, xr0, xr1, 1, 2, 0) || 44922 | !helper::load_vector_range<T>::process(parameters, yr0, yr1, 4, 5, 3) 44923 | ) 44924 | return T(0); 44925 | } 44926 | 44927 | const std::size_t n = std::min(xr1 - xr0 + 1, yr1 - yr0 + 1); 44928 | 44929 | std::copy( 44930 | x.begin() + xr0, 44931 | x.begin() + xr0 + n, 44932 | y.begin() + yr0); 44933 | 44934 | return T(n); 44935 | } 44936 | }; 44937 | 44938 | template <typename T> 44939 | class rol exprtk_final : public exprtk::igeneric_function<T> 44940 | { 44941 | public: 44942 | 44943 | typedef typename exprtk::igeneric_function<T> igfun_t; 44944 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44945 | typedef typename igfun_t::generic_type generic_type; 44946 | typedef typename generic_type::scalar_view scalar_t; 44947 | typedef typename generic_type::vector_view vector_t; 44948 | 44949 | using igfun_t::operator(); 44950 | 44951 | rol() 44952 | : exprtk::igeneric_function<T>("VT|VTTT") 44953 | /* 44954 | Overloads: 44955 | 0. VT - vector, N 44956 | 1. VTTT - vector, N, r0, r1 44957 | */ 44958 | {} 44959 | 44960 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 44961 | { 44962 | vector_t vec(parameters[0]); 44963 | 44964 | std::size_t n = 0; 44965 | std::size_t r0 = 0; 44966 | std::size_t r1 = vec.size() - 1; 44967 | 44968 | if (!scalar_t(parameters[1]).to_uint(n)) 44969 | return T(0); 44970 | 44971 | if ( 44972 | (1 == ps_index) && 44973 | !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0) 44974 | ) 44975 | return T(0); 44976 | 44977 | const std::size_t dist = r1 - r0 + 1; 44978 | const std::size_t shift = n % dist; 44979 | 44980 | std::rotate( 44981 | vec.begin() + r0, 44982 | vec.begin() + r0 + shift, 44983 | vec.begin() + r1 + 1); 44984 | 44985 | return T(1); 44986 | } 44987 | }; 44988 | 44989 | template <typename T> 44990 | class ror exprtk_final : public exprtk::igeneric_function<T> 44991 | { 44992 | public: 44993 | 44994 | typedef typename exprtk::igeneric_function<T> igfun_t; 44995 | typedef typename igfun_t::parameter_list_t parameter_list_t; 44996 | typedef typename igfun_t::generic_type generic_type; 44997 | typedef typename generic_type::scalar_view scalar_t; 44998 | typedef typename generic_type::vector_view vector_t; 44999 | 45000 | using igfun_t::operator(); 45001 | 45002 | ror() 45003 | : exprtk::igeneric_function<T>("VT|VTTT") 45004 | /* 45005 | Overloads: 45006 | 0. VT - vector, N 45007 | 1. VTTT - vector, N, r0, r1 45008 | */ 45009 | {} 45010 | 45011 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45012 | { 45013 | vector_t vec(parameters[0]); 45014 | 45015 | std::size_t n = 0; 45016 | std::size_t r0 = 0; 45017 | std::size_t r1 = vec.size() - 1; 45018 | 45019 | if (!scalar_t(parameters[1]).to_uint(n)) 45020 | return T(0); 45021 | 45022 | if ( 45023 | (1 == ps_index) && 45024 | !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0) 45025 | ) 45026 | return T(0); 45027 | 45028 | const std::size_t dist = r1 - r0 + 1; 45029 | const std::size_t shift = (dist - (n % dist)) % dist; 45030 | 45031 | std::rotate( 45032 | vec.begin() + r0, 45033 | vec.begin() + r0 + shift, 45034 | vec.begin() + r1 + 1); 45035 | 45036 | return T(1); 45037 | } 45038 | }; 45039 | 45040 | template <typename T> 45041 | class reverse exprtk_final : public exprtk::igeneric_function<T> 45042 | { 45043 | public: 45044 | 45045 | typedef typename exprtk::igeneric_function<T> igfun_t; 45046 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45047 | typedef typename igfun_t::generic_type generic_type; 45048 | typedef typename generic_type::scalar_view scalar_t; 45049 | typedef typename generic_type::vector_view vector_t; 45050 | 45051 | using igfun_t::operator(); 45052 | 45053 | reverse() 45054 | : exprtk::igeneric_function<T>("V|VTT") 45055 | /* 45056 | Overloads: 45057 | 0. V - vector 45058 | 1. VTT - vector, r0, r1 45059 | */ 45060 | {} 45061 | 45062 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45063 | { 45064 | vector_t vec(parameters[0]); 45065 | 45066 | std::size_t r0 = 0; 45067 | std::size_t r1 = vec.size() - 1; 45068 | 45069 | if ( 45070 | (1 == ps_index) && 45071 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 45072 | ) 45073 | return T(0); 45074 | 45075 | std::reverse(vec.begin() + r0, vec.begin() + r1 + 1); 45076 | 45077 | return T(1); 45078 | } 45079 | }; 45080 | 45081 | template <typename T> 45082 | class shift_left exprtk_final : public exprtk::igeneric_function<T> 45083 | { 45084 | public: 45085 | 45086 | typedef typename exprtk::igeneric_function<T> igfun_t; 45087 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45088 | typedef typename igfun_t::generic_type generic_type; 45089 | typedef typename generic_type::scalar_view scalar_t; 45090 | typedef typename generic_type::vector_view vector_t; 45091 | 45092 | using igfun_t::operator(); 45093 | 45094 | shift_left() 45095 | : exprtk::igeneric_function<T>("VT|VTTT") 45096 | /* 45097 | Overloads: 45098 | 0. VT - vector, N 45099 | 1. VTTT - vector, N, r0, r1 45100 | */ 45101 | {} 45102 | 45103 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45104 | { 45105 | vector_t vec(parameters[0]); 45106 | 45107 | std::size_t n = 0; 45108 | std::size_t r0 = 0; 45109 | std::size_t r1 = vec.size() - 1; 45110 | 45111 | if (!scalar_t(parameters[1]).to_uint(n)) 45112 | return T(0); 45113 | 45114 | if ( 45115 | (1 == ps_index) && 45116 | !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0) 45117 | ) 45118 | return T(0); 45119 | 45120 | const std::size_t dist = r1 - r0 + 1; 45121 | 45122 | if (n > dist) 45123 | return T(0); 45124 | 45125 | std::rotate( 45126 | vec.begin() + r0, 45127 | vec.begin() + r0 + n, 45128 | vec.begin() + r1 + 1); 45129 | 45130 | for (std::size_t i = r1 - n + 1ULL; i <= r1; ++i) 45131 | { 45132 | vec[i] = T(0); 45133 | } 45134 | 45135 | return T(1); 45136 | } 45137 | }; 45138 | 45139 | template <typename T> 45140 | class shift_right exprtk_final : public exprtk::igeneric_function<T> 45141 | { 45142 | public: 45143 | 45144 | typedef typename exprtk::igeneric_function<T> igfun_t; 45145 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45146 | typedef typename igfun_t::generic_type generic_type; 45147 | typedef typename generic_type::scalar_view scalar_t; 45148 | typedef typename generic_type::vector_view vector_t; 45149 | 45150 | using igfun_t::operator(); 45151 | 45152 | shift_right() 45153 | : exprtk::igeneric_function<T>("VT|VTTT") 45154 | /* 45155 | Overloads: 45156 | 0. VT - vector, N 45157 | 1. VTTT - vector, N, r0, r1 45158 | */ 45159 | {} 45160 | 45161 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45162 | { 45163 | vector_t vec(parameters[0]); 45164 | 45165 | std::size_t n = 0; 45166 | std::size_t r0 = 0; 45167 | std::size_t r1 = vec.size() - 1; 45168 | 45169 | if (!scalar_t(parameters[1]).to_uint(n)) 45170 | return T(0); 45171 | 45172 | if ( 45173 | (1 == ps_index) && 45174 | !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0) 45175 | ) 45176 | return T(0); 45177 | 45178 | const std::size_t dist = r1 - r0 + 1; 45179 | 45180 | if (n > dist) 45181 | return T(0); 45182 | 45183 | const std::size_t shift = (dist - (n % dist)) % dist; 45184 | 45185 | std::rotate( 45186 | vec.begin() + r0, 45187 | vec.begin() + r0 + shift, 45188 | vec.begin() + r1 + 1); 45189 | 45190 | for (std::size_t i = r0; i < r0 + n; ++i) 45191 | { 45192 | vec[i] = T(0); 45193 | } 45194 | 45195 | return T(1); 45196 | } 45197 | }; 45198 | 45199 | template <typename T> 45200 | class sort exprtk_final : public exprtk::igeneric_function<T> 45201 | { 45202 | public: 45203 | 45204 | typedef typename exprtk::igeneric_function<T> igfun_t; 45205 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45206 | typedef typename igfun_t::generic_type generic_type; 45207 | typedef typename generic_type::string_view string_t; 45208 | typedef typename generic_type::vector_view vector_t; 45209 | 45210 | using igfun_t::operator(); 45211 | 45212 | sort() 45213 | : exprtk::igeneric_function<T>("V|VTT|VS|VSTT") 45214 | /* 45215 | Overloads: 45216 | 0. V - vector 45217 | 1. VTT - vector, r0, r1 45218 | 2. VS - vector, string 45219 | 3. VSTT - vector, string, r0, r1 45220 | */ 45221 | {} 45222 | 45223 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45224 | { 45225 | vector_t vec(parameters[0]); 45226 | 45227 | std::size_t r0 = 0; 45228 | std::size_t r1 = vec.size() - 1; 45229 | 45230 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)) 45231 | return T(0); 45232 | if ((3 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)) 45233 | return T(0); 45234 | 45235 | bool ascending = true; 45236 | 45237 | if ((2 == ps_index) || (3 == ps_index)) 45238 | { 45239 | if (exprtk::details::imatch(to_str(string_t(parameters[1])),"ascending")) 45240 | ascending = true; 45241 | else if (exprtk::details::imatch(to_str(string_t(parameters[1])),"descending")) 45242 | ascending = false; 45243 | else 45244 | return T(0); 45245 | } 45246 | 45247 | if (ascending) 45248 | std::sort( 45249 | vec.begin() + r0, 45250 | vec.begin() + r1 + 1, 45251 | std::less<T>()); 45252 | else 45253 | std::sort( 45254 | vec.begin() + r0, 45255 | vec.begin() + r1 + 1, 45256 | std::greater<T>()); 45257 | 45258 | return T(1); 45259 | } 45260 | }; 45261 | 45262 | template <typename T> 45263 | class nthelement exprtk_final : public exprtk::igeneric_function<T> 45264 | { 45265 | public: 45266 | 45267 | typedef typename exprtk::igeneric_function<T> igfun_t; 45268 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45269 | typedef typename igfun_t::generic_type generic_type; 45270 | typedef typename generic_type::scalar_view scalar_t; 45271 | typedef typename generic_type::vector_view vector_t; 45272 | 45273 | using igfun_t::operator(); 45274 | 45275 | nthelement() 45276 | : exprtk::igeneric_function<T>("VT|VTTT") 45277 | /* 45278 | Overloads: 45279 | 0. VT - vector, nth-element 45280 | 1. VTTT - vector, nth-element, r0, r1 45281 | */ 45282 | {} 45283 | 45284 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45285 | { 45286 | vector_t vec(parameters[0]); 45287 | 45288 | std::size_t n = 0; 45289 | std::size_t r0 = 0; 45290 | std::size_t r1 = vec.size() - 1; 45291 | 45292 | if (!scalar_t(parameters[1]).to_uint(n)) 45293 | return T(0); 45294 | 45295 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)) 45296 | { 45297 | return std::numeric_limits<T>::quiet_NaN(); 45298 | } 45299 | 45300 | std::nth_element( 45301 | vec.begin() + r0, 45302 | vec.begin() + r0 + n , 45303 | vec.begin() + r1 + 1); 45304 | 45305 | return T(1); 45306 | } 45307 | }; 45308 | 45309 | template <typename T> 45310 | class assign exprtk_final : public exprtk::igeneric_function<T> 45311 | { 45312 | public: 45313 | 45314 | typedef typename exprtk::igeneric_function<T> igfun_t; 45315 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45316 | typedef typename igfun_t::generic_type generic_type; 45317 | typedef typename generic_type::scalar_view scalar_t; 45318 | typedef typename generic_type::vector_view vector_t; 45319 | 45320 | using igfun_t::operator(); 45321 | 45322 | assign() 45323 | : exprtk::igeneric_function<T>("VT|VTTT|VTTTT") 45324 | /* 45325 | Overloads: 45326 | 0. VT - vector, V 45327 | 1. VTTT - vector, V, r0, r1 45328 | 2. VTTTT - vector, V, r0, r1, SS 45329 | */ 45330 | {} 45331 | 45332 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45333 | { 45334 | vector_t vec(parameters[0]); 45335 | 45336 | const T assign_value = scalar_t(parameters[1]); 45337 | 45338 | const std::size_t step_size = (2 != ps_index) ? 1 : 45339 | static_cast<std::size_t>(scalar_t(parameters.back())()); 45340 | 45341 | std::size_t r0 = 0; 45342 | std::size_t r1 = vec.size() - 1; 45343 | 45344 | if ( 45345 | ((ps_index == 1) || (ps_index == 2)) && 45346 | !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0) 45347 | ) 45348 | { 45349 | return T(0); 45350 | } 45351 | 45352 | for (std::size_t i = r0; i <= r1; i += step_size) 45353 | { 45354 | vec[i] = assign_value; 45355 | } 45356 | 45357 | return T(1); 45358 | } 45359 | }; 45360 | 45361 | template <typename T> 45362 | class iota exprtk_final : public exprtk::igeneric_function<T> 45363 | { 45364 | public: 45365 | 45366 | typedef typename exprtk::igeneric_function<T> igfun_t; 45367 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45368 | typedef typename igfun_t::generic_type generic_type; 45369 | typedef typename generic_type::scalar_view scalar_t; 45370 | typedef typename generic_type::vector_view vector_t; 45371 | 45372 | using igfun_t::operator(); 45373 | 45374 | iota() 45375 | : exprtk::igeneric_function<T>("VTT|VT|VTTTT|VTTT") 45376 | /* 45377 | Overloads: 45378 | 0. VTT - vector, SV, SS 45379 | 1. VT - vector, SV, SS (+1) 45380 | 2. VTTT - vector, r0, r1, SV, SS 45381 | 3. VTT - vector, r0, r1, SV, SS (+1) 45382 | 45383 | Where: 45384 | 1. SV - Start value 45385 | 2. SS - Step size 45386 | */ 45387 | {} 45388 | 45389 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45390 | { 45391 | vector_t vec(parameters[0]); 45392 | 45393 | const T start_value = (ps_index <= 1) ? 45394 | scalar_t(parameters[1]) : 45395 | scalar_t(parameters[3]) ; 45396 | 45397 | const T step_size = ((0 == ps_index) || (2 == ps_index)) ? 45398 | scalar_t(parameters.back())() : 45399 | T(1) ; 45400 | 45401 | std::size_t r0 = 0; 45402 | std::size_t r1 = vec.size() - 1; 45403 | 45404 | if ( 45405 | ((ps_index == 2) || (ps_index == 3)) && 45406 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 45407 | ) 45408 | { 45409 | return T(0); 45410 | } 45411 | 45412 | for (std::size_t i = r0; i <= r1; ++i) 45413 | { 45414 | vec[i] = start_value + ((i - r0) * step_size); 45415 | } 45416 | 45417 | return T(1); 45418 | } 45419 | }; 45420 | 45421 | template <typename T> 45422 | class sumk exprtk_final : public exprtk::igeneric_function<T> 45423 | { 45424 | public: 45425 | 45426 | typedef typename exprtk::igeneric_function<T> igfun_t; 45427 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45428 | typedef typename igfun_t::generic_type generic_type; 45429 | typedef typename generic_type::scalar_view scalar_t; 45430 | typedef typename generic_type::vector_view vector_t; 45431 | 45432 | using igfun_t::operator(); 45433 | 45434 | sumk() 45435 | : exprtk::igeneric_function<T>("V|VTT|VTTT") 45436 | /* 45437 | Overloads: 45438 | 0. V - vector 45439 | 1. VTT - vector, r0, r1 45440 | 2. VTTT - vector, r0, r1, stride 45441 | */ 45442 | {} 45443 | 45444 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45445 | { 45446 | const vector_t vec(parameters[0]); 45447 | 45448 | const std::size_t stride = (2 != ps_index) ? 1 : 45449 | static_cast<std::size_t>(scalar_t(parameters[3])()); 45450 | 45451 | std::size_t r0 = 0; 45452 | std::size_t r1 = vec.size() - 1; 45453 | 45454 | if ( 45455 | ((1 == ps_index) || (2 == ps_index)) && 45456 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 45457 | ) 45458 | { 45459 | return std::numeric_limits<T>::quiet_NaN(); 45460 | } 45461 | 45462 | T result = T(0); 45463 | T error = T(0); 45464 | 45465 | for (std::size_t i = r0; i <= r1; i += stride) 45466 | { 45467 | details::kahan_sum(result, error, vec[i]); 45468 | } 45469 | 45470 | return result; 45471 | } 45472 | }; 45473 | 45474 | template <typename T> 45475 | class axpy exprtk_final : public exprtk::igeneric_function<T> 45476 | { 45477 | public: 45478 | 45479 | typedef typename exprtk::igeneric_function<T> igfun_t; 45480 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45481 | typedef typename igfun_t::generic_type generic_type; 45482 | typedef typename generic_type::scalar_view scalar_t; 45483 | typedef typename generic_type::vector_view vector_t; 45484 | 45485 | using igfun_t::operator(); 45486 | 45487 | axpy() 45488 | : exprtk::igeneric_function<T>("TVV|TVVTT") 45489 | /* 45490 | y <- ax + y 45491 | Overloads: 45492 | 0. TVV - a, x(vector), y(vector) 45493 | 1. TVVTT - a, x(vector), y(vector), r0, r1 45494 | */ 45495 | {} 45496 | 45497 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45498 | { 45499 | const vector_t x(parameters[1]); 45500 | vector_t y(parameters[2]); 45501 | 45502 | std::size_t r0 = 0; 45503 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 45504 | 45505 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 3, 4, 1)) 45506 | return std::numeric_limits<T>::quiet_NaN(); 45507 | else if (helper::invalid_range(y, r0, r1)) 45508 | return std::numeric_limits<T>::quiet_NaN(); 45509 | 45510 | const T a = scalar_t(parameters[0])(); 45511 | 45512 | for (std::size_t i = r0; i <= r1; ++i) 45513 | { 45514 | y[i] = (a * x[i]) + y[i]; 45515 | } 45516 | 45517 | return T(1); 45518 | } 45519 | }; 45520 | 45521 | template <typename T> 45522 | class axpby exprtk_final : public exprtk::igeneric_function<T> 45523 | { 45524 | public: 45525 | 45526 | typedef typename exprtk::igeneric_function<T> igfun_t; 45527 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45528 | typedef typename igfun_t::generic_type generic_type; 45529 | typedef typename generic_type::scalar_view scalar_t; 45530 | typedef typename generic_type::vector_view vector_t; 45531 | 45532 | using igfun_t::operator(); 45533 | 45534 | axpby() 45535 | : exprtk::igeneric_function<T>("TVTV|TVTVTT") 45536 | /* 45537 | y <- ax + by 45538 | Overloads: 45539 | 0. TVTV - a, x(vector), b, y(vector) 45540 | 1. TVTVTT - a, x(vector), b, y(vector), r0, r1 45541 | */ 45542 | {} 45543 | 45544 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45545 | { 45546 | const vector_t x(parameters[1]); 45547 | vector_t y(parameters[3]); 45548 | 45549 | std::size_t r0 = 0; 45550 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 45551 | 45552 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1)) 45553 | return std::numeric_limits<T>::quiet_NaN(); 45554 | else if (helper::invalid_range(y, r0, r1)) 45555 | return std::numeric_limits<T>::quiet_NaN(); 45556 | 45557 | const T a = scalar_t(parameters[0])(); 45558 | const T b = scalar_t(parameters[2])(); 45559 | 45560 | for (std::size_t i = r0; i <= r1; ++i) 45561 | { 45562 | y[i] = (a * x[i]) + (b * y[i]); 45563 | } 45564 | 45565 | return T(1); 45566 | } 45567 | }; 45568 | 45569 | template <typename T> 45570 | class axpyz exprtk_final : public exprtk::igeneric_function<T> 45571 | { 45572 | public: 45573 | 45574 | typedef typename exprtk::igeneric_function<T> igfun_t; 45575 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45576 | typedef typename igfun_t::generic_type generic_type; 45577 | typedef typename generic_type::scalar_view scalar_t; 45578 | typedef typename generic_type::vector_view vector_t; 45579 | 45580 | using igfun_t::operator(); 45581 | 45582 | axpyz() 45583 | : exprtk::igeneric_function<T>("TVVV|TVVVTT") 45584 | /* 45585 | z <- ax + y 45586 | Overloads: 45587 | 0. TVVV - a, x(vector), y(vector), z(vector) 45588 | 1. TVVVTT - a, x(vector), y(vector), z(vector), r0, r1 45589 | */ 45590 | {} 45591 | 45592 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45593 | { 45594 | const vector_t x(parameters[1]); 45595 | const vector_t y(parameters[2]); 45596 | vector_t z(parameters[3]); 45597 | 45598 | std::size_t r0 = 0; 45599 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 45600 | 45601 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1)) 45602 | return std::numeric_limits<T>::quiet_NaN(); 45603 | else if (helper::invalid_range(y, r0, r1)) 45604 | return std::numeric_limits<T>::quiet_NaN(); 45605 | else if (helper::invalid_range(z, r0, r1)) 45606 | return std::numeric_limits<T>::quiet_NaN(); 45607 | 45608 | const T a = scalar_t(parameters[0])(); 45609 | 45610 | for (std::size_t i = r0; i <= r1; ++i) 45611 | { 45612 | z[i] = (a * x[i]) + y[i]; 45613 | } 45614 | 45615 | return T(1); 45616 | } 45617 | }; 45618 | 45619 | template <typename T> 45620 | class axpbyz exprtk_final : public exprtk::igeneric_function<T> 45621 | { 45622 | public: 45623 | 45624 | typedef typename exprtk::igeneric_function<T> igfun_t; 45625 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45626 | typedef typename igfun_t::generic_type generic_type; 45627 | typedef typename generic_type::scalar_view scalar_t; 45628 | typedef typename generic_type::vector_view vector_t; 45629 | 45630 | using igfun_t::operator(); 45631 | 45632 | axpbyz() 45633 | : exprtk::igeneric_function<T>("TVTVV|TVTVVTT") 45634 | /* 45635 | z <- ax + by 45636 | Overloads: 45637 | 0. TVTVV - a, x(vector), b, y(vector), z(vector) 45638 | 1. TVTVVTT - a, x(vector), b, y(vector), z(vector), r0, r1 45639 | */ 45640 | {} 45641 | 45642 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45643 | { 45644 | const vector_t x(parameters[1]); 45645 | const vector_t y(parameters[3]); 45646 | vector_t z(parameters[4]); 45647 | 45648 | std::size_t r0 = 0; 45649 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 45650 | 45651 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 5, 6, 1)) 45652 | return std::numeric_limits<T>::quiet_NaN(); 45653 | else if (helper::invalid_range(y, r0, r1)) 45654 | return std::numeric_limits<T>::quiet_NaN(); 45655 | else if (helper::invalid_range(z, r0, r1)) 45656 | return std::numeric_limits<T>::quiet_NaN(); 45657 | 45658 | const T a = scalar_t(parameters[0])(); 45659 | const T b = scalar_t(parameters[2])(); 45660 | 45661 | for (std::size_t i = r0; i <= r1; ++i) 45662 | { 45663 | z[i] = (a * x[i]) + (b * y[i]); 45664 | } 45665 | 45666 | return T(1); 45667 | } 45668 | }; 45669 | 45670 | template <typename T> 45671 | class axpbsy exprtk_final : public exprtk::igeneric_function<T> 45672 | { 45673 | public: 45674 | 45675 | typedef typename exprtk::igeneric_function<T> igfun_t; 45676 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45677 | typedef typename igfun_t::generic_type generic_type; 45678 | typedef typename generic_type::scalar_view scalar_t; 45679 | typedef typename generic_type::vector_view vector_t; 45680 | 45681 | using igfun_t::operator(); 45682 | 45683 | axpbsy() 45684 | : exprtk::igeneric_function<T>("TVTTV|TVTTVTT") 45685 | /* 45686 | y <- ax + by 45687 | Overloads: 45688 | 0. TVTVV - a, x(vector), b, shift, y(vector), z(vector) 45689 | 1. TVTVVTT - a, x(vector), b, shift, y(vector), z(vector), r0, r1 45690 | */ 45691 | {} 45692 | 45693 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45694 | { 45695 | const vector_t x(parameters[1]); 45696 | vector_t y(parameters[4]); 45697 | 45698 | std::size_t r0 = 0; 45699 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 45700 | 45701 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 5, 6, 1)) 45702 | return std::numeric_limits<T>::quiet_NaN(); 45703 | else if (helper::invalid_range(y, r0, r1)) 45704 | return std::numeric_limits<T>::quiet_NaN(); 45705 | 45706 | const T a = scalar_t(parameters[0])(); 45707 | const T b = scalar_t(parameters[2])(); 45708 | 45709 | const std::size_t s = static_cast<std::size_t>(scalar_t(parameters[3])()); 45710 | 45711 | for (std::size_t i = r0; i <= r1; ++i) 45712 | { 45713 | y[i] = (a * x[i]) + (b * y[i + s]); 45714 | } 45715 | 45716 | return T(1); 45717 | } 45718 | }; 45719 | 45720 | template <typename T> 45721 | class axpbsyz exprtk_final : public exprtk::igeneric_function<T> 45722 | { 45723 | public: 45724 | 45725 | typedef typename exprtk::igeneric_function<T> igfun_t; 45726 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45727 | typedef typename igfun_t::generic_type generic_type; 45728 | typedef typename generic_type::scalar_view scalar_t; 45729 | typedef typename generic_type::vector_view vector_t; 45730 | 45731 | using igfun_t::operator(); 45732 | 45733 | axpbsyz() 45734 | : exprtk::igeneric_function<T>("TVTTVV|TVTTVVTT") 45735 | /* 45736 | z <- ax + by 45737 | Overloads: 45738 | 0. TVTVV - a, x(vector), b, shift, y(vector), z(vector) 45739 | 1. TVTVVTT - a, x(vector), b, shift, y(vector), z(vector), r0, r1 45740 | */ 45741 | {} 45742 | 45743 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45744 | { 45745 | const vector_t x(parameters[1]); 45746 | const vector_t y(parameters[4]); 45747 | vector_t z(parameters[5]); 45748 | 45749 | std::size_t r0 = 0; 45750 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 45751 | 45752 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 6, 7, 1)) 45753 | return std::numeric_limits<T>::quiet_NaN(); 45754 | else if (helper::invalid_range(y, r0, r1)) 45755 | return std::numeric_limits<T>::quiet_NaN(); 45756 | else if (helper::invalid_range(z, r0, r1)) 45757 | return std::numeric_limits<T>::quiet_NaN(); 45758 | 45759 | const T a = scalar_t(parameters[0])(); 45760 | const T b = scalar_t(parameters[2])(); 45761 | 45762 | const std::size_t s = static_cast<std::size_t>(scalar_t(parameters[3])()); 45763 | 45764 | for (std::size_t i = r0; i <= r1; ++i) 45765 | { 45766 | z[i] = (a * x[i]) + (b * y[i + s]); 45767 | } 45768 | 45769 | return T(1); 45770 | } 45771 | }; 45772 | 45773 | template <typename T> 45774 | class axpbz exprtk_final : public exprtk::igeneric_function<T> 45775 | { 45776 | public: 45777 | 45778 | typedef typename exprtk::igeneric_function<T> igfun_t; 45779 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45780 | typedef typename igfun_t::generic_type generic_type; 45781 | typedef typename generic_type::scalar_view scalar_t; 45782 | typedef typename generic_type::vector_view vector_t; 45783 | 45784 | using igfun_t::operator(); 45785 | 45786 | axpbz() 45787 | : exprtk::igeneric_function<T>("TVTV|TVTVTT") 45788 | /* 45789 | z <- ax + b 45790 | Overloads: 45791 | 0. TVTV - a, x(vector), b, z(vector) 45792 | 1. TVTVTT - a, x(vector), b, z(vector), r0, r1 45793 | */ 45794 | {} 45795 | 45796 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45797 | { 45798 | const vector_t x(parameters[1]); 45799 | vector_t z(parameters[3]); 45800 | 45801 | std::size_t r0 = 0; 45802 | std::size_t r1 = x.size() - 1; 45803 | 45804 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1)) 45805 | return std::numeric_limits<T>::quiet_NaN(); 45806 | else if (helper::invalid_range(z, r0, r1)) 45807 | return std::numeric_limits<T>::quiet_NaN(); 45808 | 45809 | const T a = scalar_t(parameters[0])(); 45810 | const T b = scalar_t(parameters[2])(); 45811 | 45812 | for (std::size_t i = r0; i <= r1; ++i) 45813 | { 45814 | z[i] = (a * x[i]) + b; 45815 | } 45816 | 45817 | return T(1); 45818 | } 45819 | }; 45820 | 45821 | template <typename T> 45822 | class diff exprtk_final : public exprtk::igeneric_function<T> 45823 | { 45824 | public: 45825 | 45826 | typedef typename exprtk::igeneric_function<T> igfun_t; 45827 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45828 | typedef typename igfun_t::generic_type generic_type; 45829 | typedef typename generic_type::scalar_view scalar_t; 45830 | typedef typename generic_type::vector_view vector_t; 45831 | 45832 | using igfun_t::operator(); 45833 | 45834 | diff() 45835 | : exprtk::igeneric_function<T>("VV|VVT") 45836 | /* 45837 | x_(i - stride) - x_i 45838 | Overloads: 45839 | 0. VV - x(vector), y(vector) 45840 | 1. VVT - x(vector), y(vector), stride 45841 | */ 45842 | {} 45843 | 45844 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45845 | { 45846 | const vector_t x(parameters[0]); 45847 | vector_t y(parameters[1]); 45848 | 45849 | const std::size_t r0 = 0; 45850 | const std::size_t r1 = std::min(x.size(),y.size()) - 1; 45851 | 45852 | const std::size_t stride = (1 != ps_index) ? 1 : 45853 | std::min(r1,static_cast<std::size_t>(scalar_t(parameters[2])())); 45854 | 45855 | for (std::size_t i = 0; i < stride; ++i) 45856 | { 45857 | y[i] = std::numeric_limits<T>::quiet_NaN(); 45858 | } 45859 | 45860 | for (std::size_t i = (r0 + stride); i <= r1; ++i) 45861 | { 45862 | y[i] = x[i] - x[i - stride]; 45863 | } 45864 | 45865 | return T(1); 45866 | } 45867 | }; 45868 | 45869 | template <typename T> 45870 | class dot exprtk_final : public exprtk::igeneric_function<T> 45871 | { 45872 | public: 45873 | 45874 | typedef typename exprtk::igeneric_function<T> igfun_t; 45875 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45876 | typedef typename igfun_t::generic_type generic_type; 45877 | typedef typename generic_type::scalar_view scalar_t; 45878 | typedef typename generic_type::vector_view vector_t; 45879 | 45880 | using igfun_t::operator(); 45881 | 45882 | dot() 45883 | : exprtk::igeneric_function<T>("VV|VVTT") 45884 | /* 45885 | Overloads: 45886 | 0. VV - x(vector), y(vector) 45887 | 1. VVTT - x(vector), y(vector), r0, r1 45888 | */ 45889 | {} 45890 | 45891 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45892 | { 45893 | const vector_t x(parameters[0]); 45894 | const vector_t y(parameters[1]); 45895 | 45896 | std::size_t r0 = 0; 45897 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 45898 | 45899 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)) 45900 | return std::numeric_limits<T>::quiet_NaN(); 45901 | else if (helper::invalid_range(y, r0, r1)) 45902 | return std::numeric_limits<T>::quiet_NaN(); 45903 | 45904 | T result = T(0); 45905 | 45906 | for (std::size_t i = r0; i <= r1; ++i) 45907 | { 45908 | result += (x[i] * y[i]); 45909 | } 45910 | 45911 | return result; 45912 | } 45913 | }; 45914 | 45915 | template <typename T> 45916 | class dotk exprtk_final : public exprtk::igeneric_function<T> 45917 | { 45918 | public: 45919 | 45920 | typedef typename exprtk::igeneric_function<T> igfun_t; 45921 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45922 | typedef typename igfun_t::generic_type generic_type; 45923 | typedef typename generic_type::scalar_view scalar_t; 45924 | typedef typename generic_type::vector_view vector_t; 45925 | 45926 | using igfun_t::operator(); 45927 | 45928 | dotk() 45929 | : exprtk::igeneric_function<T>("VV|VVTT") 45930 | /* 45931 | Overloads: 45932 | 0. VV - x(vector), y(vector) 45933 | 1. VVTT - x(vector), y(vector), r0, r1 45934 | */ 45935 | {} 45936 | 45937 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45938 | { 45939 | const vector_t x(parameters[0]); 45940 | const vector_t y(parameters[1]); 45941 | 45942 | std::size_t r0 = 0; 45943 | std::size_t r1 = std::min(x.size(),y.size()) - 1; 45944 | 45945 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)) 45946 | return std::numeric_limits<T>::quiet_NaN(); 45947 | else if (helper::invalid_range(y, r0, r1)) 45948 | return std::numeric_limits<T>::quiet_NaN(); 45949 | 45950 | T result = T(0); 45951 | T error = T(0); 45952 | 45953 | for (std::size_t i = r0; i <= r1; ++i) 45954 | { 45955 | details::kahan_sum(result, error, (x[i] * y[i])); 45956 | } 45957 | 45958 | return result; 45959 | } 45960 | }; 45961 | 45962 | template <typename T> 45963 | class threshold_below exprtk_final : public exprtk::igeneric_function<T> 45964 | { 45965 | public: 45966 | 45967 | typedef typename exprtk::igeneric_function<T> igfun_t; 45968 | typedef typename igfun_t::parameter_list_t parameter_list_t; 45969 | typedef typename igfun_t::generic_type generic_type; 45970 | typedef typename generic_type::scalar_view scalar_t; 45971 | typedef typename generic_type::vector_view vector_t; 45972 | 45973 | using igfun_t::operator(); 45974 | 45975 | threshold_below() 45976 | : exprtk::igeneric_function<T>("VTT|VTTTT") 45977 | /* 45978 | Overloads: 45979 | 0. VTT - vector, TV, SV 45980 | 1. VTTTT - vector, r0, r1, TV, SV 45981 | 45982 | Where: 45983 | TV - Threshold value 45984 | SV - Snap-to value 45985 | */ 45986 | {} 45987 | 45988 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 45989 | { 45990 | vector_t vec(parameters[0]); 45991 | 45992 | const T threshold_value = (0 == ps_index) ? 45993 | scalar_t(parameters[1]) : 45994 | scalar_t(parameters[3]) ; 45995 | 45996 | const T snap_value = scalar_t(parameters.back()); 45997 | 45998 | std::size_t r0 = 0; 45999 | std::size_t r1 = vec.size() - 1; 46000 | 46001 | if ( 46002 | (1 == ps_index) && 46003 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 46004 | ) 46005 | { 46006 | return T(0); 46007 | } 46008 | 46009 | for (std::size_t i = r0; i <= r1; ++i) 46010 | { 46011 | if (vec[i] < threshold_value) 46012 | { 46013 | vec[i] = snap_value; 46014 | } 46015 | } 46016 | 46017 | return T(1); 46018 | } 46019 | }; 46020 | 46021 | template <typename T> 46022 | class threshold_above exprtk_final : public exprtk::igeneric_function<T> 46023 | { 46024 | public: 46025 | 46026 | typedef typename exprtk::igeneric_function<T> igfun_t; 46027 | typedef typename igfun_t::parameter_list_t parameter_list_t; 46028 | typedef typename igfun_t::generic_type generic_type; 46029 | typedef typename generic_type::scalar_view scalar_t; 46030 | typedef typename generic_type::vector_view vector_t; 46031 | 46032 | using igfun_t::operator(); 46033 | 46034 | threshold_above() 46035 | : exprtk::igeneric_function<T>("VTT|VTTTT") 46036 | /* 46037 | Overloads: 46038 | 0. VTT - vector, TV, SV 46039 | 1. VTTTT - vector, r0, r1, TV, SV 46040 | 46041 | Where: 46042 | TV - Threshold value 46043 | SV - Snap-to value 46044 | */ 46045 | {} 46046 | 46047 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) exprtk_override 46048 | { 46049 | vector_t vec(parameters[0]); 46050 | 46051 | const T threshold_value = (0 == ps_index) ? 46052 | scalar_t(parameters[1]) : 46053 | scalar_t(parameters[3]) ; 46054 | 46055 | const T snap_value = scalar_t(parameters.back()); 46056 | 46057 | std::size_t r0 = 0; 46058 | std::size_t r1 = vec.size() - 1; 46059 | 46060 | if ( 46061 | (1 == ps_index) && 46062 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) 46063 | ) 46064 | { 46065 | return T(0); 46066 | } 46067 | 46068 | for (std::size_t i = r0; i <= r1; ++i) 46069 | { 46070 | if (vec[i] > threshold_value) 46071 | { 46072 | vec[i] = snap_value; 46073 | } 46074 | } 46075 | 46076 | return T(1); 46077 | } 46078 | }; 46079 | 46080 | template <typename T> 46081 | struct package 46082 | { 46083 | all_true <T> at; 46084 | all_false <T> af; 46085 | any_true <T> nt; 46086 | any_false <T> nf; 46087 | count <T> c; 46088 | copy <T> cp; 46089 | rol <T> rl; 46090 | ror <T> rr; 46091 | reverse <T> rev; 46092 | shift_left <T> sl; 46093 | shift_right <T> sr; 46094 | sort <T> st; 46095 | nthelement <T> ne; 46096 | assign <T> an; 46097 | iota <T> ia; 46098 | sumk <T> sk; 46099 | axpy <T> b1_axpy; 46100 | axpby <T> b1_axpby; 46101 | axpyz <T> b1_axpyz; 46102 | axpbyz <T> b1_axpbyz; 46103 | axpbsy <T> b1_axpbsy; 46104 | axpbsyz <T> b1_axpbsyz; 46105 | axpbz <T> b1_axpbz; 46106 | diff <T> df; 46107 | dot <T> dt; 46108 | dotk <T> dtk; 46109 | threshold_above<T> ta; 46110 | threshold_below<T> tb; 46111 | 46112 | bool register_package(exprtk::symbol_table<T>& symtab) 46113 | { 46114 | #define exprtk_register_function(FunctionName, FunctionType) \ 46115 | if (!symtab.add_function(FunctionName,FunctionType)) \ 46116 | { \ 46117 | exprtk_debug(( \ 46118 | "exprtk::rtl::vecops::register_package - Failed to add function: %s\n", \ 46119 | FunctionName)); \ 46120 | return false; \ 46121 | } \ 46122 | 46123 | exprtk_register_function("all_true" , at ) 46124 | exprtk_register_function("all_false" , af ) 46125 | exprtk_register_function("any_true" , nt ) 46126 | exprtk_register_function("any_false" , nf ) 46127 | exprtk_register_function("count" , c ) 46128 | exprtk_register_function("copy" , cp ) 46129 | exprtk_register_function("rotate_left" , rl ) 46130 | exprtk_register_function("rol" , rl ) 46131 | exprtk_register_function("rotate_right" , rr ) 46132 | exprtk_register_function("ror" , rr ) 46133 | exprtk_register_function("reverse" , rev ) 46134 | exprtk_register_function("shftl" , sl ) 46135 | exprtk_register_function("shftr" , sr ) 46136 | exprtk_register_function("sort" , st ) 46137 | exprtk_register_function("nth_element" , ne ) 46138 | exprtk_register_function("assign" , an ) 46139 | exprtk_register_function("iota" , ia ) 46140 | exprtk_register_function("sumk" , sk ) 46141 | exprtk_register_function("axpy" , b1_axpy ) 46142 | exprtk_register_function("axpby" , b1_axpby ) 46143 | exprtk_register_function("axpyz" , b1_axpyz ) 46144 | exprtk_register_function("axpbyz" , b1_axpbyz ) 46145 | exprtk_register_function("axpbsy" , b1_axpbsy ) 46146 | exprtk_register_function("axpbsyz" , b1_axpbsyz) 46147 | exprtk_register_function("axpbz" , b1_axpbz ) 46148 | exprtk_register_function("diff" , df ) 46149 | exprtk_register_function("dot" , dt ) 46150 | exprtk_register_function("dotk" , dtk ) 46151 | exprtk_register_function("threshold_above" , ta ) 46152 | exprtk_register_function("threshold_below" , tb ) 46153 | #undef exprtk_register_function 46154 | 46155 | return true; 46156 | } 46157 | }; 46158 | 46159 | } // namespace exprtk::rtl::vecops 46160 | } // namespace exprtk::rtl 46161 | } // namespace exprtk 46162 | #endif 46163 | 46164 | namespace exprtk 46165 | { 46166 | namespace information 46167 | { 46168 | using ::exprtk::details::char_cptr; 46169 | 46170 | static char_cptr library = "Mathematical Expression Toolkit" 46171 | static char_cptr version = "2.718281828459045235360287471352662497757" 46172 | "24709369995957496696762772407663035354759" 46173 | "45713821785251664274274663919320030599218" 46174 | "17413596629043572900334295260595630738132" 46175 | static char_cptr date = "20240101" 46176 | static char_cptr min_cpp = "199711L" 46177 | 46178 | static inline std::string data() 46179 | { 46180 | static const std::string info_str = std::string(library) + 46181 | std::string(" v") + std::string(version) + 46182 | std::string(" (") + date + std::string(")") + 46183 | std::string(" (") + min_cpp + std::string(")"); 46184 | return info_str; 46185 | } 46186 | 46187 | } // namespace information 46188 | 46189 | #ifdef exprtk_debug 46190 | #undef exprtk_debug 46191 | #endif 46192 | 46193 | #ifdef exprtk_error_location 46194 | #undef exprtk_error_location 46195 | #endif 46196 | 46197 | #ifdef exprtk_fallthrough 46198 | #undef exprtk_fallthrough 46199 | #endif 46200 | 46201 | #ifdef exprtk_override 46202 | #undef exprtk_override 46203 | #endif 46204 | 46205 | #ifdef exprtk_final 46206 | #undef exprtk_final 46207 | #endif 46208 | 46209 | #ifdef exprtk_delete 46210 | #undef exprtk_delete 46211 | #endif 46212 | 46213 | } // namespace exprtk 46214 | 46215 | #endif